Driver-level state + step routines for the outer (baroclinic) +
inner (barotropic) split-explicit RK2 integrator of the ocean
dynamical core. Carries the substep ratio n_inner, the fast-mode
time-averaging accumulators, and energy/CFL diagnostic slots.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | public, | parameter | :: | SPLIT_SCHEME_PRED_CORR | = | 1 |
MOM6 predictor-corrector: off-centred predictor at Neutrally stable to Was renamed twice. This scheme shipped as |
| integer, | public, | parameter | :: | SPLIT_SCHEME_SSP_RK2 | = | 0 |
Two identical stages + SSP average ( What it costs you, measured. The two-stage average amplifies
an internal gravity wave by Practically: the error is a gravity-wave-scale numerical noise
floor that grows with |
| real(kind=wp), | public, | save | :: | bcdiag_S_ref | = | 35.0_wp | |
| logical, | public, | save | :: | bcdiag_enabled | = | .false. | |
| integer, | public, | save | :: | bcdiag_step_limit | = | 2 |
Probe only the first |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| logical, | public | :: | accel_visc_rem | = | .false. |
MOM6 |
|
| real(kind=wp), | public | :: | angstrom_h | = | 0.0_wp |
Phase-2/3 copy of |
|
| real(kind=wp), | public, | allocatable | :: | avr_u0(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | avr_v0(:,:,:) |
accel_visc_rem stage-entry velocity snapshots. Eagerly
allocated at setup ( |
||
| integer, | public | :: | bt_halo | = | 0 |
Wide-halo march-in width (0 = per-substep v1, bit-identical).
Set by |
|
| integer, | public | :: | bt_nonfin_step | = | 0 |
Faces whose BT-correction Δ was non-finite this stage (fold write skipped; pdc 2d5338f9). 0 on a healthy run. |
|
| type(bt_wide_t), | public, | allocatable | :: | bt_wide |
Wide shadow state; allocated only when |
||
| type(barotropic_workstate_t), | public | :: | bt_work | ||||
| logical, | public | :: | cfl_ignore_vanished | = | .false. |
Phase 3: when |
|
| real(kind=wp), | public | :: | cfl_inner_max | = | 0.0_wp |
Max realised inner CFL within the last outer step. |
|
| real(kind=wp), | public | :: | cfl_outer | = | 0.0_wp |
Realised outer CFL (diagnostic). |
|
| real(kind=wp), | public | :: | cfl_trunc | = | 0.0_wp |
Advective-CFL truncation threshold (nondim). When > 0, any
face whose |
|
| logical, | public | :: | check_h_positive | = | .false. |
DEBUG copy of |
|
| type(chksum_probe_t), | public | :: | chksum_probe |
MOM6-style per-phase field checksums + HOTFACE argmax rows
( |
|||
| logical, | public | :: | debug_bt_budget | = | .false. |
When |
|
| real(kind=wp), | public | :: | dt_inner | = | 0.0_wp |
Inner barotropic substep length (s). |
|
| real(kind=wp), | public | :: | dt_outer | = | 0.0_wp |
Outer baroclinic timestep length (s). |
|
| integer, | public | :: | dt_therm_ratio | = | 1 |
Tracer/thermo step runs every |
|
| integer, | public | :: | dt_tracer_advect_ratio | = | 1 |
MOM6 DT_TRACER_ADVECT analogue. Horizontal tracer advection
fires every |
|
| logical, | public | :: | enable_thermodynamics | = | .true. |
Mirrors MOM6 |
|
| real(kind=wp), | public | :: | ideal_age_sfc_growth_rate | = | 0.0_wp |
Exponential growth rate of the surface value (1/s), set by
|
|
| real(kind=wp), | public | :: | ideal_age_young_val | = | 0.0_wp |
Surface-band age value (s), set by |
|
| logical, | public | :: | is_init | = | .false. |
True between |
|
| real(kind=wp), | public | :: | ke_outer | = | 0.0_wp |
Total kinetic energy after the last outer step (diagnostic). |
|
| type(ke_probe_t), | public | :: | ke_probe |
Per-segment layer-KE attribution meter ( |
|||
| real(kind=wp), | public | :: | maxvel | = | 0.0_wp |
When > 0, face velocities are clipped to |
|
| integer, | public | :: | n_inner | = | 0 |
Number of barotropic substeps per outer baroclinic step (0 = “auto, derived from CFL”). |
|
| integer, | public | :: | n_nanzero_step | = | 0 |
Non-finite (NaN/Inf) face velocities zeroed by the truncation’s NaN-catch in the most recent outer step. MUST be 0 on a healthy run; any non-zero is a producer 0/0 upstream (loud — NaNs used to launder to ±maxvel silently, pdc 8c2fd674). |
|
| integer(kind=int64), | public | :: | n_nanzero_total | = | 0_int64 |
Cumulative NaN-catch count over the run. |
|
| integer, | public | :: | ntrunc_step | = | 0 |
Face components CFL-truncated in the most recent outer step
(host-scalar reduction; reset each |
|
| integer, | public | :: | ntrunc_total | = | 0 |
Cumulative CFL-truncation count over the run (driver logs it). |
|
| integer, | public | :: | outer_step_count | = | 0 |
Outer (baroclinic) step counter. |
|
| real(kind=wp), | public | :: | pc_be | = | 0.6_wp |
pred_corr predictor fraction (MOM6 |
|
| logical, | public | :: | poison_ghosts | = | .false. |
When |
|
| logical, | public | :: | reset_vanished_u | = | .false. |
Phase 2: when |
|
| integer, | public | :: | split_scheme | = | SPLIT_SCHEME_PRED_CORR |
Outer time-scheme selector (see the module constants). Kept in
step with the |
| procedure, public, non_overridable :: bytes => ocean_dyn_bytes | |
| procedure, public, non_overridable :: destroy => ocean_dyn_destroy | |
| procedure, public, non_overridable :: enter_data => ocean_dyn_enter_data | |
| procedure, public, non_overridable :: exit_data => ocean_dyn_exit_data | |
| procedure, public, non_overridable :: init => ocean_dyn_init | |
| procedure, public, non_overridable :: is_thermo_step => ocean_dyn_is_thermo_step | |
| procedure, public, non_overridable :: is_tracer_advect_step => ocean_dyn_is_tracer_advect_step | |
| procedure, public, non_overridable :: therm_dt => ocean_dyn_therm_dt |
Shared vanish-tolerance for Phase-2/3 kernels: the layer is
considered vanished when its thickness is at or below this value.
Defined as max(angstrom_h, H_VANISHED) so both the physical
floor (Phase 1) and the skip/merge marker are covered by a
single threshold. Providing this as a pure helper ensures
Phase 2 (reset_vanished_layer_velocities) and Phase 3
(apply_velocity_truncation gate + compute_max_cfl gate)
cannot drift in their vanish definition.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | angstrom_h |
Phase-1 floor (m); 0.0 when Phase 1 is off. |
||
| logical, | intent(in), | optional | :: | pd_floor |
When .true. AND |
Configure-time validity of the (dt_therm_ratio,
dt_tracer_advect_ratio) pair. Both must be >= 1 and
dt_therm_ratio must be an integer multiple of
dt_tracer_advect_ratio so the ALE remap (which fires at the
DT_THERM cadence) never lands inside an open tracer-flux
accumulation window. The setup layer (configure_ocean_vmix)
calls this and error stops with a descriptive message on
.false.; exposed as a pure predicate so the validation logic
is unit-testable without constructing a full ocean state.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | dt_therm_ratio | |||
| integer, | intent(in) | :: | dt_tracer_advect_ratio |
.true. when the GM block below this step already calls
varmix_compute (GM present + enabled + slopes present, at a
thermo step) — so the standalone Gap-1 resolution-function refresh
must NOT run it again (avoids a double compute and preserves the
GM+VarMix slope ordering bit-for-bit).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_gm_t), | intent(in), | optional | :: | gm | ||
| type(ocean_slopes_t), | intent(in), | optional | :: | slopes | ||
| type(ocean_dyn_t), | intent(in) | :: | dyn |
.true. when the lateral-mix compute call should be handed the
VarMix resolution-function face fields (Gap 1): the lateral-mix
slot is present + initialised with resoln_scaled_visc, AND VarMix
is present + enabled (so res_fn_u/v carry a valid, up-to-date
resolution function). Either absent / off ⇒ unscaled coefficients
(bit-identical).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_lateral_mix_t), | intent(in), | optional | :: | lateral_mix | ||
| type(ocean_varmix_t), | intent(in), | optional | :: | varmix |
Counted allocatable footprint of the split-RK2 driver (BT work state + wide-halo shadow state) slot (0 when unallocated).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_dyn_t), | intent(in) | :: | this |
Returns .true. if the thermodynamic / tracer kernels should
fire on this outer step. dt_therm_ratio <= 1 (default) →
always true (every step is a thermo step, bit-identical to
prior behaviour). ratio >= 2 → fires every Nth step,
aligned to outer_step_count = 0 for the IC snapshot.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_dyn_t), | intent(in) | :: | this |
Returns .true. when the windowed horizontal tracer-advect drain
should fire on the current outer step, evaluated with the
PRE-increment outer_step_count so it aligns bit-for-bit with
is_thermo_step() (which gates the ALE remap on the same count).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_dyn_t), | intent(in) | :: | this |
Effective dt for the thermo / tracer kernels. When
dt_therm_ratio = 1 returns dt exactly; otherwise returns
ratio · dt, since the kernels only fire every Nth step and
must advance by that aggregate interval.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_dyn_t), | intent(in) | :: | this | |||
| real(kind=wp), | intent(in) | :: | dt |
accel_visc_rem post-apply reweight:
vel = snap + rem·(vel − snap) — the whole explicit-tendency
sum accumulated since the snapshot is attenuated by the
per-layer viscous remnant (linearity ⇒ identical to weighting
each tendency individually, MOM6 u = u_init + dt·visc_rem·
(CAu + PFu + diffu)). Faces with rem == 1 (the unconditioned
source=1.0 init, and every face before the first vdiff fills
the producer) are SKIPPED, not rewritten — snap + 1·(vel−snap)
is not an FP identity, and the skip keeps rem≡1 bitwise inert.
Friction-dominated near-massless layers (rem → 0) keep their
entry velocity. Public only for the unit-test suite. Under
mem:separate this do concurrent runs on the device-resident
arrays in production (all mapped on the ocean state); unit tests
must map their own arrays explicitly. The masked write stays
inside the do concurrent body (legal — no cross-iteration dep).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | n1 | |||
| integer, | intent(in) | :: | n2 | |||
| integer, | intent(in) | :: | n3 | |||
| real(kind=wp), | intent(in) | :: | snap(n1,n2,n3) | |||
| real(kind=wp), | intent(in) | :: | rem(n1,n2,n3) | |||
| real(kind=wp), | intent(inout) | :: | vel(n1,n2,n3) |
accel_visc_rem stage-entry snapshot: snap = vel, device-side.
Public only for the unit-test suite. Under mem:separate this
do concurrent runs on the device-resident arrays in production
(both are mapped on the ocean state); unit tests must map their
own arrays explicitly (!$acc enter data copyin / update self).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | n1 | |||
| integer, | intent(in) | :: | n2 | |||
| integer, | intent(in) | :: | n3 | |||
| real(kind=wp), | intent(in) | :: | vel(n1,n2,n3) | |||
| real(kind=wp), | intent(out) | :: | snap(n1,n2,n3) |
Post-RK2 velocity housekeeping: the advective-CFL truncation
(E7) followed by the absolute maxvel cap. Called once at the
end of each outer step (after the RK2 average, before the ALE
remap) so the carried-forward / remapped velocity field is
bounded. Replaces the bare apply_maxvel_clamp call at both
ocean_dyn_step / ocean_dyn_step_split sites.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| real(kind=wp), | intent(in) | :: | cfl_trunc | |||
| real(kind=wp), | intent(in) | :: | maxvel | |||
| integer, | intent(out) | :: | ntrunc_step | |||
| real(kind=wp), | intent(in), | optional | :: | vanish_tol |
When present (> 0): zero both-sided-vanished faces before the CFL clip. Absent / 0 ⇒ skip ⇒ bit-identical. |
|
| integer, | intent(out), | optional | :: | n_nanzero |
Count of non-finite (NaN/Inf) face velocities zeroed by the step -1 NaN-catch this call. A non-finite velocity is a producer bug (a 0/0 upstream); it MUST be caught here so it can never launder to ±maxvel (nvfortran lowers the `if(u>hi)…else if(u |
|
| logical, | intent(in), | optional | :: | clip_cell_metric |
When present AND .true.: the CFL clip bounds each face on the
CELL metric |
|
| integer, | intent(out), | optional | :: | nan_i |
Grid location (local, including ghosts) of the FIRST non-finite
face this call caught, in (k,j,i)-ascending scan order —
actionable in place of the old bare count (“producer 0/0
upstream — investigate”; FINDINGS.md’s global-tripolar-aquaplanet
debugging session had nothing better to go on). 0 when
|
|
| integer, | intent(out), | optional | :: | nan_j |
Grid location (local, including ghosts) of the FIRST non-finite
face this call caught, in (k,j,i)-ascending scan order —
actionable in place of the old bare count (“producer 0/0
upstream — investigate”; FINDINGS.md’s global-tripolar-aquaplanet
debugging session had nothing better to go on). 0 when
|
|
| integer, | intent(out), | optional | :: | nan_k |
Grid location (local, including ghosts) of the FIRST non-finite
face this call caught, in (k,j,i)-ascending scan order —
actionable in place of the old bare count (“producer 0/0
upstream — investigate”; FINDINGS.md’s global-tripolar-aquaplanet
debugging session had nothing better to go on). 0 when
|
|
| logical, | intent(out), | optional | :: | nan_is_u |
|
|
| real(kind=wp), | intent(out), | optional | :: | nan_dx |
Local cell size (m) at |
|
| real(kind=wp), | intent(out), | optional | :: | nan_visc_cfl |
Local viscous CFL |
|
| real(kind=wp), | intent(in), | optional | :: | nu_h |
Constant horizontal viscosity (m^2/s), for |
Allocate, initialise, and GPU-attach the wide-halo shadow state
from dyn%bt_halo (already set by the caller).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_dyn_t), | intent(inout) | :: | dyn |
Dynamics state; |
||
| type(hgrid_t), | intent(in) | :: | grid |
Normal-width grid for this subdomain. |
||
| real(kind=wp), | intent(in) | :: | dx |
Cell spacing (m for Cartesian; deg for spherical). |
||
| real(kind=wp), | intent(in) | :: | dy |
Cell spacing (m for Cartesian; deg for spherical). |
||
| real(kind=wp), | intent(in) | :: | lon_west |
Spherical-grid parameters (ignored for Cartesian). |
||
| real(kind=wp), | intent(in) | :: | lat_south |
Spherical-grid parameters (ignored for Cartesian). |
||
| real(kind=wp), | intent(in) | :: | rad_earth |
Spherical-grid parameters (ignored for Cartesian). |
||
| character(len=*), | intent(in) | :: | grid_config_str |
Grid-config string (e.g. “cartesian”, “spherical”). |
||
| real(kind=wp), | intent(in) | :: | f_0 |
Beta-plane Coriolis parameters. |
||
| real(kind=wp), | intent(in) | :: | beta |
Beta-plane Coriolis parameters. |
||
| real(kind=wp), | intent(in) | :: | y_ref |
Beta-plane Coriolis parameters. |
||
| character(len=*), | intent(in) | :: | coriolis_scheme_str |
Coriolis-scheme string (e.g. “beta_plane”). |
||
| real(kind=wp), | intent(in), | optional | :: | omega |
Planetary rotation rate (1/s) for |
Mandatory end-of-segment flush of the windowed tracer-advect
accumulators (spec §(c) — MOM6’s n == n_max). Drains any OPEN
accumulation window (t_dyn_rel_adv > 0) so no Lagrangian-advanced
h_layer is ever paired with FROZEN hTr at an output write, a
restart checkpoint, or the end of a run segment whose length is not
an exact multiple of dt_tracer_advect_ratio.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(ocean_dyn_t), | intent(in) | :: | dyn | |||
| type(continuity_t), | intent(inout) | :: | ct | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| type(ocean_bc_state_t), | intent(in), | optional | :: | bc |
Multilayer extension of ocean_dyn_step_barotropic. One
SSP-RK2 outer step that orchestrates the full per-layer
dynamical core:
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics |
Curvilinear horizontal metrics — forwarded to the PGF (and, in slice 2, the other geometry-aware kernels). |
||
| type(ocean_dyn_t), | intent(inout) | :: | dyn | |||
| type(eos_t), | intent(in) | :: | eos | |||
| type(coriolis_adv_t), | intent(inout) | :: | cor | |||
| type(continuity_t), | intent(inout) | :: | ct | |||
| type(ocean_pressure_force_t), | intent(inout) | :: | pgf | |||
| type(ocean_horizontal_viscosity_t), | intent(inout) | :: | hv | |||
| type(ocean_bottom_drag_t), | intent(inout) | :: | bd | |||
| type(ocean_surface_stress_t), | intent(inout) | :: | ss | |||
| type(ocean_vertical_advection_t), | intent(inout) | :: | va | |||
| type(ocean_hdiff_tracer_t), | intent(inout) | :: | hd | |||
| type(ocean_vdiff_t), | intent(inout) | :: | vd | |||
| type(ocean_vmix_t), | intent(inout) | :: | vmix | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| type(ocean_surface_flux_t), | intent(in), | optional | :: | sf | ||
| type(ocean_geothermal_t), | intent(in), | optional | :: | geo |
Geothermal bottom-heat-flux slot. Absent or |
|
| type(ocean_lateral_mix_t), | intent(inout), | optional | :: | lateral_mix | ||
| type(ocean_epbl_t), | intent(inout), | optional | :: | epbl |
Energetics-based PBL slot. Absent or |
|
| type(ocean_kappa_shear_t), | intent(inout), | optional | :: | kshear |
Kappa-shear interior closure slot. Absent or
|
|
| type(ocean_slopes_t), | intent(inout), | optional | :: | slopes |
Isopycnal-slope diagnostic slot. Absent or |
|
| type(ocean_tidal_mixing_t), | intent(inout), | optional | :: | vmix_tidal |
Tidal-mixing interior closure slot. Absent or
|
|
| type(ocean_bc_state_t), | intent(in), | optional | :: | bc |
Boundary state — forwarded ONLY to the windowed tracer-advect
drain so its single-rank periodic-x / north-fold seam wraps
fire for periodic unsplit runs at |
|
| real(kind=wp), | intent(in), | optional | :: | t |
Model time (s) since run start, used to evaluate the ideal-age
vintage-mode surface value (PR-7). Mirrors the split driver’s
|
|
| type(ocean_top_drag_t), | intent(inout), | optional | :: | td |
Ice-shelf TOP-drag slot ( |
|
| type(ocean_cavity_flux_t), | intent(inout), | optional | :: | cav |
Ice-shelf basal-melt slot ( |
Public only for the unit-test suite (no production module imports it); ignore when developing production code in other modules. Unsplit SSP-RK2 (Heun’s method) outer step on the barotropic C-grid state. Couples continuity-PPM (h-update) and the Sadourny Coriolis-advection tendency (u, v update) into one second-order-accurate step.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(ocean_dyn_t), | intent(inout) | :: | dyn | |||
| type(coriolis_adv_t), | intent(inout) | :: | cor | |||
| type(continuity_t), | intent(inout) | :: | ct | |||
| type(barotropic_state_t), | intent(inout) | :: | bs | |||
| real(kind=wp), | intent(in) | :: | dt |
Split-explicit SSP-RK2 outer step on the multilayer state.
Parallel to ocean_dyn_step (the unsplit driver
still ships for tests + reference). Phase 4b-MVP scope:
gravity-wave-stability fix on momentum only. ALE-aware
h_layer redistribution and full nonlinear-bt corrections
are deferred to a follow-up branch.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics |
Curvilinear horizontal metrics — forwarded to the PGF (and, in slice 2, the other geometry-aware kernels). |
||
| type(ocean_dyn_t), | intent(inout) | :: | dyn | |||
| type(eos_t), | intent(in) | :: | eos | |||
| type(coriolis_adv_t), | intent(inout) | :: | cor | |||
| type(continuity_t), | intent(inout) | :: | ct | |||
| type(ocean_pressure_force_t), | intent(inout) | :: | pgf | |||
| type(ocean_horizontal_viscosity_t), | intent(inout) | :: | hv | |||
| type(ocean_bottom_drag_t), | intent(inout) | :: | bd | |||
| type(ocean_surface_stress_t), | intent(inout) | :: | ss | |||
| type(ocean_vertical_advection_t), | intent(inout) | :: | va | |||
| type(ocean_hdiff_tracer_t), | intent(inout) | :: | hd | |||
| type(ocean_vdiff_t), | intent(inout) | :: | vd | |||
| type(ocean_vmix_t), | intent(inout) | :: | vmix | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| integer, | intent(in) | :: | n_inner | |||
| type(ocean_surface_flux_t), | intent(in), | optional | :: | sf | ||
| type(ocean_geothermal_t), | intent(in), | optional | :: | geo |
Geothermal bottom-heat-flux slot. Absent or |
|
| type(ocean_vcoord_t), | intent(inout), | optional | :: | vcoord |
Vertical-coordinate state. When present and
|
|
| type(ocean_bc_state_t), | intent(inout), | optional | :: | bc |
Open-boundary config. Absent or all-OBC_WALL preserves the closed-wall behaviour bit-identically (the barotropic substep’s tag dispatch falls through to hard-zero). When any edge is non-WALL, the corresponding BC variant fires inside the barotropic substep’s per-substep wall closure. |
|
| type(ocean_sponge_t), | intent(in), | optional | :: | sp |
Map-driven sponge slot (PR-23). Absent or |
|
| real(kind=wp), | intent(in), | optional | :: | t |
Wall-clock time at the start of this outer step (s), used to evaluate the OBC_TIDAL constituent table. |
|
| type(ocean_lateral_mix_t), | intent(inout), | optional | :: | lateral_mix |
Flow-aware lateral-viscosity closure (Leith / Smagorinsky).
Absent or |
|
| type(ocean_epbl_t), | intent(inout), | optional | :: | epbl |
Energetics-based PBL slot. Absent or |
|
| type(ocean_kappa_shear_t), | intent(inout), | optional | :: | kshear |
Kappa-shear interior closure slot. Absent or
|
|
| type(ocean_mle_t), | intent(inout), | optional | :: | mle |
Fox-Kemper MLE slot (B5). Absent or |
|
| type(ocean_slopes_t), | intent(inout), | optional | :: | slopes |
Isopycnal-slope diagnostics slot. Refreshed at THERMO cadence
(the split driver otherwise never calls |
|
| type(ocean_gm_t), | intent(inout), | optional | :: | gm |
Gent-McWilliams thickness-diffusion slot (capability [2]).
Absent or |
|
| type(ocean_varmix_t), | intent(inout), | optional | :: | varmix |
VarMix slot (capability [4]): spatially-varying GM/Redi
coefficients. When present + |
|
| type(ocean_wave_speed_t), | intent(inout), | optional | :: | wavespeed |
Wave-speed slot supplying |
|
| type(ocean_redi_t), | intent(inout), | optional | :: | redi |
Redi continuous neutral-diffusion slot (capability [3]). Absent
or |
|
| type(ocean_meke_t), | intent(inout), | optional | :: | meke |
MEKE prognostic eddy-energy slot (capability [5]). Stepped once
per outer step at THERMO cadence right after |
|
| type(ocean_tidal_mixing_t), | intent(inout), | optional | :: | vmix_tidal |
Tidal-mixing interior closure slot. Absent or
|
|
| type(ocean_tides_t), | intent(inout), | optional | :: | tides |
Equilibrium body-force tide slot (C1) + scalar SAL (C2). When
present and |
|
| type(ocean_p_surf_t), | intent(inout), | optional | :: | psurf |
Atmospheric surface-pressure loading / inverse barometer slot
(PR-17). When present and |
|
| type(ocean_top_drag_t), | intent(inout), | optional | :: | td |
Ice-shelf TOP-drag slot ( |
|
| type(ocean_cavity_flux_t), | intent(inout), | optional | :: | cav |
Ice-shelf basal-melt slot ( |
Recompute the porous-barrier layer-averaged open-area fractions
from the current layer thicknesses. No-op (and untouched
placeholder arrays) when &ocean_porous_nml enable is off.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(inout) | :: | metrics | |||
| type(multilayer_state_t), | intent(in) | :: | ms |
Truncate face velocities to |u| ≤ maxvel. MOM6’s MAXVEL
analogue. Called once at the end of each outer step (after
the RK2 average so the clipped state is what gets carried
into the next stage). No-op when maxvel <= 0.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | maxvel |
The two cell-centred surface kernels that do NOT route through
the assembler’s Q_heat / Q_salt, with their ice-shelf-cover
dispatch. Shortwave penetration reads a pristine q_sw
component (or moves a lump the masked deposit never added) and
restoring forms its flux in-kernel from the live SST/SSS, so
each needs the cover factor of its own; everything else the
atmosphere contributes is already masked inside
ocean_surface_flux_assemble.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(ocean_surface_flux_t), | intent(in), | optional | :: | sf |
Forwarded; absent ⇒ both kernels no-op (their own contract). |
|
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | therm_dt | |||
| logical, | intent(in) | :: | therm_active |
&ocean_isopycnal_nml check_h_positive guard. Abort on the FIRST
negative layer thickness, naming the pipeline stage that produced it,
the offending (i,j,k), and that column’s full thickness profile.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| character(len=*), | intent(in) | :: | label |
Pipeline stage that last wrote |
||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | outer_step | |||
| logical, | intent(in) | :: | check_layers |
|
&vcoord_nml remap_check_preconditions guard (audit findings V5, V6).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_vcoord_t), | intent(in) | :: | vcoord | |||
| integer, | intent(in) | :: | nz |
Number of layers ( |
||
| integer, | intent(in) | :: | outer_step |
Outer-step index, for the abort message. |
Fail-loud TRIPWIRE for invariant I1′ — h_layer <= H_VANISHED ⇒
hTr = h_layer·c_live (the donor live layer’s concentration; hTr = 0
in a column with no live layer) for every registered tracer. Gated on
&vcoord_nml check_vanished_content (default .false.), which is
the knob the stability suite turns on for the cases that actually
have vanishing layers.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_vcoord_t), | intent(in), | optional | :: | vcoord | ||
| type(multilayer_state_t), | intent(in) | :: | ms | |||
| integer, | intent(in) | :: | outer_step |
src -> dst flat copy on the device. Bare-array shim avoids the deep struct deref inside do-concurrent (tracer hTr lives in an array-of-derived-types registry).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | src(nx,ny,nz) | |||
| real(kind=wp), | intent(out) | :: | dst(nx,ny,nz) | |||
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz |
Zero the per-layer face velocities at land faces (spec §14 C4 /
R4(b.2) / MOM6 up = mask2dCu·(u+dt·accel)). Runs once per
RK2 stage AFTER
apply_bt_correction and inside the RK2 average so the
additive layer tendencies + the BT correction cannot leave a
re-ingested land-face velocity (a slow conservation leak). The
transports themselves already ride zeroed metrics; this resets
the prognostic velocity so derive_bt_from_layers next step
sees zero there. All-wet ⇒ wet_u/v≡1 ⇒ literal no-op.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| type(barotropic_workstate_t), | intent(in), | optional | :: | bt_work |
Apply the land contract of mask_layer_velocities — static
wet_u/wet_v, times the z-level open_u/open_v when
zfixed_closed_faces is on — to the pred_corr time-mean
velocities u_av/v_av. Called once, on the step-0 seed: the
renormaliser’s u_cor, their only other writer, never writes a
masked face, so what the seed leaves there is what every later
step reads. (Wet/dry is refused under pred_corr, so its
dynamic mask has no branch here.) All-wet, knob off ⇒ products
with exactly 1, i.e. byte-identical.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(multilayer_state_t), | intent(inout) | :: | ms |
Accumulate the net mass (kg) that left the domain this RK stage into
ms%mass_out. flux_h_layer is the total horizontal divergence
(h_layer -= dt·flux_h_layer), so -Σ_interior(−flux_h_layer)·areaT
is the boundary outflux (interior faces telescope — divergence
theorem), and it is the SAME field the thickness update consumes, so
with the RK2 stage weight this closes the mass budget to round-off.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | flux_h_layer(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | areaT(:,:) | |||
| integer, | intent(in) | :: | nghost | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| real(kind=wp), | intent(in) | :: | weight |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_dyn_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_dyn_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_dyn_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_dyn_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_dyn_t), | intent(inout) | :: | this |
Initialise the barotropic working-state slot. Pass nz_ml
to also allocate the split-driver slow-tendency
accumulators (F_slow_u/v, F_bt_u/v, ubt_at_n/vbt_at_n).
Barotropic-substep unit tests can skip the optional argument since
they don’t exercise the split-driver coupling.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_dyn_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in), | optional | :: | nz_ml |
Debug-gated diagnostic. Pulls h_layer + hTr_S from device
and prints max|hTr_S/h_layer - bcdiag_S_ref| over interior
columns. Early-returns when bcdiag_enabled = .false. or
after bcdiag_step_limit outer steps have completed.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| character(len=*), | intent(in) | :: | label | |||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | outer_step |
Debug probe: print max|sum_k(h_layer) - (H_ref + bt_eta_end)|
over interior cells. In Eulerian-z this is forced to zero
by apply_bt_correction’s h-rescale. In Lagrangian mode
the rescale is skipped, so this residual is what the slow
continuity actually drifts to (expected to be FP). Watching
how it grows over time across many outer steps is what
pins down whether the long-run momentum NaN is FP
accumulation in sum_k(h_layer) - H - bt_eta_end.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| type(barotropic_workstate_t), | intent(in) | :: | bt_work | |||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | outer_step |
Re-fill every tracer’s ghost band from its owners: the halo exchange (MPI seams, and the local periodic wrap on an undecomposed periodic axis — the halo primitive does both), then the tripolar north fold on the rank that owns it. Thickness and velocity are left alone. Collective (every rank calls it).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| type(ocean_bc_state_t), | intent(in), | optional | :: | bc |
Zero the per-layer face velocity at any face where BOTH adjacent
centre-cell thicknesses are at or below vanish_tol
(isopycnal_vanish_tol(angstrom_h) = max(angstrom_h, H_VANISHED)).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | vanish_tol |
Copy the *_0 save buffers back into h_layer / u_face_x_layer / v_face_y_layer — the pred_corr between-stage reset (SPEC §2): the predictor’s provisional up/vp/hp are DISCARDED (only u_av/v_av/ h_av survive it), and the corrector advances from u^n / h^n. Tracers are untouched by the predictor (TR_MODE_NONE + no thermodynamics), so no tracer restore is needed.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(multilayer_state_t), | intent(inout) | :: | ms |
State <- 0.5 * (state_0 + state) for h_layer, u_face_x_layer, v_face_y_layer. Tracer averages are done by the caller.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(multilayer_state_t), | intent(inout) | :: | ms |
current <- 0.5 * (saved + current) on the device. Same bare-array shim rationale as copy_field_3d.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | saved(nx,ny,nz) | |||
| real(kind=wp), | intent(inout) | :: | current(nx,ny,nz) | |||
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz |
The slow horizontal continuity + tracer chain (ghost fills →
constrained continuity+tracer split → reservoirs → halo/wrap →
tracer hdiff → Redi → vertical advection), extracted verbatim
from run_stage_split so the pred_corr path can run it AFTER the
velocity update + implicit friction (the forward-backward
pairing, SPEC §2 C8/§1 fact 5) while the historical ssp_rk2
path keeps it before the applies (bit-identical).
h_only selects the predictor’s TR_MODE_NONE (SPEC §2 P9);
mass_out_weight is the per-call budget weight (0.5 per SSP
stage; 0 for the discarded predictor state, 1 for the
corrector).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(ocean_dyn_t), | intent(inout) | :: | dyn | |||
| type(continuity_t), | intent(inout) | :: | ct | |||
| type(ocean_hdiff_tracer_t), | intent(inout) | :: | hd | |||
| type(ocean_vertical_advection_t), | intent(inout) | :: | va | |||
| type(ocean_redi_t), | intent(inout), | optional | :: | redi | ||
| type(ocean_varmix_t), | intent(inout), | optional | :: | varmix | ||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| real(kind=wp), | intent(in) | :: | therm_dt | |||
| logical, | intent(in) | :: | therm_active | |||
| logical, | intent(in) | :: | is_lagrangian | |||
| real(kind=wp), | intent(in) | :: | h_min_floor | |||
| real(kind=wp), | intent(in) | :: | mass_out_weight | |||
| logical, | intent(in) | :: | h_only | |||
| integer, | intent(in) | :: | stage_id | |||
| integer, | intent(in) | :: | step_id | |||
| type(ocean_bc_state_t), | intent(inout), | optional | :: | bc | ||
| type(ocean_mle_t), | intent(inout), | optional | :: | mle |
Gent-McWilliams thickness diffusion as its OWN sequential operator,
run once per outer step AFTER the dynamics (the stage loop and, under
ssp_rk2, the stage average) — where MOM6 calls thickness_diffuse
after step_MOM_dyn_split_RK2, every dynamics step:
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(ocean_dyn_t), | intent(inout) | :: | dyn | |||
| type(continuity_t), | intent(inout) | :: | ct | |||
| type(ocean_vertical_advection_t), | intent(inout) | :: | va | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| type(ocean_gm_t), | intent(inout), | optional | :: | gm | ||
| type(ocean_slopes_t), | intent(inout), | optional | :: | slopes | ||
| type(ocean_varmix_t), | intent(inout), | optional | :: | varmix | ||
| type(ocean_wave_speed_t), | intent(inout), | optional | :: | wavespeed | ||
| type(ocean_vcoord_t), | intent(in), | optional | :: | vcoord | ||
| type(ocean_bc_state_t), | intent(inout), | optional | :: | bc |
Thin dispatcher: call meke_step only when the MEKE slot is present
AND enabled, forwarding the (also-optional) VarMix + wavespeed slots
so the feedback seam + length scales engage when those are on.
meke_step itself no-ops on enable=.false.; this guard avoids the
call (and the present-propagation noise) when the slot is absent.
hv%ke_diss (the lateral-viscosity KE dissipation rate) is forwarded
for the frictional source; it is 0 unless hv%compute_ke_diss is set
(and meke%frcoeff<0 ignores it) ⇒ inert by default.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(ocean_gm_t), | intent(in) | :: | gm | |||
| type(ocean_varmix_t), | intent(inout), | optional | :: | varmix | ||
| type(ocean_wave_speed_t), | intent(in), | optional | :: | wavespeed | ||
| type(ocean_horizontal_viscosity_t), | intent(in) | :: | hv | |||
| type(multilayer_state_t), | intent(in) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| type(ocean_meke_t), | intent(inout), | optional | :: | meke |
One FE stage of the multilayer step. Order of operations:
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics |
Curvilinear horizontal metrics — forwarded to the PGF. |
||
| type(ocean_dyn_t), | intent(in) | :: | dyn | |||
| type(eos_t), | intent(in) | :: | eos | |||
| type(coriolis_adv_t), | intent(inout) | :: | cor | |||
| type(continuity_t), | intent(inout) | :: | ct | |||
| type(ocean_pressure_force_t), | intent(inout) | :: | pgf | |||
| type(ocean_horizontal_viscosity_t), | intent(inout) | :: | hv | |||
| type(ocean_bottom_drag_t), | intent(inout) | :: | bd | |||
| type(ocean_surface_stress_t), | intent(inout) | :: | ss | |||
| type(ocean_vertical_advection_t), | intent(inout) | :: | va | |||
| type(ocean_hdiff_tracer_t), | intent(inout) | :: | hd | |||
| type(ocean_vdiff_t), | intent(inout) | :: | vd | |||
| type(ocean_vmix_t), | intent(inout) | :: | vmix | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| integer, | intent(in) | :: | stage |
RK2 stage (1 or 2); see vmix_apply_in_stage. |
||
| type(ocean_surface_flux_t), | intent(in), | optional | :: | sf | ||
| type(ocean_geothermal_t), | intent(in), | optional | :: | geo |
Geothermal bottom-heat-flux slot. See |
|
| type(ocean_lateral_mix_t), | intent(inout), | optional | :: | lateral_mix | ||
| type(ocean_epbl_t), | intent(inout), | optional | :: | epbl | ||
| type(ocean_kappa_shear_t), | intent(inout), | optional | :: | kshear | ||
| type(ocean_slopes_t), | intent(inout), | optional | :: | slopes | ||
| type(ocean_tidal_mixing_t), | intent(inout), | optional | :: | vmix_tidal | ||
| type(ocean_top_drag_t), | intent(inout), | optional | :: | td |
Ice-shelf TOP-drag slot ( |
|
| type(ocean_cavity_flux_t), | intent(inout), | optional | :: | cav |
Ice-shelf basal-melt slot ( |
One FE stage of the split-explicit step. See the
ocean_dyn_step_split header for the design.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics |
Curvilinear horizontal metrics — forwarded to the PGF (and, in slice 2, the other geometry-aware kernels). |
||
| type(ocean_dyn_t), | intent(inout) | :: | dyn | |||
| type(eos_t), | intent(in) | :: | eos | |||
| type(coriolis_adv_t), | intent(inout) | :: | cor | |||
| type(continuity_t), | intent(inout) | :: | ct | |||
| type(ocean_pressure_force_t), | intent(inout) | :: | pgf | |||
| type(ocean_horizontal_viscosity_t), | intent(inout) | :: | hv | |||
| type(ocean_bottom_drag_t), | intent(inout) | :: | bd | |||
| type(ocean_surface_stress_t), | intent(inout) | :: | ss | |||
| type(ocean_vertical_advection_t), | intent(inout) | :: | va | |||
| type(ocean_hdiff_tracer_t), | intent(inout) | :: | hd | |||
| type(ocean_vdiff_t), | intent(inout) | :: | vd | |||
| type(ocean_vmix_t), | intent(inout) | :: | vmix | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| integer, | intent(in) | :: | n_inner | |||
| type(ocean_surface_flux_t), | intent(in), | optional | :: | sf | ||
| type(ocean_geothermal_t), | intent(in), | optional | :: | geo |
Geothermal bottom-heat-flux slot. See |
|
| integer, | intent(in), | optional | :: | stage |
Outer SSP-RK2 stage index (1 or 2) — only used by the debug probe so trace lines self-identify which half-step they came from. Production paths leave it unset. |
|
| type(ocean_vcoord_t), | intent(in), | optional | :: | vcoord |
Vertical-coordinate state. When present and
|
|
| type(ocean_bc_state_t), | intent(inout), | optional | :: | bc |
Open-boundary config forwarded straight to the barotropic substep. Absent / all-OBC_WALL keeps the closed-wall path. |
|
| type(ocean_sponge_t), | intent(in), | optional | :: | sp |
Map-driven sponge slot (PR-23). See |
|
| real(kind=wp), | intent(in), | optional | :: | t |
Wall-clock time for OBC_TIDAL constituent evaluation. |
|
| type(ocean_lateral_mix_t), | intent(inout), | optional | :: | lateral_mix |
Flow-aware lateral closure. See the matching arg on
|
|
| type(ocean_epbl_t), | intent(inout), | optional | :: | epbl |
EPBL slot. See the matching arg on |
|
| type(ocean_kappa_shear_t), | intent(inout), | optional | :: | kshear |
Kappa-shear slot. See |
|
| type(ocean_mle_t), | intent(inout), | optional | :: | mle |
Fox-Kemper MLE slot (B5). Forwarded to
|
|
| type(ocean_redi_t), | intent(inout), | optional | :: | redi |
Redi neutral-diffusion slot (capability [3]). The Phase-A
coefficients are precomputed in |
|
| type(ocean_varmix_t), | intent(inout), | optional | :: | varmix |
VarMix coefficient slot (capability [4]). When enabled, its
per-face |
|
| type(ocean_tidal_mixing_t), | intent(inout), | optional | :: | vmix_tidal |
Tidal-mixing slot. See |
|
| type(ocean_meke_t), | intent(in), | optional | :: | meke |
MEKE slot (capability [5]). Read-only here: when
|
|
| real(kind=wp), | intent(in), | optional | :: | eta_forcing(grid%nx_total,grid%ny_total) | ||
| type(ocean_top_drag_t), | intent(inout), | optional | :: | td |
Ice-shelf TOP-drag slot ( |
|
| type(ocean_cavity_flux_t), | intent(inout), | optional | :: | cav |
Ice-shelf basal-melt slot ( |
|
| real(kind=wp), | intent(in), | optional | :: | eta_pf_seam(grid%nx_total,grid%ny_total) |
The part of the |
Copy h_layer, u_face_x_layer, v_face_y_layer into the *_0 save buffers on the multilayer state. Per-tracer hTr is saved by the caller via copy_field_3d (the registry has to be walked on the host).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(multilayer_state_t), | intent(inout) | :: | ms |
Exchange bt_work%visc_rem_u/v face halos right after
production — MOM6’s pass_visc_rem group pass, run after
every one of the three vertvisc_remnant calls. MPI
halo first, then the periodic wrap, then the tripolar fold —
the same ordering contract every other seam fill in this module
follows (ocean_halo_exchange_ml_state then
ocean_periodic_wrap_state then ocean_fold_wrap_state).
visc_rem is a POSITIVE SCALAR on a face (the viscous-remnant
fraction), not a true-vector flux component, so the fold uses
ocean_fold_wrap_visc_rem (copy across the seam), NOT
ocean_fold_wrap_stress’s negate-on-fold vector contract.
bc absent (e.g. a direct unit-test call with no boundary
state) ⇒ periodic wrap + fold are skipped; the halo exchange
itself is unconditional (no-op on 1 rank, D0).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(barotropic_workstate_t), | intent(inout) | :: | bt_work | |||
| type(ocean_bc_state_t), | intent(in), | optional | :: | bc |
Refresh bt_work%visc_rem_u/v from the CURRENT stage state
BEFORE the barotropic forcing assembly (PGF_BUG.md §9) — the
MOM6-order parity (vertvisc_coef runs before btstep every
stage). The stage-end producer alone leaves visc_rem at its
init value (≡ 1) for the whole first stage, so the rem-weighted
F_bt degenerates to the plain mean exactly when the spurious
grounded-layer PGF is at its ballistic worst, and the Δu
corrector then deposits the spurious column-mean into wet
layers. Remnant-only vdiff call: builds the same matrix the
stage-end solve will build (kv one stage stale — benign; the
thickness field, which the BBL glue keys on, is current) and
does NOT touch the velocities. Vertex kappa-shear: the corner
Kv source enters this matrix too (same operator as the
stage-end momentum solve — a remnant built without it would
weight the BT corrector with a different friction operator
than the one actually applied).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(barotropic_workstate_t), | intent(inout) | :: | bt_work | |||
| type(ocean_vmix_t), | intent(in) | :: | vmix | |||
| type(ocean_vdiff_t), | intent(inout) | :: | vd | |||
| type(ocean_surface_stress_t), | intent(in) | :: | ss | |||
| type(ocean_bottom_drag_t), | intent(in) | :: | bd | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| type(ocean_kappa_shear_t), | intent(in), | optional | :: | kshear |
Kappa-shear slot; only read when enabled + vertex mode (supplies the corner Kv source). |
|
| real(kind=wp), | intent(in), | optional | :: | lambda_top_u(grid%nx_total+1,grid%ny_total) | ||
| real(kind=wp), | intent(in), | optional | :: | lambda_top_v(grid%nx_total,grid%ny_total+1) |
Ice-shelf top-drag Rayleigh rate — forwarded so the REMNANT
is built from the same operator the stage-end momentum solve
will build. A remnant built without a sink the solve has
would weight the barotropic corrector with a friction
operator that is not the one applied. EXPLICIT SHAPE for the
reason spelled out on |
|
| real(kind=wp), | intent(in), | optional | :: | cover_u(grid%nx_total+1,grid%ny_total) | ||
| real(kind=wp), | intent(in), | optional | :: | cover_v(grid%nx_total,grid%ny_total+1) |
Face ice-cover masks, same reason. |
|
| type(ocean_bc_state_t), | intent(in), | optional | :: | bc |
Forwarded ONLY for the post-production halo/periodic/fold
refresh of |
Bundle the per-stage vmix closure / KPP overlay / KV_ML_INVZ2 /
assembly gate / vdiff dispatch into one routine so the run_stage
drivers can call vmix_apply_in_stage(grid, dyn, vmix, vd, ss,
ms, dt, sf) instead of carrying 30 lines of nested if-branching.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_dyn_t), | intent(in) | :: | dyn | |||
| type(ocean_vmix_t), | intent(inout) | :: | vmix | |||
| type(ocean_vdiff_t), | intent(inout) | :: | vd | |||
| type(ocean_surface_stress_t), | intent(in) | :: | ss | |||
| type(ocean_bottom_drag_t), | intent(in) | :: | bd |
Bottom-drag slot — supplies the bed-layer Rayleigh-rate field
|
||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| integer, | intent(in) | :: | stage |
RK2 stage (1 or 2): the EPBL/kappa-shear COLUMN SOLVES fire only at stage 1 of a thermo step (their kd is stage-invariant by design — recomputing at stage 2 doubled the closure cost for no accuracy: 19.6%% of GPU time was kappa-shear at 2x cadence). The merges still run EVERY stage (PP81 rewrites kv/kt per stage). |
||
| type(ocean_surface_flux_t), | intent(in), | optional | :: | sf | ||
| type(ocean_epbl_t), | intent(inout), | optional | :: | epbl |
EPBL slot. When present and enabled, replaces the KPP
overlay (configure enforces the mutual exclusion):
|
|
| type(ocean_kappa_shear_t), | intent(inout), | optional | :: | kshear |
Kappa-shear interior closure slot. When present and enabled,
|
|
| type(ocean_tidal_mixing_t), | intent(inout), | optional | :: | vmix_tidal |
St-Laurent/Simmons tidal-mixing interior closure slot. When
present and enabled, |
|
| type(barotropic_workstate_t), | intent(inout), | optional | :: | bt_work |
The BT-corrector workstate — supplies |
|
| real(kind=wp), | intent(in), | optional | :: | lambda_top_u(grid%nx_total+1,grid%ny_total) | ||
| real(kind=wp), | intent(in), | optional | :: | lambda_top_v(grid%nx_total,grid%ny_total+1) |
Ice-shelf top-drag Rayleigh rate (1/s) at u / v faces — the
|
|
| real(kind=wp), | intent(in), | optional | :: | cover_u(grid%nx_total+1,grid%ny_total) | ||
| real(kind=wp), | intent(in), | optional | :: | cover_v(grid%nx_total,grid%ny_total+1) |
Face ice-cover masks (the OR of the two abutting cells).
Present together with |
|
| logical, | intent(in), | optional | :: | apply_tracers |
|
|
| type(ocean_metrics_t), | intent(in), | optional | :: | metrics |
Metrics slot — supplies the halo-valid wet masks
( |
|
| real(kind=wp), | intent(in), | optional | :: | dt_remnant |
|
|
| type(ocean_bc_state_t), | intent(in), | optional | :: | bc |
Open-boundary / periodic / tripolar-fold state — forwarded
ONLY so the visc_rem halo refresh ( |