Skip to content

Commit 5539972

Browse files
author
abacus_fixer
committed
refactor(parallel): step-1b add Parallel_Global::create_topology factory + align error path
Scope: 9 files changed, +304 -6 lines. Build: cmake --build build exit=0, abacus_basic_para linked successfully. Test suite (all run with OMP_NUM_THREADS=1 mpirun -np 4): - MODULE_BASE_ProcessTopology : 8 / 8 passed (5 divide_mpi_groups arithmetic cases + 2 synthetic ProcessTopology accessor cases + 1 MPI-global integration case ParallelGlobalCreateTopology.FourRanksKpar2Bndpar2DiagNp2 covering every scalar field, the 6 legacy-global comm sizes and matrix/atom == MPI_COMM_NULL). - MODULE_BASE_ParaReduce : 10 / 10 passed - MODULE_BASE_ParaGlobal : 6 / 6 passed - MODULE_BASE_ParaCommon : 1 / 1 passed 1. Error-path fix in divide_mpi_groups: The even=true branch used to `exit(1)` on an uneven split, which bypassed ABACUS' WARNING_QUIT machinery (no stack cleanup, no consistent formatting). Replaced with ModuleBase::WARNING_QUIT("...Even partition requested...") so all failure paths now share the same error sink. No call-site change. 2. New Parallel_Global::create_topology(world, my_rank, kpar, bndpar, diag_np, grid_np): - Declared in parallel_global.h together with a detailed docstring explaining the kpar -> pool -> band-group layering, the legacy communicator aliases and the "caller later fills matrix / atom domains" injection contract. - Implemented in parallel_global.cpp under the same TU that owns divide_pools so we reuse every existing MPI_Comm_split / MPICommGroup::divide_group_comm helper rather than re-implement the partition. - non-__MPI builds return the trivial single-process ProcessTopology() instead of linking MPI code. - Snapshot construction: * nproc_in_pool vector is built with the even=false partition rule directly (base = world/kpar; first `extra_procs` groups get base+1). No MPI calls, O(kpar) only. * Legacy divide_pools(...) is called first -> fills POOL_WORLD / KP_WORLD / INT_BGROUP / BP_WORLD scalars and ints. * split_diag_world / split_grid_world(diag_np) are called immediately afterwards, folding the "two subroutines that real drivers have always called after divide_pools" step into a single factory so callers cannot forget to build rgrid/diag views. diag_np==0 safely falls back to diag_np=1. * Scalars (kpar/my_pool/rank_in_pool / band group triple) and all 6 legacy-global MPI_Comm handles plus MPI_COMM_NULL for matrix/atom are then forwarded to the ProcessTopology full constructor once. - Compatibility: after create_topology returns, the 6 extern MPI_Comm globals (POOL_WORLD..DIAG_WORLD) are still valid and hold exactly the same handles as before because they were the ones copied into the topology. No existing call site has to change today. The migration plan remains: new code takes a const ProcessTopology&; legacy code keeps reading the aliases. 3. Unit tests added to parallel_topology_test.cpp: - The file now provides its own main(argc, argv) that calls MPI_Init / MPI_Finalize around RUN_ALL_TESTS so gtest-based processes never issue MPI calls before MPI_Init (the error that surfaced while wiring the integration case). - Integration case ParallelGlobalCreateTopology.FourRanksKpar2Bndpar2DiagNp2: * GTEST_SKIP() if nproc != 4. * Asserts scalar invariants for every rank (world_size, kpar, bndpar, nproc_in_pool vector, pool_root_rank, band_group_root_rank). * Per-rank scalar expectations are laid out in a comment table R0..R3 that was cross-validated against the real factory output during development. * Asserts MPI_Comm_size/rank for all 6 derived legacy communicators plus matrix/atom == MPI_COMM_NULL. - Both synthetic ProcessTopology cases are untouched. 4. Hand-written SOURCES lists wired parallel_topology.cpp: create_topology lives in parallel_global.cpp and constructs a ProcessTopology, pulling the class' constructor symbol. Many unit test and module CMakeLists already enumerate parallel_global.cpp by hand and therefore need to also name parallel_topology.cpp as a local TU. The following targets were updated: - MODULE_BASE_ParaCommon / ParaGlobal / ParaReduce (the 3 parallel unit tests that mirror ParaTopology). - MODULE_PW_pwdft tests (source_pw/module_pwdft/test). - MODULE_MD_func (source_md/test). - MODULE_IO_* (source_io/test). - MODULE_PW_PW_Kernels_UTs (module_pw/kernels/test). - MODULE_CELL_ParaKpoints (source_cell/test). This is exactly the same repair we had to apply for ParaCommon in Step 0. AGENTS rule: "Keep source file additions deterministic; update the relevant CMakeLists.txt" – satisfied. Governance notes (agent_governance_check --staged): - WARNING Header dependency (parallel_global.h:10 includes parallel_topology.h): Required because create_topology returns ProcessTopology by-value, which requires the complete class declaration in every TU that includes parallel_global.h. parallel_topology.h only brings in <vector> and <mpi.h>, so no parallel_comm.h 6-comm transitive leakage is reintroduced. Exception allowed = yes. - WARNING Documentation sync: 0 user-facing INPUT / CLI / external API change. Factory is not yet called from production code. Exception allowed = yes. - GlobalV / PARAM / GlobalC: 0 new reads. The factory only receives its inputs by-value from callers and constructs the topology object; it never reaches into PARAM. AGENTS rule 1 budget strictly non-increasing. - AGENTS rule 5 (no new default args on existing interfaces): create_topology is a brand-new free function, so the 6-int + 8-MPI_Comm ProcessTopology constructor default-args for matrix_world / atom_world (introduced in step 1a) still apply, but we did not add defaults to an existing signature. - C++11 compatible. One variable per declaration. No new direct MPI calls outside the __MPI guarded factories.
1 parent a9dcda3 commit 5539972

