Files
SystemSimulationApp/docs/standard/component-model-authoring-spec-v1.md
ljz 7611f13208 修复循环信号与事件采样并接入 LSTP 接触定位,补充八路验证及复用实验
相较上一版 Jacobian 确定性复用更新,本次补齐事件边界一致性、结果两侧采样及接触事件定位;保留已有物性复用和组件力学公式。

- 统一 UD00 信号求值与下一事件查询的绝对时间边界,修复循环边界浮点舍入导致的阶段错位、重复或漏报,并覆盖零时长、多阶段及长周期场景。
- 引入原生输出语义 v2:保留规则网格真实时间,补充内部时间事件和状态事件的左邻及事件后采样,按保存时间、状态和离散模式重放结果。
- 两条代码生成路径均发出 LSTP 接触描述,默认定位间隙过零及非负力模式的力截断;仅在接受事件时更新防重复记录,增加 contactEvents 诊断计数。
- 补充 MASS/LSTP 独立事件实验、八路全曲线与驱动阶段配对评估,以及 Amesim 不连续点输出对照和力差定位报告;MASS 新增释放机制仍保留为独立实验。
- 保存局部 probe、context 访问与回退、shadow replay、R288 real skip/typed replay 及阀门数值尾部诊断工具和报告;未证明净收益的实验不启用为生产默认优化。
- 更新原生运行说明和元件建模规范,补充信号边界、输出语义、接触事件和实验依赖回归测试。

验证:五组专项回归共 34 项全部通过;37 个待提交 Python 文件语法检查通过;git diff --cached --check 通过。
2026-09-17 23:50:13 +08:00

32 KiB
Raw Permalink Blame History

组件模型建模规范 v1

文档版本:1.2.0 修订日期:2026-09-12 核对代码基线:22579e5 加本次输入合同实现;配套工程 JSON v2,XML v3 和模型版本不变。

状态:Python 声明、C 数值实现;本版按实际注册与浏览器导入演练修订。 总流程:新组件注册流程;示例:注册示例与验证。 适用对象:人工开发者、代码生成工具和 AI 编程助手 配套读取规范:组件库分类、发现与读取规范 v1 端口供需规范:气动端口变量供需合同

1. 文档目标

本文档规定采用 Python 元数据与 C 数值内核的元件应如何创建、修改、测试和注册。完成后的模型必须 同时满足四个使用方:

  1. C 编译器能够读取模型声明、生成系统代码并调用 C 方程。
  2. System XML 能够根据稳定类型找到模型。
  3. React Flow 能够自动显示图标、端口和参数。
  4. 结果页面能够根据结构化元数据展示变量。

本文档是模型代码的开发合同。若本文档与当前代码行为不一致,应把它视为缺陷: 先核对实际实现,再在同一次修改中同步代码、测试和文档,禁止让两套规则长期并存。

2. 开始前先判断任务类型

2.1 新增公开模型

公开模型加入启用库后能被目录和 System XML 识别;前端当前隐藏 experimental 库,其余有效库可见。参与原生仿真还需第 12 节的完整数值接入。必须:

  • 放入某个组件库的分类目录。
  • 实现完整模型契约。
  • 加入该库 library.py 的 models 清单。
  • 添加目录、契约、方程和最小仿真测试。

2.2 修改已有公开模型

必须先判断改动是否破坏已有工程:

改动 版本建议 兼容性要求
修复数值实现但不改变契约 修订版本 若提高 modelVersion,既有 XML 会因精确版本不匹配而被拒绝;需明确是否真的变更合同
新增有默认值的参数或结果 次版本 新 XML 必须写全当前参数;无通用迁移,前端已有部分型号专用迁移
修改界面名称或图标 库修订版本 不修改机器标识
修改方程的物理语义 根据影响提高次版本或主版本 补充基准和变更说明
删除、改名端口或参数 主版本 当前格式直接拒绝旧端口或参数;如以后需要兼容,再单独设计迁移器
修改 MODEL_TYPE 视为新模型 明确保留旧实现、显式迁移或拒绝旧工程;没有自动生成的迁移映射

