config_t Derived Type

type, public :: config_t

Container for all runtime simulation parameters


Inherits

type~~config_t~~InheritsGraph type~config_t config_t type~ocean_config_t ocean_config_t type~config_t->type~ocean_config_t ocean type~ocean_bc_config_t ocean_bc_config_t type~ocean_config_t->type~ocean_bc_config_t bc type~ocean_bdrag_config_t ocean_bdrag_config_t type~ocean_config_t->type~ocean_bdrag_config_t bdrag type~ocean_bt_config_t ocean_bt_config_t type~ocean_config_t->type~ocean_bt_config_t bt type~ocean_cavity_dyn_config_t ocean_cavity_dyn_config_t type~ocean_config_t->type~ocean_cavity_dyn_config_t cavity_dyn type~ocean_cavity_melt_config_t ocean_cavity_melt_config_t type~ocean_config_t->type~ocean_cavity_melt_config_t cavity_melt type~ocean_continuity_config_t ocean_continuity_config_t type~ocean_config_t->type~ocean_continuity_config_t continuity type~ocean_conv_config_t ocean_conv_config_t type~ocean_config_t->type~ocean_conv_config_t conv type~ocean_coriolis_config_t ocean_coriolis_config_t type~ocean_config_t->type~ocean_coriolis_config_t coriolis type~ocean_data_config_t ocean_data_config_t type~ocean_config_t->type~ocean_data_config_t data type~ocean_dataovr_config_t ocean_dataovr_config_t type~ocean_config_t->type~ocean_dataovr_config_t dataovr type~ocean_ddiff_config_t ocean_ddiff_config_t type~ocean_config_t->type~ocean_ddiff_config_t ddiff type~ocean_debug_config_t ocean_debug_config_t type~ocean_config_t->type~ocean_debug_config_t debug type~ocean_diag_config_t ocean_diag_config_t type~ocean_config_t->type~ocean_diag_config_t diag type~ocean_eos_config_t ocean_eos_config_t type~ocean_config_t->type~ocean_eos_config_t eos type~ocean_epbl_config_t ocean_epbl_config_t type~ocean_config_t->type~ocean_epbl_config_t epbl type~ocean_forcing_config_t ocean_forcing_config_t type~ocean_config_t->type~ocean_forcing_config_t forcing type~ocean_foxkemper_config_t ocean_foxkemper_config_t type~ocean_config_t->type~ocean_foxkemper_config_t foxkemper type~ocean_geothermal_config_t ocean_geothermal_config_t type~ocean_config_t->type~ocean_geothermal_config_t geothermal type~ocean_gm_config_t ocean_gm_config_t type~ocean_config_t->type~ocean_gm_config_t gm type~ocean_grid_config_t ocean_grid_config_t type~ocean_config_t->type~ocean_grid_config_t grid type~ocean_hdiff_config_t ocean_hdiff_config_t type~ocean_config_t->type~ocean_hdiff_config_t hdiff type~ocean_hvisc_config_t ocean_hvisc_config_t type~ocean_config_t->type~ocean_hvisc_config_t hvisc type~ocean_ic_config_t ocean_ic_config_t type~ocean_config_t->type~ocean_ic_config_t ic type~ocean_ice_config_t ocean_ice_config_t type~ocean_config_t->type~ocean_ice_config_t ice type~ocean_ice_ic_config_t ocean_ice_ic_config_t type~ocean_config_t->type~ocean_ice_ic_config_t ice_ic type~ocean_isopycnal_config_t ocean_isopycnal_config_t type~ocean_config_t->type~ocean_isopycnal_config_t isopycnal type~ocean_kappa_shear_config_t ocean_kappa_shear_config_t type~ocean_config_t->type~ocean_kappa_shear_config_t kshear type~ocean_meke_config_t ocean_meke_config_t type~ocean_config_t->type~ocean_meke_config_t meke type~ocean_mpi_config_t ocean_mpi_config_t type~ocean_config_t->type~ocean_mpi_config_t mpi type~ocean_pgf_config_t ocean_pgf_config_t type~ocean_config_t->type~ocean_pgf_config_t pgf type~ocean_porous_config_t ocean_porous_config_t type~ocean_config_t->type~ocean_porous_config_t porous type~ocean_psurf_config_t ocean_psurf_config_t type~ocean_config_t->type~ocean_psurf_config_t psurf type~ocean_redi_config_t ocean_redi_config_t type~ocean_config_t->type~ocean_redi_config_t redi type~ocean_restore_config_t ocean_restore_config_t type~ocean_config_t->type~ocean_restore_config_t restore type~ocean_slopes_config_t ocean_slopes_config_t type~ocean_config_t->type~ocean_slopes_config_t slopes type~ocean_sponge_config_t ocean_sponge_config_t type~ocean_config_t->type~ocean_sponge_config_t sponge type~ocean_tdrag_config_t ocean_tdrag_config_t type~ocean_config_t->type~ocean_tdrag_config_t tdrag type~ocean_thermo_config_t ocean_thermo_config_t type~ocean_config_t->type~ocean_thermo_config_t thermo type~ocean_tidal_mixing_config_t ocean_tidal_mixing_config_t type~ocean_config_t->type~ocean_tidal_mixing_config_t tidal_mixing type~ocean_tides_config_t ocean_tides_config_t type~ocean_config_t->type~ocean_tides_config_t tides type~ocean_topo_config_t ocean_topo_config_t type~ocean_config_t->type~ocean_topo_config_t topo type~ocean_tracers_config_t ocean_tracers_config_t type~ocean_config_t->type~ocean_tracers_config_t tracers type~ocean_varmix_config_t ocean_varmix_config_t type~ocean_config_t->type~ocean_varmix_config_t varmix type~ocean_vdiff_config_t ocean_vdiff_config_t type~ocean_config_t->type~ocean_vdiff_config_t vdiff type~ocean_vmix_config_t ocean_vmix_config_t type~ocean_config_t->type~ocean_vmix_config_t vmix type~ocean_wave_speed_config_t ocean_wave_speed_config_t type~ocean_config_t->type~ocean_wave_speed_config_t wavespeed type~ocean_wetdry_config_t ocean_wetdry_config_t type~ocean_config_t->type~ocean_wetdry_config_t wetdry type~ocean_zinit_config_t ocean_zinit_config_t type~ocean_config_t->type~ocean_zinit_config_t zinit type~dataovr_entry_config_t dataovr_entry_config_t type~ocean_dataovr_config_t->type~dataovr_entry_config_t tau_x, tau_y, heat, evap, lprec, salt

Inherited by

type~~config_t~~InheritedByGraph type~config_t config_t type~ocean_handle_t ocean_handle_t type~ocean_handle_t->type~config_t cfg

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: S_init_bottom = 0.0_wp

Initial salinity at the bed (k=1, PSU).

real(kind=wp), public :: S_init_surface = 0.0_wp

Initial salinity at the surface layer (k=nz_ml, PSU). Activates linear S(z) stratification when set non-zero together with S_init_bottom.

real(kind=wp), public :: S_max = 40.0_wp

Upper physical bound for salinity (PSU)

real(kind=wp), public :: S_min = 0.0_wp

Lower physical bound for salinity (PSU)

real(kind=wp), public :: S_ref = LEGACY_TRACER_S_REF

RETIRED coastal-legacy EOS reference salinity (PSU). The live ocean-path spelling is &ocean_ic_nml S_ref; moving this one off its default is a fail-loud configure error.

real(kind=wp), public :: T_init_bottom = 0.0_wp

Initial temperature at the bed (k=1, degC).

real(kind=wp), public :: T_init_surface = 0.0_wp

