CelerisLab/docs/audit/body_refactor_notes.md

9.9 KiB
Raw Permalink Blame History

目标

第二阶段不再以补丁式修 bug 为主,而是重建 bodyLBM 之间的模块边界,形成可持续扩展到 Bouzidi、IBM、粒子和多相耦合的骨架。重构后的代码需要保持短文件、清晰职责、显式契约并避免几何语义直接渗入 CUDA 核心计算链路。

第一阶段与第二阶段的边界

第一阶段

目标是验证当前修复后的代码没有恶化,并保住最基本执行链路。

  • 能稳定计算流场
  • 能读取力与力矩
  • Bouzidi 路径不出现新的时序性错误
  • 初始化、flag、object overlay 不再互相污染
  • 现有接口不做大改,只修运行期 bug 和明显契约错误

第二阶段

目标是结构性重构,而不是继续在旧链路上叠加特例。

  • 重构 body
  • 重构 curved boundary 数据链
  • 为 IBM 预留统一入口
  • 为简单几何和离散几何建立同一中间表示
  • 为未来多相与多物理场保留清晰耦合面

当前架构的核心问题

主要问题

模块 当前问题 后果
body 几何、flag overlay、compact list、action、obs、coupling 混在一起 任一功能扩展都会牵动整条链路
objects.py 几何对象直接生成 Bouzidi 专用数据 简单几何和离散几何无法共享同一接口
curved_boundary 几何解释、边界格式、移动壁修正、力提取绑在同一层 替换边界方法成本高
ObjectManager 过度集中,已经接近万能管理器 可读性下降,后续只能继续膨胀
host-device contract 分散在多个文件,缺少统一定义 调试困难,容易出现隐式耦合

本质判断

当前最大问题不是公式本身,而是缺少稳定的中间层。几何对象、边界方法、运行时打包目前没有被拆开,导致代码很难既简洁又可扩展。

结合本轮修 bug 的经验,再补一条判断:很多问题不是几何本身出错,而是 donor、fallback、time layer 这类数值语义散落在不同文件中,读代码时必须来回跳转才能确认。当前项目更适合把这些语义集中写进少数注释位置,而不是继续加更多隐式保护逻辑。

第二阶段的目标架构

顶层模块

保持两大物理模块:

  • LBM
  • body

但它们之间不直接互相了解实现细节,而通过显式中间数据结构耦合。

推荐分层

层级 职责 不应负责
simulation 装配模块,定义推进顺序 几何处理,边界公式细节
body 几何、刚体状态、预处理、力回收 DDF 操作LBM 核心算法
lbm 格子流体、collision、streaming、boundary operator 几何来源,刚体业务语义
coupling cut-link、IBM marker、body-fluid 数据交换 具体几何类定义,具体 collision 实现

推荐的 body 内部结构

目标

body 应只表达拉格朗日对象和几何处理,不直接承载 LBM 业务逻辑。

补充边界:body 负责管理对象并产出统一 cut-link 几何记录,lbm 只消费 cut-link 做数值计算。对象类型区分、几何来源、以及“该记录来自圆柱还是离散几何”都不应进入 LBM kernel 视野。

推荐文件树

body
  geometry
    base
    circle
    sphere
    polygon
    mesh
  state
    rigid_body_state
    particle_state
  preprocess
    flag_overlay
    cut_links
    ibm_markers
    sensors
  runtime
    action_buffer
    telemetry_buffer
    registry
  coupling
    wall_velocity
    force_torque

说明

  • geometry 只回答几何问题
  • state 只保存状态量
  • preprocess 负责把几何投影到欧拉网格
  • runtime 负责 GPU 上传与 buffer 管理
  • coupling 负责 body 与 fluid 的交换规则

进一步要求:

  • geometry 不直接生成 Bouzidi 专用 SoA
  • preprocess 先产出统一 cut-link 结果,再由更薄的一层做运行时打包
  • runtime 不回头参与几何判断
  • 单文件保持简短,避免再出现一个文件同时含几何、打包、上传、观测解释四类职责

推荐的 LBM 边界

LBM 应该看到什么

LBM 只应看到这些输入:

  • flag
  • cut-link records
  • IBM marker records
  • runtime params
  • obs buffers

LBM 不应知道:

  • 该 link 来自圆柱还是三角网格
  • 该对象是粒子还是障碍物
  • 该边界记录由哪种 host 几何算法产生

curved boundary 的重构方向

核心原则

不要把 curved boundary 等同于 Bouzidi。

需要拆成三个维度:

  • 几何表示
  • 边界处理方法
  • 运动模型

补充一条实现原则donor、fallback、time layer 等关键数值语义,优先通过集中注释写清楚,不额外引入很多“自动保证语义”的复杂逻辑。当前项目更优先保持代码短、直、可读。

建议的统一中间表示

定义通用 cut-link record,至少包含:

字段 含义
fluid_idx 流体格点索引
dir 指向边界的格子方向
q 交点沿链路的位置
body_id 所属物体
hit_point 壁面交点
lever_arm 相对参考点的力臂
normal 壁面法向
motion_tag 静止、平移、旋转等
scheme_tag Bouzidi、half-way、未来 TRT-compatible scheme
fallback_tag donor 非法时的退化方式