2.3 新增内部模型

研究类可以不加入生产清单。但当前原生入口要求精确的类及版本合同,不能只新增 C 函数和白名单就直接执行未发现的类。需要端到端演练时,在隔离源码副本中建立明确的测试库、原生发现入口与方程适配,见注册示例;或设计并验证专门的内部适配入口。不要恢复旧 Python 求解路径,也不要把演练类留在正式目录。

2.4 新增物理域

仅新增模型类不足以支持新物理域。除了模型,还必须设计:

  • PortDefinition 和端口变量。
  • 变量角色与连接规则。
  • 网络兼容性检查。
  • 代数方程和 stream/signal 传播。
  • XML 端口协议。
  • 前端连线兼容规则。
  • 最小闭合系统与求解测试。

没有完成这些基础能力时,不得仅通过修改 domain 字符串宣称支持新物理域。

3. 开发前必须读取的文件

人工或 AI 在修改模型前,应按顺序读取:

  1. 本文档。
  2. 目标库的 library.py。
  3. 同分类中物理行为最接近的现有模型。
  4. core/base.py。
  5. core/ports.py。
  6. core/metadata.py。
  7. core/catalog.py。
  8. registry.py 中的启动校验。
  9. 与目标模型最接近的测试。

不要只根据文件名、前端图标或旧 XML 猜测模型语义。

4. 文件位置和命名

公开模型放在:

app/simulation/components/<library_id>/<category_id>/<model_module>.py

例如:

app/simulation/components/experimental/storage/cylinder.py
app/simulation/components/experimental/flow/orifice.py
app/simulation/components/experimental/junctions/tee.py

规则:

  • 推荐每个公开模型单独成文件;注册器不按文件名发现,现有同一文件包含多个相关型号的组织方式仍有效。
  • 模块名、MODEL_TYPE、端口名和参数名使用稳定机器标识。
  • MODEL_TYPE 使用小写 snake_case。
  • 参数和结果变量允许保留已有热力学惯例,如 T0、T、U。
  • 中文名称只写入 label,不能代替机器标识。
  • 求解器、介质和网络通用逻辑不得复制到模型文件。

5. 公开模型完整契约

每个公开模型类必须在自身类体中显式声明:

MODEL_TYPE = "example_component"
MODEL_VERSION = "1.0.0"
PORTS = (...)
PARAMETERS = (...)
RESULT_VARIABLES = (...)
DISPLAY = ...

同时必须实现:

@classmethod
def create(
    cls,
    *,
    name: str,
    medium: IdealGasMedium,
    parameters: Mapping[str, float],
) -> Component:
    ...

注册器要求这些字段直接存在于公开模型类中。不要依赖父类隐式提供 MODEL_TYPE、MODEL_VERSION、PORTS、PARAMETERS、RESULT_VARIABLES、 DISPLAY 或 create()。

6. 基类选择

AlgebraicComponent 表示没有积分状态的元件;DynamicComponent 表示有积分状态的元件;ThermodynamicVolumeComponent 提供标准 m,U,p,T,rho,u,h 结果声明。这些基类只描述模型,不再实现数值求值方法。

state_size 只描述 Python 对象,不能自动生成原生状态;状态索引、初值、导数和输出须在生成路径逐项实现。

构造函数负责参数校验、几何预处理和端口注册。介质对象保存物性常量与模型选择。状态初值、流量、焓、受力和导数必须在 C 中计算。

用 EQUATIONS 或 equation_definitions() 声明结构化连接约束,返回 EquationDefinition,包括关系、变量和归属,不包含运行时残差值。__MODEL__ 占位符由基类替换为实例名。该声明供网络结构展示与检查使用,不替代 C 方程或构建支持白名单。

7. 端口建模规范

当前气动模型使用:

PortDefinition.pneumatic(
    "port_a",
    nominal_role="bidirectional",
    computation=THERMODYNAMIC_SUPPLY,
)

上例适用于提供温度/压力的储气端,THERMODYNAMIC_SUPPLY 从 core.port_computation 导入。阀门或管道阻力端应按实际模型选择 FLOW_SUPPLY;不能给所有气动端口套用同一个供需模板。

