Owns node coordinates and the derived finite-volume metrics for the 2D Euler solver: cell areas (vol), face area-normal vectors (s_xi, s_eta), and cell centres (xc, yc). Geometry is read from a single-block Plot3D grid file (ASCII or binary). On a uniform Cartesian grid the metrics are unused — the residual keeps its scalar dx/dy fast path (bit-for-bit). Phase A builds the whole-domain (serial) metrics; local slicing for MPI is added in Phase D.
Dependency rule: this module must NOT use config_2d (config_2d uses it).
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | public, | parameter | :: | MESH2D_MAX_DIM | = | 1000000 |
Sanity caps on Plot3D header dimensions. Per-axis node cap mirrors the spirit of the 1D n_cell schema bound; the total-node cap is checked via an int64 product so a pathological header cannot overflow the default-integer ni*nj before the allocation's stat= is consulted. |
| integer(kind=int64), | private, | parameter | :: | MESH2D_MAX_POINTS | = | 100000000_int64 |
Grid metrics for the 2D structured scheme.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| logical, | public | :: | uniform | = | .true. | ||
| integer, | public | :: | nx | = | 0 | ||
| integer, | public | :: | ny | = | 0 | ||
| real(kind=wp), | public | :: | dx_uniform | = | 0.0_wp | ||
| real(kind=wp), | public | :: | dy_uniform | = | 0.0_wp | ||
| real(kind=wp), | public, | allocatable | :: | x_node(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | y_node(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | vol(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | s_xi(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | s_eta(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | xc(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | yc(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | sx_xi(:,:,:) |
Nodal FDM transformation metrics (allocated only for curvilinear FDM). |
||
| real(kind=wp), | public, | allocatable | :: | sx_eta(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | jac(:,:) | |||
| logical, | public | :: | fdm_curvilinear | = | .false. |
True iff every element of a 2D coordinate array is finite (no NaN/Inf).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | a(:,:) |
Stencil width for the high-order conservative-flux metric operator on n nodes: 6 (6th-order) when n>=6, 4 (4th-order) when n>=4, else 2 (the classical central scheme). Even widths keep the interior operator a symmetric central difference, whose conservative flux telescopes cleanly.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | n |
Read a single-block 2D Plot3D grid. Header ni nj, then all x(i,j)
(i fastest), then all y(i,j). ASCII (binary=.false.) or Fortran
unformatted sequential (binary=.true.).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | path | |||
| logical, | intent(in) | :: | binary | |||
| real(kind=wp), | intent(out), | allocatable | :: | xg(:,:) | ||
| real(kind=wp), | intent(out), | allocatable | :: | yg(:,:) | ||
| integer, | intent(out) | :: | ni | |||
| integer, | intent(out) | :: | nj | |||
| logical, | intent(out) | :: | is_ok | |||
| character(len=*), | intent(out) | :: | message |
Validate a Plot3D header: lower bound (>= 2 nodes per axis) and upper sanity caps (per-axis and total node count). Returns is_ok=.false. with a descriptive message on violation.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | ni | |||
| integer, | intent(in) | :: | nj | |||
| logical, | intent(out) | :: | is_ok | |||
| character(len=*), | intent(out) | :: | message |
Build the global (whole-domain) mesh from either a uniform specification or a Plot3D grid file. For 'uniform', nx/ny are read from the caller. For 'plot3d', ni/nj are read from the file and nx/ny are written back (intent(inout)) so the caller knows the derived sizes. Calls compute_metrics_2d at the end and propagates its status — a metric failure (e.g. a folded or zero-area cell) fails the build.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(mesh_2d_t), | intent(inout) | :: | mesh | |||
| character(len=*), | intent(in) | :: | grid_type | |||
| character(len=*), | intent(in) | :: | grid_file | |||
| logical, | intent(in) | :: | grid_binary | |||
| integer, | intent(inout) | :: | nx | |||
| integer, | intent(inout) | :: | ny | |||
| real(kind=wp), | intent(in) | :: | x_left | |||
| real(kind=wp), | intent(in) | :: | x_right | |||
| real(kind=wp), | intent(in) | :: | y_left | |||
| real(kind=wp), | intent(in) | :: | y_right | |||
| logical, | intent(out) | :: | is_ok | |||
| character(len=*), | intent(out) | :: | message |
Compute finite-volume metrics from node coordinates already in mesh%x_node / mesh%y_node. Allocates (with stat=) and fills vol(nx,ny), s_xi(2,nx+1,ny), s_eta(2,nx,ny+1), xc(nx,ny), yc(nx,ny). Returns is_ok=.false. and a diagnostic message naming the first (i,j) with non-positive cell area.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(mesh_2d_t), | intent(inout) | :: | mesh | |||
| logical, | intent(out) | :: | is_ok | |||
| character(len=*), | intent(out) | :: | message |
Lagrange weights c(1:w) for interpolating/extrapolating a unit-spacing line sampled at local positions 0,1,...,w-1 to the (possibly out-of-range) target offset t. Used to build the ghost values that close the symmetric stencil at domain boundaries.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | w | |||
| real(kind=wp), | intent(in) | :: | t | |||
| real(kind=wp), | intent(out) | :: | c(:) |
High-order freestream-consistent CONSERVATIVE-FLUX face values of a unit-spacing nodal line g(1..n): hf(1..n+1), where face iface lies between node iface-1 and node iface. The construction guarantees the telescoping identity
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | g(:) | |||
| real(kind=wp), | intent(out) | :: | hf(:) |
Matching high-order first derivative of a unit-spacing nodal line: the undivided difference of the conservative-flux face values (cons_flux_1d_unit), so dg(i) reproduces the high-order central derivative AND stays bit-consistent with the face metrics built from the same operator (the property that makes freestream telescope to round-off, design spec §5.3).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | g(:) | |||
| real(kind=wp), | intent(out) | :: | dg(:) |
Compute NODAL transformation metrics for curvilinear FDM from the node coordinates already in mesh%x_node / mesh%y_node (shape (nx, ny), the Plot3D points treated as nodes; unit computational spacing dxi=deta=1).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(mesh_2d_t), | intent(inout) | :: | mesh | |||
| logical, | intent(out) | :: | is_ok | |||
| character(len=*), | intent(out) | :: | message |
Build a curvilinear-FDM mesh from a single-block Plot3D grid: the Plot3D points are treated as NODES (mesh % nx = ni, mesh % ny = nj, nodes lying ON the boundaries), mesh % uniform = .false., dx/dy = 0 (unused on the curvilinear path), then compute_metrics_fdm_2d fills the nodal metrics. Distinct from build_mesh_2d_global's 'plot3d' branch, which treats the points as CELL CORNERS (nx = ni-1 cells) and builds finite-volume metrics.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(mesh_2d_t), | intent(inout) | :: | mesh | |||
| character(len=*), | intent(in) | :: | grid_file | |||
| logical, | intent(in) | :: | grid_binary | |||
| logical, | intent(out) | :: | is_ok | |||
| character(len=*), | intent(out) | :: | message |
Build a uniform Cartesian NODAL mesh for the finite-difference (FDM) path. Unlike build_mesh_2d_global's 'uniform' branch (which stores CELL counts and derives FV metrics), this stores NODE counts directly: mesh % nx = npx, mesh % ny = npy, with grid points lying ON both boundaries. The spacing is dx = (x_right - x_left) / (npx - 1) (equal to the FV cell size for the same number of cells). The FV metric arrays (vol, s_xi, s_eta, xc, yc) are left UNALLOCATED on purpose — the uniform FDM residual divides by the scalar dx/dy, not by vol — so this builder does NOT call compute_metrics_2d.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(mesh_2d_t), | intent(inout) | :: | mesh | |||
| integer, | intent(in) | :: | npx | |||
| integer, | intent(in) | :: | npy | |||
| real(kind=wp), | intent(in) | :: | x_left | |||
| real(kind=wp), | intent(in) | :: | x_right | |||
| real(kind=wp), | intent(in) | :: | y_left | |||
| real(kind=wp), | intent(in) | :: | y_right |
Slice the (global) metric arrays of mesh into this rank's local sub-block.
Cells ix_first..ix_first+nx_local-1, iy_first..iy_first+ny_local-1 (1-based
global). xi-faces span nx_local+1 columns starting at global column
ix_first; eta-faces span ny_local+1 rows starting at iy_first. Shared
inter-rank faces are identical on both ranks because both slice the same
global metrics. No-op for uniform grids (they use scalar dx/dy).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(mesh_2d_t), | intent(inout) | :: | mesh | |||
| integer, | intent(in) | :: | ix_first | |||
| integer, | intent(in) | :: | iy_first | |||
| integer, | intent(in) | :: | nx_local | |||
| integer, | intent(in) | :: | ny_local | |||
| logical, | intent(out) | :: | is_ok | |||
| character(len=*), | intent(out) | :: | message |