Initial temperature at the surface layer (k=nz_ml, degC). Activates linear T(z) stratification when set non-zero together with T_init_bottom.

real(kind=wp), public :: T_max = 40.0_wp

Upper physical bound for temperature (degC)

real(kind=wp), public :: T_min = -2.0_wp

Lower physical bound for temperature (degC); seawater freezing

real(kind=wp), public :: T_ref = LEGACY_TRACER_T_REF

RETIRED coastal-legacy EOS reference temperature (degC). The live ocean-path spelling is &ocean_ic_nml T_ref; moving this one off its default is a fail-loud configure error.

real(kind=wp), public :: alpha_T = LEGACY_TRACER_ALPHA_T

RETIRED coastal-legacy thermal expansion coefficient (kg/m^3 per degC). Live spelling: &ocean_ic_nml alpha_T.

character(len=256), public :: bathymetry_file = ""

Path to NetCDF bathymetry file (empty = flat bottom)

character(len=16), public :: bc_east = "wall"

East boundary: “wall”, “open”, “tidal”, “nested”

character(len=16), public :: bc_north = "wall"

North boundary: “wall”, “open”, “tidal”, “nested”

character(len=16), public :: bc_south = "wall"

South boundary: “wall”, “open”, “tidal”, “nested”

character(len=16), public :: bc_west = "wall"

West boundary: “wall”, “open”, “tidal”, “nested”

real(kind=wp), public :: beta_S = LEGACY_TRACER_BETA_S

RETIRED coastal-legacy haline contraction coefficient (kg/m^3 per PSU). Live spelling: &ocean_ic_nml beta_S.

real(kind=wp), public :: cfl = 0.45_wp

CFL number for adaptive timestep

integer, public :: cfl_interval = 1

Recompute CFL timestep every N steps (1 = every step)

logical, public :: check_vanished_content = .false.

I1′ tripwire — assert 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, once per outer step, immediately after the enforcement point that establishes it (multilayer_state_t%enforce_vanished_content). A violation logs the offending cell count and the worst |hTr − h·c_live| and error stops.

HEAVY only in the sense that it adds two device reductions per tracer per step; the healthy path does no H←D copy. Default .false.. Turn it ON for any configuration whose coordinate actually vanishes layers (z_fixed, zstar, zstar_full, wet/dry) — the stability suite does. Inert on a family with no fillers.

See src/core/ocean/README.md, “The vanished-layer content rule”.

integer, public :: compress_level = 1

Deflate compression level (1=fast, 9=max). 1 is usually optimal.

logical, public :: compress_output = .false.

Enable deflate compression for NetCDF output (NetCDF4/HDF5)

real(kind=wp), public :: coriolis_f = 0.0_wp

Coriolis parameter f (1/s), typically 2Omegasin(lat)

real(kind=wp), public :: dt_fixed = 0.0_wp

Fixed timestep (s), 0 = adaptive CFL. Same convention as dt_max — always seconds.

real(kind=wp), public :: dt_max = 1.0e10_wp

Maximum allowable timestep (s) — always in seconds, NOT affected by time_unit. Timesteps are naturally short and CFL-bounded; writing them in "day" would force awkward fractional values.

real(kind=wp), public :: dx = 1.0_wp

Cell size in x-direction (m)

real(kind=wp), public :: dy = 1.0_wp

Cell size in y-direction (m)

real(kind=wp), public :: h0 = 1.0_wp

Background depth for gaussian_hump IC (m)

real(kind=wp), public :: hdiff_kappa = 0.0_wp

Horizontal diffusion coefficient for tracers (m^2/s). VESTIGIAL: its only consumers were the coastal solvers, which left with the carve-out, so nothing reads it today. The along-coordinate equivalent is the separate &ocean_hdiff_nml kappa_h knob (rdb_ocean_hdiff_tracer). Smooths sharp density fronts to reduce BPG overshoot. Typical values: 1-10 m^2/s depending on grid resolution.

real(kind=wp), public :: inflow_salinity = -1.0_wp

Prescribed salinity for inflow BC (PSU); <0 = zero-gradient

real(kind=wp), public :: inflow_temperature = -999.0_wp

Prescribed temperature for inflow BC (degC); <0 = zero-gradient

real(kind=wp), public :: initial_salinity = 35.0_wp

Initial salinity for all layers (PSU). Used as a uniform IC unless S_init_surface and S_init_bottom are BOTH set non-zero, in which case the seed builds a linear S(z) profile from S_init_bottom at k=1 (bed) to S_init_surface at k=nz (surface). NOTE the stable polarity is the inverse of temperature: salty/dense water belongs at the bed, so a stable haline column has S_init_bottom > S_init_surface (fresh surface, e.g. a river-plume column).

real(kind=wp), public :: initial_temperature = 15.0_wp

Initial potential temperature for all layers (degC). Used as a uniform IC unless T_init_surface and T_init_bottom are BOTH set non-zero, in which case the seed builds a linear T(z) profile from T_init_bottom at k=1 (bed) to T_init_surface at k=nz (surface). Stratified IC is the prerequisite for baroclinic-instability-driven eddies.

real(kind=wp), public :: kappa_S_bg = 1.0e-5_wp

Background vertical salinity diffusivity (m^2/s)

real(kind=wp), public :: kappa_T_bg = 1.0e-5_wp

Background vertical temperature diffusivity (m^2/s)

real(kind=wp), public :: kpp_c_vt2 = 1.8_wp

Unresolved-turbulence coefficient for the V_t^2 term in the bulk-Ri denominator (LMD94 eq 23). Set 0 to disable V_t^2.

real(kind=wp), public :: kpp_cs_nonlocal = 6.3_wp

Non-local (counter-gradient) transport coefficient C_s (LMD94 eq 20, limit value).

real(kind=wp), public :: kpp_ri_crit = 0.3_wp

Critical bulk Richardson number for the KPP BL-depth sweep.

character(len=16), public :: log_level = "info"

Log verbosity: “debug”, “verbose”, “info”, “performance”, “warning”, “error”

real(kind=wp), public :: manning_n = 0.0_wp

Manning roughness coefficient

integer, public :: n_tidal_constituents = 0

Number of active tidal constituents (0 = use legacy single)

integer, public :: nghost = 3

Number of ghost cells on each side. Default 3 (not 2): the ocean dyn-core’s continuity/tracer PPM reconstruction is a 5-point stencil, so a rank-seam face’s ghost-side donor needs two neighbours beyond itself — full-order reconstruction AT the seam requires three ghost columns. At nghost=2 the PPM local-array-edge fallback fires at the seam and degrades the face to first order, producing a seam-inconsistent tracer mass flux: it conserves a uniform tracer (constant field cancels) but LEAKS a structured one (advecting T with rank-A-out /= rank-B-in on the shared seam face drifts hT), invisible to the mass/salt closure gates. Measured on seamount_bench_full (np2 x-split): heat closure grew to +5e-11 by day 2 at nghost=2, stays at round-off (~5e-14, no growth) at nghost=3. Single-rank runs are unaffected by the wider halo (same interior); the extra ghost column only costs a little memory.

integer, public :: nx = 200

Number of physical cells in x-direction

integer, public :: ny = 1

Number of physical cells in y-direction

integer, public :: nz_layers = 2

Number of sigma layers for NH solver

type(ocean_config_t), public :: ocean

Nested ocean knobs. Per-concern sub-types live under here (coriolis, thermo, bt, pgf, bdrag, hvisc, vmix, continuity, topo, ic, diag). PR-B1 migrates knobs from this struct’s flat fields into the nested form one group at a time — callers go from cfg%ocean_X → cfg%ocean%group%X. PR-B2 will split the giant &ocean_setup_nml to match.