气动端口包含:

变量 角色 连接规则 SI 单位
p effort equal Pa
m_flow flow sumToZero kg/s
h_outflow stream streamMix J/kg
volume signal directed m3
volume_flow signal directed m3/s

必须遵守:

  • m_flow > 0 表示质量流入当前组件。
  • nominal_role 只用于界面和默认布局,不限制实际流向。
  • 物理连接的端点顺序不代表流向;具体子模型仍可规定固定的变量供需,例如 PN3NODE2 的参考口。
  • 所有声明端口必须使用 register_declared_port() 创建。
  • DISPLAY.ports 必须与 PORTS 名称集合完全一致。
  • 分支连接使用三通等连接元件,不能让一个物理端口直接连接多条边。

禁止:

  • 在模型内部根据画布左右方向判断流向。
  • 为了前端显示另造一套端口名。
  • 把 port_a 固定解释为真实入口、把 port_b 固定解释为真实出口。
  • 直接绕过端口状态读写其他组件对象。

7.1 新元件先写逐变量接口表

新模型必须先在模型说明中列明每个端口的下列信息,再写元数据和 C 代码:

信息 必须回答的问题
物理含义、机器名、SI 单位 传递的是温度还是比焓?能量还是能量流率?
提供方/使用方 该变量由本部件提供、从对端取得,还是需要连接方程共同确定?
提供方式 来自当前状态、固定值、另一个端口的别名,还是由公式计算?
计算依赖 计算该输出具体需要哪些输入、状态和参数?不要只写“依赖某部件”。
符号与坐标 正号代表流入还是流出?机械量采用什么方向?映射原模型时是否取反?
必需性及默认值 缺少对端变量时能否用有物理依据的默认值?何时应当报错?
条件变化 参数是否改变可用端口、输入输出关系?反向流、零流量或切换时怎样处理?

固定参数放在 PARAMETERS,例如管径、长度、初始温度 T0;随仿真变化的端口量放在接口定义中,例如当前温度 T。固定开度变体可以有意用参数代替开度信号,但应使用独立模型类型并说明差异。

7.2 供需声明与当前实现边界

PORTS 是权威来源。当前 PortComputation 的 inputs/outputs 支持 p、T、m_flow、H_flow 四个气动量;reference_port 只表达 p/T 从另一个端口输入复制的关系。前端目录与 JSON/XML 校验从注册表恢复这些声明,工程快照不能覆盖它们。

H_flow 表示能量流率(W),只用于当前接口供需检查,不能当作已经存在的 C 运行时端口字段;运行时仍使用 h_outflow 和质量流率。两种表达的单位、符号及零流量处理必须在 C 方程中正确转换。

  • mode="fixed" 表示该子模型的接口供需是固定要求;它不表示输出数值为常量,也不是固定积分步长。
  • mode="equation" 表示允许连接方程联合确定变量。必须有相应 C 求解能力支持,不得为了绕过错误接线而随意改为此模式。
  • 新移植部件如有明确的固定输入输出,应按原始接口声明并验证。现有非节点部件采用 equation 是本阶段保留已有联合求解能力的策略,不能把它当作所有 Amesim 子模型的原始接口定义。
  • 新模型需要声明容积、机械量、任意输出依赖或可选输入默认值时,应先同步扩展供需数据结构、注册器、目录 schema、前后端检查与测试。当前四变量接口尚不能完整承载这些信息,不得只在注释或 JSON 中添加编译器不读取的字段。

7.3 从 Amesim 移植时的对照要求

以明确的 Amesim 版本和子模型编号为依据读取端口变量表及其实现;图标相同或端口数量相同不足以证明模型等价。每个原始变量都应有映射记录:保留、换名、单位/符号变换、由其他量导出、仅保留默认值,或明确不支持。

