# 新组件注册流程与交付规范 文档版本:1.1.0 修订日期:2026-09-12 核对代码基线:`22579e5`(缓存功能 Windows 平台适配)。本文是新增网页建模与原生仿真组件的总流程;专项字段规则见[规范索引](README.md),执行证据见[注册示例与验证](component-registration-example-v1.md)。文档版本独立于模型和协议版本。 本版通过隔离源码中的斜坡信号源注册演练校正现有规范。演练组件和编译缓存不加入正式组件库;可复现脚本保留在 `tests/manual/`。 ## 1. 当前架构与完成边界 当前有两条接入链路。元数据注册控制组件发现和编辑;原生支持控制能否生成并执行数值模型。注册类不会自动获得 C 求解能力。 ```mermaid flowchart TD A[组件物理定义与 Python 声明] --> B[library.py 与注册校验] B --> C[组件目录 API] C --> D[前端组件库、参数面板和端口] D --> E[工程 JSON 与执行 XML] E --> F[校验并构造网络] B --> F F --> G[C 支持合同与系统代码生成] H[公共 C 数值模块] --> I[按需编译、缓存和链接] G --> I I --> J[独立 C 程序积分与输出] J --> K[网页结果、保存和 CSV] ``` 源码依据: - [注册中心](../../app/simulation/registry.py):`ENABLED_COMPONENT_LIBRARIES` → `library.py` → `validate_component_model_class()` / `create()` → 注册表。 - [目录 API 与网络构造](../../app/main.py):`/api/components/catalog`、`compile_system_xml_network()`、`_compile_solver_network()`。 - [原生入口](../../app/simulation/native_codegen/compiler.py):`compile_native_program()` 检查类型和版本,再选择紧凑路径或扩展路径。 - [扩展生成器](../../app/simulation/native_codegen/extended.py):按具体模型实现状态、方程与输出映射。 - [前端工作台](../../frontend/src/App.tsx):`normalizeComponentCatalog()`、工程读写及通用参数处理。 本次直接加载注册目录核对:`experimental` 5 类、`amesim` 22 类,共 27 类;原生版本表与注册版本一致。这是当前快照,不应成为未来新增组件后的固定数量要求。 以下标识不可混为一谈: | 标识 | 作用 | 示例 | | --- | --- | --- | | `library.id` | 发布和发现边界 | `amesim` | | `category.id` | 前端组件面板分组 | `flow` | | `MODEL_TYPE` | 工程/XML/原生支持的模型类型 | `amesim_pnor001` | | `DISPLAY.symbol` | 前端图形渲染键 | 可以与 MODEL_TYPE 相同,也可以复用已有图形 | | C 功能模块 | 数值代码组织及对象缓存粒度 | `orifice`、`pipe` | 界面分类与 C 功能模块没有自动的一一映射。不同型号可以调用同一个公共 C 函数;同一型号也可以依赖多个模块。 ## 2. 新增组件的实际步骤 ### 第一步:确定物理合同和接入范围(必做) 先整理模型依据、适用介质/物理域、计算公式、符号约定、有效范围和未支持能力。明确它是无状态代数组件、动态组件,还是编译期介质定义。若是新增物理域或新种类的介质,须单独评估网络、XML、前端连线、物性和原生生成支持,不能只新增一个 `domain` 或类型字符串。 建议首先形成四张表: - 参数:机器名、物理意义、SI 单位、默认值、范围、枚举、显示条件和是否影响端口/状态数量。 - 端口:稳定名称、物理域、连接类型、各变量含义、正方向、供需关系、参考来源及是否必须连接。 - 状态:名称、含义、单位、初值公式、导数公式、允许范围、绝对误差尺度及相关事件。 - 输出:稳定名称、含义、单位、显示名称、计算公式和所属组件/端口。 ### 第二步:编写 Python 组件声明(必做) 文件放在 `app/simulation/components///`,参照同类模型。现有代码存在一个文件容纳多个相关型号的情况;“每模型单文件”是整理建议,不是注册器的硬性要求。 公开模型类必须在自己的类体显式声明: ```python MODEL_TYPE MODEL_VERSION PORTS PARAMETERS RESULT_VARIABLES DISPLAY @classmethod def create(cls, *, name, medium, parameters): ... ``` 这七项由 [registry.py](../../app/simulation/registry.py) 检查,不能只从父类隐式继承。可以显式引用已有声明,例如 `RESULT_VARIABLES = Parent.RESULT_VARIABLES`。 构造过程调用 `set_parameter_values()` 保存完整规范化参数,使用 `register_declared_port()` 注册声明的端口,并保存介质和常量。参数合法性包括单字段范围和跨参数约束;默认参数必须能够创建描述对象。公共创建入口填充缺省值后还会核对实例类型、端口和参数是否与声明一致。 Python 可以做参数验证和常量几何换算;运行时物性、流量、力和状态导数由 C 计算。`EQUATIONS` / `equation_definitions()` 是结构化约束声明,不会被自动翻译成完整 C 数值方程。仅设置 `DynamicComponent.state_size` 也不会自动分配原生积分状态。 ### 第三步:落实端口语义(必做,静态与数值两侧一致) `PORTS` 是物理接口来源,`DISPLAY.ports` 是显示布局,两者的名称集合必须一致。当前显示端口基础声明支持 `left/right`,旋转和镜像由前端处理,不能直接写未经实现的显示边。 气动端口需要区分: - 名义入口/出口及实际正反流。 - 哪些量由本端提供,哪些量由对端提供。 - 是否是固定供需的参考口或支路口;`reference_port` 指向哪个真实参考来源。 使用 [port_computation.py](../../app/simulation/core/port_computation.py) 的既有合同或声明准确的新合同。参考关系不会随流向反转而自动改变;不能从图标左右位置推断物理参考口。端口流量遵守现有“流入组件为正”的合同。 参数决定端口启停时,同时实现类级和实例级有效端口查询,并核对必须连接的端口。前端目前对 LMECHN1 的动态端口还有专门逻辑,尚无统一的参数化端口目录协议;新动态端口模型要明确补齐前端规则及变更参数后旧连线的处理。 ### 第四步:加入受控组件清单(必做) 在所属库 `library.py` 的 `models` 中加入 `完整模块路径:类名`。如新增界面分类,同步该库 `categories` 和 `DISPLAY.category_id`。不要直接修改运行时 `COMPONENT_MODEL_REGISTRY`,也不要扫描目录执行任意 Python 文件。 新库需增加 `ComponentLibrarySpec`,并加入 `registry.py` 的 `ENABLED_COMPONENT_LIBRARIES`。另外,当前 `extended.py::catalog_contracts()` 仍显式读取 `amesim` 和 `experimental` 两个库,**新增第三个库还必须扩展这一原生发现入口**。 前端当前按库 ID 隐藏 `experimental`。加入实验库的模型可以被后端发现,但不会出现在左侧公开组件列表;`temporary` 标记不是现有隐藏规则。 ### 第五步:实现或复用 C 数值内核(数值接入必做,新增 C 文件按需) 先判断现有公共函数是否已经满足方程。如果只需已有内核加不同参数或组合,可以复用,避免按元件实例复制内核。 新增函数应放在 `native/components/modules/` 的合适模块,公共接口在 [kernels.h](../../native/include/kernels.h) 声明;新增独立模块时再建立新的 `.c`。当前五模块为物性、孔口、管路、机械和信号。 按需构建由 [modules.py](../../app/simulation/native_codegen/modules.py) 的 `EXPORTS` 和 `DEPENDENCIES` 决定。增加新导出函数或模块依赖时应同步这里;只在头文件写声明不会保证模块进入链接。新模块如需参与聚合诊断,还要加入 `native/components/kernels.c` 的包含清单。 `kernels.c` 现在是诊断聚合入口,生产构建不直接编译它;不能同时链接聚合入口与各模块,否则产生重复定义。 内核应说明非法状态、非有限值及迭代失败的处理。新气动计算优先传递现有 `NativePropertyCache` 上下文;试算不能污染已接受状态,也不能把跨状态的旧物性无条件复用。沿用 C11、严格浮点和已有 Windows/Linux 构建约定。 ### 第六步:接入系统代码生成、依赖和数值精度(必做) 在 `native_codegen/extended.py` 接入该具体型号的: 1. 有效端口、连接组及介质选择。 2. 状态编号、初值、必要的状态约束/投影。 3. 代数关系、流量、焓和力计算。 4. 状态导数及全部可见输出赋值。 5. 分段信号、限位或其他事件(适用时)。 目前这些逻辑包含具体类型集合与分支,例如 `GAS_TYPES`、`NODES`、`RESISTORS`;简单地把新型号塞进某个集合,不能保证后续分支正确处理它。 计算输入/输出通过 `Computation` / `EvaluationSchedule` 接入 [求值排序](../../app/simulation/native_codegen/schedule.py)。多输出函数要准确声明读取量和写出量;参考值复制与依赖流量的混合计算应分开;正流、逆流、零流量和各离散模式的依赖均需覆盖。新增不被当前局部求解器支持的非线性环,要实现对应求解或明确拒绝。 还需核对 [雅可比结构](../../app/simulation/native_codegen/jacobian.py) 的状态依赖。新的多输出调用、投影和分支不能遗漏依赖;无法证明时允许使用保守逐列差分,不能为保持着色而把未知依赖当作常量。适用时给生成的 `model`/`model.exe` 传入 `--verify-jacobian` 核对;Python 包装 CLI 没有同名选项。 新增状态量需要检查 [绝对误差尺度](../../app/simulation/native_codegen/tolerances.py)。当前按状态字段名区分质量、位移/速度,其余默认 `1e-8`;新物理量不能未经量纲评估直接套默认值。 `compiler.py` 保留紧凑生成路径,但新型号不一定需要同步实现第二套路径。正确做法是确认它被路由到已支持的生成路径;只有纳入紧凑路径或改变两路径共享行为时,才同步实现并做路径对照。不要只扩充 `_STORAGE_ANCHORED_TYPES` 却漏掉对应计算。 实现并验证后,将 `MODEL_TYPE: MODEL_VERSION` 加入 [contracts.py](../../app/simulation/native_codegen/contracts.py)。这是支持承诺,不能用加入白名单代替真正的数值实现。 ### 第七步:核对前端图形与交互(必查,代码修改按需) 对普通固定端口、现有编辑器和现有单位的模型,组件库列表、参数名称/默认值/边界/枚举/显隐条件通过目录自动生成。通常不用在 `App.tsx` 再添加一份型号参数表或新建仿真 API。 需要新图形时,在 `frontend/src/componentSymbols/` 实现渲染,并加入 [ComponentSymbol.tsx](../../frontend/src/ComponentSymbol.tsx) 的 `symbolRegistry`。完整图形定义包含 `viewBox`、图标尺寸、节点占地、端口锚点;按参数变化的图形还需相应布局函数。没有专用图形时当前有通用边框回退,但它不代表专用图形已经验收。 以下情况需额外前端工作: | 新能力 | 需要核对的入口 | | --- | --- | | 新图形/锚点 | `componentSymbols/*`、`ComponentSymbol.tsx` | | 新参数编辑器 | `core/metadata.py` / 注册校验、目录解析、`ParameterTable.tsx` / `App.tsx` | | 新单位或物理量的单位切换 | 后端 `SI_UNIT_BY_QUANTITY`、共享参数 `schemas/parameter-units.json`、结果 `RESULT_UNIT_OPTIONS`;三入口回归 | | 动态端口 | 后端有效端口接口、前端端口显示/连线处理和参数变更逻辑 | | 新物理域/连接规则 | `core/ports.py`、网络/XML 校验、前端连线检查及 C 生成 | | 特殊介质定义/引用 | XML/前端的目录角色、网络识别的介质定义基类、介质注册与引用选择逻辑 | 浏览器检查应覆盖端口号、实际连线端点、旋转/镜像、参数改变后的布局及导入导出。图形变了不能偷偷改变物理端口名称或参考关系。 ### 第八步:核对工程文件、版本和输出(必做) 普通已有协议下的模型通过注册表即可被通用 XML 流程识别,通常不需要修改 XSD 或添加型号专用 API。 - XML 要求精确匹配 `modelVersion`,参数集合完整且没有未知字段;Python 工厂可填默认值不等于 XML 可以任意缺参数。 - 外部工程 JSON v2 的数值和表达式统一按所选单位解释,网页/HTTP/CLI 预处理后才进入 SI 数值边界。旧 v1 数值不能重复换算。组件版本差异提示后允许执行;型号、端口、参数错误继续拒绝。导出时只对通过校验的节点升级版本,按[输入合同](backend-interface-version-spec-v1.md#61-工程存储与执行入口)验收旧文件和重新导出的文件。 - 采用实际浏览器导出的工程结构,不直接复制目录对象。例如信号端口快照须省略 `positiveFlowDirection: null`;连线须保存 `data.isContactEdge` 布尔字段;后端转 XML 成功不能代替浏览器导入检查,见[目录与快照差异](component-library-spec-v1.md#143-目录对象与工程快照不是同一协议)。 - 网页当前要求所有显示端口恰好连接一次。后端单元件算例的未接端口警告不能替代网页完整网络验收。 - 发布后保持模型/端口/参数/结果机器名稳定。提高版本可能使旧 XML 被拒绝;当前没有通用自动迁移框架,前端仅存在部分特定型号迁移逻辑。 - `RESULT_VARIABLES` 中可见项与活动端口的可见变量必须在实际 C 输出中全部赋值,结果键/单位应与网页、缓存恢复、CSV 一致。 ### 第九步:分层测试和双平台验收(必做,按物理适用性选择案例) | 层次 | 最少核验内容 | 现有入口示例 | | --- | --- | --- | | 声明与注册 | 全局类型唯一、版本、默认可创建、非法/边界参数、端口/显示/结果一致 | `test_component_registry`、`test_component_catalog`、`test_component_metadata` | | 接口与文件 | 正确连接、缺口/错误参考被拒绝、JSON/XML 往返、版本不兼容 | `test_port_computation`、`test_system_xml_v3`、型号专项 | | 元件数值 | 独立公式或可信参考、正常/零值/边界/逆向、守恒和明确失败 | 型号 C 专项、`--init` / `--probe` | | 系统求解 | 包含新元件的最小闭合网络,RK45/BDF(适用时),事件、顺序打乱与输出完整 | `test_native_codegen`、`test_native_schedule`、`test_native_catalog` | | 雅可比 | 状态依赖覆盖、模式切换、必要的完整矩阵核对 | `test_native_jacobian_structure`、`test_native_jacobian_runtime` | | 编译与缓存 | 空缓存构建、完整命中、参数/模块变化后正确失效、缺失模块链接失败能被发现 | `test_native_build_cache`、`test_native_cache_platform` | | 浏览器 | 发现/拖入/编辑/连线/旋转镜像、运行、结果可查看、IndexedDB 保存、下载/CSV/刷新恢复分别核查 | `frontend/tests/e2e/` 的相关测试 | | 双平台 | Windows 与 Linux 实际构建和运行;Windows `.exe` / DLL / 路径 / 文件系统能力 | `native-windows` CI、跨平台集成测试 | 新增模型要有自己的可执行案例,不能只改变“现有 27 类”的数量断言。已有测试包含固定类型清单/数量,新增后需合理更新覆盖期望,并证明新型号确实执行。 数值参考来自独立解析结果、可信外部结果或经过审查的冻结基准;不能从待验实现自动生成“预期值”来证明自身正确。保留原有参考,不直接覆盖历史基线掩盖差异。 对共享内核/求解器的修改,沿用修正八路作为系统回归与性能案例;新元件自身仍需最小闭合案例。只有八路无法运行且短期无解,才退回四路。性能对照分别记录构建、求解、结果处理与网页可查看/保存;无可信 Amesim 曲线或耗时则明确跳过相应对比。 Windows 验收遵循 [跨平台交付约定](跨平台交付约定.md)。模拟测试与代码适配不能代称 Windows 实机运行通过。 ## 3. 常见修改范围 | 文件/区域 | 新增普通型号时是否必改 | | --- | --- | | 所属组件库中的 Python 声明 | 必改 | | 所属库 `library.py` | 必改 | | `native_codegen/extended.py` 或已确定的生成适配入口 | 必须接入;当前通常需修改 | | `native_codegen/contracts.py` | 必改 | | `native/components/modules/*.c` / `kernels.h` | 新数值函数才改;已有内核可复用 | | `native_codegen/modules.py` | 新导出函数或新模块依赖时改 | | `native_codegen/compiler.py` 紧凑路径 | 新型号纳入该路径或共享行为受影响时改 | | `schedule.py` / `jacobian.py` / `tolerances.py` | 核对生成器接入;现有机制不足、新函数依赖或新状态尺度需要时改 | | 前端图形注册与渲染 | 需要专用图形或布局时改 | | `App.tsx` / `ParameterTable.tsx` | 动态端口、新编辑器、新单位等现有元数据能力不足时改 | | `app/main.py` / `app/system_xml.py` / XSD | 普通型号通常不改;新协议/物理域/介质机制时改 | | 注册、型号数值、系统和浏览器测试 | 增加相应案例并更新受影响的覆盖期望 | ## 4. 组件接入交付资料 每个拟交付的新型号提供“组件接入说明”,按适用性填写以下栏目;未涉及的能力写明不适用: 1. **身份与版本**:类型、类路径、所属库/分类、模型版本、图形键、关联已有型号及兼容性处理。 2. **物理依据**:参考来源、完整方程、假设、适用范围、未支持功能。 3. **参数表**:SI 值、默认值、边界、枚举、条件显示、几何常量预处理。 4. **端口表与标号图**:变量、正方向、供需、参考口、动态启停和必接要求。 5. **状态/事件/结果表**:初值、导数、误差尺度、事件行为、输出键和单位。 6. **原生接入表**:C 函数、所属模块、依赖、生成路径、计算顺序、雅可比依赖与缓存失效范围。 7. **前端/文件合同**:图形及锚点、单位和编辑器、JSON/XML 示例、旧工程处理。 8. **验证记录**:最小算例、独立参考来源、误差门槛、失败路径、Windows/Linux 实际结果和网页验证;性能数据按阶段区分。 验证记录区分三个完成状态: - **已注册**:目录/工厂/XML 类型与参数校验通过。 - **可求解**:原生构建、独立数值对照、闭合网络运行和输出检查通过。 - **可交付**:浏览器交互/文件往返/保存及 Windows/Linux 验证通过,兼容性和资料齐全。 这些是文档中的验收状态,当前目录 API 尚未提供对应的统一字段;不要向工程 JSON 添加未实现的状态协议。 ## 5. 本版修订与维护 本版已在专项规范中修正:旧 C 文件入口、移除的 Python 结果接口、新库的两条发现入口、原生版本与方程的独立接入、前端条件能力、目录与工程快照差异、网页完整接线要求、精确版本和专用迁移的边界,以及模块缓存、雅可比依赖和 Windows 验证要求。 具体逐项对照、失败阶段和最终测试结果见[注册示例与验证](component-registration-example-v1.md)。后续代码架构变更时更新对应专项规范及本流程;不在文档中维护第二份可执行型号参数表。