4

如上所述:我希望随时间计算连续变量的最小值(和/或最大值)。这是一个演示的最小示例:

model MinMaxTest
  Real u;
  Real u_min(start = 10);
  Real u_max(start = -10);
equation
  u = sin(time / 180 * Modelica.Constants.pi);
  u_min = min(u, u_min);
  u_max = max(u, u_max);
  annotation(experiment(StartTime = 0, StopTime = 360, Tolerance = 1e-06, Interval = 1));
end MinMaxTest;

u是任意连续变量(出于演示目的,一个简单的正弦波)。 u_min/u_max是随时间变化的最小值/最大值。

显然预期的结果是u_min=-1u_max=1。不幸的是,模拟因“矩阵奇异!”而崩溃。错误。谁能指导我如何避免这种情况?


编辑 1

我正在使用 OpenModelica 1.15(原为 1.9.2)

编辑 2

由于我对 Modelica 很陌生,我很难理解以下方法之间的区别:

  1. u_min = if noEvent(u < u_min) then u else pre(u_min);
  2. if noEvent(u < u_min) then u_min = u; else u_min = pre(u_min); end if;
  3. u_min = if noEvent(u < u_min) then u else u_min;
  4. u_min = if u < u_min then u else pre(u_min);
  5. u_min = if u < u_min then u else u_min;
  6. when u < u_min then u_min = u; end when;
  7. u_min + T*der(u_min) = if u <= u_min then u else u_min;

1 和 2 是等效的,并导致预期的行为。

3 产生了预期的结果,但给出了关于“代数循环”的“翻译通知”,为什么?

4 到目前为止失败,结果u_min曲线与u?!为什么?

5 结合了 3 和 4。

6 编译失败Sorry - Support for Discrete Equation Systems is not yet implemented

7 我不清楚这背后的想法是什么,但如果T是建议的大小,它就可以工作。

如果我正确理解了 Modelica 文档,那么 1-5 的共同点是始终只有一个方程处于活动状态。noEvent在指定的过零处抑制事件生成。我的印象是,这主要是提高效率。为什么忽略它会导致 4 失败?pre指的是变量的前一个值,所以我想如果我们想保持一个变量不变,那是有道理的,但是为什么没有它 7 可以工作呢?我的理解when是,它的方程只在那个精确的事件中有效,否则保持以前的值,这就是我尝试在 6 中使用它的原因。如果我与常数值进行比较,它似乎有效(这对这个特殊的问题)。

编辑3

  1. u_min = smooth(0, if u < u_min then u else pre(u_min));

有趣的是,这也有效。

4

3 回答 3

3

我使用 Dymola 2016 测试了您的模型并且它可以工作,但是您可以尝试使用另一种方法。在 Modelica 中,您必须根据方程而不是分配来思考。

u_min = min(u, u_min);

如果将代码作为指令序列执行,您会做什么。在后台,Modelica 工具将此方程转换为一个非线性系统,该系统会随着仿真的进行而求解。

这些是我在模拟你的模型时得到的统计数据

Statistics

Original Model
Number of components: 1
Variables: 3
Unknowns: 3 (3 scalars)
Equations: 3
Nontrivial: 3

Translated Model
Time-varying variables: 3 scalars
Number of mixed real/discrete systems of equations: 0
Sizes of linear systems of equations: { }
Sizes after manipulation of the linear systems: { }
Sizes of nonlinear systems of equations: {1, 1}
Sizes after manipulation of the nonlinear systems: {1, 1}
Number of numerical Jacobians: 0

如您所见,有两个非线性系统,一个为u_min,一个为u_max

您问题的替代解决方案如下

model Test
  Real x;
  Real y;
  Real u_min;
  Real u_max;
  parameter Real T = 1e-4;
equation 
  x = sin(time) + 0.1*time;
  y = sin(time) - 0.1*time;
  u_min + T*der(u_min) = if y <= u_min then y else u_min;
  u_max + T*der(u_max) = if x >= u_max then x else u_max;

end Test;

在这种情况下u_min,andu_max是两个状态变量,它们跟随变量 x 和 y,具体取决于它们的值。例如,当x低于u_maxthenu_max时,“卡”在该时间点之前达到的最大值。

抱歉,由于这是我的第一次回复,我无法发布正在运行的模型的图像。

于 2015-06-09T21:19:37.627 回答
3

对于您最初的问题,在 OpenModelica 中对我来说似乎可以正常工作的是:

u_min = min(u, pre(u_min));
u_max = max(u, pre(u_max));

对我来说,编译、模拟并给出预​​期结果,但也确实说“矩阵奇异!”。另一方面,如果我将 u_max 的初始声明更改为:

Real u_max(start = 0);

然后,“矩阵奇异!” 消失了。
我不知道为什么,但这似乎确实可以完成这项工作,我建议它比您列出的其他选项更直接。

于 2015-06-10T13:01:32.417 回答
2

这里的主要问题是你得到一个奇异的方程,因为你试图解方程 u_min = min(u,u_min)。其中 u_min 取决于 u 和 u_min 并且其中的每个值u_min小于u适合该方程的值,工具也可能会尝试为此使用非线性求解器。另一个解决方案可能是延迟运算符:

  u_min = min(u, delay(u_min,0));
  u_max = max(u, delay(u_max,0));

关于不同方法的一些说明:

  1. u_min = if noEvent(u < u_min) then u else pre(u_min);
  2. if noEvent(u < u_min) then u_min = u; else u_min = pre(u_min); end if;

这两者在语义上是相同的,所以结果应该是相同的。pre 运算符的使用也解决了这个问题,因为这里u_min取决于uand pre(u_min),所以不需要非线性求解器。

  1. u_min = if noEvent(u < u_min) then u else u_min;

与上面一样,这里min()使用的解决方案u_min取决于uu_min,导致非线性解决方案的原因。

  1. u_min = if u < u_min then u else pre(u_min);

运算符的语义noEvent()导致字面上使用 if 表达式,在这种情况下,这里u < u_min触发了一个事件,并且u_min = u一直使用该表达式。

  1. u_min = if u < u_min then u else u_min;

是的,它结合了3和4的问题。

  1. when u < u_min the u_min = u; end when;

这里的解又u_min取决于u_minu

  1. u_min + T*der(u_min) = if u <= u_min then u else u_min;

这里 u_min 是一个状态,因此 u_min 的计算由积分器完成,这个方程现在求解 der(u_min),然后影响 u_min。

于 2015-06-10T14:23:43.520 回答