枚举必须按含义转换,不能按数字相等判断匹配。已核查的直接选择参数集中在 app/simulation/components/amesim/semantics.py;例如 UD00 的 AME 1/2 对应公共 0/1。转换仅应用于外部 AME 参数,禁止再次应用于已经采用公共编码的 JSON/XML。新增选择项须补映射覆盖测试;尚未实现的活动选项必须在执行编译时明确拒绝,不能静默沿用其他模式的公式。模型仍可保存,执行能力与保存能力分别说明。

既要记录普通输入/输出,也要记录状态、固定输出、别名、取反别名、可选输入及默认值。例如 PNCH012 的容积输入和 MECMAS21 的加速度端口量,不能因为当前四变量气动模板没有对应字段就不作说明。

接口方向对齐、局部公式对齐和完整仿真曲线对齐是三项不同的验证;不能用其中一项替代其他两项。实验组件及自行简化的变体,不应宣称与 Amesim 原子模型一比一相同。

7.4 为计算排序准备元件步骤

元件说明和 C 接入应区分:状态/物性输出、连接量与局部代数计算、状态导数、展示输出。例如储气元件先由当前状态提供温度和压力,得到流量后再算导数,不能把整个元件当作一个不可拆分的步骤。

端口供需合同不承载任意计算步骤的依赖图。当前扩展 C 生成器使用 Computation 记录内置气动方程的输入、输出与 C 语句,再自动排序及划分局部循环。新模型须显式接入这些计算关系;只注册 PORTS/PARAMETERS 不会自动生成数值方程。参考值复制与能量汇总应拆开,多输出 C 调用必须正确列出读取参数与写出结果,见 C 求值排序规范。

新增或修改接口至少验证:合法连接、输入无人提供、冲突连接、参考链及参考环、反向/零流量、可选输入默认值、单位/符号映射,以及独立解析或外部基准下的 C 结果。没有对应机制的能力必须标记为尚未支持。

8. 参数建模规范

所有用户可配置输入必须使用 ParameterDefinition:

ParameterDefinition(
    name="volume",
    label="容积",
    quantity="volume",
    unit="m3",
    default=0.1,
    minimum=0.0,
    minimum_exclusive=True,
)

字段含义:

字段 规则
name 稳定机器名,同时用于 XML、工程文件和 create()
label 前端显示名称,不能为空
quantity 受控物理量标识
unit 后端 SI 基准单位
default 必须能够创建有效模型
minimum / maximum 必须反映方程有效范围
minimum_exclusive 用于直径、容积等严格大于零的量

当前受控单位定义在 SI_UNIT_BY_QUANTITY:

quantity SI 单位
acceleration m/s2
area m2
dimensionless 空字符串
density kg/m³
flow_coefficient kg/(s*Pa^0.5)
force N
heat_transfer_coefficient W/(m2*K)
internal_energy J
length m
mass kg
mass_flow kg/s
pressure Pa
specific_enthalpy J/kg
specific_internal_energy J/kg
temperature K
time s
translational_damping N/(m/s)
translational_stiffness N/m
velocity m/s
volume m3
volume_flow m3/s
windage N/(m/s)^2

新增物理量时先扩展后端受控单位表,并核对共享参数单位表 schemas/parameter-units.json、结果页 RESULT_UNIT_OPTIONS 及三入口换算测试。目录的 unit 只给出基准单位,不会自动产生全部换算选项;例如当前 time 参数只显示 s,不能假设已支持 ms。新增编辑器需同时扩展元数据枚举、注册校验、目录解析和实际控件。禁止在单个模型中私自拼写新的同义 quantity。

构造函数必须调用:

self.set_parameter_values(
    {
        "volume": volume,
        "p0": p0,
        "T0": T0,
    }
)

方程和结果输出使用 SI。外部工程 JSON v2 数值、数字字符串、表达式统一使用所选参数单位;网页、HTTP、CLI 在适配层归一化,内核仅接受有限 SI 数字。旧 v1 数值为 SI,导入保留含义后再转换导出 v2。单位源表为 schemas/parameter-units.json,详见参数入口合同。

9. 结果变量规范

9.1 组件级结果

组件自身状态或派生量使用 ResultVariableDefinition:

ResultVariableDefinition(
    name="pressure_drop",
    label="压降",
    quantity="pressure",
    unit="Pa",
    category="derived",
    order=10,
)