character(len=256), public :: output_dir = "./output"

Directory for output files

logical, public :: output_to_file = .false.

Enable file output (NetCDF snapshots)

integer, public :: px = 1

Number of MPI processes in x-direction

integer, public :: py = 1

Number of MPI processes in y-direction

real(kind=wp), public :: regrid_time_scale = 0.0_wp

Grid time-filter timescale τ (s). The ALE regrid relaxes the coordinate a fraction dt/(τ+dt) toward the target each thermo step instead of jumping (White & Adcroft 2008), damping the σ/z* per-step grid-motion shock. 0 (default) = jump to target = bit-identical.

logical, public :: remap_boundary_extrap = .false.

Linear-exact one-sided reconstruction in the ALE remap’s two boundary cells (MOM6 BOUNDARY_EXTRAPOLATION) instead of the PCM flatten, which leaves PLM/PPM/PPM_H4/PQM first-order at k=1 and k=nz. .false. (default) = bit-identical.

logical, public :: remap_check_preconditions = .false.

Assert, once per ALE remap (thermo cadence), that every column satisfies what the overlap sweep has always assumed: non-negative source AND target thicknesses, and matching column totals. Both are caller obligations and neither was ever checked; a violation silently CREATES or DELETES tracer mass. Diagnostic knob — .false. (default) = the check never runs = bit-identical.

character(len=16), public :: remap_method = "ppm"

Vertical remapping method: “pcm”, “plm”, “ppm”, “ppm_h4”, “pqm”. Default PPM (piecewise parabolic, Colella & Woodward 1984) — the state-of-the-art conservative vertical-remap stencil for the coastal ALE coords. “pqm” is piecewise quartic (White & Adcroft 2008); it falls back to PPM for nz < 5.

logical, public :: remap_nonuniform_weights = .false.

Non-uniform-grid reconstruction weights in the ALE remap’s PLM slope and PPM edge estimate (Colella & Woodward 1984 eqs 1.6-1.8) instead of their equal-thickness specialisations, which are linear-exact only on a UNIFORM source column. PPM_H4 and PQM already carry thickness-weighted stencils and are unchanged. .false. (default) = bit-identical.

logical, public :: remap_vel_conserve_ke = .false.

KE-conserving rescale of the remapped layer velocities: scale the baroclinic anomaly per column so column KE is preserved (Adcroft & Hallberg 2006), capped 1.25×; barotropic mean untouched. .false. (default) = momentum-only = bit-identical.

character(len=256), public :: restart_file = ""

Path to restart file for warm start (empty = cold start)

real(kind=wp), public :: restart_interval = 0.0_wp

Time between restart file writes (s), 0 = no restarts

real(kind=wp), public :: rho_0 = 1000.0_wp

Reference density for EOS (kg/m^3)

real(kind=wp), public :: rho_ref_pressure = 2.0e7_wp

Reference pressure (Pa, default 2e7 = 2000 dbar) for the potential density that defines the VCOORD_RHO coordinate.

real(kind=wp), public :: rho_target_dense = 1030.0_wp

Densest target interface potential density (kg/m³) — the bed interface for VCOORD_RHO / VCOORD_HYCOM. See rho_target_light.

real(kind=wp), public :: rho_target_light = 1020.0_wp

Lightest target interface potential density (kg/m³) — the surface interface for VCOORD_RHO / VCOORD_HYCOM. With rho_target_dense builds the uniform light→dense target-density linspace (MOM6 ALE_COORDINATE_CONFIG=UNIFORM analogue) under rho_target_profile = "uniform".

real(kind=wp), public :: rho_target_list(MAX_Z_FIXED_DZ+1) = -1.0_wp

rho_target_profile = "list": interface potential densities (kg/m³) at rho_ref_pressure, LIGHTEST (surface) FIRST, strictly increasing. Exactly nz_layers+1 leading positive entries; the rest unset (<= 0, default -1).

character(len=16), public :: rho_target_profile = "uniform"

Target-density profile of vcoord_type = "rho" | "hycom": "uniform" (default — the rho_target_light→rho_target_dense linspace, byte-identical) or "list" (the nz_layers+1 interface densities in rho_target_list, light first — MOM6 target densities from a list/file, e.g. the HYBRID:file,sigma2,dz coordinate of OM4). A uniform list is a poor fit wherever most of the volume sits in a narrow density range (the Southern Ocean: half its volume inside ~2 linspace layers). Refused on any other coordinate.

character(len=16), public :: sim_type = "ocean"

Simulation regime: “coastal” or “ocean”

real(kind=wp), public :: sponge_strength = 0.0_wp

Sponge relaxation rate (1/s)

integer, public :: sponge_width = 0

Sponge layer width in cells

real(kind=wp), public :: status_interval = 0.0_wp

Print status every N seconds of simulation time (0 = default every 100 steps)

Use for circulation-pathway diagnostics + spurious diapycnal-mixing validation against MOM6.

real(kind=wp), public :: t_end = 1.0_wp

Simulation end time, interpreted in time_unit (default s).

character(len=16), public :: thickness_config = "sigma"

INITIAL layer-thickness profile for the ocean path (sim_type = 'ocean'); ignored by the coastal regimes. Distinct from vcoord_type, which selects the RUNNING coordinate: this knob only decides what h_layer is seeded to at t=0.

“sigma” (default) — even split of the LOCAL depth, h_layer(i,j,k) = b(i,j)/nz_ml. Bit-identical to the pre-knob behaviour for every existing nml. “uniform_z” — MOM6 THICKNESS_CONFIG="uniform" port: uniform z interfaces laid over the GLOBAL ocean_max_depth, clipped bottom-up to the local bathymetry, with sub-floor layers collapsed to the isopycnal angstrom_h. Gives FLAT resting isopycnals under a horizontally-uniform density stack — the layered / isopycnal (VCOORD_LAGRANGIAN) resting state. With “sigma” the density interfaces instead follow the bathymetry, which puts the full rho_range contrast across every shelf break at t=0 and releases that available potential energy as a slumping gravity current.

real(kind=wp), public :: tidal_amp(MAX_TIDAL_CONSTITUENTS) = 0.0_wp

Constituent amplitudes (m)

real(kind=wp), public :: tidal_omega(MAX_TIDAL_CONSTITUENTS) = 0.0_wp

Constituent angular frequencies (rad/s)

real(kind=wp), public :: tidal_phase(MAX_TIDAL_CONSTITUENTS) = 0.0_wp

Constituent phases (radians)

character(len=8), public :: time_unit = "s"

Unit applied to the long-time fields: t_end, status_interval (logging cadence), ocean_diag_dt_out (diag-write cadence). dt_fixed and dt_max stay in seconds — see their docstrings. Read at namelist parse, then multiplied through so the rest of the code keeps using seconds internally. Valid values: "s", "min", "hr", "day", "year". Year is 365.25 days (Julian, matches MOM6 / UDUNITS convention). Default "s" preserves backward compatibility — every existing nml is bit-identical.

logical, public :: use_io_server = .false.

Dedicate one MPI rank per node as I/O server (MPI only)

logical, public :: use_multilayer = .false.

Enable coupled hydrostatic vertical layers (alternative to NH)

character(len=16), public :: vcoord_type = "sigma"

Vertical coordinate type: “sigma”, “zsigma”, “zstar”, etc.

real(kind=wp), public :: wind_stress_x = 0.0_wp

Surface wind stress in x-direction (Pa)

real(kind=wp), public :: wind_stress_y = 0.0_wp

Surface wind stress in y-direction (Pa)

real(kind=wp), public :: z_fixed_dz(MAX_Z_FIXED_DZ) = -1.0_wp

