Недискретные назначения целых переменных
Является ли недискретное присваивание выражений целым числам только в пределах algorithm
a function
?
Если в алгоритме требуется много параметров модели, было бы намного проще вычислить выходное значение непосредственно в разделе алгоритма модели.
Если вы используете функцию, вам необходимо передать все необходимые значения параметров из среды в качестве входных данных для функции.
Мне кажется, что спецификация Modelica заставляет инкапсулировать целые числа с недискретными назначениями локально внутри функций.
Возможным прецедентом для таких целых присвоений является то, что нужно представить характеристики переноса как сумму гладких базовых функций с компактным носителем.
Для вычисления выходного значения для определенного входного значения x необходимо определить индексы базовых функций, носители которых содержат x.
Я включаю более простой случай линейной интерполяции табличных данных в качестве рабочего примера, где интервал интерполяции должен быть найден (даже если такая интерполяция не дифференцируема).
noEvent(...)
в коде не требуется, так как отношения внутри секции алгоритма функции не генерируют события, если аннотация GenerateEvents=true
не задана.
Тем не менее, я включил его, чтобы показать, откуда происходит недискретное присвоение целому числу i
.
model testInterpol
function interpol
input Real x;
input Real tab[:,2];
output Real y;
protected
Integer i;
algorithm
i:=size(tab,1);
for ii in 2:size(tab,1) loop
if noEvent(x < tab[ii,1]) then
i := ii;
break;
end if;
end for;
y := tab[i-1,2] + (tab[i,2]-tab[i-1,2])/(tab[i,1]-tab[i-1,1])*(x-tab[i-1,1]);
end interpol;
Real x = 10*sin(8*atan(1.0)*time);
parameter Real tab[:,2]={{1,1},{2,4},{3,9},{5,25},{6,36}};
Real y;
equation
y = interpol(x,tab);
end testInterpol;
В следующей модели тип Interpol
изменяется от function
до model
.
Обратите внимание, что это подразумевает некоторые изменения для использования Interpol
.
model testInterpolModel
model Interpol
input Real x;
input Real tab[:,2];
output Real y;
protected
Integer i;
algorithm
i:=size(tab,1);
for ii in 2:size(tab,1) loop
if noEvent(x < tab[ii,1]) then
i := ii;
break;
end if;
end for;
y := tab[i-1,2] + (tab[i,2]-tab[i-1,2])/(tab[i,1]-tab[i-1,1])*(x-tab[i-1,1]);
end Interpol;
Real x = 10*sin(8*atan(1.0)*time);
parameter Real tab[:,2]={{1,1},{2,4},{3,9},{5,25},{6,36}};
Real y;
Interpol interpol(x=x,tab=tab,y=y);
end testInterpolModel;
-
OpenModelica 1.9.3 + dev (r25613) принимает
testInterpolModel
-
Dymola отклоняет модель со следующим сообщением об ошибке:
Trying to assign a discrete variable inside a loop controlled by higher variability: interpol.i = ii;
В разделе 12.2 "Функция как специализированный класс" спецификации Modelica 3.3 rev. 1 можно найти следующее утверждение:
Компоненты функции будут внутри функции вести себя так, как если бы они имели вариабельность по времени.
Я не совсем уверен, что это значит. Если бы у этого предложения было только предложение и не было опыта с инструментами Modelica, можно было бы подумать, что утверждения из секции алгоритма функции оцениваются только в экземплярах событий, потому что они ведут себя так, как если бы они имели вариабельность в дискретном времени.
Но это впечатление неверно. Операторы функции всегда выполняются, а отношения внутри функций не генерируют события, если аннотация GenerateEvents
явно не установлена на true
.
Это указано в разделе 8.5 "События и синхронизация" спецификации:
Все уравнения и операторы присваивания в тех случаях, когда предложения и все операторы присваивания в классах функций неявно рассматриваются как функция
noEvent
, т.е. отношения в рамках этих операторов никогда не вызывают состояния или события времени.
Существует уже связанный билет в Track-Tracker Modelica: Ticket-Comment-Link
У меня есть неопределенное представление о том, какова фактическая причина различий в обработке целочисленных переменных в функциях и моделях.
Алгоритмы в моделях можно концептуально интерпретировать как анонимные функции в отношении входов и выходов (см. раздел 11.1.2 "Выполнение алгоритма в модели" Спецификации). Все переменные, которые назначены в алгоритме, становятся выходами анонимной функции и могут использоваться в уравнениях вне алгоритма.
Но тогда эти переменные могут вводить разрывы в других частях модели.
В именованных функциях ситуация различна. Переменные, которые не объявлены как входные или выходные данные, не могут быть доступны извне. Поэтому функцию можно безопасно сконструировать так, чтобы целочисленные переменные не вносили разрывов в общую модель.
У меня сложилось впечатление, что проблема будет решена, если бы было возможно объявить локальные переменные алгоритма. Для экземпляра можно разрешить объявление algorithm
-local переменных, таких как i
после algorithm
-keyword.
Альтернативным решением могло бы стать повторное введение ключевого слова nondiscrete
Modelica-Specification 1. Уже существует старый билет Modelica где такое повторное введение было предложено в комментарии. Предложение получило только одобрение, но ничего не произошло.
Ключевое слово nondiscrete
можно использовать перед Integer i;
во втором примере кода выше. Поскольку переменная i
и присваивание i:=ii;
будут nodiscrete
, в этом случае noEvent
также будет легальным в рамках алгоритма.