声明为可见的组件输出和活动端口可见输出必须在 C 生成器的输出布局中有对应值。测试应核对实际 EXE 输出键与 result_variable_metadata() 一致,不再实现 Python component_result_values()。

9.2 端口结果

端口结果由 PORTS 的端口变量自动产生,不要在 RESULT_VARIABLES 中重复声明 port_a.p、port_a.m_flow 等字段。

9.3 禁止暴露的内容

以下内容默认不能作为用户结果:

  • 非线性求解器内部未知量索引。
  • 缩放残差和迭代缓存。
  • 仅用于调试的临时中间值。
  • 可以由已有结果稳定推导、但没有明确工程用途的重复字段。

10. 显示声明规范

公开模型必须声明 DISPLAY:

DISPLAY = ComponentDisplaySpec(
    label="示例阻力元件",
    library_id="experimental",
    category_id="flow",
    symbol="generic",
    ports=(
        PortDisplaySpec("port_a", "left", order=10),
        PortDisplaySpec("port_b", "right", order=20),
    ),
    order=90,
)

规则:

  • library_id 必须等于所属库 ID。
  • category_id 必须存在于所属库的 categories。
  • symbol 是前端图形键,不是模型类型。
  • 可复用已存在的图形键;也可使用新的稳定键并暂时回退通用图形,不能据此声称已实现专用图标。
  • 只有确实需要专用工程图标时才修改前端图标渲染器。
  • side 只允许 left 或 right。
  • 旋转和镜像不能改变端口名或物理语义。
  • role="amesimGasMediumDefinition" 是介质识别元数据,XML/前端和网络的介质定义基类必须配套;不是只设图形角色就能实现新介质。
  • 动态端口不是通用目录能力;当前 LMECHN1 存在专用逻辑。新动态型号必须同步有效端口查询、前端布局、参数变更后旧连线处理及往返测试。

11. 标准创建入口

create() 是注册器创建模型的唯一入口:

@classmethod
def create(
    cls,
    *,
    name: str,
    medium: IdealGasMedium,
    parameters: Mapping[str, float],
) -> ExampleComponent:
    return cls(
        name=name,
        medium=medium,
        coefficient=parameters["coefficient"],
    )

注册器会在调用前:

  1. 补齐默认参数。
  2. 拒绝未知参数。
  3. 检查有限值和边界。

调用后还会检查:

  1. 返回对象类型正确。
  2. 实例 model_type 与 MODEL_TYPE 一致。
  3. 实际端口与 PORTS 完全一致。
  4. 实例保存的参数与规范化参数完全一致。

create() 不另造一套默认值或偷偷修改传入参数。构造函数仍须调用 set_parameter_values(),并处理必要的跨字段约束;不能以注册器已检查为由删除直接构造所需的校验。XML 要求完整参数,不能把 Python 工厂的补默认行为当成 XML 的规则。

