函数的 Modelica 和事件生成 状态事件 vs 时间事件

问题描述

我尝试了解 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)将时间=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.

不仅没有检测到时间 = 10 时的事件,求解器甚至遇到了一些问题,如错误测试失败所示。 这是一个微不足道的例子,但是,我可以想象,函数对事件的明显抑制可能会导致更大模型中的重大问题。 我在这里错过了什么?我可以在函数内强制执行严格的事件触发吗? 一些内置函数也会触发事件,例如div 和 mod(奇怪的是,sign 和 abs 没有)。

编辑:显然,您需要至少运行示例超过 10 秒。我将模拟运行到 20 秒。

解决方法

Modelica 中的函数通常不会生成事件。

请参阅 Modelica 规范中的 8.5 Events and Synchronization

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;

状态事件 vs 时间事件

要将 timeEventTest 中的状态事件转换为时间事件,请将 if 条件更改为

if time > 10 then

Modelica 规范的第 8.5 Events and Synchronization 章也介绍了这一点。只有以下两种情况会触发时间事件:

  • 时间 >= 离散表达式
  • 时间

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...