Applies the per-concern &ocean_* namelist knobs onto an
ocean_state_t’s kernel slots (bottom drag, vmix, lateral
viscosity, vertical coord, PGF, barotropic split). Pure
cfg → slot wiring + rank-0 logging — no I/O, no NetCDF — so it
is shared by the production driver and the NetCDF-free benchmark.
Call order after ocean_state%init_from_config +
ocean_state_seed_from_cfg + register_default_tracers:
configure_ocean_drag / _vmix / _lateral / _pgf / _bt / _bt_split
Smallest barotropic substep count n_inner such that the substep
dt_outer/n_inner satisfies the 2-D external-gravity-wave CFL:
dt_bt <= cfl_safety * l_cfl / c_ext,
with l_cfl the 2-D CFL length (metrics_bt_cfl_length) and c_ext
the external wave speed sqrt(g*H_max). MOM6 set_dtbt analogue, now
with the cross-direction term included (the legacy estimate used a
1-D length and under-counted n_inner by ~sqrt(2) on square cells,
leaving the effective 2-D CFL at ~0.92 for cfl_bt_safety=0.65 — on the
edge of the forward-backward scheme’s stability).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | dt_outer | |||
| real(kind=wp), | intent(in) | :: | cfl_safety | |||
| real(kind=wp), | intent(in) | :: | c_ext | |||
| real(kind=wp), | intent(in) | :: | l_cfl |
Smallest n_inner >= 1 with dt_outer/n_inner <= dt_bt_safe,
for an ALREADY-LIMITED safe barotropic substep dt_bt_safe (s) —
the per-wet-cell minimum bt_cfl_dt_wet returns, reduced across
ranks. bt_auto_n_inner is this with dt_bt_safe formed from a
single (c_ext, l_cfl) pair.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | dt_outer |
Outer (baroclinic) step (s). |
||
| real(kind=wp), | intent(in) | :: | dt_bt_safe |
Largest stable barotropic substep, safety factor included (s). |
Count cells whose top-of-column pressure does NOT carry the
isostatic ice load — the melt path’s guard that
configure_ocean_cavity (the sole ms%p_top producer) ran, and
ran before this check.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | p_top(nx,ny) |
|
||
| real(kind=wp), | intent(in) | :: | p_ice_ref(nx,ny) |
|
||
| integer, | intent(in) | :: | nx |
First dimension. |
||
| integer, | intent(in) | :: | ny |
Second dimension. |
Count ice-covered WET columns sitting at exactly f = 0 — the
configure-time domain check for exchange_law = "hj99".
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | f_cor(nx,ny) |
Cell-centred Coriolis parameter (1/s). |
||
| real(kind=wp), | intent(in) | :: | cover_frac(nx,ny) |
Ice-cover fraction. |
||
| real(kind=wp), | intent(in) | :: | wet_mask(nx,ny) |
Static wet/land mask. |
||
| integer, | intent(in) | :: | nx |
First dimension. |
||
| integer, | intent(in) | :: | ny |
Second dimension. |
Resolve the &ocean_cavity_melt_nml gamma_s “unset” sentinel to
the ISOMIP+ default gamma_t/CAVITY_GAMMA_RATIO_ISOMIP
(Asay-Davis et al. (2016) Table 4 p. 2483; the 35 is Jenkins,
Nicholls & Corr (2010) p. 2309).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | gamma_s |
The raw knob; negative = unset sentinel. |
||
| real(kind=wp), | intent(in) | :: | gamma_t |
Heat-transfer coefficient the default is a fraction of. |
2-D external-gravity-wave CFL length over the PHYSICAL region:
l_cfl = min_cell 1 / sqrt(1/dxT^2 + 1/dyT^2).
Length scale for the barotropic CFL c_ext*dt*sqrt(1/dx^2+1/dy^2) <= 1
(includes the cross-direction term; on uniform Cartesian = dx/sqrt(2)).
Handles anisotropic cells exactly. Host-side, configure time.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(hgrid_t), | intent(in) | :: | grid |
Surface-layer thickness of the hycom z* nominal floor (m), for
the configure banner: the stretched profile’s top entry, else the
uniform z_fixed_h_ref/nz, else 0 (the unconfigured sigma
fallback of ocean_vcoord_rho_target_column).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_vcoord_t), | intent(in) | :: | vcoord |
Representative minimum grid length over the PHYSICAL region,
taken over both dxT and dyT (host-side, configure time).
Bit-identical to min(grid%dx, grid%dy) on uniform Cartesian.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(hgrid_t), | intent(in) | :: | grid |
.true. iff &ocean_bc_nml north = "tripolar_fold".
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg |
.true. iff &ocean_bc_nml tags BOTH west and east periodic —
the rule ocean_bc_state_init applies, for callers that run before
configure_ocean_bc (the grid metrics).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg |
Per-WET-CELL external-gravity-wave CFL limit (MOM6 set_dtbt):
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx |
First extent of the centre arrays (ghosts included). |
||
| integer, | intent(in) | :: | ny |
Second extent of the centre arrays (ghosts included). |
||
| integer, | intent(in) | :: | i0 |
First physical i. |
||
| integer, | intent(in) | :: | i1 |
Last physical i. |
||
| integer, | intent(in) | :: | j0 |
First physical j. |
||
| integer, | intent(in) | :: | j1 |
Last physical j. |
||
| real(kind=wp), | intent(in) | :: | b(nx,ny) |
Bed depth (m, positive down). |
||
| real(kind=wp), | intent(in) | :: | wet(nx,ny) |
Static wet (1) / land (0) T-cell mask. |
||
| real(kind=wp), | intent(in) | :: | dxT(nx,ny) |
T-cell x length (m). |
||
| real(kind=wp), | intent(in) | :: | dyT(nx,ny) |
T-cell y length (m). |
||
| real(kind=wp), | intent(in) | :: | cfl_safety |
|
||
| real(kind=wp), | intent(out) | :: | dt_bt |
Smallest per-wet-cell safe substep (s); |
||
| real(kind=wp), | intent(out) | :: | h_at |
Bed depth at the limiting cell (m); 0 if no wet cell. |
||
| real(kind=wp), | intent(out) | :: | l_at |
2-D CFL length at the limiting cell (m); 0 if no wet cell. |
||
| integer, | intent(out) | :: | n_wet |
Wet cells scanned. |
Populate ocean_state%bc edge tags + per-edge data values from
cfg%ocean%bc (read from &ocean_bc_nml). Run this after
configure_ocean_bt_split and before ocean_state_enter_data
so the BC state is set before the first dyn step.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(inout) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a boundary-condition configuration conflict when
present; absent behaves as today ( |
Barotropic-substep correction knobs (MOM6 frhatu h-weighting, bc-PGF retro-correction, bt_rem_u drag damping, visc_rem joint weight), the BT_cont_type / upstream-PPM h_face workspace allocations, and the rank-0 PGF/BT configuration log lines.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank |
Auto-derive the barotropic substep count n_inner from the external
gravity-wave CFL (MOM6 set_dtbt) when requested, then latch the
mode-split reference column depth bt_H_ref from the seeded bathymetry.
cfg is intent(inout) because auto_n_inner writes cfg%ocean%bt%n_inner.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(inout) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank |
Build the static ice-shelf cavity LOAD field
metrics%p_ice_ref = (rho_ref*GRAVITY)*z_draft (Pa), ASSEMBLE it
into the top-of-column pressure multilayer_state_t%p_top, and
assert the counted-once datum invariant.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a cavity configuration conflict when present;
absent behaves as today ( |
Configure the ice-shelf basal-melt slot (&ocean_cavity_melt_nml,
P2b): copy the knobs onto the slot’s three flat parameter
bundles, resolve the gamma_s sentinel, build the per-column
Coriolis array the hj99 law needs, and CHECK that the
interface pressure the liquidus will read has actually been
loaded.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a melt configuration conflict when present;
absent behaves as today ( |
Build the static partial-step z-level FACE-CLOSURE mask
(&vcoord_nml zfixed_closed_faces; Adcroft, Hill & Marshall
1997; Losch 2008 §2.1 for the ice-shelf cavity).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a configuration conflict when present; absent
behaves as today ( |
Bottom-drag variant + coefficients, the continuity PPM positivity guard, and the BT-budget diagnostic probe — plus their rank-0 log lines. All knobs default off/zero (bit-identical to pre-knob nmls).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on an isopycnal-floor configuration conflict when
present; absent behaves as today ( |
Wire surface wind stress, horizontal-viscosity coefficients, and the Coriolis beta-plane + PV-scheme variant from cfg into the ocean slots.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| type(decomp_t), | intent(in), | optional | :: | decomp |
Along-coordinate tracer Laplacian coefficient (&ocean_hdiff_nml
kappa_h). Scalar copy onto ocean_state%hdiff_tracer, mapped
with its parent slot at ocean_state_enter_data — no explicit
!$acc update needed as long as this runs before that (it does;
see rdb_driver.F90). Default kappa_h = 0.0 leaves the
kernel’s short-circuit intact ⇒ bit-identical.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| integer, | intent(in) | :: | compute_rank |
Fill ms%k_bot / k_bot_u / k_bot_v — the shared index of the
first LIVE layer counting UP from the bed, and the field every
bed-side consumer reads instead of spelling 1. The bed-side
mirror of configure_ocean_k_top.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank |
Fill ms%k_top / k_top_u / k_top_v — the shared index of
the first LIVE layer counting down from the top, and the field
every top-side consumer reads instead of spelling nz.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank |
Derive the static C-grid land masks from the seeded T-cell
wet_mask and zero the 6 face metrics at land faces
(metrics_apply_land_mask). Run AFTER configure_ocean_metrics
(the metrics + inverses must exist) AND configure_ocean_bc (the
periodic / fold flags drive the halo-aware mask derivation), but
BEFORE ocean_state_enter_data (the host edit is what the GPU
copyin captures).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| logical, | intent(in), | optional | :: | warm_restart |
|
Flow-aware lateral-viscosity closure (Leith / Smagorinsky + biharmonic Smagorinsky_AH), the vertical coordinate (VCOORD_* code + z_fixed reference depth), and the PP81/KPP vertical-mixing switches — with their rank-0 log lines.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero when any of the sub-closures configured here
(EPBL/kappa-shear/tidal-mixing/conv/ddiff/wavespeed/Fox-Kemper)
rejects the resolved configuration, when present; absent
behaves as today ( |
Fill the ocean_metrics_t slot per cfg%ocean%grid%grid_config,
then single-source the inverses + hvisc ratio bundle
(metrics_finalize). Must run BEFORE ocean_state_enter_data
(the host fill is what the GPU copyin captures). For
“spherical”, the &grid_nml dx/dy are reinterpreted as
dlon/dlat in degrees.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a grid/geometry configuration failure when present;
absent behaves as today ( |
Configure the atmospheric surface-pressure loading slot (PR-17):
copy enable, take ρ₀ from ocean_state%eos%rho0 (the single ρ₀
of record — NOT a namelist knob), and allocate the seam fields.
Host-side setup — runs BEFORE ocean_state_enter_data.
enable=.false. => no-op, bit-identical. The uniform-p_surf
inert warning is emitted in validate_config; here we only log the
enable on rank 0.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank |
Pressure-force variant, the reference densities (rho0 / rho_ref,
both from the single configured ρ₀ — &ocean_ic_nml rho_0 via
eos%rho0), the reduced-gravity (gprime / gfs_scale) knobs, the
bathymetry copy into the PGF slot, and the matching barotropic
fast-loop gravity g_bt for the gprime / FV_MOM6-reduced-GFS paths.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| integer, | intent(in) | :: | compute_rank |
Unused (no rank-0 logging in this helper); kept for a uniform configure_ocean_* signature. |
||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a PGF/EOS configuration conflict when present;
absent behaves as today ( |
Configure porous barriers (&ocean_porous_nml, Adcroft 2013).
Grows the ocean_metrics_t porous arrays to full face size and
fills the STATIC along-face d_min/d_max/d_avg statistics;
the layer-averaged open fractions themselves are recomputed on
the device every RK2 stage (they depend on the interface
heights).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a porous-barrier configuration conflict when
present; absent behaves as today ( |
Fan the ONE configured Boussinesq reference density out to every
remaining slot that carries its own rho0 copy.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(ocean_geothermal_t), | intent(inout), | optional | :: | geo |
Engine-held geothermal slot (the split driver’s |
Populate ocean_state%sponge’s per-cell idamp_h/idamp_u/
idamp_v maps from cfg%ocean%sponge (&ocean_sponge_nml) + the
already-configured ocean_state%bc edge tags. Run AFTER
configure_ocean_bc (reads the edge tags + has_* flags) and
BEFORE ocean_state_enter_data.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank |
Configure the equilibrium body-force tide slot (C1): parse the
constituent list + reference dates, fill the astronomy catalog
(phase0, nodal f/u), and build the (nx,ny,3) spatial-structure
arrays from metrics%geolatT/geolonT. Host-side setup — runs
AFTER configure_ocean_metrics (lat/lon must be filled) and
BEFORE ocean_state_enter_data. enable=.false. => no-op,
bit-identical.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a tides configuration conflict when present;
absent behaves as today ( |
Ice-shelf TOP drag (&ocean_tdrag_nml, Phase 4a): copy the
variant + coefficients onto the slot, project the static
cell-centred metrics%cover_frac onto the velocity FACES, and
enforce the ONE-C_d rule against the melt slot.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank |
&ocean_tracers_nml scalar knobs (PR-7): the ideal-age Dirichlet
surface value and its vintage-mode exponential growth rate.
enable_ideal_age itself is latched earlier by
ocean_state_copy_config (before init(grid), since it gates
tracer-slot allocation) — these two scalars gate nothing, so
they land here in the post-init configure pass. Both default
to 0 ⇒ bit-identical.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| integer, | intent(in) | :: | compute_rank |
Thermodynamics on/off, velocity-truncation clamp (MAXVEL), DIRECT_STRESS surface-stress distribution, KV_ML_INVZ2 surface-band viscosity, HARMONIC_VISC face-thickness mean, and the DT_THERM thermo/tracer cadence — with their rank-0 log lines.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a vertical-mixing configuration conflict when
present; absent behaves as today ( |
Configure the barotropic linear (Rayleigh) wave-drag piston-velocity
maps (Egbert & Ray 2001; Jayne & St Laurent 2001) — the bulk energy
sink for the barotropic tide, MOM6 BT_LINEAR_WAVE_DRAG. Builds a
host-only h-point r_h(nx,ny) map (uniform scalar or a
resolved-bathymetry roughness proxy), scales it, averages h->face
into bt_work%lwd_drag_u/v, and leaves the arrays unallocated when
the knob is off (bit-identical). MUST run AFTER bathymetry is set
(ocean_state%barotropic%b) and land masking
(configure_ocean_land_mask) and BEFORE ocean_state_enter_data —
the !$acc enter data copyin in barotropic_workstate_enter_data
carries these host-filled values to the device (CLAUDE.md gotcha
(2): arrays mapped create do not carry pre-map host values, so
this ordering is load-bearing).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on an unreachable/unimplemented |
Dynamic wetting/drying (docs/ocean_wetdry_plan.md): copy the
&ocean_wetdry_nml knobs onto the BT workstate, allocate the
wd_* workspaces (lazy — absent when the knob is off, so the
default path carries no new arrays and stays byte-identical),
and seed the hysteresis wet mask from the seeded bathymetry
(barotropic%b — the same array configure_ocean_bt_split
later latches into bt_H_ref; bt_eta is still 0 here).
Must run BEFORE the restart read (so wd_wet_dyn is allocated
+ registered when the registry walk runs and a warm restart
overwrites the seed with the saved front state) and BEFORE
ocean_state_enter_data (host seeding; the enter_data walk
attaches whatever is allocated).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank |
Resolve the VCOORD_Z_FIXED nominal layering onto the vcoord slot —
and the VCOORD_ZSTAR one, which is the same nominal profile
(MOM6 z* dilates it per column; ocean_vcoord_zstar_target):
z_fixed_h_ref = &ocean_topo_nml max_depth (the uniform
max_depth/nz spacing — the default, byte-identical), or, under
&vcoord_nml z_fixed_profile = "list" | "tanh", the stretched
per-layer tables z_fixed_zi / z_fixed_dz built by
rdb_vcoord :: z_fixed_nominal_dz (z_fixed_h_ref then becomes
the profile’s total depth).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| integer, | intent(in) | :: | compute_rank | |||
| logical, | intent(in) | :: | log_it |
Log the resolved profile (rank 0). |
form="roughness_proxy" filler — a DOCUMENTED PLACEHOLDER for
Jayne & St Laurent (2001)’s subgrid <h^2>, not a substitute for
it (that needs PR-14’s file reader or PR-30’s field-valued
roughness). Estimates the subgrid topographic-height variance from
the RESOLVED 2-delta bathymetry increment:
r_H = 1/2*kappa*min(<h^2>_proxy, h2_max)*N_bot. b is
bottom elevation, positive UP (rdb_barotropic_state.F90) —
differences are sign-independent. Zero on land (wet_T==0) and on
the ghost ring (the 2-delta stencil is unavailable there; a
formula-bathymetry path that leaves ghosts unfilled would
otherwise manufacture a spurious cliff at the ghost seam — CLAUDE.md
“Formula bathymetry setters must fill ghost rows”).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | b(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | wet_T(nx,ny) | |||
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nghost | |||
| real(kind=wp), | intent(in) | :: | kappa | |||
| real(kind=wp), | intent(in) | :: | n_bot | |||
| real(kind=wp), | intent(in) | :: | h2_max | |||
| real(kind=wp), | intent(inout) | :: | r_h(nx,ny) |
Bake the C3 nodal/astronomical correction into one OBC edge, then
fail loud (rank-0 error + error stop) if any of the edge’s
constituent frequencies matches no tide-catalog entry, else log the
resolved constituent → (name, f_c, V_c+u_c) map on rank 0. Host-side
setup wrapper around the pure obc_tide_nodal_fill — the pure
helper signals the failure via fill_ierr; the loud policy lives
here.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bc_face_tag_t), | intent(inout) | :: | face | |||
| real(kind=wp), | intent(in) | :: | f_all(TIDES_CATALOG_SIZE) | |||
| real(kind=wp), | intent(in) | :: | u_all(TIDES_CATALOG_SIZE) | |||
| real(kind=wp), | intent(in) | :: | v_all(TIDES_CATALOG_SIZE) | |||
| character(len=*), | intent(in) | :: | edge_name | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero when an OBC tidal constituent matches no tide-catalog
entry, when present; absent behaves as today ( |
Copy the &ocean_conv_nml knobs onto ocean_state%vmix – every
field, no dead-config gaps. Convective adjustment adds no new
slot / allocatable (it lives on the already-unconditionally-
allocated vmix), so unlike configure_ocean_tidal_mixing there
is no separate enable latch to set on a distinct sub-object;
vmix%conv_enable IS the latch. No mutual exclusion with
KPP / EPBL: convection masks against whichever BL depth is live
this stage (rdb_ocean_dyn.F90 vmix_apply_in_stage).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a convective-adjustment configuration conflict when
present; absent behaves as today ( |
Copy the &ocean_ddiff_nml knobs onto ocean_state%vmix – every
field, no dead-config gaps. Like convection, double diffusion adds
no new slot (it rides the unconditionally-allocated vmix and the
already-mirrored vmix%eos); vmix%ddiff_enable IS the latch.
Folded into vmix_split_kd_heat_salt, so it needs the interior
closure pipeline (use_closure) and thermodynamics (it reads T/S
and the EOS alpha/beta). enable=.false. => bit-identical.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a double-diffusion configuration conflict when
present; absent behaves as today ( |
Copy the &ocean_epbl_nml knobs onto the EPBL slot — every
field, end to end (don’t repeat the KPP ri_crit/c_vt2
dead-config gap). Also fills f_centre from the same
beta-plane parameters the Coriolis slot uses, copies the EOS
hookup, validates the configuration, and resolves the
EPBL-vs-KPP mutual exclusion.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on an EPBL configuration conflict when present; absent
behaves as today ( |
Copy the &ocean_foxkemper_nml knobs onto the MLE slot (B5).
Validates: B5 reads epbl%mld, so EPBL must be enabled; and the
resolution_taper hook is a hard error until B2 lands.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a Fox-Kemper MLE configuration conflict when
present; absent behaves as today ( |
Copy the &ocean_kappa_shear_nml knobs onto the kappa-shear slot
— every field, end to end (don’t repeat the KPP dead-config
gap). Fills f_centre from the same beta-plane parameters the
Coriolis slot uses, copies the EOS hookup, and validates. No
mutual exclusion: kappa-shear is an interior closure that
coexists with KPP / EPBL and PP81/background.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a kappa-shear configuration conflict when present;
absent behaves as today ( |
Fill the MEKE slot’s cell-centre |Coriolis| from the same
metrics_fill_coriolis path VarMix / EPBL use (handles beta-plane
AND spherical), so beta = |grad f| for the Rhines length is live
when alpha_rhines > 0. The MEKE scalar knobs are copied earlier
by ocean_state_copy_config; this only fills f_centre. Host loop
before enter_data. No-op when MEKE is disabled.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid |
Copy the &ocean_tidal_mixing_nml knobs onto the tidal-mixing
slot — every field, end to end (no dead-config gaps). Seeds the
prescribed bottom energy field e_in (v1 uniform path), copies
the shared EOS hookup for the N^2 buoyancy derivatives, and
validates. No mutual exclusion: tidal mixing is an interior
closure that coexists with KPP / EPBL / PP81 / kappa-shear.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| integer, | intent(in) | :: | compute_rank | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a tidal-mixing configuration conflict when present;
absent behaves as today ( |
Build the STATIC VarMix grid terms (f2_dx2_*, beta_dx2_*,
l2_*) on the varmix slot once at configure time, from the filled
curvilinear metrics + the cell-centre Coriolis magnitude. The slot
scalars are copied earlier by ocean_state_copy_config; this only
fills the static arrays (the per-step Res_fn/SN/assembly fire in the
dyn step). No-op when VarMix is disabled.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid |
Copy the &ocean_wavespeed_nml knobs onto the wave-speed slot
(B1). Diagnostic, no mutual exclusion: cg1/Rd read rho_layer
directly. Fills f_centre + the static beta_centre = |grad
f| field via fill_coriolis_centre + build_static — the
SAME metrics_fill_coriolis path VarMix/MEKE use (planetary on
spherical/tripolar, beta-plane bit-identical elsewhere) —
rather than the legacy hard-coded beta-plane set_f_centre.
Copies rho0 from the EOS slot for the Boussinesq gprime. Must
run AFTER configure_ocean_metrics (metrics filled + finalized).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_state_t), | intent(inout) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a wave-speed configuration conflict when present;
absent behaves as today ( |
Populate the isopycnal rho_target(0:nz_ml) interface densities
for VCOORD_RHO / VCOORD_HYCOM. rho_target(0) is the surface
(lightest) interface, rho_target(nz_ml) the bed (densest).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| real(kind=wp), | intent(inout) | :: | rho_target(0:) | |||
| integer, | intent(in) | :: | nz_ml |
Fill a cell-centre |Coriolis| array via metrics_fill_coriolis
(D7). beta_plane (default) is BIT-IDENTICAL to the legacy
EPBL / kappa-shear set_f_centre. The corner output is
discarded here (filled into local scratch).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(out) | :: | f_centre(:,:) |
Fill a C-grid corner Coriolis array via the single
generator-driven routine metrics_fill_coriolis, honouring
&ocean_grid_nml coriolis_scheme (D7). beta_plane (default)
is BIT-IDENTICAL to the legacy coriolis_adv_set_beta_plane;
planetary uses the metrics geography. The centre output is
discarded here (filled into local scratch).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(config_t), | intent(in) | :: | cfg | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(out) | :: | f_corner(:,:) |
Periodic-x wrap + north-fold (scalar copy) of the static corner Coriolis array for a tripolar grid. f is reflection-invariant (same latitude at the conjugate corner), so negate=.false.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(inout) | :: | f_corner(:,:) |
Tokenize a whitespace/comma-separated constituent list into
catalog indices (case-insensitive). Unknown tokens fail loud;
nconst is the count of recognised entries.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | list | |||
| integer, | intent(out) | :: | cat_idx(:) | |||
| integer, | intent(out) | :: | nconst | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on an unrecognised constituent token when present;
absent behaves as today ( |
The zfixed_closed_faces = .false. leg of
configure_ocean_closed_faces: refuse vcoord_type = "z_fixed"
with OPEN staircase faces over a STEPPED bed.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_state_t), | intent(in) | :: | ocean_state | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(out), | optional | :: | ierr |
Add a cosine-ramp Idamp band for a west/east (x-normal) sponge
edge into the three maps, SUMMING onto whatever is already there
(§3.2 corner composition). Offsets reproduce
rdb_ocean_sponge::ocean_sponge_apply{,_tracers} exactly:
idamp_h/idamp_v share the cell-column offset; idamp_u (the
x-normal face) sits one further column in for the west edge (side
= +1) and shares the offset for the east edge (side = -1) — the
legacy kernel’s own asymmetry (see Risk 2 of the plan), reproduced
verbatim so damp_source="band" matches today’s band exactly.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | idamp_h(:,:) | |||
| real(kind=wp), | intent(inout) | :: | idamp_u(:,:) | |||
| real(kind=wp), | intent(inout) | :: | idamp_v(:,:) | |||
| integer, | intent(in) | :: | wall_face | |||
| integer, | intent(in) | :: | band | |||
| real(kind=wp), | intent(in) | :: | strength | |||
| integer, | intent(in) | :: | side | |||
| integer, | intent(in) | :: | j0 | |||
| integer, | intent(in) | :: | j1 | |||
| integer, | intent(in) | :: | ramp |
|
Mirror of sponge_add_band_x for a south/north (y-normal) sponge
edge: idamp_h/idamp_u share the row offset; idamp_v (the
y-normal face) sits one further row in for the south edge (side =
+1) and shares the offset for the north edge (side = -1).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(inout) | :: | idamp_h(:,:) | |||
| real(kind=wp), | intent(inout) | :: | idamp_u(:,:) | |||
| real(kind=wp), | intent(inout) | :: | idamp_v(:,:) | |||
| integer, | intent(in) | :: | wall_face | |||
| integer, | intent(in) | :: | band | |||
| real(kind=wp), | intent(in) | :: | strength | |||
| integer, | intent(in) | :: | side | |||
| integer, | intent(in) | :: | i0 | |||
| integer, | intent(in) | :: | i1 | |||
| integer, | intent(in) | :: | ramp |
See |