9.9 KiB
目标
第二阶段不再以补丁式修 bug 为主,而是重建 body 与 LBM 之间的模块边界,形成可持续扩展到 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 这类数值语义散落在不同文件中,读代码时必须来回跳转才能确认。当前项目更适合把这些语义集中写进少数注释位置,而不是继续加更多隐式保护逻辑。
第二阶段的目标架构
顶层模块
保持两大物理模块:
LBMbody
但它们之间不直接互相了解实现细节,而通过显式中间数据结构耦合。
推荐分层
| 层级 | 职责 | 不应负责 |
|---|---|---|
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 专用 SoApreprocess先产出统一 cut-link 结果,再由更薄的一层做运行时打包runtime不回头参与几何判断- 单文件保持简短,避免再出现一个文件同时含几何、打包、上传、观测解释四类职责
推荐的 LBM 边界
LBM 应该看到什么
LBM 只应看到这些输入:
flagcut-link recordsIBM marker recordsruntime paramsobs 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 等关键数值语义必须在少数固定位置集中注释说明
- 优先保持文件短和职责单一,不为“保险”堆太多诊断与保护代码
这个阶段的核心产出不是新功能,而是一个能长期承载新功能的骨架。