DNDSR 0.1.0.dev1+gcd065ad
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
test_MeshDistributedRead.cpp File Reference

Tests for ReadSerializeAndDistribute: write mesh to H5, then read it back with even-split + ParMetis repartition and verify the rebuilt mesh matches the original. More...

#include "doctest.h"
#include "Geom/Mesh.hpp"
#include "DNDS/SerializerH5.hpp"
#include <string>
#include <filesystem>
#include <algorithm>
#include <numeric>
Include dependency graph for test_MeshDistributedRead.cpp:

Go to the source code of this file.

Classes

struct  MeshConfig
 
struct  RefCounts
 

Macros

#define DOCTEST_CONFIG_IMPLEMENT
 
#define FOR_EACH_CONFIG(body)
 
#define FOR_EACH_CROSS_CONFIG(body)
 

Functions

int main (int argc, char **argv)
 
 TEST_CASE ("SameNp: global cell count")
 
 TEST_CASE ("SameNp: global node count")
 
 TEST_CASE ("SameNp: global bnd count")
 
 TEST_CASE ("SameNp: global face count")
 
 TEST_CASE ("SameNp: expected counts from config")
 
 TEST_CASE ("SameNp: every rank has cells")
 
 TEST_CASE ("SameNp: face2cell valid")
 
 TEST_CASE ("SameNp: node2cell non-empty")
 
 TEST_CASE ("SameNp: cell2cellOrig globally unique")
 
 TEST_CASE ("SameNp: coordinate bounding box is sane")
 
 TEST_CASE ("CrossNp: global cell count")
 
 TEST_CASE ("CrossNp: global node count")
 
 TEST_CASE ("CrossNp: global bnd count")
 
 TEST_CASE ("CrossNp: global face count")
 
 TEST_CASE ("CrossNp: every rank has cells")
 
 TEST_CASE ("CrossNp: face2cell valid")
 
 TEST_CASE ("CrossNp: cell2cellOrig globally unique")
 
 TEST_CASE ("CrossNp: node2cell non-empty")
 

Detailed Description

Tests for ReadSerializeAndDistribute: write mesh to H5, then read it back with even-split + ParMetis repartition and verify the rebuilt mesh matches the original.

Test plan
(A) Same-np: write at np=N, read at np=N with a different Metis seed. Verifies that repartitioning produces a valid mesh. (B) Cross-np: write with a rank subset [0, npWrite), read with all ranks. Verifies that reading at a different np works.
Checks (each scenario)
  • Global cell, node, bnd, face counts match the reference.
  • AssertOnFaces passes (face topology correct after full rebuild).
  • face2cell entries are valid (left cell local, right cell local or ghost).
  • node2cell non-empty for all owned nodes.
  • cell2cellOrig globally unique (no duplicate or lost cells).
  • Coordinate bounding box is non-degenerate.
