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

Modelica 算法部分中语句的执行顺序,modelica,Modelica,OpenModelica上的两个模拟结果都是x始终等于5。为什么? 似乎模型中的xtry应该是5。但是当时间等于3时,为什么模型try1中的x不是10呢。首先,请记住,在处理when子句时,通常谨慎地使用pre(…)运算符来明确说明所引用的值是新值还是前一值。我不知道在这种情况下是否有严格的必要(即使我知道,我也不确定Modelica工具的所有开发人员是否都使用一致的语义),但这是一个好主意,只要让代码的读者清楚就行了 另一个问题是算法的处理。通常,这些语句是按照它们在算法部分中出现的顺序执行的

OpenModelica上的两个模拟结果都是x始终等于5。为什么?


似乎模型中的x
try
应该是5。但是当时间等于3时,为什么模型try1中的x不是10呢。首先,请记住,在处理
when
子句时,通常谨慎地使用
pre(…)
运算符来明确说明所引用的值是新值还是前一值。我不知道在这种情况下是否有严格的必要(即使我知道,我也不确定Modelica工具的所有开发人员是否都使用一致的语义),但这是一个好主意,只要让代码的读者清楚就行了

另一个问题是算法的处理。通常,这些语句是按照它们在
算法
部分中出现的顺序执行的。但是
when
子句有点棘手,因为它们具有异步性质。同样,我也不清楚当<代码>子句与模型中的其他赋值语句交错时,<代码>子句的确切语义是什么,但是像您这样编写<代码>算法<代码>部分有点含糊不清。让我们假设当计算
语句并且
x
被赋予一个新值时,
将保持该值多长时间?编译器可以在调用
子句后立即计算
算法部分,在这种情况下,
x
将被赋予一个新值
5
(甚至可能没有时间推进)

我不确定你对这个模型的真正意图是什么。但是,如果您希望它从一个值开始,然后在时间>3之后,采用一个新值(基于旧值),我在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;
此模型使用
pre
运算符,但更重要的是,它还使用
initial()
事件为
x
提供初始值。这样,就避免了以前的模型可能遇到的问题,即不断将
x
的值覆盖到
5
。另一种方法是:

  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;
尽管我承认,我怀疑不同的工具对于这些版本可能有不同的语义。我想说,
when initial()
版本可能更普遍一致

更新:

我认为你的误解是因为没有考虑后续评估的影响。在
try1
的情况下,在时间==3时,
子句被计算,并且
x
被赋予一个新值

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


请记住这个问题……从执行
when
子句到下一个模型求值(when
x
重置)之间需要多少模拟时间?很可能。您无法知道算法部分何时执行(这取决于事件、使用的积分器等)。因此,如果您希望在模拟开始时和
时间==3时分别为
x
指定一个值,那么您需要在模型中说明这一点(正如我在示例中所做的)。

谢谢您的建议。我认为算法部分中的语句只有在满足“when”语句中的任何条件时才会执行。例如,在模型“try1”中,x最初设置为5。当时间等于3时,将再次执行算法部分中的所有语句。作为'x:=5;'没有保护,它将始终执行,并且x设置为5。之后,当满足条件时,x将被设置为(5+5)。但是x的变化是瞬间发生的(根本没有时间推进)。因此,我们无法看到x被更改为5,但x是10。以上评论是我基于Modelica材料的理解。但现在我很困惑。我添加了一个更新,并添加了一些附加注释。我希望这会有帮助。是的,你是对的。如果您希望某个内容只分配一次,请将其包装在when子句中。非常感谢。算法部分和等式部分中when子句的触发机制似乎有些不同。但是我的问题现在已经解决了。再次感谢你。
  model InitAndEvent
    discrete Integer x(start=1);
  initial algorithm
    x := 5;
  algorithm
    when time >= 3 then
      x := pre(x) + 5;
    end when;
  end InitAndEvent;