算法部分中语句的执行顺序

时间:2012-09-11 16:17:36

标签: modelica

model try
discrete Integer x(start = 1);
algorithm
when time >= 3 then
  x:= x + 5;
end when;
x:= 5;
end try;

model try1
discrete Integer x(start = 1);
algorithm
x:= 5;
when time >= 3 then
  x:= x + 5;
end when;
end try;

OpenModelica上的两个模拟结果都是x总是等于5.为什么?

似乎模型try中的x应为5.但是当时间等于3时,为什么模型try1中的x不是10?

1 个答案:

答案 0 :(得分:3)

我有两条评论。首先,请记住,在处理when子句时,通常谨慎使用pre(...)运算符来明确说明您引用的值,新值或前者。我不知道在这种情况下是否是完全必要的(即使我知道,我不确定Modelica工具的所有开发人员是否都使用一致的语义),但如果只是为了清楚地说明它是一个好主意代码的读者。

另一个问题是处理算法。通常,语句按照它们在algorithm部分中出现的顺序执行。但when条款有点棘手,因为它们具有异步性质。同样,我不清楚关于when子句与模型中的其他赋值语句的交错的确切语义是什么,但是像你一样编写algorithm部分有点模棱两可。我们假设when语句已被评估,x被赋予一个新值,您期望它保持该值多长时间?编译器具有重复评估的自由度,可以在调用when子句后立即评估算法部分,在这种情况下,x将被赋予5的新值(甚至可能没有时间推进在所有)。

我不确定你对这个型号的意图是什么。但是如果你想让它以一个值开始,然后在时间> 3之后,取一个新值(基于旧值),我看到两种方法在Modelica中实现这一点,并且它们都涉及如何设置初始值值。考虑以下模型:

  model InitAndEvent
    discrete Integer x(start=1);
  algorithm
    when initial() then
      x := 5;
    end when;
    when time >= 3 then
      x := pre(x) + 5;
    end when;
  end InitAndEvent;

此模型使用pre运算符,但更重要的是,它还使用initial()事件为x提供初始值。通过这种方式,这可以避免您以前不断覆盖x5的值的模型所遇到的问题。另一种方法是:

  model InitAndEvent
    discrete Integer x(start=1);
  initial algorithm
    x := 5;
  algorithm
    when time >= 3 then
      x := pre(x) + 5;
    end when;
  end InitAndEvent;

虽然我承认我怀疑不同的工具可能对每个版本都有不同的语义。我会说when initial()版本可能更普遍一致。

<强>更新

我认为您的误解来自于不考虑后续评估的含义。在try1的情况下,在时间== 3,评估when子句,并为x赋予新值。

但是下一次模型评估会发生什么?再次评估算法部分并将x设置回5 when子句不会再次进行评估,直到条件表达式变为false,然后再次为true。所以在这种情况下,它只触发一次!如果您希望对所有大于3的时间进行评估,则需要使用if语句。

并记住这个问题...... when子句的执行和下一次模型评估(重置x时)之间经过了多少仿真时间?很可能。您无法知道何时执行算法部分(这取决于事件,使用的积分器等)。因此,如果您希望x在模拟开始时获得一次值,而在time==3时获得一次,那么您需要在模型中说明(如我在示例中所做的那样)。