Per-layer prognostic state for the ocean dynamical core.
Layout mirrors the 2D barotropic_state_t, lifted to (i, j, k):
Lives at ocean_state%multilayer when sim_type='ocean'.
Caller must set this%nz_ml before calling init — typically
threaded through from cfg%nz_layers in state_init_from_config.
Per-layer multilayer C-grid state.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public, | allocatable | :: | flux_h_layer(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | h_av_layer(:,:,:) |
Step time-mean layer thickness, shape (nx, ny, nz_ml). MOM6 |
||
| real(kind=wp), | public, | allocatable | :: | h_layer(:,:,:) |
Layer thickness at cell centres (m), shape (nx, ny, nz_ml). |
||
| real(kind=wp), | public, | allocatable | :: | h_layer0(:,:,:) |
RK2 save of h_layer at start of outer step. |
||
| real(kind=wp), | public, | allocatable | :: | heat_budget_geothermal(:,:,:) |
hTr (K·m) change per cell per step attributed to the geothermal bottom-heat-flux kernel. Populated only at the lowest massive layer (k=1 in the common case); zero elsewhere. Sign convention: positive = source into the ocean from below. |
||
| real(kind=wp), | public, | allocatable | :: | heat_budget_hdiff(:,:,:) |
hTr (K·m) change per cell per layer per step attributed to the Laplacian horizontal-diffusion kernel for temperature. Closed walls (wall faces forced to zero) ⇒ spatial integral telescopes to zero. |
||
| real(kind=wp), | public, | allocatable | :: | heat_budget_horiz_adv(:,:,:) |
hTr (°C·m) change per cell per layer, accumulated (summed)
across BOTH RK2 stages from t=0 ( |
||
| real(kind=wp), | public, | allocatable | :: | heat_budget_remap(:,:,:) |
Per-cell |
||
| real(kind=wp), | public, | allocatable | :: | heat_budget_sponge(:,:,:) |
hTr (K·m) change per cell per layer per step attributed to
the map-driven sponge’s tracer relaxation
( |
||
| real(kind=wp), | public, | allocatable | :: | heat_budget_surface(:,:,:) |
hTr (K·m) change per cell per step attributed to the surface
heat-flux kernel. Populated only at |
||
| real(kind=wp), | public, | allocatable | :: | heat_budget_vdiff(:,:,:) |
hTr (K·m) change per cell per layer per step attributed to the backward-Euler vertical-diffusion tridiag solve for temperature. Closed BCs (no flux through bed or surface) ⇒ column sum telescopes to zero. |
||
| real(kind=wp), | public, | allocatable | :: | heat_budget_vert_adv(:,:,:) |
hTr (K·m) change per cell per layer per step attributed to the first-order-upwind vertical-advection kernel for temperature. Closed-BC kernel: column sum telescopes to zero, so the spatial integral is zero to FP. |
||
| real(kind=wp), | public, | allocatable | :: | hu_face_x_layer(:,:,:) |
h*u at the same west-face stagger (m^2/s). |
||
| real(kind=wp), | public, | allocatable | :: | hv_face_y_layer(:,:,:) |
h*v at the same south-face stagger. |
||
| integer, | public | :: | idx_age | = | 0 |
Index into tracers(:) for the ideal-age tracer. 0 = not registered. When > 0, the dyn step ages at 1 s/s and zeros the surface layer (k = nz_ml) every step. No EOS coupling. |
|
| integer, | public | :: | idx_pseudo_salt | = | 0 |
Index into tracers(:) for the pseudo-salt verification tracer. 0 = not registered. |
|
| integer, | public | :: | idx_salinity | = | 0 |
Index into tracers(:) for salinity. 0 = not registered. |
|
| integer, | public | :: | idx_temperature | = | 0 |
Index into tracers(:) for temperature. 0 = not registered. |
|
| logical, | public | :: | is_init | = | .false. |
True between |
|
| integer, | public, | allocatable | :: | k_bot(:,:) |
Deepest live layer at cell centres, shape (nx, ny). |
||
| integer, | public, | allocatable | :: | k_bot_u(:,:) |
u-face twin, shape (nx+1, ny). |
||
| integer, | public, | allocatable | :: | k_bot_v(:,:) |
v-face twin, shape (nx, ny+1). Same |
||
| integer, | public, | allocatable | :: | k_top(:,:) |
Shallowest live layer at cell centres, shape (nx, ny). |
||
| integer, | public, | allocatable | :: | k_top_u(:,:) |
u-face twin, shape (nx+1, ny). |
||
| integer, | public, | allocatable | :: | k_top_v(:,:) |
v-face twin, shape (nx, ny+1). Same |
||
| real(kind=wp), | public, | allocatable | :: | mass_budget_continuity(:,:,:) |
Mass change per cell per step attributed to continuity-PPM divergence (m·dt units; the budget integral over volume recovers m³). Shape (nx, ny, nz_ml). Zero in a closed basin (perfect telescope). |
||
| real(kind=wp), | public, | allocatable | :: | mass_budget_remap(:,:,:) |
Per-cell |
||
| real(kind=wp), | public, | allocatable | :: | mass_flux_x_layer(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mass_flux_y_layer(:,:,:) | |||
| real(kind=wp), | public | :: | mass_out | = | 0.0_wp |
Cumulative mass (kg) that has left the domain through its open
boundaries since t=0 (positive = outflow), accumulated per RK2
stage from the continuity divergence ( |
|
| integer(kind=int64), | public | :: | mass_out_efp(EFP_DIGITS) | = | 0_int64 |
This rank’s |
|
| logical, | public | :: | mass_out_efp_on | = | .false. |
Also accumulate |
|
| integer(kind=int64), | public | :: | mass_out_efp_poison | = | 0_int64 |
Non-finite counter for |
|
| logical, | public | :: | mass_out_tracked | = | .false. |
Set once the dyn step has accumulated |
|
| real(kind=wp), | public | :: | mass_src | = | 0.0_wp |
Cumulative mass (kg) ADDED to the domain since t=0 by a
tracked volume SOURCE (positive = added), the mass twin of
|
|
| integer, | public | :: | nz_ml | = | 0 |
Number of multilayer levels (k=1 bed, k=nz_ml surface). |
|
| real(kind=wp), | public, | allocatable | :: | p_top(:,:) | |||
| logical, | public | :: | registry_locked | = | .false. |
Set by |
|
| real(kind=wp), | public, | allocatable | :: | rho_layer(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | salt_budget_hdiff(:,:,:) |
Salinity analogue of |
||
| real(kind=wp), | public, | allocatable | :: | salt_budget_horiz_adv(:,:,:) |
Salinity analogue (PSU·m) of |
||
| real(kind=wp), | public, | allocatable | :: | salt_budget_remap(:,:,:) |
Salinity analogue. |
||
| real(kind=wp), | public, | allocatable | :: | salt_budget_sponge(:,:,:) |
hTr (PSU·m) change per cell per layer per step attributed to
the map-driven sponge’s tracer relaxation. Same shape +
indexing convention as |
||
| real(kind=wp), | public, | allocatable | :: | salt_budget_surface(:,:,:) |
hTr (PSU·m) change per cell per step attributed to the
surface salt-flux kernel. Same shape + indexing convention
as |
||
| real(kind=wp), | public, | allocatable | :: | salt_budget_vdiff(:,:,:) |
Salinity analogue of |
||
| real(kind=wp), | public, | allocatable | :: | salt_budget_vert_adv(:,:,:) |
hTr (PSU·m) change per cell per layer per step for salinity. Same closed-BC telescope property. |
||
| type(tracer_t), | public, | allocatable | :: | tracers(:) |
Registered prognostic tracers. |
||
| real(kind=wp), | public, | allocatable | :: | u_av_layer(:,:,:) |
Step time-mean x face velocity, shape (nx+1, ny, nz_ml). MOM6 |
||
| real(kind=wp), | public, | allocatable | :: | u_face_x_layer(:,:,:) |
x-velocity at the WEST face of cell (i,j,k), shape
(nx+1, ny, nz_ml): face i sits between cells i-1 and i, so a
cell’s divergence reads faces (i, i+1) — the convention every
consumer (continuity |
||
| real(kind=wp), | public, | allocatable | :: | u_face_x_layer0(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | v_av_layer(:,:,:) |
Step time-mean y face velocity, shape (nx, ny+1, nz_ml). MOM6 |
||
| real(kind=wp), | public, | allocatable | :: | v_face_y_layer(:,:,:) |
y-velocity at the SOUTH face of cell (i,j,k), shape
(nx, ny+1, nz_ml): face j sits between cells j-1 and j
(same stagger rule as |
||
| real(kind=wp), | public, | allocatable | :: | v_face_y_layer0(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | w_interface(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | wet_mask(:,:) |
| procedure, public, non_overridable :: bytes => multilayer_state_bytes | |
| procedure, public, non_overridable :: destroy => multilayer_state_destroy | |
| procedure, public, non_overridable :: enforce_vanished_content => multilayer_enforce_vanished_content | |
| procedure, public, non_overridable :: enforce_vanished_content_host => multilayer_enforce_vanished_content_host | |
| procedure, public, non_overridable :: enter_data => multilayer_state_enter_data | |
| procedure, public, non_overridable :: exit_data => multilayer_state_exit_data | |
| procedure, public, non_overridable :: init => multilayer_state_init | |
| procedure, public, non_overridable :: register_passive_tracer => multilayer_register_passive_tracer | |
| procedure, public, non_overridable :: scan_vanished_content => multilayer_scan_vanished_content |
Counted allocatable footprint of the ocean C-grid layer slot: the layer prognostics + face transports + RK2 saves + density/vertical diagnostics, the per-tracer registry (each tracer sums its own arrays; ideal-age rides the registry when on), and the device-resident conservation-budget accumulators.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(multilayer_state_t), | intent(in) | :: | this |
Flat-impl of the I1′ sweep for ONE tracer. Explicit-shape dummies so NVHPC does not walk a descriptor per launch.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | h_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(inout) | :: | hTr(nx,ny,nz) |
THE enforcement point for invariant I1′.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(multilayer_state_t), | intent(inout) | :: | this | |||
| integer, | intent(in) | :: | nx |
i-extent of |
||
| integer, | intent(in) | :: | ny |
j-extent (total, incl. halos). |
HOST twin of enforce_vanished_content, for SETUP only. The seed
(ocean_state_seed_land_cells) runs before enter_data, where a
do concurrent on the offload build would work on device memory
that is not mapped yet (mem:separate: no implicit copies). Plain
host loops over the SAME included rdb_vl_merge_content, so the
seeded state satisfies I1′ by the one definition. Never call it on
a device-resident state.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(multilayer_state_t), | intent(inout) | :: | this | |||
| integer, | intent(in) | :: | nx |
i-extent (total, incl. halos). |
||
| integer, | intent(in) | :: | ny |
j-extent (total, incl. halos). |
Append a passive tracer (eos_coeff = 0, budget_id = NONE) to
the registry, growing tracers(:) past the default S/T[/age] set.
Returns its slot in idx, or idx = 0 on refusal (registry not
init’d, or locked by enter_data). MUST be called after init
and BEFORE enter_data — and, on the ocean path, before
ocean_bc_state_init sizes bc%n_tracers. Caller populates
hTr once layer thicknesses exist, and may set
tracers(idx)%standard_name / the pipeline opt-outs directly
(public components). S/T/age keep their indices.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(multilayer_state_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| character(len=*), | intent(in) | :: | name | |||
| character(len=*), | intent(in) | :: | units | |||
| character(len=*), | intent(in) | :: | long_name | |||
| integer, | intent(out) | :: | idx |
Pure I1′ TRIPWIRE scan — counts the vanished cells that do NOT hold
their donor’s concentration (rdb_vl_holds_live_conc: |hTr −
h·c_live| > 1e-12·|h·c_live|, i.e. hTr ≠ 0 in a column with no
live layer) and reports the largest offending |hTr − h·c_live|,
without touching anything. Two device reductions per tracer, two
scalars out; no H←D copy on the healthy path.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(multilayer_state_t), | intent(in) | :: | this | |||
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(out) | :: | n_bad |
Number of |
||
| real(kind=wp), | intent(out) | :: | worst |
Largest |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(multilayer_state_t), | intent(inout) | :: | this |
Attach the C-grid multilayer allocatables to the device. The
tracer registry uses the two-step pattern: array descriptor
first, then each element’s hTr / hTr0 — NVHPC stdpar can’t
dereference tracers(it)%hTr from a do-concurrent body
otherwise.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(multilayer_state_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(multilayer_state_t), | intent(inout) | :: | this |
Reverse of enter_data. Copy out the prognostic fields and
the tracer hTr arrays (so post-run host inspection works),
drop scratch + RK saves. Tracer registry tears down per-
element first, then the array descriptor — mirror of
enter_data order.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(multilayer_state_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(multilayer_state_t), | intent(inout) | :: | this |
Allocate per-layer C-grid arrays at the grid size and the
configured layer count (caller must set this%nz_ml first).
Registers salinity + temperature with default identity strings.
When with_ideal_age is present and true, also registers an
ideal-age tracer at index 3 (see rdb_ocean_ideal_age).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(multilayer_state_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| logical, | intent(in), | optional | :: | with_ideal_age |
Flat-impl of the I1′ scan for ONE tracer. Per column: find the
topmost live layer, then walk DOWN carrying the nearest live layer
above — the donor map rdb_vl_merge_content / rdb_vl_column_conc
use — and test each filler against its donor’s hTr/h.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | h_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | hTr(nx,ny,nz) | |||
| integer, | intent(out) | :: | n_bad | |||
| real(kind=wp), | intent(out) | :: | worst |