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?
答案 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
提供初始值。通过这种方式,这可以避免您以前不断覆盖x
到5
的值的模型所遇到的问题。另一种方法是:
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
时获得一次,那么您需要在模型中说明(如我在示例中所做的那样)。