|
DNDSR 0.2.1
Distributed Numeric Data Structure for CFV
|
Status: Implemented. C++ helpers are in
src/Geom/Mesh/Mesh_Helpers.hpp. Python helpers are inpython/DNDSR/Geom/utils.pyasread_mesh,prepare_mesh,build_bnd_mesh,build_fv,serialize_mesh, andmesh_h5_path. The legacycreate_mesh_from_CGNSwrapper is preserved for backward compatibility.
Mesh assembly logic is duplicated across at least 6 sites:
| Site | Language | Lines |
|---|---|---|
python/DNDSR/Geom/utils.py create_mesh_from_CGNS | Python | ~230 |
python/DNDSR/EulerP/EulerP_Solver.py ReadMesh | Python | thin wrapper |
src/Euler/EulerSolver_Init.hxx ReadMeshAndInitialize | C++ | ~370 |
app/Geom/partitionMeshSerial.cpp | C++ | ~60 |
app/Geom/meshSerial_Test.cpp | C++ | ~100 |
test/Geom/draw_meshes_2D.py | Python | ~50 (manual) |
Every test that builds a mesh (test_basic_geom, test_basic_fv, test_basic_cfv, test_cfv_dissdisp, test_basic_eulerP, test_solver, test_fv_correctness, test_vr_correctness) calls create_mesh_from_CGNS followed by ad-hoc FV setup.
The problems:
EulerP_Solver.BuildFV and test_basic_fv.get_fv.name2ID is only defined in the Serial branch of create_mesh_from_CGNS but is returned unconditionally (bug: UnboundLocalError in Parallel/Distributed modes).Five helpers, each doing one job. They compose linearly:
All helpers live in python/DNDSR/Geom/utils.py (Python side). The C++ solver (EulerSolver_Init.hxx) keeps its own pipeline but should converge on the same structure over time.
Returns a MeshReadResult dataclass:
Auto-detection:
If read_mode is None, infer from file extension:
.cgns -> "cgns" (serial CGNS read + Metis partition).dnds.h5 -> "h5" (distributed read: even-split + ParMetis)Explicit read_mode override is still available for edge cases.
Behavior by mode:
_build_ghost_primary(mesh)_build_ghost_primarydefault_serializer_factory())ReadSerializeAndDistribute(serializer, "meshPart", partition_options) – even-split read + ParMetis repartition, works with any MPI size_build_ghost_primary(mesh)The internal helper _build_ghost_primary encapsulates the 5-step connectivity+ghost sequence identical across all branches:
What it does NOT do:
Mutates mesh in place. Steps:
mesh.ReorderLocalCells(nParts=reorder_parts, nPartsInner=reorder_inner_parts)mesh.InterpolateFace()mesh.AssertOnFaces()AdjLocal2GlobalN2CB -> BuildGhostN2CB -> AdjGlobal2LocalN2CBmesh.BuildNodeWallDist(wall_dist_predicate, wall_dist_options) if predicate givenAdjLocal2GlobalPrimary -> reader.BuildSerialOut -> AdjGlobal2LocalPrimary if build_serial_outmesh.RecreatePeriodicNodes()mesh.BuildVTKConnectivity()Note: elevation smoothing is NOT included here. It is a separate stage between prepare_mesh and build_bnd_mesh (see Resolved Questions).
Steps (same as current create_bnd_mesh but with explicit serial_out control):
mesh.ConstructBndMesh(mesh_bnd)mesh_bnd.RecreatePeriodicNodes()mesh_bnd.BuildVTKConnectivity()Encapsulates the 14-step FV construction currently duplicated in EulerP_Solver.BuildFV and test_basic_fv.get_fv:
CFV.FiniteVolume(mpi, mesh)settings into defaults via fv.GetSettings().update(settings)fv.ParseSettings(merged)SetCellAtrBasic, ConstructCellVolume, ConstructCellBary, ConstructCellCent, ConstructCellIntJacobiDet, ConstructCellIntPPhysics, ConstructCellAlignedHBox, ConstructCellMajorHBoxCoordInertiaSetFaceAtrBasic, ConstructFaceCent, ConstructFaceArea, ConstructFaceIntJacobiDet, ConstructFaceIntPPhysics, ConstructFaceUnitNorm, ConstructFaceMeanNormConstructCellSmoothScaleSteps:
mesh.AdjLocal2GlobalPrimary()mesh.WriteSerialize(serializer, "meshPart")mesh.AdjGlobal2LocalPrimary()This is the Python equivalent of the partitionMeshOnly path in C++.
MeshReadResult and BndMeshResult dataclasses to utils.py._build_ghost_primary from current code.read_mesh, prepare_mesh, build_bnd_mesh, build_fv, serialize_mesh in utils.py.name2ID bug (set to None for H5 modes, include in MeshReadResult).create_mesh_from_CGNS as a thin wrapper that calls read_mesh + prepare_mesh with the same signature for backward compatibility. Mark it deprecated.create_bnd_mesh as a thin wrapper around build_bnd_mesh.EulerP_Solver.ReadMesh to use the new helpers.EulerP_Solver.BuildFV to use build_fv.create_mesh_from_CGNS and create_bnd_mesh once all callers are migrated.H5 file path convention: read_mesh auto-detects the read mode from the file path with predefined conventions. When read_mode is None:
.cgns -> CGNS serial read.dnds.h5 -> H5 distributed read (even-split + ParMetis). This is the safest default: works with any MPI size regardless of how the file was written.read_mode override is still available.For the H5 path naming convention used by serialize_mesh, a utility function mesh_h5_path(base, mpi_size, elevation, bisect) is provided:
This keeps the convention in one place rather than scattered across callers.
Elevation smoothing: Kept as a separate stage between prepare_mesh and build_bnd_mesh / build_fv. The solver calls the smoothing methods directly on the mesh:
This avoids coupling prepare_mesh to the BC handler and keeps the smoothing logic visible at the call site.
prepare_mesh with optional parameters defaulting to no-op. When read_mode was "h5_distributed" or "h5_parallel" (i.e. reading an already-partitioned mesh), the transforms default to being omitted since the stored mesh may already have been transformed before serialization. Callers can still pass explicit transform parameters if needed.prepare_mesh.