12 KiB
12 KiB
审计结论
当前代码的问题不是单点误差,而是沿着主链路分布。最重的问题集中在三处: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_oseen 与 add_taylor_green。实际 initializers.py 只提供 add_vortex。 |
CelerisLab.lbm 包导入会退化到空 __all__,对外 API 与代码不一致。 |
field.py、config.py、inlet_outlet.cuh、init_flow.cu |
[已解决] update_runtime_params() 暴露了 u_inlet 与 rho_ref 一类接口,但入口、出口、初始化全部仍然读编译期宏 U0 与 RHO。如果这些接口继续保留在活跃 API 中,就会形成假功能。 |
运行时接口语义与真实执行路径不一致。 |
helpers.cuh 与 forcing_guo.cuh |
[已解决] collide_dispatch() 每步都调用 zero_forcing(Fin),没有任何地方根据 d_params.fx fy fz 生成 Guo forcing,也没有调用速度半步修正。 |
运行时体力项接口是死路径。任何依赖体力驱动的算例都会静默失效。 |
collision_trt.cuh 与 collision_mrt.cuh |
[已解决] 在 forcing 真的接通之前,TRT 与 MRT 版本目前都是直接加 Fin[i],SRT 则乘了 (1-omega/2)。 |
forcing 一旦接通,三种碰撞模型会立刻表现出不一致的体力离散。 |
Curved boundary 与几何预处理
| 文件 | 问题 | 影响 |
|---|---|---|
one_step_double.cu、aux_kernels.cu、curved_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.5 与 q >= 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_old 与 uy_old 用的是动量和,没有除以 rho_old。 |
任何基于该函数构造的初值都会把速度场放大为密度加权动量场。 |
step/aux_kernels.cu 与 body/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 仍是少量未知方向重构。 |
算法说明与真实边界实现不一致。 |
README 与 config.py |
文档把 FP16C 当成可选存储精度,但 LBMConfig.validate() 会直接拒绝 FP16C。 |
对外能力声明与当前运行时不一致。 |
高风险问题
边界方法与碰撞模型耦合
| 文件 | 问题 | 影响 |
|---|---|---|
curved_boundary.cuh 与 collision_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.cuh 与 config.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 == 1 和 y == 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.cuh 与 aux_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 修完,边界策略本身仍然需要额外核验。