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 之间形成稳定极限环。若温度在阈值附近高频抖动,说明事件检测步长或迟滞设置需要调整。

混合系统事件处理与状态切换 连续演化(方程段) C·der(T) = if on then P − h(T−Tamb) else − h(T−Tamb) 求解器连续积分 T(t) 监测事件函数:T−40、T−60 事件检测与定位 过零检测:T−40 或 T−60 变号 暂停积分 → 定位事件时刻 执行 when 分支赋值 on := true / on := false 离散状态更新 on = true on = false T < 40 → 开启加热 T > 60 → 关闭加热 状态反馈:on 影响连续方程,形成闭环 温度轨迹与开关振荡 20 40 60 时间 →

建模要点与常见问题

混合系统建模中最容易出错的地方有三类。第一,事件条件不完整:when 条件若没有明确的边沿语义,求解器可能在同一次事件中重复触发。第二,离散变量未初始化:discrete Boolean on; 在仿真开始前应有确定初值,否则首次事件前的行为不确定。第三,连续与离散耦合过紧:如果 on 的切换频率远高于温度变化的时间尺度,仿真步长会被迫缩小,效率急剧下降,此时应引入迟滞或最小开关间隔。

在实际操作中,建议先用 if 表达式验证连续分段关系,再引入 when 处理离散跳变;仿真后通过 plot 同时观察连续量 T 和离散量 on,检查跳变时刻是否与阈值一致。若发现事件时刻偏移,可减小 tolerance 或启用 events 相关求解器选项。掌握这些方法后,就能在 OpenModelica 中稳定地构建包含开关、饱和、死区和状态机的混合系统模型。