Using the Variant Source and Variant Sink blocks
In this example, we will show how the blocks work. Variant Source and Variant Sink. These blocks allow you to switch between different model implementations, which are generators of input data or consumers of output data of some subsystem.
Introduction
Suppose you need to calculate the operation of a model with different input sensors, different cyclograms, or different algorithms for filtering data at the output. For such testing, you can assemble several separate models, the number of which will quickly become impractically large. Or you can assemble all the models into one and switch the conditions using variables.
In this simplified example, the model configuration will be set by two scalar variables.:
Pkg.add(["Combinatorics"])
V = 1;
W = 1;
The model has several signal line switches controlled by external variables.
Signal selection conditions in each block Variant Source or Variant Sink they are set using expressions.
The expression that first takes the true value defines the port number through which the data will go from or to some subsystem. Let's interpret the different variants of the systems that are implemented in this scheme.:
- If
W==1is the true expression of theVariant Source1activates the inputSine3, and whenV==4the entrance is activatedSine4. - When
V==1blockVariant Source 2skips the signal from the blockSine1, and whenV==2– signal from the unitAdd1. - If the block
Add1inactive, thenVariant Source 1It will also be inactive, and then the blocks will be disabled.Sine3andSine4(blockSine3active whenV==2 && W==1, and the blockSine4active whenV==2 && W==2). - Yulok
Gain3active either whenV==1, or whenV==2; under other conditions (for example , whenV=4) we will get an error because on the output portOut1no output signal will be given. - Blocks at the exit
Variant Sink1they become active whenW==1 (Gain5)or whenW==2 (Gain2, Substract, Terminator). - Finally, the blocks
Sine6,SumandOut2they are always active, they are not subject to the conditions for choosing system options. To ensure that these blocks are executed only under certain conditions, you can put blocks before and after them.Variant Source/Sinkboth with a single entrance and exit.
Under some combinations of conditions, this model returns an error because the subsystem's output ports must receive an active signal regardless of the subsystem's variant. It is not possible to send an active and inactive signal to any block at the same time, it is necessary to explicitly design the output ports of such a system using blocks Variant Source/Sink to set default values.
Running the script
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 scripts
Now we will run several variants of the model in a loop, switching state variables in order to use a combination of input conditions to show how the system works in different scenarios.
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
Let's display a graph on which statistics on launches of different variants of our model will be collected.
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 several system variants can be assembled on one canvas. This method simplifies testing and allows you to generate many code variants at once to further automate semi-natural modeling.