旧版前端工程文件导入时版本对比查验、审阅与仿真时部分阻挡功能实现;前端参数输入格式统一规范
This commit is contained in:
1 parent
22579e51c9
commit
44b6ea74ab
32 files changed
+2087
-322
No files matched your search
@@ -0,0 +1,165 @@
|
||||
# 新组件注册示例与验证记录
|
||||
|
||||
文档版本:1.0.0;修订日期:2026-09-12;代码基线:`22579e5`。
|
||||
|
||||
本文由原 `app/simulation/components/example.md` 迁入并重写,配合[注册流程](component-registration-workflow-v1.md)、[建模规范](component-model-authoring-spec-v1.md)和[库读取规范](component-library-spec-v1.md)使用。示例在隔离源码副本中实际执行,正式组件库不增加演练型号。它验证当前接入流程,不是待发布的新物理模型。
|
||||
|
||||
## 1. 示例合同
|
||||
|
||||
新建第三个库 `registration_demo`、分类 `signals`、型号 `registration_demo_ramp`,类名 `DemoRamp`,模型版本 `1.0.0`。复用图形键 `amesim_step0`,增加 C 模块 `demo_signal`;图形键不决定数值行为。
|
||||
|
||||
公式为:
|
||||
|
||||
```text
|
||||
y(t) = offset + amplitude × t / duration
|
||||
```
|
||||
|
||||
| 参数 | SI / 默认值 | 约束 |
|
||||
| --- | --- | --- |
|
||||
| `offset` | 无量纲 / 2 | 有限值 |
|
||||
| `amplitude` | 无量纲 / 3 | 有限值 |
|
||||
| `duration` | s / 1 | 有限且严格大于零 |
|
||||
|
||||
唯一端口 `out` 是信号输出,显示在右侧。组件输出 `y` 与端口输出 `out.signal` 相同。模型无积分状态、无事件、无气动参考口。Python 类显式声明 `MODEL_TYPE/MODEL_VERSION/PORTS/PARAMETERS/RESULT_VARIABLES/DISPLAY/create`;构造函数保存参数并注册端口。完整可执行类及各处接入代码保存在[后端演练脚本](../../tests/manual/rehearse_component_registration.py),不再维护另一份易过期的代码副本。
|
||||
|
||||
C 函数是:
|
||||
|
||||
```c
|
||||
#include "kernels.h"
|
||||
double native_demo_ramp(double t, double offset, double amplitude, double duration) {
|
||||
return offset + amplitude * t / duration;
|
||||
}
|
||||
```
|
||||
|
||||
`duration > 0` 由组件参数合同检查。本演练用已校验的参数生成 C 常量,不能据此认为任意外部输入都已校验,或任意有限幅值不会溢出;它是受限输入的接入示例。
|
||||
|
||||
## 2. 分阶段注册:有意遗漏与实际失败
|
||||
|
||||
每阶段使用新 Python 进程,避免已导入模块掩盖发现入口变化。脚本在对应失败处断言错误原因,最终阶段要求成功。
|
||||
|
||||
| 阶段 | 已完成的步骤 | 实际结果 / 规范含义 |
|
||||
| --- | --- | --- |
|
||||
| `unlisted` | 新类和库文件存在,未启用库 | 注册表没有新型号;目录扫描不会自动注册 |
|
||||
| `catalog_only` | 启用新库与清单 | 目录、参数和 XML 校验通过;原生生成报 `no native contract` |
|
||||
| `native_discovery_only` | 将新库加入 `extended.catalog_contracts()` | 原生版本与模型合同不匹配;还需 `SUPPORTED_VERSIONS` |
|
||||
| `contract_only` | 补支持版本 | 报 `Native output mapping incomplete`,缺少 `ramp_1.y` 和 `ramp_1.out.signal`;版本白名单不会实现方程 |
|
||||
| `lowered_without_module_export` | 扩展生成器输出分支、C 函数和公共头文件 | 链接报 `undefined reference to native_demo_ramp`;模块未纳入按需导出 |
|
||||
| `complete` | 补 `modules.py::EXPORTS`、诊断聚合包含清单、经核对的函数识别 | 构建与 RK45/BDF 运行通过 |
|
||||
|
||||
实际修改仅发生在生成的 `sandbox/`:新库的四个 Python 文件、`registry.py`、`extended.py`、`contracts.py`、`modules.py`、`jacobian.py`、`kernels.h`、新 C 模块及诊断聚合入口。生产源码没有新增该类型。
|
||||
|
||||
该函数只读取时间和参数,没有状态依赖。将其纳入受控函数识别集不等于验证了任意多输出函数、投影或新动态模型的雅可比结构;这些仍按专项规范审查。
|
||||
|
||||
## 3. 浏览器导入过程中发现的额外边界
|
||||
|
||||
| 初次尝试 | 实际行为 | 已采用的处理与规范修订 |
|
||||
| --- | --- | --- |
|
||||
| 把目录 `ports` 原样写入工程 | 信号端口带 `positiveFlowDirection: null`,浏览器拒绝;后端仍可转出有效 XML | 工程快照按前端结构规范化,信号端口省略该字段;保留错误导入检查 |
|
||||
| 连线只写端点 | 缺 `data.isContactEdge`,浏览器拒绝 | 普通连线显式保存 `data: {"isContactEdge": false}` |
|
||||
| 尝试把时长从 s 切到 ms | 当前只有 s 选项 | 验证已有 SI 参数编辑;不把新增单位描述成目录自动支持 |
|
||||
| 使用未接线的独立信号源点击运行 | 后端是未接端口警告,前端检查为错误并阻止仿真 | 网页改用完整接线网络;区分单元件后端测试与网页系统测试 |
|
||||
|
||||
合法信号端口快照示例:
|
||||
|
||||
```json
|
||||
{"name":"out","kind":"signal","domain":"signal","nominalRole":"output","side":"right"}
|
||||
```
|
||||
|
||||
网页案例使用四个元件、三条连接:
|
||||
|
||||
```text
|
||||
ramp_1.out -> force_1.res
|
||||
force_1.port_2 -- mass_1.port_2
|
||||
mass_1.port_1 -- zero_1.port_1
|
||||
```
|
||||
|
||||
`force_1` 使用 FORC 的正向信号转力,`mass_1` 使用 MECMAS21(质量 10 kg、零初始位移/速度、禁用摩擦和限位),`zero_1` 是 F000。网页把 `duration` 从 1 s 改为 2 s,因此 `F(t)=2+1.5t` N,质量块的独立解析参考为:
|
||||
|
||||
```text
|
||||
v(t) = 0.2t + 0.075t²
|
||||
x(t) = 0.1t² + 0.025t³
|
||||
```
|
||||
|
||||
## 4. 本版规范的逐项校正
|
||||
|
||||
| 旧规范不匹配之处 | 本版处理 |
|
||||
| --- | --- |
|
||||
| 仅描述 experimental,仍计划未来建立正式库 | 核对当前 experimental/amesim 两库;临时隐藏由库 ID 决定 |
|
||||
| “加入 library 就完成注册/无需其他修改” | 明确元数据发现与原生发现、版本、方程和模块链接四个独立检查点 |
|
||||
| C 公式仍要求放 `kernels.c` | 改为 `modules/*.c`、`kernels.h` 和模块导出/依赖;聚合文件仅用于诊断 |
|
||||
| 启动校验要求 Python `component_result_values()` | 删除过期要求,改为元数据校验、C 输出映射及 EXE 输出的分层检查 |
|
||||
| Python 状态声明容易被理解为自动得到 C 状态 | 明确索引、初值、导数和结果由具体生成路径实现 |
|
||||
| 前端新增能力仅需图标 | 补齐动态端口、新编辑器、新物理量/单位、介质和连线规则的条件修改范围 |
|
||||
| 目录、工程和 XML 合同被混用 | 补信号端口 null、连线 data 字段、SI 参数、完整参数、网页必接端口要求 |
|
||||
| 无原生模块缓存、雅可比、新状态尺度要求 | 新增导出/依赖、缓存失效、状态依赖和容差量纲检查项 |
|
||||
| “不支持迁移”的表述过于绝对 | 区分 XML 精确版本、前端型号专用处理和未实现的通用迁移框架 |
|
||||
| 未区分跨平台适配与实际验收 | 分别记录 Linux/Windows 状态,新 C/构建/缓存能力同样适用 |
|
||||
|
||||
修改发生在现行规范正文,不只在本表列出待办。文件分工和迁移位置见[规范索引](README.md)。
|
||||
|
||||
## 5. 验证结果与范围
|
||||
|
||||
最终可复现记录放在本地 `test/component-registration-20260912-verified/`,该目录被 Git 忽略。
|
||||
|
||||
| 验证 | 结果与边界 |
|
||||
| --- | --- |
|
||||
| 六阶段发现、版本、输出、链接检查 | 全部符合阶段预期,最终构建成功 |
|
||||
| 后端独立元件,RK45 与 BDF | 0~1 s,0.1 s 采样,各 11 点;`y` 解析误差为 0,端口输出与组件输出相同 |
|
||||
| 重复构建 | 完整模型命中,对象编译 0 次 |
|
||||
| 参数 duration 1→2 | 模型对象重编译 1 次,其余 8 个对象复用,最终输出 3.5 |
|
||||
| 失败输入 | 错误 modelVersion、零 duration、XML 缺 duration 均被拒绝 |
|
||||
| 浏览器 | 真实 Chromium、真实目录/API/C 程序;发现、拖入、错误 JSON 拒绝、完整工程导入、参数编辑、JSON/XML 导出、两次 BDF、曲线显示、结果文件/CSV、刷新恢复 |
|
||||
| 网页解析对照 | 信号与输出力逐点误差 < 1e-12;质量块最大位移差 `1.26236e-11 m`、速度差 `2.36616e-13 m/s`(门槛分别为 1e-7) |
|
||||
| 网页缓存与保存 | 第二次运行完整模型缓存命中;CSV 中新元件两列符合解析值;刷新恢复与保存结果完全一致 |
|
||||
| 生产目录回归 | 注册、目录、元数据共 23 项测试通过;生产仍为 27 类,原生版本一致,演练类型未进入生产库 |
|
||||
| Windows | 未实际执行;本机无 Windows 运行环境,不宣称双平台验收完成 |
|
||||
|
||||
第一轮缺导出的链接失败已生成部分共享对象,因此 `firstCompleteBuild` 不是全空缓存耗时;本演练不作性能优化结论。目录结构、失败阶段、函数接入在 Linux 得到实证,Windows 仍需用现有工具链执行复现与对应回归。
|
||||
|
||||
本案例不覆盖新物理域、动态端口、新编辑器、非平凡的雅可比着色、新非线性环或气动固定参考口,也不代表完成了 Amesim 等价性验证。此次修改仅为规范和演练工具,未修改共享求解行为,因此没有再次运行八路性能基准。
|
||||
|
||||
主要证据文件:`summary.json`、各阶段 `*.json/*.log`、`input.xml`、`project.json`(后端独立案例)、`browser-project.json`(网页完整网络)、`browser/summary.json`、网页导出与截图。探索中的失败记录在旁边的 `test/component-registration-20260912/` 和 `test/component-registration-20260912-final/`;最终结论以 `-verified` 目录为准。
|
||||
|
||||
## 6. 复现方法
|
||||
|
||||
前提:仓库 Python 依赖、现有 C/SUNDIALS 工具链和前端依赖可用。前端源代码变化后先在 `frontend/` 执行 `npm run build`,演练会复制现有 `frontend/dist/`。环境、工具链和浏览器不随 Git 提交。
|
||||
|
||||
Linux,从仓库根目录生成全新目录(已存在会拒绝覆盖):
|
||||
|
||||
```bash
|
||||
.venv/bin/python tests/manual/rehearse_component_registration.py --output-dir test/registration-replay
|
||||
```
|
||||
|
||||
另开终端启动隔离后端,使用同一 Python 环境:
|
||||
|
||||
```bash
|
||||
registration_repo="$PWD"
|
||||
cd test/registration-replay/sandbox
|
||||
"$registration_repo/.venv/bin/python" -m uvicorn app.main:app --host 127.0.0.1 --port 8036
|
||||
```
|
||||
|
||||
回到仓库根目录运行浏览器脚本:
|
||||
|
||||
```bash
|
||||
node tests/manual/browser_component_registration.mjs test/registration-replay/browser-project.json test/registration-replay/browser http://127.0.0.1:8036
|
||||
```
|
||||
|
||||
本机采用 `.tools/node-v24.18.0-linux-x64/bin/node`。若使用此前补充的浏览器动态库,在命令前设置:
|
||||
|
||||
```bash
|
||||
export LD_LIBRARY_PATH="$PWD/.venv/native/browser-libs/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
||||
```
|
||||
|
||||
Windows PowerShell 对应入口(须先配置现有 Windows C/SUNDIALS 工具链及 Playwright 浏览器,以下不是已通过记录):
|
||||
|
||||
```powershell
|
||||
$registrationRepo = (Get-Location).Path
|
||||
$registrationPython = Join-Path $registrationRepo '.venv-win\Scripts\python.exe'
|
||||
& $registrationPython tests/manual/rehearse_component_registration.py --output-dir test/registration-replay-win
|
||||
Set-Location test/registration-replay-win/sandbox
|
||||
& $registrationPython -m uvicorn app.main:app --host 127.0.0.1 --port 8036
|
||||
```
|
||||
|
||||
在另一个 PowerShell 终端回到仓库,运行同一 `.mjs` 脚本,输入换成 `test/registration-replay-win/browser-project.json`,Node 使用本机 Windows 路径。浏览器与 Python 均使用原平台环境,不复制 Linux 动态库。
|
||||
|
||||
完成后在启动 uvicorn 的终端按 `Ctrl+C`。演练使用临时端口 8036;本次未启动用户已停止的 5173/8000。删除生成目录即可清理演练源码、结果与缓存;生产组件及现行规范不依赖这些生成物。
|
||||
Reference in new issue
Block a user