12. C 方程实现要求

  1. 优先复用现有内核;新公式放入 native/components/modules/ 合适模块,公共声明放入 native/include/kernels.h。增加函数或模块依赖时同步 native_codegen/modules.py::EXPORTS/DEPENDENCIES,防止生成代码已有调用但链接遗漏实现。
  2. native/components/kernels.c 是模块的诊断聚合入口,生产按需构建不直接编译它。新增模块核对聚合包含清单;不要同时链接聚合文件和各模块造成重复定义。
  3. 在 native_codegen/extended.py 接入端口、介质、状态、初始化、方程、导数、输出与事件。新型号默认走支持它的路径;只有将其纳入 compiler.py 紧凑路径时才同步实现该路径,不能只扩充类型集合。
  4. 新库还要加入 extended.py::catalog_contracts();核对精确类及 contracts.py::SUPPORTED_VERSIONS。版本表代表已实现的能力,不能代替方程或 C 输出映射。
  5. 用 Computation/EvaluationSchedule 声明实际计算依赖,多输出函数区分读取参数与写出指针;别名和依赖流量的汇总拆开。新增循环需要对应的求解能力,不是图排序成功就一定能求解。
  6. 核对 jacobian.py 的表达式和状态依赖分析。新函数经审查后才纳入识别集合;分支、投影、多输出依赖必须完整。未知依赖允许保守逐列差分,禁止当常量处理来保留着色。动态模型适用时给生成的 model/model.exe 传 --verify-jacobian 对照;Python 包装 CLI 当前没有该参数。
  7. 核对 tolerances.py 的量纲尺度:当前 m/m1/m2 为 1e-14,x/v 为 1e-12,其他字段默认 1e-8。新状态按物理量评估,不能只依名称套用默认值。
  8. 当前状态与试探状态分离,无效物性、欠定连接和不收敛明确失败。气动物性复用传递 NativePropertyCache 上下文,不跨试算无条件复用旧值。信号跳变和限位接入运行库,不能改物理参数或放宽容差隐藏错误。
  9. 保持 SI、端口符号和适用的质量/能量守恒;按需编译及缓存由内容失效机制管理,测试完整模型命中、参数变化、模块变化及遗漏导出错误。
  10. C 代码、构建依赖、进程与文件操作遵守跨平台交付约定。分别记录 Linux 与 Windows 实际结果,不把 Linux 模拟测试写成 Windows 验收。

12.1 分段信号的时间事件

新增阶跃、脉冲或循环分段信号时,元数据注册不会自动建立时间事件。除信号值方程外,还须在原生生成器中提供下一事件时间,汇入 model_next_break(t, end)。默认接入 extended.py;若该型号也走 compiler.py 紧凑路径,则两条路径都须实现。连续光滑信号没有这项分段要求;由压力、位置等状态触发的切换需要相应状态事件支持,不能仅凭时间表处理。

  • 求值与事件查询必须共享同一套绝对时间边界。可复用 UD00 的 native_signal / native_signal_break;避免一边以取模判断阶段,另一边独立计算事件。仅新增现有 UD00 实例或修改参数无需再次注册事件。
  • 对 t < end,返回严格晚于 t 的最近边界,超过仿真终点或没有后续事件时返回 end。包含开始时刻、阶段端点、周期回绕,以及模型需要定位的斜率变化;同一时刻的零时长阶段按合同合并处理。
  • UD00 使用右连续阶段规则:t < boundary 属于前一段,t == boundary 属于后一段。周期终点统一使用下一周期起点。不能用任意全局 epsilon 把真实边界前的时刻提前切换。
  • 求值必须支持试探步、回退和结果重放;不得在普通 model_eval 调用中推进全局阶段索引。UD00 当前由时间纯函数查找阶段。需要离散状态的组件,应另行实现可回退、可重放的状态及事件提交机制。
  • 运行库按最早边界分段积分,在内部边界左侧结束旧段,再于边界处保留连续状态并重新启动积分。新组件通常复用该流程,不为每个型号新增求解器分支。名义采样时间仍按其实际浮点值求值;“界面显示同一小数”不等于内部时间完全相等。
  • 新内核函数同步公共声明及 native_codegen/modules.py 导出/依赖。测试边界前一个浮点数、边界本身及后一个浮点数,并覆盖延迟开始、周期回绕、多周期、退化参数和 BDF/RK45 最小系统的结果重放。参照 tests/test_native_signal_boundaries.py。

12.2 事件输出与重放

原生输出语义 version 2 保留实际时间的规则采样,并自动保存内部时间事件的左侧相邻浮点时刻及事件时刻。已有状态重置事件在当前积分区间可用时保存左邻插值状态,再保存重置后的状态;同一实际时间以后一次接受状态为准。时间序列保持严格递增,样本数量可能超过规则网格点数。初始即时事件不倒填时间,仿真终点不额外制造时间事件。

组件接入已有时间/状态事件接口后无需自行写入输出文件。结果重放必须仅依赖保存时间、完整状态和模型参数;模式影响输出时,必须有可保存、可回退、可重放的表示,不能读取运行结束时的全局模式。接触状态接口同样需要遵守这项约束。相关运行库合同见 native/README.md,测试见 tests/test_native_output_semantics.py。

