修复循环信号与事件采样并接入 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 通过。
This commit is contained in:
ljz committed 2026-09-17 23:50:13 +08:00
1 parent 1aac220084
commit 7611f13208
85 files changed
+11358 -33

No files matched your search

+169
View File
@@ -0,0 +1,169 @@
# 两个 operation 的 context 访问级诊断
## 结论
两个案例均能按“查询 key 和首次匹配关系 → 消费字段 → 有序更新与追加”建立局部清单。完整仿真中,每例各验证 896 对 baseline/probe:查询 key、命中状态、逻辑条目对应后的消费值、valid 测试及有序写入一致,operation 输出逐位一致。
- **group 18 / R475 / position 52**:Jacobian 200 中 `states[74].p` 确实被两次 PT 查询扫描读取,但两次都在压力比较处排除。它没有成为物性计算输入;`states[74].T/h/rho/isentropic` 均未被该 operation 读取。因此,**本次入口差异不影响查询选择和计算**,不能表述为“这个字段完全没被读取”,也不能无条件忽略任意压力变化。
- **group 6 / R288 / position 16**:Jacobian 200 的入口 count 从 baseline 12 变为 probe 13。两次 PT 查询均 miss,逻辑新条目应从 baseline 12/13 映射到 probe 13/14;退出 count 应为 15。probe 原有 slot 12 必须保留。
这是独立诊断 worker 的验证结果。生产求解器、现有 local-probe guard 和整段回放策略没有修改;不能据此直接允许整个 R475 复用。
具体数值、每次查询的完整 key、valid 测试和逐项有序写入见 [实测清单](context_access_checklists.md)。以下解释这些清单如何用于后续设计。
## 验证范围与方法
输入 `tests/data/test-mql-8-corrected.json`,BDF,0–10 s,采样间隔 0.01 s,rtol=1e-8。位置、group、Jacobian 序号均采用已有诊断的 0 起始编号。Windows / GCC 8.1.0;本次没有执行 Linux 验收。
独立 worker 来源为 `test/context-fallback-20260917/worker`。生成时,仅在副本内包装实际字段读取、valid 位测试、赋值、结构体清零、count++、查询和分配点,保留原表达式、短路条件和原 guard。Jacobian scalar get 经输出指针写入 `rho` 的路径也单独记录。
原始事件带有执行顺序、函数、context 域、字节偏移及原始位值。PT/PH 查询记录 medium kind、全部七个 medium 浮点参数、p 和 T/h;校验器独立扫描当前重放状态,检查所有匹配项、首个匹配 slot,以及实际扫描到的 valid 测试序列。miss 后的 `allocate` 事件给出所选追加 slot。
观察器和 memo 指针还校验了当前 context 的归属,以及同一 Jacobian 内 baseline/probe 的绑定一致性,不只是比较“是否非空”。日志中的原始地址仅用于本次进程诊断,不作为跨进程、跨机器的逻辑 key。
**前后快照仅作校验终点**:逐条读取须与当时 context 一致;逐条写入须重建退出 context 的每个有效字节,包括未改动旧条目和其余 pipe 槽。另独立检查原代码规定的新条目初始化顺序及 pipe 的 11 次写入,因而删除 `pipe.valid=0` 这类同值写入也会验收失败。未初始化槽清零前的内容未知,不把它计作“已知同值写入”。
`operations.json` 中的 `consumed` 是选择完成后的实际字段读取集合;查询扫描的 `p/T/h/medium` 和 valid 测试在原始事件中单独保留。新条目内部的计算读取也在集合内,但这些值不是需要和入口旧条目比较的前置条件。
## 案例一:group 18,R475 内 position 52
operation 为 `flow:amesim_pnl0001_17.port_1`,输出 `q[152]`,使用 `pipe_cache[28]`。
### 查询及必要前置条件
Jacobian 200,t≈0.372854446 s,入口 count=75,capacity=256。
| 项目 | baseline | probe |
|---|---:|---:|
| states[74].p | 15019640.74937454 | 15019641.148960622 |
| states[74].T | 460.10768147887495 | 460.1076863719882 |
| states[74].valid | 21 | 21 |
| 上游 PT key 的 p | 15019625.056587901 | 相同 |
| 上游 PT key 的 T | 529.0977489177745 | 相同 |
| 下游 PT key 的 p | 15019613.376778807 | 相同 |
| 下游 PT key 的 T | 529.0975843945621 | 相同 |
完整 medium key 为 `(real_helium=1, R=2077.26439404998, cp=5193.1609851249505, Tref=293.15, slope=0, mu=1.96e-5, muT=293.15, S=79.4)`。实际二进制位值保存在事件和清单来源 JSON 中,不依赖上表小数显示精度。
两次 PT 都 miss,分别扫描 75、76 项,追加到 slot 75、76。slot 74 的两次访问均为 `valid & 1 → p == query.p`;压力不等后短路,未读取其 T 或 medium。满足同样排除关系即可允许这项差异,不要求两次入口的 slot 74 压力相等。
此时 `p[44] <= g[40].p`:温度来自 `g[40].T`,没有 PH 查询,`h[178]` 没有被本次分支消费。需要保持压力方向、近零流量分支、实际温度来源、medium 和管道常量一致。
### 实际读取 → 必须保留的 probe 数据
- 上游新条目:p、T、medium、mu、rho、isentropic_factor、isentropic_exponent,以及温度观察器/Jacobian memo 指针。
- 下游新条目:p、T、medium、rho、两个 isentropic 字段和上述指针;没有消费下游 mu/h。
- 选中后的 valid 测试依次为:上游 MU=0、ISENTROPIC=0、RHO=0;下游 ISENTROPIC=0、RHO=0;再次上游 RHO=4。
- `pipe_cache[28]` 入口只读 valid=0,其余旧键字段被短路跳过。
- 保留 probe 的 `states[0:75]` 全部内容,尤其是 slot 74 的新 p/T;其他 39 个 pipe 槽保持 probe 值。这条实测路径没有写任何已有物性条目。
### 有序字段更新与追加动作
1. count 75→76;在 slot 75 整体清零,依次写 medium、p、T、valid=PT、temperatures、jacobian。
2. 写 mu,`valid |= MU`;写 rho,`valid |= RHO`;写 factor、exponent,`valid |= ISENTROPIC`。上游最终 valid=29。
3. count 76→77;同样初始化 slot 76;写 rho、RHO 位、factor、exponent、ISENTROPIC 位。下游最终 valid=21,未写 h/mu 的计算值,但初始化清零必须执行。
4. pipe[28] 按顺序写 valid=0、medium、p1、p2、T、diameter、length、roughness、kind、flow、valid=1。首次 valid=0 是真实的 0→0 写入。
5. 输出 `q[152]=-1.4080633385291488e-6`;model evaluator 返回 1。
### 不能省略的其他实测分支
| position 52 查询序列 | probe 次数 | 代表 Jacobian |
|---|---:|---:|
| PT miss → PT miss | 727 | 200 |
| PH miss → PT miss(登记 h)→ PT hit → PT miss | 167 | 2 |
| PH hit → PT hit → PT miss | 1 | 1 |
| 无物性查询,近零流量 | 1 | 0 |
PH miss 路径需要测试 H 位并显式写 h、`valid |= H`,随后 pipe 的 PT 查询复用这个刚创建的逻辑条目;不能把后一次 hit 另当一次追加。PH hit 路径实际消费已有条目的 T,随后读取其已有效的 mu/rho/isentropic 字段;这些入口载荷必须比较。Jacobian 1 中首次匹配为 slot 7,仅新增下游条目。两条补充分支的完整 key 和写入顺序已收入实测清单。
全程有 24 对入口 count 不同,偏移为 +1 或 +2;其查询和逻辑字段仍一致。位置 52 也需要动态 slot 映射,不能固定为 75/76。
## 案例二:group 6,R288 / position 16
operation 为 `flow:amesim_pnl0001_1.port_1`,输出 `q[45]`,使用 `pipe_cache[0]`。
### 查询及必要前置条件
Jacobian 200 的 medium 与上例相同:
| 逻辑条目 / 查询顺序 | p | T | baseline slot | probe slot |
|---|---:|---:|---:|---:|
| 上游 U | 15019678.822746754 | 291.8496414260662 | miss → 12 | miss → 13 |
| 下游 D | 15019662.638804033 | 291.84951601402554 | miss → 13 | miss → 14 |
baseline 扫描 12、13 项;probe 扫描 13、14 项。probe 增加的入口项都不匹配当前查询,且两次追加时均有容量。**相同逻辑条目由查询 key 和创建次序定义,不能用“相同数组下标”定义。**
此时 `p[3] <= g[4].p`,使用 `g[4].T`,未消费 `h[64]`。需要比较实际压力/温度输入、medium/管道常量,以及查询和分支前置条件。
### 实际读取 → 必须保留的 probe 数据
U、D 的消费字段及 valid 测试与上例的两次 PT miss 路径一致,只需映射到 probe slot 13/14。pipe[0] 只消费入口 valid=0。
**保留 probe `states[0:13]` 的每个字段,包括 slot 12,以及其他全部 pipe 槽。** 本 operation 没有对已有物性条目的写入。入口 count 不需要等于 baseline,但它决定下一次追加位置,不能忽略其作用。
### 有序字段更新与追加动作
1. 在 probe 当前尾部追加 U:count 13→14,slot 13 完整初始化,写 mu/rho/factor/exponent 和对应 valid 位,最终 valid=29。
2. 重新按更新后的 probe context 查询 D;miss 后 count 14→15,slot 14 初始化,写 rho/factor/exponent 和对应 valid 位,最终 valid=21。
3. pipe[0] 执行同样的 11 次有序写入,包括同值 valid=0。
4. `q[45]=-3.34452871903457e-6`,model evaluator 返回 1。
把 baseline slot 12/13 的退出快照直接覆盖到 probe 会损坏原 slot 12;把 count 恢复为 baseline 14 会丢失 probe 的有效尾项。正确动作是“保留 probe 前缀,在 probe 当前 count 顺序追加”。
896 对中,638 对存在 count 差异,最大偏移 +4;829 对走两次 PT miss,67 对走近零流量路径且不增加 count。全部能建立一致的逻辑映射。
## 比较、保留、写回与 fallback 的边界
| 入口差异 / 动作 | 本次清单要求 |
|---|---|
| 未选中的条目 p/T/h/medium 不同 | 可允许数值不同,但必须验证仍被当前查询排除,不改变首次匹配关系 |
| count / slot 平移 | 可允许;用当前 probe count 检查容量,按 key/首次命中和创建顺序建立映射 |
| 选中已有条目的有效载荷不同 | 必须比较本分支实际消费的 T、mu、rho、factor、exponent 等;不一致则 fallback |
| valid 位不同 | 比较实际测试的掩码结果;未知分支不可放行。`valid |= flag` 应保留其余 probe 位,不能泛化为整字覆盖 |
| 入口未被读取的 h 或 pipe 旧键值不同 | 本分支可以忽略比较;仍须保留未被实际写入的 probe 数据 |
| 新条目 | 当前尾部追加;完整初始化再按事件次序赋值,同值写入也不能删除 |
| 已有条目更新 | 两例的完整运行未观察到。插桩已覆盖相关赋值,但不能声称已实测该分支;若后续出现,需要保留其原有有效字段、按映射定点更新 |
| 容量不足、无效 key、scratch 路径 | 本次未出现。清单要求 fallback,不能套用“必定追加两项” |
| 非空 temperature observer | 本次均为 NULL;非空会有外部观察器副作用,未验证,fallback |
| pipe 入口命中分支改变 | 本次目标槽均 valid=0;若变为有效需重新核验完整 pipe key、flow 载荷和分支,不能沿用本清单 |
| 首匹配不同 / 重复 key 改变匹配先后 | fallback;单纯“某处有同 key”不够 |
Jacobian scalar memo 是另一个需要保留的作用域:其 key、get 命中、put 尝试、recording/capacity 已记录。Jacobian 200 baseline 的两次 density 和一次 pipe scalar get 为 miss,probe 均 hit;返回数值一致。此处不能简单回放 baseline 的 memo 写入或统计副作用。当前诊断不修改该 memo;后续局部复用必须维持其生命周期和统计语义。
operation 本身是一次 double 赋值,没有独立 int 状态码。记录的是实际输出/pipe flow,以及包围它的 model evaluator 返回值;没有虚构 operation 成功码。
## 验收结果
- 3,584 次 operation(2 案例 × baseline/probe × 896),全部访问校验和退出 context 重放一致。
- 1,382,612 次字段/基址读取逐条核对通过;valid 掩码测试另外记录并校验。
- 每例 896 对的完整查询 key、hit/miss、首次匹配关系经过独立验证;按逻辑映射后的消费字段集合、valid 测试及有序写入一致。
- 136,606 次显式写入,其中 **10,614 次已知同值写入**;检查包括 pipe valid 的 0→0,未把未初始化槽的清零算作已知同值写入。
- 状态、输出、事件及所有 896 个 132×132 Jacobian 的 SHA-256 与已有未插桩基线一致;矩阵元素共 15,611,904 个。
- accepted=10,840,rejected=918,nfev=44,467,njev=896,nlu=3,106;Newton iterations=19,371,Newton convergence failures=798,均与基线一致。
- 2,688 次包含目标 operation 的 model evaluator 调用均返回 1;baseline 每次含两个目标 operation,所以该数小于 operation 数量。
- 证据校验器另有 6 个负例:遗漏同值写入、rho 读取错误、追加使用 baseline slot、恢复 baseline count、错误首匹配、错误 valid 位结果。它们是对证据校验器的反例测试,**不是已实现的生产 fallback 测试**。
插桩会引入大量日志开销,本次时长不用于评价优化收益。容量耗尽、scratch、非空 observer、已有物性条目更新及 pipe 命中分支未在这两个案例内实测,仍是未来实现时的明确边界。
## 复现与交付文件
需先保留已有 local-probe、context-fallback worker 及其 baseline 验证文件。它们的生成入口分别是 `local_probe_experiment.py`、`diagnose_context_fallback.py`;本次脚本会对缺失来源报错,不生成替代基线。
```powershell
.venv-win\Scripts\python.exe tests/manual/diagnose_context_access.py prepare
.venv-win\Scripts\python.exe tests/manual/diagnose_context_access.py run
.venv-win\Scripts\python.exe tests/manual/analyze_context_access.py
.venv-win\Scripts\python.exe tests/manual/verify_context_access_evidence.py
```
所有路径由脚本所在项目目录推导。原始证据和生成 worker 位于 `test/context-access-20260917/`,属于被 Git 忽略的运行产物:
- `worker/build.json`:来源及插桩源码 SHA-256。
- `audit/access.jsonl`:逐次实际查询、读取、测试、写入、分配、输出和返回事件。
- `audit/measurement.json`:全量仿真数值一致性哈希。
- `summary.json`:逐 Jacobian 的两路径对应关系。
- `operations.json`:全部 3,584 次 operation 的查询、消费字段、valid 测试、有序更新与追加。
- `jacobian-200.json`:两个主案例的原始事件和结构化清单。
- `negative-checks.json`:六项证据负例结果。
本报告及 [实测数值清单](context_access_checklists.md) 保存在 `tests/manual/`,可与诊断脚本一起提交。