function - 函数的Modelica和事件生成
问题描述
我试图了解何时在 Modelica 中生成事件。在函数的上下文中,我注意到了我没想到的行为:函数似乎抑制了事件的生成。
我很惊讶,因为据我所知,Modelica 参考文献中没有明确说明这一点。例如,如果我在 OpenModelica 1.17.0 的 OMEdit 中运行此模型
model timeEventTest
Real z(start=0);
Real dummy(start=0);
equation
der(z) = dummy;
algorithm
if time > 10 then
dummy := 1;
else
dummy := -1.;
end if;
end timeEventTest;
我在 OMEdit 的求解器窗口中得到以下输出
### STATISTICS ###
timer
events
1 state events
0 time events
solver: dassl
46 steps taken
46 calls of functionODE
44 evaluations of jacobian
0 error test failures
0 convergence test failures
0.000122251s time of jacobian evaluation
The simulation finished successfully.
除了求解器(我使用 dassl)将 time=10 处的事件解释为状态事件而不是时间事件这一事实之外,行为与预期一致。但是,如果我改为运行(数学上相同的)模型
model timeEventTest2
Real z(start=0);
equation
der(z) = myfunc(time-10);
end timeEventTest2;
myfunc 定义为
function myfunc
input Real x;
output Real y;
algorithm
if x > 0 then
y := 1;
else
y:= -1;
end if;
end myfunc;
我在 OMEdit 中获得以下输出
### STATISTICS ###
timer
events
0 state events
0 time events
solver: dassl
52 steps taken
79 calls of functionODE
63 evaluations of jacobian
13 error test failures
0 convergence test failures
0.000185296s time of jacobian evaluation
The simulation finished successfully.
不仅没有检测到 time = 10 的事件,求解器甚至遇到了一些问题,如错误测试失败所示。这是一个微不足道的例子,但是,我可以想象,按功能对事件的明显抑制可能会导致较大模型中的主要问题。我在这里错过了什么?我可以强制在函数内严格触发事件吗?一些内置函数也会触发事件,例如 div 和 mod(奇怪的是,sign 和 abs 不会)。
编辑:显然,您需要至少运行示例 > 10 秒。我将模拟运行到 20 秒。
解决方案
Modelica 中的函数通常不会生成事件。
请参阅Modelica 规范中的8.5 事件和同步。
when 子句中的所有方程和赋值语句以及函数类中的所有赋值语句都被隐式处理为 noEvent,即这些运算符范围内的关系从不引发状态或时间事件。
但它可以改变这种行为:将注释添加GenerateEvents=true
到函数中。
但是,对于某些 Modelica 模拟器来说,这似乎还不够(使用 OpenModelica v1.16.5 和 Dymola 2021x 进行了测试)。
要使其在 OpenModelica 和 Dymola 中工作,您必须添加Inline
注释,或者您必须在一行中分配函数输出。
因此,如果您按如下方式重新编写函数,您将获得一个状态事件:
function myfunc
input Real x;
output Real y;
algorithm
y := if x > 0 then 1 else -1;
annotation (GenerateEvents=true);
end myfunc;
或者通过另外添加Inline
注释:
function myfunc
input Real x;
output Real y;
algorithm
if x > 0 then
y := 1;
else
y := -1;
end if;
annotation (GenerateEvents=true, Inline=true);
end myfunc;
状态事件与时间事件
要将状态事件timeEventTest
转换为时间事件,请将 if-condition 更改为
if time > 10 then
这在 Modelica Spec 的第8.5 章事件和同步中也有介绍。只有以下两种情况会触发时间事件:
- 时间 >= 离散表达式
- 时间 < 离散表达式
推荐阅读
- kotlin - 如何正确地在 Kotlin 中快速失败?
- python - render_template() 在蓝图文件夹中找不到模板
- javascript - 如何使用应用程序脚本将值复制到 Gsheets 中?
- ios - 滚动到 tableview 顶部并显示大标题 iOS
- angular - 如何通过电子邮件从特定区域发送屏幕?
- spacy - SpaCy 使用 Lemmatizer 作为独立组件
- css - 下拉菜单不超过 div
- mysql - SQL get perticuler name 排列在查询中间
- python - 通过遍历数据来连接元素
- java - 如何使用 JDK8 和 JDK11(内部带有 String.format)拥有相同的 slf4j 日志?