mesh_2d Module

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).



Variables

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

Derived Types

type, public ::  mesh_2d_t

Grid metrics for the 2D structured scheme.

Components

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.

Functions

private pure function all_finite_2d(a) result(ok)

True iff every element of a 2D coordinate array is finite (no NaN/Inf).

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: a(:,:)

Return Value logical

private pure function cons_width(n) result(w)

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.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

Return Value integer


Subroutines

public subroutine read_plot3d_2d(path, binary, xg, yg, ni, nj, is_ok, message)

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.).

Arguments

Type IntentOptional 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

public subroutine check_plot3d_dims(ni, nj, is_ok, 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.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: ni
integer, intent(in) :: nj
logical, intent(out) :: is_ok
character(len=*), intent(out) :: message

public subroutine build_mesh_2d_global(mesh, grid_type, grid_file, grid_binary, nx, ny, x_left, x_right, y_left, y_right, is_ok, 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.

Arguments

Type IntentOptional 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

public subroutine compute_metrics_2d(mesh, is_ok, 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.

Read more…

Arguments

Type IntentOptional Attributes Name
type(mesh_2d_t), intent(inout) :: mesh
logical, intent(out) :: is_ok
character(len=*), intent(out) :: message

private pure subroutine lagrange_unit_weights(w, t, c)

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.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: w
real(kind=wp), intent(in) :: t
real(kind=wp), intent(out) :: c(:)

private pure subroutine cons_flux_1d_unit(g, hf)

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

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: g(:)
real(kind=wp), intent(out) :: hf(:)

private pure subroutine deriv_1d_unit(g, dg)

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).

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: g(:)
real(kind=wp), intent(out) :: dg(:)

public subroutine compute_metrics_fdm_2d(mesh, is_ok, message)

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).

Read more…

Arguments

Type IntentOptional Attributes Name
type(mesh_2d_t), intent(inout) :: mesh
logical, intent(out) :: is_ok
character(len=*), intent(out) :: message

public subroutine build_mesh_2d_fdm_curvilinear(mesh, grid_file, grid_binary, is_ok, 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.

Arguments

Type IntentOptional 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

public subroutine build_mesh_2d_uniform_nodal(mesh, npx, npy, x_left, x_right, y_left, y_right)

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.

Arguments

Type IntentOptional 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

public subroutine build_mesh_2d_local(mesh, ix_first, iy_first, nx_local, ny_local, is_ok, message)

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).

Arguments

Type IntentOptional 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