补充约束:

  • cut-link record 只表达几何命中结果与最小运行时字段,不直接长成某一种 kernel 专用格式
  • donor 的来源与时间层语义不额外做复杂自动推断,靠集中注释写清楚
  • 记录字段命名要直接对应 kernel 使用含义,避免同一字段在不同文件中有不同解释

这样做的好处

  • 圆形和离散几何可以输出同一种记录
  • Bouzidi 与 IBM 可以共享一部分几何预处理
  • boundary kernel 只消费记录,不关心几何来源
  • 以后替换边界方法时,不必回改对象类
  • donor、fallback、hit-point 这类契约可以在少数固定注释位置集中说明,而不是散落在对象类和 kernel 两侧

IBM 的预留方式

IBM 不应和 Bouzidi 混成一条链,而应与 cut-link 平行。

建议另设统一 marker record,用于:

  • 插值点位置
  • 支撑域格点
  • 权重
  • 与刚体的归属关系

这样未来可以并存:

  • cut-link boundary
  • IBM boundary
  • 混合策略

运行时契约的建议

必须显式化的契约

应把 host-device contract 从各文件中收口,单独维护。

建议集中定义:

  • action buffer layout
  • telemetry buffer layout
  • cut-link record layout
  • marker record layout
  • force torque sign convention
  • body velocity contract

运动状态契约

即使短期只做 2D 圆柱旋转,也建议按最终形式设计:

状态 建议字段
平移 vx vy vz
角运动 wx wy wz 或 2D 的 omega 特化视图
参考点 cx cy cz
姿态 theta 或旋转表示

不要再把 3D 路径固化为“只读一个 z 轴 omega”。

第二阶段推荐顺序

阶段 2A

先把职责边界拆开,不追求新功能。

  • ObjectManager
  • 建立 BodyRegistry
  • 建立 clean runtime buffer
  • 建立单独的 geometry preprocess 层
  • 把“对象管理”和“cut-link 产出”分开

验收标准:

  • body 不再直接知道具体 LBM kernel 调度
  • ObjectManager 不再承担几何、obs、state、flag 全部职责
  • objects.py 不再直接输出某一种 boundary method 专用打包格式

阶段 2B

重构 curved boundary 数据链。

  • 定义统一 cut-link record
  • 让圆柱先输出新 record
  • 让 Bouzidi kernel 消费新 record
  • 把现有 CurvedLinkSoA 从“Bouzidi 专用”改成“通用 cut-link buffer`
  • donor 与 fallback 的契约集中写入注释,不额外增加复杂语义保护代码

验收标准:

  • kernel 不需要知道几何来源
  • host 侧可以替换 cut-link builder 而不改 kernel 接口
  • 读 builder 与 kernel 时,不需要跨很多文件才能理解 donor 和 fallback 的基本语义

阶段 2C

为 IBM 留入口。

  • 定义 marker record
  • 预留独立 preprocess 和 runtime buffer
  • 暂不实现完整 IBM 细节,只把架构位置留好

验收标准:

  • IBM 不需要重写 body 骨架
  • IBM 与 Bouzidi 可以共存于同一 body 系统

阶段 2D

补文档与契约说明。

  • 当前能力
  • 预留能力
  • 不支持项
  • 2D 与 3D 差异
  • TRT 与 plain Bouzidi 的限制

不建议做的事

  • 不要继续强化万能 ObjectManager
  • 不要让几何对象直接生成某一种边界格式专用 SoA
  • 不要把 curved boundary 和 Bouzidi 永久绑定
  • 不要在 3D 运动契约上继续堆占位特例
  • 不要在第二阶段把多相、IBM、粒子一起全做完
  • 不要为了“自动保证语义”继续增加很多隐式逻辑分支,优先用集中注释把契约写清楚
  • 不要引入必须跨很多文件来回跳转才能理解的 host-kernel 组织方式

第二阶段完成后的理想状态

代码层面

  • 文件更短
  • 模块职责更单一
  • host-device contract 更显式
  • kernel 更专注于数值操作
  • geometry 与 boundary method 解耦

扩展层面

后续可自然扩展到:

  • 离散几何 cut-link
  • IBM marker 链路
  • 粒子和刚体共用 body runtime
  • 多相流对 body 的额外 coupling

维护层面

后续新增功能时,优先在对应层增加文件,而不是回到单个 manager 中继续堆逻辑。

建议的执行方式

第二阶段执行前,先固定一个简短设计约束:

  • 单文件不过长
  • 新增模块必须有明确职责说明
  • 任何 host-device 数据结构必须有集中定义
  • 新接口先定义契约,再写 kernel
  • 能通过新增 builder 解决的问题,不要回写到 geometry 类中
  • donor、fallback、time-layer 等关键数值语义必须在少数固定位置集中注释说明
  • 优先保持文件短和职责单一,不为“保险”堆太多诊断与保护代码

这个阶段的核心产出不是新功能,而是一个能长期承载新功能的骨架。