3. 方程与算法建模方法
在 OpenModelica 中,建模的本质是描述系统“应该满足什么规律”,而不是“按什么顺序计算”。这一区别决定了方程建模与算法建模在语法、求解方式和适用场景上的根本差异。理解这一点,是掌握条件方程、when 语句、离散变量以及混合系统建模的前提。
方程与算法的本质区别
方程(equation)是声明式的:它描述变量之间必须同时成立的约束关系,不指定求解顺序。例如一个电阻的欧姆定律 v = i*R,无论已知 v 求 i,还是已知 i 求 v,方程本身不变,求解方向由求解器根据整体方程组决定。算法(algorithm)则是命令式的:它是一段按顺序执行的赋值语句,类似传统编程,每一步都明确“先算什么、后算什么”。
在 Modelica 中,equation 段用于连续方程,algorithm 段用于顺序算法。二者不能在同一模型中对同一变量重复赋值。方程适合描述物理守恒、本构关系和连接关系;算法适合描述查表、迭代、状态机逻辑或难以写成闭合方程的计算过程。一个常见误区是把算法当成“更灵活的方程”,实际上算法会破坏求解器对系统的整体符号分析能力,应仅在必要时使用。
事件处理与条件方程
连续系统在仿真中并非总是光滑演化。当某个条件发生跳变时,系统进入事件(event)处理流程。OpenModelica 求解器在每一步都会监测事件函数(如 time >= 5 或 x > 0)是否过零,一旦检测到过零,就暂停连续积分,定位事件时刻,执行离散更新,再决定是否重新初始化连续状态。
条件方程用 if 表达式在方程中表达分段关系,例如:
equation
y = if x > 0 then k1*x else k2*x;
这里 if 是表达式而非语句,它仍然是一个方程,只是在不同区域取不同形式。求解器会在 x = 0 附近监测事件,避免在分段点两侧盲目积分。需要注意的是,条件方程的分支应尽量保持连续或至少分段连续,否则可能引入数值刚性或不收敛。
when 语句与离散变量
when 语句用于在事件时刻触发离散赋值,其典型形式为:
when x > 0 then
y = 1;
end when;
与 if 不同,when 只在条件由假变真的瞬间执行一次,而不是在整个条件为真期间持续生效。这正是离散变量更新的语义基础。离散变量(discrete variable)在两次事件之间保持不变,只在事件点被重新赋值。常见声明方式为 discrete Real y; 或 Boolean flag;。
一个容易混淆的点是 when 与 if 的配合:when 内部可以嵌套 if 来选择不同赋值,但 when 本身不能出现在 if 方程的分支里作为条件触发。此外,when 条件应使用 edge() 或 change() 明确表达边沿语义,例如 when edge(x > 0) then,以避免求解器对事件重复触发的歧义。
混合系统建模案例:温控加热器
考虑一个带开关控制的加热器:温度 T 低于 40°C 时加热器开启,高于 60°C 时关闭,加热功率 P 为 500 W,热容 C = 2000 J/K,环境散热系数 h = 5 W/K,环境温度 20°C。这是一个典型的混合系统:连续的温度演化叠加离散的开关状态。
model Heater
Real T(start=20);
discrete Boolean on;
parameter Real C=2000, h=5, P=500, Tamb=20;
equation
C*der(T) = if on then P - h*(T-Tamb) else -h*(T-Tamb);
algorithm
when T < 40 then
on := true;
elsewhen T > 60 then
on := false;
end when;
end Heater;
仿真时,温度从 20°C 上升,在 40°C 触发 on := true,加热器开启;温度继续上升到 60°C 触发 on := false,加热器关闭;随后温度因散热下降,再次低于 40°C 时重新开启,形成周期性开关振荡。观察结果时,应重点检查 on 的跳变时刻是否与温度阈值一致,以及温度是否在 40~60°C 之间形成稳定极限环。若温度在阈值附近高频抖动,说明事件检测步长或迟滞设置需要调整。
建模要点与常见问题
混合系统建模中最容易出错的地方有三类。第一,事件条件不完整:when 条件若没有明确的边沿语义,求解器可能在同一次事件中重复触发。第二,离散变量未初始化:discrete Boolean on; 在仿真开始前应有确定初值,否则首次事件前的行为不确定。第三,连续与离散耦合过紧:如果 on 的切换频率远高于温度变化的时间尺度,仿真步长会被迫缩小,效率急剧下降,此时应引入迟滞或最小开关间隔。
在实际操作中,建议先用 if 表达式验证连续分段关系,再引入 when 处理离散跳变;仿真后通过 plot 同时观察连续量 T 和离散量 on,检查跳变时刻是否与阈值一致。若发现事件时刻偏移,可减小 tolerance 或启用 events 相关求解器选项。掌握这些方法后,就能在 OpenModelica 中稳定地构建包含开关、饱和、死区和状态机的混合系统模型。