Использование блоков Variant Source и Variant Sink
В этом примере мы покажем работу блоков Variant Source и Variant Sink. Эти блоки позволяют переключаться между разными реализациями моделей, являющимися генераторами входных данных или потребителями выходных данных некоторой подсистемы.
Введение
Предположим, вам нужно просчитать работу модели с разными входными датчиками, разными циклограммами или различными алгоритмами фильтрации данных на выходе. Для такого тестирования можно собрать несколько отдельных моделей, число которых быстро станет непрактично большим. Или можно собрать все модели в одну и переключать условия при помощи переменных.
В этом упрощенном примере конфигурация модели будет задана двумя скалярными переменными:
Pkg.add(["Combinatorics"])
V = 1;
W = 1;
В модели есть несколько переключателей сигнальных линий, управляемых внешними переменными.

Условия выбора сигнала в каждом блоке Variant Source или Variant Sink заданы при помощи выражений.
Выражение, которое первым принимает истинное значение, определяет номер порта, по которому пойдут данные от или к некоторой подсистеме. Проинтерпретируем разные варианты систем, которые реализованы на этой схеме:
- Если
W==1является истинным выражением тоVariant Source1активирует входSine3, а приV==4активируется входSine4. - При
V==1блокVariant Source 2пропускает сигнал от блокаSine1, а приV==2– сигнал от блокаAdd1. - Если блок
Add1неактивен, тоVariant Source 1тоже будет неактивным, и тогда будут отключены блокиSine3иSine4(блокSine3активен приV==2 && W==1, а блокSine4активен приV==2 && W==2). - Юлок
Gain3активен либо приV==1, либо приV==2; при других условиях (например приV=4) мы получим ошибку, потому что на выходной портOut1не будет подано никакого выходного сигнала. - Блоки на выходе
Variant Sink1становятся активными приW==1 (Gain5)либо приW==2 (Gain2, Substract, Terminator). - Наконец, блоки
Sine6,SumиOut2всегда активны, на них не распространяются условия по выбору вариантов системы. Чтобы эти блоки выполнялись только при некоторых условиях, можно поставить перед и после них блокиVariant Source/Sinkоба с единственным входом и выходом.
При некоторых комбинациях условий данная модель возвращает ошибку, потому что выходные порты подсистемы должны получать активный сигнал вне зависимости от варианта подсистемы. Подача на любой блок одновременно активного и неактивного сигнала невозможна, нужно явно оформлять выходные порты такой системы при помощи блоков Variant Source/Sink чтобы задавать значения по умолчанию.
Запуск сценария
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 )
Запуск нескольких сценариев
Теперь мы запустим несколько вариантов модели в цикле, переключая переменные состояния, чтобы при помощи комбинации входных условий показать, как система работает в разных сценариях.
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
Выведем график, на котором будет собрана статистика по запускам разных вариантов нашей модели.
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)))) )
Заключение
Мы убедились в том, что на одном холсте можно собрать несколько вариантов системы. Этот метод упрощает тестирование и позволяет генерировать сразу много вариантов кода для еще большей автоматизации полунатурного моделирования.