2012-06-13 149 views
3

刚开始使用Modelica并无法理解其工作原理。Modelica执行顺序

在模型的下面'方法'中,第二行使用qInflow和qOutflow来评估der(h),但他们还没有收到数值! (他们没有在方法的'数据'中定义)?代码执行的顺序是什么。

equation 
assert(minV >= 0, "minV must be greater or equal to zero"); 
der(h)=(qInflow - qOutflow)/area; 
qInflow=if time > 150 then 3*flowLevel else flowLevel; 
qOutflow=Functions.LimitValue(minV, maxV, -flowGain*outCtr); 
error=ref - h; 
der(x)=error/T; 
outCtr=K*(error + x); 
end FlatTank;  

http://www.mathcore.com/resources/documents/ie_tank_system.pdf

回答

5

当来自使用命令式语义的语言和系统时,这是一个可以理解的混乱点。但是Modelica不能这样工作。

使用Modelica时,重要的是要明白equation部分包含方程式,而不是分配。考虑这一点,如果我给你以下方程

x + y = 3; 
x + 2*y = 5; 

如果你明白这是一个数学问题,你就可以判断x必须为1和y的值必须为2的值换句话说,你必须解决一个联立方程组。你会注意到这些方程的左边是而不是变量(一般来说),它们是表达式。公式只是一种关系,它将左侧的一个表达式与右侧的另一个表达式等同起来。此外,这种关系是总是是真的,所以订单是无关紧要的。

这与具有命令语义的命令式编程语言完全不同。但它也非常强大,因为你可以说明这些关系(线性方程组,方程组,非线性方程组,隐式方程等),编译器将找出最有效的方法来解决它们。

回到您的示例中,当您查看问题中的代码时,您正在将这些方程式解释为赋值语句。这个概念被强化了,因为它们恰好在左边有变量。但他们真的是方程式。在基于方程式的系统中,您不必担心给定的变量是否已被分配到以前。相反,要求只是对于每个变量都存在(某处)方程,并且没有额外的方程。换句话说,你应该有与未知数相同数量的变量,方程组有一个独特的解决方案。这就是Modelica所要求的一切。

现在,Modelica支持您习惯的命令式语义。但是它们只能在特殊情况下使用,因为它们限制了数学行为的解释,以至于它干扰了允许Modelica编译器生成真正快速代码的符号操作。所以它不仅仅是一个风格问题。如果可能的话,您应该使用方程式,Modelica中的算法只能用作最后的手段。

最后一个注释。有些人可能想知道:“你是否告诉我这些方程将被放入一个巨大的方程组中,并通过矩阵求逆或Newton-Raphson或其他方法求解?为什么使它变得如此复杂,以至于它可以很容易地解决!”但它不会被解为一个巨大的方程组。如果它可以作为一组简单的作业解决,它将。这是将应用的不同符号操作技术之一(其中很多)。事实上,这是Modelica的一个关键点......您不需要担心优化解决方案的方法,该工具会照顾到这一点。更重要的是,如果你以一种同时系统的方式连接组件,你也不必担心。 Modelica工具可以为您处理这种“代数循环”,他们将优化它以找到计算效率最高的公式,并且不依赖于您为这些案例重新制定模型。

这是否帮助?

+0

没错!我继续介绍基于组件的示例,并且它更有意义。非常感谢作者的指导! – Matt

+0

太好了。很高兴帮助。来自* an *作者“的小修正(有许多Modelica规范的作者,除此之外,Modelica还有其他一些书籍) –

1

你不会知道在Modelica的模型公式的执行顺序,直到你运行它的Modelica工具(你可以重新排序源模型中的任何方程,得到相同的结果)。然后该命令仅适用于您使用此设置的此工具。

这是由OpenModelica编译器选择的顺序(OMC + S + simCodeTarget =转储model.mo):

error = ref - h;
outCtr = K * (error + x);
der(x) = DIVISION(error, T, #SHARED_LITERAL_2(String#);
qOutflow = LimitValue(minV, maxV, (-flowGain) * outCtr);
qInflow = if time > 150.0 then 3.0 * flowLevel else flowLevel;
der(h) = DIVISION(qInflow - qOutflow, area, #SHARED_LITERAL_3(String#);

这个例子有点无聊,因为没有方程式的左右两边发生了变化(如果没有选择h作为状态变量等,h = error - ref将是可行的)。