函数的 Modelica 和事件生成
Modelica and Event generation of Functions
我试图了解在 Modelica 中何时生成事件。在函数上下文中,我注意到了我没有预料到的行为:函数似乎会抑制事件生成。
令我惊讶的是,据我所知,Modelica 参考文献中并未明确说明这一点。
例如,如果我在 OpenModelica 1.17.0 的 OMEdit 中 运行 这个 model
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
的求解器 window 中得到以下输出
### 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 的事件解释为 state 事件 而不是 time 事件,行为符合预期。
但是,如果我改为 运行 (数学上相同) model
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.
不仅时间 = 10 的事件未被检测到,求解器甚至遇到了一些麻烦,如错误测试失败所示。
这是一个微不足道的例子,但是,我可以想象,按功能明显抑制事件可能会导致更大的 models 出现市长问题。
我在这里错过了什么?我可以强制严格触发函数内的事件吗?
一些内置函数也会触发事件,例如div 和 mod(奇怪的是,sign 和 abs 没有)。
编辑:显然,您需要 运行 示例的时间至少 > 10 秒。我运行模拟到20s.
Modelica 中的函数通常不会生成事件。
请参阅 Modelica 规范中的 8.5 Events and Synchronization。
All equations and assignment statements within when-clauses and all assignment statements within function classes are implicitly treated with noEvent, i.e., relations within the scope of these operators never induce state or time events.
但可以更改此行为:
在函数中添加注解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;
状态事件 vs 时间事件
要将 timeEventTest
中的状态事件变为时间事件,请将 if 条件更改为
if time > 10 then
Modelica 规范的第 8.5 Events and Synchronization 章也介绍了这一点。只有以下两种情况触发时间事件:
- 时间 >= 离散表达式
- 时间 < 离散表达式
我试图了解在 Modelica 中何时生成事件。在函数上下文中,我注意到了我没有预料到的行为:函数似乎会抑制事件生成。
令我惊讶的是,据我所知,Modelica 参考文献中并未明确说明这一点。 例如,如果我在 OpenModelica 1.17.0 的 OMEdit 中 运行 这个 model
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
的求解器 window 中得到以下输出 ### 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 的事件解释为 state 事件 而不是 time 事件,行为符合预期。 但是,如果我改为 运行 (数学上相同) model
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.
不仅时间 = 10 的事件未被检测到,求解器甚至遇到了一些麻烦,如错误测试失败所示。 这是一个微不足道的例子,但是,我可以想象,按功能明显抑制事件可能会导致更大的 models 出现市长问题。 我在这里错过了什么?我可以强制严格触发函数内的事件吗? 一些内置函数也会触发事件,例如div 和 mod(奇怪的是,sign 和 abs 没有)。
编辑:显然,您需要 运行 示例的时间至少 > 10 秒。我运行模拟到20s.
Modelica 中的函数通常不会生成事件。
请参阅 Modelica 规范中的 8.5 Events and Synchronization。
All equations and assignment statements within when-clauses and all assignment statements within function classes are implicitly treated with noEvent, i.e., relations within the scope of these operators never induce state or time events.
但可以更改此行为:
在函数中添加注解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;
状态事件 vs 时间事件
要将 timeEventTest
中的状态事件变为时间事件,请将 if 条件更改为
if time > 10 then
Modelica 规范的第 8.5 Events and Synchronization 章也介绍了这一点。只有以下两种情况触发时间事件:
- 时间 >= 离散表达式
- 时间 < 离散表达式