外部对照不能把显示为同一小数时刻当作同一事件侧。当前八路评估以全部分段常值信号核验驱动阶段,所有变量共用同一对保存样本;保留双方真实时间及无法配对记录。相同阶段也不等于实际时间完全相同,高刚度快速过程仍需进一步核验时间差的影响。

12.3 LSTP 接触状态事件

LSTP00A 已在两条原生生成路径默认注册:native_codegen/contacts.py 发出两端机械速度/位移状态索引、间隙、刚度、阻尼、阻尼距离、力符号模式及原公式运算顺序;native/runtime/contact_events.h 在接受步的密集插值上定位间隙过零,并在非负力模式定位接触区内的原始力过零。新增现有 LSTP 实例或修改其参数无需额外注册。

此接口只覆盖已审查的 LSTP 状态形式,不会因新组件名称或元数据相似而自动适用。新增类似组件时,须明确事件函数及依赖、根方向、初始贴边/切触、连续状态是否重置、同时事件和防重复提交规则;生成的事件表达式应与力公式保持一致,包括浮点运算顺序。检测不能悄悄引入整模型 RHS 求值或改变已有雅可比/物性复用。MASS 弹性限位及连续释放仍为独立实验,未在本次加入默认路径。

接触事件的运行期记录只用于定位及防止重复触发,不影响力求值。若新模式需要真正的离散物理状态,应按 12.2 保存和重放,不能借用这个定位记录作为不可重放的力开关。验证应包括解析或独立参考、步长变化、接触与脱离、力截断、无事件轨迹保持和 BDF/RK45;参考 tests/test_native_contact_events.py。

13. 模型实现示例

可参照 气瓶声明、气腔声明、C 数值模块 与 系统 C 生成器。完整开发顺序见 注册示例与验证。

Python create() 只创建经校验的描述对象;C model_init() 生成质量、能量及机械状态,model_eval() 计算导数和输出。两者通过生成的状态/参数布局关联。

14. 注册模型

元数据发现这一步,在所属库的 library.py 加入类路径;它不替代第 12 节的原生接入:

models=(
    # 已有模型
    "app.simulation.components.experimental.flow.example_restriction:ExampleRestriction",
)

禁止:

  • 直接修改 COMPONENT_MODEL_REGISTRY。
  • 在前端复制参数和端口定义作为正式来源。
  • 递归扫描组件目录自动导入所有 .py。
  • 同时注册两个相同 MODEL_TYPE。
  • 把测试类、抽象基类或内部算例模型加入公开清单。

15. 测试要求

每个公开模型至少添加:

  1. 静态契约测试。
  2. 默认参数创建测试。
  3. 参数边界测试。
  4. 端口与显示布局一致性测试。
  5. C 方程与独立解析解或冻结参考值对照。
  6. 按物理适用性覆盖零流量、反向流动或信号边界;无流量的信号源不套用气动守恒验收。
  7. 目录输出测试。
  8. 最小 XML 编译测试。
  9. 使用当前支持的 C RK45/BDF 做短时仿真,事件按模型适用性验证;XSD 中出现其他方法不代表运行库已支持。
  10. 浏览器完整接线工程的导入、编辑、XML、运行、结果保存、CSV 和刷新恢复。后端单元件允许的未接端口警告,在前端可能是阻止运行的错误。
  11. 编译/缓存与实际 Windows/Linux 验证;依赖着色的动态模型另有雅可比对照。

推荐先运行:

