# 八路采样失败与曲线差异定位 日期:2026-09-14。分支:`system-optimization`。本次只定位,未修改生产代码、原始 JSON 或原始 Amesim 文件。 ## 结论 | 现象 | 判定 | 证据 | |---|---|---| | 50 s 仿真、0.001 s 采样退出 64 | 触发结果容量限制;错误解释和日志保留有缺陷,不是积分失败 | 进入积分前预计约 746 MiB,超过固定 256 MiB 限制;同一 EXE 关闭历史结果保存后完成 50 s | | 启动阶段约 163 kPa、105 K 差异 | **主要是节点能量传递 bug** | 仅在诊断生成代码中按各支路能量流求和,50 s 对比的最大压力差降至 44 Pa、温差降至 0.37 K | | 循环切换点约 1.29 MN 力差 | 比较时刻位于切换点不同侧,且存在信号边界计算不一致;不能直接归为 BDF 算法误差 | 32.4 s 两端读取了不同信号阶段;44 s 的事件定位与信号求值在同一个 double 时间上不一致 | | 高温物性差别 | 氦气黏度和热物性分段实现有遗漏 | 相同 p、T 下直接调用双方物性;高温黏度明显不同,但单独调整它不能消除主要温差 | | 管流小幅差别 | 摩擦系数公式的近似差异,属于模型实现差异 | 不经过积分,在相同边界状态下仍有流量差;常温探针测试点最大约 0.234% | | 其余很小的差别 | 包含已知物性/管流公式差异及数值误差,尚不能全部指定为积分算法差别 | 节点诊断后仍非逐位一致;没有证据要求先更换 BDF 或矩阵求解方式 | ## 1. 测试对象与范围 沿用上份报告的八路循环模型及参数审计结果:157 个组件、178 条连接,1092 项公开参数已核对。平台采用 BDF;Amesim 保留标准变步长隐式配置,未假定其内部算法、误差权重与 CVODE 完全相同。 原始文件在本次结束时的 SHA256 与开始前一致: - `tests/data/test-mql-8-corrected.json`:`60ed16c71b72be4ae71ca7980f4f8cdcdf6b4c4c8950863c2390960b71ced4` - `tests/data/test_mql.ame`:`251b2f17c24ea02c1ab48f9f441a0ec38e7920627ea7e6870392326424a517c5` 循环比较基准使用 `test/mql8-cyclic-20260914/` 内上次保留的模型副本。诊断实验集中在 `test/diagnosis-20260914/`。对 188 个已跟踪的 app/native/frontend 文件逐一核对开始、结束时的哈希,变化数量为 0;保留工作区此前已有改动。 ## 2. 0.001 s 采样为什么退出 64 这里的 0.001 是**采样时间间隔**,即每秒保存 1000 次,不是积分器的最大步长。 `native/runtime/main.c:163` 在调用 `native_solve` 前检查预计结果容量: `(仿真时长 / 采样间隔 + 1024) × (状态数 + 输出数) × 8 字节` 八路模型有 132 个状态、1784 个输出。50 s、0.001 s 时: `(50000 + 1024) × (132 + 1784) × 8 = 782095872 字节 = 745.865 MiB` 固定上限是 268435456 字节,即 256 MiB。超限直接 `return 64`,没有进入积分,也没有写结构化结果或解释原因。因此这不是 GCC、CVODE 或操作系统实际分配内存失败。 使用同一缓存 EXE 的复现结果: | 配置 | 结果 | 时间 | |---|---|---| | 50 s,采样 0.001 s,保存历史结果 | 退出码 64,无结果文件,日志 0 字节 | 进程约 0.054 s | | 1 s,采样 0.001 s,保存历史结果 | 正常完成 1 s | 求解 2.613 s | | 50 s,采样参数仍为 0.001 s,`--solve-only` | 正常完成 50 s | 求解 12.187 s | 这些耗时用于判别失败阶段,不是重复测量后的性能基准。 目前保存的是全部输出,不仅是界面选择绘制的曲线。结果写出阶段还会一次性申请 `采样数 × 输出数` 的数组,并再次检查 256 MiB。因此单纯移除前面的限制也不构成完整解决方案。 `runner.py:122` 将“无结果文件”解释成通用 Native worker 错误;`runner.py:151` 的临时目录随后被清理,所以错误文字中的日志路径可能已不存在。本次给出的原始临时日志路径也已不存在,但保留工作目录的复现清楚确认了退出原因。 后续建议: 1. 启动前给出“结果容量超限”、状态/输出/采样数量、预计容量和上限,后端也要校验。 2. 原生程序返回明确的资源限制错误;异常时保留或回传日志,不能只指向随后被删除的路径。 3. 分块计算、写出历史输出,或支持选择保存变量。前端、HTTP 与 CLI 使用一致的限制和错误含义。 4. 当前模型 50 s 对该前置检查的采样间隔阈值约为 0.00303237 s;0.004 s 可通过此项容量检查。已实测可正常运行的旧配置是 0.01 s。通过容量检查不代表对其他运行问题作保证。 ## 3. 主要压力、温度差异:节点没有完整传递能量流 ### 3.1 具体代码路径 - `app/simulation/native_codegen/extended.py:452`:PN3NODE2/P4NODE2 将支路流量和焓折算成参考口的一个焓值。 - `extended.py:457` 起:只有部分流向进行补偿,并在净流量接近零时使用正则化的倒数。 - `extended.py:615`:储气元件按流向选择“流入焓”或“本腔体焓”,再乘该口的净质量流量。 这套表达对于普通单支路换向可以成立,但对于一边进、一边出的多支路汇合节点不够。**净质量流量与净能量流必须分别求和;不能依据净质量流量的正负决定整组支路只携带一个来源的能量。** Amesim 本机安装的 `libpn/submodels/PN3NODE2.c` 和 `P4NODE2.c` 声明参考口分别汇总各支路的质量流、焓流、体积及体积变化率。它们直接对带符号的焓流求和,并不先除以净质量流量再折回能量。 例如,一支路送入 2 kg/s、比焓 2000 J/kg,另一支路送出 3 kg/s、比焓 1000 J/kg:净质量流是流出 1 kg/s,但净能量流是流入 1000 W。把它当成“净流出 1 kg/s × 本腔体 1000 J/kg”,会得到流出 1000 W,连方向都反了。 ### 3.2 在实际八路模型中捕捉到的错误 把 Amesim 在 0.0004 s 的完整物理状态送给原平台 C 方程计算。压力、温度、位移等状态匹配后,`amesim_p4node2_8` 向 `amesim_pnl0001_20` 传递的能量为: | 量 | 数值 | |---|---:| | 净质量流入管腔 | −0.0525535 kg/s | | 支路 1 的能量流 | +7.080728 MW | | 支路 3 的能量流 | −4.770562 MW | | 支路 4 的能量流 | +0.027449 MW | | 按支路求和应计入的能量 | **+2.337615 MW** | | 原代码计入的能量 | **−1.252658 MW** | | 少计的能量流 | **3.590273 MW** | 以上全部来自**同一组状态下的一次方程计算**,不需要比较积分器。这直接证明存在能量传递错误。 ### 3.3 隔离因果实验 在诊断目录生成独立 C 模型,只把节点参考口传给储气元件的能量改为支路能量求和。没有改正式 Python/C 文件、管路公式、物性、积分器或原模型参数。 双方误差限取 1e-10、最大步长 1e30;50 s 全程按共同 0.01 s 网格比较: | 指标 | 原实现 | 仅调整诊断副本的节点能量 | |---|---:|---:| | 最大压力差 | 163359.89 Pa | **43.96 Pa** | | 最大温度差 | 105.24 K | **0.373 K** | | 排除信号切换点前后 0.02 s 后的最大力差 | 约 5131 N | **1.373 N** | | 是否完成 50 s | 是 | 是 | 因此主要压力、温度偏差已定位为模型连接层的能量计算 bug,不是“换一种积分方法自然产生的正常差别”。诊断生成代码只用于验证原因,不是已经合入的通用修复。 后续应在 C 连接计算中明确传递带符号的能量流,质量流和能量流独立守恒;不要依赖“能量流除以接近零的净质量流”来构造参考口焓。正式修复还需覆盖节点串联、流向同时相反、净流量为零但有热量交换等情况。 ## 4. 排查过的其他原因 ### 积分步长和误差限 此前已从 1e-8 收紧至 1e-10,主要误差不消失。本次进一步比较前 0.02 s:最大积分步长由 1e30 降至 1e-5 s,采样间隔为 1e-5 s。0.01 s 的最大压力差仍约 163359.8 Pa,最大温差仍约 105.237 K。 细采样还发现启动过程真正的短时最大差约为 276.66 kPa 和 125.05 K,分别出现在约 0.00042 s 和 0.00055 s。上份报告的 163 kPa、105 K 是共同 0.01 s 网格上的最大差,不是对所有内部时刻取最大。 ### 物性及储气方程 在已经初始化真实氦气介质的 Amesim 生成程序副本中,调用官方库的 p、T 物性接口和储气方程;与直接包含平台原始物性 C 文件的探针比较。 - 同 p、T 下,密度和低于 6000 K 的焓基本一致。 - 分别输入质量变化、能量输入、压缩体积三种情况,双方储气压力/温度变化率基本一致;高温处残余差异与热物性分段遗漏相符。 - Amesim 的温度有效域警告不表示温度被强行截为 1500 K;直接测试表明它仍在高温状态上计算。 - 平台氦气黏度始终使用第一段公式,Amesim 数据在 1000 K 和 5000 K 换段。5000 K 时平台黏度低约 3.48%,9600 K 时低约 5.51%。 - 平台定比热的氦气理想热物性也未覆盖 Amesim 6000 K 以上的数据段。在 9600 K 探针点,焓相对差约 2.72e-7、比热相对差约 4.70e-6;它不是这次 105 K 温差的主要来源。 仅在隔离副本补上黏度分段,前 0.15 s 最大温差只从 105.237 K 降至 105.104 K,压力差从 163359.89 Pa 降至 163032.28 Pa。主因被明确排除。 ### 管路摩擦公式 使用同 p、T、压力比、管径、长度和粗糙度,直接比较 Amesim `pn2pipefr_` 与原生 `native_pipe_flow`,不进行时间积分。探针包含 3 个压力、4 个温度、5 个压力比,共 60 点。 300 K 测试点的最大流量相对差约 0.234%,1000 K 约 0.241%。这些点的可压缩流量参数基本一致,摩擦系数不同。平台 `native/components/modules/pipe.c:8` 使用拟合、混合的摩擦系数公式,不能视为与 Amesim 实现完全相同;高温差异还叠加黏度分段遗漏。 节点能量和黏度同时在诊断副本调整后,前 0.15 s 最大压力差约 24.26 Pa,温差约 0.453 K。单项误差并不保证同方向变化,不能只凭某个最大温差略升就否定已确认的黏度缺项。剩余小误差尚未完全拆分为摩擦近似、热物性分段和积分误差各自的份额。 ### 自由质量块的巨大位移数值 上份报告单列的 `amesim_mecmas21_9` 质量为 100 kg,静摩擦、库仑摩擦、黏性摩擦均为零,不启用限位;模型施加的循环力达到 1e17 N。其位移本身约为 1e17 m 量级,不能把绝对位移差直接与正常行程元件比较。收紧误差限后的 50 s 节点诊断对比,最大位移差约 2.04e8 m,相对该位移量级约为十亿分之几。这里具有明显的误差尺度和数值累计特征,未发现与主要节点能量 bug 相当的力学公式错误证据;尚未对这一自由质量块另做解析解误差分解。 ## 5. 循环信号切换点与力尖峰 ### 同一个显示时间,不一定处于同一阶段 收紧误差限后的原始结果: | 原始保存时刻 | 平台/来源 | 信号 1 | 信号 2 | LSTP00A_1 力 | |---|---|---:|---:|---:| | 32.4 | 平台 | 49000 | 0 | 468633.757 N | | 32.40000000000221 | Amesim | 1e17 | 1e12 | 1756893.431 N | 平台的事件时间计算为 `32.400000000000006`,所以采样时刻 `32.4` 位于切换前;Amesim 上述结果位于切换后。这些时间在界面上都会显示为 32.4 s。模型信号幅值和接触阻尼非常大,微小时间差造成的小速度差会被阻尼放大为很大的力差。 节点能量诊断后,32.4 s 处仍有约 1.288 MN 的差别,但排除切换窗口后的力差降到 1.373 N,说明这与主要能量 bug 是两个问题。当前证据不支持把切换点差别直接判为 LSTP00A 力公式错误。 ### 信号求值和事件定位本身也存在不一致 `native/components/modules/signal.c:8` 用 `fmod` 求周期内时间;`signal.c:26` 起用“周期数乘周期再加阶段偏移”定位事件。 独立 C 探针直接调用这两个原始函数:事件定位返回 44 s,但在完全相同的 double 值 44 上,信号求值仍返回上一阶段的 1e17;到 `nextafter(44, +∞)` 才返回 49000。54 s 也可复现类似现象。**这是可重复的边界一致性缺陷,不需要运行积分器即可触发。** 后续应让阶段判定、事件定位及结果采样共享同一套边界定义,并明确保存切换前值、切换后值或两者。不能用任意放宽时间容差的方式把所有邻近时刻混在一起。 ### 普通采样会漏掉很窄的尖峰 平台原始结果还保存了约 32.40035510065 s 的额外事件点,力约 −2.0839e14 N,0.01 s 共同网格并不包含它。为排除“平台独有尖峰”,在 Amesim 生成 C 的诊断副本中记录该窗口的内部方程计算,也捕捉到相同时刻、相同量级的负尖峰(约 −2.0839e14 N)。这些内部计算含事件和试算调用,不能把它们全部当作已经接受的普通输出采样。 因此既不能拿平台额外事件点与 Amesim 的粗采样曲线直接逐点相比,也不能把上份报告的共同网格指标当作全时间域尖峰误差。后续事件验收应分别比较同侧极限、事件时间、事件后的状态及窄窗口波形。 ## 6. 后续修复顺序建议 1. 先修复节点能量传递:这是已证实影响主要物理结果的 bug。 2. 修复采样容量错误的校验、说明和日志保留;再安排分块结果输出。 3. 统一循环信号的事件与采样边界。 4. 补齐氦气分段物性,明确管路摩擦公式对齐标准;之后再量化剩余积分误差。 本次没有合入以上修改,也没有调整求解器、矩阵或生产工具链。 ## 7. 可复核证据 以下路径均相对 `test/diagnosis-20260914/`: - `sampling-reproduction.json`:退出 64、短仿真及 solve-only 的命令和结果。 - `initial-convergence-summary.json`:启动瞬间细采样、最大步长收紧实验。 - `same-state-flow-comparison.json`、`replay-state-*.json`:将 Amesim 物理状态送入原平台 C 方程。 - `node-energy-balance.json`:各支路能量及漏算量。 - `node-energy-replacements.json`、`node-energy-model.c`:只用于因果验证的生成代码改动。 - `node-energy-final-comparison.json`:独立诊断程序完成 50 s 的曲线指标,以及节点加黏度实验。 - `properties-summary.json`、`volume-comparison.json`、`native-flows.csv`、`ame-flow-probe/flow-probe.csv`:直接物性、储气方程及管流对比。 - `signal-boundaries.csv`、`force-event-samples.json`、`event-force-probe-summary.json`:循环边界和窄尖峰证据。 - `production-source-verification.json`:188 个生产文件哈希核对结果。 所有诊断源码、实验模型副本及日志均保留在该目录,可在后续正式修复时复用。