Files
SystemSimulationApp/docs/other/机械元件事件覆盖与Amesim对照-2026-09-17.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

137 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 机械元件事件覆盖与 Amesim 对照
本次核查基于当前平台源码、八路工程的实际生成代码、本机 Amesim 2404 子模型源码及随安装提供的帮助。没有修改机械内核,也没有重新运行 Amesim;数值验收证据引用上一轮修复后的回归日志。
## 1. UD00 修复的影响范围
生产代码改动仅在 `native/components/modules/signal.c`。MASS、接触力公式、机械事件定位及求解器重启代码没有修改。已有机械事件仍然生效,不需要因为这次信号修复而重新注册。
若机械系统由 UD00 驱动,修正信号边界的取值会影响驱动力、后续轨迹和碰撞时刻;积分步分布也可能变化。因此“机械事件机制没有改动”不代表耦合系统的每一个数值结果都保持不变。纯机械模型若没有使用 UD00,则没有这条直接数值调用依赖。
## 2. 逐类比较
| 元件或模式 | 当前平台 | Amesim 2404 本机证据 | 判断 |
| --- | --- | --- | --- |
| MECMAS21 理想限位,`stoptype=1` | 注册 `NativeStop`;在接受步内用密集插值和二分定位上下界;命中后位置置于界面,速度置零,再重启积分 | `MECMAS21.c` 调用 `endst2_`;帮助说明其碰撞处理为位置等于限位、速度为零,并维护状态标记 | 撞击事件已具备,无需重复添加;应核验脱离限位、初始就在限位及同时事件 |
| MECMAS21 恢复碰撞,`stoptype=3` | 注册相同的限位定位;入射速度超过阈值时按恢复系数反向,否则置零 | 调用 `endstrc_`;帮助说明恢复系数及防止无限反弹的低速阈值 | 核心撞击事件已具备;保留并补边界组合验收 |
| MECMAS21 弹性限位,`stoptype=2` | 计算上下限穿透及弹簧阻尼力,未向 `NativeStop` 或其他通用事件表注册接触/脱离 | 允许负力时调用 `endst1b_`,否则调用 `mecEndStop_` 且 `handle_disc=1`;帮助说明维护接触状态 | 建议补充上下界接触/脱离事件,非负力模式还应处理原始接触力的截断边界 |
| LSTP00A 弹性接触 | 用间隙计算非负穿透,再调用 `native_contact`;没有接触状态事件注册 | 与弹性限位复用上述接触工具;`mecEndStop_` 明确启用不连续处理 | 当前八路模型应优先补充这一项 |
| 静摩擦、库仑摩擦、Karnopp/Stribeck 模式 | 已有 `NativeFriction`、保存的离散模式、停滑与起滑定位;密集插值定位速度阈值和净驱动力超过静摩擦阈值的时刻 | `MECMAS21.c` 调用摩擦工具;`linert1c` 帮助说明低速区、起滑阈值及保存的模式标记 | 已有基础,不是缺失整套事件;需核验换向、阈值相等、与限位/信号同时触发 |
| 无限位 MASS,`stoptype=4` | 不注册限位;若启用干摩擦仍有摩擦事件 | 同样绕过限位工具,保留所选摩擦模型 | 无需人为添加上下限位事件 |
| 普通双向线性弹簧、黏性阻尼 | 当前公开机械目录主要提供 LSTP00A 接触件;不能把它等同于普通双向弹簧阻尼 | Amesim `SD0000.c` 直接计算连续的弹簧、阻尼力及导数 | 将来新增这类光滑模型通常不需要事件;出现间隙、单向作用、饱和或摩擦切换时再添加 |
平台依据:
- [机械力公式](../../native/components/modules/mechanics.c):`native_contact`、`native_stop_motion`。
- [机械事件定位与状态更新](../../native/runtime/common.c):`locate`、`locate_breakaway`、`native_accept`。
- [生成器的接触方程、摩擦与限位注册](../../app/simulation/native_codegen/extended.py):接触力约在 559 行,MASS 弹性力约在 571 行,限位注册约在 625 行。
- [紧凑生成路径](../../app/simulation/native_codegen/compiler.py):支持的限位模式也生成 `NativeStop`;其他模式由扩展生成路径处理。
Amesim 依据:
- [MECMAS21.c](F:/AMESim2404/Amesim/libmec/submodels/MECMAS21.c:547):理想、弹性、恢复碰撞和摩擦模式的实际调用分支。
- [LSTP00A.c](F:/AMESim2404/Amesim/libmec/submodels/LSTP00A.c:294):接触工具调用及 `handle_disc=1`。
- [SD0000.c](F:/AMESim2404/Amesim/libmec/submodels/SD0000.c:267):普通弹簧阻尼连续方程。
- 本机 [amehelp.qch](F:/AMESim2404/Amesim/doc/amehelp.qch) 内的 `libmec/doc/html/utils/endst1b.html`、`mecEndStop.html`、`endst2.html`、`endstrc.html`、`linert1c.html`。这些帮助页通过只读查询 Qt 帮助数据库取得。
本机安装未提供上述接触工具的完整内部源代码。因此可以确认 Amesim 的接触状态管理和不连续处理接口,但不据此声称已完全复原其全部根函数、内部容差或同一时刻的执行顺序。
## 3. 当前八路工程的优先级
从 `tests/data/test-mql-8-corrected.json` 实际生成得到:
- 共 10 个 MECMAS21:9 个无限位,1 个理想限位;理想限位元件为 `amesim_mecmas21_10`,范围 `[0, 0.37] m`。
- 共 8 个 LSTP00A,均为数值刚度、允许负接触力;`kcont=1e11 N/m`、`rcont=1e11 N·s/m`、`Pdis≈1e-7 m`。
- 生成头文件为 `NSTATES=132`、`NSTOPS=1`、`NFRICTIONS=0`。这 1 组 `NativeStop` 包含上下两个位置界面,不代表只有一个事件时刻。
- `model_next_break` 只汇总信号时间事件,没有注册这 8 个接触件的间隙事件。接触力仍被计算,只是没有单独定位接触/脱离时刻。
建议优先顺序:
1. **先补 LSTP00A 的接触/脱离定位。** 它直接覆盖当前八路模型的 8 个接触件。
2. **复用同一机制覆盖 MASS 弹性限位。** 当前八路工程没有启用该模式,但这是平台组件能力中明显未显式覆盖的事件。
3. **完善已有理想/恢复限位和摩擦的组合边界。** 当前理想限位通过 `native_stop_motion` 的条件方程处理保持与离开,没有单独注册“约束反力消失/自由净驱动力反向”的根函数;应核验连续驱动力下的离开时刻,再补充需要的释放事件。
缺少接触事件不等于当前接触力公式错误。自适应积分可以通过缩小步长处理部分分段变化,已有温和工况也能通过对照。显式事件的目的,是更稳定地确定作用阶段、接触时刻及峰值附近的积分历史。此次核查不能证明之前八路模型的全部力峰差异均由这一缺口导致。
## 4. 应怎样添加
这类事件由状态决定,不能像 UD00 那样只向 `model_next_break(t,end)` 添加预定时间。应扩展状态事件接口,允许组件提供事件面、穿越方向、有效模式及事件后的操作。
- **接触边界:** LSTP00A 使用带符号间隙 `gap = gap0 + x2 - x1` 的 `gap=0`;MASS 弹性限位使用 `x-xmin=0`、`x-xmax=0`。不要用已截成非负的 penetration 作为唯一找根量,否则脱离区间整段为零,失去跨越方向。
- **非负接触力边界:** 仅在 `discContactOption=2` 且处于接触区时,处理未截断力 `Fraw=0` 的分支切换。允许负力的模式没有这个截断开关,不应因力过零就重启。
- **事件动作不同:** 弹性接触只重新确认分段并重启积分,位置和速度保持连续;理想碰撞、恢复碰撞才按其模型重置状态。不能把弹性接触事件直接当成硬碰撞。
- **不需要的事件:** `Pdis` 是指数过渡尺度,不是“穿透达到它就突然切换”的阈值;也不应在 `3*Pdis` 处造事件。数值刚度/几何刚度是初始化参数模式,若运行中不切换,也不产生事件。
- **防止重复触发:** 初始恰好接触、贴边不动、离开后重新接触、同一时刻多个接触和信号跳变都需明确阶段与方向,并保证试探求值不提交离散模式。
最低验收应覆盖:单 MASS 上下碰撞及释放、单弹性限位、双质量块 LSTP00A 接触/脱离、允许/禁止负力两种模式、非零/零阻尼过渡尺度,并对 BDF/RK45、不同最大步长比较事件时刻和接触峰值。与 Amesim 对照时还需区分事件前后值。
## 5. 已有验证能说明什么
上一轮修复后的[完整回归日志](../../test/ud00-boundaries-20260917/regression-tests.log)中,恢复碰撞双求解器测试、LSTP00A 接触测试、MASS 摩擦保持以及 `test_amesim_stick_slip_endstops_and_joint_circuits` 均通过。
最后一项使用独立 Amesim 2404 运行生成的参考数据,覆盖理想限位、弹性限位、摩擦与联合机械等场景;每个参考场景检查 40 个选定时刻,测试设置最大步长 0.002 s。它支持“相关常规数值行为仍可用”,不足以证明当前八路模型的高刚度接触全过程、所有边界组合都与 Amesim 严格一致。
## 6. 补充接触/脱离事件的求解时间成本
### 结论及适用范围
事件检查、定位和处理会增加计算工作,但总求解时间不一定增加。若它减少了跨接触边界的拒步、非线性迭代和反复缩步,这些节省可能抵消部分甚至全部开销。当前尚未实现接触事件,不能给出已测得的变慢百分比。
以下分析针对前文建议的“状态事件定位后重启积分”实现。单纯记录零点与切换接触阶段不是同一件事,也不应假设所有事件定位都必然要求相同的重启方式。
### 成本来自哪里
| 环节 | 当前代码依据及新增成本 | 判断 |
| --- | --- | --- |
| 每个接受步检查接触状态 | `native_accept` 已经检查硬限位/摩擦;新增 LSTP00A 间隙可直接由两个位置状态及常数计算 | 对 8 个接触件,轻量状态判断预计成本较低;这是算法量级判断,不是计时结果 |
| 定位实际跨越时刻 | 现有 `locate` 固定执行 60 次二分,每次调用密集插值;BDF 使用 `CVodeGetDky`,RK45 计算状态插值多项式 | 纯间隙根函数不需要重算整个气动网络;定位次数和精度决定成本 |
| 截断并重启积分 | `native_accept` 可把已接受步截回事件;BDF 调用 `CVodeReInit`,RK45 重新计算导数和初始步长 | 会放弃事件之后那部分试算工作,并产生重新起步的工作;BDF 的历史重建尤其值得关注 |
| 雅可比及线性求解 | BDF 原生路径使用差分雅可比和稠密线性求解器;新起步需要相应初始化与后续数值建立工作 | 成本作用于整个耦合系统,而非只作用于触发事件的那一个弹簧 |
| 保存事件点及输出重放 | 若沿用现有状态事件存储流程,每个新增事件时刻会保存状态,输出阶段再次调用 `model_eval` | 通常少量事件时不突出;大量事件会增加结果体积与后处理时间,需要与纯求解耗时区分 |
CVODE 7.4.0 的官方实现中,`CVodeReInit` 将当前阶次重设为 1,并重置步数/历史起点;下一次积分进入初始设置与初始步长计算。它复用已有内存,不是重新编译模型或重新分配整个求解器。见 [CVODE 7.4.0 官方源代码](https://github.com/LLNL/sundials/blob/v7.4.0/src/cvode/cvode.c#L518)。平台对应入口见 [cvode_solver.c](../../native/runtime/cvode_solver.c:357)、[rk45.c](../../native/runtime/rk45.c:57) 和 [common.c](../../native/runtime/common.c:137)。
因此,主要风险是频繁切换造成的整系统重新起步,不是“多写了几个 if 判断”。重启不清除从仿真开始以来的物理运动结果,而是从事件处的状态继续积分。
### 既有八路运行数据能支持什么判断
早先正确性评估中的 **50 s 循环工况**记录如下,来源为 [native-summary.json](../../test/evaluation-mql8-20260917/full/native-summary.json)。这是 UD00 修复前的历史样本,仅用于估计工作量,不能作为当前代码已经完成的性能 A/B 对比。
| 指标 | 历史样本 |
| --- | ---: |
| 求解壁钟时间 `solveSeconds` | 12.414 s |
| 接受步数 | 19,412 |
| 误差测试失败次数 `rejectedSteps` | 1,511 |
| 方程求值计数 `nfev` | 84,268 |
| 其中雅可比差分求值 | 50,512 |
| 雅可比刷新次数 | 1,804 |
| 线性求解器 setup 次数,输出字段 `nlu` | 5,903 |
| 求解器启动次数,含初次启动 | 20 |
| 已注册状态事件的触发批次数 | 9 |
该生成模型包含 132 个状态、1,784 个输出和 27 个雅可比分色组。历史数据中每次雅可比刷新对应 28 次方程求值(27 组扰动加一个基准求值),合计 `1804 × 28 = 50512`。这说明多余的整模型求值、雅可比刷新和重新起步比单纯间隙算术更值得控制;不能把方程调用次数占比直接当作耗时占比。
若接受步数暂按历史样本不变估算,8 个接触件每步检查一次是 `8 × 19412 = 155296` 次简单间隙检查;两个端点均重算则约为其两倍。间隙直接读取位置即可,不需要为这些检查各自求解气动物性、管道流量和全部输出。
另一方面,历史的 `stateTransitions=9` 不包含当时没有注册的 LSTP00A 接触/脱离,所以不能据此预测新增事件数量。8 个接触件可能长期保持接触,也可能反复接触和脱离;真正影响重启成本的是整个仿真期间的切换次数,以及是否出现数值反复触发。
不能将 12.414 s 除以启动次数来推算单次事件成本,也不能把平台求解时间与报告中的 Amesim 完整进程时间直接比较。
### 建议采用的成本控制措施
1. **专门生成轻量事件函数。** 直接读取位置/速度状态,批量计算间隙和需要的局部接触力;避免为了事件检查调用完整 `model_eval`。在不需要新增物理动态量时,不人为增加连续状态维度。
2. **先筛查,后定位。** 只对可能跨界的区间执行找根;同时覆盖区间内转向等情况,不能为了省时漏掉端点同号但中间跨界的情形。定位达到所需精度或浮点区间不再可分后停止,不必机械重复满 60 次。
3. **仅在阶段实际切换时处理。** 保持接触期间不反复重启;明确初始贴边、穿越方向和离开后的再次触发规则。不能以放大物理间隙、移动事件时间或粗暴忽略真实小振荡来换速度。
4. **同一时刻的多个事件批量提交、一次重启。** 包括多个接触件,以及与信号边界重合的情况;不得为了减少启动次数把有真实先后关系的事件强行合并。
5. **只注册启用模式所需的边界。** 当前八路的接触件均允许负力,不额外注册非负力截断事件;也不在 `Pdis` 或 `3*Pdis` 处造事件。
按上述实现,接触/脱离次数较少时,额外成本预期可控;频繁真实碰撞或边界数值反复触发时,成本可能明显增加。事件处理不会消除模型本身的高刚度,也不能保证 RK45 因此适合所有高刚度工况。
### 如何验证增量成本
完成实现后,在同一份 JSON、求解器、容差、最大步长和输出设置下,对修改前后分别重复运行,使用已构建的可执行文件,比较中位数并记录波动。分别记录纯求解时间、进程总时间、事件检查/定位次数、实际切换数、启动次数、接受步/拒步、`nfev`、`njev` 和线性 setup 次数。
平台 `solveSeconds` 不包含后续全部输出重放和 JSON 写出,所以事件点增多的输出成本还应检查总进程时间。现有 `nfev` 也不统计纯密集插值调用,新增定位计数/耗时才能解释这部分成本。
除当前八路模型外,至少检查长期不接触、持续接触、单次接触/脱离及反复碰撞四种情况;在事件时刻与接触力精度得到验证的前提下评估速度。本轮仅完成成本评估,没有修改机械事件实现或进行新增事件的性能实测。