Mesh configs
[0] UniformSquare_10 – 2D, 100 quad, non-periodic TODO: [1] IV10_10 – 2D, 100 quad, periodic (pending periodic bnd convention)
Bugs found and fixed during development
  1. H5 path navigation (Mesh_ReadSerializeDistributed.cpp): GoToPath("..") appends ".." literally in the H5 serializer instead of navigating up. Fixed by saving/restoring absolute paths via GetCurrentPath().
  2. Bnd partition from ghost cells (Mesh_ReadSerializeDistributed.cpp): bnd2cell(iBnd, 0) can reference a ghost cell in the even-split partition. A ghost pull of the cell partition array is needed to resolve the target partition for bnds whose owner cell is on another rank.
  3. Ghost append index vs local index (Mesh_ReadSerializeDistributed.cpp): search_indexAppend returns father_size + ghost_local_idx, but the bnd partition code used this directly as an index into cellPartArrGhost (which is 0-indexed). Fixed by subtracting cellPartArr->Size().
  4. Ghost bnd nodes not in coord ghost layer (Mesh.cpp, BuildGhostPrimary): Ghost bnds (pulled by BuildGhostPrimary via node2bnd) may reference nodes not in the coord ghost layer (which only covers cells' nodes). Fixed by expanding the coord ghost layer after bnd ghosting, with a collective Allreduce guard to avoid deadlock.
  5. AdjGlobal2LocalPrimary assertion on ghost bnds (Mesh.cpp): Ghost bnds' parent cells may not be in the cell ghost layer (which only includes cell2cell neighbors). Relaxed the assertion to only enforce for father bnds: the semantic contract is that father bnds must have their parent cell as a local father cell.
  6. Serializer shared-ptr dedup address reuse (SerializerBase/H5/JSON): The ptr_2_pth dedup map keyed on raw void* addresses. After a temporary shared_ptr was destroyed, the allocator could reuse the address for a new shared_ptr, causing false dedup (e.g., bnd2node's pRowStart written as a ::ref to cell2node's pRowStart). Fixed by storing shared_ptr<void> to keep objects alive.
  7. CSR Compress before dataOffset (ArrayTransformer.hpp, ParArray): ParArray::WriteSerializer computed dataOffset from _pRowStart before Compress() was called. For uncompressed CSR arrays (np=1 after TransferDataSerial2Global), _pRowStart was null and pRowStart was silently skipped. Fixed by calling Compress() first.
  8. Periodic bnd pbi filter on non-local cells (Mesh.cpp, RecoverCell2CellAndBnd2Cell): The periodic pbi filter used cell2node.father->pLGlobalMapping->search() which only returns father-local indices, skipping non-local cells. On even-split partitions a periodic bnd's two cells can both be on other ranks, leaving cellRecCur empty after the filter (assertion failure). Fixed by refactoring into a two-pass approach: first pass collects candidate cells from node intersection for all bnds, then a ghost pull fetches cell2node and cell2nodePbi for ALL candidates, then second pass does the pbi filter using search_indexAppend on the ghost mapping. This correctly handles non-local cells on any partition.
  9. ctest parallel collision (test_MeshDistributedRead.cpp): All np variants wrote H5 files to the same temp directory. When ctest ran them in parallel, file corruption occurred. Fixed by including np in the temp directory name.

Definition in file test_MeshDistributedRead.cpp.

Macro Definition Documentation

◆ DOCTEST_CONFIG_IMPLEMENT

#define DOCTEST_CONFIG_IMPLEMENT

Definition at line 86 of file test_MeshDistributedRead.cpp.

◆ FOR_EACH_CONFIG

#define FOR_EACH_CONFIG (   body)
Value:
for (int ic = 0; ic < N_CONFIGS; ic++) \
{ \
CAPTURE(ic); \
CAPTURE(g_configs[ic].name); \
body \
}

Definition at line 416 of file test_MeshDistributedRead.cpp.

◆ FOR_EACH_CROSS_CONFIG

#define FOR_EACH_CROSS_CONFIG (   body)
Value:
if (!g_crossNpAvailable) \
return; \
for (int ic = 0; ic < N_CONFIGS; ic++) \
{ \
CAPTURE(ic); \
CAPTURE(g_configs[ic].name); \
body \
}

Definition at line 519 of file test_MeshDistributedRead.cpp.

Function Documentation

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 351 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [1/18]

TEST_CASE ( "CrossNp: cell2cellOrig globally unique"  )

Definition at line 584 of file test_MeshDistributedRead.cpp.

◆ TEST_CASE() [2/18]

TEST_CASE ( "CrossNp: every rank has cells"  )

Definition at line 557 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [3/18]

TEST_CASE ( "CrossNp: face2cell valid"  )

Definition at line 565 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [4/18]

TEST_CASE ( "CrossNp: global bnd count"  )

Definition at line 543 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [5/18]

TEST_CASE ( "CrossNp: global cell count"  )

Definition at line 529 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [6/18]

TEST_CASE ( "CrossNp: global face count"  )

Definition at line 550 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [7/18]

TEST_CASE ( "CrossNp: global node count"  )

Definition at line 536 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [8/18]

TEST_CASE ( "CrossNp: node2cell non-empty"  )

Definition at line 591 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [9/18]

TEST_CASE ( "SameNp: cell2cellOrig globally unique"  )

Definition at line 499 of file test_MeshDistributedRead.cpp.

◆ TEST_CASE() [10/18]

TEST_CASE ( "SameNp: coordinate bounding box is sane"  )

Definition at line 506 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [11/18]

TEST_CASE ( "SameNp: every rank has cells"  )

Definition at line 462 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [12/18]

TEST_CASE ( "SameNp: expected counts from config"  )

Definition at line 452 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [13/18]

TEST_CASE ( "SameNp: face2cell valid"  )

Definition at line 471 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [14/18]

TEST_CASE ( "SameNp: global bnd count"  )

Definition at line 438 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [15/18]

TEST_CASE ( "SameNp: global cell count"  )

Definition at line 424 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [16/18]

TEST_CASE ( "SameNp: global face count"  )

Definition at line 445 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [17/18]

TEST_CASE ( "SameNp: global node count"  )

Definition at line 431 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function:

◆ TEST_CASE() [18/18]

TEST_CASE ( "SameNp: node2cell non-empty"  )

Definition at line 490 of file test_MeshDistributedRead.cpp.

Here is the call graph for this function: