CelerisLab/tests/审计.md

12 KiB
Raw Blame History

审计结论

当前代码的问题不是单点误差而是沿着主链路分布。最重的问题集中在三处curved Bouzidi 的施加时机不对Bouzidi 分支公式与文献不一致,以及若干运行时接口与内核实现脱节。这几类问题叠加后,足以让同一 case 在 SRT、TRT、MRT 之间出现远大于正常数值差异的结果。

需要单独说明的是,部分未来接口属于有意预留,不应被视为 bug。本审计只把已经进入当前执行契约、但实现与语义不一致的部分列为问题。

按当前项目约束,以下两类设计不再单列为缺陷:

  • 运行时接口为后续能力预留,但当前未完全接通,只要注释明确即可
  • obs 采用跨多步累加,由调用者决定何时清零,这属于有意设计而非实现错误

状态说明

  • [已解决] 已进入当前代码
  • [待重构] 不是单点修补能彻底解决,适合下一阶段重构
  • [待验证] 需要最小算例或单元测试确认
  • [保留说明] 当前不修,但需要在代码或文档中明确限制

当前总览

已解决

  • [已解决] lbm/__init__.py 导出错误
  • [已解决] forcing 主链路未接通,以及 SRT TRT MRT forcing 预因子不一致
  • [已解决] TRT outlet NEQ 重构未补齐
  • [已解决] add_vortex() 把动量当速度
  • [已解决] Sensor 面积归一化缺失,已在 ObjectManager 层提供
  • [已解决] sync_to_gpu() 末尾重置非流体节点的架构错误
  • [已解决] curved donor 合法性未检查真实 domain flags
  • [已解决] curved Bouzidi 时序错误
  • [已解决] q >= 0.5 分支读错时间层
  • [已解决] moving wall 修正未按 q 分支实现
  • [已解决] 初始化链路与 object flag 叠加关系错误
  • [已解决] config_body.json 未进入实际初始化链路
  • [已解决] inlet U0 语义已补注释

仍需重构或继续处理

  • [待重构] body 模块整体职责边界仍不清晰几何描述、flag overlay、compact list 生成、动作状态、观测打包仍然耦合过重
  • [待重构] curved boundary 当前仍是“圆形简单几何特化 + Bouzidi kernel 特化”架构,不适合继续扩到离散几何与通用移动刚体
  • [待重构] 3D 刚体旋转契约仍是 z 轴占位实现
  • [待重构] plain linear Bouzidi 与 TRT 不相容问题已注明限制,但没有方法级替代方案
  • [待重构] config.py 与文档层对预留能力、当前能力、限制条件的边界还不够清楚
  • [待验证] MRT 路径仍需最小算例单独核对
  • [待验证] Esopull 邻壁处理仍需与 double-buffer 做一致性复核
  • [待验证] force 提取与 host 侧系数归一化仍需放到同一处核对

历史问题清单

主执行链路

文件 问题 影响
lbm/__init__.py [已解决] 导入了并不存在的 add_lamb_oseenadd_taylor_green。实际 initializers.py 只提供 add_vortex CelerisLab.lbm 包导入会退化到空 __all__,对外 API 与代码不一致。
field.pyconfig.pyinlet_outlet.cuhinit_flow.cu [已解决] update_runtime_params() 暴露了 u_inletrho_ref 一类接口,但入口、出口、初始化全部仍然读编译期宏 U0RHO。如果这些接口继续保留在活跃 API 中,就会形成假功能。 运行时接口语义与真实执行路径不一致。
helpers.cuhforcing_guo.cuh [已解决] collide_dispatch() 每步都调用 zero_forcing(Fin),没有任何地方根据 d_params.fx fy fz 生成 Guo forcing也没有调用速度半步修正。 运行时体力项接口是死路径。任何依赖体力驱动的算例都会静默失效。
collision_trt.cuhcollision_mrt.cuh [已解决] 在 forcing 真的接通之前TRT 与 MRT 版本目前都是直接加 Fin[i]SRT 则乘了 (1-omega/2) forcing 一旦接通,三种碰撞模型会立刻表现出不一致的体力离散。

Curved boundary 与几何预处理

