Files

194 lines
25 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.
# CelerisLab 修复交接:供 TRON 独立复核
2026-10-10。用户授权本轮修复现有错误、组织 subagents 并实际运行检查。没有实现壁面 jet、AMR/多层网格,也没有开展全面重构。保持当前模块边界和主要公共接口。
## 工作树与来源
基线为 `main` 的 `6e3756c587ec08ab6a55c4a1a5f4671822d3f0a0`,没有提交或推送。修复前已有用户改动,见 `baseline-status.txt`、`baseline-hashes.json`。四个生成配置头和 `tests/postproc/experiment.ipynb` 是原有改动,**不是本轮补丁**;修复后逐字节哈希与本轮开始时一致。原副本保存在 `original-user-files/`。
唯一运行来源为 `/home/frank14f/CelerisLab/src`,解释器为 `/home/frank14f/anaconda3/envs/pycuda_3_10/bin/python`(Python 3.10.13)。包、compiler 和 CUDA 源文件的实测路径见 `provenance.json`,永久 GPU 测试也断言源码来源。未修改 DynamisLab 下的副本、全局安装或环境配置。
运行采用 Tesla V100-SXM2-16GB;物理 GPU 限定0、1,进程内映射为 device 0。编译使用临时独立源码副本和配置头,Simulation 关闭时清理;测试没有覆盖仓库内生成头或 PTX。
## 分工与独立复核
- numerical:CUDA 算子、边界、EsoPull 映射与 stepper;报告 `repair-numerical.md`。
- state:对象、局部流场修补、传输、快照和检查点;报告 `repair-state.md`。
- architecture:配置、隔离编译、上下文与资源、CPU 导入和包声明;报告 `repair-architecture.md`。
- root:Simulation 集成、涡初始化修复、现有测试门槛、实际 GPU 验证和交接。仅就 close/constructor 异常清理授权 architecture 协助修改 Simulation 对应区域。
实施时共享任务说明明确物理与兼容约束(完成后已清理过程文件),接口变更先互通。state/numerical 相互核查同时间 EsoPull 映射与恢复阶段,并独立运行对方测试。architecture 对检查点进行交叉审查,发现定期保存时 obs 计数落后;root 修正为逐批累计,保存前等待对应 stream 完成。
## 实施的修复
| 范围 | 修复结果 | 核查重点 |
|---|---|---|
| 全局外力 | TRT 按偶/奇松弛率修正源项;MRT 使用各矩对应的修正 | 除质量、动量外,D2 全分布与独立矩阵公式对照 |
| 稀疏 force_region | 保留原来的步后独立冲量;用中点速度源项消除错误碰撞系数 | 单步 Δj=F;二次平衡下等价于局部平衡分布差,不声称与全局 Guo 在所有阶数等价 |
| EsoPull | 同一 completed count 的编码成为解码逆;同步不再隐含碰撞;壁面供体在原地写之前统一读取 | 首步、后续奇偶步、非均匀场、闭域与双缓冲同空间阶段比较 |
| 移动壁和入口 | Bouzidi 反射修正符号及可压缩密度因子;shifted 入口密度常数修正 | 各方向、q 两分支和 fallback;不改既有入口方法 |
| 物体增删 | Q-major 访问、精度/shift 编码与字节偏移一致;补丁外数据保持;立即删除也维持 dense IDs | FP32/FP16S,奇偶步、cache、增删后继续运行 |
| 对象控制与叠加 | 控制不被其他对象刷新覆盖;sensor/force 标记不改变 solid occupancy;过滤无效采样点 | 多个 force_region 的实际流体 footprint 重叠提前拒绝,避免同 cell 并行写 |
| 快照与检查点 | field-only 快照跨 EsoPull 奇偶恢复;v2 检查几何/投影并恢复控制、设备已应用 action、runtime params、obs 和缓存 | 保存 host 待上传目标与 device 已应用 action 的区别,保留 upload_act=False;相同 count 不代表同几何 |
| CUDA 传输与资源 | 异步 host 缓冲使用 pinned memory 并保持生命周期;操作作用域绑定所属 context;多实例非逆序关闭 | 构造失败保留原始异常;关闭失败可重试;外部 stream 必须在对应实例 context 下创建 |
| 配置与构建 | 独立临时编译目录;浮点宏不再按展示精度截断;显式路径缺失报错;分配结构变化拒绝;重编译同步新黏性 omega | 编译失败不读取旧隐式 PTX;CPU 工具可独立导入;Python 最低版本声明 3.10 |
| 涡初始化 | 复用标准可压缩平衡分布,补齐 rho;Oseen 中心使用解析极限及近中心稳定展开 | rho≠1 的零强度不变;中心/近中心有限、远处保持原公式;没有时间信息的 EsoPull 初始化明确拒绝 |
| 检查本身 | 集成测试固定小网格、显式空对象配置;传感器数值比较成为 pytest assert | 原来只返回结果的 validation 不能再静默通过 |
## 经复核保留的设计
1. `snapshot()/restore()` 只保存/恢复流场,不回退时钟和控制。EsoPull 保存 next-pull 物理分布,并按恢复时的 count 重编码。需要精确续跑用 checkpoint。
2. `run()` 仍丢弃未 `sync_bodies()` 的暂存编辑;runtime sync 仍重编号。立即删除现也明确会压紧 IDs,调用者需重新取得剩余 ID。
3. 公共 `recompile()` 仍禁止初始化后调用;运行中拓扑改变经 `sync_bodies()`。root 新测试曾误期望公开入口能越过此限制,修正了测试而没有改变 API。
4. checkpoint 仍允许 collision/LES 等参数研究;改变黏性时使用新配置 omega。v1 内置 circle/sensor 的匹配几何可以安全读回;无法恢复真实控制的 v1 force_region 及未知自定义几何明确拒绝。
5. force_region 仍是稀疏步后冲量;LES 原有模型选择、BFS 新流体填充策略没有替换。
6. EsoPull `get_ddf()` 仍返回已解码精度/shift 的 backing 排列,不冒充物理节点分布。EsoPull 宏观诊断是当前 count 的 next-pull 阶段;双缓冲诊断是空间 postcollision 阶段。已移除文档中不适用于这些阶段的历史“bit-identical”断言。
## 复现检查
从 `/home/frank14f/CelerisLab` 执行:
```bash
env PYTHONPATH=/home/frank14f/CelerisLab/src PYTHONDONTWRITEBYTECODE=1 PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 \
/home/frank14f/anaconda3/envs/pycuda_3_10/bin/python -m pytest tests/unit -q -p no:cacheprovider
env PYTHONPATH=/home/frank14f/CelerisLab/src PYTHONDONTWRITEBYTECODE=1 PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 \
/home/frank14f/anaconda3/envs/pycuda_3_10/bin/python -m pytest tests/integration tests/validation/test_sensor_accuracy.py -q -p no:cacheprovider
```
数值 unit suite 包含真实头文件/辅助 kernel 的 CPU shim 和 12 个独立 nvcc 编译组合;状态 unit suite 用真实 Python 方法与 HDF5,driver double 检查地址边界和 pinned 约束。两者不能替代 GPU。GPU suite 使用真实编译入口与设备,覆盖守恒、奇偶步、双布局、FP16S 状态修补、bitwise checkpoint 续跑、多实例上下文,以及约 1000 步后的 sensor 与宏观采样直接对比。
最终结果以同目录 `final-unit.log` 和 `final-gpu.log` 为准,汇总在本文件尾部。
## 尚未证明或未实现的边界
- **D3Q19 完整求解器仍未实现。** 全入口仍有维度不完整的 aux/sync 调用;Simulation 在分配/编译前明确拒绝。D3 局部 collision/shift 修复与测试不代表三维求解器可运行。
- 未做长时间高 Re、生产工况、LES 全组合、曲壁力/力矩网格收敛验证。小算例有限值、守恒和续跑一致性不能证明这些性质。
- EsoPull 入口/出口已在后续轮统一为预暂存 spatial postcollision 供体;原始失败与后续验证分开保留,见末节。仍不将有限回归扩大为所有边界组合的正确性证明。
- 壁面正确性引入每步一次小规模 prepass 和 `4*(6*nx+2*ny*nq)` 字节 scratch(已合并入口/出口准备);没有进行性能基准,不能宣称绝无性能变化。可后续基于性能实测合并兼容的边界准备工作。
- 编译成功后若发生设备 OOM/重绑定失败,runtime topology sync 尚不是通用事务回滚机制;不要将正常路径测试描述成所有设备故障下的原子恢复。
- 动态拓扑仍使用现有 BFS/equilibrium 初始化,未新增严格守恒移动边界算法。jet/网格方向需以后单独设计与验证。
建议 TRON 顺序:检查本轮与基线的差异归属 → 同 count/空间阶段映射与移动壁符号 → 力源项全向量 → checkpoint host/device 控制时序与兼容性 → 独立复现 GPU 测试 → 原地入口/出口读写与性能复核。
## 最终实测结果
合并所有修复后重新运行,两个进程均 exit 0:
- `tests/unit`:**124 passed,8 subtests passed**,26.72 秒。日志 `final-unit.log`。
- `tests/integration` + `tests/validation/test_sensor_accuracy.py`:**66 passed**,190.25 秒,真实 V100 GPU。日志 `final-gpu.log`。
- `git diff --check`:通过。
- 原有四个配置头和 notebook:最终哈希与修复开始时一致。见 `provenance.json`。
这些结果是本轮受测范围的证据;TRON 的独立复核仍有必要,尤其是上面列明的数值阶段、入口/出口并发与性能边界。
## 整理与精简(稳定性验证轮)
删除了 17 个由本轮研究/修复产生的旧复现脚本、调度记录、重复哈希和重复 baseline diff,共 3718875 字节。保留原始失败结果、正式研究、永久测试与当前交接。用户原文件未修改,`original-user-files/` 备份与哈希保护链保留;没有清理 `ref/`、用户原有研究文档或实验结果。旧报告中的复现命令是历史记录,现行命令以本交接及永久测试为准。
生产代码消除了重复参数打包、独立构建目录内多余的临时文件写入,以及手写配置字段清单;没有新增插件、注册器或通用框架。经典验证复用原有圆柱脚本,补齐作用域 context 和临时目录清理;Poiseuille 只有一个独立验证脚本。
## 经典案例与稳定性:后续修复前的基线(2026-10-10)
本轮只用物理 GPU **0、1**;进程内均为映射后的 device 0,固定前述独立源码和解释器。结果集中在 `classic-results.json`,可复算频率/受力的时序集中在 `classic-signals.npz`。不保存重复的整场快照与多套 CSV/报告。
| 案例与范围 | 实际运行 | 结果 |
|---|---|---|
| Sah04 S2,MRT/双缓冲,Re_nom=200,β=.5,2402×62 | 120000 步,burn 45000 | St=.3566902,对 .3513 误差 **1.534%**,通过原 5% 门槛;Re_real=204.881,ρ范围 .9820–1.0512 |
| Kan99b K2,MRT/双缓冲,Re=100,α=1,1351×601 | 280000 步(burn 80000 + 200000) | 五项均通过原有门槛:St=.169641(2.502%),mean Cl=−2.57953(3.675%),mean Cd=1.14603(3.807%),Cl振幅=.355069(2.212%),Cd振幅=.098919(.384%) |
| 相同 K2,EsoPull | 同样 280000 步,无 NaN/Inf | **五项均未通过**:St=.138851(16.102%),mean Cl=−2.32464,mean Cd=.823321;不应把“没发散”算作精度合格 |
| 解析 Poiseuille,SRT/TRT/MRT×两布局×H16/32/64,FP32+shift | 共 18 个基准组合、299754 步,Re=4.8,Ma≤.052 | **16/18 通过**预设误差/质量/稳态门槛;各碰撞模型的双布局剖面逐值一致。H64 弱力 MRT 两布局误差 .6977%,超过 .15% 门槛 |
Poiseuille 采用 x 周期、半程无滑移壁,解析式 `u(s)=F*s*(H-s)/(2*rho*nu)`;参考 `ref/lbmpy/src/lbmpy/analytical_solutions.py::poiseuille_flow` 及 `ref/lbmpy/tests/poiseuille.py`。公开宏观读取阶段不同,本验证统一回到 spatial postcollision 分布并按该阶段减去半力动量;没有把两种阶段的速度直接比较。原门槛为 H16/32/64 相对 L2≤1%/.3%/.15%,质量漂移≤5e−4,稳态相对残差≤2e−5,横向速度≤1e−5。H64 MRT 将外力提高4倍、仍保持 Ma≈.052 后误差降到 .00776%;这是另一参数诊断,**没有替换失败的原案例**。它提示弱力/FP32敏感性,未证明具体误差机制;TRT 误差也非单调下降,不能概括为所有组合已验证二阶收敛。
Sah04 的现有提取器带目标频段筛选,因此另用全部非零频率中的全局主峰复算,得到完全相同 St=.3566902,排除了本次结果因目标加权挑峰而“通过”。K2 保留原文升力符号,没有取绝对值或翻转观测量来通过门槛。参考全文已在 `tests/specs/sah04.md`、`tests/specs/kan99b.md`,阈值来自既有对应 validation spec,没有事后放宽。历史记忆中的 K2 升力符号问题在**当前双缓冲配置**不再出现;不能据此替旧结果重新定性。
### EsoPull 新发现的边界限制
64×32 小域、共同 spatial count=1 初态、圆柱 omega=0/.002,运行20步:x 周期时两布局分布逐值相同(力仅有原子归约舍入差);regularized/uniform/free-slip 开放边界时,首步误差出现在入口/出口(约6.8e−5),20步最大约 .0068,初期圆柱附近无差异。额外只读 CPU 检查在没有并发的情况下也产生边界输出差异。
源码原因:`boundary/inlet_outlet.cuh` 的 EsoPull regularized/channel/outlet 从邻居读 `load_f_esopull(...,t)` 的 next-pull 状态,双缓冲却读 spatial postcollision 供体。阶段不一致已经复现;原地核同时读取邻居多方向值还存在并发风险,但本次实验没有单独测定其贡献。这是两个实现尚未统一离散边界语义的证据,不能简单把不同公式都归为存储差别。
在已有 `tests/integration/test_numerical_gpu.py` 增加了周期曲壁的2项通过回归,以及开放边界的2项 **strict xfail(已知未修,不能算通过)**;root 在 GPU0 独立复跑得到 `2 passed, 2 xfailed`。后续修复应在原地推进前取同一明确阶段的供体,并统一入口、出口和自由滑移交角读取;优先考虑复用现有边界准备过程。仅换一个 load helper 不能解决读写时序。上述为修复前基线;后续实施与结果见末节。
### D3 支持边界的准确解释
当前绕过 runtime 检查、对无对象 D3Q19/SRT/双缓冲进行隔离 nvcc 编译,仍有 **18 个错误**,来自 `aux_kernels.cu` 和 `esopull_sync.cu` 的二维 `coordinates/compute_neighbors` 调用;统一入口无条件 include 这些文件,所以即使不使用 EsoPull 或对象也被阻断。原审计为20个错误;提前报错没有撤掉原本能运行的三维功能。
已有 D3 descriptors、局部碰撞、双缓冲主步、部分初始化和双缓冲 host 宏观诊断。缺的是完整链:对象 mask/links/sensor 仍按 nx×ny 构建(16×8×4 的 CPU 实测产生512/128长度错误);D3 EsoPull 初始化布局、墙面处理和宏观诊断未闭合;对象控制及局部补值仍偏二维。最小扩展可先做“无对象、双缓冲、明确 z 周期边界”的受限 D3,再验证均匀态、剪切波、平行板流与重启;不必以一次实现所有三维功能为前提,也没有在本轮开启这项实现。
### 精简后的复查与复现
本轮生产逻辑共去掉约37行重复;相对最初 HEAD、扣除原有用户修改后,生产代码/元数据净增约384行,主要用于已复现的恢复、所有权和配置缺陷。不能把新增测试与生产路径混算,也不能用净行数代替可读性审查。没有新增生产模块、注册器或抽象层。
精简后的检查:`tests/unit` 加状态/配置 GPU 回归,**141 passed,8 subtests passed**;日志 `simplification-checks.log`。经典 runner 使用作用域 context 和 TemporaryDirectory;其原本不论验收结果都返回0的行为也已修正:非 smoke 模式验收失败返回非零。利用本次已保存的真实结果重放 CLI 报告路径,验证好/坏结果分别返回0/1;这是报告层检查,没有伪称重跑物理。
经典运行命令(同样设置固定 PYTHONPATH 与 PYTHONDONTWRITEBYTECODE):
```bash
CUDA_VISIBLE_DEVICES=0 /home/frank14f/anaconda3/envs/pycuda_3_10/bin/python tests/validation/run_sah04_st_matrix.py --case S2 --json-out /tmp/sah04.json --dump-npz-dir /tmp/sah04
CUDA_VISIBLE_DEVICES=0 /home/frank14f/anaconda3/envs/pycuda_3_10/bin/python tests/validation/run_kan99b_rotating_cylinder.py --case K2 --no-k2-control --domain M --out-dir /tmp/k2-double
CUDA_VISIBLE_DEVICES=1 /home/frank14f/anaconda3/envs/pycuda_3_10/bin/python tests/validation/run_kan99b_rotating_cylinder.py --case K2 --no-k2-control --domain M --streaming esopull --out-dir /tmp/k2-esopull
CUDA_VISIBLE_DEVICES=1 /home/frank14f/anaconda3/envs/pycuda_3_10/bin/python tests/validation/run_poiseuille.py --output /tmp/poiseuille.json
```
上述基线中的 EsoPull 开放边界与弱力 MRT 问题已进入后续修复;最新状态见末节。任何有限案例均不能扩展成全部模型、全部入口和整个稳定性范围已通过。
## 二维后续修复:MRT 精度与开放边界(2026-10-10)
此节是最新实现状态;上方经典表格保留修复前结果。继续采用相同模型、Re/Ma、网格、采样长度与门槛。numerical 负责边界和初始化,state 负责 MRT,architecture 独立核对,root 负责公共入口、整体验证和结果整理。
- **EsoPull 开放边界**:原 `PrepareEsoPullWalls` 扩为 `PrepareEsoPullBoundaries`,同时读取 y 壁和 x 入口/出口的供体,仍只有原来的一次准备启动。scratch 为 `[6*nx][2*ny*nq]` 个 float;在曲壁及原地写入前暂存同阶段 spatial postcollision,首步保留初始化语义。入口/出口和 free-slip 已知方向修补均改读这份供体,移除 live-fi、t 参数和重复邻居计算。原两项 strict xfail 已改为正常断言并通过,覆盖静止/旋转圆柱、开放/周期 x 边界;额外覆盖 ny>nx、首步和后续奇偶步、实际边界头文件检查。
- **D2 shifted MRT**:直接变换 `g=f-w`,以 `M*w=(1,-2,1,0,0,0,0,0,0)` 移除平衡矩背景。保留 LL 矩阵、固定 1.2 松弛率、shear omega、Guo 半前半后源项。旧式在 rho=1、u=F=0 单次碰撞就产生约1e−8的分布漂移;新式精确保持静止。独立 FP64 全九分量 oracle 覆盖54种弱力/密度/非平衡组合。原18项 Poiseuille 全通过,H64 MRT L2 从 .6977% 降为 .02085%,质量漂移从4.927e−4降至3.896e−7;SRT/TRT原数值不变,9对双布局剖面逐值一致。这是精度修复,不是最优 MRT 或所有参数收敛性证明。
- **初始化与入口契约**:初始化复用 `compute_feq` 和现有同时间 EsoPull 编码,删去重复公式;shifted u=1e−9不再归零。成功重新初始化后 step_count 归0,再以0解码;不新增重复 obs 清零(既有流程已完成)。两布局各先跑3/4步后重初始化,与新实例的初态及下一步逐值一致,host/device obs与累计窗口均清零。`run` 在修改状态前拒绝负数/非整数步数及 checkpoint_interval,保留 run(0) 与整数协议。runtime 拒绝 nx<3、ny<4:否则供体越界或上下壁相邻行重合;局部算子配置仍可独立研究。
参考与复核:`ref/lbmpy/src/lbmpy/moment_transforms/` 的 background_distribution 变换与 `forcemodels.py::Guo` 支持背景矩、松弛和源项推导;`ref/FluidX3D/src/kernel.cpp` 的 paired EsoPull load/store 支持布局映射。边界阶段以本项目双缓冲 ghost scheme 和 `load_physical_dir_pre_streaming` 契约为准,不照搬其他库的入口模型。初始化使用同一标准二次平衡分布。两位非作者独立核对了代数/映射;没有新增生产模块、注册器或通用框架。
最终源码的经典长跑(仅GPU0/1):
| 案例 | 步数 | 原门槛结果 |
|---|---:|---|
| Kan99b K2,MRT、regularized/uniform/free-slip,双缓冲 | 280000 | 五项全过 |
| 相同 K2,EsoPull | 280000 | 五项全过,修复前五项全败 |
| Sah04 S2,MRT、channel_stabilized/parabolic,双缓冲 | 120000 | St=.356690202,误差1.53436%,通过5%门槛 |
| Poiseuille,3碰撞×2布局×3网格,shifted FP32 | 18组合 | 18/18通过;保留修复前16/18结果 |
K2 最终指标(不改升力符号、不放宽阈值):
| 指标 | 双缓冲 | EsoPull |
|---|---:|---:|
| St | 0.169640991 | 0.169640966 |
| mean_cl | -2.57953058 | -2.57953222 |
| mean_cd | 1.146032 | 1.14603163 |
| amp_cl | 0.355069886 | 0.355078089 |
| amp_cd | 0.0989277137 | 0.0989264594 |
Sah04 另用无目标加权的全局 FFT 主峰复算,St完全一致;St归一化沿用原spec的标称 Umax=.1,同时单独报告实际 Re。K2 两布局长期统计接近,但由于原子归约和诊断阶段,不声称所有时序/宏观字段逐位一致。
后续原始结果已合入 `classic-results.json::d2_followup`;长跑受力/升力时序合入 `classic-signals.npz` 的 `repaired_*` 项。原始失败数据仍保留。没有遍历所有入口/出口模式,未验证 FP16 长期稳定性、全部LES组合或高Re极限,也没有新增性能基准。修复后相对原HEAD生产/元数据为+1008/−685、净+323行(剔除用户原有生成头改动);比此前净增约384行减少约61行。测试和证据文件不计入生产行数。
最终整体验证:**130 unit passed、13 subtests passed;74 GPU integration/sensor passed**,无 xfail/skip。日志为已更新的 `final-unit.log`(33.12s)和 `final-gpu.log`(242.15s,物理GPU0)。root重新验证当前生产源码哈希与记录一致、git diff --check通过、原有四个配置头与实验notebook哈希未变。临时经典报告、重复CSV与整场快照已清除,仅保留上述合并结果和必要时序;没有提交或推送。
## 2026-10-12 小步修复:x 周期 Poiseuille checkpoint
依据用户指定的 [TRON 独立审查](https://drive.google.com/file/d/16VkxhdfJAmv4_4X6EkQjUldXNOdywkZu/view) 中 checkpoint 覆盖缺口;此轮仅修复该问题,不推进 Jet/AMR。起点是10月10日修复后的脏工作树,不是HEAD;本次增量见 `checkpoint-domain-2026-10-12.diff`。生产仅改 `src/CelerisLab/common/checkpoint.py`(+42/−8,净+34行),补充两份既有状态测试(unit +116/−2,GPU +39/−1)。其余既有src/tests/research文件在整理本节前逐文件哈希未变。未改DynamisLab、安装依赖、提交或推送。
复现:新增默认/周期域×有/无对象4个CPU用例,旧实现默认2项通过、周期2项因flags与默认channel不符而拒绝。保存读实际GPU flags;几何计算/加载却重建默认入口出口,是根因。参考 `ref/lbmpy/src/lbmpy/scenarios.py::create_channel` 区分force-driven x周期与velocity-driven入口;本项目 `merge_flag_masks` 与curved donor的domain_flags约定要求几何投影使用真实域。
修复:checkpoint升为v3,保存独立 `domain_flag`。从实际GPU flags去除注册对象overlay,固体覆盖下不可辨识的底域规范为FLUID;重叠加当前对象必须严格等于实际flags,且compact ownership有效,校验完成后才打开目标文件。加载以所存域重建geometry/projection,仍严格比较对象类型、角色、mask/hash及完整flags,另校验domain_flag形状/类型和规范化往返;全部在host/device恢复写入前完成。独立agent只读复核接受。
兼容范围:v3提供固定几何恢复,不是通用base-domain所有权系统。load之后再调用initialize(重新初始化)或sync_bodies,仍可能重建默认域;本补丁不承诺这类后续操作保留周期域。旧v1/v2仍限default-channel并按原规则严格验证,不猜测旧周期文件缺失的base-domain。隐藏underlay规范为FLUID仅是固定几何restart约定,不代表恢复或猜测被遮住的真实墙面。
验证:现有pycuda_3_10环境,固定 `PYTHONPATH=/home/frank14f/CelerisLab/src`、`PYTHONDONTWRITEBYTECODE=1`、`PYTEST_DISABLE_PLUGIN_AUTOLOAD=1`。单元测试 `tests/unit/test_state_regressions.py` **43 passed / 0.87s**。实际GPU测试前两次查询GPU0/1:均0%利用率、5MiB显存、无计算进程;仅使用物理GPU0。`tests/integration/test_state_gpu.py -k checkpoint` **10 passed、8 deselected / 33.41s**。新GPU案例D2Q9 MRT、FP32 shifted、16×18、nu=.1、Umax=.03(周期Poiseuille Re=4.8、Ma约.052),只推进3+4步:同实例/新实例恢复后,默认和周期域在两布局下与未中断续跑逐值相同。保留几何不匹配前写入拒绝、controls及obs恢复回归。CPU另覆盖旧版本、异常domain元数据、额外对象标记、无OBSTACLE的自定义SOLID掩码,以及保存失败不覆盖旧文件。没有重复经典长跑或宣称重新验证整个工程。
复现命令(仓库根目录;GPU命令前须重新确认设备空闲):
```bash
env PYTHONPATH=/home/frank14f/CelerisLab/src PYTHONDONTWRITEBYTECODE=1 PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 /home/frank14f/anaconda3/envs/pycuda_3_10/bin/python -m pytest tests/unit/test_state_regressions.py -q -p no:cacheprovider
env CUDA_VISIBLE_DEVICES=0 PYTHONPATH=/home/frank14f/CelerisLab/src PYTHONDONTWRITEBYTECODE=1 PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 /home/frank14f/anaconda3/envs/pycuda_3_10/bin/python -m pytest tests/integration/test_state_gpu.py -k checkpoint -q -p no:cacheprovider
```
本轮验收后停在checkpoint修复,最小平壁Jet留待下一步讨论。