redeclare 与修饰链:工程设置与参数选择
修饰符链的生效顺序是四级赋值取最后一次,redeclare 有 extends、组件、端口三个落点。给出优先级公式、final 与 break 的判断标准、一个可复现的覆盖示例,以及修饰链断裂的五类报错与定位方法。
redeclare 与修饰链:工程设置与参数选择
redeclare 决定换掉哪一个声明,修饰符链决定参数最终取哪个值。两者遵守同一条原则:离实例化点越近的赋值越优先,越靠近类定义默认值越弱。工程上出错最多的地方是同一个参数在四个位置被赋值,而工程师只看到其中一个。下面给出优先级的确定性顺序、final 的封锁语义,以及修饰链断裂时的报错判据。
修饰符的生效顺序
设某参数 依次在类默认值、extends 修饰符、组件声明修饰符、redeclare 修饰符处被赋值,最终生效值为链上最后一次赋值:
等价地,整条链可以看成一串修饰符按由外到内的顺序复合作用在默认值上:
以初压为例:类默认 p_start = 1.0e5 Pa,类内修饰符给 1.01325e5 Pa,实例声明给 2.0e5 Pa,则 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 沿用类默认。缺了这张表,同一模型在不同装配层级下会得到不同初值,而错误只表现为稳态收敛点漂移百分之几,很难归因。
参考
- Modelica Association. Modelica Language Specification, Version 3.6. 2023. — 修饰符优先级与 redeclare 语法
- Modelica Association. Modelica Standard Library 4.0.0,
Modelica.Fluid.System. 2020. — inner 环境对象的默认值链 - Fritzson P. Principles of Object-Oriented Modeling and Simulation with Modelica 3.3. Wiley-IEEE Press, 2015. — 继承与 final 语义
- Otter M., Elmqvist H., Mattsson S.E. Hybrid Modeling in Modelica Based on the Synchronous Data Flow Principle. IEEE CACSD, 1999. — 结构变化与 redeclare
- Tiller M. Introduction to Physical Modeling with Modelica. Kluwer Academic Publishers, 2001. — 参数覆盖与修饰链
- Sielemann M., Casella F., Otter M., et al. Robust Initialization of Differential-Algebraic Equations Using Homotopy. 8th International Modelica Conference, 2011. — 初值被修饰符覆盖时的初始化