redeclare 与修饰链:工程设置与参数选择

修饰符链的生效顺序是四级赋值取最后一次,redeclare 有 extends、组件、端口三个落点。给出优先级公式、final 与 break 的判断标准、一个可复现的覆盖示例,以及修饰链断裂的五类报错与定位方法。

Modelica连接器redeclare工程设置与参数选择final参数覆盖工程

redeclare 与修饰链:工程设置与参数选择

redeclare 决定换掉哪一个声明,修饰符链决定参数最终取哪个值。两者遵守同一条原则:离实例化点越近的赋值越优先,越靠近类定义默认值越弱。工程上出错最多的地方是同一个参数在四个位置被赋值,而工程师只看到其中一个。下面给出优先级的确定性顺序、final 的封锁语义,以及修饰链断裂时的报错判据。

修饰符的生效顺序

设某参数 θ\theta 依次在类默认值、extends 修饰符、组件声明修饰符、redeclare 修饰符处被赋值,最终生效值为链上最后一次赋值:

θeff=last(θdefault, θclass, θinstance, θredeclare)\theta_{eff} = \mathrm{last}\bigl(\theta_{default},\ \theta_{class},\ \theta_{instance},\ \theta_{redeclare}\bigr)

等价地,整条链可以看成一串修饰符按由外到内的顺序复合作用在默认值上:

θeff=mn∘mn−1∘⋯∘m1 (θdefault)\theta_{eff} = m_n \circ m_{n-1} \circ \cdots \circ m_1\,(\theta_{default})

以初压为例:类默认 p_start = 1.0e5 Pa,类内修饰符给 1.01325e5 Pa,实例声明给 2.0e5 Pa,则 θeff=2.0×105\theta_{eff} = 2.0\times10^{5} Pa。若在实例声明上加 final p_start = 2.0e5,任何更内层的赋值都会被封锁,工具报 cannot redeclare final element。工程做法是:库作者对物理上不允许改的参数加 final(如介质的水蒸气分压上限),对标定值不加。

redeclare 的三个落点

落点 语法位置 影响范围 典型用途
extends 子句内 extends Base(redeclare package Medium = M) 整个派生类 派生出固定介质的专用模型
组件声明 X(redeclare package Medium = M) x 单个组件实例 同一模型里两种工质并存
端口实例 port_a(redeclare package Medium = M) 该端口 让端口数组维数跟随组件介质
inner 声明 inner System system(...) 全部 outer 引用 全模型统一环境参数

第四行不属于 redeclare 但常与它混用:环境对象用 inner/outer 共享,而介质包用 redeclare 逐组件传递,两者不能互相替代。

final 与 break 的使用场合

final 封锁再赋值,break 解除继承来的 final。判断标准只有一条:这个参数是否属于接口承诺。属于承诺的(如换热器管程数、介质组分个数)必须 final,否则用户改掉后方程结构变化;属于设计变量的(如管长 1.5 m、内径 0.025 m)不加 final,让每个实例自由赋值。

package MyLib
  model Pipe
    replaceable package Medium = Modelica.Media.Water.StandardWater
      constrainedby Modelica.Media.Interfaces.PartialMedium;
    final parameter Integer nX = Medium.nX "组分个数由介质决定";
    parameter Modelica.Units.SI.Length L = 1.5;
    parameter Modelica.Units.SI.Diameter d = 0.025;
    Modelica.Fluid.Interfaces.FluidPort_a port_a(redeclare package Medium = Medium);
    Modelica.Fluid.Interfaces.FluidPort_b port_b(redeclare package Medium = Medium);
  end Pipe;

  model WaterLoop
    extends Modelica.Icons.Example;
    inner Modelica.Fluid.System system;
    Pipe pipe(L = 2.0) "覆盖默认管长";
  end WaterLoop;
end MyLib;

nX 被 final 锁死,用户写 Pipe(nX = 1) 直接编译失败;L 未加 final,WaterLoop 里的 L = 2.0 m 覆盖默认 1.5 m,生效值就是 2.0 m。

修饰链断裂的判定

现象 根因 判定试验
报 cannot redeclare final element 上游已加 final,下游仍赋值 沿继承链搜索 final 关键字
参数值不是实例里写的那个 更靠内的 extends 修饰符优先级更高 把实例修饰符删掉,看输出是否回退到类默认
报 redeclare element not found 被替换声明不在当前作用域或名字拼写不符 核对 redeclare 与 replaceable 的标识符完全一致
替换后方程数变化、模型过定 换入类比约束类多声明了方程 对比替换前后方程数,差值应来自新增组件而非接口
outer 环境取到默认值 容器上缺少 inner 实例 搜索全模型 inner 关键字,确认恰好一处

参数覆盖的核对记录

一个可复现的做法是把四级赋值写进同一张表,逐行标注来源文件与行号。例如 p_start 取 2.0e5 Pa、T_start 取 293.15 K、L 取 2.0 m、d 保持 0.025 m,就应在记录里写明 L 由 WaterLoop 实例覆盖,d 沿用类默认。缺了这张表,同一模型在不同装配层级下会得到不同初值,而错误只表现为稳态收敛点漂移百分之几,很难归因。

参考

  1. Modelica Association. Modelica Language Specification, Version 3.6. 2023. — 修饰符优先级与 redeclare 语法
  2. Modelica Association. Modelica Standard Library 4.0.0, Modelica.Fluid.System. 2020. — inner 环境对象的默认值链
  3. Fritzson P. Principles of Object-Oriented Modeling and Simulation with Modelica 3.3. Wiley-IEEE Press, 2015. — 继承与 final 语义
  4. Otter M., Elmqvist H., Mattsson S.E. Hybrid Modeling in Modelica Based on the Synchronous Data Flow Principle. IEEE CACSD, 1999. — 结构变化与 redeclare
  5. Tiller M. Introduction to Physical Modeling with Modelica. Kluwer Academic Publishers, 2001. — 参数覆盖与修饰链
  6. Sielemann M., Casella F., Otter M., et al. Robust Initialization of Differential-Algebraic Equations Using Homotopy. 8th International Modelica Conference, 2011. — 初值被修饰符覆盖时的初始化