Using Variant Source and Variant Sink blocks¶
In this example we will show the work of blocks Variant Source
and Variant Sink
. These blocks allow you to switch between different realisations of models that are generators of input data or consumers of output data of some subsystem.
Introduction¶
Suppose you need to calculate the performance of a model with different input sensors, different cyclograms, or different output data filtering algorithms. For such testing, you could build several separate models, the number of which would quickly become impractically large. Or you can collect all the models into one and switch conditions using variables.
In this simplified example, the model configuration will be specified by two scalar variables:
Pkg.add(["Combinatorics"])
V = 1;
W = 1;
The model has several signal line switches controlled by external variables.
The signal selection conditions in each block Variant Source
or Variant Sink
are specified using expressions.
The expression that first takes the true value determines the port number through which the data will go from or to some subsystem. Let us interpret the different variants of the systems that are realised in this diagram:
- If
W==1
is a true expression thenVariant Source1
activates inputSine3
, and atV==4
activates inputSine4
. - If
V==1
blockVariant Source 2
skips the signal from blockSine1
, and ifV==2
skips the signal from blockAdd1
. - If
Add1
block is inactive,Variant Source 1
will also be inactive, and thenSine3
andSine4
blocks will be disabled (Sine3
block is active atV==2 && W==1
, andSine4
block is active atV==2 && W==2
). - The
Gain3
block is active either atV==1
or atV==2
; under other conditions (for example atV=4
) we will get an error because no output signal will be supplied to the output portOut1
. - The blocks at the output
Variant Sink1
become active atW==1 (Gain5)
or atW==2 (Gain2, Substract, Terminator)
. - Finally, the blocks
Sine6
,Sum
andOut2
are always active and are not subject to the system option conditions. To ensure that these blocks are only executed under certain conditions, you can precede and follow them with the blocksVariant Source/Sink
both with a single input and output.
Under some combinations of conditions, this model returns an error because the output ports of a subsystem must receive an active signal regardless of the subsystem option. It is not possible to supply any block with both active and inactive signals at the same time, you must explicitly design the output ports of such a system using Variant Source/Sink
blocks to set default values.
Running the scenario¶
mName = "variant_source_sink"
model = mName in [m.name for m in engee.get_all_models()] ? engee.open( mName ) : engee.load( "$(@__DIR__)/$(mName).engee" );
data = engee.run( mName )
plot( data["Gain3.1"].time, data["Gain3.1"].value )
Running multiple scenarios¶
We will now run several variations of the model in a loop, switching state variables to show how the system performs in different scenarios using a combination of input conditions.
using Combinatorics
# Зададим все интересующие нас входные условия
vV = [1,2,4];
vW = [1,2,4];
# Загрузим модель
mName = "variant_source_sink"
model = mName in [m.name for m in engee.get_all_models()] ? engee.open( mName ) : engee.load( "$(@__DIR__)/$(mName).engee" );
# Успех выполнения мы будем хранить в матрице, которую инициализируем пропущенными значениями
run_success = NaN .* zeros(length(vV), length(vW))
# Пройдемся по всем комбинациям входных условий и проверим, выполнится ли модель
for c in combinations( vcat( vV,vW ), 2 )
V,W = c[1],c[2]
i = findfirst( vV.==c[1] )
j = findfirst( vW.==c[2] )
try
# Запустим модель на выполнение
data = engee.run( mName )
catch e
# Если модель выполнилась с ошибкой, запишем 0 в выходную матрицу
run_success[i,j] = 0
else
# Запишем единицу только если условие catch не сработало
run_success[i,j] = 1
end
end
We will display a graph that will show the statistics on the runs of different variants of our model.
gr()
# Вывод не интерактивной карты, отражающей успех выполнения модели
heatmap( run_success, xticks=(range(1,length(vV)), vV), yticks=(range(1,length(vW)), vW),
xlabel = 'V', ylabel='W', title="Успех выполнения модели", yflip = true, cbar=false, c=:Blues )
# Аннотация поверх каждой ячейки
annotate!( vec(tuple.((1:length(vV))', (1:length(vW)), string.(Int32.(run_success)))) )
Conclusion¶
We have seen that it is possible to build multiple variants of a system on a single canvas. This method simplifies testing and allows generating many code variants at once to further automate semi-natural modelling.