z_fixed_profile = "list": nominal layer thicknesses (m), SURFACE FIRST (MOM6 ALE_COORDINATE_CONFIG = "PARAM:..." / vgrid order). Exactly nz_layers leading positive entries; the rest unset (<= 0, default -1). The profile’s total is its sum; a column deeper than that puts the excess in the bed layer.

real(kind=wp), public :: z_fixed_dz_top = 2.0_wp

z_fixed_profile = "tanh": surface-layer nominal thickness (m). Must satisfy nz_layers*z_fixed_dz_top < max_depth.

character(len=16), public :: z_fixed_profile = "uniform"

Nominal layer-thickness profile of vcoord_type = "z_fixed" and of vcoord_type = "zstar" (MOM6 z*, which dilates this same nominal profile per column by (H + η)/H): "uniform" (default — max_depth/nz_layers everywhere, byte-identical), "list" (the thicknesses in z_fixed_dz, surface first) or "tanh" (a hyperbolic-tangent stretching from z_fixed_dz_top at the surface, scaled to sum to &ocean_topo_nml max_depth; see rdb_vcoord :: z_fixed_nominal_dz). The z_fixed target builder, the closed-face mask, k_top, the cavity partial-top rule and the bed partial-cell rule all read the profile.

It is the z COORDINATE RESOLUTION, and vcoord_type = "hycom" reads it too, as its z nominal floor (MOM6 HYCOM1 floors its interfaces at the coordinateResolution that ALE_COORDINATE_CONFIG / HYBRID: defines): interface k is kept at least Σ dz·(H+η)/H deep. “uniform” there means max_depth/nz_layers METRES, not 1/nz_layers of the column. The z_fixed_* names are kept for every reader rather than introducing a parallel table that could disagree. vcoord_type = "zstar" (MOM6 z*) reads it as its nominal levels as well. Refused on any other coordinate.

real(kind=wp), public :: z_fixed_tanh_center = 0.5_wp

z_fixed_profile = "tanh": transition centre as a fraction of the layer-index span, [0, 1] (0 = surface, 1 = bed).

real(kind=wp), public :: z_fixed_tanh_width = 0.25_wp

z_fixed_profile = "tanh": transition width as a fraction of the layer-index span (> 0; small = abrupt).

logical, public :: zfixed_closed_faces = .false.

Partial-step z-level face closure under vcoord_type = "z_fixed" (Adcroft, Hill & Marshall 1997; Losch 2008 for the ice-shelf cavity). A layer whose nominal geopotential range lies inside the bed — or inside the ice draft — carries an inert FILLER of thickness zstar_h_min (<= H_VANISHED). A velocity face where layer k is a filler on EITHER side is not a thin passage, it is a WALL for that layer: no normal velocity, no mass / tracer flux, and FREE-SLIP on the tangential component. Leaving it open makes the FV pressure gradient integrate across a staircase step of height Δz_step, which drives |ρ′|·g·Δz_step/(ρ₀·dx) out of a resting stratified state — independent of the filler thickness, so no h-gate reaches it.

ON builds a STATIC 0/1 per-layer face mask (ocean_metrics_t%open_u / open_v) once at configure from the z_fixed target at η = 0, and composes it multiplicatively with the land metrics and the porous-barrier open-area fraction: dy_eff(i,j,k) = dy_cu(i,j)·por_face_area_u(i,j,k)·open_u(i,j,k).

Default .false. ⇒ the mask arrays stay at their (1,1,1) placeholder, no kernel branch is taken, byte-identical. Accepted on z_fixed, zstar (MOM6 z*) and zstar_full — the three GEOMETRIC families whose bed-side fillers sit at fixed reference depths (under zstar: the z_fixed fillers, decided at η = 0 and exactly static under the dilation; under zstar_full: every layer below a column’s partial cell when the column is shallower than the zstar_h_surf_target fine zone). The mask is built from the coordinate’s target at η = 0, and under zstar / zstar_full the IC is then seeded on that target. Refused on every other coordinate, and without fillers to close (z_fixed / zstar without a resolved z_fixed_h_ref; zstar_full with zstar_h_surf_target <= 0). The name is historical.

real(kind=wp), public :: zstar_h_min = 1.0e-4_wp

Vanishing-layer floor (m). Layers that would land below the local bed get clipped to this thickness rather than going to zero.

real(kind=wp), public :: zstar_h_surf_target = 0.0_wp

Target physical thickness of the surface layer (m). 0 => auto: fall back to the lite (uniform sigma) profile per column (effectively zstar-lite per-column). Set > 0 to anchor the surface layer at a fixed thickness regardless of H.

integer, public :: zstar_n_surf = 0

Number of “fine” near-surface layers using stretching. 0 => auto (use max(1, nz/3))

character(len=16), public :: zstar_stretching = "log"

Surface-concentration stretching: “log” | “uniform”


