Replace Python numerical kernels with native C execution

This commit is contained in:
ljz committed 2026-09-10 01:12:18 +08:00
1 parent 48da6be21c
commit 3b38f73fe0
227 files changed
+16801 -75499

No files matched your search

@@ -0,0 +1,66 @@
# C 内核第一版实施计划与记录
> 本文记录迁移当时的阶段结果;Python 参考实现已于 2026-09-10 退役,当前入口与保留范围见 [退役记录](Python数值实现退役记录.md)。
2026-09-09。状态:第一版已完成并验证;尚未将全组件库切换为原生默认后端。
## 分步计划
| 顺序 | 工作 | 第一版交付 | 状态 |
| --- | --- | --- | --- |
| 1 | 冻结边界与模型合同 | skill-test 的组件能力表、输入与运行设置、共同 XML 前端 | 已完成 |
| 2 | 开发 C 组件内核与模型编译器 | 由 XML 拓扑生成状态、端口、计算顺序及系统 C 源码;不依赖固定组件编号 | 已完成 |
| 3 | 接入原生积分执行 | 独立 EXE,RK45 与 CVODE BDF;进度、取消、错误、结果和编译缓存 | 已完成 |
| 4 | 接入 Python 并精简重复代码 | 统一后端分派;保留模型定义、有效的 Python 参考与兼容路径,移除被替代的重复入口逻辑 | 已完成 |
| 5 | 验证第一版 | 同状态 Python/C 方程对照、拓扑通用性、API 回归、skill-test 完整求解与计时 | 已完成 |
## 本版范围
- 首批覆盖 skill-test 使用的 12 类组件:氦气介质、PNCH023、PNCH012、PNVO001、PNPL01、STEP0、UD00、FORC、PNRP17、MECMAS21、F000、LSTP00A。具体支持的参数模式由编译器检查,不将组件类型覆盖误报为所有模式覆盖。
- Python 负责 XML 校验、网络检查、代码生成、编译缓存与任务管理;生成程序中的物性、流量、机械、积分与事件处理不回调 Python。
- 用户要求本轮不调整雅可比:现有 Python 雅可比、着色与切向代码保持不变;原生 BDF 使用本机 SUNDIALS 7.4.0 默认稠密数值雅可比,不添加自定义雅可比或矩阵优化。
- `test/skill-test.json` 是前次 RK45 / maxStep=0.001 s 测试副本;下载原件是 BDF / maxStep=0.02 s。本轮分别标注两组设置,不混用时间;仿真均为 0–10 s,仅数值验证,无绘图。
- C 组件从现有 Python 方程及已验证的 C 原型迁移,核对单位、符号、事件和模式;不直接复制原型中的固定模型连接或编号。
- 本版能力以显式后端开关启用。不支持的模型在积分开始前给出明确诊断;默认 Python 路径继续服务尚未迁移的组件。
## 后续版本
1. 扩大到管路、分支节点、更多物性和摩擦/接触模式;增加通用代数环执行。
2. 完善参数与结构分离缓存、跨平台发布和更大模型验收。
3. 用户另行授权后开展雅可比、稀疏矩阵和局部导数优化。
## 实施结果
### 代码与精简内容
- 新增 `app/simulation/native_codegen/`:JSON/XML 输入适配、能力检查、模型 C 生成、构建缓存、隔离运行与 CLI。
- 新增 `native/components/`、`native/runtime/`、`native/include/`:物性/阀流量/信号/接触/端挡原语,RK45 与 CVODE BDF,事件、采样和结果输出。
- `app/main.py` 改为共用后端分派,移除入口内重复的求解器配置与 Python 系统构造。
- 将通用结果和准备错误合同从 `generic.py` 抽到 `results.py`,C 结果适配不再为获取数据类型而导入整个 Python 求解系统;原模块保留导入兼容性。
- 活动跟踪器增加原生汇总进度接口,直接接收真实 RHS/接受步计数,避免每次 C 求值都回调 Python。
- Python 组件定义、仍在使用的示例 API 和参考求解器继续保留;没有把被其他模型调用的代码误判为无用代码删除。
- 现有 Python 雅可比、着色、切向和矩阵求解逻辑未修改。
### 验证
执行 `python -m unittest tests.test_native_codegen tests.test_generic_system_xml_simulation tests.test_system_xml_v3 -q`,33 项测试全部通过。覆盖组件方程、逆向流、端挡试探、组件重命名/重排、增加独立支路、缓存、移除 Python PATH 后独立运行 EXE、取消、XML API 和既有 Python 路径。
当前 Python 的完整 0–10 s RK45 对照已重跑;175 个变量、502 个时间点及求值次数、接受步、事件数全部与 C 对应,序列比较采用 `rtol=1e-9, atol=1e-9`。所有样本有限、系统质量守恒检查通过。
首轮通用接口测试中的毫秒级心跳用例曾出现一次 Windows 时序波动;独立复核通过,最终上述完整 33 项测试也通过。未修改生产心跳行为或放宽断言。
### skill-test 求解时间
同机、预热一次后测三次取中位数,关闭轨迹采样与绘图;初始化、编译、结果投影和文件写入不计入求解时间。
| 配置 | 最大步长 | rtol | 求解中位时间 | RHS 次数 |
| --- | --- | --- | ---: | ---: |
| 原生 RK45 | 0.001 s | 1e-6 | 0.2947735 s | 60,200 |
| 原生 CVODE BDF | 0.02 s | 1e-6 | 0.0222788 s | 3,915 |
| 原生 CVODE BDF,收紧精度检查 | 0.02 s | 1e-8 | 0.0152101 s | 3,097 |
BDF 默认设置相对更细 RK45 参考的最大压力偏差约 2.38 kPa、温度偏差 0.0863 K、位移偏差 2.04e-7 m;收紧到 `rtol=1e-8` 后分别降至约 3.09 Pa、2.83e-5 K、1.72e-8 m。本例收紧误差限同时减少了求值/拒绝步,不能据此推广“越严格越快”。
第一版尚未声称覆盖全部物理模式或与 Amesim 所有曲线一致。BDF 使用另一种积分实现,不能把它的耗时与 Python RK45 相除后归因于语言。
使用说明见 [native/README.md](../../native/README.md),完整证据见 [第一版测试报告](../../test/native-v1/report.md)。
@@ -0,0 +1,63 @@
# C 内核组件库覆盖记录
> 本文记录迁移当时的阶段结果;Python 参考实现已于 2026-09-10 退役,当前入口与保留范围见 [退役记录](Python数值实现退役记录.md)。
日期:2026-09-10。范围是当前注册表中的全部模型:Amesim 库 22 类,实验库 5 类。这里的“覆盖”指项目现有模型方程有对应的 C 实现,不代表复刻完整 Siemens 元件库,也不代表任意拓扑、任意刚性模型均能快速求解。
## 实施步骤
1. 核对注册表、模型版本、全部活动端口、状态与结果变量,建立显式 C 合同白名单。
2. 补充空气物性、阀模式、管路、节点、换热、摩擦与反弹限位的 C 公式。
3. 扩展系统 C 生成:压力分组、串联阻力闭合、焓传播、常系数力/流量约束消元、刚性质量合并、兼容管路容腔状态投影。
4. 对照 Python 的状态导数和全部结果变量,执行 RK45/BDF 事件回归及实际 JSON 测试。
四步已经落实到代码。完整运行中的超时限制单独记录,不作为通过项。
## 组件清单
| 类别 | 已覆盖模型 | 主要补充 |
| --- | --- | --- |
| 介质,2 类 | Ideal Air Medium、Helium Medium | 编译期选择空气理想气体或氦气 Peng–Robinson C 物性;包括能量反解、密度、等熵因子和黏度。 |
| 气动边界,1 类 | PNPL01 | 零流量、连接侧焓传播。 |
| 信号,2 类 | STEP0、UD00 | 跳变、分段斜坡、循环与事件分段;纯信号模型也可运行。 |
| 机械,6 类 | F000、FORC、MECMAS21、LSTP00A、LMECHN1、PNRP17 | 力/速度/位移约束、可变端口节点、刚性质量合并、活塞容积与压力力。 |
| 气腔,2 类 | PNCH023、PNCH012 | 固定/可变容积、质量与内能守恒、换热与边界功。 |
| 阀,3 类 | PNOR001、PNVO001 Fixed、PNVO001 Signal | 面积/Cv/Kv 模式、限幅开度、正反向流动、近等压平滑及诊断。 |
| 管路,4 类 | PNL00R、PNL0001、PNL0002、PNL0003 | 无储能/单容腔/双容腔、摩阻与层流过渡、换热、流动诊断、兼容容腔合并。 |
| 气动节点,2 类 | PN3NODE2、P4NODE2 | 等压与质量守恒,端口 2 温度参考、平滑能量分配。 |
| 实验组件,5 类 | Cylinder、Tank、ResistivePipe、Orifice、Tee | 储能、Darcy 阻力、孔口和混合节点。 |
模型版本逐项固定于 `app/simulation/native_codegen/contracts.py`。回归检查注册表与此表完全一致;新增模型、未移植的版本和自定义子类会明确拒绝,不会因继承了一个 Python 类就被视为已移植。
## 参数模式与物理范围
- MECMAS21:`stoptype=1/2/3/4`,塑性、柔性、反弹及无限位;黏性摩擦、库仑摩擦和风阻使用现有方程。反弹使用 `restcoeff`/`restdvel`,刚性组冲击按活动端挡的最小反弹系数处理,塑性端挡优先。
- LSTP00A:接受 `stiffmode=1/2` 和两种 `discContactOption`。当前 Python 的接触力始终使用 `kcont`、`rcont`、`Pdis`,C 保持一致。几何模式参数目前未生成另一套刚度公式。
- 当前 Python 中 MECMAS21 的 `theta`、`fstick`、`strib`、`frictionType` 等参数没有对应的额外动力学分支,C 沿用其实际行为;不能把接受这些参数解释为已增加重力斜面、静摩擦锁止或完整 Stribeck 模型。
- 管路继续沿用当前 Python 的公式:PNL0003 是 Darcy 压降反解;PNL00R/0001/0002 是已有的可压缩摩擦流及过渡拟合。未更换为另一套 Amesim 库公式。
## 系统生成与运行
Python 读取/校验 XML、创建模型对象、整理连接与常量并生成 C。质量/内能初值也在预处理阶段计算。EXE 内执行物性反解、流量/焓闭合、机械力计算、状态导数、积分、事件定位和采样,不调用 Python 方程。
保留原来针对简单储能拓扑的紧凑生成路径;新增 `extended.py` 覆盖完整目录及扩展连接。两条路径都是 C。编译器不使用 Python 数值后端作为隐式备用。
兼容的 PNL0001/PNL0003 固定容腔可直接连接:初始压力/温度需一致,同组质量与内能按体积投影,导数按体积分配。独立气腔之间的无阻力直连仍按项目既有规则拒绝;无压力锚点、欠定机械约束及无法收敛的闭合也明确报错。
积分器仍为原生 RK45、CVODE BDF;没有修改 ODE 雅可比、稀疏性或线性求解策略。C 网络中的常系数连接消元属于系统组装。扩展编译器上限为 1024 状态、16384 输出;平台仍为 Windows x64。
## 验证及重要限制
回归入口:
```powershell
.venv-win/Scripts/python.exe -m unittest tests.test_native_catalog tests.test_native_codegen tests.test_simulation_warmup -v
```
27 项回归通过,包含空气/氦气、正反向流动、阀参数模式、管路换热/光滑壁、节点、串联阻力、兼容管路容腔、机械摩擦/柔性限位、接触和信号。状态导数及输出对照容限为 `rtol=2e-8, atol=2e-7`,原 skill fixture 的更严格对照仍保留。RK45/BDF 均验证了反弹解析解和纯信号运行。另补充四个质量块刚性相连的解析校验:总质量 10 kg、外力 30 N,C 得到共享加速度 3 m/s²;该测试通过。
实际 JSON、运行日志与报告存于 `test/native-catalog/`。最终构建的 `skill-test` 完成 10 s 仿真,RK45、最大步长 0.001 s、rtol=1e-7;预热后一次求解计时为 0.322429 s,进程墙钟 0.743252 s。它是功能回归期间的单次记录,不是严格性能基准。`test-mql-8` 的 132 个状态导数、1784 个输出量在初始、信号变化及保存的瞬态状态上与 Python 对照通过。
**test-mql-8 的完整 BDF 运行未通过**:`rtol=1e-7`、最大步长 0.02 s、60 s 求解超时,推进至约 0.0153307 s;记录为受控超时,不是完成 10 s 的耗时。当前 CVODE 多次重建默认数值雅可比,属于仍需处理的完整系统求解性能问题。本次保留用户要求的雅可比策略,不用降低刚度、放宽误差或更换物理方程来掩盖它。之前固定模型的 C BDF/NDF 程序与当前通用 CVODE 是不同求解实现,其既有完成时间不能直接套用到这里。
Python 参考方程暂保留以支撑这些数值对照,且模型描述、公共配置、XML/API 与旧示例仍有依赖。组件 C 覆盖完成并不等于可以整目录删除 Python。
@@ -2,6 +2,7 @@
> 文档状态:待评审实施方案
> 建立日期:2026-09-02
> 补充日期:2026-09-09;第 10 节结合最新实测,细化 XML → 系统专用 C → 原生 EXE 路线。前九节保留原阶段方案与历史评估;本次仅补充设计,未完成生产内核替换。
> 适用分支:`model-development`
> 关联文档:[求解器性能优化任务清单](求解器性能优化任务清单.md)、[后端求解逻辑与效率优化调研](后端求解逻辑与效率优化调研.md)
> 范围:后端数值执行内核;不包含前端重写,也不主张把整个 Python 后端改写为 C
@@ -404,3 +405,137 @@ Numba 可以在完整数组 IR 后用于 1–2 周的架构验证,但不作为
6. 评审通过后,再建立最小 C ABI 和纵向切片。
第一批的退出条件不是“已经写了多少 C”,而是:当前基准可信、同一计算能被无回调 IR 完整表达、差异能定位到具体阶段和槽位。只有达到这个条件,后续 C 工作才具有可预测的收益和可控的回滚成本。
## 10. 2026-09-09 补充:XML 自动生成系统专用 C / EXE
### 10.1 新证据与本次目标
用户本次希望解析 XML 后,自动生成对应系统的 C 求解程序。建议把“模型专用代码生成 + 原生积分运行”作为目标架构;开发时仍保留“相同输入逐阶段比较”和“相同 SciPy 积分器仅替换完整 RHS/Jacobian”的诊断阶段,用来分别测量执行语言与积分算法的影响。后者是验证手段,不是最终交付边界。
最新证据不能把速度差异全部归因于 Python:
- 先前特定模型的完整 C EXE 求解仍约 44.82 s;C 剖析中模型求值占 97.07%,雅可比构造占 87.17%。雅可比包含模型求值,两项不能相加。
- 该 C 版本采用 132 状态的逐列差分,每次雅可比约需 133 次完整 RHS,累计 124,089 次。这个结论针对测试 C 实现;当前 Python 引擎已经有稀疏结构、着色和部分半解析路径,不能把它也描述成始终采用全稠密差分。
- Amesim 仅关闭 optimized solver,进程 CPU 从 2.890625 s 增至 13.890625 s,结果文件字节、函数/雅可比计数、成功步数均相同。这证明执行优化层本身很重要,但没有揭示其专有优化实现。
- C 管流中的固定次数二分及频繁未收敛退出是已知热点,不能作为成熟组件内核直接复制到生产生成器。
依据:[C 剖析报告](../../test/native-mql8-profile/performance-analysis.md)、[Amesim 优化开关对照](../../test/native-mql8-profile/amesim-optimizer-comparison.json)。这是特定模型对照,不是受控的生产 Python/C 语言收益测量,也不保证新引擎达到 Amesim 的速度。
### 10.2 最终执行边界
```text
网页导出 System XML
→ Python:协议校验、组件版本/参数/连接校验
→ ModelIR:方程/可信组件原语、连续状态、代数变量、事件、依赖
→ 结构编译:合并等价变量、确定计算顺序、划分代数环、生成稀疏结构
→ C emitter:model.c + model.h + manifest.json
→ 编译并链接:组件 C 库 + 原生积分运行库
→ 独立 native worker / 模型 EXE:完成初始化、积分、事件、数值采样
→ Python:读取结果、任务状态、现有 API 编码
```
编译和 EXE 均在后端机器执行。Python 可以继续完成低频管理工作;一次积分中的 RHS、代数闭合、物性、Jacobian、Newton 和事件处理全部留在原生进程,不能在每次求值时回调 Python。
首个交付可生成模型专用 EXE,便于独立运行、复现和隔离崩溃。之后如实测编译或启动成本成为问题,再用通用 worker 加载缓存模型 DLL;DLL 同样加载在隔离进程中。原生运行时与组件库预先编译,每个新拓扑只生成和编译模型装配部分。
### 10.3 XML 不包含完整方程,必须建立 C 组件库
现行 XML 保存组件类型、版本、参数和连接,不包含各组件的物理公式。自动编译依赖一份可信映射:
```text
(model_type, model_version, 支持的结构选项)
→ 参数校验 + 状态/端口布局 + 方程或 C kernel + 局部导数 + 事件/reset
```
`app/simulation/registry.py` 的注册定义可以继续作为编译前端的数据来源,逐个增加原生能力描述。普通公式可用受限表达式 IR 表达,同时生成数值计算和导数;复杂物性与非线性管流使用经过验证的手写 C 原语,并声明完整输入输出及导数合同。不要依赖自动翻译任意 Python 类。
例如“气室 A—管道—气室 B”编译后固定为状态和参数数组下标:求两边物性、算这根管道的流量、按端口方向累加质量/能量导数。运行时不再寻找组件对象、端口名称或连接边。系统专用代码可以直接调用 `pipe_kernel(...)`,无需把物性库和积分器源码重复展开进每一个模型。
现有 `EquationResidual` 保存变量名称及已经计算出的 `value`,并没有保存完整公式表达式;`causal_ir.py` 提供部分结构基础,但其执行绑定仍有 Python 回调。因此需要补齐完整数值 IR。当前 `app/simulation/ir/` 仅发现缓存文件,不能视为已有可维护的完整 IR 源码。
`test/native-mql8-bdf/generate_model.py` 是验证原型:仍限定特定阀动作、机械组件编号、部分参数和连接形式,并拒绝某些循环闭合。正式编译器应由拓扑和能力合同推导这些内容,不能直接把这份脚本改成 XML 读入便宣称通用。
### 10.4 编译器要提前完成的计算
| 编译工作 | 运行时收益或正确性要求 |
| --- | --- |
| 合并等压、等速度等别名变量;组装流量/力平衡 | 消除多余未知量,统一端口方向与 SI 单位 |
| 对方程和未知量做匹配,将相互依赖部分划成小块 | 能顺序计算的直接计算,仅对真正代数环迭代;无法配平时定位到组件 |
| 固定状态、代数变量、参数、工作区和输出下标 | 每次求值使用连续数组,避免字典、字符串查找和临时分配 |
| 编译 stream 图及受温度影响的物理子网 | 保留现有无环传播和局部闭合能力,避免退回每轮全网重算 |
| 计算各入口的依赖集合与所有支持模式的稀疏结构 | RHS、事件、Jacobian 和输出按需计算;求 RHS 不自动附带所有输出 |
| 提取几何常量、公共表达式和物性状态包 | 参数不变的部分只初始化一次;相同精确输入下共享结果 |
| 声明事件、离散模式、缓存失效和状态复位 | 阀门跳变、流向切换、接触不依赖碰巧足够小的积分步长 |
跨积分调用的缓存必须按输入和模式有效性管理,不能仅以时间为键;同一时间可能存在多个 Newton 试探状态或雅可比扰动。试探工作区与已接受状态分开,拒绝步与事件回退不得提交试探产生的模式或缓存。
### 10.5 积分库与代数环的选择
当前引擎在 RHS 内闭合代数变量,对外给出 ODE。第一版原生全流程建议使用 **SUNDIALS CVODE 的 BDF 模式**。CVODE 提供 C 接口、1–5 阶变阶变步长 BDF,以及稠密、带状、稀疏线性求解接口。它的 Adams/BDF 由调用方选择,不能将其描述成 Amesim/LSODA 那样自动切换两种方法。[CVODE 数学方法](https://sundials.readthedocs.io/en/latest/cvode/Mathematics_link.html)
生成器负责模型方程、结构和导数,成熟积分库负责步长/阶数、误差控制和求解器历史。不要为每份 XML 重新生成一套 BDF 算法。先锁定可复现的 SUNDIALS 版本、C 接口、构建工具和依赖;Windows 用原生 C 构建链产出 EXE,Linux 对应 ELF 程序。
稀疏矩阵可配合 KLU,但先提供正确稀疏 Jacobian,再根据模型规模比较稀疏与稠密线性代数;132 状态案例的 LU 仅占约 2.19%,只换 LU 库难以改变总体耗时。[CVODE 线性求解选择](https://sundials.readthedocs.io/en/latest/cvode/Mathematics_link.html)
如果某类代数环难以可靠消去,可另行建立 `F(t, y, ydot) = 0` 的 DAE 后端,评估 C 接口的 IDA。此时必须处理代数变量、一致初始化和系统指数;高指数约束不能直接交给 IDA 期待自动解决。[IDA 官方介绍](https://sundials.readthedocs.io/en/latest/ida/Introduction_link.html)
消去代数变量后,Jacobian 不能只拼接相邻组件的直接偏导。对
```text
ydot = f(t, y, z)
0 = g(t, y, z)
```
在当前光滑分支、`g_z` 可逆时,需通过线性求解得到 `g_z * dz/dy = -g_y`,再组装 `J = f_y + f_z * dz/dy`,无需显式计算逆矩阵。这样才包含“状态变化 → 代数环重新平衡 → 导数变化”的影响。结构编译也要考虑此过程产生的新依赖。
第一版可用保守结构着色差分建立正确基线,再逐类增加局部解析导数或自动微分。旧实测的非零图和 27 色只是某次运行观察,不能直接当作全部流向/接触模式的可靠结构。迭代求解器的导数应针对其收敛方程,不宜把固定次数迭代轨迹直接当作物理方程导数。
### 10.6 项目接入点和生成产物
| 位置 | 具体接入方式 |
| --- | --- |
| `app/system_xml.py` | 复用现有校验和 `SystemXmlDocument`;补充明确的误差设置传递合同 |
| `app/main.py:compile_system_xml_network` | 抽取共同的版本、参数、介质与连接规范化前端;避免 Python/C 分别解释模型 |
| `app/simulation/solvers/causal_ir.py` 与现有分块/stream 计划 | 复用结构分析结果,转换为无 Python 回调的数值计划 |
| 建议新增 `app/simulation/native_codegen/` | 完整数值 IR、组件原生能力注册、结构编译、C emitter、编译缓存 |
| 建议新增 `native/runtime/`、`native/components/`、`native/include/` | CVODE 适配、代数求解、组件与物性原语、版本化 C ABI |
| 建议新增 `app/simulation/backends/` | Python 与原生 worker 的统一运行接口、结果适配和诊断 |
| `app/main.py:_run_system_xml_simulation_profiled` | 在现有任务/进度/取消接口内选择后端,保持结果变量标识和单位一致 |
每个模型的缓存目录建议包含:
```text
<build-key>/
model.c / model.h # 状态、端口布局和模型专用计算入口
manifest.json # 来源、版本、布局、组件映射、支持能力、构建哈希
model.exe # 链接原生运行库的可执行模型
```
每次运行另建目录,保存数值参数、运行选项、结果和诊断。模型 ABI 至少区分 `initialize`、`rhs/residual`、`jacobian`、`roots`、`apply_event`、`outputs`,通用运行库提供 `run`。RHS 返回导数,事件函数返回零点函数值,输出函数只在需要物理投影时调用。每个运行拥有独立 context,禁止共享可变全局状态。
缓存键包括规范化拓扑、组件/介质实现版本、结构参数、IR/ABI 版本、精度、平台、编译器和编译选项。普通数值参数以数组传入,时长、容差、最大步长与输出间隔由运行选项传入;这些修改通常无需重新编译。改变端口数量、状态数量或方程分支结构的参数必须触发重新编译。若把某个普通参数特化进源码,也必须将其值纳入缓存键。
生成器只输出可信原语与合法数值,用户组件 ID 通过映射表定位,不作为任意 C 源码或编译命令片段。未支持的组件、模式或算法在编译/启动阶段明确报告;强制原生测试不得静默改用 Python。
### 10.7 精度、采样与性能口径
本次检查发现两个实际差异:
- 网页入口 `app/main.py` 的 `rtol` 当前写死为 `1e-6`;此前测试 C 为 `1e-7`。XML v3 尚无 `rtol/atol` 字段,应通过明确的协议演进同时更新 XSD、解析、导出和执行设置,不可只修改某一后端。
- 当前 `tests/data/test-mql-8.xml` 仍为 `maxStep=0.001`,而此前 JSON 测试副本使用过 `1e30` 和 `0.02`。后续应由同一份规范化模型与独立运行配置驱动比较,不能用文件同名推断设置相同。
`rtol` 相同也不等于总体精度相同:需同时固定每类状态的 `atol`、单位/缩放、代数闭合容差、初始化及事件处理。首阶段保持状态定义和方程一致;改变质量/内能为压力/温度等状态形式属于单独的数值方案。
`sampleStep` 与内部积分步长分开:使用积分库的插值能力取得输出采样点,不为每个输出点重新启动求解器。已知不连续时刻仍要显式分段,状态事件要定位零点并执行复位/重启。`maxStep=1e30` 只放宽上限,不会使求解器忽略精度或事件自动迈大步。
主指标单列求解墙钟与求解 CPU;XML 解析、代码生成、冷编译、初始化、输出投影、文件写入和 HTTP 序列化分别计时。性能模式只计推进所需的求值与事件定位,不计绘图及额外结果投影;正确性模式另行采样曲线验证。积分器要求的初始 RHS/Jacobian 也计入求解工作量,避免从计时中漏掉。
### 10.8 推荐实施顺序
1. **冻结一份共同输入和运行配置。** 以 `test-mql-8.xml` 为首个完整目标,列出其全部组件类型/模式、公式与原生能力;对齐当前 Python、旧 C 原型和 Amesim 的参数、单位、状态与事件差异。
2. **完成一条闭环支路的完整 IR 和 C kernel。** 以同一 `t/y/mode/parameters` 比较初始化、物性、闭合、RHS、Jacobian 与事件左右值;覆盖正常、反向流、近零压差和接触状态。
3. **生成该支路的 C 并链接 CVODE,跑通独立 EXE。** 同时以“相同 SciPy + Python/C RHS”作为执行开销对照,分开判断 C 迁移收益与更换积分器的影响。
4. **覆盖首个完整模型,并接入现有 API 的显式原生选项。** 将当前 Python 的结构消元、stream 局部执行、事务回滚和稀疏能力迁入;优先修复管流收敛与雅可比重复求值,再考虑低占比线性代数优化。
5. **验证通用性和再逐步默认启用。** 用组件重命名、连线变化、不同支路数量、反向流和其他受支持参数模式证明生成器不依赖原测试拓扑;按现有物理验收合同检查 Amesim 投影、事件时刻和守恒残差。
首个交付应能由任意命名、符合已声明支持范围的 XML 稳定生成可运行 EXE,同时报告实际后端、求解器版本、模型/二进制哈希、计时及求值/迭代计数。本次文档没有执行这项迁移,也没有新增性能测试;提速倍率需待上述共同输入对照完成后报告。
@@ -0,0 +1,26 @@
# Python 数值实现退役记录(2026-09-10)
网页与 CLI 统一采用 C 数值内核。删除旧 Python 积分器及模型数值实现;Python 保留输入校验、模型元数据、C 生成、构建缓存、任务与结果管理。
## 删除与保留
- 删除 `app/simulation/solvers/`、`systems/generic.py`、Python 状态/物性求值、组件流量/受力/导数方法、物性缓存及对应的逐次物性计时。
- 删除旧固定算例求解器、旧 Python 基准执行脚本和依赖它们的比较脚本;保留 Amesim 结果读取器与历史数值文件。
- `config.py` 保存配置与进度,`sampling.py` 保存采样合法性检查,`results.py` 保存结果合同。
- 组件 Python 文件保留参数、端口、显示、结果、方程结构以及几何预处理。方程结构声明不再包含运行时残差值。
- 气体质量/能量初值由 C `native_medium_init()` 计算,兼容实验气瓶/贮箱原有初值定义。
- 后端默认且仅支持 `native`;`native-c` 是别名,`python` 会明确报错。旧固定算例 HTTP 接口返回 410,统一 XML 接口继续使用。
- 后端运行依赖移除 NumPy/SciPy。NumPy 仅用于回归断言,列在 `requirements-test.txt`。
- C RK45/CVODE BDF 和既有雅可比策略保持不变。无时间信号机械模型的生成代码补充未使用参数声明,修复严格编译警告导致的构建失败。
## 回归依据
删除前从旧 Python 内核捕获 `tests/data/native-python-reference.json`:50 个网络、112 组状态的初值、导数和输出。覆盖空气/氦气、正反向流、换热、节点、串联阻力、管路容腔、机械模式、信号、重命名/重排及重复支路;删除后由生成的 EXE 对照冻结值,容差 `rtol=2e-8, atol=2e-7`。另有四质量块解析校验、反弹与纯信号 RK45/BDF、XML/任务取消和接口测试。
历史 Python MQL 基准的原始 XML/JSON 移到 `tests/baselines/simulation/test_mql_8/sources/`,保留原始哈希与仿真设置,不用新内核覆盖历史结果。当前 `tests/data/test-mql-8.json` 和 XML 同步采用已选择的最大步长 0.02 s。
`skill-test` 对应的 `tests/data/native-skill-test.xml` 完成 0–10 s:RK45、最大步长 0.001 s、rtol 1e-7、不记录轨迹。预热后单次纯求解 **0.381517 s**,60224 次导数求值、10022 个接受步、14 个拒绝步。该次同时进行其他回归工作,不作为新的性能优劣结论。
当前版本仍仅提供 Windows x64 原生构建。此前已发现大型 `test-mql-8` 的 CVODE BDF 完整仿真过慢;本次删除旧实现不解决该问题,不能据组件覆盖或短时测试宣称其长时仿真已通过。详见 [组件覆盖记录](C内核组件库覆盖记录.md)。
本地生成的 EXE、DLL、计时日志在 `/test/`,不提交编译产物。源码和冻结基准进入 Git,可重新生成。