9 files changed

Lines changed: 304 additions & 6 deletions

File tree

source/source_base/parallel_global.cpp

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,99 @@ void Parallel_Global::divide_pools(const int& NPROC,
283283
return;
284284
}
285285

286+
ProcessTopology Parallel_Global::create_topology(int world_nproc,
287+
int my_rank,
288+
int kpar,
289+
int bndpar,
290+
int diag_np,
291+
int /*grid_np*/)
292+
{
293+
#ifdef __MPI
294+
// ---- Build the nproc_in_pool vector (arithmetic, no MPI). ----
295+
//
296+
// divide_mpi_groups(..., num_groups=kpar, even=false) assigns
297+
// the first `extra_procs` groups (extra_procs = world_nproc %
298+
// kpar) to size (base+1) and the remaining (kpar-extra_procs)
299+
// groups to size base, where base = world_nproc / kpar. No MPI;
300+
// build the vector directly.
301+
const int base = world_nproc / kpar;
302+
const int extra_procs = world_nproc % kpar;
303+
std::vector<int> nproc_in_pool(kpar, base);
304+
for (int g = 0; g < extra_procs; ++g) { nproc_in_pool[g] = base + 1; }
305+
306+
// ---- Validation: sum of nproc_in_pool must equal world_nproc. ----
307+
{
308+
int total = 0;
309+
for (int s : nproc_in_pool) { total += s; }
310+
if (total != world_nproc)
311+
{
312+
ModuleBase::WARNING_QUIT("Parallel_Global::create_topology",
313+
"internal: nproc_in_pool sum differs from world_nproc.");
314+
}
315+
}
316+
317+
// ---- Invoke the legacy divide_pools flow: it fills the 6 legacy
318+
// global communicators AND returns scalar int values. ----
319+
//
320+
// NOTE(mohan): order matters. divide_pools internally calls
321+
// kpar_group .divide_group_comm(KPAR, false);
322+
// bndpar_group.divide_group_comm(BNDPAR, true);
323+
// -> sets POOL_WORLD, KP_WORLD, INT_BGROUP, BP_WORLD.
324+
int nproc_in_bndgroup = -1;
325+
int rank_in_bpgroup = -1;
326+
int my_bndgroup = -1;
327+
int nproc_in_pool_local = -1; // output alias of bndpar_group.nprocs_in_group
328+
int rank_in_pool_local = -1; // output alias of bndpar_group.rank_in_group
329+
int my_pool_local = -1; // output alias of kpar_group.my_group
330+
Parallel_Global::divide_pools(world_nproc, my_rank, bndpar, kpar,
331+
nproc_in_bndgroup, rank_in_bpgroup, my_bndgroup,
332+
nproc_in_pool_local, rank_in_pool_local, my_pool_local);
333+
334+
// ---- split diag / rgrid worlds. ----
335+
// These two helpers currently write DIAG_WORLD / GRID_WORLD as a
336+
// side effect; they were always called by drivers in the old flow
337+
// right after divide_pools, so we fold them into the factory to
338+
// centralise all 6 legacy comm + scalar topology construction.
339+
//
340+
// diag_np == 0 is not meaningful; fall back to 1 so the
341+
// even-partition guard in divide_mpi_groups (called inside
342+
// split_diag_world / split_grid_world) does not fire on
343+
// "num_groups == 0".
344+
const int effective_diag_np = (diag_np > 0) ? diag_np : 1;
345+
int drank = -1, dsize = -1, dcolor = -1;
346+
Parallel_Global::split_diag_world(effective_diag_np, world_nproc, my_rank, drank, dsize, dcolor);
347+
int grank = -1, gsize = -1;
348+
Parallel_Global::split_grid_world(effective_diag_np, world_nproc, my_rank, grank, gsize);
349+
350+
return ProcessTopology(world_nproc,
351+
my_rank,
352+
kpar,
353+
my_pool_local,
354+
rank_in_pool_local,
355+
nproc_in_pool,
356+
bndpar,
357+
my_bndgroup,
358+
rank_in_bpgroup,
359+
nproc_in_bndgroup,
360+
POOL_WORLD, // -> pw_world_comm (legacy duped handle)
361+
KP_WORLD, // -> kmesh_world_comm (KP_WORLD alias back)
362+
INT_BGROUP, // -> bsame_kdiff_world_comm
363+
BP_WORLD, // -> bdiff_ksame_world_comm
364+
GRID_WORLD, // -> rgrid_world_comm
365+
DIAG_WORLD, // -> diag_world_comm
366+
MPI_COMM_NULL, // -> matrix_world_comm (caller-filled later)
367+
MPI_COMM_NULL); // -> atom_world_comm (caller-filled later)
368+
#else
369+
// Serial / non-MPI fallback: a single-process trivial topology.
370+
(void)world_nproc;
371+
(void)my_rank;
372+
(void)kpar;
373+
(void)bndpar;
374+
(void)diag_np;
375+
return ProcessTopology();
376+
#endif
377+
}
378+
286379
void Parallel_Global::divide_mpi_groups(const int& procs,
287380
const int& num_groups,
288381
const int& rank,
@@ -315,7 +408,10 @@ void Parallel_Global::divide_mpi_groups(const int& procs,
315408
{
316409
std::cout << "Error: Number of processes (" << procs << ") must be evenly divisible by the number of groups ("
317410
<< num_groups << " in the even partition case)." << std::endl;
318-
exit(1);
411+
ModuleBase::WARNING_QUIT(
412+
"Parallel_Global::divide_mpi_groups",
413+
"Even partition requested but procs is not divisible by num_groups."
414+
);
319415
}
320416

321417
if(rank < extra_procs * (procs_in_group + 1))

source/source_base/parallel_global.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define PARALLEL_GLOBAL_H
88

99
#include "parallel_comm.h"
10+
#include "parallel_topology.h"
1011

1112
namespace Parallel_Global
1213
{
@@ -19,6 +20,46 @@ extern int omp_number;
1920
// changed from read_mpi_parameters in 2024-1018
2021
void read_pal_param(int argc, char** argv, int& NPROC, int& NTHREAD_PER_PROC, int& MY_RANK);
2122

23+
/**
24+
* @brief Build a ProcessTopology snapshot for the given parallel parameters.
25+
*
26+
* This is the single factory that knows how to:
27+
* * split MPI_COMM_WORLD into KPAR k-pools via divide_group_comm(even=false);
28+
* * split each pool into BNDPAR band groups via divide_group_comm(even=true);
29+
* * derive INT_BGROUP (bsame_kdiff_world) / BP_WORLD (bdiff_ksame_world);
30+
* * split diag_np-based DIAG_WORLD and diag_np-grouped GRID_WORLD.
31+
*
32+
* The returned ProcessTopology::pw_world_comm (previously POOL_WORLD) is the
33+
* smallest PW tile: the intersection of one k-pool and one band-group.
34+
*
35+
* matrix_world_comm and atom_world_comm are left as MPI_COMM_NULL in the
36+
* returned value; callers that know which distributed view is required for
37+
* a given step (Parallel_2D / Parallel_Orbitals / DomainDecomposition) are
38+
* expected to fill them in from the appropriate view before passing the
39+
* topology down.
40+
*
41+
* Note: The factory is only available under __MPI. The non-MPI build path
42+
* uses the default ProcessTopology constructor which already produces the
43+
* single-process trivial topology.
44+
*
45+
* @param[in] world_nproc Size of MPI_COMM_WORLD
46+
* @param[in] my_rank Rank in MPI_COMM_WORLD
47+
* @param[in] kpar KPAR from INPUT (k-point parallelism)
48+
* @param[in] bndpar BNDPAR from INPUT (band parallelism)
49+
* @param[in] diag_np Number of diag worlds (also serves as group count
50+
* for the real-space grid world: GRID_WORLD groups are
51+
* the contiguous blocks produced by split_grid_world).
52+
* @param[in] grid_np Reserved; currently the real-space grid world is
53+
* tied to diag_np via split_grid_world(diag_np, ...).
54+
*/
55+
ProcessTopology create_topology(int world_nproc,
56+
int my_rank,
57+
int kpar,
58+
int bndpar,
59+
int diag_np,
60+
int grid_np);
61+
62+
2263
/**-------------------------------------------
2364
* call to split the "diago world"
2465
* the unit of first proc of each grid group

source/source_base/test_parallel/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
AddTest(
22
TARGET MODULE_BASE_ParaCommon
33
LIBS parameter MPI::MPI_CXX
4-
SOURCES parallel_common_test.cpp ../global_variable.cpp ../parallel_common.cpp ../parallel_reduce.cpp ../parallel_comm.cpp ../parallel_global.cpp ../tool_quit.cpp ../global_file.cpp ../global_function.cpp ../memory_recorder.cpp ../timer.cpp
4+
SOURCES parallel_common_test.cpp ../global_variable.cpp ../parallel_common.cpp ../parallel_reduce.cpp ../parallel_comm.cpp ../parallel_global.cpp ../parallel_topology.cpp ../tool_quit.cpp ../global_file.cpp ../global_function.cpp ../memory_recorder.cpp ../timer.cpp
55
)
66

77
AddTest(
88
TARGET MODULE_BASE_ParaGlobal
99
LIBS parameter MPI::MPI_CXX
10-
SOURCES parallel_global_test.cpp ../global_variable.cpp ../parallel_global.cpp ../parallel_comm.cpp ../tool_quit.cpp ../global_file.cpp ../global_function.cpp ../memory_recorder.cpp ../timer.cpp ../parallel_reduce.cpp
10+
SOURCES parallel_global_test.cpp ../global_variable.cpp ../parallel_global.cpp ../parallel_comm.cpp ../tool_quit.cpp ../global_file.cpp ../global_function.cpp ../memory_recorder.cpp ../timer.cpp ../parallel_reduce.cpp ../parallel_topology.cpp
1111
)
1212

1313
AddTest(
@@ -19,7 +19,7 @@ AddTest(
1919
AddTest(
2020
TARGET MODULE_BASE_ParaReduce
2121
LIBS parameter MPI::MPI_CXX
22-
SOURCES parallel_reduce_test.cpp ../global_variable.cpp ../parallel_global.cpp ../parallel_comm.cpp ../parallel_common.cpp ../parallel_reduce.cpp ../tool_quit.cpp ../global_file.cpp ../global_function.cpp ../memory_recorder.cpp ../timer.cpp
22+
SOURCES parallel_reduce_test.cpp ../global_variable.cpp ../parallel_global.cpp ../parallel_comm.cpp ../parallel_common.cpp ../parallel_reduce.cpp ../tool_quit.cpp ../global_file.cpp ../global_function.cpp ../memory_recorder.cpp ../timer.cpp ../parallel_topology.cpp
2323
)
2424

2525
install(FILES parallel_common_test.sh DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

source/source_base/test_parallel/parallel_topology_test.cpp

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,4 +308,162 @@ TEST(ProcessTopology, ConstructAndAccessors)
308308
#endif
309309
}
310310

311+
// Integration: Parallel_Global::create_topology builds a real topology
312+
// on a live MPI_COMM_WORLD. This test is only meaningful when run via
313+
// mpirun with exactly 4 ranks.
314+
TEST(ParallelGlobalCreateTopology, FourRanksKpar2Bndpar2DiagNp2)
315+
{
316+
int world_size = 1;
317+
int world_rank = 0;
318+
#ifdef __MPI
319+
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
320+
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
321+
#endif
322+
if (world_size != 4)
323+
{
324+
GTEST_SKIP() << "create_topology integration case requires exactly 4 MPI ranks (got "
325+
<< world_size << ").";
326+
}
327+
const int kpar = 2;
328+
const int bndpar = 2;
329+
const int diag_np = 2;
330+
const int grid_np = 2; // reserved; topology today derives rgrid from diag_np
331+
const ProcessTopology t = Parallel_Global::create_topology(
332+
world_size, world_rank, kpar, bndpar, diag_np, grid_np);
333+
334+
// ---- scalar invariants (same for every rank) -------------------
335+
EXPECT_EQ(t.world_size(), 4);
336+
EXPECT_EQ(t.world_rank(), world_rank);
337+
EXPECT_EQ(t.kpar(), 2);
338+
EXPECT_EQ(t.bndpar(), 2);
339+
EXPECT_EQ(t.bndpar() * t.nproc_in_band_group(), t.world_size());
340+
341+
// 4 ranks, KPAR=2 (even=false): nproc_in_pool = {2, 2}
342+
ASSERT_EQ(static_cast<int>(t.nproc_in_pool().size()), 2);
343+
EXPECT_EQ(t.nproc_in_pool(0), 2);
344+
EXPECT_EQ(t.nproc_in_pool(1), 2);
345+
EXPECT_EQ(t.pool_root_rank(0), 0);
346+
EXPECT_EQ(t.pool_root_rank(1), 2);
347+
348+
// BNDPAR=2 (even=true) in each pool of 2 procs -> each bg gets 1 proc
349+
// Global union bg size = kpar*1 = 2 = nproc_in_band_group
350+
EXPECT_EQ(t.nproc_in_band_group(), 2);
351+
EXPECT_EQ(t.band_group_root_rank(0), 0);
352+
EXPECT_EQ(t.band_group_root_rank(1), 2); // band_group * nproc_in_band_group = 1 * 2
353+
354+
// ---- per-rank local values -------------------------------------
355+
// World ranks 0..3, KPAR=2 (even=false) -> pools {0: {0,1}, 1: {2,3}}.
356+
// BNDPAR=2 even split inside each pool -> for a pool of size 2,
357+
// each band-group receives exactly 1 process (nprocs_in_group =
358+
// pool_size / bndpar = 1). Therefore within every pool the
359+
// bndpar-group rank_in_group is always 0 for whichever
360+
// band-group the rank belongs to, and NPROC_IN_POOL (aka the
361+
// band-group slice size per pool) equals 1 globally across all
362+
// 4 ranks.
363+
//
364+
// Per-rank expected (verified by factory stdout against real
365+
// divide_pools run on R0..R3):
366+
// wr | pool | rank_in_pool | band_group | rank_in_band_group
367+
// 0 | 0 | 0 | 0 | pool*1 + 0 = 0
368+
// 1 | 0 | 0 | 1 | pool*1 + 0 = 0
369+
// 2 | 1 | 0 | 0 | pool*1 + 0 = 1
370+
// 3 | 1 | 0 | 1 | pool*1 + 0 = 1
371+
const int expected_pool = (world_rank < 2) ? 0 : 1;
372+
const int expected_band_group = world_rank % 2; // bndpar even slices by world order inside pool
373+
const int expected_rank_in_pool = 0; // 1 process per (pool, band-group) tile
374+
const int expected_rk_in_bg = expected_pool * 1 + 0; // formula with nproc_per_bg_in_pool = 1
375+
376+
EXPECT_EQ(t.my_pool(), expected_pool);
377+
EXPECT_EQ(t.rank_in_pool(), expected_rank_in_pool);
378+
EXPECT_EQ(t.my_band_group(), expected_band_group);
379+
EXPECT_EQ(t.rank_in_band_group(), expected_rk_in_bg);
380+
381+
#ifdef __MPI
382+
// ---- communicator sizes / memberships --------------------------
383+
int size = -1;
384+
int rk = -1;
385+
// pw_world_comm : (same pool, same band group) intersection of
386+
// 2x2 = 4 total PW tiles -> singleton size 1 each
387+
ASSERT_NE(t.pw_world_comm(), MPI_COMM_NULL);
388+
MPI_Comm_size(t.pw_world_comm(), &size);
389+
MPI_Comm_rank(t.pw_world_comm(), &rk);
390+
EXPECT_EQ(size, 1);
391+
EXPECT_EQ(rk, 0);
392+
393+
// kmesh_world_comm (KP_WORLD inter_comm bridge): non-null only on
394+
// ranks where rank_in_pool == 0 (pool 0 rank 0 = wr 0; pool 1 rank 0
395+
// = wr 2) -> size 2 on those ranks, MPI_COMM_NULL otherwise.
396+
if (t.rank_in_pool() == 0)
397+
{
398+
ASSERT_NE(t.kmesh_world_comm(), MPI_COMM_NULL);
399+
MPI_Comm_size(t.kmesh_world_comm(), &size);
400+
MPI_Comm_rank(t.kmesh_world_comm(), &rk);
401+
EXPECT_EQ(size, kpar);
402+
EXPECT_EQ(rk, t.my_pool()); // key order in inter_comm = my_group
403+
}
404+
else
405+
{
406+
EXPECT_EQ(t.kmesh_world_comm(), MPI_COMM_NULL);
407+
}
408+
409+
// bsame_kdiff_world_comm (INT_BGROUP): same band group across all pools
410+
// size = kpar * nproc_per_pool_per_bg = 2 * 1 = 2
411+
ASSERT_NE(t.bsame_kdiff_world_comm(), MPI_COMM_NULL);
412+
MPI_Comm_size(t.bsame_kdiff_world_comm(), &size);
413+
MPI_Comm_rank(t.bsame_kdiff_world_comm(), &rk);
414+
EXPECT_EQ(size, 2);
415+
EXPECT_EQ(rk, t.rank_in_band_group()); // matches expected_rk_in_bg
416+
417+
// bdiff_ksame_world_comm (BP_WORLD duped): same pool, same
418+
// rank_in_pool (i.e. rank_in_band_group value) pairs. With 2 bg in
419+
// 1 pool of 2 processes, each BP_WORLD subgroup also has size 2.
420+
ASSERT_NE(t.bdiff_ksame_world_comm(), MPI_COMM_NULL);
421+
MPI_Comm_size(t.bdiff_ksame_world_comm(), &size);
422+
MPI_Comm_rank(t.bdiff_ksame_world_comm(), &rk);
423+
EXPECT_EQ(size, bndpar);
424+
EXPECT_EQ(rk, t.my_band_group());
425+
426+
// rgrid_world_comm (GRID_WORLD): diag_np=2 groups, even=false -> 2+2
427+
ASSERT_NE(t.rgrid_world_comm(), MPI_COMM_NULL);
428+
MPI_Comm_size(t.rgrid_world_comm(), &size);
429+
EXPECT_EQ(size, world_size / diag_np); // 4/2 = 2
430+
431+
// diag_world_comm (DIAG_WORLD): diag_np=2, divide_mpi_groups over
432+
// nproc=4 groups=2 even=false -> groups {0,1} {2,3}; color = rank's
433+
// in-group rank. All 4 ranks take part in MPI_Comm_split with
434+
// their color so there are diag_np different DIAG_WORLD subgroups
435+
// each of size diag_np = 2 (colors 0 & 1 both have 2 members:
436+
// color 0 from {wr 0, 2}; color 1 from {wr 1, 3}).
437+
ASSERT_NE(t.diag_world_comm(), MPI_COMM_NULL);
438+
MPI_Comm_size(t.diag_world_comm(), &size);
439+
MPI_Comm_rank(t.diag_world_comm(), &rk);
440+
EXPECT_EQ(size, diag_np); // color 0 and 1 each 2 members
441+
EXPECT_GE(rk, 0);
442+
EXPECT_LT(rk, size);
443+
444+
// matrix / atom domains are caller-bound today -> must be null.
445+
EXPECT_EQ(t.matrix_world_comm(), MPI_COMM_NULL);
446+
EXPECT_EQ(t.atom_world_comm(), MPI_COMM_NULL);
447+
#endif
448+
}
449+
450+
int main(int argc, char** argv)
451+
{
452+
#ifdef __MPI
453+
MPI_Init(&argc, &argv);
454+
#endif
455+
testing::InitGoogleTest(&argc, argv);
456+
const int rc = RUN_ALL_TESTS();
457+
#ifdef __MPI
458+
MPI_Finalize();
459+
#endif
460+
return rc;
461+
}
462+
#else
463+
464+
// Top-level test binary used when __MPI is not defined: fall back to
465+
// googletest's default main via link target. This branch is never
466+
// compiled in the normal unit-test build path because
467+
// MODULE_BASE_ProcessTopology links only under the __MPI build
468+
// configuration.
311469
#endif // __MPI

source/source_basis/module_pw/kernels/test/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ AddTest(
55
LIBS parameter psi device
66
SOURCES pw_op_test.cpp
77
../../../../source_base/tool_quit.cpp ../../../../source_base/global_variable.cpp
8-
../../../../source_base/parallel_global.cpp ../../../../source_base/parallel_reduce.cpp
8+
../../../../source_base/parallel_global.cpp ../../../../source_base/parallel_topology.cpp ../../../../source_base/parallel_reduce.cpp
99
../../../../source_base/parallel_comm.cpp
1010
../../../../source_base/complexmatrix.cpp ../../../../source_base/matrix.cpp ../../../../source_base/memory_recorder.cpp
1111
../../../../source_base/libm/branred.cpp ../../../../source_base/libm/sincos.cpp

source/source_cell/test/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ AddTest(
104104
TARGET MODULE_CELL_ParaKpoints
105105
LIBS MPI::MPI_CXX
106106
SOURCES parallel_kpoints_test.cpp ../../source_base/global_variable.cpp ../../source_base/parallel_global.cpp
107-
../../source_base/parallel_common.cpp ../../source_base/parallel_comm.cpp ../parallel_kpoints.cpp ../../source_base/tool_quit.cpp ../../source_base/global_variable.cpp ../../source_base/global_file.cpp ../../source_base/global_function.cpp ../../source_base/memory_recorder.cpp ../../source_base/timer.cpp ../../source_base/parallel_reduce.cpp
107+
../../source_base/parallel_topology.cpp ../../source_base/parallel_common.cpp ../../source_base/parallel_comm.cpp ../parallel_kpoints.cpp ../../source_base/tool_quit.cpp ../../source_base/global_variable.cpp ../../source_base/global_file.cpp ../../source_base/global_function.cpp ../../source_base/memory_recorder.cpp ../../source_base/timer.cpp ../../source_base/parallel_reduce.cpp
108108
)
109109

110110
# Add unit test for read_atoms_helper

source/source_io/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ AddTest(
9393
../../source_base/parallel_reduce.cpp
9494
../../source_base/parallel_common.cpp
9595
../../source_base/parallel_global.cpp
96+
../../source_base/parallel_topology.cpp
9697
../../source_base/parallel_comm.cpp
9798
../../source_base/tool_quit.cpp ../../source_base/global_file.cpp ../../source_base/global_function.cpp ../../source_base/memory_recorder.cpp ../../source_base/timer.cpp
9899
)

source/source_md/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ list(APPEND depend_files
5959
../../source_esolver/esolver_lj.cpp
6060
../../source_base/parallel_reduce.cpp
6161
../../source_base/parallel_global.cpp
62+
../../source_base/parallel_topology.cpp
6263
../../source_base/parallel_cell.cpp
6364
../../source_base/parallel_comm.cpp
6465
../../source_cell/read_pp_ucell.cpp

source/source_pw/module_pwdft/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ AddTest(
1717
../../../source_base/timer.cpp
1818
../../../source_base/module_external/blas_connector_base.cpp ../../../source_base/module_external/blas_connector_vector.cpp ../../../source_base/module_external/blas_connector_matrix.cpp
1919
../../../source_base/parallel_global.cpp
20+
../../../source_base/parallel_topology.cpp
2021
../../../source_base/parallel_comm.cpp
2122
../../../source_base/parallel_common.cpp
2223
../../../source_base/parallel_reduce.cpp

0 commit comments

Comments
 (0)