文件 问题 影响
one_step_double.cuaux_kernels.cucurved_boundary.cuh [已解决] Curved Bouzidi 是在 OneStep 完成 collision 与 store 之后,通过 CurvedBoundaryKernel 二次修补。 紧邻曲壁的 fluid 节点在本步 collision 时已经使用了从 solid 方向拉来的错误分布。后修补只能影响下一步,不能修正本步碰撞污染。
curved_boundary.cuh [已解决] q >= 0.5 分支使用 fi_in[k_f, dir_opp]也就是上一步缓冲区而不是同一步、碰撞后传播前的分布函数。Bouzidi 线性插值两支公式都要求同一时间层的 post-collision 数据 [Bou01]。 该分支与文献公式不一致,会直接破坏 curved wall 的局部反射关系。
curved_boundary.cuh [已解决] moving wall 修正统一写成 + 6 w_i (c_i · u_w),没有区分 q < 0.5q >= 0.5 两支,也没有体现 Bouzidi moving boundary 中的分支依赖系数 [Bou01]。 对旋转圆柱或移动物体,壁面速度修正的量级与形式都不对。
body/objects.py [已解决] Cylinder.get_curved_list() 的 donor 合法性只检查了“是否越界”和“是否落在圆柱内部”,没有检查 donor 是否落在上壁、下壁、入口、出口等非流体节点。 fallback_class 的主机侧担保并不成立。靠近通道壁或边界时,q < 0.5 分支可能继续使用非法 donor。
aux_kernels.cu [待重构] 3D curved body 的运行时角速度契约只读取一个标量 omega,并硬编码成 z 轴转动,代码里也明确写了 placeholder。 3D 旋转物体路径并未真正完成,但接口没有把这种限制暴露出来。

初始化、观测与工具函数

文件 问题 影响
initializers.py [已解决] add_vortex()ux_olduy_old 用的是动量和,没有除以 rho_old 任何基于该函数构造的初值都会把速度场放大为密度加权动量场。
step/aux_kernels.cubody/manager.py [已解决] SensorKernel 对传感器区域做的是逐格点求和,ObjectManager 也没有按面积归一化。 如果外部把传感器输出当成平均速度或平均观测量,结果会系统偏大并随探针面积变化。
body/manager.py [已解决] sync_to_gpu() 最后调用 _rest_nonfluid(),会把所有非流体节点都重置成静止平衡态,而不仅是物体节点。 只要场中有物体,就会额外改写入口、出口、壁面节点的初始化状态。

文档与配置层

文件 问题 影响
configs/CONFIG 文档写 nx 必须整除 threads_per_block,但实际 launch 使用的是 ceiling division。 配置说明与执行实现不一致。
configs/CONFIG [已解决] 文档写 neq_extrap 下 SRT 与 TRT 都使用全分布 damped NEQ 重构,但代码里只有 SRT 走全分布分支TRT 仍是少量未知方向重构。 算法说明与真实边界实现不一致。
READMEconfig.py 文档把 FP16C 当成可选存储精度,但 LBMConfig.validate() 会直接拒绝 FP16C 对外能力声明与当前运行时不一致。

高风险问题

边界方法与碰撞模型耦合

文件 问题 影响
curved_boundary.cuhcollision_trt.cuh [保留说明] 当前实现采用 plain linear Bouzidi 与 TRT 直接拼接。TRT 的黏性无关参数化只在边界离散满足相应条件时才成立,普通线性插值边界并不会自动保留该性质 [Gin08b]。 即使把显式 bug 全部修掉TRT 与 SRT、MRT 的结果仍可能因边界离散而系统分叉。
curved_boundary.cuh 当前 curved wall 没有任何质量守恒修正。对于高 Re、长时间、周期性 curved flow文献已经报告 plain Bouzidi 会出现质量泄漏与力漂移 [San18]。 长时间拖算时,平均密度、阻力与升力可能持续漂移。
collision_mrt.cuh D2Q9 MRT 为配合新方向排序手工重写了整套 moment transform 与 inverse transform但代码里没有任何一致性校验或自测痕迹。 一旦某个符号、系数或方向映射有误,结果会直接体现在升阻力与稳定性上,而且不容易从表面现象定位。
inlet_outlet.cuhconfig.py 抛物入口把 U0 解释成截面平均速度,峰值自动变成 1.5 * U0。接口名字仍然叫 velocity,没有区分平均速度与最大速度。 只要用户按最大入口速度设参数,实际 Re 就会整体偏移。
init_flow.cu 四个角点优先按 inlet 或 outlet 分类,而不是 wall。随后边界核又把非 interior_y 的角点落回 bounce_back_swap() 角点的标记语义与实际处理语义不一致,容易在后续扩展中埋下隐患。

