4
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。为什么?

看起来模型中的xtry应该是5。但是为什么try1当时间等于3时模型中的x不是10呢?

4

1 回答 1

3

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

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

我不确定你对这个模型的真正意图是什么。但是,如果您希望它以一个值开始,然后在 time>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. 通过这种方式,这避免了您在以前的模型中可能遇到的不断覆盖xto值的问题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,在 time==3 时,该when子句被评估并被x赋予一个新值。

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

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

于 2012-09-11T20:18:40.490 回答