At np>1 every rank owns a tile of the global domain. gather_and_write_2d
collects all tiles onto rank 0 via point-to-point MPI (simpler than
MPI_Gatherv for irregular 2D blocks), assembles the full (neq2d,nx,ny) field
on rank 0, and writes the same "x y rho u v p" ASCII format that
write_result_2d produces at np=1.
At np=1 this is identical to write_result_2d (root receives nothing, just writes its own block which covers the whole domain).
The Cartesian communicator (from mpi_cart_2d) is used consistently so that rank renumbering by MPI_Cart_create(reorder=.true.) cannot cause a mismatch between gather source/destination and decomp placement indices.
Legacy-MPI note: MS-MPI ships only the legacy use mpi module; OpenMPI
ships both. We guard with CFD_SOLVER_LEGACY_MPI in the same way as the
other Phase-2D MPI source files.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private, | parameter | :: | TAG_META | = | 3001 | |
| integer, | private, | parameter | :: | TAG_BLOCK | = | 3002 | |
| integer, | private, | parameter | :: | TAG_COORD | = | 3003 |
(TAG_COORD+1 = 3004 carries the y block) |
| integer, | private, | parameter | :: | TAG_GHOST_L | = | 3005 |
Boundary-ghost frame slabs (checkpoint v6; see gather_boundary_ghosts_to_root). |
| integer, | private, | parameter | :: | TAG_GHOST_R | = | 3006 | |
| integer, | private, | parameter | :: | TAG_GHOST_B | = | 3007 | |
| integer, | private, | parameter | :: | TAG_GHOST_T | = | 3008 |
Gather all per-rank tiles to rank 0 and write the global field as ASCII.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(solver_state_2d_t), | intent(in) | :: | state |
Solver state (ub(:,1:nx_local,1:ny_local) = interior cells). |
||
| character(len=*), | intent(in) | :: | filename |
Output path (written by rank 0 only). |
||
| logical, | intent(out) | :: | is_ok |
.true. on success, .false. on I/O or MPI error. |
||
| character(len=*), | intent(out) | :: | message |
Human-readable error description on failure. |
Gather all per-rank tiles to rank 0, assembling the full global solution field.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(solver_state_2d_t), | intent(in) | :: | state |
Solver state (ub(:,1:nx_local,1:ny_local) = interior cells). |
||
| real(kind=wp), | intent(out), | allocatable | :: | global_field(:,:,:) | ||
| logical, | intent(out) | :: | is_ok |
.true. on local success; caller reduces if needed. |
||
| character(len=*), | intent(out) | :: | message |
Human-readable error on failure. |
||
| real(kind=wp), | intent(out), | optional, | allocatable | :: | global_xc(:,:) | |
| real(kind=wp), | intent(out), | optional, | allocatable | :: | global_yc(:,:) |
Write the assembled global field to filename in the standard ASCII format.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | global_field(:,:,:) | |||
| type(solver_state_2d_t), | intent(in) | :: | state | |||
| character(len=*), | intent(in) | :: | filename | |||
| logical, | intent(out) | :: | is_ok | |||
| character(len=*), | intent(out) | :: | message | |||
| real(kind=wp), | intent(in), | optional | :: | xc(:,:) | ||
| real(kind=wp), | intent(in), | optional | :: | yc(:,:) |
Write the assembled global field as legacy-ASCII VTK STRUCTURED_POINTS. Cell-centred: ORIGIN at the first cell centre, SPACING=(dx,dy). Emits SCALARS rho, SCALARS pressure, VECTORS velocity (i fastest, then j).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | global_field(:,:,:) | |||
| type(solver_state_2d_t), | intent(in) | :: | state | |||
| character(len=*), | intent(in) | :: | filename | |||
| logical, | intent(out) | :: | is_ok | |||
| character(len=*), | intent(out) | :: | message |
Slab geometry of one rank's owned piece of the GLOBAL boundary-ghost
frame (the four width-h bands outside the global interior, corners
included). Ownership is disjoint and exhaustive: the left/right bands
cover global rows 1..ny_g only; the bottom/top bands span the FULL
padded width 1-h..nx_g+h and therefore own the four corners. A rank
owns a band segment iff its tile touches that global edge; a
bottom/top-edge rank's segment extends into the corner columns iff it
is also a left/right-edge rank (ilo/ihi below, in LOCAL i). Ghost
cells of a rank that are NOT global-boundary cells are interior MPI-halo
words: they are refreshed from neighbour interiors by the next halo
exchange and are deliberately not part of the frame.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | ix1 | |||
| integer, | intent(in) | :: | iy1 | |||
| integer, | intent(in) | :: | nxl | |||
| integer, | intent(in) | :: | nyl | |||
| integer, | intent(in) | :: | nx_g | |||
| integer, | intent(in) | :: | ny_g | |||
| integer, | intent(in) | :: | h | |||
| logical, | intent(out) | :: | has_l | |||
| logical, | intent(out) | :: | has_r | |||
| logical, | intent(out) | :: | has_b | |||
| logical, | intent(out) | :: | has_t | |||
| integer, | intent(out) | :: | ilo | |||
| integer, | intent(out) | :: | ihi |
Gather the GLOBAL boundary-ghost frame to cart rank 0: the four width-h
ghost bands outside the global interior, corners included — every ghost
cell of every rank that is NOT an interior MPI-halo cell. The 2D twin of
1D's gather_edge_ghosts_to_root (checkpoint v6; 1D's is v5/F2): the
checkpoint must persist these words because the multi-stage whole-array
RK kernels leave a stage-snapshot blend in them that is not
reconstructable from the interior (see checkpoint_2d.f90's record-block
comment for the full root cause).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(solver_state_2d_t), | intent(in) | :: | state |
This rank's solver state ( |
||
| real(kind=wp), | intent(inout) | :: | lft(:,:,:) | |||
| real(kind=wp), | intent(inout) | :: | rgt(:,:,:) | |||
| real(kind=wp), | intent(inout) | :: | bot(:,:,:) | |||
| real(kind=wp), | intent(inout) | :: | top(:,:,:) |
Allocate buf to (n1, n2, n3) and blocking-receive one frame slab into
it from cart rank src (gather_boundary_ghosts_to_root's root side).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout), | allocatable | :: | buf(:,:,:) | ||
| integer, | intent(in) | :: | n1 | |||
| integer, | intent(in) | :: | n2 | |||
| integer, | intent(in) | :: | n3 | |||
| integer, | intent(in) | :: | src | |||
| integer, | intent(in) | :: | tag | |||
| integer, | intent(in) | :: | comm | |||
| character(len=*), | intent(in) | :: | which |
Deallocate a frame slab buffer with the mandatory stat check.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout), | allocatable | :: | buf(:,:,:) | ||
| character(len=*), | intent(in) | :: | which |
Inverse of gather_boundary_ghosts_to_root: deliver the checkpoint's
GLOBAL boundary-ghost frame bands into this rank's ub ghost cells.
Same band layout and disjoint ownership as the gather (the slab geometry
lives ONLY in frame_slab_extents, so gather and scatter cannot drift).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(solver_state_2d_t), | intent(inout) | :: | state |
This rank's solver state ( |
||
| real(kind=wp), | intent(in) | :: | lft(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | rgt(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | bot(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | top(:,:,:) |