MPI Exchange Testing Guide
1. 范围
本指南专门说明 tests/008_mpi_exchange 的算例构造、手工期望值和诊断数据含义。
如果只需要看“怎么跑、覆盖到哪里、如何判断通过”,先看
008_mpi_exchange Tests。
当前 case 固定使用 4 个 MPI rank 和 2 x 2 x 1 拓扑:
项目 |
固定设置 |
说明 |
|---|---|---|
rank 数 |
|
用最小代价覆盖真实 MPI 邻居交换。 |
拓扑 |
|
x/y 方向有真实 MPI 邻居,z 方向不拆分。 |
H01 覆盖 |
x/y halo + 本地 z 周期 |
同时检查真实 halo 覆盖和 unsplit 方向的本地 ghost 填充。 |
H02 覆盖 |
x/y face/edge/corner + 吸收边界 + 本地 z 回绕 |
一次运行覆盖所有权迁移、删除和本地周期 wrap。 |
H03 覆盖 |
x/y 边界累加 + 本地 z 周期折叠 |
区分“覆盖 ghost”与“累加边界节点”两种语义。 |
(1,2,1)
rank 3(2,2,1)
rank 0(1,1,1)
rank 1(2,1,1)
这个 guide 关注“为什么这样构造、期望值怎么算”,而不是脚本入口细节。
2. 逻辑拓扑
init_topology 的逻辑坐标和真实邻居关系如下:
rank |
逻辑坐标 |
x 邻居 |
y 邻居 |
z 邻居 |
|---|---|---|---|---|
0 |
|
|
|
无 |
1 |
|
|
|
无 |
2 |
|
|
|
无 |
3 |
|
|
|
无 |
3. H01 场量 halo 测试
项目 |
设置 |
说明 |
|---|---|---|
有效区间 |
|
每个 rank 的 active block 都相同。 |
本地数组范围 |
|
active block 为 |
初始化 |
|
数值可直接反推来源 rank 和格点。 |
发送层契约 |
|
H01 发的是有效内部一层,不是 |
接收层契约 |
|
收到的数据写入 ghost 层。 |
轮次 |
|
目标 |
断言粒度 |
代表样本 / 期望 |
|---|---|---|---|---|
1 |
|
只测 x/y 的真实 MPI halo |
整张 x 面和 y 面逐点比较 |
|
2 |
|
只测 unsplit z 的本地周期 ghost |
抽查两个代表点 |
|
本地 z 周期规则就是:
f(:,:,il(3)-1)=f(:,:,iu(3)-1),
f(:,:,iu(3)+1)=f(:,:,il(3)+1)。
4. H03 密度边界累加测试
项目 |
设置 |
说明 |
|---|---|---|
有效区间 |
|
每个 rank 的 active block 都相同。 |
初始化 |
|
数值可直接拆成本地值和邻居贡献。 |
接收语义 |
边界节点累加 |
H03 不是 ghost 覆盖,而是把邻居贡献加到 |
本地 z 周期 |
|
表示 unsplit 周期方向的本地折叠。 |
轮次 |
|
目标 |
断言粒度 |
代表样本 / 期望 |
|---|---|---|---|---|
1 |
|
只测 x/y 边界累加 |
x 面固定 |
|
2 |
|
只测 z 周期折叠 |
抽查一个代表点 |
|
build/h03_density_faces.dat 和 fig/h03_density_exchange.png 当前取自第二轮,
也就是“已经做完 z 周期折叠”的样本状态,而不是第一轮非周期 x/y 边界断言的完整导出。
因此 2442 仍然是解释 H03 累加语义的正确例子,但图和 .dat 会反映第二轮状态。
5. H02 粒子迁移测试
项目 |
设置 |
说明 |
|---|---|---|
全局粒子盒子 |
|
全局局域边界由这一对索引定义。 |
周期长度 |
|
只有 z 是周期方向,x/y 为非周期。 |
局部归属规则 |
|
半开区间避免边界粒子双重归属。 |
物种与 ID |
|
方便检查迁移后所有权和删除行为。 |
下面几张表建议按“拥有区间 -> 初始粒子构成 -> 刻意越界样本 -> 最终期望归属”的顺序阅读。 先用 rank 的 x/y 拥有区间判断一个粒子理论上应该属于谁,再对照基础粒子和额外越界粒子的设计, 最后核对迁移后的最终 ID 分布,这样更容易把“为什么会迁移到这个 rank”直接追溯回初值构造。
rank |
x 拥有区间 |
y 拥有区间 |
|---|---|---|
0 |
|
|
1 |
|
|
2 |
|
|
3 |
|
|
由于本 case 只在 x/y 上做真实 MPI 拆分,z 方向不会改变 MPI 所有者;
z 只负责触发“本地周期回绕”这条逻辑,因此后面看到 1300 + rank 时,
应理解为“rank 不变,但粒子坐标会被本地修正”。
基础粒子 ID |
species |
作用 |
|---|---|---|
|
1 |
本地保留,给迁移前后提供稳定参照。 |
|
1 |
初值设成 |
|
2 |
本地保留,验证第二物种不被错误迁移。 |
rank |
额外放入的越界粒子 |
主要覆盖 |
|---|---|---|
0 |
|
x/y 迁移、吸收边界、species 2 |
1 |
|
x/y 迁移、corner、species 2 |
2 |
|
x/y 迁移、corner、species 2 |
3 |
|
x/y 迁移、吸收边界、species 2 |
1900 和 1903 设计为越过全局非周期边界,必须被吸收删除;
1300 + rank 设计为越过 z 上边界,并在本地回绕到 z=0.25。
也就是说,这里同时故意混入了三类事件:跨 rank 迁移、本地 wrap、以及全局吸收删除,
这样最终结果表不只是“列一个答案”,而是在同一套样本里同时验证三种边界行为。
rank |
species 1 最终应持有的 ID |
species 2 最终应持有的 ID |
|---|---|---|
0 |
|
|
1 |
|
|
2 |
|
|
3 |
|
|
这张“最终应持有的 ID”表可以看成前面三张输入表的汇总结论:
1000 + rank / 2000 + rank 用来验证本地保留,
12xx / 22xx 用来验证跨 rank 迁移是否落到了正确拥有者,
1300 + rank 用来验证 z 周期回绕后仍留在原 rank,
而 1900 / 1903 则应该完全从全局结果里消失。
检查项 |
通过条件 |
|---|---|
本地粒子数 |
每个 rank、每个 species 的本地计数都与上表一致。 |
粒子所有权 |
每个期望 ID 都出现在正确 rank,且不重复。 |
z 周期回绕 |
|
吸收边界 |
|
6. 诊断输出的用途
这三份诊断输出并不是三套独立的测试,而是分别对应 H01、H02、H03 三类交换语义的可视化切片。 它们的作用是把 Fortran 断言背后的“局部面值、边界累加状态、粒子所有权变化”具体展示出来, 方便在断言失败时快速判断问题更像是 halo 覆盖错误、边界累加错误,还是粒子归属错误。
Fortran 诊断表 |
Python 输出图 |
主要用途 |
|---|---|---|
|
|
展示 H01 代表面值,快速检查 halo 覆盖。 |
|
|
展示迁移前后粒子所有权和边界行为。 |
|
|
展示 H03 边界累加和 z 周期折叠后的样本状态。 |
这些文件适合文档配图、排障和汇报展示,但不是 pass/fail 的唯一依据;
真正的通过条件仍然是 test_H_MPI_Exchange.f90 中的 Fortran 断言全部成功。
一个实用的排查顺序是:先看断言失败落在 H01/H02/H03 的哪一段,再去对照对应 .dat 和图,
这样能更快缩小到“发送层不对”“累加语义不对”或“粒子删除/迁移不对”这类具体错误。
1. Scope
This guide explains how tests/008_mpi_exchange is constructed, how the
expected values are derived by hand, and how to read the diagnostic outputs.
If you only need run commands, coverage, and pass/fail interpretation, start
from 008_mpi_exchange Tests.
The case always uses 4 MPI ranks on a fixed 2 x 2 x 1 topology:
Item |
Fixed setting |
Meaning |
|---|---|---|
Rank count |
|
Covers the exchange logic with the smallest useful MPI run. |
Topology |
|
x/y have real MPI neighbors while z stays unsplit. |
H01 coverage |
x/y halos + local z periodic fill |
Exercises both true halo overwrite and unsplit-direction local ghost handling. |
H02 coverage |
x/y face/edge/corner + absorbing boundaries + local z wrap |
One run covers migration, deletion, and local periodic wrapping. |
H03 coverage |
x/y accumulation + local z periodic fold |
Separates “overwrite ghost” from “accumulate boundary node” semantics. |
(1,2,1)
rank 3(2,2,1)
rank 0(1,1,1)
rank 1(2,1,1)
This guide is about “why this case is built this way” and “how the expected values are computed”, not about shell-script entry points.
2. Logical Topology
init_topology gives the following logical coordinates and real
neighbor relations:
Rank |
Logical index |
x neighbors |
y neighbors |
z neighbors |
|---|---|---|---|---|
0 |
|
|
|
none |
1 |
|
|
|
none |
2 |
|
|
|
none |
3 |
|
|
|
none |
3. H01 Field Halo Test
Item |
Setting |
Meaning |
|---|---|---|
Effective range |
|
The active block is identical on every rank. |
Local array range |
|
One |
Initialization |
|
Every value directly reveals its source rank and indices. |
Send-layer contract |
|
H01 sends the inner effective layer, not |
Receive-layer contract |
|
Received values overwrite local ghosts. |
Pass |
|
Goal |
Assertion granularity |
Representative sample / expected result |
|---|---|---|---|---|
1 |
|
Test true x/y MPI halos only |
Full x and y faces pointwise |
|
2 |
|
Test local z-periodic ghost fill |
Two representative sample points |
|
The local z-periodic rule is:
f(:,:,il(3)-1)=f(:,:,iu(3)-1),
f(:,:,iu(3)+1)=f(:,:,il(3)+1).
4. H03 Density Accumulation Test
Item |
Setting |
Meaning |
|---|---|---|
Effective range |
|
The active block is identical on every rank. |
Initialization |
|
Values can be decomposed into local and neighbor contributions by inspection. |
Receive semantics |
Boundary-node accumulation |
H03 does not overwrite ghosts; it adds neighbor values onto |
Local z periodic rule |
|
This is the local fold used in the unsplit periodic direction. |
Pass |
|
Goal |
Assertion granularity |
Representative sample / expected result |
|---|---|---|---|---|
1 |
|
Test x/y boundary accumulation only |
Sample one center line on each boundary face |
|
2 |
|
Test local z-periodic folding |
One representative point |
|
build/h03_density_faces.dat and fig/h03_density_exchange.png are
currently generated from the second pass, i.e. after z-periodic folding.
So values like 2442 remain the correct conceptual examples for H03
accumulation semantics, while the dumped and plotted samples reflect the
second-pass state.
5. H02 Particle Migration Test
Item |
Setting |
Meaning |
|---|---|---|
Global particle box |
|
Defines the global domain limits for ownership decisions. |
Periodic lengths |
|
Only z is periodic; x/y are nonperiodic. |
Local ownership rule |
|
Half-open intervals avoid double ownership on boundaries. |
Species and ID storage |
|
Makes ownership checks explicit after migration. |
Read the next few tables in this order: ownership ranges -> initial particle groups -> intentionally out-of-domain samples -> expected final ownership. That order makes it easier to trace “why this particle ends up on this rank” directly back to how the test data was seeded.
Rank |
x ownership range |
y ownership range |
|---|---|---|
0 |
|
|
1 |
|
|
2 |
|
|
3 |
|
|
Because this case is only MPI-decomposed in x/y, the z direction never
changes the owning MPI rank. z only triggers the local periodic-wrap path,
so 1300 + rank should be read as “same rank, corrected local z”.
Base-particle ID |
Species |
Role |
|---|---|---|
|
1 |
Stays local and provides a stable reference. |
|
1 |
Starts at |
|
2 |
Stays local and verifies the second species is not moved incorrectly. |
Rank |
Extra out-of-domain particles inserted |
Main cases covered |
|---|---|---|
0 |
|
x/y migration, absorbing boundary, species 2 |
1 |
|
x/y migration, corner cases, species 2 |
2 |
|
x/y migration, corner cases, species 2 |
3 |
|
x/y migration, absorbing boundary, species 2 |
1900 and 1903 are designed to cross nonperiodic global boundaries
and must be absorbed. 1300 + rank crosses the z upper boundary and must
wrap locally to z=0.25.
In other words, the same dataset deliberately mixes three event types:
cross-rank migration, local wrapping, and global absorbing deletion.
The final-ID table therefore validates three boundary behaviors at once,
not just one migration pattern.
Rank |
Species 1 expected final IDs |
Species 2 expected final IDs |
|---|---|---|
0 |
|
|
1 |
|
|
2 |
|
|
3 |
|
|
This final-ownership table is the combined conclusion of the previous input
tables:
1000 + rank / 2000 + rank validate local retention,
12xx / 22xx validate cross-rank migration to the correct owner,
1300 + rank validates z wrapping without ownership change,
and 1900 / 1903 should disappear from the global result entirely.
Check |
Pass condition |
|---|---|
Local counts |
Per-rank, per-species counts match the table above. |
Ownership |
Every expected ID exists on the correct rank and is not duplicated. |
z wrapping |
|
Absorbing boundaries |
Global counts of |
6. Purpose of the diagnostic outputs
These three diagnostics are not three unrelated reports. They are the H01, H02, and H03 visual slices of the same testing strategy. Their role is to expose the local face values, boundary-accumulation state, and particle-ownership changes behind the Fortran assertions, so when an assertion fails you can quickly tell whether the bug looks like a halo overwrite issue, an accumulation issue, or an ownership issue.
Fortran diagnostic table |
Python figure |
Main use |
|---|---|---|
|
|
Shows representative H01 face values and halo overwrite behavior. |
|
|
Shows particle ownership before and after migration. |
|
|
Shows H03 accumulation samples and the z-folded state. |
These files are useful for documentation figures, debugging, and regression
summaries, but they are not the sole pass/fail criterion. The real decision
still comes from the Fortran assertions in test_H_MPI_Exchange.f90.
A practical debugging order is: first identify whether the failing
assertion belongs to H01, H02, or H03, then inspect the matching .dat
and figure to narrow it down to send-layer mistakes, accumulation-semantics
mistakes, or particle migration/deletion mistakes.