When语句¶
通过使用when
,我们可以表达我们所感兴趣的条件判断以及对这些条件判断的回应。在本节中,我们将回顾when
语句背后的主要思想。when
语句的一般形式如下:
when expr then
// Statements
end when;
对比if
和when
¶
在前面对滞回的讨论里,我们简要地讨论了if
语句和when
语句之间的区别。在when
语句内的代码仅会在触发条件表达式为真的一瞬间被激活。在所有其它的时候,when
语句不会有任何影响。而if
陈述或if
表达式只要在条件表达式为真时,它们就有效。倘若if
陈述或if
表达式包含了else
子句,那么总会有一个分支有效。
表达式¶
大多数时候,expr
表达式会是个条件表达式,而且通常会涉及关系运算符。when
语句常用的条件表达式有例如time>=2.0
、x>=y+2
、phi<=prev_phi
等。回忆前面在讨论间隔测量测算算法时,对于同时出现在expr
以及when
表达式里的变量,你几乎总要在给这些变量加上pre
操作符。
在弹跳球的例子里,我们遇到过expre
并非有一个(标量)条件表达式,而是由条件表达式向量组成的情况。请回忆前面关于有向量形式条件语句的when
语句的讨论:当向量中的任何一个条件变为真时,when
语句就会被激活。
语句¶
when
语句的作用是为变量定义新的取值。我们可以用两种方法定义新的取值。第一种方法是通过将具有以下形式的公式:
var = expr;
在这种情况下,var
将会等于expr
的取值。而expr
里的pre
操作符用于指代变量在事件前的取值。任何以这种方式赋值的变量均为离散变量。这意味着,这些变量的值仅在事件进行时发生变化。换句话说,变量将是分段常数函数。请注意,以这种方式赋值的变量不可能在仿真的任何时间间隔内都保持连续。
虽然严格而言并非必须,但如果你想明确地将变量标记为离散,你可以用discrete
限定词作为其前缀(正如我们在本章前面的取样保持所看到的例子一样)。添加discrete
限定词可以确保该变量的值必须由when
语句来确定。
另一种在when
变量里为变量赋值的方法,正如在弹跳球的例子里一样,是通过使用reinit
操作符。在这种情况下,when
语句内部的代码将会有如下形式:
reinit(var, expr);
在使用reinit
操作符时,变量var
必须是一个状态。换句话说,此变量必须是微分方程求解的结果。在这样的变量里使用reinit
会停止积分过程并改变该状态 (以及其它在同一个when
语句里添加了reinit
的)的值。紧接着,积分实际上使用了一套新的初始条件重新开始。而没有使用reinit
操作符进行重新初始化的其他状态会保持不变。
algorithm
区域¶
最后要注意when
语句如何与Modelica的“单赋值规则”产生关系。Modelica规范中的这条规则规定了每一个变量的值都正好对应一个求值的方程。正如速度的测量以及滞回小节里提到的,有时我们需要用多个赋值语句来描述系统行为(或者说这样可以表达得更为清晰)。在这些情况下,如果所有的赋值语句都被只被放在algorithm
区域,那么这些语句实际上会被看成是一个等式。但是,这样做会减弱编译器执行符号运算的能力,结果可能至少会影响仿真的性能和模型的可重用性中的一个。
值得注意的是,如果在初始化期间需要algorithm
区域这种语义,Modelica包含了一种initial algorithm
区域来实现这种功能。initial algorithm
区域的作用可以类比前面在初始化讨论过的initial equation
区域。正如initial equation
一样,initial algorithm
只会在初始化阶段确定初始化条件时有效,但这种区域支持多次赋值。前述关于符号操作的警告仍然有效。