Source Code

   type :: config_t
      !! Container for all runtime simulation parameters

      ! Simulation regime.  "ocean" (Arakawa C-grid + continuity-PPM) is
      ! the only regime this build ships — the coastal A-grid path was
      ! carved out into its own repository.  Retained as a knob so an
      ! existing namelist keeps parsing; validate_config rejects any other
      ! value.  See docs/ROADMAP_OCEAN.md.
      character(len=16) :: sim_type = "ocean"
         !! Simulation regime: "coastal" or "ocean"

      ! Grid parameters
      integer :: nx = 200
         !! Number of physical cells in x-direction
      integer :: ny = 1
         !! Number of physical cells in y-direction
      real(wp) :: dx = 1.0_wp
         !! Cell size in x-direction (m)
      real(wp) :: dy = 1.0_wp
         !! Cell size in y-direction (m)
      integer :: nghost = 3
         !! Number of ghost cells on each side.  Default 3 (not 2): the
         !! ocean dyn-core's continuity/tracer PPM reconstruction is a
         !! 5-point stencil, so a rank-seam face's ghost-side donor needs
         !! two neighbours beyond itself — full-order reconstruction AT the
         !! seam requires three ghost columns.  At nghost=2 the PPM
         !! local-array-edge fallback fires at the seam and degrades the
         !! face to first order, producing a seam-inconsistent tracer mass
         !! flux: it conserves a uniform tracer (constant field cancels)
         !! but LEAKS a structured one (advecting T with rank-A-out /=
         !! rank-B-in on the shared seam face drifts hT), invisible to the
         !! mass/salt closure gates.  Measured on seamount_bench_full
         !! (np2 x-split): heat closure grew to +5e-11 by day 2 at nghost=2,
         !! stays at round-off (~5e-14, no growth) at nghost=3.  Single-rank
         !! runs are unaffected by the wider halo (same interior); the extra
         !! ghost column only costs a little memory.

      ! Time parameters
      real(wp) :: t_end = 1.0_wp
         !! Simulation end time, interpreted in `time_unit` (default s).
      real(wp) :: cfl = 0.45_wp
         !! CFL number for adaptive timestep
      real(wp) :: dt_max = 1.0e10_wp
         !! Maximum allowable timestep (s) — always in seconds, NOT
         !! affected by `time_unit`.  Timesteps are naturally short
         !! and CFL-bounded; writing them in `"day"` would force
         !! awkward fractional values.
      real(wp) :: dt_fixed = 0.0_wp
         !! Fixed timestep (s), 0 = adaptive CFL.  Same convention
         !! as `dt_max` — always seconds.
      integer :: cfl_interval = 1
         !! Recompute CFL timestep every N steps (1 = every step)
      character(len=8) :: time_unit = "s"
         !! Unit applied to the long-time fields: `t_end`,
         !! `status_interval` (logging cadence), `ocean_diag_dt_out`
         !! (diag-write cadence).  `dt_fixed` and `dt_max` stay in
         !! seconds — see their docstrings.  Read at namelist parse,
         !! then multiplied through so the rest of the code keeps
         !! using seconds internally.  Valid values: `"s"`, `"min"`,
         !! `"hr"`, `"day"`, `"year"`.  Year is 365.25 days (Julian,
         !! matches MOM6 / UDUNITS convention).  Default `"s"`
         !! preserves backward compatibility — every existing nml is
         !! bit-identical.

      ! Physics parameters
      real(wp) :: manning_n = 0.0_wp
         !! Manning roughness coefficient
      real(wp) :: wind_stress_x = 0.0_wp
         !! Surface wind stress in x-direction (Pa)
      real(wp) :: wind_stress_y = 0.0_wp
         !! Surface wind stress in y-direction (Pa)
      real(wp) :: coriolis_f = 0.0_wp
         !! Coriolis parameter f (1/s), typically 2*Omega*sin(lat)

      ! Output parameters
      logical :: output_to_file = .false.
         !! Enable file output (NetCDF snapshots)
      character(len=256) :: output_dir = "./output"
         !! Directory for output files
      real(wp) :: restart_interval = 0.0_wp
         !! Time between restart file writes (s), 0 = no restarts
      logical :: compress_output = .false.
         !! Enable deflate compression for NetCDF output (NetCDF4/HDF5)
      integer :: compress_level = 1
         !! Deflate compression level (1=fast, 9=max). 1 is usually optimal.
      logical :: use_io_server = .false.
         !! Dedicate one MPI rank per node as I/O server (MPI only)

      ! Output variable selection (multilayer)

      ! I/O file parameters
      character(len=256) :: bathymetry_file = ""
         !! Path to NetCDF bathymetry file (empty = flat bottom)
      character(len=256) :: restart_file = ""
         !! Path to restart file for warm start (empty = cold start)

      ! Nesting parameters

      ! Boundary parameters
      character(len=16) :: bc_west = "wall"
         !! West boundary: "wall", "open", "tidal", "nested"
      character(len=16) :: bc_east = "wall"
         !! East boundary: "wall", "open", "tidal", "nested"
      character(len=16) :: bc_south = "wall"
         !! South boundary: "wall", "open", "tidal", "nested"
      character(len=16) :: bc_north = "wall"
         !! North boundary: "wall", "open", "tidal", "nested"

      ! Tidal forcing parameters

      ! Multi-constituent tidal forcing
      integer :: n_tidal_constituents = 0
         !! Number of active tidal constituents (0 = use legacy single)
      real(wp) :: tidal_amp(MAX_TIDAL_CONSTITUENTS) = 0.0_wp
         !! Constituent amplitudes (m)
      real(wp) :: tidal_phase(MAX_TIDAL_CONSTITUENTS) = 0.0_wp
         !! Constituent phases (radians)
      real(wp) :: tidal_omega(MAX_TIDAL_CONSTITUENTS) = 0.0_wp
         !! Constituent angular frequencies (rad/s)

      ! Inflow/discharge/clamped BC parameters
      real(wp) :: inflow_salinity = -1.0_wp
         !! Prescribed salinity for inflow BC (PSU); <0 = zero-gradient
      real(wp) :: inflow_temperature = -999.0_wp
         !! Prescribed temperature for inflow BC (degC); <0 = zero-gradient

      ! Sponge layer parameters
      integer :: sponge_width = 0
         !! Sponge layer width in cells
      real(wp) :: sponge_strength = 0.0_wp
         !! Sponge relaxation rate (1/s)

      ! Metadata parameters

      ! MPI domain decomposition
      integer :: px = 1
         !! Number of MPI processes in x-direction
      integer :: py = 1
         !! Number of MPI processes in y-direction

      ! Non-hydrostatic pressure correction
      integer :: nz_layers = 2
         !! Number of sigma layers for NH solver

      ! Coupled hydrostatic multi-layer
      logical :: use_multilayer = .false.
         !! Enable coupled hydrostatic vertical layers (alternative to NH)
      real(wp) :: rho_0 = 1000.0_wp
         !! Reference density for EOS (kg/m^3)
      real(wp) :: kpp_ri_crit = 0.3_wp
         !! Critical bulk Richardson number for the KPP BL-depth sweep.
      real(wp) :: kpp_cs_nonlocal = 6.3_wp
         !! Non-local (counter-gradient) transport coefficient C_s
         !! (LMD94 eq 20, limit value).
      real(wp) :: kpp_c_vt2 = 1.8_wp
         !! Unresolved-turbulence coefficient for the V_t^2 term in the
         !! bulk-Ri denominator (LMD94 eq 23).  Set 0 to disable V_t^2.
      real(wp) :: hdiff_kappa = 0.0_wp
         !! Horizontal diffusion coefficient for tracers (m^2/s).
         !! VESTIGIAL: its only consumers were the coastal solvers, which
         !! left with the carve-out, so nothing reads it today.  The
         !! along-coordinate equivalent is the separate
         !! `&ocean_hdiff_nml kappa_h` knob (`rdb_ocean_hdiff_tracer`).
         !! Smooths sharp density fronts to reduce BPG overshoot.
         !! Typical values: 1-10 m^2/s depending on grid resolution.

      ! Tracer parameters (salinity + temperature)
      real(wp) :: initial_salinity = 35.0_wp
         !! Initial salinity for all layers (PSU).  Used as a uniform IC
         !! unless `S_init_surface` and `S_init_bottom` are BOTH set
         !! non-zero, in which case the seed builds a linear S(z) profile
         !! from `S_init_bottom` at k=1 (bed) to `S_init_surface` at
         !! k=nz (surface).  NOTE the stable polarity is the inverse of
         !! temperature: salty/dense water belongs at the bed, so a stable
         !! haline column has `S_init_bottom > S_init_surface` (fresh
         !! surface, e.g. a river-plume column).
      real(wp) :: S_init_surface = 0.0_wp
         !! Initial salinity at the surface layer (k=nz_ml, PSU).
         !! Activates linear S(z) stratification when set non-zero
         !! together with `S_init_bottom`.
      real(wp) :: S_init_bottom = 0.0_wp
         !! Initial salinity at the bed (k=1, PSU).
      real(wp) :: S_ref = LEGACY_TRACER_S_REF
         !! RETIRED coastal-legacy EOS reference salinity (PSU).  The live
         !! ocean-path spelling is `&ocean_ic_nml S_ref`; moving this one
         !! off its default is a fail-loud configure error.
      real(wp) :: beta_S = LEGACY_TRACER_BETA_S
         !! RETIRED coastal-legacy haline contraction coefficient
         !! (kg/m^3 per PSU).  Live spelling: `&ocean_ic_nml beta_S`.
      real(wp) :: S_min = 0.0_wp
         !! Lower physical bound for salinity (PSU)
      real(wp) :: S_max = 40.0_wp
         !! Upper physical bound for salinity (PSU)
      real(wp) :: kappa_S_bg = 1.0e-5_wp
         !! Background vertical salinity diffusivity (m^2/s)
      real(wp) :: initial_temperature = 15.0_wp
         !! Initial potential temperature for all layers (degC).  Used
         !! as a uniform IC unless `T_init_surface` and `T_init_bottom`
         !! are BOTH set non-zero, in which case the seed builds a
         !! linear T(z) profile from `T_init_bottom` at k=1 (bed) to
         !! `T_init_surface` at k=nz (surface).  Stratified IC is the
         !! prerequisite for baroclinic-instability-driven eddies.
      real(wp) :: T_init_surface = 0.0_wp
         !! Initial temperature at the surface layer (k=nz_ml, degC).
         !! Activates linear T(z) stratification when set non-zero
         !! together with `T_init_bottom`.
      real(wp) :: T_init_bottom = 0.0_wp
         !! Initial temperature at the bed (k=1, degC).
      real(wp) :: T_ref = LEGACY_TRACER_T_REF
         !! RETIRED coastal-legacy EOS reference temperature (degC).  The
         !! live ocean-path spelling is `&ocean_ic_nml T_ref`; moving this
         !! one off its default is a fail-loud configure error.
      real(wp) :: alpha_T = LEGACY_TRACER_ALPHA_T
         !! RETIRED coastal-legacy thermal expansion coefficient
         !! (kg/m^3 per degC).  Live spelling: `&ocean_ic_nml alpha_T`.
      real(wp) :: T_min = -2.0_wp
         !! Lower physical bound for temperature (degC); seawater freezing
      real(wp) :: T_max = 40.0_wp
         !! Upper physical bound for temperature (degC)
      real(wp) :: kappa_T_bg = 1.0e-5_wp
         !! Background vertical temperature diffusivity (m^2/s)
      ! Sediment transport (single class, gated; default off = bit-identical).

      ! Initial condition selection
      real(wp) :: h0 = 1.0_wp
         !! Background depth for gaussian_hump IC (m)

      ! Mode splitting parameters

      ! Vertical coordinate parameters
      character(len=16) :: vcoord_type = "sigma"
         !! Vertical coordinate type: "sigma", "zsigma", "zstar", etc.
      character(len=16) :: thickness_config = "sigma"
         !! INITIAL layer-thickness profile for the ocean path (`sim_type =
         !! 'ocean'`); ignored by the coastal regimes.  Distinct from
         !! `vcoord_type`, which selects the RUNNING coordinate: this knob only
         !! decides what `h_layer` is seeded to at t=0.
         !!
         !!   "sigma"     (default) — even split of the LOCAL depth,
         !!                `h_layer(i,j,k) = b(i,j)/nz_ml`.  Bit-identical to
         !!                the pre-knob behaviour for every existing nml.
         !!   "uniform_z" — MOM6 `THICKNESS_CONFIG="uniform"` port: uniform z
         !!                interfaces laid over the GLOBAL `ocean_max_depth`,
         !!                clipped bottom-up to the local bathymetry, with
         !!                sub-floor layers collapsed to the isopycnal
         !!                `angstrom_h`.  Gives FLAT resting isopycnals under a
         !!                horizontally-uniform density stack — the layered /
         !!                isopycnal (VCOORD_LAGRANGIAN) resting state.  With
         !!                "sigma" the density interfaces instead follow the
         !!                bathymetry, which puts the full `rho_range` contrast
         !!                across every shelf break at t=0 and releases that
         !!                available potential energy as a slumping gravity
         !!                current.
      character(len=16) :: remap_method = "ppm"
         !! Vertical remapping method: "pcm", "plm", "ppm", "ppm_h4", "pqm".  Default PPM
         !! (piecewise parabolic, Colella & Woodward 1984) — the state-of-the-art
         !! conservative vertical-remap stencil for the coastal ALE coords. "pqm" is
         !! piecewise quartic (White & Adcroft 2008); it falls back to PPM for nz < 5.
      ! Full MOM6 z* parameters (VCOORD_ZSTAR_FULL)
      real(wp) :: zstar_h_surf_target = 0.0_wp
         !! Target physical thickness of the surface layer (m).
         !! 0 => auto: fall back to the lite (uniform sigma) profile
         !! per column (effectively zstar-lite per-column).  Set > 0 to
         !! anchor the surface layer at a fixed thickness regardless of H.
      character(len=16) :: zstar_stretching = "log"
         !! Surface-concentration stretching: "log" | "uniform"
      real(wp) :: zstar_h_min = 1.0e-4_wp
         !! Vanishing-layer floor (m).  Layers that would land below the
         !! local bed get clipped to this thickness rather than going to zero.
      integer :: zstar_n_surf = 0
         !! Number of "fine" near-surface layers using stretching.
         !! 0 => auto (use max(1, nz/3))
      ! Isopycnal coordinate (VCOORD_RHO) parameters
      real(wp) :: rho_ref_pressure = 2.0e7_wp
         !! Reference pressure (Pa, default 2e7 = 2000 dbar) for the
         !! potential density that defines the VCOORD_RHO coordinate.
      real(wp) :: rho_target_light = 1020.0_wp
         !! Lightest target interface potential density (kg/m³) — the
         !! surface interface for VCOORD_RHO / VCOORD_HYCOM.  With
         !! `rho_target_dense` builds the uniform light→dense
         !! target-density linspace (MOM6 `ALE_COORDINATE_CONFIG=UNIFORM`
         !! analogue) under `rho_target_profile = "uniform"`.
      real(wp) :: rho_target_dense = 1030.0_wp
         !! Densest target interface potential density (kg/m³) — the bed
         !! interface for VCOORD_RHO / VCOORD_HYCOM.  See `rho_target_light`.
      character(len=16) :: rho_target_profile = "uniform"
         !! Target-density profile of `vcoord_type = "rho" | "hycom"`:
         !! `"uniform"` (default — the `rho_target_light`→`rho_target_dense`
         !! linspace, byte-identical) or `"list"` (the `nz_layers+1`
         !! interface densities in `rho_target_list`, light first — MOM6
         !! target densities from a list/file, e.g. the
         !! `HYBRID:file,sigma2,dz` coordinate of OM4).  A uniform list is a
         !! poor fit wherever most of the volume sits in a narrow density
         !! range (the Southern Ocean: half its volume inside ~2 linspace
         !! layers).  Refused on any other coordinate.
      real(wp) :: rho_target_list(MAX_Z_FIXED_DZ + 1) = -1.0_wp
         !! `rho_target_profile = "list"`: interface potential densities
         !! (kg/m³) at `rho_ref_pressure`, LIGHTEST (surface) FIRST, strictly
         !! increasing.  Exactly `nz_layers+1` leading positive entries; the
         !! rest unset (`<= 0`, default `-1`).
      ! ALE-regrid refinements (ocean path)
      real(wp) :: regrid_time_scale = 0.0_wp
         !! Grid time-filter timescale τ (s).  The ALE regrid relaxes the
         !! coordinate a fraction dt/(τ+dt) toward the target each thermo
         !! step instead of jumping (White & Adcroft 2008), damping the
         !! σ/z* per-step grid-motion shock.  0 (default) = jump to target
         !! = bit-identical.
      logical :: remap_vel_conserve_ke = .false.
         !! KE-conserving rescale of the remapped layer velocities: scale
         !! the baroclinic anomaly per column so column KE is preserved
         !! (Adcroft & Hallberg 2006), capped 1.25×; barotropic mean
         !! untouched.  .false. (default) = momentum-only = bit-identical.
      logical :: remap_boundary_extrap = .false.
         !! Linear-exact one-sided reconstruction in the ALE remap's two
         !! boundary cells (MOM6 `BOUNDARY_EXTRAPOLATION`) instead of the
         !! PCM flatten, which leaves PLM/PPM/PPM_H4/PQM first-order at
         !! `k=1` and `k=nz`.  .false. (default) = bit-identical.
      logical :: remap_nonuniform_weights = .false.
         !! Non-uniform-grid reconstruction weights in the ALE remap's PLM
         !! slope and PPM edge estimate (Colella & Woodward 1984 eqs
         !! 1.6-1.8) instead of their equal-thickness specialisations, which
         !! are linear-exact only on a UNIFORM source column.  PPM_H4 and
         !! PQM already carry thickness-weighted stencils and are unchanged.
         !! .false. (default) = bit-identical.
      logical :: remap_check_preconditions = .false.
         !! Assert, once per ALE remap (thermo cadence), that every column
         !! satisfies what the overlap sweep has always assumed: non-negative
         !! source AND target thicknesses, and matching column totals.  Both
         !! are caller obligations and neither was ever checked; a violation
         !! silently CREATES or DELETES tracer mass.  Diagnostic knob —
         !! .false. (default) = the check never runs = bit-identical.
      logical :: check_vanished_content = .false.
         !! **I1′ tripwire** — assert `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, once
         !! per outer step, immediately after the enforcement point that
         !! establishes it (`multilayer_state_t%enforce_vanished_content`).
         !! A violation logs the offending cell count and the worst
         !! `|hTr − h·c_live|` and `error stop`s.
         !!
         !! HEAVY only in the sense that it adds two device reductions per
         !! tracer per step; the healthy path does no H←D copy.  Default
         !! `.false.`.  Turn it ON for any configuration whose coordinate
         !! actually vanishes layers (`z_fixed`, `zstar`, `zstar_full`, wet/dry) —
         !! the stability suite does.  Inert on a family with no fillers.
         !!
         !! See `src/core/ocean/README.md`, "The vanished-layer content
         !! rule".
      logical :: zfixed_closed_faces = .false.
         !! **Partial-step z-level face closure** under
         !! `vcoord_type = "z_fixed"` (Adcroft, Hill & Marshall 1997;
         !! Losch 2008 for the ice-shelf cavity).  A layer whose nominal
         !! geopotential range lies inside the bed — or inside the ice
         !! draft — carries an inert FILLER of thickness `zstar_h_min`
         !! (`<= H_VANISHED`).  A velocity face where layer `k` is a
         !! filler on EITHER side is not a thin passage, it is a WALL for
         !! that layer: no normal velocity, no mass / tracer flux, and
         !! FREE-SLIP on the tangential component.  Leaving it open makes
         !! the FV pressure gradient integrate across a staircase step of
         !! height `Δz_step`, which drives
         !! `|ρ′|·g·Δz_step/(ρ₀·dx)` out of a resting stratified state —
         !! independent of the filler thickness, so no `h`-gate reaches
         !! it.
         !!
         !! ON builds a STATIC 0/1 per-layer face mask
         !! (`ocean_metrics_t%open_u` / `open_v`) once at configure from
         !! the `z_fixed` target at `η = 0`, and composes it
         !! multiplicatively with the land metrics and the porous-barrier
         !! open-area fraction:
         !! `dy_eff(i,j,k) = dy_cu(i,j)·por_face_area_u(i,j,k)·open_u(i,j,k)`.
         !!
         !! Default `.false.` ⇒ the mask arrays stay at their `(1,1,1)`
         !! placeholder, no kernel branch is taken, byte-identical.
         !! Accepted on `z_fixed`, `zstar` (MOM6 z*) and `zstar_full` —
         !! the three GEOMETRIC families whose bed-side fillers sit at
         !! fixed reference depths (under `zstar`: the `z_fixed` fillers,
         !! decided at `η = 0` and exactly static under the dilation;
         !! under `zstar_full`: every layer below a column's partial cell
         !! when the column is shallower than the `zstar_h_surf_target`
         !! fine zone).  The mask is built from the coordinate's target at
         !! `η = 0`, and under `zstar` / `zstar_full` the IC is then seeded
         !! on that target.  Refused on every other coordinate, and without
         !! fillers to close (`z_fixed` / `zstar` without a resolved
         !! `z_fixed_h_ref`; `zstar_full` with `zstar_h_surf_target <= 0`).
         !! The name is historical.
      character(len=16) :: z_fixed_profile = "uniform"
         !! Nominal layer-thickness profile of `vcoord_type = "z_fixed"`
         !! and of `vcoord_type = "zstar"` (MOM6 z*, which dilates this
         !! same nominal profile per column by `(H + η)/H`):
         !! `"uniform"` (default — `max_depth/nz_layers` everywhere,
         !! byte-identical), `"list"` (the thicknesses in `z_fixed_dz`,
         !! surface first) or `"tanh"` (a hyperbolic-tangent stretching
         !! from `z_fixed_dz_top` at the surface, scaled to sum to
         !! `&ocean_topo_nml max_depth`; see `rdb_vcoord ::
         !! z_fixed_nominal_dz`).  The z_fixed target builder, the
         !! closed-face mask, `k_top`, the cavity partial-top rule and the
         !! bed partial-cell rule all read the profile.
         !!
         !! It is the z* COORDINATE RESOLUTION, and `vcoord_type = "hycom"`
         !! reads it too, as its z* nominal floor (MOM6 HYCOM1 floors its
         !! interfaces at the `coordinateResolution` that
         !! `ALE_COORDINATE_CONFIG` / `HYBRID:` defines): interface `k` is
         !! kept at least `Σ dz·(H+η)/H` deep.  "uniform" there means
         !! `max_depth/nz_layers` METRES, not `1/nz_layers` of the column.
         !! The `z_fixed_*` names are kept for every reader rather than
         !! introducing a parallel table that could disagree.  `vcoord_type =
         !! "zstar"` (MOM6 z*) reads it as its nominal levels as well.  Refused
         !! on any other coordinate.
      real(wp) :: z_fixed_dz(MAX_Z_FIXED_DZ) = -1.0_wp
         !! `z_fixed_profile = "list"`: nominal layer thicknesses (m),
         !! SURFACE FIRST (MOM6 `ALE_COORDINATE_CONFIG = "PARAM:..."` /
         !! `vgrid` order).  Exactly `nz_layers` leading positive entries;
         !! the rest unset (`<= 0`, default `-1`).  The profile's total is
         !! its sum; a column deeper than that puts the excess in the bed
         !! layer.
      real(wp) :: z_fixed_dz_top = 2.0_wp
         !! `z_fixed_profile = "tanh"`: surface-layer nominal thickness (m).
         !! Must satisfy `nz_layers*z_fixed_dz_top < max_depth`.
      real(wp) :: z_fixed_tanh_center = 0.5_wp
         !! `z_fixed_profile = "tanh"`: transition centre as a fraction of
         !! the layer-index span, `[0, 1]` (0 = surface, 1 = bed).
      real(wp) :: z_fixed_tanh_width = 0.25_wp
         !! `z_fixed_profile = "tanh"`: transition width as a fraction of
         !! the layer-index span (`> 0`; small = abrupt).

      ! Logging parameters
      character(len=16) :: log_level = "info"
         !! Log verbosity: "debug", "verbose", "info", "performance", "warning", "error"
      real(wp) :: status_interval = 0.0_wp
         !! Print status every N seconds of simulation time (0 = default every 100 steps)

      ! Ocean idealised setup (sim_type='ocean' only).  Drives the
      ! double-gyre and other analytical configurations.  Defaults
      ! reproduce a flat-bottom basin with no analytical wind / Coriolis
      ! pattern so existing tests are unaffected.
      ! `topo_config`        migrated to `cfg%ocean%topo%topo_config`.
      ! `ic_config`        migrated to `cfg%ocean%ic%ic_config`.
      ! `ocean_alpha_T`    migrated to `cfg%ocean%ic%alpha_T`.
      ! `ocean_rho_0`      migrated to `cfg%ocean%ic%rho_0`.
      ! `ocean_layer_rho_init` migrated to `cfg%ocean%ic%layer_rho_init`.
      ! `eady_dT_dy`       migrated to `cfg%ocean%ic%eady_dT_dy`.
      ! `eady_dT_dz`       migrated to `cfg%ocean%ic%eady_dT_dz`.
      ! `eady_T_ref`       migrated to `cfg%ocean%ic%eady_T_ref`.
      ! `eady_pert_amp`    migrated to `cfg%ocean%ic%eady_pert_amp`.
      ! `eady_pert_seed`   migrated to `cfg%ocean%ic%eady_pert_seed`.
      ! `ga_eta_amp`       migrated to `cfg%ocean%ic%ga_eta_amp`.
      ! `ga_length_scale`  migrated to `cfg%ocean%ic%ga_length_scale`.
      ! `ga_x_center`      migrated to `cfg%ocean%ic%ga_x_center`.
      ! `ga_y_center`      migrated to `cfg%ocean%ic%ga_y_center`.
      ! `wind_config`     migrated to `cfg%ocean%topo%wind_config`.
      ! `ocean_max_depth` migrated to `cfg%ocean%topo%max_depth`.
      ! `ocean_use_bt_cont_type`     migrated to `cfg%ocean%bt%use_cont_type`.
      ! `ocean_bt_upstream_h_face`   migrated to `cfg%ocean%bt%upstream_h_face`.
      ! `ocean_bt_cont_corr_bounds`  migrated to `cfg%ocean%bt%cont_corr_bounds`.
      ! `ocean_edge_depth`  migrated to `cfg%ocean%topo%edge_depth`.
      ! `ocean_slope_scale` migrated to `cfg%ocean%topo%slope_scale`.
      ! `taux_magnitude`    migrated to `cfg%ocean%topo%taux_magnitude`.
      ! `coriolis_beta`     migrated to `cfg%ocean%topo%coriolis_beta`.
      ! `coriolis_y_ref`    migrated to `cfg%ocean%topo%coriolis_y_ref`.
      ! `ocean_coriolis_form` migrated to `cfg%ocean%coriolis%form`
      ! (PR-B1 first knob-group migration, proof of pattern).
      ! `ocean_bdrag_form`           migrated to `cfg%ocean%bdrag%form`.
      ! `ocean_bdrag_cd`             migrated to `cfg%ocean%bdrag%cd`.
      ! `ocean_bdrag_r`              migrated to `cfg%ocean%bdrag%r`.
      ! `ocean_bdrag_hbbl`           migrated to `cfg%ocean%bdrag%hbbl`.
      ! `ocean_bdrag_bg_vel`         migrated to `cfg%ocean%bdrag%bg_vel`.
      ! `ocean_bdrag_bbl_thick_min`  migrated to `cfg%ocean%bdrag%bbl_thick_min`.
      ! `ocean_bdrag_bed_factor`     migrated to `cfg%ocean%bdrag%bed_factor`.
      ! `ocean_continuity_h_min` migrated to `cfg%ocean%continuity%h_min`.
      ! `ocean_continuity_ppm_limit_pos` migrated to
      ! `cfg%ocean%continuity%ppm_limit_pos`.
      ! `ocean_debug_bt_budget`         migrated to `cfg%ocean%debug%budget`.
      ! `ocean_bt_correction_bc_pgf`    migrated to `cfg%ocean%bt%correction_bc_pgf`.
      ! `ocean_bt_substep_drag`         migrated to `cfg%ocean%bt%substep_drag`.
      ! `ocean_bt_correction_visc_rem`  migrated to `cfg%ocean%bt%correction_visc_rem`.
      ! `ocean_enable_thermodynamics` migrated to
      ! `cfg%ocean%thermo%enable_thermodynamics`.
      ! `ocean_enable_ideal_age` migrated to
      ! `cfg%ocean%tracers%enable_ideal_age`.
         !! Use for circulation-pathway diagnostics + spurious
         !! diapycnal-mixing validation against MOM6.

      ! ---- Horizontal viscosity ----
      ! `ocean_lateral_closure` migrated to `cfg%ocean%hvisc%lateral_closure`.
      ! `ocean_c_smag`          migrated to `cfg%ocean%hvisc%c_smag`.
      ! `ocean_c_leith`         migrated to `cfg%ocean%hvisc%c_leith`.
      ! `ocean_kh_vel_scale`    migrated to `cfg%ocean%hvisc%kh_vel_scale`.
      ! `ocean_ah_bg`           migrated to `cfg%ocean%hvisc%ah_bg`.
      ! `ocean_ah_max`          migrated to `cfg%ocean%hvisc%ah_max`.
      ! `ocean_smag_ah`         migrated to `cfg%ocean%hvisc%smag_ah`.
      ! `ocean_smag_bi_const`   migrated to `cfg%ocean%hvisc%smag_bi_const`.
      ! `ocean_nu_4_bg`         migrated to `cfg%ocean%hvisc%nu_4_bg`.
      ! `ocean_nu_4_max`        migrated to `cfg%ocean%hvisc%nu_4_max`.
      ! `ocean_direct_stress`  migrated to `cfg%ocean%vmix%direct_stress`.
      ! `ocean_hmix_stress`    migrated to `cfg%ocean%vmix%hmix_stress`.
      ! `ocean_kv_ml_invz2`    migrated to `cfg%ocean%vmix%kv_ml_invz2`.
      ! `ocean_hmix_fixed`     migrated to `cfg%ocean%vmix%hmix_fixed`.
      ! `ocean_harmonic_visc`  migrated to `cfg%ocean%vmix%harmonic_visc`.

      ! `ocean_dt_therm_ratio` migrated to `cfg%ocean%vmix%dt_therm_ratio`.

      ! `ocean_pgf_form`     migrated to `cfg%ocean%pgf%form`.
      ! `ocean_gprime_gfs`   migrated to `cfg%ocean%pgf%gprime_gfs`.
      ! `ocean_gprime_gint`  migrated to `cfg%ocean%pgf%gprime_gint`.
      ! `ocean_gfs_scale`    migrated to `cfg%ocean%pgf%gfs_scale`.
      ! `ocean_maxvel`       migrated to `cfg%ocean%pgf%maxvel`.
      ! `ocean_nu_h` migrated to `cfg%ocean%hvisc%nu_h`.
      ! `ocean_nu_4` migrated to `cfg%ocean%hvisc%nu_4`.
      ! `n_inner`         migrated to `cfg%ocean%bt%n_inner`.
      ! `auto_n_inner`    migrated to `cfg%ocean%bt%auto_n_inner`.
      ! `cfl_bt_safety`   migrated to `cfg%ocean%bt%cfl_bt_safety`.
      ! `ocean_bebt`      migrated to `cfg%ocean%bt%bebt`.
      ! `ocean_bt_correction_h_weighted` migrated to
      ! `cfg%ocean%bt%correction_h_weighted`.
      ! `vmix_use_closure` migrated to `cfg%ocean%vmix%use_closure`.
      ! `vmix_use_kpp`     migrated to `cfg%ocean%vmix%use_kpp`.

      ! Ocean diag manager knobs migrated to `cfg%ocean%diag` —
      ! `enabled`, `filename`, `dt_out`, `vgrid`, `z_levels`, `n_z_levels`.

      type(ocean_config_t) :: ocean
         !! Nested ocean knobs.  Per-concern sub-types live under here
         !! (coriolis, thermo, bt, pgf, bdrag, hvisc, vmix, continuity,
         !! topo, ic, diag).  PR-B1 migrates knobs from this struct's
         !! flat fields into the nested form one group at a time —
         !! callers go from `cfg%ocean_X` → `cfg%ocean%group%X`.
         !! PR-B2 will split the giant `&ocean_setup_nml` to match.
   end type config_t