From daef03c3fc8269437a6e5b5a9fac4969d4c9b883 Mon Sep 17 00:00:00 2001 From: Yu Hao Date: Sat, 12 Sep 2026 10:04:57 +0800 Subject: [PATCH] docs: remove completed implementation plans --- docs/nopbc-cv-sits-refactor-plan.md | 602 ------------------ docs/pbc-nopbc-boundary-decoupling-plan.md | 122 ---- .../virtual-atoms-non-center-refactor-plan.md | 401 ------------ 3 files changed, 1125 deletions(-) delete mode 100644 docs/nopbc-cv-sits-refactor-plan.md delete mode 100644 docs/pbc-nopbc-boundary-decoupling-plan.md delete mode 100644 docs/virtual-atoms-non-center-refactor-plan.md diff --git a/docs/nopbc-cv-sits-refactor-plan.md b/docs/nopbc-cv-sits-refactor-plan.md deleted file mode 100644 index f5224d56..00000000 --- a/docs/nopbc-cv-sits-refactor-plan.md +++ /dev/null @@ -1,602 +0,0 @@ -# NOPBC、CV 与 SITS 解耦修改计划 - -## 1. 文档状态 - -- 目标分支:`lab/sidereus-ai` -- 源码基线:`3ca40fc5ddca069d42547467b45dc3f2e6347949` -- 文档性质:设计与实施计划,不代表功能已经修改或通过验收 -- 讨论范围:NOPBC、CV/偏置调度、CV 边界语义、全体系 SITS、H5 SITS 配置时序 - -接口更新:四个 PR 现使用单一 Boundary;第 3、4 节是上述旧基线的诊断记录, -不能作为修改后源码状态。实际边界所有权和逐模块接口以 -`pbc-nopbc-boundary-decoupling-plan.md` 为准,未实现下文示例中的独立 CV 上下文类。 - -## 2. 结论摘要 - -本次修改应完成四件事: - -1. 将 CV、steer、CV restraint 和 metadynamics 的执行从 PME/PM 进程条件中拆出。 -2. 为 CV 引入明确的边界条件策略;NOPBC 下不再隐式使用周期最小镜像。 -3. 正式支持 NOPBC 与全体系 SITS(`atom_numbers = "ITS"` 或 `"ALL"`)组合。 -4. 在 H5/legacy SITS 配置完全解析之后统一执行兼容性检查,保证 NOPBC 下的 selective SITS 始终明确拒绝。 - -本次不支持 NOPBC 与 selective SITS 的组合,也不实现 NOPBC selective energy/force decomposition。 - -目标支持矩阵如下: - -| 功能 | PBC | NOPBC | -|---|---:|---:| -| 无 SITS | 支持 | 支持 | -| 全体系 SITS:`ITS`/`ALL` | 支持 | 支持 | -| Selective SITS:整数、文件或 H5 `atom_indices` | 支持 | 明确拒绝 | -| distance/displacement/angle/dihedral CV | 周期最小镜像 | 直接笛卡尔位移 | -| position/RMSD CV | 保持当前定义 | 保持当前非周期坐标定义 | -| scaled-position CV | 支持 | 默认拒绝,除非以后定义参考盒 | -| box-length CV | 支持 | 默认拒绝,除非以后定义参考盒 | - -## 3. SPONGE 当前的 NOPBC 实现 - -### 3.1 配置入口和硬限制 - -`pbc` 默认为 `true`。当输入设置 `pbc = false` 时, -`periodic_box_condition_information::Initial` 仍依次执行: - -1. `No_PBC_Check`; -2. `PBC_Check`; -3. 保存 `cell0`。 - -也就是说,NOPBC 并不会跳过 cell/rcell 的构造。当前实现仍使用输入坐标尾部的 -`box_length` 和 `box_angle` 构造一个可逆的 `cell` 与 `rcell`。 - -`No_PBC_Check` 当前施加以下限制: - -- 只允许单进程;`MPI_size > 1` 直接报错。 -- `cutoff < 100 Å` 时给出警告,但不会终止。 -- 三个方向的 box length 都必须至少为 `900 Å`。 -- 不允许 NPT。 -- SITS 检查直接读取 controller 中的 legacy 字符串;只有 `ITS`/`ALL` 被放行。 - -源码入口: - -- `SPONGE/MD_core/pbc.hpp:3-101` -- `SPONGE/MD_core/MD_core.cpp:332-369` - -### 3.2 NOPBC 不是“没有 box”,而是“大虚拟盒 + 非周期核心非键力” - -当前实现保留一个至少 900 Å 的虚拟盒,主要是为了满足大量仍接收 -`cell/rcell` 的公共接口。真正的 NOPBC 差异发生在核心非键力内核: - -```cpp -VECTOR dr = crd[atom_j] - crd[atom_i]; -``` - -LJ 和 Coulomb NOPBC 内核不调用 minimum-image,也不根据 cell 折返位移。 -它们仍执行以下逻辑: - -- 遍历 `i < j` 的原子对; -- 查询 exclusion list; -- 使用直接笛卡尔距离; -- 只计算 `r < cutoff` 的相互作用; -- 对两个原子累加大小相等、方向相反的力; -- 需要势能时同时累加 atom energy 和模块能量。 - -因此,大盒并不会取消 cutoff。若希望近似完整的真空全库仑相互作用,cutoff 本身必须足够大; -这也是当前代码在 cutoff 小于 100 Å 时发出警告的原因。 - -当前 NOPBC 非键实现是全原子对遍历,而不是 PBC neighbor-list 路径,计算复杂度近似为 -`O(N²)`。 - -源码入口: - -- `SPONGE/NO_PBC/Lennard_Jones_force_No_PBC.cpp:6-123` -- `SPONGE/NO_PBC/Coulomb_Force_No_PBC.cpp:3-96` - -### 3.3 初始化分叉 - -`Main_Initial` 在 `md_info.pbc.pbc` 上分成两条力场初始化路径。 - -PBC 路径初始化: - -- PBC LJ 和 soft-core LJ; -- PME/Particle Mesh; -- pairwise force; -- PBC NB14; -- SITS; -- selective SITS 的 dihedral、NB14 和 CMAP helper; -- 后续的 neighbor list 和 solvent LJ。 - -NOPBC 路径初始化: - -- `LJ_NOPBC`; -- `CF_NOPBC`; -- 可选 GB; -- 使用 NOPBC LJ 参数表的普通 NB14; -- SITS 核心。 - -NOPBC 不初始化 PME、PBC LJ、selective SITS helper 和 PBC neighbor list。 - -bond、angle、Urey-Bradley、CMAP、dihedral、improper、listed force 等公共 bonded -模块在分叉之后统一初始化。它们的接口仍会收到 `cell/rcell`,因此是否使用周期位移由各模块 -自己的实现决定;当前“大虚拟盒”在这里充当兼容层,而不是显式的边界策略。 - -源码入口: - -- `SPONGE/main.cpp:1160-1205` -- `SPONGE/main.cpp:1249-1282` - -### 3.4 每步力计算 - -单步力计算的主要顺序是: - -1. 根据 SITS 需求设置势能计算标志。 -2. 调用 `pm.Get_Atoms`。 -3. 清零 domain-decomposition 力和 virial。 -4. 更新 ghost 与 neighbor list。 -5. 计算 ReaxFF(若启用)。 -6. 调用 NOPBC LJ、NOPBC Coulomb 和可选 GB。 -7. 调用 PME excluded-force 接口。 -8. 计算 bonded、NB14、wall、plugin、restraint 等公共贡献。 -9. 计算 PME reciprocal、CV 和 CV bias。 -10. 调用 SITS 更新和增强。 -11. 回传虚原子力。 - -其中多个 PBC/PM 公共调用在 NOPBC 下仍会出现,但依靠对象的 `is_initialized` 或 -`PM_MPI_size` 守卫变为 no-op: - -- `neighbor_list.Update` 在未初始化时立即返回; -- PME reciprocal 和 excluded-force 要求 `pm.is_initialized`; -- PM 坐标/力通信在 `PM_MPI_size == 0` 时返回。 - -这种“无条件调用 + 对象内部 no-op”让公共主循环比较统一,但也造成了模块能力不透明: -调用者无法从控制流直接判断功能是真正执行了还是静默跳过。当前 CV/PME 问题就是该模式的 -一个具体后果。 - -源码入口: - -- `SPONGE/main.cpp:1348-1635` -- `SPONGE/neighbor_list/neighbor_list.cpp:834-841` -- `SPONGE/PM_force/PM_force.cpp:1067-1074` -- `SPONGE/PM_force/PM_force.cpp:1816-1824` - -### 3.5 PME/PM 与 NOPBC 进程状态 - -NOPBC 不调用 `pm.Initial`,全局 `pm` 对象保持未初始化,其 `PM_MPI_size` 为 0。 -`Main_Process_Management` 随后把该值复制到 controller: - -```text -MPI_size = 1 -PP_MPI_size = 1 -PM_MPI_size = 0 -PM_MPI_rank = -1 -``` - -NOPBC 又在更早阶段禁止多进程,因此当前合法 NOPBC 运行只有一个 PP 进程,没有 PM 进程。 - -这本身不妨碍 CV。单进程 NOPBC 的 `dd.crd` 已经是完整坐标,`dd.frc` 也是可直接累加的 -完整力缓冲。真正的问题是主循环把 CV 和 PME reciprocal 放在同一个 -`PM_MPI_size == 1` 条件中,导致 NOPBC 的 CV 被整体跳过。 - -源码入口: - -- `SPONGE/main.cpp:1535-1582` -- `SPONGE/main.cpp:2147-2173` -- `SPONGE/PM_force/PM_force.cpp:353-374` - -### 3.6 坐标、轨迹和 box 输出 - -NOPBC 输出时: - -- 不执行 PBC molecule coordinate mapping; -- 直接输出未包裹的原始坐标; -- H5MD box 仍写入对角 `box_length`,因此输出中仍能看到大虚拟盒; -- molecule 模块在 NOPBC 下不建立用于周期重映射的状态。 - -所以当前 NOPBC 的坐标会自由漂移,不会被重新映射回虚拟盒。任何仍调用 periodic minimum-image -的上层模块,最终都可能在原子跨越虚拟盒半长时与 NOPBC 力场产生语义分歧。 - -源码入口: - -- `SPONGE/main.cpp:1919-1932` -- `SPONGE/MD_core/output.hpp:38-68` -- `SPONGE/MD_core/mol.hpp:891-894` - -### 3.7 当前 NOPBC 架构的本质 - -当前设计可以概括为: - -```text -输入中的大 box - ├── 构造 cell/rcell,供公共接口继续运行 - ├── 不用于 NOPBC LJ/Coulomb 的位移折返 - └── 仍可能被 CV、bonded、restraint 等上层模块使用 - -NOPBC 核心非键力 - ├── 直接笛卡尔位移 - ├── 全原子对遍历 - ├── exclusion list - └── 有限 cutoff - -运行条件 - ├── 单进程 PP - ├── PM 未初始化 - ├── 无 neighbor list - └── 非 NPT -``` - -因此,NOPBC 当前是一个独立非键后端,但还不是贯穿所有模块的统一边界条件策略。 - -## 4. 已确认的问题 - -### 4.1 CV 与 PME/PM 调度耦合 - -主循环当前只有在: - -```cpp -CONTROLLER::MPI_size == 1 && CONTROLLER::PM_MPI_size == 1 -``` - -时才执行 PME reciprocal、CV print、steer、CV restraint 和 metadynamics。 - -NOPBC 的 `PM_MPI_size` 为 0,因此 CV 可以成功解析和初始化,却不会在运行时执行。 -PME reciprocal 函数内部已经具有 `is_initialized` 守卫,因而没有必要用 PM 进程条件保护整段 CV。 - -### 4.2 CV 边界语义与 NOPBC 力场不一致 - -distance、displacement、angle 和 dihedral CV 无条件使用 minimum-image displacement; -NOPBC LJ/Coulomb 使用直接位移。大虚拟盒只能延迟问题,不能定义正确语义。 - -position 和当前 RMSD 实现主要使用原始坐标;scaled-position 与 box-length 则直接依赖 -`cell/rcell`,在 NOPBC 下没有明确物理定义。 - -### 4.3 全体系 SITS 支持未收尾 - -全体系 SITS 在每步更新中直接复制系统总能量、总力和总 virial 作为增强对象: - -```text -U_enhanced = U_total -F_enhanced = F_total -V_enhanced = V_total -``` - -因此其核心算法不依赖 PBC、PME、neighbor list 或 minimum-image,架构上可以支持 NOPBC。 - -当前缺口包括: - -- 无 NOPBC + `ITS/ALL` 的运行回归测试; -- NOPBC 下 SITS step output 路径不完整; -- H5 配置可能绕过当前兼容性检查; -- 尚未把支持矩阵写入用户文档。 - -### 4.4 Selective SITS 必须在 NOPBC 下稳定拒绝 - -Selective SITS 需要单独构造被增强部分的能量、力和 virial。当前 selected contribution 路径 -依赖 PBC LJ、soft-core LJ、neighbor list、PME beta、minimum-image,以及只在 PBC 分支初始化的 -dihedral/NB14/CMAP helper。 - -NOPBC 没有等价的 selected contribution provider。若绕过检查,运行可能使用不完整的 -`U_enhanced/F_enhanced`,属于错误物理结果,而不仅仅是缺少一个功能。 - -### 4.5 H5 SITS 配置检查时序错误 - -当前 `pbc.Initial` 在 `sits.Initial` 之前执行,而 typed H5 SITS 的 mode 和 atom selection 是在 -`sits.Initial` 内由 `sits_h5_input.hpp` 加载并注入 controller。 - -因此 `No_PBC_Check` 只能可靠看到 legacy controller 字段,不能可靠判断 H5 配置最终是: - -- 全体系 `ITS/ALL`;还是 -- selective `atom_indices`/整数选择。 - -边界兼容性检查必须发生在统一配置解析之后。 - -## 5. 目标设计 - -### 5.1 显式边界条件策略 - -沿用 PR1 的边界策略,不再定义第二套类型: - -```cpp -enum class BoundaryPolicy : std::uint8_t -{ - Open = 0, - Periodic = 1 -}; -``` - -`pbc=false` 产生 `BoundaryPolicy::Open`。统一的 `md_info.pbc.boundary` 持有 -policy/cell/rcell,CV 接收它,不通过盒长推断边界类型,也不另存一套盒子。 - -### 5.2 独立的 CV 执行上下文 - -将 CV/bias 调用从 PME reciprocal 调用中拆出。实际实现保留直接调度, -使用 CV_MPI_rank 表达坐标所有权,并向计算函数传同一 Boundary; -不新增含独立盒子副本的 CVExecutionContext。 - -坐标所有权策略: - -| 运行方式 | CV 坐标/力缓冲 | -|---|---| -| 单进程 PBC | `dd.crd` / `dd.frc` | -| 单进程 NOPBC | `dd.crd` / `dd.frc` | -| PP/PM 分离 | `pm.g_crd` / `pm.g_frc`,完成后回传 | - -PME reciprocal 继续根据 PM/PME 自身初始化状态执行,不再决定 CV 是否执行。 - -### 5.3 CV 几何按策略计算 - -提供统一 displacement primitive: - -```cpp -VECTOR Get_Displacement(a, b, boundary); -``` - -- `BoundaryPolicy::Periodic`:保持当前 minimum-image。 -- `BoundaryPolicy::Open`:返回 `a - b`。 - -distance、displacement、angle、dihedral 统一使用该 primitive。禁止在各 CV 内自行根据 box 长度 -猜测边界类型。 - -scaled-position 和 box-length CV 在 NOPBC 下先明确报 capability error;以后若要支持,应额外引入 -“参考盒”概念,而不是复用 NOPBC 的虚拟大盒。 - -### 5.4 解析后的 SITS 能力模型 - -在 legacy/H5 配置统一解析后,得到稳定的 selection scope: - -```cpp -enum class SitsSelectionScope -{ - AllSystem, - Selective -}; -``` - -兼容性规则: - -```text -PBC + AllSystem -> allow -PBC + Selective -> allow -NOPBC + AllSystem -> allow -NOPBC + Selective -> reject with an explicit error -``` - -不要继续在 `pbc.hpp` 中直接检查 `SITS_atom_numbers` 字符串。推荐在 SITS 配置解析完成后调用: - -```cpp -sits.Validate_Boundary_Compatibility(boundary_policy); -``` - -错误信息应包含最终解析来源和 scope,例如: - -```text -Selective SITS is not supported with pbc=false. -Resolved selection source: H5 /sits/SITS/atom_indices. -Use atom_numbers = "ALL" or "ITS" for all-system SITS. -``` - -### 5.5 全体系 SITS 的 NOPBC 路径 - -全体系 SITS 继续复用现有 `Update_And_Enhance` 的 non-selective 分支,不新增 NOPBC 专用 SITS -kernel。SITS 只消费已经完成的 total state: - -```cpp -sits.Update_And_Enhance(step, total_energy, need_pressure, - total_virial, total_force, beta0); -``` - -需要修复的是生命周期、输出和测试,而不是 SITS 数学公式。 - -## 6. 分阶段修改计划 - -### 阶段 0:建立失败基线 - -目标:在修改运行逻辑前,把当前缺陷固化为最小测试。 - -- 增加单进程 NOPBC + distance CV 测试,证明当前 CV 被 PM gate 跳过。 -- 增加 NOPBC + steer CV 测试,检查修改前没有预期偏置力。 -- 增加 H5 selective SITS + NOPBC 测试,证明当前配置时序可以绕过 legacy guard。 -- 保存 PBC CV/SITS 基线,防止后续改变已有周期语义。 - -验收:测试应稳定复现问题,而不是只检查程序是否成功退出。 - -### 阶段 1:拆分 CV 与 PME 调度 - -主要修改位置: - -- `SPONGE/main.cpp` -- 必要时新增 CV execution helper 文件 - -步骤: - -1. 将 PME reciprocal 调用与 CV/bias 调用拆成两个独立函数或代码块。 -2. 单进程时无论 PM 是否初始化,都使用 `dd.crd/dd.frc` 执行 CV。 -3. 保留 PP/PM 分离下的全局坐标和力回传路径。 -4. 保留 `vatom.Coordinate_Refresh_CV` 和 `Force_Redistribute_CV` 的调用顺序。 -5. 确保 metadynamics H5 diagnostic 写出不再依赖 PME 是否执行。 - -验收: - -- NOPBC CV 从 `****` 变为有限值; -- steer/restrain/meta 对力和能量产生可验证变化; -- PBC 单进程及 PP/PM 行为不回归; -- 无 CV 时不增加可测量的运行副作用。 - -### 阶段 2:引入 CV 边界策略 - -主要修改位置: - -- `SPONGE/MD_core/pbc.h` / `pbc.hpp` -- `SPONGE/collective_variable/CV.h` 及实现 -- `SPONGE/collective_variable/simple_cv.cpp` -- CV controller、steer、restrain_cv、metadynamics 的调用接口 -- 可能复用或扩展 `third_party/jit/jit_matrix.h` 的 displacement helper - -步骤: - -1. 定义 `BoundaryPolicy`,由 MD 配置唯一解析。 -2. 将 policy 传入 CV compute 路径。 -3. distance/displacement/angle/dihedral 根据 policy 选择 displacement。 -4. 为 scaled-position 和 box-length 增加 NOPBC capability error。 -5. 检查虚原子 CV 坐标刷新及力回传是否需要同一策略。 -6. 文档化各 CV 在 PBC/NOPBC 下的定义。 - -验收: - -- 对同一对原子构造超过虚拟盒半长的位移:PBC CV 折返,NOPBC CV 不折返; -- angle/dihedral 在手工笛卡尔几何上匹配参考值; -- CV gradient 与有限差分一致; -- steer、CV restraint、meta 的偏置力方向与 boundary policy 一致; -- PBC 原有验证测试保持通过。 - -### 阶段 3:统一 H5/legacy SITS 配置与能力检查 - -主要修改位置: - -- `SPONGE/SITS/sits_h5_input.hpp` -- `SPONGE/SITS/SITS.h` / `SITS.cpp` -- `SPONGE/MD_core/pbc.hpp` -- `SPONGE/main.cpp` - -步骤: - -1. 将最终 selection scope 作为 SITS 解析结果保存,而不是运行时反复读取字符串。 -2. H5 和 legacy 输入映射到同一个 `SitsSelectionScope`。 -3. 从 `No_PBC_Check` 删除基于 `SITS_atom_numbers` 字符串的判断。 -4. 在 SITS 配置完全解析后执行 boundary capability validation。 -5. selective + NOPBC 在初始化阶段稳定报错,不进入任何力计算。 -6. 错误信息报告 selection source,便于诊断 H5/legacy 配置。 - -验收: - -- legacy `ITS`、`ALL` 与 H5 policy `ITS`、`ALL` 均在 NOPBC 下通过; -- legacy 整数、`atom_in_file` 与 H5 `atom_indices` 均在 NOPBC 下以同类错误拒绝; -- PBC selective SITS 继续初始化全部 helper; -- disabled H5 SITS 不触发兼容性错误。 - -### 阶段 4:正式支持 NOPBC + 全体系 SITS - -主要修改位置: - -- `SPONGE/main.cpp` -- `SPONGE/SITS/SITS.cpp` -- output/H5 SITS 路径 -- 输入参考文档 - -步骤: - -1. 明确 non-selective SITS 使用 total energy/force/virial。 -2. 检查 NOPBC 下 `need_potential` 始终满足 SITS 更新要求。 -3. 将普通 `sits.Step_Print` 从 PBC-only 输出分支移到 SITS 生命周期公共位置。 -4. 验证 legacy Nk trajectory/restart 输出。 -5. 验证 H5 Nk observable 和 native restart state。 -6. 在用户文档中写明支持矩阵和 selective 限制。 - -验收: - -- NOPBC `observation`:`h_factor = 1`,力与无 SITS 基线一致; -- NOPBC `iteration`:Nk 在配置间隔更新,所有输出为有限值; -- NOPBC `production`:可从 legacy 和 native H5 restart 恢复并连续运行; -- `ITS` 与 `ALL` 行为一致; -- 修改前后的 PBC 全体系 SITS 在相同输入下保持数值一致。 - -### 阶段 5:文档、清理与完整回归 - -- 更新 `docs/input-reference/core.md` 中 NOPBC 的精确限制。 -- 更新 `docs/input-reference/collective-variables.md` 中各 CV 的 boundary semantics。 -- 更新 `docs/input-reference/enhanced-sampling.md` 中 SITS 支持矩阵。 -- 删除不再使用的旧字符串 guard 和重复调度分支。 -- 运行格式、编译、focused tests、H5 tests、PBC 回归及 NOPBC 组合测试。 - -## 7. 测试矩阵 - -### 7.1 CV 和偏置 - -| Boundary | CV/功能 | 核心断言 | -|---|---|---| -| PBC | distance/angle/dihedral | minimum-image 结果不回归 | -| NOPBC | distance/angle/dihedral | 直接位移结果与参考几何一致 | -| NOPBC | CV print | 输出有限值而非 `****` | -| NOPBC | steer | 力差与解析梯度一致 | -| NOPBC | CV restraint | 力、势能与参考公式一致 | -| NOPBC | metadynamics | hill/bias/force 正常更新 | -| NOPBC | scaled-position | 初始化阶段明确拒绝 | -| NOPBC | box-length | 初始化阶段明确拒绝 | - -每个几何测试至少包含一个超过虚拟盒半长的坐标差,避免“大盒下碰巧相同”的假阳性。 - -### 7.2 SITS - -| Boundary | Selection | 输入来源 | 预期 | -|---|---|---|---| -| PBC | `ITS`/`ALL` | legacy/H5 | 运行通过 | -| NOPBC | `ITS`/`ALL` | legacy/H5 | 运行通过 | -| PBC | selective integer | legacy/H5 | 运行通过 | -| PBC | selective atom file/indices | legacy/H5 | 运行通过 | -| NOPBC | selective integer | legacy/H5 | 初始化拒绝 | -| NOPBC | selective atom file/indices | legacy/H5 | 初始化拒绝 | - -全体系 NOPBC 至少覆盖: - -- observation; -- iteration; -- production; -- fresh run; -- legacy restart; -- native H5 restart; -- Nk/log state 连续性; -- mdout、legacy 文件和 H5 dataset 输出。 - -### 7.3 回归边界 - -- CPU 与 GPU 至少各运行一个 NOPBC CV 和全体系 SITS smoke case。 -- PBC CV validation 全量通过。 -- 现有 SITS iteration-to-production performance/functional case 通过。 -- H5 input equivalence 和 runtime restart closure 通过。 -- 不以“成功退出”代替数值断言。 - -## 8. 风险与非目标 - -### 8.1 本次非目标 - -- NOPBC 多进程支持。 -- NOPBC NPT。 -- Selective SITS 的 NOPBC contribution backend。 -- 删除 NOPBC 的 900 Å 虚拟盒兼容层。 -- 全面重构所有 bonded/restraint 模块的边界策略。 -- 改变 SITS 的 Nk、feedback bias、AMD 或 GaMD 数学公式。 - -### 8.2 主要风险 - -1. **数值语义风险**:仅让 CV 成功执行而不修改 displacement 会产生更隐蔽的错误结果。 -2. **调用顺序风险**:CV 必须在正确坐标刷新后执行,偏置后必须回传虚原子力。 -3. **并行回归风险**:拆调度时不能破坏 PP/PM 的全局坐标与力通信。 -4. **H5 生命周期风险**:不能只修 legacy guard;typed H5、compatibility config、restart 都要经过同一解析结果。 -5. **输出回归风险**:全体系 SITS 在 NOPBC 下运行成功但不输出 Nk/bias,仍不能视为完整支持。 -6. **假阳性测试风险**:小体系位于 900 Å 盒中心时,周期和非周期 displacement 可能恰好相同。 - -## 9. 完成定义 - -只有同时满足以下条件,才能宣称本计划完成: - -- CV 执行不再由 PME/PM 是否初始化决定; -- CV 的 PBC/NOPBC 几何语义由显式 policy 决定; -- scaled-position/box-length 在 NOPBC 下不会静默使用虚拟盒; -- NOPBC + 全体系 SITS 的 observation/iteration/production 有数值测试; -- NOPBC + selective SITS 对 legacy 和 H5 输入都稳定拒绝; -- H5 restart 和输出连续性经过验证; -- PBC CV、PBC SITS 和 PP/PM 路径无回归; -- 用户文档准确描述最终支持矩阵。 - -## 10. 证据索引 - -- NOPBC 配置、box 构造与限制:`SPONGE/MD_core/pbc.hpp` -- MD 初始化顺序:`SPONGE/MD_core/MD_core.cpp` -- PBC/NOPBC 模块初始化与主循环:`SPONGE/main.cpp` -- NOPBC LJ:`SPONGE/NO_PBC/Lennard_Jones_force_No_PBC.cpp` -- NOPBC Coulomb:`SPONGE/NO_PBC/Coulomb_Force_No_PBC.cpp` -- PM/PME 守卫和进程状态:`SPONGE/PM_force/PM_force.cpp` -- CV 周期位移:`SPONGE/collective_variable/simple_cv.cpp` -- minimum-image primitive:`SPONGE/third_party/jit/jit_matrix.h` -- SITS 核心与 selection:`SPONGE/SITS/SITS.h`、`SPONGE/SITS/SITS.cpp` -- H5 SITS 配置:`SPONGE/SITS/sits_h5_input.hpp` -- NOPBC trajectory/box 输出:`SPONGE/MD_core/output.hpp`、`SPONGE/main.cpp` -- 现有输入文档:`docs/input-reference/core.md`、`collective-variables.md`、`enhanced-sampling.md` diff --git a/docs/pbc-nopbc-boundary-decoupling-plan.md b/docs/pbc-nopbc-boundary-decoupling-plan.md deleted file mode 100644 index 51e38866..00000000 --- a/docs/pbc-nopbc-boundary-decoupling-plan.md +++ /dev/null @@ -1,122 +0,0 @@ -# PBC/NOPBC 边界接口与模块迁移 - -## 状态与范围 - -本文替代早期多结构和快照工厂方案,说明四个 PR 的接口边界。 -PR1 是接口重构;PR2 是 CV/SITS 功能修复;PR3 是虚原子数学修复;PR4 是晶胞几何及 MC 回滚修复。 -支持目标不等于所有配置都已通过科学验收。 - -不增加 NOPBC 近邻表、多体势 NOPBC、MPI NOPBC、选择性 SITS NOPBC; -不修改整分子成像、周期性聚合物识别或质心缩放,不增加插件 ABI 或 H5 schema。 - -## 单一数据结构 - -```cpp -enum class BoundaryPolicy : std::uint8_t { Open = 0, Periodic = 1 }; -struct Boundary -{ - BoundaryPolicy policy = BoundaryPolicy::Open; - LTMatrix3 cell; - LTMatrix3 rcell; -}; -``` - -MD_INFORMATION::periodic_box_condition_information::boundary 是运行时 policy/cell/rcell 的唯一持有者。 -不再另外保存同名矩阵、独立可变的盒子副本或包装工厂。 -原有 pbc 布尔配置入口保留,初始化时确定 policy;控压不改变 policy。 -cell0 是网格重建的历史比较基准,不是另一份当前盒子状态。 - -sys.box_length/box_angle 保留为输入、输出和控压接口所需的几何元数据。 -初始化先读取坐标/重启元数据,再构造 boundary;Update_Box 更新矩阵并反写元数据。 -Rerun 的新帧元数据通过原有 Main_Box_Change 路径应用。不重写 I/O 协议, -也不把盒长数值当作物理边界模式。 - -主计算入口用 const Boundary& 引用持有者;盒子更新后,后续调用自然读取新值。 -CPU/CUDA/HIP kernel 按值接收调用时的参数,不能把主机引用作为设备指针; -模块不跨步缓存边界副本。 - -## 位移、映射和网格索引 - -```cpp -Get_Displacement(a, b, boundary); -Get_Displacement(a, b, boundary); -Get_Displacement(a, b, boundary); -Wrap_Coordinate(coordinate, boundary); -Get_Mesh_Index_Displacement(index_a, index_b, scaler); -``` - -通用位移在 Open 下返回 a-b,在 Periodic 下保持原 fractional rounding 公式。 -固定策略模板不读取运行时 policy,仅用于已经确认支持该模式的计算路径。 -这不是更换三斜角最小镜像算法,也不保证任意倾斜晶胞中的最短欧氏镜像。 - -Wrap_Coordinate 在 Open 下返回原坐标,在 Periodic 下映射回主盒。 -整数网格位移仍是独立数学操作,不接收物理边界策略。 -自动微分中带梯度的盒长参数属于导数输入,不是另一个运行时盒子持有者。 - -Host/JIT 使用同一 Boundary 定义和位移公式;listed/pairwise JIT ABI 直接传 Boundary。 -Listed force 保留原正交盒长度梯度算法,本次不扩展其三斜角应力语义。 - -## 盒子更新顺序 - -保留 Main_Box_Change 的生命周期: - -1. 压力控压、MC trial/reject 或 rerun 提交形变。 -2. pbc.Update_Box 更新唯一 boundary 的矩阵以及盒长/盒角。 -3. 按原有选项缩放坐标、速度。 -4. 小变化更新 DD/PM 派生状态,大变化重建近邻网格、PM 和 DD。 -5. 后续力、约束、虚原子和 CV 调用读取当前 boundary。 - -不增加 revision、Prepare/Commit 状态机或跨模块缓存。 -MPI 按原有同步调度在各 rank 更新盒子,不引入跨进程 boundary 指针。 - -## 模块与文件覆盖 - -| 模块/文件 | 处理方式 | -| --- | --- | -| utils/boundary.h、vector.hpp、sad.hpp | 单一 Boundary;位移、映射、网格索引分离 | -| third_party/jit/jit_boundary.h、jit_sadvector.h 等 | Host/JIT 对齐;保留自动微分公式 | -| MD_core/pbc.h、pbc.hpp、main.cpp | 唯一持有者;初始化、控压、rerun、kernel 传参 | -| MD_core/mol.hpp、sys.hpp、output.hpp、rerun.hpp | 读取同一盒子;保留成像、质心和 I/O 语义 | -| bond、angle/Urey_Bradley、dihedral/improper、cmap、nb14 | 通用边界位移;不改能量/力公式 | -| constrain/shake、settle | 坐标约束及速度投影,保留上游 guard 和精度回退 | -| restrain、virtual_atoms | 通用边界参数;虚原子数学及依赖顺序修复在 PR3 | -| collective_variable、bias/steer、restrain_cv、sinkmeta | PR1 迁移参数并保留行为;PR2 修复 Open 策略和调度 | -| Lennard_Jones_force、solvent_LJ、LJ_soft_core | Boundary 贯穿调用;固定 Periodic 位移 | -| PM_force | Boundary 替代成对矩阵参数;网格/FFT 仍读取对应矩阵 | -| neighbor_list/full_neighbor_list | 构建、刷新、溢出重建统一参数;不加 Open 后端 | -| Domain_decomposition | 读取唯一矩阵;分数坐标、域分箱等数学不变 | -| SITS | 选择性周期分量传 Boundary;PR2 允许全体系 NOPBC | -| custom_force/listed_forces、pairwise_force | JIT ABI 同步迁移;pairwise 仍依赖周期近邻表 | -| manybody/SW、EDIP、EAM、Tersoff、reaxff 子模块 | 固定 Periodic 位移,Open 明确拒绝 | -| plugin | API v2 无边界约定,NOPBC 拒绝;不升级 ABI | -| NO_PBC/LJ、Coulomb、generalized_Born | 保留直接笛卡尔计算和专用后端 | -| barostat | 仍仅 PBC;几何和 MC 逆缩放修复在 PR4 | -| thermostat、nve、min、wall | 不需要新增边界对象,积分及绝对坐标外场不变 | - -## 四个 PR 完成后的兼容性范围 - -| 功能 | PBC | NOPBC | -| --- | --- | --- | -| 通用成键力、约束、位置限制 | 支持 | 支持 | -| 虚原子 Type 0–3 | 支持 | 支持 | -| Type 4/加权中心 | 保留原定义 | 保留直接加权定义 | -| 距离、位移、角、二面角、位置/RMSD CV | 支持 | 支持各自定义 | -| scaled-position、box-length CV | 支持 | 拒绝 | -| steer、restrain CV、metadynamics | 随所用 CV | 随所用 CV | -| 全体系 ITS/ALL | 支持 | 支持,具体模式以专项测试为准 | -| 选择性 SITS | 支持 | 拒绝 | -| 周期 LJ/PME、周期近邻表、多体势 | 支持对应后端 | 不支持 | -| NOPBC LJ/Coulomb/GB | 对应 PBC 后端或不适用 | 保留专用实现 | -| listed custom force | 保留原盒型语义 | 支持 | -| pairwise custom force、插件 API v2 | 保留原支持 | 拒绝 | -| 控压、MPI 区域分解 | 保留原支持,MPI 非正交 DD 不支持 | 不支持 | - -## 验证要求 - -- 四个 PR 独立编译,各自保留明确职责及回归。 -- CPU/CUDA 动态/固定策略、坐标映射、盒子更新后再次调用的数值检查。 -- 源码合约禁止旧类型/包装工厂,校验 Host/JIT 公共边界实现一致。 -- 真正编译执行 listed PBC/Open 和 pairwise PBC JIT,与解析力对照。 -- 保留约束探针、CV、十二肽、虚原子、H5 输入与控压回归。 -- 最终栈检查 CPU、CUDA、CPU-MPI;np=3 控压验证区域分解,np=2 仅验证 CV owner。 -- 正确性和性能测量分开报告,不能凭内联或测试通过宣称零性能回退。 diff --git a/docs/virtual-atoms-non-center-refactor-plan.md b/docs/virtual-atoms-non-center-refactor-plan.md deleted file mode 100644 index 9d5d7082..00000000 --- a/docs/virtual-atoms-non-center-refactor-plan.md +++ /dev/null @@ -1,401 +0,0 @@ -# Virtual Atoms 非质心部分修复计划 - -## 1. 文档状态与范围 - -- 目标分支:`fix/nopbc-cv-sits` -- 当前基线:`b1017ae571b8d7abb4dbd1b3c0907f398928141e` -- 文档性质:实施计划,不表示相关问题已经修复或通过验收 -- 主要源码:`SPONGE/virtual_atoms/virtual_atoms.cpp`、`SPONGE/virtual_atoms/virtual_atoms.h` -- 本计划覆盖:force-field virtual atom Type 0、Type 1、Type 2、Type 3,依赖层级、力回传、输入校验、局部化、MPI/update-group 和测试 -- 本计划明确不覆盖:Type 4、`center`、`center_of_mass`、周期质心展开、质心权重语义。上述内容待单独讨论并形成后续方案 - -本文把“虚原子不参与积分”和“虚原子不需要力”区分开:虚原子不保存独立动力学自由度, -但作用在虚原子上的相互作用力必须按坐标映射的雅可比回传给来源原子,随后将虚原子力清零。 - -## 2. 当前模型 - -Type 0–3 都由真实原子或更低层虚原子构造: - -| 类型 | 坐标定义 | 当前边界依赖 | -|---|---|---| -| Type 0 | `x_v=x_1, y_v=y_1, z_v=2h-z_1`,固定平面镜像 | 不使用边界条件 | -| Type 1 | `r_v=r_1+a(r_2-r_1)` | `Get_Displacement(..., boundary)` | -| Type 2 | `r_v=r_1+a(r_2-r_1)+b(r_3-r_1)` | `Get_Displacement(..., boundary)` | -| Type 3 | `r_v=r_1+d u/|u|`,`u=(r_2-r_1)+k(r_3-r_2)` | `Get_Displacement(..., boundary)` | - -坐标按依赖层级正向刷新,力按相反层级逆向回传。单进程初始化阶段先使用全局记录, -进入 domain decomposition 后由 `Get_Local` 建立局部索引。Type 0–3 在 PP 进程上计算, -不绑定 CV owner 或 PM/PME 进程。 - -本次 `BoundaryPolicy` 重构已经使 Type 1–3 的坐标几何能够区分: - -- PBC:使用当前 `cell/rcell` 的 minimum image; -- Open/NOPBC:使用直接笛卡尔位移。 - -下面的问题独立于上述边界接口,属于 virtual-atom 自身的历史正确性和生命周期缺陷。 - -## 3. 已确认问题 - -### 3.1 Type 1 力回传系数相反 - -当前坐标为: - -```text -r_v = r_1 + a (r_2 - r_1) - = (1-a) r_1 + a r_2 -``` - -因此应有: - -```text -F_1 += (1-a) F_v -F_2 += a F_v -F_v = 0 -``` - -当前实现却把 `a F_v` 加到 `atom_1`,把 `(1-a) F_v` 加到 `atom_2`。 -四原子 PBC 运行检查中,`a=0.25` 得到的两个来源原子受力比为 `1:3`,正确结果应为 `3:1`。 - -影响:只要 Type 1 虚原子承受非零相互作用力,真实原子上的力矩和动力学都会错误; -虚原子最终力被正确清零并不能抵消该问题。 - -### 3.2 Type 2 非原子写竞争检测失效 - -初始化阶段使用 `v2_info.local_numbers` 检查同层 Type 2 是否共享来源原子, -但 `local_numbers` 要到 `Get_Local` 后才会填充,初始化时恒为 0。因此 `need_atomic` -实际上不会被置为 `true`,运行时总会选择 `v2_Force_Redistribute_No_Atomic`。 - -当同层多个 Type 2 虚原子共享来源原子时: - -- CPU OpenMP 线程会并发执行非原子 `+=`; -- CUDA/HIP 线程会并发写入同一来源原子的力; -- 结果可能丢失部分力,并随线程调度产生非确定性。 - -### 3.3 层级推导依赖输入顺序 - -当前层级只按输入记录扫描一次。如果子虚原子先于父虚原子出现,父原子的层级仍为 0, -子原子会被错误放入过低层。后续同层并行刷新可能读取尚未更新的虚原子坐标。 - -当前还没有检测: - -- 自依赖; -- 虚原子依赖环; -- 同一 `virtual_atom` 的重复定义; -- 记录顺序不是拓扑序; -- 来源原子和目标原子的负数或越界索引(legacy 路径); -- 一个普通原子被意外覆盖为虚原子。 - -### 3.4 多层虚原子的 MPI/update-group 信息不完整 - -`update_ug_connectivity` 只遍历 `virtual_layer_info[0]`,即只完整连接第一层虚原子和来源原子。 -`Get_Local` 则只判断虚原子是否在当前 rank,随后直接将所有来源索引转换成 `atom_local_id`, -没有验证来源原子是否也在本地。 - -对于单层 TIP4P 一类常见模型,第一层 connectivity 通常可以把虚原子和来源原子放入同一 update group。 -对于嵌套虚原子,父子可能被 domain decomposition 分开,形成 `atom_local_id == -1`、陈旧坐标或越界访问。 - -### 3.5 Type 3 退化构型没有保护 - -Type 3 使用: - -```text -u = (r_2-r_1) + k(r_3-r_2) -r_v = r_1 + d u/|u| -``` - -当 `|u|` 接近 0 时,坐标刷新中的归一化和力回传都会除零。`d=0` 时力回传还会通过 -`rv1 * rv1` 再次产生零除。目前既没有初始化期参数检查,也没有运行期退化几何检查。 - -### 3.6 Type 0 参数契约与实现不一致 - -头文件注释定义 `z_v=2h-z_1`,字段名为 `h_double`。但初始化保存 -`h_double=2*parameter`,坐标核又执行 `z_v=2*h_double-z_1`,实际结果是 -`z_v=4*parameter-z_1`。 - -现有 bundled-I/O oracle 也复现了双重乘 2,因此旧测试会通过。这个问题不能在未确认历史文件格式前 -直接修改,否则可能破坏旧输入。需要先确定 legacy 参数究竟表示平面高度 `h`、`h/2`,还是已有其他约定。 - -### 3.7 输入生命周期和资源管理缺少统一约束 - -legacy loader 主要校验字段数量,不统一校验索引、有限值和拓扑关系;H5 topology reader 的校验更完整, -导致两种输入路径在到达 `VIRTUAL_INFORMATION::Initial` 时不具备相同前置条件。 - -此外,`VIRTUAL_INFORMATION` 使用多组裸 host/device 指针,没有显式清理或重新初始化语义。 -当前主流程通常只初始化一次,但测试、库调用或未来重建路径可能造成重复分配和残留状态。 - -## 4. 目标设计 - -### 4.1 建立统一的非质心虚原子中间表示 - -在分配任何 host/device 数组前,将 legacy、H5/Xponge 输入统一转换为内部定义: - -```cpp -struct VirtualAtomDefinition -{ - int type; - int target; - std::vector sources; - std::vector parameters; -}; -``` - -统一校验完成后,再生成 Type 0–3 的紧凑运行结构。输入来源不再决定校验强弱。 - -### 4.2 用依赖图计算层级 - -处理步骤: - -1. 建立 `target -> definition` 唯一映射; -2. 验证 target/source 索引范围和 arity; -3. 对来源中的虚原子建立有向依赖边; -4. 使用 Kahn 或 DFS 拓扑排序; -5. 明确报告自依赖、环和重复目标; -6. 根据最长依赖路径计算 level; -7. 按 `(level, type)` 生成运行数组。 - -输入文件顺序不得影响计算结果。错误信息应包含虚原子 target、type 和造成问题的 source。 - -### 4.3 坐标和力公式成对维护 - -每一种虚原子必须把坐标定义和力雅可比视为同一功能: - -- Type 0:确认参数契约后固定单一镜像公式; -- Type 1:修正为 `(1-a)` 和 `a`; -- Type 2:保持 `(1-a-b), a, b`; -- Type 3:保持投影雅可比,同时增加退化保护; -- 所有类型在回传后清零目标虚原子力; -- 每一种类型都用有限差分验证 `F_i = -dE/dr_i`,不能只检查总力或虚原子力是否为 0。 - -### 4.4 正确性优先处理 Type 2 并发 - -第一阶段删除 `v2_Force_Redistribute_No_Atomic` 快速路径,Type 2 始终使用原子累加,先建立正确基线。 - -只有在性能数据证明该原子操作构成瓶颈后,才恢复安全优化。可选优化必须根据全局定义记录, -而不是尚未构建的局部表判断同层来源是否互斥;CPU 和 GPU 需要分别验证无数据竞争。 - -### 4.5 明确退化几何策略 - -Type 3 建议同时采用: - -- 初始化期拒绝非有限参数和 `abs(d) <= epsilon`; -- 运行期检查 `u·u <= epsilon²`; -- 发生退化时明确终止并报告 target/source,而不是继续产生 NaN。 - -如果未来需要容忍瞬时退化,应另外定义连续化公式,不能简单将归一化分母截断后宣称物理等价。 - -### 4.6 MPI 局部化必须验证完整依赖闭包 - -`update_ug_connectivity` 应遍历所有层、所有 Type 0–3,并将每个虚原子与全部直接来源加入同一连通分量。 -由传递闭包保证嵌套虚原子的整个依赖链属于同一 update group。 - -`Get_Local` 仍需防御性检查: - -- target 在本地时,所有 source 的 `atom_local_id` 必须非负; -- 条件不满足时初始化或 domain refresh 立即报错; -- 不允许将 `-1` 写入局部虚原子记录; -- `local_atom_numbers` 参数应真正用于范围检查,或者从接口删除。 - -在该逻辑通过双 rank 验证前,应明确把“MPI + 多层虚原子”标记为未正式支持,而不是静默运行。 - -### 4.7 生命周期和资源所有权 - -将每层裸指针的分配、释放和状态复位集中到明确接口: - -```cpp -void Reset(); -void Build_From_Definitions(...); -``` - -要求: - -- `Initial` 开始前状态为空; -- host/device 分配失败时不留下半初始化对象; -- `is_initialized` 只在所有层和局部辅助数组成功创建后设置; -- 如不准备支持重复初始化,则在第二次调用时明确报错; -- `need_atomic`、`local_state_ready`、`max_level` 和 layer vector 不得继承旧值。 - -## 5. 精确文件修改方案 - -### 5.1 `SPONGE/virtual_atoms/virtual_atoms.cpp` - -- 修正 `v1_Force_Redistribute` 的两个权重; -- 删除或暂时停用 `v2_Force_Redistribute_No_Atomic`; -- 为 Type 3 坐标刷新和力回传加入统一退化检查; -- 将当前三遍但顺序相关的初始化改为“统一定义校验 → 拓扑排序 → 分层分配 → 数据上传”; -- 对 legacy 和 Xponge/H5 来源使用相同校验入口; -- `Get_Local` 验证 target/source 局部索引; -- `update_ug_connectivity` 遍历所有层,不再只读取第 0 层; -- 明确 Type 0 参数转换只发生一次;最终公式取决于第 7 节的兼容性决定; -- 保持 `Coordinate_Refresh` 正序逐层、`Force_Redistribute` 逆序逐层的生命周期; -- 不在本文件中修改 Type 4/质心逻辑,避免与后续质心设计混合。 - -### 5.2 `SPONGE/virtual_atoms/virtual_atoms.h` - -- 修正文档公式,使参数名、存储值和运行公式一致; -- 将拼写错误的内部 `*_INFROMATION` 逐步更名为 `*_INFORMATION`; -- 增加统一 definition/validation/build 辅助类型或声明; -- 增加 Reset/析构或明确的一次性初始化约束; -- 如保留 Type 2 优化,使用每层冲突信息而不是全局模糊布尔值; -- Type 4 结构保持不动,等待独立方案。 - -### 5.3 `SPONGE/xponge/load/native/virtual_atoms.hpp` - -- loader 继续负责解析文本,但不再把“成功读出字段”当成“定义有效”; -- 保留行号,为后续统一校验错误提供输入位置; -- 拒绝额外截断字段、非有限参数和无效整数; -- 索引、重复目标和依赖图校验交给统一验证层,避免 legacy/H5 重复实现不同规则。 - -### 5.4 `SPONGE/utils/h5md/topology_native_h5_reader.hpp` - -- 保留现有 arity、offset 和索引范围检查; -- 补充非有限参数检查; -- 将重复目标、环和普通原子覆盖规则与 runtime 统一; -- H5 reader 可以提前失败,但 runtime 统一验证仍必须执行,不能依赖特定输入入口。 - -### 5.5 `SPONGE/main.cpp` 与 domain/update-group 路径 - -- 保持 Type 0–3 在 PP rank 上进行坐标刷新和力回传; -- 初始化顺序仍为 virtual atom 建图后,再建立 update group 和 domain decomposition; -- 必要时给 `VIRTUAL_INFORMATION::Get_Local` 传入 rank/controller 信息,以输出可定位的局部依赖错误; -- 不改变 CV owner/PME 调度;该部分属于 Type 4/质心后续方案。 - -### 5.6 测试与 CI - -- 新增 `tests/virtual_atoms/`:纯几何、雅可比、图校验和非法输入单元测试; -- 更新 `tests/CMakeLists.txt` 纳入 virtual-atoms 测试; -- 新增 `benchmarks/validation/virtual_atoms/tests/`:CPU/CUDA 和 MPI 运行级测试; -- 更新 `pixi.toml`,增加 `vali-virtual-atoms` 和 `vali-virtual-atoms-mpi`; -- 更新 `.github/workflows/benchmark.yml`,在 CPU、CUDA、CPU-MPI 中运行相应测试; -- 更新 bundled-I/O virtual-atom oracle,使其验证精确来源原子受力,而不只是检查“真实原子力非零”; -- Type 0 oracle 在参数契约决定后再更新,并明确记录兼容行为。 - -## 6. 测试矩阵 - -### 6.1 每种类型的基本测试 - -| 测试 | Type 0 | Type 1 | Type 2 | Type 3 | -|---|---:|---:|---:|---:| -| 坐标解析解 | 必须 | 必须 | 必须 | 必须 | -| 虚原子最终力为 0 | 必须 | 必须 | 必须 | 必须 | -| 来源原子精确力系数 | 必须 | 必须 | 必须 | 必须 | -| 有限差分雅可比 | 必须 | 必须 | 必须 | 必须 | -| CPU/CUDA 一致性 | 必须 | 必须 | 必须 | 必须 | -| PBC 跨盒来源坐标 | 不适用/单独定义 | 必须 | 必须 | 必须 | -| NOPBC 大位移 | 不适用/绝对平面 | 必须 | 必须 | 必须 | - -### 6.2 Type 2 并发测试 - -- 两个同层 Type 2 共享 `from_1`; -- 分别共享 `from_2`、`from_3` 和交叉来源; -- CPU 使用多个 OpenMP 线程重复运行; -- CUDA/HIP 重复运行并检查确定性; -- 与串行参考力逐分量比较; -- 检查来源总力和虚原子力清零。 - -### 6.3 Type 3 退化测试 - -- 正常非共线构型; -- `u` 很小但高于容差; -- `u=0`; -- `d=0`; -- 非有限参数; -- PBC minimum-image 后恰好退化; -- NOPBC 直接位移下不退化的对照。 - -### 6.4 图和输入测试 - -- 记录已按拓扑顺序; -- 父记录晚于子记录,但结果保持相同; -- 三层以上嵌套; -- 自依赖、两节点环、长环; -- 重复 target; -- 负数、等于 atom count、超过 atom count 的 source/target; -- 错误 arity、缺少参数、NaN/Inf 参数; -- legacy 与 native H5 对同一错误给出等价失败; -- 输入顺序随机打乱后坐标和力保持一致。 - -### 6.5 MPI 测试 - -- 1 rank 与 2 rank 的单层虚原子坐标/力一致; -- 1 rank 与 2 rank 的多层嵌套虚原子一致; -- 来源原子靠近 domain 边界; -- PBC 下虚原子依赖跨主盒边界; -- domain refresh/particle migration 前后结果一致; -- 人为破坏 update-group 完整性时必须明确报错,而不是继续访问 `-1` 索引。 - -## 7. Type 0 兼容性决定点 - -实施前需要单独确认:legacy `virtual_atom` Type 0 的参数是镜面高度 `h`,还是某个经过缩放的值。 - -验收证据至少包括: - -- Xponge 当前生成器或历史生成器; -- 已有实际 Type 0 输入文件; -- 用户文档/论文/示例; -- 与其他引擎或解析公式的对照。 - -若参数就是 `h`,应将内部值保存为 `two_h=2*h`,核函数执行 `z_v=two_h-z_1`。 -若历史格式确实定义为 `h/2`,应在文档中明确,并将字段命名改成不会重复乘 2 的物理含义。 -不能继续保留“字段叫 `h_double`,核函数再次乘 2”这种隐式约定。 - -## 8. 分阶段实施顺序 - -### 阶段 A:建立失败测试 - -1. Type 1 精确来源力和有限差分测试; -2. Type 2 共享来源并发测试; -3. Type 3 退化失败测试; -4. 乱序依赖、环、重复和非法索引测试; -5. 双 rank 多层依赖测试。 - -### 阶段 B:修复局部数值正确性 - -1. 修正 Type 1 力系数; -2. Type 2 全部改用安全原子累加; -3. Type 3 增加退化检查; -4. 保持 PBC/NOPBC `Get_Displacement` 行为不变。 - -### 阶段 C:重构定义和层级 - -1. 引入统一 definition; -2. 统一 legacy/H5 runtime 校验; -3. 拓扑排序和循环检测; -4. 分层数组与资源生命周期重建。 - -### 阶段 D:修复 MPI 依赖闭包 - -1. 所有层加入 update-group connectivity; -2. `Get_Local` 完整性校验; -3. 单 rank/双 rank 对照; -4. domain migration 回归。 - -### 阶段 E:Type 0 契约落地 - -在第 7 节证据完成后独立修改 Type 0,避免与 Type 1–3 的确定性修复混在一起。 - -## 9. 验收标准 - -- Type 0–3 坐标解析解和有限差分力全部通过; -- Type 1 来源力权重符合 `(1-a), a`; -- Type 2 共享来源在 CPU 多线程和 GPU 上无竞争、可重复; -- Type 3 退化输入明确失败,不产生 NaN 后继续运行; -- 虚原子依赖图与输入顺序无关,环和重复定义明确失败; -- legacy/H5 对索引、arity、有限值和依赖图具有相同 runtime 约束; -- 所有层的 MPI update group 包含完整依赖闭包; -- 1 rank 与 2 rank 的坐标、能量和来源原子力在容差内一致; -- PBC 与 NOPBC 的 Type 1–3 分别使用 minimum-image 和直接笛卡尔位移; -- bundled-I/O 继续验证 legacy/H5 等价,同时新增独立科学 oracle; -- Type 4/质心代码在本任务中没有行为变化; -- CPU、CUDA、CPU-MPI 目标构建和相关旧回归通过。 - -## 10. 非目标与后续工作 - -本计划不决定以下问题: - -- PBC 原子组质心应使用 anchor minimum-image、拓扑展开、连续轨迹还是其他定义; -- 跨半盒或非连通原子组的周期质心是否有唯一物理意义; -- `center` 权重是否必须归一化; -- Type 4 大原子组 GPU 归约实现; -- Type 4 在 CV owner、PM rank 和 PP rank 之间的坐标/力生命周期。 - -这些内容应在质心语义讨论完成后形成独立计划,随后再决定是否与本计划的实现合并到同一 PR。