16#define DOCTEST_CONFIG_IMPLEMENT
24int main(
int argc,
char **argv)
26 MPI_Init(&argc, &argv);
28 ctx.applyCommandLine(argc, argv);
49TEST_CASE(
"GlobalOffsetsMapping uniform distribution")
57 SUBCASE(
"globalSize equals nLocal * size")
62 SUBCASE(
"RLengths all equal nLocal")
65 REQUIRE(
static_cast<int>(lens.size()) == mpi.size);
66 for (
int r = 0;
r < mpi.size;
r++)
70 SUBCASE(
"ROffsets are multiples of nLocal")
73 REQUIRE(
static_cast<int>(offs.size()) == mpi.size + 1);
74 for (
int r = 0;
r <= mpi.size;
r++)
78 SUBCASE(
"operator() returns correct global index")
90TEST_CASE(
"GlobalOffsetsMapping non-uniform distribution")
103 SUBCASE(
"globalSize matches expected sum")
108 SUBCASE(
"offsets are cumulative sums of lengths")
113 for (
int r = 0;
r < mpi.size;
r++)
116 CHECK(offs[
r + 1] == offs[
r] + lens[
r]);
120 SUBCASE(
"search recovers rank and local index for each rank's first element")
125 auto [found, rank, loc] = gm.
search(offs[
r]);
132 SUBCASE(
"search recovers rank and local index for each rank's last element")
139 auto [found, rank, loc] = gm.
search(lastGlobal);
142 CHECK(loc == lens[
r] - 1);
157 SUBCASE(
"search for first global index")
159 auto [found, rank, loc] = gm.
search(0);
165 SUBCASE(
"search for last global index")
168 auto [found, rank, loc] = gm.
search(lastGlobal);
170 CHECK(rank == mpi.size - 1);
174 SUBCASE(
"search for a middle global index")
178 auto [found, rank, loc] = gm.
search(mid);
184 SUBCASE(
"search across rank boundary")
196 SUBCASE(
"search out-of-range returns false")
202 SUBCASE(
"search for negative index returns false")
204 auto [found, rank, loc] = gm.
search(-1);
208 SUBCASE(
"search with reference outputs matches tuple outputs")
212 auto [found1, rank1, loc1] = gm.
search(g);
215 bool found2 = gm.
search(g, rank2, loc2);
216 CHECK(found1 == found2);
217 CHECK(rank1 == rank2);
227TEST_CASE(
"OffsetAscendIndexMapping pull-based construction")
238 std::vector<DNDS::index> pullIdx;
245 pullIdx.push_back(base + i);
250 SUBCASE(
"searchInMain finds local indices")
261 SUBCASE(
"searchInMain rejects out-of-range")
266 MPI_int other = (mpi.rank + 1) % mpi.size;
272 SUBCASE(
"searchInGhost finds pulled indices per rank")
289 SUBCASE(
"searchInAllGhost finds pulled indices")
308 SUBCASE(
"search dispatches to main (rank==-1) and ghost correctly")
312 auto [found, rank, val] = mapping.
search(myOffset + 5);
321 MPI_int other = (mpi.rank + 1) % mpi.size;
323 auto [found, rank, val] = mapping.
search(ghostGlobal);
329 SUBCASE(
"operator() reverse mapping for main data")
334 CHECK(global == myOffset + i);
338 SUBCASE(
"operator() reverse mapping for ghost data")
350 CHECK(global == base + i);
371 std::vector<DNDS::index> pullIdx;
378 pullIdx.push_back(base + i);
383 SUBCASE(
"search_indexAppend returns local val for main data")
391 SUBCASE(
"search_indexAppend offsets ghost val by mainSize")
395 MPI_int other = (mpi.rank + 1) % mpi.size;
399 auto [found1, rank1, rawVal] = mapping.
search(ghostGlobal);
405 CHECK(rank2 == rank1);
410 SUBCASE(
"search_indexAppend with reference outputs matches tuple outputs")
414 MPI_int other = (mpi.rank + 1) % mpi.size;
423 CHECK(found1 == found2);
424 CHECK(rank1 == rank2);
445 std::vector<DNDS::index> emptyPull;
448 SUBCASE(
"searchInMain still works")
459 SUBCASE(
"searchInGhost returns false for any query")
469 SUBCASE(
"searchInAllGhost returns false")
473 MPI_int other = (mpi.rank + 1) % mpi.size;
481 SUBCASE(
"search falls back to main only")
483 auto [found, rank, val] = mapping.
search(myOffset);
490 MPI_int other = (mpi.rank + 1) % mpi.size;
491 auto [found2, rank2, val2] = mapping.
search(gm(other, 0));
496 SUBCASE(
"operator() still works for main data")
499 CHECK(mapping(-1, i) == myOffset + i);
507template <DNDS::index N>
527 SUBCASE(
"globalSize equals nLocal * size")
532 SUBCASE(
"search first element of each rank")
537 auto [found, rank, loc] = gm.
search(offs[
r]);
544 SUBCASE(
"operator() returns correct global index")
566 std::vector<DNDS::index> pullIdx;
573 pullIdx.push_back(base + i);
578 SUBCASE(
"searchInMain finds local indices")
589 SUBCASE(
"searchInGhost finds pulled ghost indices")
606 SUBCASE(
"operator() reverse mapping for main data")
611 CHECK(global == myOffset + i);
615 SUBCASE(
"operator() reverse mapping for ghost data")
625 CHECK(global == base + i);
Global-to-local index mapping for distributed arrays.
MPI wrappers: MPIInfo, collective operations, type mapping, CommStrategy.
Table mapping rank-local row indices to the global index space.
index globalSize() const
Total number of rows across all ranks.
t_IndexVec & ROffsets()
Prefix-sum offsets vector (size == nRanks + 1, last element == globalSize).
void setMPIAlignBcast(const MPIInfo &mpi, index myLength)
Broadcast each rank's length, then compute the global prefix sums.
bool search(index globalQuery, MPI_int &rank, index &val) const
Convert a global index to (rank, local). Returns false if out of range.
t_IndexVec & RLengths()
Per-rank lengths vector (size == nRanks).
Mapping between a rank's main data and its ghost copies.
bool search_indexAppend(index globalQuery, MPI_int &rank, index &val) const
Like search, but the returned val is in the concatenated father+son address space.
bool searchInGhost(index globalQuery, MPI_int rank, index &val) const
Search a single peer rank's ghost slab for a global index.
bool searchInMain(index globalQuery, index &val) const
Check whether a global index lies within the main block.
bool search(index globalQuery, MPI_int &rank, index &val) const
Search main + ghost in one call. rank == -1 signals "hit in main".
bool searchInAllGhost(index globalQuery, MPI_int &rank, index &val) const
Search the concatenated ghost array for a global index (O(log nGhost)).
the host side operators are provided as implemented
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
int MPI_int
MPI counterpart type for MPI_int (= C int). Used for counts and ranks in MPI calls.
Lightweight bundle of an MPI communicator and the calling rank's coordinates.
static constexpr DNDS::index n
TYPE_TO_STRING(SizeTag< 10 >)
TEST_CASE_TEMPLATE("Parametric GlobalOffsetsMapping", Tag, SizeTag< 10 >, SizeTag< 50 >, SizeTag< 200 >, SizeTag< 1000 >)
TEST_CASE("3D: VFV P2 HQM error < P1 on sinCos3D")