High-performance unstructured-mesh distributed CFD solver (compressible viscous Navier–Stokes equations).
apps/mesh_partition reads a CGNS mesh in parallel (PCGNS / parallel HDF5) across all MPI ranks, builds face–cell connectivity in a distributed fashion, partitions the dual graph (dKaMinPar), constructs a one-hop ghost layer (face neighbors + vertex-sharing neighbors for least-squares gradients), computes finite-volume geometric metrics, applies SFC/RCM cache-locality reordering, and exports a single topology-aware Parallel HDF5 container. Additionally, it generates a boundary-condition TOML configuration template and VTU/PVTU files for partition visualization.
apps/solver.cpp loads the xported HDF5 container, runs an exhaustive sanity audit, parse solver config, parse boundary conditions config (template is generated by mesh_partition, exact boundary condition types and values must be filled manualy, see below) and run solver. Output file in vtu format (one file per rank grouped in collection).
include/cfd/ Public headers (clean interface separation)
├── core/ Fundamental types (LocalIndex, GlobalIndex, precision)
├── mpi/ MPI wrappers, collective reductions, structured logging
├── mesh/ MeshPart SoA, geometric metrics, ghost layer, reordering
├── partition/ dKaMinPar wrapper + Space-Filling Curve rank mapping
├── io/cgns/ Parallel CGNS reader (PCGNS cgp_* API)
├── io/solver_mesh/ Parallel HDF5 mesh serializer and loader
├── io/vtk/ Parallel VTU/PVTU export for ParaView visualization
├── linalg/ Distributed linear algebra
├── solver/bc Boundary conditions types and manager
├── solver/eos Equation of state conpect and implementations (e.g ideal gas)
├── solver/fields General fields manager and fields view data structures for solvers
├── solver/gradient Gradient differential operator module
├── solver/limiter Limiters for high order schemes
├── solver/reconstruction High order methods (policies)
├── solver/riemann Riemann solvers for inviscid fluxes through faces
├── solver All methods for distributed cfd solver
src/ Library implementation sources mirroring include/
apps/ Executables (mesh_partition, solver_mesh_check)
tests/ Unit & integration tests (API & partitioner smoke tests)
external/ Some external modules (e.g tolm++)
examples/ Some examples (only solver and boundary configuration files, no mesh, no solution)
mesh/ Local test meshes (git-ignored)
out/ Output files (git-ignored)
cfd_mpi— MPI communication wrappers, topology logging, and assertions.cfd_mesh— Distributed mesh topology, halo exchange layers, geometric metrics, SFC/RCM reordering.cfd_partition— dKaMinPar dual-graph partitioner and SFC part-to-rank topological mapper.cfd_cgns_io— Collective parallel CGNS reader (cgp_*API).cfd_solver_mesh_io— High-throughput Parallel HDF5 writer/loader (H5FD_MPIO_COLLECTIVE).cfd_vtk_io— Buffered parallel VTU/PVTU mesh exporters.cfd_solver— All solver components (bc, fields, reconstructions, manages)cfd_linalg— All linear algebra module (fully independent from other modules)
- Compiler: GCC >= 11 (C++20 standard required)
- MPI: OpenMPI >= 4.1 or MPICH
- I/O Libraries: Parallel HDF5 (with MPI-IO support), CGNS >= 4.0 (built with Parallel HDF5)
- Partitioning & Concurrency: KaMinPar / dKaMinPar, Intel oneTBB
- Build System: CMake >= 3.28, Ninja
For a step-by-step installation guide (WSL2 Ubuntu / Linux HPC clusters), see INSTALL-AND-SETUP-EN.md.
# Configure build preset (Release by default, 32-bit global indexing)
cmake --preset release
# (Optional) Build with 64-bit global indexing for billion-cell meshes:
# cmake --preset release -DCFD_INDEX_64BIT=ON
# Compile with Ninja
cmake --build --preset release -j$(nproc)Build artifacts will appear in build/release/.
mkdir -p out
mpirun -np 4 build/release/mesh_partition mesh/mesh.cgns out/mesh.h5 \
--verbose \
--bc out/bc.toml \
--vtu out/vtu \
--reorder RCMKey CLI Options:
--verbose / -v: Print stage timings and partitioning balance.--bc <file>: Auto-generate boundary conditions TOML template.--vtu <dir>: Export partitioned domain to ParaView VTU/PVTU format.--reorder <method>: Local cache reordering strategy (NONE,RCM,HILBERT_SFC).
- Open
out/vtu/mesh.pvtuto inspect the volume mesh. Color by:rank— Subdomain spatial decomposition.local_id— Cache memory order (shows the Hilbert SFC curve path).volume— Cell finite-volume distribution.
- Open
out/vtu/mesh_bnd.pvtuto inspect boundary patches. Color bypatch_idto verify boundary condition assignments.
mpirun -np 4 build/release/solver out/mesh.h5 \
examples/wedge/solver.toml \
examples/wedge/bc.toml \
--verboseThe mesh container is rank-locked: it must be run with exactly the same
-np as mesh_partition. Solution dumps (rho, u, v, w, pressure, mach as CellData) are written as
<stem>.pvtu collections into the configured output directory.
The main solver execution parameters are specified in a TOML file (e.g. solver.toml). The configuration is split into seven sections: [numerics], [flow], [initial], [time], [output], [turbulence], and [linalg].
Both compressible (Density-Based) and segregated incompressible (SIMPLE) formulations are supported via the solver parameter in [numerics].
Solver Configuration Guide (Click to expand)
Configuration Sections
1. [numerics] — Solver Framework, Discretization & Limiters
Selects the solver formulation and controls numerical flux computation, spatial reconstruction order, limiters, and under-relaxation parameters.
| Key | Type | Allowed Values | Default | Description |
|---|---|---|---|---|
solver |
String |
"DENSITY_BASED", "SIMPLE"
|
"DENSITY_BASED" |
Solver architecture (Compressible Density-Based vs. Segregated Incompressible SIMPLE). |
flux |
String | "HLLC" |
Required for DENSITY_BASED |
Riemann flux solver. Forbidden if solver = "SIMPLE". |
alpha_u |
Float | 0.7 |
Velocity under-relaxation factor (Patankar). Allowed only for SIMPLE. |
|
alpha_p |
Float | 0.3 |
Pressure under-relaxation factor. Allowed only for SIMPLE. |
|
reconstruction |
String |
"FIRST_ORDER", "MUSCL", "MUSCL_DIRECTIONAL"
|
Required | Spatial accuracy scheme for convective terms. |
limiter |
String |
"VENKAT", "BARTH", "VAN_ALBADA" (for MUSCL),"MINMOD_1D", "VAN_ALBADA_1D" (for MUSCL_DIRECTIONAL) |
Required for MUSCL |
Slope limiter for gradient suppression near discontinuities. |
venkat_k |
Float | 0.5 |
Threshold parameter |
|
gradient |
String |
"GREEN_GAUSS_FACE", "GREEN_GAUSS_CELL","LEAST_SQUARES_FACE", "LEAST_SQUARES_NODE"
|
"GREEN_GAUSS_FACE" |
Gradient evaluation method. |
Validation Rules:
- If
solver = "DENSITY_BASED",fluxis strictly required; specifyingalpha_uoralpha_pwill trigger an unknown key error.- If
solver = "SIMPLE",fluxis forbidden;alpha_uandalpha_pmust be in the range$(0.0, 1.0]$ .- If
reconstruction = "FIRST_ORDER", thelimiterkey is not used.- If
reconstruction = "MUSCL",limiteris strictly required ("VENKAT","BARTH","VAN_ALBADA").- If
reconstruction = "MUSCL_DIRECTIONAL",limiteris strictly required ("MINMOD_1D","VAN_ALBADA_1D").
2. [flow] — Thermodynamic Model & Fluid Properties
Defines the working fluid, equation of state, and transport properties.
| Key | Type | Allowed Values | Default | Description |
|---|---|---|---|---|
eos |
String |
"IDEAL_GAS", "INCOMPRESSIBLE"
|
Required | Equation of State model ("IDEAL_GAS" for DENSITY_BASED, "INCOMPRESSIBLE" for SIMPLE). |
flow_model |
String |
"INVISCID_FLOW", "VISCOUS_FLOW"
|
Required for DENSITY_BASED( "VISCOUS_FLOW" for SIMPLE) |
Flow model formulation. |
gamma |
Float |
1.4) |
Required for IDEAL_GAS |
Specific heat ratio (INCOMPRESSIBLE. |
gas_constant |
Float |
287.05) |
Required for IDEAL_GAS |
Specific gas constant INCOMPRESSIBLE. |
prandtl |
Float |
0.71) |
Required for compressible VISCOUS_FLOW |
Laminar Prandtl number. Forbidden if flow_model = "INVISCID_FLOW" or eos = "INCOMPRESSIBLE". |
rho |
Float |
|
1.225 |
Fluid density (material constant for incompressible flow). Allowed only for INCOMPRESSIBLE. |
mu |
Float |
|
1.7894e-5 |
Molecular dynamic viscosity. Allowed only for INCOMPRESSIBLE. |
Validation Rules:
- For
DENSITY_BASED:eos = "IDEAL_GAS"is required.flow_modelmust be specified ("INVISCID_FLOW"or"VISCOUS_FLOW").gammaandgas_constantare required.- For
SIMPLE:eos = "INCOMPRESSIBLE"is required. Fluid propertiesrhoandmuare configured here. Keysgamma,gas_constant, andprandtlwill trigger an unknown key error.
3. [initial] — Initial Field Conditions
Sets the uniform initial flow field across all cells at
| Key | Type | Allowed Values | Default | Description |
|---|---|---|---|---|
velocity |
Array of 3 Floats | 3 numbers [$\text{m}/\text{s}$] ( |
Required | Initial Cartesian velocity vector |
pressure |
Float | Any Float for SIMPLE( DENSITY_BASED) |
0.0 for SIMPLE(Required for DENSITY_BASED) |
Initial static pressure [$\text{Pa}$]. In SIMPLE, represents relative/gauge pressure (can be |
rho |
Float |
|
Required for DENSITY_BASED |
Initial static density. Forbidden if solver = "SIMPLE" (configured in [flow]). |
Validation Rules:
- For
DENSITY_BASED:rho,pressure($> 0.0$ ), andvelocityare all strictly required.- For
SIMPLE:velocityis strictly required;pressuredefaults to0.0if omitted. Specifyingrhoin[initial]triggers an unknown key error.
4. [time] — Temporal Integration & Convergence
Governs time-stepping schemes, iteration limits, and stopping criteria.
| Key | Type | Allowed Values | Default | Description |
|---|---|---|---|---|
mode |
String |
"Steady", "Unsteady"
|
Required | Time mode scheme (Steady / Unsteady). |
scheme |
String |
"FORWARD_EULER", "BACKWARD_EULER"
|
Required for DENSITY_BASED |
Time integration scheme. Forbidden if solver = "SIMPLE". |
cfl |
Float |
0.5 – 25.0) |
Required for DENSITY_BASED |
Courant-Friedrichs-Lewy (CFL) number. Forbidden if solver = "SIMPLE". |
max_iterations |
Integer | Required | Maximum number of iterations (or inner iterations per time step in unsteady mode). | |
residual_tolerance |
Float |
1e-6) |
Required | Relative |
time_step |
Float |
|
Required for Unsteady |
Physical time step size |
max_time_steps |
Integer | Required for Unsteady |
Number of physical time steps. | |
bdf_order |
Integer |
|
2 |
Order of Backward Differentiation Formula for unsteady derivatives. |
Validation Rules:
- For
DENSITY_BASED:schemeandcflare strictly required.- For
SIMPLE:schemeandcflare forbidden (governed by under-relaxation and physical time stepping).- If
mode = "Unsteady",time_stepandmax_time_stepsare strictly required for both solvers.
5. [turbulence] — Turbulence Modeling (In Development)
Optional physics module for turbulent flow closure.
| Key | Type | Allowed Values | Default | Description |
|---|---|---|---|---|
model |
String | "SA" |
Required | Spalart-Allmaras 1-equation model. |
nu_inf_ratio |
Float | 3.0 |
Freestream ratio $\tilde{\nu}\infty / \nu{mol}$. | |
max_distance_sweeps |
Integer | 500 |
Maximum sweeps for wall-distance calculation. | |
distance_tolerance |
Float | 1.0e-8 |
Relative tolerance for wall-distance calculation. |
Validation Rule: Enabling
[turbulence]strictly requiresflow_model = "VISCOUS_FLOW"in[flow].
6. [output] — Diagnostics & Solution Export
Configures disk export frequency and console residual logging.
| Key | Type | Allowed Values | Default | Description |
|---|---|---|---|---|
directory |
String | Valid directory path | Required | Output directory for solution files and logs. |
field_interval |
Integer | Required | Step interval for writing 3D VTU solution files (0 disables intermediate writes). |
|
residual_interval |
Integer | Required | Step interval for logging convergence diagnostics to console/log. |
7. [linalg] — Linear Algebra Solver
Configures the iterative SLAE solver used by implicit schemes (BACKWARD_EULER) and the segregated SIMPLE solver (Momentum and Pressure Poisson equations). Optional; defaults are used if omitted.
| Key | Type | Allowed Values | Default | Description |
|---|---|---|---|---|
solver |
String | "BICGSTAB" |
"BICGSTAB" |
Iterative linear solver. |
preconditioner |
String |
"None", "SGS"
|
"None" |
Preconditioner ("None" or Symmetric Gauss-Seidel "SGS"). |
rel_tol |
Float | 1e-1 |
Relative tolerance for linear solver convergence. | |
abs_tol |
Float | 1e-30 |
Absolute tolerance floor. | |
max_iter |
Integer | 100 |
Maximum iterations per linear solve. | |
verbosity |
String |
"Silent", "Summary", "Verbose"
|
"Silent" |
Solver logging verbosity. |
res_verify |
Any | Allowed key | None | Optional flag for residual norm verification. |
Example Configuration (solver.toml)
[flow]
solver = "DENSITY_BASED"
flow_model = "INVISCID_FLOW"
eos = "IDEAL_GAS"
gamma = 1.4
gas_constant = 287.052874
[initial]
rho = 1.1768
pressure = 101325.0
velocity = [1041.0, 0.0, 0.0]
[numerics]
flux = "HLLC"
reconstruction = "MUSCL"
limiter = "VENKAT"
venkat_k = 0.5
gradient = "LEAST_SQUARES_FACE"
[time]
mode = "Steady"
scheme = "BACKWARD_EULER"
cfl = 25.0
max_iterations = 500
residual_tolerance = 1.0e-10
[output]
directory = "out/wedge_implicit_muscl"
field_interval = 1000
residual_interval = 250
[linalg]
solver = "BICGSTAB"
preconditioner = "SGS"
rel_tol = 1e-1
abs_tol = 1e-15
max_iter = 100
verbosity = "Summary"Boundary conditions are defined in a TOML configuration file via [[boundary_condition]] tables.
Note on Workflow: When running
mesh_partition, the partitioner automatically inspects the CGNS mesh patches and outputs a fully populated template configuration file containing allpatch_id,name,cgns_type, andglobal_face_countentries with defaultSLIP_WALLtypes. You only need to adjust thetypeand set the required physical parameters for each patch.
Boundary Conditions Configuration Guide (Click to expand)
Inflow Modes (SUPERSONIC_INLET, SUBSONIC_INLET, FARFIELD)
For patches that inject or transfer momentum (SUPERSONIC_INLET, SUBSONIC_INLET, FARFIELD), three mutually exclusive velocity specification modes are supported.
Warning (Ideal Gas Assumption): When using Mach-based modes (
MachAnglesorMachDirection) forSUBSONIC_INLETorFARFIELD, velocity magnitude is evaluated at initialization assuming Ideal Gas EOS kinematics ($a = \sqrt{\gamma R T}$ ).
| Mode | Required Keys | Optional / Default Keys | Description |
|---|---|---|---|
| Velocity Vector |
velocity (or velocity_inf) |
— | Direct Cartesian velocity components |
| Mach + Direction |
mach, direction
|
— | Mach number |
| Mach + Angles | mach |
alpha / alpha_deg (def: 0.0)beta / beta_deg (def: 0.0) |
Mach number |
-
Pressure: Specified via
porp_inf[Pa] (strictly positive). Required forSUPERSONIC_INLETandFARFIELD. Optional forSUBSONIC_INLET(defaults to reference pressure if omitted, as static pressure is extrapolated from the interior). -
Temperature: Specified via
tort_inf[K] (strictly positive). Required for all inflow types. -
Mutual Exclusivity Rule: Specifying direct
velocityalongsidemach,direction, oralpha/betawill trigger a parser validation error.
Supported Boundary Condition Types
1. SUPERSONIC_INLET
Full Dirichlet boundary condition fixing all 5 primitive variables (
-
Allowed parameters:
p(orp_inf),t(ort_inf), plus one of the three Inflow Modes.
2. SUBSONIC_INLET
Inflow boundary where velocities and temperature are fixed, while static pressure is extrapolated from the interior (
-
Allowed parameters:
t(ort_inf), plus one of the three Inflow Modes.p/p_infis optional.
3. FARFIELD
Non-reflecting characteristic boundary condition based on 1D Riemann invariants. Automatically switches between subsonic/supersonic inflow and outflow locally across each boundary face.
-
Allowed parameters:
p(orp_inf),t(ort_inf), plus one of the three Inflow Modes.
4. SUPERSONIC_OUTLET
Full zero-order extrapolation of all primitive variables and gradients (
-
Allowed parameters: Metadata only (
patch_id,type,name, etc.). No physical parameters.
5. SUBSONIC_OUTLET
Imposes a static backpressure while extrapolating velocity components and temperature from the interior domain (
-
Allowed parameters: Backpressure via
p,p_back, orp_outlet[Pa] (strictly positive).
6. SLIP_WALL & SYMMETRY
Inviscid wall / symmetry plane. Enforces zero normal velocity (
- Allowed parameters: Metadata only.
7. NO_SLIP_WALL (Isothermal Wall)
Viscous wall with no-slip condition ($\mathbf{v}{\text{wall}}$) and fixed wall temperature ($T{\text{wall}}$). Pressure gradient is zero (
-
Allowed parameters:
-
tort_wall[K] (default:288.15) -
velocity$[u, v, w]$ [m/s] (default:[0.0, 0.0, 0.0])
-
8. NO_SLIP_WALL_HEAT_FLUX / NO_SLIP_WALL_ADIABATIC
Viscous wall with no-slip condition (
-
Allowed parameters:
-
tmp_gradorheat_flux_grad[K/m] (default:0.0$\to$ Adiabatic wall$\partial T / \partial n = 0$ ) -
velocity$[u, v, w]$ [m/s] (default:[0.0, 0.0, 0.0])
-
Example Configuration (bc.toml)
# Farfield with Mach number and aerodynamic angles
[[boundary_condition]]
patch_id = 0
name = "Farfield_Outer"
type = "FARFIELD"
p_inf = 101325.0
t_inf = 288.15
mach = 0.85
alpha_deg = 2.5
beta_deg = 0.0
# Stationary Adiabatic Viscous Wall
[[boundary_condition]]
patch_id = 1
name = "Wing_Surface"
type = "NO_SLIP_WALL_HEAT_FLUX"
tmp_grad = 0.0 # dT/dn = 0 (Adiabatic)
velocity = [0.0, 0.0, 0.0]
# Isothermal Moving Wall
[[boundary_condition]]
patch_id = 2
name = "Moving_Belt"
type = "NO_SLIP_WALL"
t_wall = 320.0
velocity = [15.0, 0.0, 0.0]
# Subsonic Pressure Outlet
[[boundary_condition]]
patch_id = 3
name = "Nozzle_Exit"
type = "SUBSONIC_OUTLET"
p_back = 101325.0
# Symmetry Plane
[[boundary_condition]]
patch_id = 4
name = "Symmetry_Y"
type = "SYMMETRY"Global metadata attributes and per-partition offset tables (cell_offsets, face_offsets, node_offsets, comm_nb_offsets, part2rank, rank2part), followed by contiguous 1D/2D SoA datasets.
HDF5 Layout Tree (Click to expand)
mesh.h5
├── /metadata/ (Root Group Attributes)
│ ├── nprocs (int32 / int - Total MPI partition count)
│ ├── n_cells_global (uint64 - Total domain owned volume cells)
│ ├── n_faces_global (uint64 - Total domain unique interior + boundary faces)
│ ├── n_bfaces_global (uint64 - Total domain boundary faces)
│ ├── n_nodes_global (uint64 - Total domain unique mesh vertices)
│ ├── bbox_lo [3] (float64 - Domain minimum bounding box [x_min, y_min, z_min])
│ └── bbox_hi [3] (float64 - Domain maximum bounding box [x_max, y_max, z_max])
│
├── /partition/ (Partition Topology & Hyperslab Offset Tables for Collective MPI-IO)
│ ├── cell_offsets [nprocs + 1] (uint64 - Cumulative cell partition slice offsets)
│ ├── cell_nodes_offsets [nprocs + 1] (uint64 - Cumulative cell connectivity CSR offsets)
│ ├── face_offsets [nprocs + 1] (uint64 - Cumulative face partition slice offsets)
│ ├── face_nodes_offsets [nprocs + 1] (uint64 - Cumulative face connectivity CSR offsets)
│ ├── node_offsets [nprocs + 1] (uint64 - Cumulative node partition slice offsets)
│ ├── comm_nb_offsets [nprocs + 1] (uint64 - Cumulative MPI neighbor count offsets)
│ ├── part2rank [nprocs] (int32 - Spatial partition ID to MPI rank mapping)
│ └── rank2part [nprocs] (int32 - MPI rank to spatial partition ID mapping)
│
├── /cells/ (Volume Cells: Owned [0, n_own) followed by Halo Ghosts [n_own, n_cells))
│ ├── type [n_cells_total] (uint8 - CellType enum: TETRA, HEXA, PRISM, PYRA)
│ ├── gid [n_cells_total] (GlobalIndex ──► int32 / int64 - Global cell ID)
│ ├── donor [n_cells_total] (int32 - Owner rank for halo ghost cells, -1 for owned)
│ ├── volume [n_cells_total] (float64 - Precomputed cell volume [m^3])
│ ├── centroid [n_cells_total, 3] (float64 - Cell centroid coordinates [x, y, z])
│ ├── nodes_offsets [n_cells_total + 1](LocalIndex ──► int32 / int64 - CSR node index offsets)
│ └── nodes [total_cell_nodes] (LocalIndex ──► int32 / int64 - CSR cell-to-node connectivity)
│
├── /faces/ (Sorted monotonically by (owner, neigh) for L1/L2 cache locality)
│ ├── owner [n_faces_total] (LocalIndex ──► int32 / int64 - Owned cell index [0, n_own))
│ ├── neigh [n_faces_total] (LocalIndex ──► int32 / int64 - Neighbor cell index, or -1 for boundary)
│ ├── patch [n_faces_total] (PatchId ──► int32 - Boundary patch ID, or -1 for interior)
│ ├── type [n_faces_total] (uint8 - Face CellType enum: TRI, QUAD)
│ ├── area [n_faces_total] (float64 - Face surface area magnitude [m^2])
│ ├── normal [n_faces_total, 3] (float64 - Outward unit normal vector [nx, ny, nz] from owner)
│ ├── centroid [n_faces_total, 3] (float64 - Face centroid coordinates [x, y, z])
│ ├── nodes_offsets [n_faces_total + 1](LocalIndex ──► int32 / int64 - CSR node index offsets)
│ └── nodes [total_face_nodes] (LocalIndex ──► int32 / int64 - CSR face-to-node connectivity)
│
├── /nodes/ (Local Unique Node Pool)
│ ├── coords [n_nodes_total, 3] (float64 - Nodal coordinates [x, y, z])
│ └── gid [n_nodes_total] (GlobalIndex ──► int32 / int64 - Global node ID)
│
├── /comm/ (Zero-Copy Halo Exchange Communication Graphs for Solver)
│ ├── nb_ranks [total_neighbors] (int32 - Neighboring MPI rank IDs)
│ ├── send_offsets [total_nb + nprocs](LocalIndex ──► int32 / int64 - CSR offsets into send_owned_cells)
│ ├── recv_offsets [total_nb + nprocs](LocalIndex ──► int32 / int64 - CSR offsets into recv_ghost_cells)
│ ├── send_owned_cells [total_send_cells] (LocalIndex ──► int32 / int64 - Local owned cell indices to pack & send)
│ └── recv_ghost_cells [total_recv_cells] (LocalIndex ──► int32 / int64 - Local ghost cell indices to unpack & recv)
│
└── /patches/ (Boundary Condition Definitions & Surface Face CSR Maps)
├── names [n_patches] (fixed-string char[64] - Boundary patch names from CGNS)
├── cgns_types [n_patches] (fixed-string char[64] - CGNS BC types: BCWall, BCInflow, etc.)
├── patch_face_offsets [n_offsets_total] (LocalIndex ──► int32 / int64 - Rank-local CSR face offsets per patch)
└── patch_faces [total_patch_faces](LocalIndex ──► int32 / int64 - Local face indices belonging to patch)
Data of rank [offset[p], offset[p+1]) across all hyperslabs. All ranks perform non-interfering I/O using collective MPI-IO (H5FD_MPIO_COLLECTIVE).