待验证问题

需要单元测试或最小算例复核的项

文件 问题 影响
one_step_esopull.cu Esopull 路径没有像 double-buffer 那样对 y == 1y == NY-2 的流体邻壁行做显式半格 bounce-back 修正。 bounded channel 在 esopull 与 double-buffer 之间可能存在额外差异,需要最小通道算例核对。
collision_mrt.cuh [待验证] D2Q9 MRT 的新配对顺序、moment basis、inverse transform 是否与 compute_rho_u()compute_feq() 完全一致,目前只能靠数值表现间接推断。 这条路径可能包含隐藏的符号错位需要用均匀流、Poiseuille、衰减涡等简单算例单独验算。
inlet_outlet.cuh SRT 出口在 neq_extrap 下重构了全体分布,不仅是未知方向。 该设计是否有利于稳定性、是否额外改变质量守恒,需要独立做 outlet 对比测试。
curved_boundary.cuhaux_kernels.cu [待验证] 当前力提取采用 f_toward + f_reflected 的链路级动量交换,但没有与 host 侧的阻力系数归一化和符号约定放在同一处核对。 即使流场正确,力的符号、量级和平均方式也仍可能在后处理阶段出错。

本轮已修复

  • lbm/__init__.py 已改为导出真实存在的 add_vortex
  • 运行时参数接口已收紧到当前真实生效的 omega 与 forcing 相关项
  • Guo forcing 已接入主碰撞分发链路SRT、TRT、MRT 的 forcing 预因子已统一
  • TRT 的 outlet NEQ 重构已补齐为与 SRT 一致的全分布 damped NEQ 路径
  • add_vortex() 已修正为用速度而不是动量直接叠加初值
  • 传感器读数已在 ObjectManager 层提供面积归一化接口
  • 物体同步后的静止平衡重置已收缩为只作用于 obstacle interior而不再覆盖所有非流体节点
  • curved link donor 合法性检查已扩展到实际 domain flags而不只检查是否在圆柱内部
  • curved Bouzidi 已从“步后修补流体节点”改为“步前写入 obstacle source slot”并改掉了 q >= 0.5 分支对前一时间层 opposite population 的读取
  • curved moving-wall 修正已继续收紧为独立 helper并把 q < 0.5 与 fallback 分支改回与 [Bou01] 一致的符号约定
  • 初始化链路已改为“先构建 clean channel flags再叠加 object mask再由 init kernel 保持 obstacle flag 并写入静止平衡态”,移除了 sync_to_gpu() 末尾对 obstacle interior 的二次主机侧重置
  • Simulation 已开始消费 config_body.json 中的简单物体定义,并在编译期同步 N_OBJS 契约
  • inlet 抛物入口已补充注释,明确 U0 在当前实现中表示截面平均速度,峰值为 1.5 * U0
  • curved boundary 文件已显式注释plain linear Bouzidi 与 TRT 不具备 TRT-parametrized curved-wall 保证,当前实现保留该限制说明

交叉症状解释

当前现象和代码结构是吻合的。TRT 加 Bouzidi 直接发散,最符合 curved wall 时序错误与 q >= 0.5 分支读错时间层这两个问题叠加后的表现。SRT 与 MRT 加 Bouzidi 不发散但升阻力偏离,则更像是主链路虽然还能跑,但边界修正、观测累加、入口参数语义和 MRT 未校验实现共同把结果拖离了正常范围。

文献层面的两条提醒也和代码现状一致。第一plain linear boundary 与 TRT 的参数化并不天然相容 [Gin08b]。第二plain Bouzidi 在高 Re 周期 curved flow 中会出现质量泄漏与力漂移 [San18]。这两条不是当前代码里最先要解释的大偏差,但它们说明就算显式 bug 修完,边界策略本身仍然需要额外核验。