.\.venv-win\Scripts\python.exe -m unittest `
  tests.test_component_registry `
  tests.test_component_catalog `
  tests.test_component_metadata

随后按改动范围运行型号数值、网络、原生构建与浏览器测试;涉及共享合同、内核或求解行为时运行完整回归:

.\.venv-win\Scripts\python.exe -m unittest discover -s tests

目录契约影响前端时还要运行:

cd frontend
$env:Path = (Join-Path (Split-Path $PWD) '.tools\node-v24.18.0-win-x64') + ';' + $env:Path
npm.cmd run build

16. 修改已有模型的安全步骤

  1. 找到 MODEL_TYPE 的所有 XML、工程和测试引用。
  2. 记录修改前的端口、参数、结果和默认行为。
  3. 判断版本级别和是否需要迁移。
  4. 先增加或修改测试,明确预期物理行为。
  5. 修改模型类,不在注册器和前端复制规则。
  6. 检查默认实例和旧参数是否仍能创建。
  7. 检查最小系统是否仍然闭合。
  8. 运行针对性测试,涉及共享机制时完成相应完整回归。
  9. 同步本文档或模型专属说明中的物理假设。

17. 人工或 AI 的任务输入卡

为了减少猜测,新增模型前建议先填写:

模型中文名称:
MODEL_TYPE:
所属 library_id:
所属 category_id:
物理域:
模型用途和边界:
端口列表及含义:
参数列表、SI 单位、默认值和范围:
状态变量:
代数方程或微分方程:
正流量约定:
需要显示的组件结果:
已知参考模型或工程公式:
最小测试系统:
允许的近似:
明确不实现的能力:

如果关键物理信息缺失,AI 应先通过现有模型、测试或用户提供的参考补齐;不能仅凭 组件名称自行创造方程。

18. AI 修改协议

AI 创建或修改模型时必须遵守:

修改前

  1. 读取第 3 节列出的文件。
  2. 检查工作区已有改动,不能覆盖无关修改。
  3. 明确模型是公开模型还是内部模型。
  4. 明确端口物理域、状态、参数、方程和结果。
  5. 找到最接近的现有模型并沿用代码风格。

修改中

  1. 将物理契约保存在模型类中。
  2. 只在库清单中登记公开模型。
  3. 不修改集中注册表来加入单个模型。
  4. 不为了让测试通过而放宽全局校验。
  5. 不改变现有模型标识,除非任务明确要求迁移。
  6. 不把前端拖拽方向当作物理流向。
  7. 不把求解器失败简单隐藏为默认结果。

修改后

  1. 展示涉及的模型、清单和测试文件。
  2. 报告版本变化和兼容性影响。
  3. 运行针对性测试和必要的前端构建;共享机制修改运行相应完整后端回归。
  4. 检查 GET /api/components/catalog 中的模型、分类、端口和参数。
  5. 告知用户需要重启 FastAPI 才能加载新的 Python 模块。
  6. 未执行的校验必须明确说明原因。

19. 常见失败与处理

现象 常见原因 处理
FastAPI 启动时报模型缺少声明 字段继承自父类或漏写 在公开模型类中显式声明
模型未出现在前端 未加入 library.py 或后端未重启 检查清单并重启 FastAPI
前端显示红色“加载失败” /api/components/catalog 不可用或目录合同无效 悬停状态查看详情,再检查 8000 端口和接口响应
显示端口校验失败 DISPLAY.ports 与 PORTS 不一致 使用相同端口名和完整集合
单位校验失败 quantity 与 SI 单位不匹配 使用受控单位表或先扩展规范
默认模型无法注册 默认参数越界或构造函数未保存参数 修复默认值和 set_parameter_values()
XML 报不支持模型 XML type 与 MODEL_TYPE 不一致 修正类型或提供迁移
模型可显示但无法仿真 只完成目录元数据,方程或物理域求解未实现 补齐方程、网络和求解测试

20. 完成定义

一个模型只有同时满足以下条件才算完成:

  • 模型契约完整且启动校验通过。
  • 默认参数和边界有效。
  • 端口、参数和结果具有稳定物理含义。
  • 方程覆盖正常、边界与适用的反向流动/事件,并有独立参考。
  • 模型已加入正确库清单。
  • 目录接口能自动输出模型。
  • 前端无需复制参数和端口定义即可使用。
  • XML 能映射到正确模型。
  • 最小系统能够编译;声称可仿真的模型必须产生有限结果。
  • 相应分层测试及必要的构建/回归通过,浏览器能实际运行完整接线案例。
  • Windows/Linux 的验证状态明确,尚未实测的平台不能标记为通过。
  • 文档记录了模型假设、适用范围和已知限制。