rdb_config Module

Reads simulation parameters from a namelist input file


Uses

  • module~~rdb_config~~UsesGraph module~rdb_config rdb_config module~rdb_constants rdb_constants module~rdb_config->module~rdb_constants module~rdb_error_ring rdb_error_ring module~rdb_config->module~rdb_error_ring module~rdb_ice_enthalpy rdb_ice_enthalpy module~rdb_config->module~rdb_ice_enthalpy module~rdb_ice_init rdb_ice_init module~rdb_config->module~rdb_ice_init module~rdb_nml_schema rdb_nml_schema module~rdb_config->module~rdb_nml_schema module~rdb_ocean_status rdb_ocean_status module~rdb_config->module~rdb_ocean_status pic_ascii pic_ascii module~rdb_config->pic_ascii pic_logger pic_logger module~rdb_config->pic_logger pic_strings pic_strings module~rdb_config->pic_strings pic_types pic_types module~rdb_constants->pic_types module~rdb_error_ring->pic_logger module~rdb_ice_enthalpy->module~rdb_constants module~rdb_ice_init->module~rdb_constants module~rdb_ice_init->module~rdb_ice_enthalpy module~rdb_grid rdb_grid module~rdb_ice_init->module~rdb_grid module~rdb_ice_column rdb_ice_column module~rdb_ice_init->module~rdb_ice_column module~rdb_ice_state rdb_ice_state module~rdb_ice_init->module~rdb_ice_state module~rdb_multilayer_state rdb_multilayer_state module~rdb_ice_init->module~rdb_multilayer_state module~rdb_ocean_metrics rdb_ocean_metrics module~rdb_ice_init->module~rdb_ocean_metrics module~rdb_nml_schema->module~rdb_constants module~rdb_nml_schema->module~rdb_error_ring module~rdb_nml_schema->pic_logger module~rdb_grid->module~rdb_constants module~rdb_ice_column->module~rdb_constants module~rdb_ice_column->module~rdb_ice_enthalpy module~rdb_ice_mass rdb_ice_mass module~rdb_ice_column->module~rdb_ice_mass module~rdb_ice_optics rdb_ice_optics module~rdb_ice_column->module~rdb_ice_optics module~rdb_ice_state->module~rdb_constants module~rdb_ice_state->module~rdb_ice_enthalpy module~rdb_ice_state->module~rdb_grid module~rdb_ice_state->module~rdb_ice_column iso_fortran_env iso_fortran_env module~rdb_ice_state->iso_fortran_env module~rdb_mem_report rdb_mem_report module~rdb_ice_state->module~rdb_mem_report module~rdb_multilayer_state->module~rdb_constants module~rdb_multilayer_state->module~rdb_error_ring module~rdb_multilayer_state->pic_logger module~rdb_multilayer_state->module~rdb_grid module~rdb_multilayer_state->iso_fortran_env module~rdb_efp rdb_efp module~rdb_multilayer_state->module~rdb_efp module~rdb_multilayer_state->module~rdb_mem_report module~rdb_tracer rdb_tracer module~rdb_multilayer_state->module~rdb_tracer module~rdb_ocean_metrics->module~rdb_constants module~rdb_ocean_metrics->module~rdb_error_ring module~rdb_ocean_metrics->module~rdb_ocean_status module~rdb_ocean_metrics->pic_logger module~rdb_ocean_metrics->pic_strings module~rdb_ocean_metrics->module~rdb_grid module~rdb_ocean_metrics->iso_fortran_env module~rdb_io_netcdf rdb_io_netcdf module~rdb_ocean_metrics->module~rdb_io_netcdf module~rdb_ocean_metrics->module~rdb_mem_report module~rdb_ocean_bipolar rdb_ocean_bipolar module~rdb_ocean_metrics->module~rdb_ocean_bipolar module~rdb_ocean_fold rdb_ocean_fold module~rdb_ocean_metrics->module~rdb_ocean_fold netcdf netcdf module~rdb_ocean_metrics->netcdf module~rdb_efp->iso_fortran_env ieee_arithmetic ieee_arithmetic module~rdb_efp->ieee_arithmetic module~rdb_ice_mass->module~rdb_constants module~rdb_ice_mass->module~rdb_ice_enthalpy module~rdb_ice_optics->module~rdb_constants module~rdb_ice_optics->module~rdb_ice_enthalpy module~rdb_io_netcdf->module~rdb_constants module~rdb_io_netcdf->module~rdb_error_ring module~rdb_io_netcdf->pic_logger module~rdb_io_netcdf->pic_strings module~rdb_io_netcdf->iso_fortran_env module~rdb_io_netcdf->netcdf iso_c_binding iso_c_binding module~rdb_io_netcdf->iso_c_binding module~rdb_mem_report->module~rdb_constants module~rdb_mem_report->pic_logger module~rdb_mem_report->pic_strings module~rdb_mem_report->iso_fortran_env module~rdb_ocean_bipolar->module~rdb_constants module~rdb_ocean_fold->module~rdb_constants module~rdb_tracer->module~rdb_constants module~rdb_tracer->module~rdb_grid module~rdb_tracer->iso_fortran_env module~rdb_tracer->module~rdb_mem_report

Used by

  • module~~rdb_config~~UsedByGraph module~rdb_config rdb_config module~rdb_config_schema rdb_config_schema module~rdb_config_schema->module~rdb_config module~rdb_decomp rdb_decomp module~rdb_decomp->module~rdb_config module~rdb_driver rdb_driver module~rdb_driver->module~rdb_config module~rdb_ocean_engine rdb_ocean_engine module~rdb_driver->module~rdb_ocean_engine module~rdb_ocean_state rdb_ocean_state module~rdb_driver->module~rdb_ocean_state module~rdb_halo rdb_halo module~rdb_driver->module~rdb_halo module~rdb_ocean_console_stats rdb_ocean_console_stats module~rdb_driver->module~rdb_ocean_console_stats module~rdb_ocean_dyn rdb_ocean_dyn module~rdb_driver->module~rdb_ocean_dyn module~rdb_handle rdb_handle module~rdb_handle->module~rdb_config module~rdb_handle->module~rdb_ocean_engine module~rdb_handle->module~rdb_ocean_state module~rdb_ocean_api rdb_ocean_api module~rdb_ocean_api->module~rdb_config module~rdb_ocean_api->module~rdb_handle module~rdb_ocean_api->module~rdb_ocean_engine module~rdb_ocean_diag_derived rdb_ocean_diag_derived module~rdb_ocean_api->module~rdb_ocean_diag_derived module~rdb_ocean_diag_fills rdb_ocean_diag_fills module~rdb_ocean_api->module~rdb_ocean_diag_fills module~rdb_ocean_api->module~rdb_ocean_dyn module~rdb_ocean_fold_apply rdb_ocean_fold_apply module~rdb_ocean_api->module~rdb_ocean_fold_apply module~rdb_ocean_data_forcing rdb_ocean_data_forcing module~rdb_ocean_data_forcing->module~rdb_config module~rdb_ocean_data_input rdb_ocean_data_input module~rdb_ocean_data_forcing->module~rdb_ocean_data_input module~rdb_ocean_halo_state rdb_ocean_halo_state module~rdb_ocean_data_forcing->module~rdb_ocean_halo_state module~rdb_ocean_data_input->module~rdb_config module~rdb_ocean_engine->module~rdb_config module~rdb_ocean_engine->module~rdb_decomp module~rdb_ocean_engine->module~rdb_ocean_data_forcing module~rdb_ocean_engine->module~rdb_ocean_data_input module~rdb_ocean_setup rdb_ocean_setup module~rdb_ocean_engine->module~rdb_ocean_setup module~rdb_ocean_stability_audit rdb_ocean_stability_audit module~rdb_ocean_engine->module~rdb_ocean_stability_audit module~rdb_ocean_engine->module~rdb_ocean_state module~rdb_state rdb_state module~rdb_ocean_engine->module~rdb_state module~rdb_ocean_engine->module~rdb_halo module~rdb_ocean_engine->module~rdb_ocean_diag_derived module~rdb_ocean_engine->module~rdb_ocean_diag_fills module~rdb_ocean_fold_exchange rdb_ocean_fold_exchange module~rdb_ocean_engine->module~rdb_ocean_fold_exchange module~rdb_ocean_halo rdb_ocean_halo module~rdb_ocean_engine->module~rdb_ocean_halo module~rdb_ice_evp rdb_ice_evp module~rdb_ocean_engine->module~rdb_ice_evp module~rdb_ice_transport rdb_ice_transport module~rdb_ocean_engine->module~rdb_ice_transport module~rdb_ocean_engine->module~rdb_ocean_dyn module~rdb_ocean_engine->module~rdb_ocean_fold_apply module~rdb_ocean_engine->module~rdb_ocean_halo_state module~rdb_ice_ocean_coupler rdb_ice_ocean_coupler module~rdb_ocean_engine->module~rdb_ice_ocean_coupler module~rdb_ocean_setup->module~rdb_config module~rdb_ocean_setup->module~rdb_decomp module~rdb_ocean_setup->module~rdb_ocean_state module~rdb_ocean_setup->module~rdb_halo module~rdb_ocean_setup->module~rdb_ocean_fold_exchange module~rdb_ocean_setup->module~rdb_ocean_halo module~rdb_ocean_setup->module~rdb_ocean_dyn module~rdb_ocean_setup->module~rdb_ocean_fold_apply module~rdb_ocean_setup->module~rdb_ocean_halo_state module~rdb_ocean_stability_audit->module~rdb_config module~rdb_ocean_state->module~rdb_config module~rdb_ocean_state->module~rdb_decomp module~rdb_ocean_state->module~rdb_ocean_data_forcing module~rdb_ocean_state->module~rdb_ocean_data_input module~rdb_ocean_z_init rdb_ocean_z_init module~rdb_ocean_state->module~rdb_ocean_z_init module~rdb_ocean_restart_io rdb_ocean_restart_io module~rdb_ocean_state->module~rdb_ocean_restart_io module~rdb_continuity rdb_continuity module~rdb_ocean_state->module~rdb_continuity module~rdb_ocean_state->module~rdb_ocean_dyn module~rdb_ocean_z_init->module~rdb_config module~rdb_state->module~rdb_config module~rdb_halo->module~rdb_decomp module~rdb_ocean_diag_derived->module~rdb_ocean_state module~rdb_ocean_diag_derived->module~rdb_ocean_diag_fills module~rdb_ocean_diag_fills->module~rdb_ocean_state module~rdb_ocean_fold_exchange->module~rdb_decomp module~rdb_ocean_halo->module~rdb_decomp module~rdb_ocean_restart_io->module~rdb_decomp module~rdb_barotropic_substep rdb_barotropic_substep module~rdb_barotropic_substep->module~rdb_ocean_fold_exchange module~rdb_barotropic_substep->module~rdb_ocean_halo module~rdb_continuity->module~rdb_ocean_fold_exchange module~rdb_continuity->module~rdb_ocean_halo module~rdb_continuity->module~rdb_ocean_fold_apply module~rdb_ice_evp->module~rdb_ocean_halo module~rdb_ice_transport->module~rdb_halo module~rdb_ice_transport->module~rdb_ocean_halo module~rdb_ice_transport->module~rdb_continuity module~rdb_ice_transport->module~rdb_ocean_halo_state module~rdb_ocean_bt_wide rdb_ocean_bt_wide module~rdb_ocean_bt_wide->module~rdb_ocean_halo module~rdb_ocean_bt_wide->module~rdb_barotropic_substep module~rdb_ocean_chksum rdb_ocean_chksum module~rdb_ocean_chksum->module~rdb_halo module~rdb_ocean_console_stats->module~rdb_halo module~rdb_ocean_dyn->module~rdb_ocean_halo module~rdb_ocean_dyn->module~rdb_barotropic_substep module~rdb_ocean_dyn->module~rdb_continuity module~rdb_ocean_dyn->module~rdb_ocean_bt_wide module~rdb_ocean_dyn->module~rdb_ocean_chksum module~rdb_ocean_dyn->module~rdb_ocean_console_stats module~rdb_ocean_dyn->module~rdb_ocean_fold_apply module~rdb_ocean_dyn->module~rdb_ocean_halo_state module~rdb_ocean_fold_apply->module~rdb_ocean_fold_exchange module~rdb_ocean_halo_state->module~rdb_ocean_halo module~rdb_ocean_halo_state->module~rdb_ocean_fold_apply proc~ocean_cavity_mass_step ocean_cavity_mass_step proc~ocean_cavity_mass_step->module~rdb_halo module~rdb_ice_ocean_coupler->module~rdb_ocean_halo_state

Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: BT_HALO_AUTO_SENTINEL = -1

&ocean_bt_nml bt_halo default: AUTO. Resolved at configure (in the driver, where compute_size is known). AUTO resolves to 0 — the march-in is OPT-IN (set bt_halo explicitly) because it is not yet bit-reproducible against the serial run. See resolve_bt_halo.

integer, public, parameter :: BT_HALO_AUTO_WIDTH = 8

The recommended EXPLICIT march-in width (the validated production width). AUTO no longer selects it — see resolve_bt_halo.

integer, public, parameter :: MAX_ICE_HLIM_VALS = 16

Maximum number of &ocean_ice_nml hlim entries a user may STATE (PR-58). Caps how many edges may be listed, not ncat (unbounded elsewhere) — production ITDs are 5-10 categories, so 16 is a generous soft cap; exceeding it is not possible for ncat<=15, and for larger ncat the remaining edges simply extrapolate (ice_hlim_spec_is_valid). Deliberately NOT matched to MAX_OCEAN_LAYER_RHO_INIT (64) — that cap is dimensioned by nz, this one by ncat+1.

integer, public, parameter :: MAX_OCEAN_DIAG_Z_LEVELS = 64

Maximum number of z-levels for ocean-diag z_fixed output vgrid

integer, public, parameter :: MAX_OCEAN_LAYER_RHO_INIT = 64

Maximum number of per-layer density init entries.

integer, public, parameter :: MAX_TIDAL_CONSTITUENTS = 10

Maximum number of tidal constituents

integer, public, parameter :: OBC_MAX_TIDAL_CFG = 8

Maximum tidal constituents per edge in the &ocean_bc_nml namelist. Mirrors OBC_MAX_TIDAL_CONSTITUENTS in rdb_ocean_boundary_types.

real(kind=wp), public, parameter :: ZFIXED_CAVITY_NU_H_MIN = 2.0_wp

Lower envelope of &ocean_hvisc_nml nu_h (m²/s) under vcoord_type = "z_fixed" x &ocean_cavity_dyn_nml enable. Below it validate_config WARNS (see zfixed_cavity_nu_h_below_envelope for the measurement).

real(kind=wp), private, parameter :: LEGACY_TRACER_ALPHA_T = 0.17_wp

Historical &tracer_nml alpha_T default (kg/m^3 per degC).

real(kind=wp), private, parameter :: LEGACY_TRACER_BETA_S = 0.78_wp

Historical &tracer_nml beta_S default (kg/m^3 per PSU).

real(kind=wp), private, parameter :: LEGACY_TRACER_S_REF = 0.0_wp

Historical &tracer_nml S_ref default (PSU).

real(kind=wp), private, parameter :: LEGACY_TRACER_T_REF = 15.0_wp

Historical &tracer_nml T_ref default (degC).

integer, private, parameter :: MAX_Z_FIXED_DZ = 128

Maximum number of &vcoord_nml z_fixed_dz entries (nominal z_fixed layer thicknesses).


Derived Types

type, public ::  config_t

Container for all runtime simulation parameters

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.

Read more…
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)

Read more…
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.

Read more…
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.

Read more…
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.

Read more…
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”

type, public ::  dataovr_entry_config_t

One file-driven surface-forcing tag in &ocean_dataovr_nml. A blank file means “this tag is not file-driven” — the slot keeps whatever the configure-time scalar/formula path seeded.

Components

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

Added after scale, once at read.

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

Path to the pre-regridded field(x, y, time) NetCDF. Blank ⇒ tag inactive.

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

Multiplied into the slab once at read (unit conversion).

character(len=64), public :: var = ""

Variable name inside file. Required when file is set — a blank var with a non-blank file is a fail-loud setup abort, never a guessed name.

type, public ::  ocean_bc_config_t

Boundary-condition configuration read from &ocean_bc_nml. All defaults reproduce a closed-wall run — existing nmls that omit this block are bit-identical to prior behaviour.

Components

Type Visibility Attributes Name Initial
character(len=16), public :: east = "wall"
real(kind=wp), public :: east_clamped_eta = 0.0_wp
real(kind=wp), public :: east_clamped_u = 0.0_wp
real(kind=wp), public :: east_ext_u = 0.0_wp

Exterior barotropic u, east (m/s).

real(kind=wp), public :: east_inflow_S = 35.0_wp
real(kind=wp), public :: east_inflow_T = 10.0_wp
integer, public :: east_n_tidal = 0
real(kind=wp), public :: east_tidal_amp(OBC_MAX_TIDAL_CFG) = 0.0_wp
real(kind=wp), public :: east_tidal_omega(OBC_MAX_TIDAL_CFG) = 0.0_wp
real(kind=wp), public :: east_tidal_phase(OBC_MAX_TIDAL_CFG) = 0.0_wp
character(len=16), public :: flather_form = "legacy"

“legacy” (default) = v1 Flather (u_ext=0, no interior vel); “full” = half-characteristic form (Flather 1976).

logical, public :: mask_wall_velocity = .true.

Zero the T-cell wet-mask in the ghost cells beyond every solid WALL edge at setup, so the derived C-grid face masks (wet_u/wet_v/wet_q) are 0 at the wall face and the existing per-stage mask_layer_velocities clears the wall-normal velocity (MOM6’s mask-in-the-update; the halo beyond a wall is land). DEFAULT ON (2026-07): a solid wall must carry zero normal velocity; leaving it garbage (flux-masked but nonzero) was a bug. Set .false. to recover the pre-fix legacy answer for a closed-basin run (e.g. to reproduce an old double_gyre baseline exactly). Without it a flat all-wet channel leaves the wall-normal face velocity as unmasked garbage — the wall flux is masked so mass conserves, but the raw v/u at the wall drifts to the maxvel clamp and paints a spurious vorticity band in diagnostics. Only WALL edges are touched: periodic edges keep their wrapped (wet) ghosts, open/OBC edges keep the interior value (OBC override). Default .false. ⇒ wall ghosts untouched ⇒ bit-identical to legacy runs (this also changes the continuity PPM mirror-h at the wall, which is why it must be opt-in).

character(len=16), public :: north = "wall"
real(kind=wp), public :: north_clamped_eta = 0.0_wp
real(kind=wp), public :: north_clamped_v = 0.0_wp
real(kind=wp), public :: north_ext_v = 0.0_wp

Exterior barotropic v, north (m/s).

real(kind=wp), public :: north_inflow_S = 35.0_wp
real(kind=wp), public :: north_inflow_T = 10.0_wp
integer, public :: north_n_tidal = 0
real(kind=wp), public :: north_tidal_amp(OBC_MAX_TIDAL_CFG) = 0.0_wp
real(kind=wp), public :: north_tidal_omega(OBC_MAX_TIDAL_CFG) = 0.0_wp
real(kind=wp), public :: north_tidal_phase(OBC_MAX_TIDAL_CFG) = 0.0_wp
real(kind=wp), public :: nudge_tau_in = 0.0_wp

Inflow nudging timescale (s, Marchesiello et al. 2001). 0 = off.

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

Outflow nudging timescale (s). 0 = off.

logical, public :: obc_tidal_nodal = .false.

Apply the 18.6-yr nodal factor f_c + equilibrium/nodal phase (V_c + u_c) to the open-boundary tidal elevation forcing, keeping the interior body tide and the boundary tide phase-consistent (same generator, same shared &ocean_tides_nml reference epoch). Default .false. ⇒ legacy static-phase OBC sum (bit-identical). When .true. the *_tidal_phase becomes a Greenwich phase LAG (subtracted).

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

Running-mean weight (0=full running mean, 1=instant; default=1).

real(kind=wp), public :: orlanski_rx_max = 10.0_wp

Clamp on the Orlanski nondimensional phase speed (grid cells / step).

character(len=16), public :: radiation_scheme = "anomaly"

“anomaly” (default) = v1 BT-mean + zero-gradient anomaly. “orlanski” = per-layer implicit-upwind radiation (Orlanski 1976).

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

Inflow reservoir length scale (m). 0 = instantaneous inflow (T_data applied on inflow unconditionally — same as v1 for inflow direction when feature is active).

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

Outflow reservoir length scale (m). 0 = feature disabled (v1 sign-switch path unchanged). Non-zero engages the implicit Marchesiello et al. 2001 reservoir on all open-ish edges.

character(len=16), public :: south = "wall"
real(kind=wp), public :: south_clamped_eta = 0.0_wp
real(kind=wp), public :: south_clamped_v = 0.0_wp
real(kind=wp), public :: south_ext_v = 0.0_wp

Exterior barotropic v, south (m/s).

real(kind=wp), public :: south_inflow_S = 35.0_wp
real(kind=wp), public :: south_inflow_T = 10.0_wp
integer, public :: south_n_tidal = 0
real(kind=wp), public :: south_tidal_amp(OBC_MAX_TIDAL_CFG) = 0.0_wp
real(kind=wp), public :: south_tidal_omega(OBC_MAX_TIDAL_CFG) = 0.0_wp
real(kind=wp), public :: south_tidal_phase(OBC_MAX_TIDAL_CFG) = 0.0_wp
logical, public :: sponge_relax_tracers = .false.

When .true., extend the sponge relaxation to h_layer + tracers. Default .false. — preserves bit-identity of existing sponge runs.

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

Peak relaxation rate (1/s) at the outer face of the band.

integer, public :: sponge_width = 0

Number of cells in the sponge band. 0 disables the sponge.

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

BC type string for the west edge. Recognised: “wall” (default), “open”, “tidal”, “clamped”, “sponge”, “chapman”, “periodic”. “tripolar_fold” is accepted on the NORTH edge only (Murray bipolar cap; requires grid_config=”tripolar” + periodic w/e).

real(kind=wp), public :: west_clamped_eta = 0.0_wp
real(kind=wp), public :: west_clamped_u = 0.0_wp
real(kind=wp), public :: west_ext_u = 0.0_wp

Exterior barotropic u, west (m/s).

real(kind=wp), public :: west_inflow_S = 35.0_wp
real(kind=wp), public :: west_inflow_T = 10.0_wp
integer, public :: west_n_tidal = 0
real(kind=wp), public :: west_tidal_amp(OBC_MAX_TIDAL_CFG) = 0.0_wp
real(kind=wp), public :: west_tidal_omega(OBC_MAX_TIDAL_CFG) = 0.0_wp
real(kind=wp), public :: west_tidal_phase(OBC_MAX_TIDAL_CFG) = 0.0_wp

type, public ::  ocean_bdrag_config_t

Components

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

Minimum effective BBL thickness (m). Typical 0.1 m.

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

Multiplier on the bed-layer (k=1) drag tendency only. Default 1.0 = bit-identical.

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

Background velocity floor (m/s) for the distributed quadratic form. Typical 0.1 m/s.

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

Quadratic drag coefficient (dimensionless). Typical 2.5e-3. Zero disables the quadratic branch.

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

Side-wall drag coefficient (dimensionless) for the channel drag. Zero (default) disables the branch.

logical, public :: channel_drag = .false.

Lateral side-wall (channel) drag: a per-layer Rayleigh sink at every layer with a partially blocked cross-stream perimeter. Default .false.. Flat-bottom/all-wet ⇒ exact no-op.

character(len=16), public :: form = "quadratic"

Bottom-drag variant: “quadratic” (default, log-layer du/dt = -C_d·|U|·u/h) or “linear” (Rayleigh du/dt = -r·u).

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

Bottom-boundary-layer thickness (m) over which drag is distributed. Zero (default) = bed-only mode.

logical, public :: implicit = .false.

Backward-Euler (implicit) bottom drag: u^{n+1}=u/(1+dt·λ), unconditionally stable. Default .false. = explicit forward-Euler (bit-identical) but unstable on thin shelf layers. Recommend .true. for shallow-shelf runs.

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

Linear Rayleigh coefficient (1/s). Active when form = "linear".

type, public ::  ocean_bt_config_t

Components

Type Visibility Attributes Name Initial
logical, public :: auto_n_inner = .false.

If .true., derive n_inner at setup from the gravity-wave CFL, evaluated per WET cell (local depth with local cell size, MOM6 set_dtbt; land never limits it). Default .false..

logical, public :: bc_pgf_forcing = .true.

MOM6 split (BT_force + eta_PF): the barotropic substep is forced by the depth mean of the FULL slow PGF — baroclinic part included — minus only the free-surface term that PGF itself carries at the η it was evaluated on (none for the surface-relative MONT/FV_LITE/FV_WRIGHT forms), which the substep’s own -g_bt·∇η replaces. .false. restores the legacy split, which subtracted the WHOLE depth-mean PGF and so never let the barotropic mode feel the baroclinic bottom-pressure gradient (JEBAR; ~0 Sv through Drake Passage on the global 1° case against MOM6’s ~160 Sv).

real(kind=wp), public :: bebt = 0.1_wp

BT continuity-flux velocity projection weight (MOM6 BEBT). Default 0.1 = MOM6’s own default for that parameter: damps the barotropic gravity waves at |λ|² = 1 − b·a² per substep (a = c·dt_bt·k_eff), which is what damps the barotropic grid-scale mode under pred_corr. 0.0 = pure forward-backward Euler (neutral, the pre-2026-09-22 default). The FB stability limit tightens to a ≤ 2/√(1+2·bebt) (MOM6 set_dtbt’s 1+2·BEBT factor).

integer, public :: bt_halo = BT_HALO_AUTO_SENTINEL

Wide-halo march-in width. -1 (default) = AUTO, which resolves to 0: the march-in is OPT-IN. A decomposed run with the march-in is not bit-identical to the serial run over variable bathymetry or with open boundaries (measured by test_ocean_decomp_bitid_mpi; flat-bottom closed / periodic / spherical cases are), so the default keeps every decomposition bit-reproducible. 8 (BT_HALO_AUTO_WIDTH) is the recommended explicit width. 0 = explicit off (per-substep grouped exchange, v1 bit-identical). Even positive value: widen the BT ghost band to nghost + bt_halo and fire one grouped exchange every bt_halo/2 substeps. Odd values are rounded DOWN to even with a warning. Fail-loud exclusions (apply when bt_halo is set EXPLICITLY > 0; AUTO instead silently resolves to 0): wet/dry enable, use_cont_type, upstream_h_face, tides enable, psurf enable, porous enable, cavity_dyn enable, supergrid/tripolar grid_config. The set of record is bt_halo_auto_exclusion; keep it and the validate_config checks in lockstep.

logical, public :: bt_rem_from_visc_rem = .false.

PR-2 (bt-rem-from-av-rem): bt_rem_u/v built from the SAME viscous remnant the layered momentum solve uses, instead of the linear-piston substep_drag law or the static 1.0 no-op. Matches MOM6’s barotropic solver: av_rem = Σ_k frhat_k·visc_rem_k (the visc_rem depth mean, frhat_k the face layer fraction derive_bt_from_layers already uses), then bt_rem = mask·av_rem**(1/n_inner) (zero where mask·av_rem <= 0), built ONCE per barotropic call — after the visc_rem producer, before the inner substeps — into the existing bt_work%bt_rem_u/v multiplier the substep loop already reads. This is the fix for the bbl_glue day-253 instability (the barotropic solver was seeing weak explicit drag while the layers were strongly glued): the fast mode now feels the SAME friction. Default .false. ⇒ no answer change. Self-sufficient (D1 follow-up) — the visc_rem producer runs whenever this is on, decoupled from the retired correction_visc_rem; mutually exclusive with substep_drag (bed drag would be double-counted — once inside visc_rem via the glue/implicit_drag fold, once again via the linear piston) and with bt_halo > 0 (the wide-halo BT clone’s metrics_w/halo-widened arrays carry no av_rem/visc_rem ghost width yet — same posture as porous). Composes with wave_drag (multiplied in after).

real(kind=wp), public :: cfl_bt_safety = 0.65_wp

Safety fraction on the shallow-water CFL bound when auto_n_inner = .true. (typical 0.65-0.7).

logical, public :: cont_corr_bounds = .false.

When .true. (and use_cont_type), the η-correction bound uses the BT_cont face-by-face flux limits. Default .false..

logical, public :: correction_bc_pgf = .false.

Adds a per-layer baroclinic-PGF retro-correction for the η change during the BT substep. Requires pgf%form = "fv_mom6".

logical, public :: correction_h_weighted = .false.

RETIRED (2026-10-02) — setting it .true. is a fail-loud validate_config error. It distributed the barotropic increment by h_face(k)/⟨h⟩_h, which is not energy-conserving: beyond the barotropic ΔKE it adds a positive-definite source ½Δ²·H·(κ−1), κ = Σh³Σh/(Σh²)², plus a shear feedback that grew the stretched-z_fixed 1-degree Southern Ocean to a non-finite state on day 16. MOM6 has no h-weighted fold (its barotropic acceleration is the same in every layer). The key stays registered only so the refusal can say why; drag-aware weighting is correction_visc_rem.

logical, public :: correction_visc_rem = .false.

RETIRED (2026-10, D1 follow-up) — setting .true. is a fail-loud validate_config error. This used to weight the BT-corrector fold by visc_rem(k)/⟨visc_rem⟩_h instead of uniformly, but MOM6’s barotropic solver gives every layer the SAME u_accel_bt via accel_layer_u — no visc_rem weight — folded into up BEFORE vertvisc distributes it via the SAME implicit friction the BBL glue uses, so MOM6 never damps it twice. This fold did, and the SECOND, unbounded visc_rem_k/⟨visc_rem⟩_h ratio is what NaNs the 1-degree Southern Ocean z* open-step case under bbl_glue at step ~40 (see validate_config’s refusal message for the measured isolation). visc_rem_chain is the replacement and uses the UNIFORM fold, matching MOM6. The key stays registered only so the refusal can say why; the underlying kernel dispatch (apply_bt_correction’s use_visc_rem) and its direct unit tests are untouched.

logical, public :: forcing_visc_rem = .false.

MOM6 wt_u parity for the BT FORCING assembly: weight each layer’s contribution to F_bt_u/v (and to the PGF-projection subtraction, which must use the same weights) by h_face·visc_rem(k) instead of h_face. Layers the implicit friction will immediately damp — grounded sliver stacks under the vdiff BBL glue — then contribute nothing to the fast loop, which otherwise integrates the spurious grounded-layer PGF’s depth-mean ballistically (PGF_BUG.md §9). Self-sufficient (D1 follow-up) — the visc_rem producer runs whenever this is on, decoupled from the retired correction_visc_rem.

character(len=16), public :: frhat_scheme = "hybrid"

rdb_barotropic_coupling::frhat_h_face_step’s per-layer face-thickness closure for EVERY barotropic depth mean that reads a layer’s face thickness: derive_bt_from_layers, face_depth_mean_u/v, face_depth_mean_rem_u/v (forcing_visc_rem’s wt_u), apply_bt_correction’s open/visc_rem folds, and — through face_depth_mean_u/v — compute_bt_rem_from_visc_rem’s av_rem.

Read more…
integer, public :: n_inner = 0

Mode-split barotropic substeps per outer step. 0 (default) routes the unsplit ocean_dyn_step; >= 1 routes the split solver with that many fast substeps (production ~30-100). Overwritten when auto_n_inner = .true..

real(kind=wp), public :: pc_be = 0.6_wp

pred_corr predictor fraction (MOM6 BE, 0.6 in the control run): the predictor’s provisional velocity advances to BE·dt; only the corrector takes the full step. Unused under ssp_rk2.

logical, public :: renorm_visc_rem = .false.

MOM6 continuity-inversion parity (SPEC §4 S2b): pass visc_rem_u/v into the slow-continuity transport-matching renormaliser, switching it to the γ-weighted du + Jacobian form (u_cor = u + du·γ_k) — a heavily-frictioned layer receives a smaller share of the barotropic correction than an undamped one, and the same weighting lands in the mass fluxes. Behaviour change when on (the flux expression tree gains the γ factors). Self-sufficient (D1 follow-up) — the visc_rem producer runs whenever this is on, decoupled from the retired correction_visc_rem.

logical, public :: rescale_strong_drag = .false.

MOM6 RESCALE_STRONG_DRAG: under strong_drag, bt_rem**n_inner /= av_rem exactly (the rational form is only an approximation), so the barotropic-correction Δu is rescaled by min(bt_rem**n_inner/av_rem, 1.0) before it is folded into the layers, keeping the correction consistent with the TRUE depth-mean remnant. Requires strong_drag = .true.; inert (and refused) otherwise.

character(len=16), public :: split_scheme = "pred_corr"

Outer time-integration scheme for the split-explicit ocean path (SPEC §4 S3/S4). Both schemes are supported and both are under test; they differ in what they cost you.

Read more…
logical, public :: strong_drag = .false.

MOM6 BT_STRONG_DRAG (default .false.): replace the plain power form with the rational approximation bt_rem = mask·n_inner·av_rem/(1 + (n_inner-1)·av_rem), which damps LESS aggressively per substep for a given av_rem — recommended only if the plain av_rem**(1/n_inner) form still leaves the acceptance-gate run unstable (D3, a measured deviation to report, not a default). Requires bt_rem_from_visc_rem = .true.; inert otherwise (checked in validate_config).

logical, public :: substep_drag = .false.

Multiplies the per-face BT velocity update by a damping factor every inner step.

logical, public :: substep_zeta_ke = .true.

When .true. (default, bit-identical) the BT fast loop integrates its LIVE relative vorticity + KE gradient ((ζ_bt+f)·v − ∇KE_bt) every substep. .false. = MOM6 parity: the fast loop carries planetary Coriolis only (f·v_at_u, live velocities); ζ_bt-advection and ∇KE stay FROZEN inside the depth-mean forcing F_bt_*_fast, exactly like MOM6’s q = f/D weights (btstep_find_Cor — planetary only, no ζ, no KE term). The subtract_fast_cor_ref reference reduces to its f·v̄ part so the τ=0 cancellation stays exact. Motivation: the live nonlinear terms host an exponential ~4Δx wall-trapped BT mode on shelf rims (wall-biased KE stencil: wall faces contribute zero KE, so −∇KE points into walls and corners) that the bound_kh-clamped viscosity (λ·dt ≤ bound_coef/8) cannot damp at large dt — the 1024²×100 dt=600 SE-corner column evacuation (h-guard step 106).

logical, public :: upstream_h_face = .false.

When .true., the BT chain uses per-face upstream-PPM column-sum thickness instead of centred h_face. Default .false..

logical, public :: use_cont_type = .false.

When .true., the BT substep uses a piecewise-cubic flux-bounded closure instead of uh = u·h_face. Default .false..

logical, public :: visc_rem_chain = .true.

PR-3 (visc_rem audit + unification, D1 — revised 2026-10 once MOM6 settled the BT-correction fold question): ONE switch for exactly MOM6’s vertvisc_remnant/av_rem/bt_rem set — DEFAULT ON since PR-4 (the flip, 2026-10), TOGETHER with &ocean_vdiff_nml hvel_mom6/bbl_glue — MOM6 gives the barotropic solver the same friction the layered vertical solve applies; without it the BBL glue’s bed piston never reaches the fast mode (NaN at day 253 on the 1-degree Southern Ocean closed-face case under glue-only). .false. restores the pre-PR-4 linear-piston substep_drag behaviour for bt_rem (mutually exclusive with this switch, D2 below) — equivalent to switching on the visc_rem PRODUCER (decoupled from the retired correction_visc_rem, runs whenever any consumer below needs it) plus forcing_visc_rem (MOM6 wt_u), renorm_visc_rem (MOM6 continuity u_cor = u + du*visc_rem, which IS how MOM6 ties visc_rem to a velocity correction) and bt_rem_from_visc_rem (MOM6’s barotropic av_rem/bt_rem viscous-remnant depth mean) all at once. The barotropic-correction fold (apply_bt_correction) stays UNIFORM under this switch — MOM6’s accel_layer_u never weights it by visc_rem, so neither does this chain; see correction_visc_rem’s docstring for why that fold is retired, not folded in here. Same caveat as before: without &ocean_vdiff_nml implicit_drag=.true. or bbl_glue=.true., visc_rem stays ≡ 1 and the whole chain is a legal, warned, no-op. The three *_visc_rem consumer knobs (forcing_visc_rem/renorm_visc_rem/bt_rem_from_visc_rem) stay individually settable (never retired) for the existing fine-grained tests, each an equivalent SUBSET of this switch, never a superset, and each now SELF-SUFFICIENT (no longer “requires” a separate producer knob — the producer runs whenever any one of them is on). strong_drag/ rescale_strong_drag stay separate namelist keys per D1 (MOM6 has its own BT_STRONG_DRAG/RESCALE_STRONG_DRAG parameters for them) and require this switch (or bt_rem_from_visc_rem) on, same as before. accel_visc_rem (&ocean_vdiff_nml) is likewise NOT part of this chain and is RETIRED (see its own docstring) — no MOM6 state-update equivalent. Default .false. ⇒ no answer change (PR-4 is the default flip). D2: mutually exclusive with substep_drag (checked via bt_rem_from_visc_rem’s existing requirement, which this switch satisfies identically to setting it directly).

logical, public :: wave_drag = .false.

Master switch for the barotropic linear (Rayleigh) wave drag — the bulk energy sink for the barotropic tide (Egbert & Ray 2001; Jayne & St Laurent 2001), MOM6 BT_LINEAR_WAVE_DRAG. Default .false. => bit-identical. Composes multiplicatively with substep_drag inside bt_rem_u/v.

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

Reserved for PR-14 (MOM6 BT_WAVE_DRAG_FILE); unused today.

character(len=32), public :: wave_drag_form = "uniform"

r_H filler: “uniform” (global scalar), “roughness_proxy” (resolved-bathymetry-variance proxy for Jayne & St Laurent <h^2>), or “file” (reserved for PR-14’s NetCDF map reader — fail-loud not-implemented today).

real(kind=wp), public :: wave_drag_h2_max = 2.5e4_wp

Ceiling on the resolved-bathymetry <h^2> proxy (m^2; ⇔ h_rms <= 158 m) for wave_drag_form = "roughness_proxy".

real(kind=wp), public :: wave_drag_kappa = 6.2832e-4_wp

Topographic wavenumber kappa (1/m) for wave_drag_form = "roughness_proxy". Same default as &ocean_tidal_mixing_nml kappa_itides — keep them equal.

real(kind=wp), public :: wave_drag_n_bot = 1.0e-3_wp

Reference near-bottom buoyancy frequency N_bot (1/s) for wave_drag_form = "roughness_proxy".

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

Piston velocity r_H (m/s) for wave_drag_form = "uniform".

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

Global tuning multiplier on r_H (MOM6 BT_WAVE_DRAG_SCALE).

character(len=64), public :: wave_drag_var = "rH"

Reserved for PR-14 (MOM6 BT_WAVE_DRAG_VAR); unused today.

type, public ::  ocean_cavity_dyn_config_t

Static ice-shelf cavity GEOMETRY (&ocean_cavity_dyn_nml, Phase 5.1). A prescribed, time-constant ice draft z_draft(i,j) (m, positive DOWN — the depth of the ice base below z = 0) is laid over the bed and absorbed into the barotropic DATUM:

Read more…

Components

Type Visibility Attributes Name Initial
character(len=32), public :: draft_config = "none"

Analytic draft shape. "none" (default): z_draft = 0 everywhere — the identity, even with enable = .true.. "flat": uniform draft_depth inside the shelf box [draft_x0, draft_x1] x [draft_y0, draft_y1], 0 outside (the open ocean beyond the calving front at draft_x1). "linear": z_draft = draft_depth + draft_slope*(x - draft_x0) inside the same box, clipped at 0 below. "file": a static 2-D NetCDF draft — NOT implemented (fails loud); the MPI-correct static-2-D reader is a later slice, and it is the only route to an ISOMIP+ draft, which has no analytic form (Asay-Davis et al. 2016 §3.1.1).

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

Draft amplitude (m, positive down) — the uniform value for "flat", the value at draft_x0 for "linear". Under draft_source = "thickness" it is an ice THICKNESS instead.

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

draft_config="file": path to the NetCDF carrying the static ice draft. The variable named by draft_var must be rank 3 in FORTRAN storage order (x, y, t) — which is how a C or Python writer (and ncdump) spells (nTime, ny, nx) — with a time coordinate variable; RECORD 1 is read and the field is never re-read. There is NO horizontal interpolation: the file must already be on the model grid (nx x ny physical cells), exactly as bathymetry_file and &ocean_zinit_nml file require. Single rank only (fail-loud otherwise).

character(len=16), public :: draft_sign = "depth"

draft_config="file": the SIGN CONVENTION of the file values. There is no default that guesses from the data — the two conventions differ by the whole ice load, and a field that is partly open water (zeros) is indistinguishable by inspection.

Read more…
real(kind=wp), public :: draft_slope = 0.0_wp

"linear" only: d(draft)/dx, dimensionless (m of draft per m of x). Positive deepens the ice base toward +x. Converted from metres to GRID units at the dispatch (metres on a Cartesian grid, degrees on spherical/curvilinear), the same way &ocean_topo_nml slope_scale is.

character(len=32), public :: draft_source = "draft"

What the draft is prescribed FROM. "draft" (default): the geometry above IS the ice-base depth. "thickness": the formula gives an ice THICKNESS, converted by the Boussinesq-isostatic (flotation) relation z_draft = rho_ice*h_ice/rho_0. "in_situ" (true isostasy, p_ice = g*integral(rho_hat)) needs a per-column root find, does not admit exact discrete rest, and is deliberately NOT implemented (fails loud).

character(len=64), public :: draft_var = "iceDraft"

draft_config="file": name of the 2-D variable to read. The default is the ISOMIP+ geometry file’s own spelling (Asay-Davis et al. 2016 Sect. 3.3).

real(kind=wp), public :: draft_x0 = -1.0e30_wp

Western edge of the shelf box (m, GLOBAL physical coordinate), and the ANCHOR of the "linear" profile (draft_depth is the draft AT draft_x0), which is why "linear" requires a finite value here. The default +/-1e30 on all four bounds is the “no limit on this side” sentinel: the shelf then covers the whole domain INCLUDING the ghost band, which is what a shelf that reaches a wall needs (a box stopping at x = 0 puts a phantom calving front one cell outside the west wall).

real(kind=wp), public :: draft_x1 = 1.0e30_wp

Eastern edge of the shelf box = the CALVING FRONT (m): beyond it the draft is 0 (open ocean). Default: no eastern limit.

real(kind=wp), public :: draft_y0 = -1.0e30_wp

Southern edge of the shelf box (m). Default: no limit.

real(kind=wp), public :: draft_y1 = 1.0e30_wp

Northern edge of the shelf box (m). Default: no limit.

logical, public :: enable = .false.

Master switch. Requires the ocean multilayer path, the split solver, &ocean_pgf_nml form="fv_mom6", vcoord_type in {sigma, zstar} and a single rank; mutually exclusive with wet/dry, porous barriers, sea ice, bt_halo > 0, tidal SAL and gfs_scale /= 1 (every one of those fails loud at configure, naming the knob and the reason).

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

Sanity bound: if more than this fraction of the interior columns ground, configure fails loud rather than silently running a domain that is mostly land.

real(kind=wp), public :: h_min_cavity = 10.0_wp

GROUNDING cutoff (m): a column whose water thickness b - z_draft is below this is LAND — it goes through the same seed_wet_mask_impl the bathymetry uses, so the static metric-zeroing land mask and the finite land-state hold for free. Never a thin film of water under grounded ice. ISOMIP+ §3.1.5 leaves the choice to the modeller and notes ~40 m (two cells) for z-level models; sigma is less restricted, hence 10 m.

real(kind=wp), public :: rho_ice = 918.0_wp

Ice density (kg/m^3), consulted ONLY by draft_source = "thickness".

logical, public :: trim_ic_for_p_surf = .false.

Trim the INITIAL column under the ice so it is at rest (MOM6 TRIM_IC_FOR_P_SURF, trim_for_ice). The load p_ice_ref = rho_ref*g*z_draft is the displaced weight at the REFERENCE density; a stratified column’s displaced water weighs g*int_{-z_draft}^{0} rho dz, and the difference is a depth- uniform bottom-pressure gradient the MOM6 barotropic split (&ocean_bt_nml bc_pgf_forcing) adjusts to. With the knob on, the load is kept (the ice MASS is what is prescribed) and each loaded column’s initial top is moved to the depth s where g*int_{-s}^{0} rho dz = p_ice_ref, i.e. an initial eta = z_draft - s (a few cm under ISOMIP+ COLD), with T/S then evaluated at the trimmed layer centres. Closed form, exact at the discrete FV interfaces: requires &ocean_eos_nml eos="linear" and &ocean_zinit_nml enable, source="linear" (the analytic profile is what defines rho above the ice base); anything else fails loud. Default off => bit-identical.

type, public ::  ocean_cavity_melt_config_t

Ice-shelf basal-melt THERMODYNAMICS (&ocean_cavity_melt_nml, Phase 2b). The three-equation interface of Holland & Jenkins (1999), solved once per thermo step on every ice-covered column and delivered to the ocean as two OWNED surface-flux components (heat_cavity, salt_cavity).

Read more…

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: cdrag_top = 2.5e-3_wp

Top drag coefficient C_D,top entering the MELT friction velocity u*^2 = C_D (U^2 + u_tide^2). ISOMIP+ Table 4 p. 2483. The least constrained number in the subject: the literature spans 1.5e-3 (Holland & Jenkins 1999 Table 1) to 9.7e-3 (Jenkins et al. 2010 Table 2). This knob does not yet drive any momentum drag — top drag is Phase 4; here it only scales u* for the exchange velocities.

logical, public :: enable = .false.

Master switch. Requires &ocean_cavity_dyn_nml enable, &ocean_eos_nml tfreeze_set="isomip" and &ocean_forcing_nml enable_components; mutually exclusive with atmospheric surface forcing (wind stress, surface restoring, shortwave penetration, the uniform scalar q_heat/q_salt) until the per-cell cover mask lands, and with sea ice. Every one of those fails loud at configure, naming the knob and the follow-up. &ocean_psurf_nml composes freely: the liquidus reads the ASSEMBLED ms%p_top = p_ice_ref + sf%p_surf, so an atmospheric load under the shelf depresses the freezing point with no extra wiring.

character(len=32), public :: exchange_law = "const_gamma"

Turbulent exchange-velocity law. "const_gamma" (default) is gamma = Gamma*u* — Jenkins, Nicholls & Corr (2010) eqs. (1),(2),(5) p. 2300 and the ISOMIP+ form. "hj99" is Holland & Jenkins (1999) eqs. (14)-(18) p. 1792 (needs a non-zero Coriolis parameter under the cover). "yung25" is Yung et al. (2025) “StratFeedback” eqs. (7)-(8) p. 5832. Every other name the kernel’s enum reserves (jenkins91, rosevear22, vt19, mk18, burchard22, jenkins21) PARSES but is refused at configure naming CAVITY_MELT_NOT_IMPLEMENTED — a reserved law and a typo must stay distinguishable.

real(kind=wp), public :: far_field_depth = 10.0_wp

Thickness (m) below the ice base over which the far-field (T, S, u, v) are thickness-averaged, with a partial last layer. Metres, deliberately, never “layer nz”. The melt rate is roughly linear in the thermal driving it is handed, and how far from the ice that was sampled is the dominant resolution artefact in the subject (Gwyther et al. 2020; Burchard et al. (2022) Table 2 p. 15 — the all-bulk error GROWS under refinement; Yung et al. (2026) p. 2074). No protocol prescribes a value; 10 m is this repository’s default and it must be held FIXED across any vertical-coordinate comparison, or the comparison measures the sampling depth instead.

character(len=16), public :: freshwater = "virtual"

How the meltwater reaches the ocean.

Read more…
real(kind=wp), public :: gamma_s = -1.0_wp

Dimensionless salt-transfer coefficient Gamma_S. Negative = unset ⇒ resolved to gamma_t/35, the ISOMIP+ ratio (Asay-Davis et al. (2016) Table 4 p. 2483, after Jenkins, Nicholls & Corr (2010) p. 2309: the ratio “should lie somewhere in the range 35-70. Adopting a value at the lower end of this range…”). Zero and positive values are taken literally, so gamma_s = 0 is refused as a range error rather than silently re-triggering the default.

real(kind=wp), public :: gamma_t = 2.2e-2_wp

Dimensionless heat-transfer coefficient Gamma_T of gamma_t = Gamma_T*u*. ISOMIP+ starting guess, Asay-Davis et al. (2016) §3.2.1 p. 2487 — a starting guess, not a constant of nature: the protocol has participants tune it, and Yung et al. (2026) Table 2 p. 2058 shows the twelve submissions spanning 0.011 to 0.2. Re-derive it per vertical coordinate; a single value across a coordinate sweep makes the sweep measure its own tuning.

character(len=32), public :: ice_conduction = "insulating"

Ice-side heat conduction. "insulating" (default) is q_ice = 0, which the ISOMIP+ protocol PRESCRIBES (Asay-Davis et al. (2016) Table 4 p. 2483 sets kappa_i = 0 and p. 2485 instructs participants not to use the H&J99 advection-diffusion scheme); t_ice is then unread. "adv_diff" is Holland & Jenkins (1999) eq. (31) p. 1794 in its melting asymptote, which collapses to q_ice = m_mass*c_i*(T_b - T_ice) and is zero on freezing. "diffusive" is RESERVED and refused: it changes the melt/freeze BRANCH logic, not just a coefficient.

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

Ice salinity (g/kg), >= 0. Zero is the ISOMIP+ value (Asay-Davis et al. (2016) Table 4 p. 2483). It must stay strictly below the far-field salinity — that inequality is what the three-equation root bracketing rests on — and a column violating it is COUNTED and given zero melt, not guessed at.

real(kind=wp), public :: t_ice = -25.0_wp

Ice interior temperature (degC), read by ice_conduction="adv_diff" only — Holland & Jenkins (1999) Table 1 p. 1790 uses T_S ~ -25. Under "insulating" the kernel substitutes exactly zero, so a stale value here cannot leak into an insulating run.

real(kind=wp), public :: u_tide = 1.0e-2_wp

RMS tidal velocity (m/s) in the melt friction velocity — ISOMIP+ Table 4 p. 2483 and eq. (27) p. 2485, after Jenkins, Nicholls & Corr (2010) eq. (10) p. 2309. TRAP, and the protocol says it outright (p. 2486): “The computation of top and bottom drag do not incorporate utidal” — it belongs to the melt u* ONLY.

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

Friction-velocity floor (m/s) — Yung et al. (2025) eq. (14) p. 5836, value from their Table 2 p. 5838. It exists because “a friction velocity of zero (perhaps created by initialising the model at rest) will result in identically zero melt … which would be inconsistent with the presence of heat available for melting”.

character(len=32), public :: volume_compensation = "none"

What to do with the volume freshwater="mass" adds to a CLOSED domain. Requires freshwater="mass".

Read more…

type, public ::  ocean_config_t

All ocean-path knobs, nested by concern. Parallel to the state composition pattern (ocean_state%dyn, %vcoord, etc.). Read-side: see the per-sub-nml blocks in read_config. Call-side: cfg%ocean%bt%use_cont_type, cfg%ocean%pgf%form, etc.

Components

Type Visibility Attributes Name Initial
type(ocean_bc_config_t), public :: bc

Open-boundary condition config (&ocean_bc_nml). All defaults = wall — existing nmls without this block are bit-identical to prior behaviour.

type(ocean_bdrag_config_t), public :: bdrag
type(ocean_bt_config_t), public :: bt
type(ocean_cavity_dyn_config_t), public :: cavity_dyn

Static ice-shelf cavity geometry (&ocean_cavity_dyn_nml). Default-OFF ⇒ bit-identical.

type(ocean_cavity_melt_config_t), public :: cavity_melt

Ice-shelf basal-melt thermodynamics (&ocean_cavity_melt_nml). Default-OFF ⇒ bit-identical.

type(ocean_continuity_config_t), public :: continuity
type(ocean_conv_config_t), public :: conv
type(ocean_coriolis_config_t), public :: coriolis
type(ocean_data_config_t), public :: data

Shared time-varying NetCDF input reader (&ocean_data_nml, PR-14). Two knobs only — see ocean_data_config_t.

type(ocean_dataovr_config_t), public :: dataovr

File-backed surface forcing (&ocean_dataovr_nml, PR-15) — the first production consumer of data. Default-OFF ⇒ bit-identical.

type(ocean_ddiff_config_t), public :: ddiff
type(ocean_debug_config_t), public :: debug

Forensic probes (&ocean_debug_nml). Default all-off ⇒ bit-identical.

type(ocean_diag_config_t), public :: diag
type(ocean_eos_config_t), public :: eos
type(ocean_epbl_config_t), public :: epbl
type(ocean_forcing_config_t), public :: forcing

Surface-flux component-set gate (&ocean_forcing_nml, PR-12). Default off ⇒ byte-identical.

type(ocean_foxkemper_config_t), public :: foxkemper
type(ocean_geothermal_config_t), public :: geothermal
type(ocean_gm_config_t), public :: gm
type(ocean_grid_config_t), public :: grid
type(ocean_hdiff_config_t), public :: hdiff

Along-coordinate tracer Laplacian (&ocean_hdiff_nml). Default kappa_h = 0.0 ⇒ bit-identical.

type(ocean_hvisc_config_t), public :: hvisc
type(ocean_ic_config_t), public :: ic
type(ocean_ice_config_t), public :: ice

Sea-ice slot config (&ocean_ice_nml). Default off ⇒ byte-identical (PR 0 scaffold).

type(ocean_ice_ic_config_t), public :: ice_ic

Sea-ice initial-condition config (&ocean_ice_ic_nml, PR 24). Default conc_config="zero" ⇒ byte-identical.

type(ocean_isopycnal_config_t), public :: isopycnal

Lagrangian grounding-stability controls (&ocean_isopycnal_nml). Default-OFF ⇒ bit-identical.

type(ocean_kappa_shear_config_t), public :: kshear
type(ocean_meke_config_t), public :: meke
type(ocean_mpi_config_t), public :: mpi

Multi-rank MPI debug / tuning controls (&ocean_mpi_nml). Default off ⇒ bit-identical.

type(ocean_pgf_config_t), public :: pgf
type(ocean_porous_config_t), public :: porous
type(ocean_psurf_config_t), public :: psurf
type(ocean_redi_config_t), public :: redi
type(ocean_restore_config_t), public :: restore
type(ocean_slopes_config_t), public :: slopes
type(ocean_sponge_config_t), public :: sponge
type(ocean_tdrag_config_t), public :: tdrag

Ice-shelf TOP drag (&ocean_tdrag_nml). Default off ⇒ bit-identical.

type(ocean_thermo_config_t), public :: thermo
type(ocean_tidal_mixing_config_t), public :: tidal_mixing
type(ocean_tides_config_t), public :: tides
type(ocean_topo_config_t), public :: topo
type(ocean_tracers_config_t), public :: tracers
type(ocean_varmix_config_t), public :: varmix
type(ocean_vdiff_config_t), public :: vdiff
type(ocean_vmix_config_t), public :: vmix
type(ocean_wave_speed_config_t), public :: wavespeed
type(ocean_wetdry_config_t), public :: wetdry

Dynamic wetting/drying (&ocean_wetdry_nml). Default off ⇒ byte-identical.

type(ocean_zinit_config_t), public :: zinit

type, public ::  ocean_continuity_config_t

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: h_min = 1.0e-6_wp

Floor used by the PPM positivity limiter (MOM6 GV%Angstrom_H). When ppm_limit_pos = .true. and a cell’s centred thickness is at or below this floor, the PPM face reconstruction is forced to a constant (= upwind for that cell); above the floor the parabola’s interior minimum is forced to h_min if it would dip below. Default 1e-6 m preserves “pure positivity” semantics. MOM6 typically uses 1–4 m (≈ 2·Angstrom_H). No-op when ppm_limit_pos = .false..

logical, public :: positive_definite = .false.

Positive-definite continuity (MOM6-prevention + Roundabout-conservation). When .true. the split layer continuity guarantees every layer stays >= h_lim after each direction pass — the PPM reconstruction edges are floored at 2·h_lim (P1, MOM6’s positive-definite PPM) and (P2, later) the per-donor outfluxes are scaled down (never thickness-inflated ⇒ zero mass created). h_lim is derived at setup: angstrom_h on VCOORD_LAGRANGIAN, else 0 (⇒ the floor is inert on non-Lagrangian coords). Default .false. ⇒ untaken branches only ⇒ bit-identical. Fail-loud composed with &ocean_wetdry_nml enable (that module owns its own barotropic limiter; composition deferred).

logical, public :: ppm_limit_pos = .false.

MOM6 PPM_limit_pos analogue. When .true., the PPM face-thickness reconstruction in continuity adds a positivity-preserving limiter that prevents the parabola from dipping below h_min inside a cell. At thin / vanishing layers (shelf-break, seamount, wet/dry boundary) the reconstruction collapses to a constant — equivalent to upwind for that cell. Bounds mass flux through near-vanishing layers by the actual layer thickness.

logical, public :: renorm_consistent_flux = .true.

Continuous flux model in the uhbt/vhbt Newton renormalisation (see continuity_t%renorm_consistent_flux): a layer whose upwind donor flips under the barotropic correction carries (u0 + du)·h_face(new donor) instead of the historical flux0 + du·h_face(new donor), which jumps by u0·(h_new − h_old) at the flip and leaves the solve with no root when uhbt falls in the gap — a wrong-sign layer transport, an O(η) mismatch between the layer and barotropic free surfaces at every thickness jump (a sigma layer over a bathymetric step), and an exponentially pumped barotropic grid-scale mode under pred_corr (finding B of the vertical-coordinate stability matrix). Newton is bracketed by bisection (MOM6 zonal_flux_adjust). Default .true. (MOM6 behaviour, maintainer decision 2026-09-22); it is bit-identical to the historical model on every face where no donor flips. .false. restores the historical discontinuous model. Ignored by the wet/dry single-step form.

logical, public :: vol_cfl = .false.

MOM6 vol_CFL analogue. When .false. (default) the continuity-PPM face thickness is the downwind PPM EDGE value (the CFL→0 limit), bit-identical to the pre-knob behaviour. When .true. the donor-side face thickness is the swept-volume integral of the reconstructed parabola (adds the missing O(CFL) term). Fixes the dt-sensitive near-bed mass residual at steep shelf breaks.

type, public ::  ocean_conv_config_t

Brunt-Vaisala-triggered convective adjustment (&ocean_conv_nml, CVMix_conv-style). Where the interior N^2 < n2_thresh (dense-over-light), raises kt -> max(kt, kd_conv) and kv -> max(kv, prandtl_conv*kd_conv), strictly below the active surface boundary layer (KPP/EPBL own that). An INTERIOR closure CONTRIBUTOR – it does not clip/floor on its own; it feeds vmix_assemble. enable = .false. keeps the existing path bit-identical. Knob table: docs/generated_nml_knobs.md.

Components

Type Visibility Attributes Name Initial
logical, public :: enable = .false.

Master switch. Requires vmix%use_closure + thermo%enable_thermodynamics (validated at configure).

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

Convective tracer diffusivity (MOM6 KD_CONV), m^2/s.

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

Trigger threshold on N^2 (MOM6 BV_SQR_CONV), s^-2.

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

Kv_conv = prandtl_conv * kd_conv (MOM6 PRANDTL_CONV), nondim.

type, public ::  ocean_coriolis_config_t

&ocean_coriolis_nml.

Components

Type Visibility Attributes Name Initial
logical, public :: bound_coriolis = .false.

MOM6 BOUND_CORIOLIS: clamp the energy-scheme Coriolis acceleration into the range of the four neighbouring VELOCITY-form estimates (f+ζ)·v BEFORE the KE-gradient subtraction. Kills the thin-layer PV blow-up: q=(f+ζ)/h_corner is huge at a vanishing edge and q·vh can inject an acceleration the local velocity field cannot support; the (f+ζ)·v bound caps it. Energy scheme only (form="sadourny_energy", fail-loud otherwise) — MOM6’s double-gyre control run enables it. Default .false. ⇒ untaken branch ⇒ bit-identical.

character(len=16), public :: corner_h = "cell_mean"

PV corner-thickness construction for the energy scheme. "cell_mean" (default, bit-identical) — Roundabout’s wet-area-weighted 4-cell mean h_corner = Σ(wet·area·h)/Σ(wet·area), floored at H_MIN_PV. "mom6_area" — MOM6’s exact form: q = abs_vort·Area_q/(hArea_q + vol_neglect) with hArea_q = Σ(mask·area·h), Area_q = Σ(mask·area). The two are algebraically IDENTICAL above the floor (same numerator + denominator); they differ ONLY in the vanishing-thickness guard — Roundabout CAPS q at abs_vort/H_MIN_PV, MOM6’s vol_neglect is pure 1/0 armor (no cap), so at sub-H_MIN_PV corners MOM6’s q is LARGER. For realistic layers (h ≳ 1e-12) the knob is a round-off no-op. Energy scheme only (fail-loud otherwise).

character(len=16), public :: form = "sadourny"

Coriolis-advection variant: “sadourny” (default, enstrophy form), “sadourny_energy” (energy-conserving transport form q·vh), “sadourny_hk” (Hollingsworth-Källén).

character(len=16), public :: pv_adv_scheme = "centered"

PV face-interpolation scheme, orthogonal to form (Sadourny path only): “centered” (default, 2-point corner average ⇒ bit-identical) or “weno3”/”weno5”/”weno7” — upwind-biased WENO-Z reconstruction of the corner absolute vorticity onto the velocity faces (MOM6 WENOVI{3,5,7}TH), sharpening submesoscale PV fronts without the centred form’s global dissipation. weno5/weno7 (radius-3/4 stencils) require nghost >= 3/4 (fail-loud otherwise).

logical, public :: use_state_fluxes = .false.

MOM6 mass-consistent CorAdCalc: the mom6 corrector’s Coriolis-adv consumes the predictor continuity’s renormalised transports (ms%mass_flux_*_layer — the uh/vh from the same solve that produced u_av) instead of recomputing u·h_face from the evaluation-state prognostics. Requires form="sadourny_energy" + &ocean_bt_nml split_scheme="pred_corr" (fail-loud). Default .false. = bit-identical.

type, public ::  ocean_data_config_t

&ocean_data_nml: the shared time-varying NetCDF input reader (rdb_ocean_data_input, PR-14). Deliberately two knobs — this group carries NO per-field entries. Registration is programmatic: each consumer (surface forcing, OBC segments, sponge targets, tidal-mixing maps, …) calls ocean_data_input_register_2d/_3d from its OWN namelist group at setup and gets back an opaque id. A field never appears here. Zero registered fields on every shipped namelist today ⇒ ocean_data_input_update_all is a no-op ⇒ bit-identical.

Components

Type Visibility Attributes Name Initial
integer, public :: max_fields = 16

Size of the reader’s field registry. A registration beyond this is a fail-loud abort (max_fields >= 1 is enforced by the schema min=1).

logical, public :: verbose = .false.

Log every bracket advance (field, record pair, weight, model time) via logger%info. Default off — quiet per-step path.

type, public ::  ocean_dataovr_config_t

&ocean_dataovr_nml: file-backed surface forcing (PR-15, the A3 keystone consumer). Binds time-varying NetCDF fields, through the shared PR-14 reader (&ocean_data_nml), onto the surface stress and surface-flux slots. enable = .false. registers nothing ⇒ ocean_data_input_update_all stays a no-op ⇒ bit-identical.

Read more…

Components

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

Climatology period (s). Required > 0 when time_mode = "cyclic"; ignored otherwise.

logical, public :: enable = .false.

Master switch. Default off ⇒ no registration, bit-identical. Requires RDB_ENABLE_NETCDF=ON at build time.

type(dataovr_entry_config_t), public :: evap

Evaporative mass flux (kg/m^2/s, <= 0) -> surface_flux%evap.

type(dataovr_entry_config_t), public :: heat

Net surface heat flux (W/m^2, positive down) -> surface_flux%heat_added.

type(dataovr_entry_config_t), public :: lprec

Liquid precipitation (kg/m^2/s, >= 0) -> surface_flux%lprec.

logical, public :: oor_clamp = .false.

.true. clamps a query outside the file time axis to the end record (one warning); default .false. aborts.

type(dataovr_entry_config_t), public :: salt

Surface salt flux (kg salt/m^2/s, positive salinifies) -> surface_flux%salt_flux.

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

Added to the model time before the file-axis lookup (s) — shifts the model epoch onto the file’s epoch.

type(dataovr_entry_config_t), public :: tau_x

Zonal wind stress (Pa) -> surface_stress%tau_x (east faces).

type(dataovr_entry_config_t), public :: tau_y

Meridional wind stress (Pa) -> surface_stress%tau_y (north faces).

character(len=16), public :: time_mode = "linear"

Shared time-axis mode for every active tag: linear (interannual; out-of-range is an abort unless oor_clamp), cyclic (climatology wrapped through cycle_period), or static (record 1, read once). Per-tag overrides are a documented v2 gap, not an oversight.

type, public ::  ocean_diag_config_t

Components

Type Visibility Attributes Name Initial
character(len=16), public :: diag_remap_scheme = "ppm"

In-cell reconstruction for the conservative diagnostic vertical remap (z_fixed / density vgrids): “pcm”, “plm”, “ppm” (default), “ppm_h4”, or “pqm”. All conserve the column integral; PPM is the accurate default (PCM stair-steps). Inert when every diagnostic is on the native “layer” grid.

character(len=512), public :: diags = ""

Unified diagnostic selection list — one authoritative spec that modifies the canonical default set. Whitespace/comma-separated entries, each name[:attr]... with self-identifying colon attributes (order-free):

Read more…
real(kind=wp), public :: dt_out = 3600.0_wp

Cadence (s) at which the diag manager fires every variable’s time op (INSTANT writes, MEAN flushes the accumulator, etc.).

logical, public :: enabled = .true.

Enable per-step diag-manager hook in driver_run_ocean.

character(len=256), public :: filename = "ocean_diag"

Output file basename — output_rank_filename appends the per-rank suffix. Final path: <output_dir>/<filename>_rank_NNNNNN.nc.

logical, public :: mask_vanished_layers = .false.

When .true., remapped (non-layer) diagnostics fill target cells that overlap no water (below-bottom / pinched-out in a shallow column) with a missing sentinel and tag the NetCDF variable with _FillValue / missing_value. Default .false. => those cells read 0 (bit-identical to the legacy writer).

integer, public :: n_rho_levels = 0

Number of entries used in rho_levels (0 = none).

integer, public :: n_sigma_levels = 0

Number of entries used in sigma_levels (0 = auto-uniform).

integer, public :: n_z_levels = 0

Number of entries used in z_levels (0 = none).

integer, public :: n_zstar_levels = 0

Number of entries used in zstar_levels (0 = auto-uniform).

character(len=16), public :: output_precision = "double"

Element width of the DIAGNOSTIC NetCDF data variables: “double” (default => byte-identical to the pre-knob writer) or “single” (fp32 => ~half the bytes per frame; diagnostic output is write-bandwidth bound, so this is the main lever on its cost). fp32 carries ~7 decimal digits — ~1e-5 degC, ~1e-5 PSU, ~1e-9 m/s at 1 m/s — orders of magnitude below the model’s own discretisation error.

Read more…
logical, public :: reproducing_sums = .true.

console-conservation totals (Mass/KE/Salt/Heat + sea-ice area) and the salt/heat closed-budget out/src terms use order-invariant extended-fixed-point (EFP) summation (rdb_efp + halo_allreduce_efp_list) instead of plain FP !$acc parallel loop reduction(+:acc) + MPI_SUM — the printed console is identical on every rank count (1 included) and reduction order, and the Error residual is formed via efp_real_diff (a fixed-point difference) rather than a double subtraction of two already-quantised totals. It runs only at the status cadence and changes diagnostic TEXT only, never the trajectory. .false. restores the pre-PR-32 FP console (whose last digits depend on the decomposition). See docs/CAPABILITIES_AND_LIMITATIONS.md’s conservation-contract section for the achievable guarantee + the EFP_MAX_RANKS = 131072 envelope.

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

Output target potential-density bin edges (kg/m^3, strictly increasing, light->dense) when vgrid = “density”. No auto-fill — validate_config requires n_rho_levels > 0 whenever the density vgrid is selected (globally or per-diagnostic).

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

Output sigma levels — cumulative fractions (0..1, shallow->deep) when sigma output is used. Empty => auto-generate nz_ml uniform fractions.

character(len=16), public :: vgrid = "layer"

Default output vertical grid for layer-shaped diags: “layer” (native nz_ml layers, default), “z_fixed” (conservative remap to z_levels), “sigma” (terrain-following, sigma_levels), “zstar” (SSH-tracking, zstar_levels), or “density” (isopycnal bins, rho_levels — requires n_rho_levels > 0, strictly increasing). Per-diagnostic overrides via the diags list :layer/z/sigma/zstar/density attribute.

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

Output z-levels (m, positive downward) when vgrid = “z_fixed”.

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

Output z reference interface depths (m, positive-down, shallow->deep; deepest = H_ref) when z output is used. Empty => auto-generate nz_ml uniform depths (== sigma; supply a non-uniform reference for z* to differ).

type, public ::  ocean_eos_config_t

Components

Type Visibility Attributes Name Initial
character(len=16), public :: eos = "linear"

Equation-of-state variant: “linear” (default, two-tracer), “wright” (Wright 1997 rational), “roquet_spv” (Roquet et al. 2015 specific-volume polynomial). “roquet_spv” is incompatible with the “fv_wright” PGF (fails loud at configure). “teos10” parses but is refused at configure (not implemented; Roquet SpV IS the 75-term TEOS-10 polynomial fit).

Read more…
real(kind=wp), public :: p_ref = 0.0_wp

Reference pressure (Pa, >= 0) at which the model’s POTENTIAL density ms%rho_layer is evaluated. Default 0 (surface density, σ₀) ⇒ bit-identical to every run before this knob existed. Read by the “wright” and “roquet_spv” variants; “linear” has no pressure dependence and ignores it.

Read more…
character(len=16), public :: tfreeze_set = "seaice"

Named seawater freezing-point (liquidus) coefficient set for eos_freezing_point, which evaluates the linear form

Read more…

type, public ::  ocean_epbl_config_t

Energetics-based planetary boundary layer (&ocean_epbl_nml). All defaults preserve bit-identity: enable = .false. keeps the existing PP81 + KPP path untouched. Knob table + MOM6 name mapping: docs/generated_nml_knobs.md.

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: c_ek = 0.085_wp

OM4 Ekman coefficient (MOM6 MSTAR2_COEF2).

character(len=8), public :: combine = "add"

“add” / “max” vs the interior closure’s kv/kt (MOM6 EPBL_IS_ADDITIVE).

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

Rotational mixing-length rolloff (MOM6 EKMAN_SCALE_COEF).

logical, public :: enable = .false.

Master switch. Requires vmix%use_closure; replaces the KPP overlay (configure logs the override).

real(kind=wp), public :: la_frac_hbl = 0.04_wp

Stokes SL-average depth fraction (MOM6 LA_DEPTH_RATIO).

real(kind=wp), public :: lt_enhance_coef = 0.447_wp

Enhancement coefficient (MOM6 LT_ENHANCE_COEF).

real(kind=wp), public :: lt_enhance_exp = -1.33_wp

Langmuir-number exponent (MOM6 LT_ENHANCE_EXP).

real(kind=wp), public :: lt_lac1 = -0.87_wp
real(kind=wp), public :: lt_lac2 = 0.0_wp
real(kind=wp), public :: lt_lac3 = 0.0_wp
real(kind=wp), public :: lt_lac4 = 0.95_wp
real(kind=wp), public :: lt_lac5 = 0.95_wp

Stability-modified La coefficients (MOM6 LT_MOD_LAC1..5); set all to 0 for the unmodified La.

real(kind=wp), public :: lt_max_enhance = 5.0_wp

Cap on the multiplicative enhancement.

character(len=16), public :: lt_scheme = "rescale"

“rescale” (multiplicative) / “additive” (MOM6 EPBL_LANGMUIR_SCHEME).

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

Mixing-length floor, m (MOM6 EPBL_MIN_MIX_LEN).

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

Shape-function exponent (MOM6 MIX_LEN_EXPONENT).

logical, public :: mld_bisection = .false.

Bisection instead of false position (MOM6 EPBL_MLD_BISECTION).

logical, public :: mld_iteration = .true.

Self-consistent MLD root-find (MOM6 USE_MLD_ITERATION).

integer, public :: mld_max_its = 20

Max MLD iterations (MOM6 EPBL_MLD_MAX_ITS).

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

MLD convergence tolerance, m (MOM6 EPBL_MLD_TOLERANCE).

logical, public :: mld_use_prev_guess = .false.

Seed from the previous step’s MLD (MOM6 MLD_ITERATION_GUESS).

real(kind=wp), public :: mstar = 1.2_wp

Constant-scheme mstar (MOM6 MSTAR).

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

Cap for OM4/RH18; off when < 0 (MOM6 MSTAR_CAP).

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

OM4 stabilizing coefficient (MOM6 MSTAR2_COEF1).

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

Convective mstar reduction in [0,1] (MOM6 MSTAR_CONV_ADJ).

character(len=16), public :: mstar_scheme = "om4"

“constant” / “om4” / “rh18” (MOM6 EPBL_MSTAR_SCHEME).

real(kind=wp), public :: nstar = 0.2_wp

Convective PE -> TKE efficiency (MOM6 NSTAR).

real(kind=wp), public :: omega = 7.2921e-5_wp

Earth rotation rate, 1/s (MOM6 OMEGA).

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

Blend |f| with 2*Omega (MOM6 ML_OMEGA_FRAC).

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

Kv = prandtl*Kd into the momentum solve (MOM6 EPBL_PRANDTL).

real(kind=wp), public :: rh18_cn1 = 0.275_wp
real(kind=wp), public :: rh18_cn2 = 8.0_wp
real(kind=wp), public :: rh18_cn3 = -5.0_wp
real(kind=wp), public :: rh18_cs1 = 0.2_wp
real(kind=wp), public :: rh18_cs2 = 0.4_wp

RH18 mstar fits (MOM6 RH18_MSTAR_CN1..CS2).

real(kind=wp), public :: tke_decay = 2.5_wp

Ekman-depth / TKE-decay-scale ratio (MOM6 TKE_DECAY).

logical, public :: tke_diags = .false.

Compute the per-column TKE budget diagnostic terms.

real(kind=wp), public :: translay_scale = 0.1_wp

Transition-layer shape floor, must be in [0,1) when iterating (MOM6 EPBL_TRANSITION_SCALE).

logical, public :: use_lt = .false.

Langmuir-turbulence enhancement (LF17 wind-only path, no wave model needed). MOM6 EPBL_LT / USE_LA_LI2016.

character(len=16), public :: vel_scale_scheme = "cube_root"

“cube_root” / “rh18” (MOM6 EPBL_VEL_SCALE_SCHEME).

real(kind=wp), public :: von_karman = 0.41_wp

kappa in Kd = vstarkappamixlen (MOM6 VON_KARMAN_CONST).

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

Overall vstar multiplier (MOM6 EPBL_VEL_SCALE_FACTOR).

real(kind=wp), public :: vstar_surf_fac = 1.2_wp

RH18 mechanical surface vstar factor (MOM6 VSTAR_SURF_FAC).

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

Convective weight in the velocity scale (MOM6 WSTAR_USTAR_COEF).

type, public ::  ocean_foxkemper_config_t

&ocean_foxkemper_nml: Fox-Kemper mixed-layer-eddy restratification. Default off ⇒ bit-identical. Reads epbl%mld.

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: bodner_mstar = 0.5_wp

Bodner mechanical (u) weight in w’u’ = (mstar·u³+nstar·w*³)^{2/3}.

real(kind=wp), public :: bodner_nstar = 0.066_wp

Bodner convective (w*) weight in the same w’u’ estimate.

real(kind=wp), public :: ce = 0.0625_wp

FK08 coefficient Ce (0.06-0.08).

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

Bodner (2023) efficiency coefficient Cr (nondim). Default 0 (MOM6 default) ⇒ no Bodner transport until set (~0.02-0.08).

logical, public :: enable = .false.

Master switch (off => bit-identity).

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

|f| regularisation floor (1/s).

real(kind=wp), public :: min_wstar2 = 1.0e-24_wp

Floor on w’u’ (m²/s²) — pure 1/0 armour when u* and the surface buoyancy flux both vanish.

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

Running-mean MLD filter time-scale (s) used when the MLD is retreating. 0 (default) => filter off => instantaneous EPBL MLD (bit-identical). Positive damps step-to-step MLD swings.

logical, public :: resolution_taper = .false.

B2 res_fn double-counting hook (hard error if on without B2).

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

mu cubic-tail extension (smoother); default 0 = exact mu.

logical, public :: use_bodner = .false.

Bodner et al. (2023) frontogenesis-arrest MLE variant: replaces the Ce/|f| timescale with Cr·Δs·|f|·h/w'u', the frontal-arrest length set by boundary-layer turbulence. Overrides ce/ use_mom_mixrate. Default off ⇒ classic Fox-Kemper.

logical, public :: use_mom_mixrate = .false.

FK11 momentum-mixrate timescale vs bare Ce/|f|. Default off.

type, public ::  ocean_geothermal_config_t

&ocean_geothermal_nml: bottom-heat-flux knobs. Default OFF = bit-identical.

Components

Type Visibility Attributes Name Initial
logical, public :: enable = .false.

Master switch. Default .false..

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

Scalar constant bottom heat flux (W/m^2, positive up). Typical ~0.05-0.1.

type, public ::  ocean_gm_config_t

&ocean_gm_nml: Gent-McWilliams thickness diffusion — eddy-induced bolus transport folded into continuity. Reads the slopes slot. Default off ⇒ no bolus flux.

Components

Type Visibility Attributes Name Initial
logical, public :: enable = .false.

Master switch. Default off ⇒ gm_compute_transports no-ops. Requires &ocean_slopes_nml enable (configure-time error).

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

Thickness diffusivity KhTh, m^2/s (constant-fill for v1; production 1e2-1e3). 0 ⇒ no bolus transport even when enabled.

real(kind=wp), public :: khth_max_cfl = 0.1_wp

Fraction of the diffusive CFL the face KH may use.

real(kind=wp), public :: khth_slope_max = 0.01_wp

Slope magnitude above which the safe-streamfunction blend takes over (MOM6 slope_max).

type, public ::  ocean_grid_config_t

&ocean_grid_nml: horizontal-grid generator + geometry knobs.

Components

Type Visibility Attributes Name Initial
character(len=16), public :: axis_units = "meters"

Units of the Cartesian domain extent (grid_config="cartesian"), mirroring MOM6 AXIS_UNITS: “meters” (default), “degrees”, “km”. With “degrees”/”km” the domain is sized by len_lon/len_lat below and &grid_nml dx/dy are DERIVED (ignored as inputs). “meters” ⇒ &grid_nml dx/dy used verbatim (bit-identical).

character(len=16), public :: coriolis_scheme = "beta_plane"

Coriolis source for the metrics f-fill: “beta_plane” (default, f_0 + betay) or “planetary” (2omega*sin(geolat)).

character(len=16), public :: grid_config = "cartesian"

Grid generator: “cartesian” (default, uniform), “spherical” (lon-lat sector), “supergrid” (MOM6 mosaic NetCDF), “tripolar”.

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

South edge of the physical domain (degrees) — spherical only.

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

Total y-extent of the Cartesian domain in axis_units (MOM6 LENLAT). Paired with len_lon; > 0 ⇒ dy = to_metres(len_lat)/ny. NOTE: spherical cell sizes reuse &grid_nml dx/dy as dlon/dlat in DEGREES when grid_config="spherical".

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

Total x-extent of the Cartesian domain in axis_units (MOM6 LENLON). <= 0 (default) ⇒ unset. > 0 ⇒ a uniform dx = to_metres(len_lon)/nx is derived, where for “degrees” to_metres(v) = rad_earth·v·π/180 (arc length, no cos(lat) — MOM6 cartesian) and for “km” to_metres(v) = 1000·v.

real(kind=wp), public :: lon_pole = 100.0_wp

Longitude (degrees) of the first tripolar cap pole; partner at lon_pole + 180.

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

West edge of the physical domain (degrees) — spherical only.

real(kind=wp), public :: omega = 7.2921e-5_wp

Planetary rotation rate (rad/s) — used by “planetary”.

real(kind=wp), public :: phi_join = 65.0_wp

Join latitude (degrees) for “tripolar”: lon-lat below, bipolar Arctic cap above.

real(kind=wp), public :: rad_earth = 6.378e6_wp

Earth radius for the spherical metric (m).

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

Path to the MOM6 supergrid NetCDF — “supergrid” only.

type, public ::  ocean_hdiff_config_t

&ocean_hdiff_nml — along-coordinate tracer Laplacian (rdb_ocean_hdiff_tracer). Diffusion along the MODEL coordinate, not neutral surfaces (that is &ocean_redi_nml, a separate already-reachable capability).

Components

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

Constant horizontal tracer diffusivity (m^2/s). Zero (default) is a no-op — the kernel short-circuits without touching hTr, so this knob is bit-identical when unset. Stability bound (explicit forward-Euler), checked at configure using the coarsest dx/dy (Cartesian metres): kappa_h * dt_therm * (1/dx^2 + 1/dy^2) <= 0.5

type, public ::  ocean_hvisc_config_t

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: ah_bg = -1.0_wp

Background harmonic viscosity (m²/s) for the lateral closure. Negative (default) = derive from nu_h and kh_vel_scale.

real(kind=wp), public :: ah_max = 1.0e4_wp

Hard cap on the per-face harmonic viscosity (m²/s).

real(kind=wp), public :: aniso_dir(2) = [1.0_wp, 0.0_wp]

Anisotropy direction vector (n1,n2) in grid i,j components. Default (1,0) = grid-i. Normalised internally.

integer, public :: aniso_mode = 0

Anisotropy-direction mode. Only mode 0 (grid-relative (n1,n2) = aniso_dir) is implemented; other values rejected at configure (no silent fall-back).

real(kind=wp), public :: bound_coef = 0.8_wp

CFL safety coefficient for the per-cell viscosity limiters (harmonic when stress_tensor, biharmonic always when nu_4 > 0 or Smag_AH). Default 0.8; must be ≤ 1.

logical, public :: bound_kh = .false.

MOM6 BOUND_KH analogue for the velocity-Laplacian paths: per-face clamp of the harmonic viscosity to bound_coef·0.125/(dt·(1/dx²+1/dy²)) (~¼ of the forward- Euler stability limit). Prevents an over-large nu_h (or flow-aware coefficient) from putting the frozen depth-mean viscous forcing on the barotropic mode into the phase- reversed ANTI-damping regime at grid scale, which pumps an exponential rim-trapped barotropic mode via the split-RK2 Δu corrector (the 600² Lagrangian double-gyre blow-up). Recommended .true. for any config where nu·dt·(1/dx²+1/dy²) ≳ 0.1. Default .false. ⇒ bit-identical.

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

Dimensionless Leith coefficient. Typical range 1.0–2.0.

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

Nondimensional biharmonic Leith constant. Drives lateral_closure="leith_biharm" (per-face nu4_face = C_lb · grid_sp⁶ · inv_PI6 · |∇²ζ|, clamped to [nu_4_bg, nu_4_max]). Default 0.0 = no-op (startup warning if leith_biharm selected at 0.0).

real(kind=wp), public :: c_smag = 0.15_wp

Dimensionless Smagorinsky coefficient. Default 0.15 (range 0.1–0.2).

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

Anisotropic Laplacian viscosity magnitude (m²/s; Smith & McWilliams 2003). When positive AND stress_tensor = .true., adds direction-tensor terms aligned with aniso_dir. Default 0 ⇒ isotropic, bit-identical. Stress-tensor path only.

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

Velocity scale (m/s) for the grid-resolution viscosity floor nu_min = kh_vel_scale · dx. Typical 3e-3 m/s.

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

Live velocity-scale viscosity coefficient (m/s). When positive, a state-dependent A_vel = kh_vel_scale_live·dx·|u| is max-combined into the per-face harmonic viscosity every step. Default 0 ⇒ off, bit-identical.

character(len=16), public :: lateral_closure = "none"

Lateral-mixing closure tag. “none” (default) keeps the scalar nu_h. “leith” = Leith vorticity-gradient scaling; “smagorinsky”/”smag” = Smagorinsky strain-rate scaling. Either gives a per-face viscosity floored at ah_bg, capped at ah_max.

logical, public :: no_slip = .false.

Lateral coast BC (static land mask). .false. (default) = FREE-SLIP (corner vorticity/shear strain multiplied by wet_q); .true. = NO-SLIP (factor 2 - wet_q). All-wet ⇒ bit-identical.

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

Constant biharmonic eddy viscosity for momentum (m⁴/s). Default 0.

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

Background biharmonic viscosity floor (m⁴/s) for the flow-aware path.

real(kind=wp), public :: nu_4_max = 1.0e12_wp

Static hard cap on per-face biharmonic viscosity (m⁴/s). The forward-Euler biharmonic-CFL bound is enforced automatically per cell (scaled by bound_coef), so this is just an extra ceiling.

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

Constant horizontal eddy viscosity for momentum (m²/s). Default 0 = bit-identical; wind-driven runs need this set.

logical, public :: resoln_scaled_visc = .false.

Resolution-scaled Laplacian viscosity (Hallberg 2013). When .true. the dynamic Laplacian viscosity is multiplied by the VarMix resolution function Res_fn ∈ [0,1] before the ah_max clamp (biharmonic nu_4 never scaled). Requires &ocean_varmix_nml enable=.true.. Default .false. ⇒ bit-identical.

logical, public :: smag_ah = .false.

Smagorinsky biharmonic. When .true. the biharmonic viscosity becomes flow-aware nu4_face = C_b · L⁴ · |D|, clamped to [nu_4_bg, nu_4_max]; the scalar nu_4 is bypassed.

real(kind=wp), public :: smag_bi_const = 0.06_wp

Nondimensional biharmonic Smagorinsky constant. Typical 0.015–0.06.

logical, public :: stress_tensor = .false.

Horizontal-viscosity operator. .false. (default) = velocity-Laplacian A·∇²u with global caps, bit-identical. .true. = thickness-weighted stress-divergence form (momentum-conserving) with per-cell CFL limiter and coast masking; reduces to the Laplacian on uniform-grid/h/all-wet.

type, public ::  ocean_ic_config_t

Initial-condition overlay + EOS reference state. Drives the analytical configurations (eady-front, geostrophic- adjustment, …) plus the linear-EOS reference values that the rest of the ocean dyn step reads.

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: S_ref = 35.0_wp

Linear-EOS reference salinity (PSU) — the S at which the haline anomaly term vanishes.

real(kind=wp), public :: T_ref = 10.0_wp

Linear-EOS reference temperature (°C) — the T at which the thermal anomaly term vanishes.

real(kind=wp), public :: alpha_T = 1.7e-4_wp

Linear-EOS thermal-expansion coefficient, DIMENSIONAL (kg/m³ per °C) — see beta_S for the conversion from the fractional 1/°C coefficient most protocols quote.

real(kind=wp), public :: beta_S = 7.6e-4_wp

Linear-EOS haline contraction coefficient, DIMENSIONAL (kg/m³ per PSU).

Read more…
real(kind=wp), public :: eady_T_ref = 10.0_wp

Reference temperature (°C) for the Eady IC at z=0, y=y_mid.

real(kind=wp), public :: eady_dT_dy = -2.0e-5_wp

Meridional gradient of T (°C/m) for the Eady IC.

real(kind=wp), public :: eady_dT_dz = 0.01_wp

Vertical stratification (°C/m) for the Eady IC.

real(kind=wp), public :: eady_pert_amp = 1.0e-3_wp

Amplitude (°C) of the random temperature perturbation seeded into the Eady IC to break symmetry.

integer, public :: eady_pert_seed = 12345

RNG seed for the Eady IC perturbation.

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

Geostrophic-adjustment IC: amplitude (m) of the Gaussian SSH bump.

real(kind=wp), public :: ga_length_scale = 50000.0_wp

Geostrophic-adjustment IC: e-folding scale (m) of the Gaussian SSH bump.

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

x-coordinate (m) of the bump centre. Negative ⇒ auto (basin midpoint).

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

y-coordinate (m) of the bump centre. Negative ⇒ auto (basin midpoint).

character(len=32), public :: ic_config = ""

IC overlay tag. “” (default) keeps the analytical T(z) + zero-velocity IC. “eady” runs the Eady-front overlay; “geostrophic_adjustment” drops a Gaussian SSH bump on an f-plane; “baroclinic_jet” runs the two-layer reduced-gravity baroclinic-instability jet (SIM_DETAILS.md §5).

real(kind=wp), public :: interface_amp = 200.0_wp

Baroclinic-jet IC: interface displacement amplitude Δξ (m). Spec “tuned” default 200 m; faithful uses 100 m.

real(kind=wp), public :: jet_half_width = 40000.0_wp

Baroclinic-jet IC (ic_config="baroclinic_jet"): tanh jet half-width L (m). Spec “tuned” default 40 km; the Julia- faithful case uses 100 km. Read only for the baroclinic-jet IC.

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

Per-layer initial density (kg/m³), k=1 bed → k=nz surface, mirroring MOM6’s COORD_CONFIG="gprime" IC. Any positive value bypasses the EOS-derived init and writes the user-specified densities straight into ms%rho_layer at the end of ocean_state_seed_from_cfg. Count of non-sentinel (>= 0) entries must equal nz_layers. Default -1.0 sentinel ⇒ existing init path (bit-identical).

real(kind=wp), public :: pert_amp_frac = 0.2_wp

Baroclinic-jet IC: front-localised meander amplitude as a fraction of Δξ (A_pert = pert_amp_frac·Δξ). Spec default 0.2.

integer, public :: pert_nx = 3

Baroclinic-jet IC: zonal perturbation wavenumber (integer number of wavelengths across the periodic domain). Integer so the analytic x-continuation wraps exactly (k_x·L_x = 2π·pert_nx). Spec default 3.

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

Reference density (kg/m³) for the linear EOS and Boussinesq PGF — the density at (T_ref, S_ref).

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

Linear density-range IC — MOM6 COORD_CONFIG="linear" analogue. When >= 0, generates nz_layers linearly-spaced layer densities spanning [rho_lightest, rho_lightest + rho_range] and writes them into ms%rho_layer (bed k=1 heaviest → surface k=nz lightest), reusing the layer_rho_init write path — so the column scales by just bumping nz_layers, no hand-listed densities. Mutually exclusive with layer_rho_init. Default -1.0 sentinel ⇒ off (bit-identical).

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

Linear density-range IC: total top-to-bottom density contrast (kg/m³), MOM6 DENSITY_RANGE (default 2.0). Read only when rho_lightest >= 0.

real(kind=wp), public :: upper_layer_rest = 500.0_wp

Baroclinic-jet IC: rest thickness of the upper (surface, k=2) layer H₁ (m). The lower (bed, k=1) rest thickness is max_depth − upper_layer_rest. Spec §4 default 500 m (H₂ = 1500 m over the 2000 m column).

type, public ::  ocean_ice_config_t

&ocean_ice_nml: sea-ice model master switch + category/layer counts (SIS2 port, PLAN_SEA_ICE.md). PR 0 scaffold — the knobs size the gated ocean_sea_ice_t slot. PR 3c adds the v1 scalar restoring atmospheric-forcing filler (air_temp/restore_lambda/ sw_down) that drives the column live in the driver. Default OFF ⇒ byte-identical.

Components

Type Visibility Attributes Name Initial
logical, public :: a_face_stress = .false.

PR 62: weight the atmospheric stress AND the ice-ocean drag in the EVP momentum balance by the face ice concentration a_u = 0.5*(ci(i-1,j) + ci(i,j)) (same expression/edge convention as ice_ocean_stress_flux_impl’s a_u), giving the textbook m du/dt = grad.sigma + a*(tau_a - tau_w) (Hibler 1979 eq. 1) and an EXACTLY closing ice<->ocean momentum budget at every fractional cover, not just steady free drift. Both terms must be weighted together – weighting the wind alone converts today’s leak (zero at steady free drift) into a permanent one. Default off => byte-identical.

integer, public :: adv_substeps = 1

Advective sub-iterations per transport call (SIS2 NSTEPS_ADV, default 1). dt_adv = dt_therm / adv_substeps.

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

Prescribed slab-atmosphere air temperature (degC) for the v1 restoring atmospheric-forcing filler. SF(T) = restore_lambda*(T - air_temp).

real(kind=wp), public :: c0 = 20.0_wp

SIS2 ICE_STRENGTH_CSTAR — ice-strength exponent constant [nondim].

real(kind=wp), public :: cdw = 3.24e-3_wp

SIS2 ICE_CDRAG_WATER — ice-ocean drag coefficient [nondim].

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

SIS2 CFL_TRUNCATE (SIS2 default 0.5) — transport-CFL ceiling on the FINAL ice velocity the EVP call hands to transport: |u| <= 0.95*cfl_trunc*areaT(donor)/(dt_transport* dy_cu). 0 (Roundabout default, house bit-identity rule) disables the clip entirely => byte-identical. Recommended production value 0.5 (“instability can occur past 0.5”, SIS2).

logical, public :: cfl_trunc_dyn_its = .false.

SIS2 CFL_TRUNC_DYN_ITS (SIS2 default .false., matches). Also clip u_ice/v_ice to the EXACT (no 0.95 back-off, no count) bound at the bottom of every EVP subcycle, not just the final velocity. Requires cfl_trunc > 0.

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

SIS2 ICE_DEL_SH_MIN_SCALE — viscosity-floor scale [nondim].

logical, public :: dynamics = .false.

EVP rheology master switch (rdb_ice_evp%ice_evp_step). Default off => byte-identical (the transport sampler keeps filling u_ice/v_ice from the ocean surface layer).

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

SIS2 ICE_YIELD_ELLIPTICITY — yield-curve axis ratio [nondim]. 0 => cavitating-fluid rheology (str_t/str_s stay exactly 0).

logical, public :: enable = .false.

Master switch. Off (default) ⇒ the sea-ice slot is never initialised, mapped, or stepped ⇒ byte-identical.

integer, public :: evp_sub_steps = 432

SIS2 NSTEPS_DYN — EVP subcycles per slow (outer) step.

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

hardcoded SIS2 default table. -1.0 sentinel (all entries) = unset. Semantics when set: hlim(1..n) where n is the leading non-sentinel run, 2 <= n <= ncat+1, strictly increasing, hlim(1) > 0. Fills h_lim(1..min(ncat+1,n)); the remainder extrapolates by constant width, h_lim(k) = 2*h_lim(k-1) - h_lim(k-2). Unset => the hardcoded SIS2 default table, byte-identical (default-off house rule). See ice_hlim_count/ice_hlim_spec_is_valid.

integer, public :: ncat = 5

Number of ice thickness categories (category 0 = open water; SIS2 default 5).

integer, public :: nk_ice = 2

Vertical ice layers per category (2 = Winton two-layer, v1).

real(kind=wp), public :: p0 = 2.75e4_wp

SIS2 ICE_STRENGTH_PSTAR — ice-strength pressure constant [Pa].

logical, public :: project_ci = .false.

SIS2 PROJECT_ICE_CONCENTRATION (SIS2 default .true.). Project the ice concentration forward along the current divergence each subcycle (ci_proj = ci*exp(-t_cum*sh_dd)) and recompute pres_mice from it, stiffening the rheology under convergence (and weakening it under divergence) within the call. .false. (Roundabout default, house bit-identity rule) holds pres_mice at its pre-loop value for all subcycles => byte-identical.

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

Surface-flux restoring coefficient (W/m^2/K), i.e. dSF/dT of the linearized SEB. 0 (default) => a passive column (dsf_dt=0, sf_0=0): no thermostat, so no restoring drive. A production melt season uses ~20. NOTE: with restore_lambda=0 the seam fields are (0,0,sw_down) => the column feels only shortwave + basal flux.

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

SIS2 RHO_OCEAN — ice-drag reference density [kg/m^3]. Deliberately independent of the ocean’s rho0 (usually 1035).

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

SIS2 SEA_ICE_ROLL_FACTOR — thin-ice rolling floor in cell_ave_state_to_ice_state. 0 disables rolling.

logical, public :: snow_ice = .false.

Archimedes freeboard snow-ice conversion (SIS2 ice_resize_SIS2 final block; diagnosed as SN2IC). When the snow load submerges the snow-ice interface, convert the submerged snow mass to ice in the top layer. Default OFF => byte-identical.

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

Uniform frozen-precipitation rate onto the ice top (kg/m^2/s) for the v1 restoring atmospheric-forcing filler (PR 26). Spread onto the atm_fprec seam exactly like sw_down -> atm_sw_dn. 0 (default) => byte-identical (has_snowfall=.false., the new kernels never fire).

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

Downwelling shortwave into the ice top (W/m^2) for the v1 filler.

real(kind=wp), public :: tdamp = -0.2_wp

SIS2 ICE_TDAMP_ELASTIC. >0 => seconds; ==0 => max(0.2*dt_slow, 3*dt); <0 => max(-tdamp*dt_slow, 3*dt).

logical, public :: transport = .false.

Enable horizontal category ice/snow transport (rdb_ice_transport%ice_transport_step) — SIS2’s default (velocity, non-merged) ice_cat_transport path. Default OFF ⇒ byte-identical for every existing nml/test (house rule).

type, public ::  ocean_ice_ic_config_t

&ocean_ice_ic_nml: sea-ice ANALYTIC initial-condition path (PR 24). Default conc_config="zero" early-returns before touching a single ice array => byte-identical to today for every existing nml/test. v1 ships "uniform" (scalar) and "latitudes" (SIS2 polar-cap analytic form) only — file-backed ICs are deliberately NOT in the allowed list ("file" is v1.1, PR-14).

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: antarctic_edge = -91.0_wp

"latitudes" Antarctic ice edge (degrees_north) — SIS2 ANTARCTIC_ICE_EDGE_IC default (no cell qualifies => no ice).

real(kind=wp), public :: arctic_edge = 91.0_wp

"latitudes" Arctic ice edge (degrees_north) — SIS2 ARCTIC_ICE_EDGE_IC default (no cell qualifies => no ice).

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

Uniform-mode concentration [0,1] (nondim). "uniform" only.

character(len=32), public :: conc_config = "zero"

"zero" (default, no-op) / "uniform" / "latitudes".

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

Ice thickness (m) where seeded — SIS2 ICE_INIT_MASS as a thickness.

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

Snow thickness (m) where seeded — SIS2 SNOW_INIT_MASS as a thickness. Snow is a one-way street (no snowfall source anywhere in the tree) — this can only ever melt.

real(kind=wp), public :: s_ice = 4.0_wp

Ice bulk salinity (PSU) — SIS2 ICE_SALINITY_IC default, matching ICE_BULK_SALINITY (ocean_sea_ice_init’s own sal_ice source value).

real(kind=wp), public :: t_ice = -4.0_wp

Ice/snow temperature (degC) fed through the exact ice_enth_from_ts inversion — SIS2 ICE_TEMPERATURE_IC default.

type, public ::  ocean_isopycnal_config_t

&ocean_isopycnal_nml: grounding-stability controls for the Lagrangian (isopycnal-class, remap-free) vertical coordinate. Every knob here engages ONLY under sim_type=’ocean’ + VCOORD_LAGRANGIAN, so the whole group is bit-identical on every other vertical coordinate. All are default-OFF except pgf_skip_nonoverlap, which is a correctness fix and defaults ON.

Components

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

Phase 1: minimum-thickness floor (m) on the Lagrangian continuity h-update — MOM6 GV%Angstrom_H analogue used as the max(h_new, Angstrom_H) clamp. 0.0 ⇒ off ⇒ bit-identical (the floor loop is skipped). Physical floor (D4 taxonomy), NOT H_DIV_EPS (too small to bound 1/h) and NOT hardwired H_VANISHED (that is the skip/merge marker). Recommended run value 1e-3..1e-2 m. NOT strictly conservative: injects <= angstrom_h*areaT per floored layer-cell (zero on non-grounding steps). Thermo-on caveat (R7): the floor lifts h but not the companion hTr, so on a floored layer the implied Tr=hTr/h shifts — harmless for the adiabatic (enable_thermodynamics=.false.) isopycnal config; thermo-on isopycnal correctness is OUT OF SCOPE for v1.

logical, public :: cfl_ignore_vanished = .false.

Phase 3: exclude vanished layers from the console MaxCFL / panic / CFL truncation so a thin-layer velocity spike cannot falsely abort.

logical, public :: check_h_positive = .false.

DEBUG GUARD (vcoord-agnostic despite living in this group): abort on the FIRST negative h_layer, naming the pipeline stage that wrote it plus the offending (i,j,k) and that column’s full profile. Without it a negative thickness is only visible later and elsewhere — as a NaN in the console stats, or as an hourly diagnostic minimum — by which point the producing kernel is unidentifiable. Costs one device-side min-reduction over h_layer per instrumented stage (~6% of an outer step at 600x600x50); no H<-D traffic on the healthy path. Default .false. ⇒ not called ⇒ bit-identical.

logical, public :: conservative_floor = .false.

Conservative minimum-thickness mode. When .true. (requires angstrom_h > 0 and VCOORD_LAGRANGIAN — fail-loud otherwise) the non-conservative max(h, angstrom_h) injection is REPLACED by a per-column conservative borrow: a sub-floor layer’s deficit is taken from the surplus layers of the same column, so total thickness, momentum, and every tracer mass are preserved to round-off and the result is independent of the floor value. Fires only where a layer is below floor; a strict no-op elsewhere (isopycnals not pinned). Default .false. ⇒ the legacy injecting floor ⇒ bit-identical.

logical, public :: pgf_skip_nonoverlap = .true.

Grounded-layer PGF gate. Default ON — unlike every other knob in this group this one is a CORRECTNESS fix, not an opt-in, and it is still bit-identical everywhere except VCOORD_LAGRANGIAN (the only coordinate it is applied under).

Read more…
logical, public :: reset_vanished_u = .false.

Phase 2: zero the face velocity of a layer vanished on BOTH adjacent cells (a massless layer carries no independent momentum).

type, public ::  ocean_kappa_shear_config_t

&ocean_kappa_shear_nml: shear-driven interior turbulence (Jackson, Hallberg & Legg 2008). Coexists with KPP/EPBL/PP81 — kappa is ADDED to the interior diffusivities. Default off ⇒ bit-identical.

Components

Type Visibility Attributes Name Initial
logical, public :: at_vertex = .false.

Solve the JHL08 columns at C-grid CORNERS (vorticity points) from the native face velocities, then average the corner Kd back to tracer points (MOM6 VERTEX_SHEAR — the OM5-class production setting). Default off ⇒ bit-identical. v1 scope is Kd only: Kv stays prandtl_turb * kd_int at cell centres (the corner->face viscosity seam is a follow-up PR).

real(kind=wp), public :: c_n = 0.24_wp

TKE decay-rate coefficient vs stratification N (JHL08).

real(kind=wp), public :: c_s = 0.14_wp

TKE decay-rate coefficient vs shear S (JHL08).

logical, public :: enable = .false.

Master switch. Requires vmix%use_closure + thermodynamics (validated at configure).

real(kind=wp), public :: fri_curvature = -0.97_wp

Ri-function curvature in the shear source (JHL08).

real(kind=wp), public :: kappa_0 = 1.0e-7_wp

Background diffusivity, m^2/s; also the pre-step kappa (JHL08).

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

Iteration seed diffusivity, m^2/s (JHL08).

real(kind=wp), public :: kappa_trunc = 1.0e-9_wp

Diffusivity below this is truncated to 0, m^2/s (JHL08).

real(kind=wp), public :: lambda = 0.82_wp

Buoyancy mixing-length-scale coefficient (JHL08).

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

Boundary-distance length-scale rescale factor (JHL08).

logical, public :: massless_merge = .false.

sub-grid before the column solve (vs the blunt gather floor). Default off (bit-identical); identity columns bypass the merge.

integer, public :: max_inner_it = 50

Inner Picard iteration cap (JHL08).

integer, public :: max_substep_it = 13

Outer adaptive-substep iteration cap (JHL08).

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

Kv = prandtl_turb * Kd into the momentum solve (JHL08).

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

Critical Richardson number (JHL08 Ri_c).

real(kind=wp), public :: shearmix_rate = 0.089_wp

Shear-source-rate coefficient (JHL08).

real(kind=wp), public :: src_max_chg = 10.0_wp

Adaptive-dt source-change tolerance band (JHL08).

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

Background TKE, m^2/s^2; Q is a denominator, floored (JHL08).

real(kind=wp), public :: tol_err = 0.1_wp

Picard convergence tolerance (JHL08).

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

Velocity snap-to-zero magnitude, m/s, in the projection (JHL08).

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

Floor, m^2/s, applied to each corner Kd BEFORE the geometric mean (MOM6 VERTEX_SHEAR_GEOMETRIC_MEAN_KDMIN; inert unless vertex_geometric_mean). OM5 configs use 1e-9.

logical, public :: vertex_geometric_mean = .false.

Geometric (vs arithmetic) mean in the corner->centre Kd average (MOM6 VERTEX_SHEAR_GEOMETRIC_MEAN). Pair with vertex_geomean_kdmin — with a 0 floor the geometric mean hard-zeros Kd along every shear-zone edge.

type, public ::  ocean_meke_config_t

&ocean_meke_nml: mesoscale eddy kinetic energy — a 2D prognostic eddy-energy field fed back as a thickness/tracer diffusivity into VarMix’s KhTh/KhTr. Reads gm%gm_src. Default off ⇒ no-op.

Components

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

Barotropic-transport advection scaling (nondim); 0 ⇒ off (v1).

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

Weight on the deformation length scale (nondim).

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

Weight on the Eady length scale (needs VarMix SN) (nondim).

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

Weight on the frictional-arrest length scale (nondim).

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

Weight on the grid length scale (nondim).

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

Weight on the Rhines length scale (nondim); v1 default 0 ⇒ inert.

logical, public :: backscatter = .false.

Enable the MEKE → momentum harmonic backscatter (negative viscosity) energy return (Gap 2, v1). Default off ⇒ bit-identical. Requires a flow-aware lateral closure (lateral_closure /= none) for the returned energy to reach the momentum tendency.

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

MOM6 MEKE_VISCOSITY_COEFF_KU — harmonic backscatter efficiency Ku = coeff·sqrt(2·gamma_t²·E)·Lmix (m²/s). Subtracted (face- averaged, CFL-floored) from the resolved harmonic viscosity. 0 (default) ⇒ inert. HARMONIC only in v1 (biharmonic Au + EBT/SQG vertical structure deferred).

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

Background energy source (m^2/s^3).

real(kind=wp), public :: cb = 25.0_wp

Coefficient in the gamma_bot (bottomFac2) expression (nondim).

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

Bottom/column eddy-velocity ratio (nondim); enters bottomFac2.

real(kind=wp), public :: cdrag = 2.5e-3_wp

Bottom drag coefficient for MEKE (nondim); enters drag_rate + Lfrict. Set from &ocean_bdrag_nml cdrag_side at configure if that is > 0, else this default.

real(kind=wp), public :: ct = 50.0_wp

Coefficient in the gamma_bt (barotrFac2) expression (nondim).

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

Local depth-independent linear MEKE dissipation rate (1/s).

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

Scale factor accelerating MEKE time-stepping (nondim).

logical, public :: enable = .false.

Master switch. Default off. Requires &ocean_gm_nml enable=.true. (configure-time error).

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

Frictional mean->eddy conversion efficiency (nondim); < 0 ⇒ off (default). When >= 0 the lateral-viscosity KE dissipation rate is sourced into MEKE.

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

Efficiency of PE->MEKE conversion (nondim); < 0 ⇒ GM source off.

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

Background biharmonic diffusion of MEKE (m^4/s); < 0 ⇒ off.

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

Background lateral diffusion of MEKE (m^2/s); < 0 ⇒ off.

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

Scaling converting MEKE into Kh (nondim); <= 0 ⇒ closure off.

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

Factor relating meke%kh to MEKE’s own lateral diffusivity (nondim).

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

Factor on the geom-mean kh added into VarMix KhTh (nondim). 0 (default) ⇒ feedback inert ⇒ bit-identical seam.

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

Factor on the geom-mean kh added into VarMix KhTr (nondim).

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

Floor on gamma_b^2 / gamma_t^2 (nondim).

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

Background eddy velocity scale for bottom drag (m/s).

logical, public :: use_bbl_drag = .false.

Add the resolved bottom-boundary-layer eddy velocity to the MEKE bottom-drag rate: drag_rate = rho0·i_mass·sqrt(cdrag²·(2·bf2·E + |u_bed|² + uscale²)) (MOM6 drag_rate_visc term, here the bed-layer speed). Default .false. ⇒ the |u_bed|² term is 0 ⇒ bit-identical to the prior MEKE drag.

type, public ::  ocean_mpi_config_t

&ocean_mpi_nml: multi-rank MPI debug and tuning controls.

Components

Type Visibility Attributes Name Initial
logical, public :: poison_ghosts = .false.

Debug knob — sentinel-NaN the exchange-covered ghost bands at each outer-step start; any unexchanged-ghost consumption becomes a loud NaN. Default .false. = bit-identical (untaken branch).

type, public ::  ocean_pgf_config_t

Components

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

Advective-CFL velocity truncation threshold (nondimensional). When > 0, faces with |u|·dt/dx > cfl_trunc are clipped to 0.9·cfl_trunc·dx/dt (runs before the maxvel cap). Default 0.0 = disabled (bit-identical).

character(len=16), public :: form = "mont"

Pressure-gradient kernel variant. “mont” (default) is the Boussinesq Montgomery-potential form — general purpose (valid over sloping bathymetry and every vcoord), algebraically identical to “fv_lite” on columns of equal layer thickness, and exact at rest in isopycnal columns; it is also the cheapest, since it builds no pressure stack. “fv_lite” and “fv_wright” are the FV sigma-aware kernels. “fv_lite” carries the SAME physics content as “mont” (layer-mean rho, no in-layer quadrature) and differs from it only where layer thicknesses are UNEQUAL across a face — there the two are different discretisations of the same term, neither exact. “gprime” is the reduced-gravity layered PGF (NK = 2 only). “fv_mom6” is the faithful FV-Bouss port (used by gfs_scale).

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

Free-surface gravity scaling for the FV_MOM6 PGF. Default 1.0 = no reduction. When < 1, applies a Montgomery dM correction and evolves η at the reduced gravity. Active only under form = "fv_mom6".

real(kind=wp), public :: gprime_gfs = 9.81_wp

Free-surface gravity (m/s²) for the gprime PGF.

real(kind=wp), public :: gprime_gint = 0.0098_wp

Internal-interface reduced gravity (m/s²) for the gprime PGF.

logical, public :: insitu_density = .true.

FV_MOM6 constant-by-layer (PCM) density at its IN-SITU pressure p = -g*rho0*z (MOM6 int_density_dz_generic_pcm; MOM6 parity, default). .false. = the legacy integral of the POTENTIAL density ms%rho_layer at the uniform &ocean_eos_nml p_ref, which loses the pressure dependence of the horizontal density gradient away from p_ref (on the global 1-degree spin-up: Drake Passage ~80 Sv against MOM6’s ~155 Sv). Consulted only by form = "fv_mom6" with reconstruct_for_pressure = .false. and a PRESSURE-DEPENDENT EOS (wright, roquet_spv); for linear in-situ and potential density coincide and the legacy path runs, bit-identical.

Read more…
logical, public :: mass_weight = .false.

FV_MOM6 shelf-break mass-weighting. When .true., biases the layer density in the horizontal pressure integral toward the thinner column at unequal-depth faces, cancelling the spurious bottom-layer PGF. Reduces to bit-identical on aligned columns. Default .false.. Active only under form = "fv_mom6".

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

Velocity-truncation clamp (m/s): u = sign(u)·min(|u|, maxvel) after each outer dyn step. Default 0 = disabled.

logical, public :: p_top_in_bc = .false.

Add the top-of-column load multilayer_state_t%p_top (Pa) to the FV_MOM6 pressure-stack surface boundary condition: pa(nz+1) = rho_ref*g*eta_geo + p_top. Default .false. => pa(nz+1) = rho_ref*g*eta_geo, bit-identical to every run before this knob existed.

Read more…
integer, public :: recon_scheme = 1

In-layer reconstruction scheme: 1 = PLM, 2 = PPM. Mirrors MOM6 Recon_Scheme. Only consulted when reconstruct_for_pressure = .true..

logical, public :: reconstruct_for_pressure = .false.

FV_MOM6 in-layer T/S reconstruction (Adcroft, Hallberg & Harrison 2008; White, Adcroft & Hallberg 2009). .false. (default) uses layer-mean (PCM) density ⇒ bit-identical. .true. builds each layer’s pressure anomaly via a 5-point Boole quadrature of a monotone PLM/PPM T/S profile. Active only under form = "fv_mom6" (fail-loud at configure otherwise).

Read more…

type, public ::  ocean_porous_config_t

Porous barriers (&ocean_porous_nml): subgrid sill/strait blocking of the C-grid face widths via the Adcroft (2013) three-parameter fit. The layer-averaged OPEN-AREA fraction multiplies dy_cu / dx_cv in the layer mass transport (continuity-PPM + Coriolis advection), so a deep sill blocks the bottom layers while the surface layers stay fully open. enable = .false. keeps the existing path bit-identical. Knob table: docs/generated_nml_knobs.md.

Components

Type Visibility Attributes Name Initial
logical, public :: enable = .false.

Master switch. Requires sim_type='ocean' + a multilayer run (validated at configure).

character(len=32), public :: eta_interp = "max"

Interface-height-at-velocity-point rule (MOM6 PORBAR_ETA_INTERP): "max" (the higher, i.e. shallower, of the two adjacent interfaces — the default, and the LEAST blocking, since the open width increases with interface height), "min" (the most blocking), "arithmetic", "harmonic".

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

Faces whose mean along-face depth is SHALLOWER than this (m, positive below the sea surface) are left fully open (MOM6 PORBAR_MASKING_DEPTH). 0 ⇒ apply everywhere the face is below sea level.

character(len=32), public :: source = "resolved"

Where the along-face min/max/mean topographic heights come from. "resolved": three samples of the RESOLVED bathymetry along the face (two corners + midpoint) — a documented PROXY, not true subgrid data. "file": an offline subgrid-bathymetry file (MOM6 topog_edge.nc), NOT implemented — fails loud pending the file-forcing backend.

type, public ::  ocean_psurf_config_t

Atmospheric surface-pressure loading / inverse barometer (&ocean_psurf_nml, PR-17). Folds eta_ib = -p_surf/(rho0 g) into the barotropic eta_forcing seam so an atmospheric high depresses SSH (~1 cm/hPa; Wunsch & Stammer 1997). enable = .false. keeps the existing path bit-identical. Split-solver only and mutually exclusive with &ocean_bt_nml bt_halo > 0. Requires &ocean_forcing_nml enable_components=.true. (the p_surf field is allocated only with the component set). ρ₀ is NOT a knob here — it is taken from ocean_state%eos%rho0 (the single ρ₀ of record).

Components

Type Visibility Attributes Name Initial
logical, public :: enable = .false.

Master switch (default off => bit-identical).

logical, public :: in_eos = .false.

Include the surface load in the EOS’s IN-SITU pressure arguments, as the top-of-column pressure p_top (multilayer_state_t%p_top): a hydrostatic pressure that used to start at 0 Pa at the free surface starts at p_top(i,j) instead. Default .false. => p_top stays the zero array and every EOS evaluation is bit-identical. This is the E3 seam for ice-shelf cavities, where 1e6-2e7 Pa of ice load makes the p=0 assumption a systematic ~4-5 kg/m^3 density error under a nonlinear EOS.

Read more…
real(kind=wp), public :: p_surf_const = 0.0_wp

Uniform atmospheric surface pressure (Pa) seeded into sf%p_surf_atm at configure. A UNIFORM load is provably inert (gauge invariance — only grad(p_surf) is physical), so a non-zero value with no file/override path emits a rank-0 warning. v1 fill path (the analogue of &ocean_thermo_nml q_heat). The NetCDF forcing reader itself ships (&ocean_dataovr_nml); p_surf is simply not one of its six tags (tau_x, tau_y, heat, salt, evap, lprec) yet, so a file-driven load needs a register_tag entry, not new reader machinery.

type, public ::  ocean_restore_config_t

&ocean_restore_nml: surface buoyancy restoring of top-layer T/S toward scalar targets via a piston velocity. Default OFF = bit-identical.

Components

Type Visibility Attributes Name Initial
logical, public :: enable_restore_salt = .false.

Master switch for SSS restoring (piston_s /= 0).

logical, public :: enable_restore_temp = .false.

Master switch for SST restoring (effective when piston_t /= 0).

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

SSS piston velocity (m/day).

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

SST piston velocity (m/day).

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

Scalar target SSS (PSU).

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

Scalar target SST (degC).

type, public ::  ocean_sponge_config_t

&ocean_sponge_nml: the map-driven sponge (PR-23). Default OFF (enable = .false.) ⇒ the legacy &ocean_bc_nml band kernels run unchanged ⇒ bit-identical. See rdb_ocean_sponge.F90’s module docstring for the physics; docs/plans/PLAN_PR23_real_sponge.md for the design record.

Components

Type Visibility Attributes Name Initial
character(len=16), public :: damp_source = "band"

How idamp_h/idamp_u/idamp_v are filled. "band" (default, implemented): cosine ramp from every OBC_SPONGE-tagged edge, summed at overlaps. "file" recognised but aborts at validate_config in v1 (PR-23b, needs the PR-14 reader).

real(kind=wp), public :: east_strength = -1.0_wp
integer, public :: east_width = -1
logical, public :: enable = .false.

Master switch. Off ⇒ legacy band kernels ⇒ byte-identical.

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

target_source="linear_z": dS/dz (PSU/m), z positive UP, so a stable column has lin_ds_dz < 0. Same convention as &ocean_zinit_nml lin_ds_dz.

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

target_source="linear_z": dT/dz (degC/m) with z positive UP, so a stable column has lin_dt_dz > 0. Same convention as &ocean_zinit_nml lin_dt_dz.

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

target_source="linear_z": salinity (PSU) at the z = 0 datum. Same convention as &ocean_zinit_nml lin_s_ref.

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

target_source="linear_z": potential temperature (degC) at the z = 0 datum. Same convention as &ocean_zinit_nml lin_t_ref.

real(kind=wp), public :: north_strength = -1.0_wp
integer, public :: north_width = -1
character(len=16), public :: ramp = "cosine"

Shape of the damp_source="band" ramp from the sponge-tagged wall (d = 0) inward.

Read more…
logical, public :: relax_h = .false.

Interior-interface thickness damping. NOT IMPLEMENTED in PR-23 v1 — enable=.true., relax_h=.true. aborts fail-loud at validate_config (deferred to PR-23b; see the plan §14 Q1).

logical, public :: relax_tracers = .true.

Relax every registered tracer toward its 3-D reference field.

logical, public :: relax_uv = .true.

Relax u/v toward u_ref/v_ref. Default .true. matches today’s legacy path (momentum is the one thing the legacy sponge always damps); MOM6’s SPONGE_UV defaults .false..

real(kind=wp), public :: south_strength = -1.0_wp
integer, public :: south_width = -1
character(len=16), public :: target_source = "ic"

Reference-state source.

Read more…
real(kind=wp), public :: west_strength = -1.0_wp

Per-edge peak relaxation-rate override (1/s). < 0 ⇒ inherit &ocean_bc_nml sponge_strength.

integer, public :: west_width = -1

Per-edge sponge-band width override (cells). < 0 ⇒ inherit &ocean_bc_nml sponge_width.

type, public ::  ocean_tdrag_config_t

&ocean_tdrag_nml — ICE-SHELF TOP drag, the mirror of &ocean_bdrag_nml at k = nz. Requires &ocean_cavity_dyn_nml enable (without a draft there is no ice base and cover_frac is identically zero, so the kernel would be a no-op with a cost). Default enable = .false. ⇒ the slot is a placeholder, no kernel runs, every path is bit-identical.

Components

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

Background velocity floor (m/s) in the quadratic speed. Zero (default) ⇒ the layer-only quadratic branch is the exact algebraic mirror of the bottom drag’s.

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

Quadratic drag coefficient (dimensionless). ISOMIP+ value 2.5e-3 (Asay-Davis et al. 2016 Table 4). Zero disables the quadratic branch. When &ocean_cavity_melt_nml enable, this is THE C_d for both momentum and the melt friction velocity — see the cdrag_top agreement rule in validate_config.

logical, public :: enable = .false.

Master switch. Requires &ocean_cavity_dyn_nml enable.

character(len=16), public :: form = "quadratic"

Top-drag variant: “quadratic” (default, du/dt = -C_d*|U|*u/h, the ISOMIP+ prescription) or “linear” (Rayleigh du/dt = -r*u). Enum mirrors parse_tdrag_variant in rdb_ocean_top_drag.

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

Top-boundary-layer thickness (m) the stress is distributed over (the mirror of &ocean_bdrag_nml hbbl). Zero (default) = layer-nz-only. Positive values keep the explicit drag rate finite where a sigma coordinate thins the top layer near a grounding line.

logical, public :: implicit = .false.

Backward-Euler top drag inside the drag kernel: u^{n+1} = u/(1 + dt*lambda), unconditionally stable for any top-layer thickness. Default .false. = explicit forward Euler (bit-identical to the pre-knob path, but conditionally unstable when lambda*dt > 1). Mutually exclusive with &ocean_vdiff_nml implicit_top_drag.

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

Linear Rayleigh coefficient (1/s). Active when form = "linear".

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

Minimum effective TBL thickness (m) in the stress/h_tbl denominator. Zero (default) falls back to the kernel’s h_min (1e-3 m), matching the bottom drag.

type, public ::  ocean_thermo_config_t

Thermodynamics master switches + scalar surface fluxes.

Components

Type Visibility Attributes Name Initial
logical, public :: enable_thermodynamics = .true.

When .true. (default), the dyn step runs EOS + tracer advection + vertical mixing. .false. = adiabatic.

logical, public :: epbl_sw_ctke = .true.

(PR-21) Charge the EPBL TKE ledger for penetrating shortwave (the in-layer PE-cost Phi(tau) shape). Inert at sw_pen_frac = 0 ⇒ bit-identical.

character(len=32), public :: kpp_sw_method = "mxl_sw"

(PR-21) KPP boundary-layer shortwave method (MOM6 KPP_SHORTWAVE_METHOD): all_sw | mxl_sw (default) | lv1_sw. Only the SW absorbed inside the boundary layer stabilises B_0. Inert at sw_pen_frac = 0 ⇒ bit-identical.

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

Scalar net surface heat flux (W/m^2, positive down).

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

Scalar net surface salt flux (kg salt/m^2/s, positive = surface salinifies).

real(kind=wp), public :: sw_band_ratio = 0.58_wp

Band-1 weight R of the two-band shortwave decay (Jerlov type I).

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

Penetrating fraction of q_heat as a two-band exponential (Paulson & Simpson 1977). 0 = off.

character(len=32), public :: sw_source = "net_heat"

(PR-21) Irradiance source for shortwave penetration + the boundary-layer SW coupling. "net_heat" (default, bit-identical): I0 = sw_pen_frac*q_heat. "q_sw": I0 = sw_pen_frac*q_sw (the dedicated >= 0 shortwave component) — kills the night-time negative-I0 hazard; REQUIRES &ocean_forcing_nml enable_components=.true. (validate_config aborts otherwise).

real(kind=wp), public :: sw_zeta1 = 0.35_wp

Band-1 (red/near-IR) e-folding depth (m).

real(kind=wp), public :: sw_zeta2 = 23.0_wp

Band-2 (blue/green) e-folding depth (m).

type, public ::  ocean_tidal_mixing_config_t

St-Laurent/Simmons internal-tide interior mixing (&ocean_tidal_mixing_nml). Bottom-intensified diapycnal diffusivity from the local dissipation of internal-tide energy over rough topography (Jayne & St Laurent 2001; St Laurent et al. 2002; Simmons et al. 2004). An INTERIOR closure: its Kd is ADDED to the surface PBL schemes (KPP or EPBL) and to PP81/background/kappa-shear. enable = .false. keeps the existing path bit-identical. Knob table: docs/generated_nml_knobs.md.

Components

Type Visibility Attributes Name Initial
logical, public :: e_compute = .false.

v1.1 state-dependent E = min(TKE_coef*N_bot, e_max).

real(kind=wp), public :: e_max = 1.0e3_wp

TKE_itide_max cap on E, W m-2.

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

Uniform bottom energy input E, W m-2 (v1 prescribed field; default 0 => inert even when enabled).

logical, public :: enable = .false.

Master switch. Requires vmix%use_closure + thermodynamics (validated at configure).

real(kind=wp), public :: frac_rough = 0.1_wp

Roughness clamp <= (frac_rough*H)^2.

real(kind=wp), public :: gamma = 0.3333_wp

Local-dissipation fraction q (GAMMA_ITIDES).

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

Sub-grid topographic roughness variance , m^2.

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

KAPPA_H2_FACTOR (v1.1 E recompute).

real(kind=wp), public :: kappa_itides = 6.2832e-4_wp

Topographic wavenumber, m^-1 (v1.1 E recompute).

real(kind=wp), public :: kd_max = 1.0e-2_wp

Per-layer physical Kd cap, m^2/s; < 0 => no cap.

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

Mask off where column depth H < min_zbot, m.

real(kind=wp), public :: mu = 0.2_wp

Mixing efficiency Gamma_mix (MU_ITIDES).

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

Kv = prandtl_tidal * Kd into the momentum solve.

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

RMS barotropic tidal velocity, m/s (v1.1 E recompute).

real(kind=wp), public :: zeta = 500.0_wp

Bottom decay scale, m (INT_TIDE_DECAY_SCALE).

type, public ::  ocean_tides_config_t

Equilibrium (astronomical) body-force tide (&ocean_tides_nml, capability C1). Drives -g grad(eta - eta_eq) in the barotropic momentum solve from a set of harmonic constituents. enable = .false. keeps the existing path bit-identical. Requires a non-cartesian grid (needs lat/lon).

Components

Type Visibility Attributes Name Initial
logical, public :: add_nodal = .false.

Apply the 18.6-yr nodal f/u corrections (fixed at nodal_ref_date).

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

Scalar SAL factor beta (~0.085-0.12); eta_sal = beta_sal*eta.

character(len=64), public :: constituents = "M2 S2 N2 K2 K1 O1 P1 Q1"

Whitespace/comma-separated active constituent list.

logical, public :: enable = .false.

Master switch (default off => bit-identical).

character(len=16), public :: nodal_ref_date = ""

Nodal reference date; “” => ref_date.

character(len=16), public :: ref_date = "1900-01-01"

Astronomical reference date “YYYY-MM-DD”; model t=0 == ref_date.

logical, public :: use_sal = .false.

Apply scalar self-attraction & loading (C2). Default off => bit-identical.

type, public ::  ocean_topo_config_t

Basin geometry + surface-forcing setup. Despite the name, this carries forcing knobs (wind_config / taux_magnitude) and Coriolis tilt (beta / y_ref) alongside the bathymetry profile, because all of them live in the same logical “set up the box and what’s pushing it” slot at init — the &ocean_topo_nml block is read once before the IC is seeded. This grouping is settled (reviewed 2026-05-27); the form knob in &ocean_coriolis_nml is the scheme selector (Sadourny vs HK), distinct from the beta/y_ref parameters here.

Components

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

Meridional gradient of f (s⁻¹ m⁻¹). 0 = f-plane (uses cfg%coriolis_f as a uniform value); non-zero engages set_beta_plane with f₀ = coriolis_f.

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

Reference y-coordinate (m) at which f = coriolis_f under the beta-plane: f(y) = coriolis_f + beta*(y - y_ref).

real(kind=wp), public :: edge_depth = 100.0_wp

Edge depth (m) for spoon bathymetry. MOM6 default 100 m.

real(kind=wp), public :: max_depth = 2000.0_wp

Basin maximum depth (m). Used by spoon bathymetry and as the uniform depth for topo_config="flat".

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

Continent amplitude for topo_config=”neverworld2”: scales the continent/ridge terms of the Neverworld2 basin (1.0 = full continents, 0.0 = aquaplanet with the southern channel only). MOM6 NL_CONTINENT_AMP default 1.0.

real(kind=wp), public :: nl_min_depth = 500.0_wp

Minimum-depth floor (m) for topo_config=”neverworld2” (MOM6 MINIMUM_DEPTH analogue). The fractional-depth formula drives the depth to 0 (land) at the continent/wall cells; the C-grid dyn-core has no robust wet/dry path yet, so true land + the resulting sub-metre surface layers blow up. Flooring to nl_min_depth keeps the basin all-wet (continents become shallow steering shelves) and stable. Lower = stronger topographic steering but thinner layers (nl_min_depth/nz).

real(kind=wp), public :: nl_roughness_amp = 0.05_wp

Roughness amplitude for topo_config=”neverworld2”: amplitude of the wavy bathymetry signal. MOM6 NL_ROUGHNESS_AMP default 0.05.

real(kind=wp), public :: slope_scale = 400000.0_wp

Exponential decay scale (m) for spoon bathymetry. MOM6 default TOPOG_SLOPE_SCALE = 400 km.

real(kind=wp), public :: taux_magnitude = 0.1_wp

Peak zonal wind stress (Pa) for wind_config = “2gyre”. MOM6 TAUX_MAGNITUDE default.

character(len=16), public :: topo_config = "flat"

Bathymetry profile selector: “flat”, “spoon”, etc.

character(len=16), public :: wind_config = "constant"

Surface wind-stress dispatch: “constant” (uniform tau_x/y from wind_stress_x/y) or “2gyre” (MOM6 sinusoidal).

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

Absolute x-coordinate (m) of the domain’s WEST edge, for the formula bathymetries whose published formula is written in an absolute coordinate frame rather than a domain-relative one. Read ONLY by topo_config="isomip_plus", whose bedrock polynomial is a function of the MISMIP+ x that runs from the ice divide at 0, while the ISOMIP+ ocean box starts at x = 320 km (Asay-Davis et al. 2016, Table 3 x0). Default 0 ⇒ the model’s own x = 0 west edge ⇒ bit-identical for every other topo_config.

type, public ::  ocean_tracers_config_t

Prognostic-tracer registry switches.

Components

Type Visibility Attributes Name Initial
logical, public :: enable_ideal_age = .false.

When .true., register a passive “ideal age” tracer. Default off.

logical, public :: enable_pseudo_salt = .false.

When .true., register the pseudo-salt verification tracer (diagnostic; seeded to S, given salinity’s boundary fluxes; typically run to measure passive-vs-active transport-path error). Default off. Incompatible with SSS piston restoring and sea-ice (both are un-mirrored salinity sources — see validate_config).

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

Exponential growth rate of the surface value (1/s). 0 (default) ⇒ young_val is constant ⇒ no exp() ⇒ bit-identical. MOM6 CS%growth_rate (which is per-year; 1/30 yr^-1 = 1.057e-9 s^-1).

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

Surface-band age value (s). Default 0 = today’s hard-coded reset ⇒ bit-identical. MOM6 CS%young_val.

type, public ::  ocean_varmix_config_t

&ocean_varmix_nml: spatially-varying GM/Redi lateral-diffusivity coefficients = (background + Visbeck) × resolution_fn, clamped. Reads the slopes + wavespeed slots. Default off ⇒ GM keeps constant khth.

Components

Type Visibility Attributes Name Initial
logical, public :: enable = .false.

Master switch. Default off. Requires &ocean_slopes_nml enable + &ocean_wavespeed_nml enable (configure-time errors).

logical, public :: gill_equatorial_ld = .true.

Gill (1982) equatorial-Ld convention (factor 2 in beta_dx2).

logical, public :: interpolate_res_fn = .false.

Interpolate the centre Res_fn to faces (.true.) vs interpolate cg1 to faces then recompute Res_fn (.false., MOM6 default).

integer, public :: kh_res_fn_power = 2

Resolution-function power p (even).

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

Resolution-function alpha (the (alpha·cg1)^p denom coefficient).

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

Background thickness diffusivity KhTh (m²/s) the Visbeck term + Res_fn scale.

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

Upper clamp on KhTh (m²/s); ≤ 0 ⇒ no cap.

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

Lower clamp on the assembled KhTh (m²/s).

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

Visbeck coefficient α_s for the KhTh chain.

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

Background tracer diffusivity KhTr (m²/s) for the future Redi.

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

Upper clamp on KhTr (m²/s); ≤ 0 ⇒ no cap.

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

Lower clamp on KhTr (m²/s).

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

Visbeck coefficient for the KhTr chain.

logical, public :: resoln_scaled_khth = .false.

Scale the assembled KhTh by the resolution function.

logical, public :: resoln_scaled_khtr = .false.

Scale the assembled KhTr by the resolution function.

logical, public :: use_visbeck = .false.

Add the Visbeck/Eady khth_slope_cff·L²·SN baroclinicity term.

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

Visbeck length scale L (m); if < 0, |L|²·areaCu is used.

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

S² limiter scale; ≤ 0 ⇒ no S² limit.

type, public ::  ocean_vdiff_config_t

Backward-Euler vertical-friction solver knobs (&ocean_vdiff_nml). The implicit folds default .false. (explicit wind-stress apply); MOM6’s face treatment (hvel_mom6 + bbl_glue) defaults ON.

Components

Type Visibility Attributes Name Initial
logical, public :: accel_visc_rem = .false.

RETIRED (PR-3, 2026-10): setting .true. is a fail-loud validate_config error. This attenuated the slow EXPLICIT accelerations by the per-layer viscous remnant — u = u_entry + visc_rem·(u_applied − u_entry) after the CorAdv/PGF/hvisc/drag applies, before the BT correction — but PR-3’s audit found NO MOM6 state-update equivalent: btstep_layer_accel and the split-explicit RK2 corrector’s up/vp update both apply the depth-mean barotropic acceleration u_accel_bt UNIFORMLY across every layer, with no visc_rem weight anywhere in that path. The real MOM6 mechanisms that multiply a velocity correction by visc_rem are &ocean_bt_nml renorm_visc_rem (continuity u_cor = u + du·visc_rem) and rescale_strong_drag. The underlying kernels (accel_visc_rem_snapshot/accel_visc_rem_reweight in rdb_ocean_dyn.F90) and their direct unit tests (tests/test_ocean_accel_visc_rem.F90) are untouched — only the configure-time path to reach them from a namelist is refused.

logical, public :: bbl_glue = .true.

DEFAULT ON (2026-10; .false. restores the explicit / folded bed drag). MOM6 BOTTOMDRAGLAW: the bottom drag lives in the vertical viscosity. MOM6 set_viscous_BBL computes, per face and once per outer step, the BBL viscosity kv_bbl = sqrt(CDRAG)·u*· bbl_thick (u* from the HBBL-mean speed under the quadratic law, sqrt(CDRAG)·DRAG_BG_VEL under the linear one) and the rotation/stratification-limited bbl_thick (KW99); the momentum solve then raises the interface viscosity by (kv_bbl − KV)·botfn near the bed and takes the bed row as the piston kv_bbl/(min(hvel₁/2, bbl_thick)), which REPLACES the explicit / folded bed drag. The drag law and its parameters come from &ocean_bdrag_nml (form, cd or r, hbbl — falling back to hbbl_visc when 0 — bg_vel, bbl_thick_min); with no drag configured the glue is inert. Requires hvel_mom6 (fail-loud at configure).

real(kind=wp), public :: bbl_piston = 3.0e-4_wp

Historical constant BBL piston velocity (m/s), kv_bbl = bbl_piston·hbbl_visc: read only by a hand-built vdiff slot without the per-face BBL (unit tests). A configured run’s glue takes its drag from &ocean_bdrag_nml.

real(kind=wp), public :: hbbl_visc = 10.0_wp

MOM6 HBBL (m) for the hvel_mom6 botfn blend without the BBL glue (under the glue each face’s bbl_thick normalises the height above the bed), and the glue’s HBBL when &ocean_bdrag_nml hbbl = 0.

logical, public :: hvel_harmonic = .false.

Which MOM6 face-thickness branch hvel_mom6 builds (MOM6 HARMONIC_VISC). .false. (MOM6’s default): arithmetic face thickness, blended to harmonic near the bed for thin -> thick flow, height above the bed max(zh, z_clear) — every face layer below the shallower bed of a step sits inside the BBL. .true.: the harmonic branch (harmonic thickness, upwind-arithmetic blend gated by hvel_upwind) — the historical hvel_mom6.

logical, public :: hvel_mom6 = .true.

MOM6 momentum face thickness hvel for the vertical-friction solve (vertvisc_coef), with MOM6’s arithmetic h_shear and the height-above-bed stack the BBL glue reads; the branch is hvel_harmonic. DEFAULT ON (2026-10, with bbl_glue: MOM6’s face treatment everywhere). .false. ⇒ the historical arithmetic h_u / face_thick pair.

logical, public :: hvel_upwind = .true.

Near-bed upwind (arithmetic-donor) blend in the hvel_mom6 face-thickness build. Default .true. = MOM6 parity / bit-identical hvel_mom6 behaviour. .false. = pure harmonic hvel — the blend’s u-sign test flip-flops on roundoff velocities at (near-)rest and collapses the BBL glue at whichever faces flip (PGF_BUG.md §9.8).

logical, public :: implicit_drag = .false.

Fold the bottom drag into the vdiff bed-row diagonal (stress bottom-BC; the row is the face’s first LIVE layer k_bot_u/v, k = 1 off z_fixed) instead of the explicit pre-solve add. Mutually exclusive with &ocean_bdrag_nml implicit (split-apply) and, without bbl_glue, incompatible with HBBL-distributed drag (hbbl > 0); both fail loud at configure. Under bbl_glue the glue’s piston replaces the fold.

logical, public :: implicit_stress = .false.

Fold the surface wind stress into the vdiff surface (k=nz) RHS row (Neumann top-BC) instead of the explicit pre-solve add.

logical, public :: implicit_top_drag = .false.

Fold the ICE-SHELF TOP drag into the vdiff k = nz DIAGONAL (&ocean_tdrag_nml’s mirror of implicit_drag) instead of the explicit pre-solve add. The wind stress already owns that row’s RHS; a drag is a diagonal term, so the two compose — but on a face the ice covers, the wind RHS is MASKED OFF here (there is no atmosphere under a shelf). That masking is now BELT AND BRACES and kept deliberately: the cover mask zeroes the tau pair at its source, so the factor multiplies zero, and it stays so the fold is correct STANDALONE if a later forcing path ever writes tau after the configure-time mask. Requires &ocean_tdrag_nml enable; mutually exclusive with &ocean_tdrag_nml implicit (both would damp the top layer) and with htbl > 0 (the fold is one k = nz rate and cannot represent a distributed band). All fail loud at configure. Default .false. ⇒ bit-identical.

type, public ::  ocean_vmix_config_t

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: bkgnd_delta = 222.0_wp

Bryan-Lewis transition half-width (m).

logical, public :: bkgnd_henyey = .false.

Henyey, Wright & Flatte (1986) JGR 91:8487 latitude-dependent internal-wave factor (constant-N0 simplification of Harrison & Hallberg 2008, JPO 38:1894), scaling the SCALAR background tracer diffusivities kt_bg/ks_bg and floored at bkgnd_kd_min. MUTUALLY EXCLUSIVE with bkgnd_profile (Bryan-Lewis) and requires a non-cartesian grid_config — both fail-loud at configure. Default off ⇒ bit-identical.

real(kind=wp), public :: bkgnd_henyey_max_lat = 95.0_wp

Latitude (degN) poleward of which the Henyey factor is reset to its minimum floor; compared against |latitude| so both hemispheres clamp. > 90 so inert for any real latitude out of the box.

real(kind=wp), public :: bkgnd_henyey_n0_2omega = 20.0_wp

Ratio of the assumed reference buoyancy frequency N0 to twice the planetary rotation rate (nondim).

real(kind=wp), public :: bkgnd_kd_deep = 1.3e-4_wp

Deep-asymptote background tracer diffusivity (m^2/s).

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

Minimum background tracer diffusivity (m^2/s) under the Henyey scaling — max(Kd_min, Kd*L(phi)). Negative = unset ⇒ resolved to 0.01*kt_bg (the reference KD_MIN default).

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

Surface-asymptote background tracer diffusivity (m^2/s).

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

Background Prandtl number: Kv_bg = bkgnd_prandtl * Kd_bg.

logical, public :: bkgnd_profile = .false.

Enable the Bryan & Lewis (1979) depth-varying background diffusivity instead of the constant interior background. Default off (bit-identical).

real(kind=wp), public :: bkgnd_z0 = 2500.0_wp

Bryan-Lewis transition-centre depth (m, positive down).

character(len=8), public :: buoyancy_coeffs = "constant"

Where the vmix closures take their α (thermal expansion) and β (haline contraction) from — "constant" (DEFAULT) or "eos". Parsed by parse_buoyancy_coeffs (rdb_ocean_vmix.F90); keep the allowed= list and that routine’s case arms in lockstep.

Read more…
logical, public :: direct_stress = .false.

When .true. the wind stress is distributed across the top hmix_stress metres rather than the surface-most layer.

integer, public :: dt_therm_ratio = 1

Thermodynamic + tracer-advection step runs at ratio · dt_dynamic. Default 1.

integer, public :: dt_tracer_advect_ratio = 1

Horizontal tracer advection runs every ratio · dt_dynamic via accumulated mass fluxes drained in one windowed advect. 1 (default) ⇒ every step, bit-identical. dt_therm_ratio must be an integer multiple of this (configure-time check).

logical, public :: harmonic_visc = .false.

When .true. vdiff uses the harmonic mean of adjacent layer thicknesses in the face-thickness denominator. Default .false. = arithmetic mean.

real(kind=wp), public :: hmix_fixed = 20.0_wp

Mixed-layer thickness (m) for the kv_ml_invz2 profile. Default 20 m.

real(kind=wp), public :: hmix_stress = 20.0_wp

Thickness (m) of the surface slab for direct_stress. Default 20 m.

real(kind=wp), public :: kd_max = huge(1.0_wp)

Ceiling on tracer diffusivity kt/ks (m^2/s). Default huge = no clip.

integer, public :: kd_smooth_iterations = 0

1-2-1 horizontal smoothing passes on kv/kt at interfaces. Default 0 = off.

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

KPP unresolved-turbulence coefficient for the V_t^2 term in the bulk-Ri denominator (LMD94 eq 23). 0 disables V_t^2.

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

KPP 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 (LMD94 §3; MOM6 KPP_BULK_RI default 0.3).

real(kind=wp), public :: kv_max = huge(1.0_wp)

Ceiling on momentum viscosity kv (m^2/s). Default huge = no clip.

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

Extra near-surface vertical viscosity (m²/s) with a 1/(z·hmix)² profile in the top hmix_fixed metres. Zero (default) = no change.

real(kind=wp), public :: pp81_alpha = 5.0_wp

PP81 Richardson-number scaling coefficient (paper value 5; implementations vary 4-10).

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

PP81 background diffusivity (m^2/s). Also seeds vmix%kt_bg/vmix%ks_bg.

real(kind=wp), public :: pp81_nu0 = 1.0e-2_wp

PP81 Richardson-dependent viscosity scale (m^2/s).

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

PP81 background viscosity (m^2/s). Also seeds vmix%kv_bg (the assembly floor) — see vmix_seed_backgrounds.

real(kind=wp), public :: shear2_floor = 1.0e-10_wp

Floor on |du/dz|^2 + |dv/dz|^2 in the PP81 Ri denominator (1/s^2).

character(len=8), public :: tracer_recon = "ppm"

Face-reconstruction scheme for the WINDOWED horizontal tracer-advection drain (dt_tracer_advect_ratio > 1 path): ppm (default, CW-PPM, bit-identical) | weno5 | weno7 | weno9 (WENO-Z swept-average, rung-adaptive; reuses the coastal reconstruction ladder). Per-rung nghost minimum (weno5→3, weno7→4, weno9→5) is fail-loud at configure. This is the SEPARATE ocean knob — independent of the coastal tracer_recon.

logical, public :: use_closure = .true.

Master switch for the vmix (vertical-mixing) module. When .true. (default), the chosen interior closure (PP81) populates vmix%kv / vmix%kt from the local Richardson number and vdiff reads them. When .false., vdiff uses its scalar K_v_* defaults and vmix kernels never run.

logical, public :: use_kpp = .true.

KPP surface-boundary-layer overlay. Requires use_closure. Adds the cubic-profile kv overlay plus non-local γ_T/γ_S transport.

logical, public :: vmix_guard = .false.

Debug-gated negative/NaN diffusivity guard. Default off.

type, public ::  ocean_wave_speed_config_t

&ocean_wavespeed_nml: first-baroclinic wave speed + deformation radius. Diagnostic, default off — feeds GM/Redi/MEKE resolution scaling.

Components

Type Visibility Attributes Name Initial
logical, public :: enable = .false.

Master switch. Default off — bit-identity preserved.

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

DEFERRED: N^2-monotonising depth. < 0 = off.

integer, public :: n_wavespeed = 1

Recompute cadence (every N steps); slow diagnostic.

logical, public :: use_ebt = .false.

DEFERRED: equivalent-barotropic / pressure-Neumann variant.

type, public ::  ocean_wetdry_config_t

&ocean_wetdry_nml: dynamic wetting/drying for the split-explicit barotropic substep (docs/ocean_wetdry_plan.md). Default off ⇒ byte-identical everywhere (the wd_* workspaces stay unallocated and the substep runs its unmodified centred-face path).

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: dry_depth = 0.05_wp

Total-depth dry threshold (m): a column with D < dry_depth is dynamically dry (masked). Must be > 0.

logical, public :: enable = .false.

Master switch. When .true. the BT substep switches to upwind face thickness + the positive-definite outflow limiter + the bed-blocking momentum gate; requires sigma / zstar(-lite) vertical coordinates, &ocean_continuity_nml ppm_limit_pos, and single-rank (all fail-loud at configure).

real(kind=wp), public :: land_margin = 5.0_wp

Static-land headroom (m) above rest MSL, used ONLY when enable=.true. A column is STATIC LAND (metrics zeroed at configure) iff its bed is above the highest credible water level: b < -land_margin (b positive- down, so -land_margin is land_margin metres above rest MSL). Columns with -land_margin <= b < LAND_DEPTH_THRESHOLD are INTERTIDAL: they seed wet_mask=1 (real metrics) and the dynamic wd_wet_dyn gate handles their wetting/drying. Set to the expected tidal amplitude + surge. When enable=.false. this knob is inert (the LAND_DEPTH_THRESHOLD seed runs).

real(kind=wp), public :: rewet_depth = 0.10_wp

Hysteresis re-wet threshold (m): a dry column re-wets only when D > rewet_depth. Must be > dry_depth (kills wet/dry flip-flop chatter at the front).

type, public ::  ocean_zinit_config_t

Z-level T/S initial-condition overlay (&ocean_zinit_nml, capability A2). Reads pre-regridded T/S from a model-grid NetCDF and interpolates linearly in depth onto the seeded layer-centre depths, overwriting any analytical T/S. All defaults preserve bit-identity: enable = .false. is a no-op. Design + MOM6 divergences: local_archive/specs/a2_zinit_spec.md.

Components

Type Visibility Attributes Name Initial
logical, public :: enable = .false.

Master switch. Default .false. keeps the analytical IC. Requires RDB_ENABLE_NETCDF=ON at build time (the overlay lives in the NetCDF-gated rdb_ocean_z_init, including the source = "linear" path, which opens nothing).

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

Path to the model-grid T/S NetCDF (dims x/y/z; vars temp/salt/z_src with the documented name-fallbacks).

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

Fallback salinity (PSU) written to dry (wet_mask <= 0) columns. source = "file" only — the analytic path has a value everywhere and uses it.

real(kind=wp), public :: land_fill_t = 10.0_wp

Fallback temperature (°C) written to dry (wet_mask <= 0) columns.

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

source = "linear": dS/dz (PSU/m) with z positive UP. Note the polarity is the INVERSE of temperature’s: salty water belongs at the bed, so a halinely STABLE column has lin_ds_dz < 0. 0 (the default) is a uniform column.

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

source = "linear": dT/dz (degC/m) with z positive UP — the same convention as &ocean_ic_nml eady_dT_dz. A thermally STABLE column has lin_dt_dz > 0 (warm on top). 0 (the default) is a uniform column.

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

source = "linear": salinity (PSU) at the z = 0 datum.

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

source = "linear": temperature (degC) at the z = 0 datum.

character(len=32), public :: s_var = ""

Salinity variable-name override; “” tries salt/S/salinity.

character(len=32), public :: source = "file"

Where the T(z)/S(z) profile comes from.

Read more…
character(len=32), public :: t_var = ""

Temperature variable-name override; “” tries temp/T/temperature.

character(len=32), public :: z_var = ""

Source-axis variable-name override; “” tries z_src/z/depth/lev.

type, private ::  ocean_ddiff_config_t

Double diffusion (&ocean_ddiff_nml, CVMix_ddiff-style): salt fingering (Large et al. 1994) + diffusive convection (Marmorino-Caldwell 1976 / Kelley 1990). Folded INTO the heat/salt split (not a kv/kt contributor) to give an asymmetric ks-vs-kt divergence. Defaults are the CVMix defaults; enable = .false. keeps the path bit-identical. Knob table: docs/generated_nml_knobs.md.

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: ddiff_exp1 = 1.0_wp

Inner (bracket) fingering exponent (CVMix DDIFF_EXP1).

real(kind=wp), public :: ddiff_exp2 = 3.0_wp

Outer fingering exponent (CVMix DDIFF_EXP2); exp1=1,exp2=3 is the Large et al. cubic.

logical, public :: enable = .false.

Master switch (MOM6 USE_CVMIX_DDIFF). Requires thermo%enable_thermodynamics (validated at configure).

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

Leading salt-fingering salinity diffusivity K_f (CVMix KAPPA_DDIFF_S), m^2/s. K_T = 0.7*K_S.

real(kind=wp), public :: mol_diff = 1.5e-6_wp

Molecular diffusivity scaling the convection branch (CVMix MOL_DIFF), m^2/s – the molecular value, not a background eddy.

real(kind=wp), public :: param1 = 0.909_wp

MC76 convection exterior coeff (CVMix KAPPA_DDIFF_PARAM1).

real(kind=wp), public :: param2 = 4.6_wp

MC76 convection middle coeff (CVMix KAPPA_DDIFF_PARAM2).

real(kind=wp), public :: param3 = -0.54_wp

MC76 convection interior coeff (CVMix KAPPA_DDIFF_PARAM3).

real(kind=wp), public :: strat_param_max = 2.55_wp

R_rho salt-fingering cutoff (CVMix STRAT_PARAM_MAX), nondim.

logical, public :: use_k90 = .false.

Convection form: .false. = Marmorino-Caldwell 1976 (default), .true. = Kelley 1990.

type, private ::  ocean_debug_config_t

&ocean_debug_nml: forensic probes for the ocean dyn-core. Every knob defaults off ⇒ bit-identical (untaken branches); all are HEAVY when on (device waits / serialised apply chains) — investigation tools, not production diagnostics. Output is greppable fixed-format rows (BUDGET / KE_ATTR / CHKSUM / HOTFACE); reader: tools/read_chksum.py.

Components

Type Visibility Attributes Name Initial
logical, public :: budget = .false.

Per-stage BT power-budget probe (BUDGET rows).

logical, public :: chksum = .false.

MOM6-style per-phase field checksums (CHKSUM rows) + the HOTFACE argmax-face anatomy at the tendency seams — the first-diverging-operator / non-finite-minting attribution probe. Device waits + reductions per phase seam.

integer, public :: chksum_end_step = 0

Last outer step the chksum probe samples (0 = no upper bound).

logical, public :: chksum_interior = .false.

Restrict every chksum reduction to PHYSICAL cells (drop the ghost ring). Default .false. = legacy whole-array output.

Read more…
integer, public :: chksum_start_step = 0

First outer step the chksum probe samples (0 = from start).

logical, public :: ke_attr = .false.

Per-segment layer-KE attribution meter (KE_ATTR rows) — serialises the velocity-apply chain while sampling.

integer, public :: ke_attr_end_step = 0

Last outer step the KE meter samples (0 = no upper bound).

integer, public :: ke_attr_start_step = 0

First outer step the KE meter samples (0 = from start).

type, private ::  ocean_forcing_config_t

&ocean_forcing_nml: PR-12 surface-flux component-set gate. Default OFF ⇒ bit-identical (no component array allocated, no assembler kernel runs; ocean_surface_flux_t%Q_heat/Q_salt are filled exactly as &ocean_thermo_nml always has).

Components

Type Visibility Attributes Name Initial
logical, public :: enable_components = .false.

Allocate the surface-flux component set (q_sw, evap, heat_content_*, …) on ocean_surface_flux_t and run ocean_surface_flux_assemble every thermo step to derive Q_heat/Q_salt from it. Individual components carry no knobs of their own — they are filled by fillers (readers, the ice coupler, …), not by this namelist.

type, private ::  ocean_redi_config_t

&ocean_redi_nml: Redi continuous neutral (along-isopycnal) tracer diffusion — the rotated diffusion tensor. Default off ⇒ no neutral flux.

Components

Type Visibility Attributes Name Initial
logical, public :: continuous = .true.

Continuous variant (closed-form linear neutral surfaces, the production path). .false. (discontinuous) DEFERRED, rejected at configure.

logical, public :: enable = .false.

Master switch. Default off ⇒ no-op ⇒ bit-identical.

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

Redi neutral diffusivity KhTr (m^2/s; production 1e2-1e3). 0 ⇒ no neutral flux even when enabled.

type, private ::  ocean_slopes_config_t

&ocean_slopes_nml: isopycnal (neutral) slope diagnostics (Griffies 1998) at C-grid interfaces. Foundational gate for GM/Redi/VarMix. Default off ⇒ no-op.

Components

Type Visibility Attributes Name Initial
logical, public :: enable = .false.

Master switch. Default off ⇒ ocean_slopes_compute no-ops.

real(kind=wp), public :: kd_smooth = 1.0e-6_wp

Vert-fill smoothing diffusivity, m^2/s (× dt fills massless layers before the gradients are formed).

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

Minimum layer thickness, m, floored in the N² / drdz denominator so vanished layers don’t spike the slope.


Functions

public pure function bbl_glue_is_effective(cfg) result(on)

Will &ocean_vdiff_nml bbl_glue actually be ON after setup?

Read more…

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg

Return Value logical

public pure function cavity_draft_is_uniform(cfg) result(uniform)

Is the configured ice-shelf draft UNIFORM over the whole array?

Read more…

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg

Return Value logical

public pure function dataovr_any_tag_set(cfg) result(any_set)

.true. when at least one tag names a file, i.e. enabling the group would actually do something.

Arguments

Type IntentOptional Attributes Name
type(ocean_dataovr_config_t), intent(in) :: cfg

Return Value logical

public pure function dataovr_entry_is_valid(e) result(ok)

.true. unless a tag names a file without naming the variable inside it. A blank file (tag not file-driven) is valid, and a var with no file is harmless — the tag simply never registers — so only the one combination is rejected.

Arguments

Type IntentOptional Attributes Name
type(dataovr_entry_config_t), intent(in) :: e

Return Value logical

public pure function dataovr_freshwater_needs_components(cfg, use_components) result(bad)

.true. when evap/lprec are file-driven but the surface-flux component set they write into is switched off. Note the polarity: this reports the PROBLEM, not validity — named for how it reads at the call site.

Arguments

Type IntentOptional Attributes Name
type(ocean_dataovr_config_t), intent(in) :: cfg
logical, intent(in) :: use_components

Return Value logical

public pure function dataovr_time_is_valid(cfg) result(ok)

.true. unless time_mode='cyclic' was requested without a positive cycle_period. Checked only for the cyclic mode; cycle_period is ignored by linear/static.

Arguments

Type IntentOptional Attributes Name
type(ocean_dataovr_config_t), intent(in) :: cfg

Return Value logical

public pure function diag_density_levels_ok(vgrid, diags, n_rho_levels, rho_levels) result(ok)

.true. iff a density-coordinate diagnostic selection (global vgrid='density', or a per-diagnostic :density/:rho attribute anywhere in diags) has a usable rho_levels axis: at least one entry, strictly increasing (invert_density_targets assumes a monotone light->dense target list), and within the declared MAX_OCEAN_DIAG_Z_LEVELS array bound. Unlike sigma/z*, density bins have no auto-fill, so an unset axis must abort rather than silently size to zero. When density is not requested at all this is unconditionally .true. (no constraint).

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: vgrid
character(len=*), intent(in) :: diags
integer, intent(in) :: n_rho_levels
real(kind=wp), intent(in) :: rho_levels(:)

Return Value logical

public pure function ice_hlim_count(hlim) result(n)

Length of the LEADING run of non-sentinel (>= 0) entries in &ocean_ice_nml hlim (PR-58). Contiguity matters here (unlike apply_layer_rho_init’s bare count(>= 0)): a value AFTER the first sentinel is silently dropped by this count, so ice_hlim_spec_is_valid checks contiguity explicitly rather than trusting the count alone.

Arguments

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

Return Value integer

public pure function ocean_bt_forcing_visc_rem_on(cfg) result(on)

PR-3 (D1): is the MOM6 wt_u BT-forcing weight on, either directly (forcing_visc_rem) or via visc_rem_chain?

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg

Return Value logical

public pure function ocean_bt_rem_from_visc_rem_on(cfg) result(on)

PR-3 (D1): is bt_rem built from av_rem (MOM6’s barotropic viscous-remnant depth mean) on, either directly (bt_rem_from_visc_rem) or via visc_rem_chain?

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg

Return Value logical

public pure function ocean_bt_renorm_visc_rem_on(cfg) result(on)

PR-3 (D1): is the MOM6 continuity u_cor = u + du*visc_rem transport-matching renormaliser on, either directly (renorm_visc_rem) or via visc_rem_chain?

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg

Return Value logical

public pure function ocean_bt_visc_rem_producer_on(cfg) result(on)

D1 follow-up: is the visc_rem PRODUCER needed, independent of the (retired) weighted BT-correction fold? .true. whenever ANY real consumer is on — forcing_visc_rem/renorm_visc_rem/ bt_rem_from_visc_rem (each already .or.-ed with visc_rem_chain by their own helper) — or the legacy correction_visc_rem field itself, so a test that constructs cfg directly and sets that field alone (bypassing the nml retirement check) still gets a live producer. This is what configure_ocean_bt wires into bt_work%bt_visc_rem_producer, which vmix_apply_in_stage’s do_remnant reads — NOT bt_work%bt_correction_visc_rem, which now drives ONLY the weighted-fold dispatch in apply_bt_correction (and is never set by visc_rem_chain).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg

Return Value logical

public pure function p_top_has_producer(cfg) result(has)

Is there anything in this configuration that WRITES multilayer_state_t%p_top?

Read more…

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg

Return Value logical

public pure function resolve_bt_halo(requested, compute_size, exclusion_active) result(width)

Resolve the &ocean_bt_nml bt_halo sentinel to a concrete march-in width. requested == BT_HALO_AUTO_SENTINEL (-1, the default) => AUTO: 0. The march-in used to switch itself on (BT_HALO_AUTO_WIDTH) on every compatible multi-rank run. It is not bit-reproducible against the serial run over variable bathymetry or with open boundaries (test_ocean_decomp_bitid_mpi), so a default multi-rank run must not pick it: AUTO is off, serial or not. requested >= 0 (user set it explicitly) => returned UNCHANGED; the fail-loud exclusion checks in validate_config police an explicit bt_halo > 0 against an incompatible feature (user asked for the impossible), so the auto-resolution never overrides an explicit 0 or an explicit width. compute_size / exclusion_active no longer change the answer; they stay so the call site (and its exclusion log) keeps its shape for the day the march-in is exact again.

Arguments

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

The namelist value: BT_HALO_AUTO_SENTINEL (-1) for auto, else >= 0.

integer, intent(in) :: compute_size

Number of compute ranks (1 = serial). Unused by AUTO (see above).

logical, intent(in) :: exclusion_active

.true. iff any march-in exclusion feature is on (see bt_halo_auto_exclusion). Unused by AUTO (see above).

Return Value integer

public pure function substep_drag_ignores_bdrag_form(cfg) result(ignores)

Is &ocean_bt_nml substep_drag blind to the configured bottom drag?

Read more…

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg

Return Value logical

public pure function zfixed_cavity_nu_h_below_envelope(cfg) result(below)

Is the constant harmonic viscosity below the z_fixed x cavity lower envelope ZFIXED_CAVITY_NU_H_MIN? The predicate behind validate_config’s WARNING (never a refusal — the vcoord stability matrix runs this combination inviscid on purpose).

Read more…

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg

Return Value logical

private pure function forcing_components_need_thermo(enable_components, enable_thermodynamics) result(bad)

&ocean_forcing_nml enable_components=.true. with &ocean_thermo_nml enable_thermodynamics=.false. is a configuration that validates but does nothing (the component set only feeds the assembler->apply_tracers thermo path) — named predicate per the lateral_closure_is_implemented idiom so validate_config reads as one line.

Arguments

Type IntentOptional Attributes Name
logical, intent(in) :: enable_components
logical, intent(in) :: enable_thermodynamics

Return Value logical

private pure function sponge_ramp_is_valid(tag) result(ok)

.true. iff &ocean_sponge_nml ramp names a band shape the damp_source="band" filler implements.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: tag

Return Value logical

private pure function sponge_source_is_implemented(tag) result(ok)

.true. iff &ocean_sponge_nml damp_source names a source that is actually filled. "file" is a recognised name (PR-23b, needs the PR-14 reader) but has no kernel yet — a source with no filler must abort, not silently build an all-zero map (the lateral_closure_is_implemented idiom).

Read more…

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: tag

Return Value logical

private pure function sponge_target_is_implemented(tag) result(ok)

.true. iff &ocean_sponge_nml target_source names a reference state that is actually filled: "ic" (snapshot of the seeded initial condition) or "linear_z" (analytic affine geopotential profile, re-evaluated on the live layer geometry). "file" is recognised but has no reader yet (PR-23b).

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: tag

Return Value logical


Subroutines

public pure subroutine bt_halo_auto_exclusion(cfg, excluded, reason)

Single source of truth for the BT march-in exclusion set (mirrors the explicit-bt_halo > 0 fail-loud checks in validate_config). Reports whether ANY exclusion is active and names the first one (for the AUTO resolution log). When none is active, reason is “”.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg
logical, intent(out) :: excluded
character(len=:), intent(out), allocatable :: reason

public subroutine build_rdb_schema(cfg, schema)

Register the validated groups + the still-external groups onto schema, capturing defaults from cfg.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(out) :: schema

public pure subroutine ice_hlim_spec_is_valid(hlim, ncat, ok, reason)

Shape/monotonicity predicate for a supplied &ocean_ice_nml hlim list (PR-58). A SUBROUTINE, not a function — a pure FUNCTION may not carry an intent(out) dummy (reason); pure SUBROUTINES can. n = ice_hlim_count(hlim); ok iff ALL of: (a) n >= 2 – one edge gives no width to extrapolate (SIS2 divergence D1: Roundabout fails loud here instead of SIS2’s silent fallback to the default table). (b) n <= ncat + 1 – more edges than the ITD has bins. (c) all(hlim(n+1:) < 0) – contiguity: no value after the first sentinel. (d) hlim(1) > 0 – mh_lim(1) > 0 is a live gate (rdb_ice_itd ice_adjust_categories). (e) hlim(k+1) > hlim(k), k = 1..n-1 – strictly increasing. Checking (d)+(e) on the SUPPLIED list is sufficient for the FULL h_lim(1..ncat+1): the constant-width extrapolation preserves both properties by induction (h_lim(k)-h_lim(k-1) = h_lim(k-1)-h_lim(k-2)), so no redundant post-extrapolation check is needed.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: hlim(:)
integer, intent(in) :: ncat
logical, intent(out) :: ok
character(len=:), intent(out), allocatable :: reason

public subroutine read_config(filename, cfg, schema, ierr)

Read simulation configuration from a namelist file.

Read more…

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: filename

Path to the namelist input file

type(config_t), intent(out), target :: cfg

Populated configuration

type(nml_schema_t), intent(out), optional :: schema

Built + parsed schema (aliases into cfg); for doc dumps.

integer, intent(out), optional :: ierr

Non-zero on a strict-parse failure (unknown group/key, range/enum violation) when present; absent behaves as today (error stop).

public subroutine read_config_from_string(text, cfg, schema, ierr)

In-memory sibling of read_config: build + strict-parse + apply a namelist held entirely in the text buffer (newline- separated), with NO filesystem touch — no temp file, no chdir, no cleanup. Same validation behaviour as the file path (the schema parser and the native &ocean_bc_nml read both run from the in-memory line array); same error stop default and same optional non-aborting ierr as read_config.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: text

Whole namelist as one string (records separated by ‘\n’).

type(config_t), intent(out), target :: cfg
type(nml_schema_t), intent(out), optional :: schema
integer, intent(out), optional :: ierr

Non-zero on a strict-parse failure when present; absent behaves as today (error stop). The natural FFI/create() door: a bad namelist string becomes a returned status instead of aborting the host process.

public subroutine validate_config(cfg, ierr)

Validate configuration parameters after reading

Read more…

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in) :: cfg
integer, intent(out), optional :: ierr

Non-zero on any cross-knob semantic validation failure when present; absent behaves as today (error stop).

private subroutine add_dataovr_entry(g, e, tag, what, units)

Register the four flat knobs of one &ocean_dataovr_nml tag. e is target, intent(in) for the same reason cfg is in every register_ocean_* above: the schema stores a pointer to the target and assigns through it at parse time, and the actual argument is always a component of the target cfg, so the association outlives this call.

Arguments

Type IntentOptional Attributes Name
type(nml_group_t), intent(inout) :: g
type(dataovr_entry_config_t), intent(in), target :: e
character(len=*), intent(in) :: tag
character(len=*), intent(in) :: what
character(len=*), intent(in) :: units

private subroutine apply_cartesian_degrees(cfg)

Post-parse Cartesian domain sizing (MOM6 GRID_CONFIG=”cartesian” + AXIS_UNITS / LENLON / LENLAT). When &ocean_grid_nml len_lon/len_lat are set (> 0) on an ocean Cartesian grid, DERIVE the uniform &grid_nml dx/dy (metres) from the domain extent, the physical cell count (nx/ny = MOM6 NIGLOBAL/NJGLOBAL) and axis_units, exactly as MOM6’s set_grid_metrics_cartesian: degrees : dx = rad_earth · len_lon · π/180 / nx (arc length, no cos(lat)) km : dx = 1000 · len_lon / nx meters : dx = len_lon / nx and likewise dy from len_lat / ny. This runs BEFORE grid init, so the metrics, barotropic CFL and Coriolis all see the derived metres. Default (len_lon <= 0) leaves dx/dy untouched ⇒ bit-identical.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(inout) :: cfg

private subroutine apply_time_unit_cascade(cfg)

Post-parse time-unit fixup shared by the file + string config paths. t_end, status_interval, ocean_diag%dt_out are given in time_unit from &time_nml; multiply through to SI seconds. dt_fixed/dt_max stay in seconds; default time_unit="s" gives a 1× factor (bit-identical to before).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(inout) :: cfg

private subroutine check_dataovr_file(e, tag, has_error)

Existence check for one tag’s file. NOT pure — inquire is an I/O statement, which is exactly why this is a subroutine setting has_error rather than another predicate: the pure ones above stay pure and independently testable, and this keeps the filesystem dependency in one visible place. Silent for a tag that names no file.

Arguments

Type IntentOptional Attributes Name
type(dataovr_entry_config_t), intent(in) :: e
character(len=*), intent(in) :: tag
logical, intent(inout) :: has_error

private subroutine read_config_from_string_impl(text, cfg, sch, ierr)

Body of read_config_from_string — mirrors read_config_impl with the line array replacing the file unit.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: text
type(config_t), intent(out), target :: cfg
type(nml_schema_t), intent(out) :: sch
integer, intent(out), optional :: ierr

Non-zero on a strict-parse failure when present; absent behaves as today (error stop).

private subroutine read_config_impl(filename, cfg, sch, ierr)

Body of read_config: build the strict schema (capturing defaults from the pristine cfg field initialisers), parse the file (validate + apply straight into cfg), run the post-parse time-unit cascade.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: filename

Path to the namelist input file

type(config_t), intent(out), target :: cfg

Populated configuration

type(nml_schema_t), intent(out) :: sch

Built + parsed schema (aliases into cfg)

integer, intent(out), optional :: ierr

Non-zero on a strict-parse failure when present; absent behaves as today (error stop).

private subroutine register_boundary(cfg, schema)

&boundary_nml: per-side BC types, tidal forcing, inflow/ discharge/clamped/sponge/nesting parameters. The four bc_* keys are enums over the bc_type_from_string accepted set.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_conv(cfg, schema)

&ocean_conv (Brunt-Vaisala-triggered convective adjustment, CVMix_conv-style).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ddiff(cfg, schema)

&ocean_ddiff (double diffusion: salt fingering + diffusive convection, CVMix_ddiff-style).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_epbl(cfg, schema)

&ocean_epbl (Reichl & Hallberg 2018 energetics-based PBL).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_foxkemper(cfg, schema)

&ocean_foxkemper (Fox-Kemper et al. 2008/2011 mixed-layer-eddy restratification, capability B5).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_gm(cfg, schema)

&ocean_gm (Gent-McWilliams thickness diffusion, capability [2]).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_grid(cfg, schema)

&grid_nml: structured-grid geometry.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_initial_condition(cfg, schema)

&initial_condition_nml: coastal IC selector + parameters.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_kappa_shear(cfg, schema)

&ocean_kappa_shear (JHL08 shear-driven interior mixing). Exclusive > 0 bounds (ri_crit, kappa_0, tol_err, prandtl_turb) are left to the configure-time strict checks.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_logging(cfg, schema)

&logging_nml: logger verbosity + status cadence.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_meke(cfg, schema)

&ocean_meke (prognostic mesoscale eddy kinetic energy, [5]).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_mpi(cfg, schema)

&mpi_nml: MPI domain decomposition.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_nonhydrostatic(cfg, schema)

&nonhydrostatic_nml: NH/multilayer switches, CG-Poisson controls, PP81 vmix, KPP knobs, k-eps, Smagorinsky, BPG, mode split. keps_stability and bpg_method are enums.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_bc(cfg, schema)

&ocean_bc_nml: open-boundary condition config (P4.5 migration off the hand-rolled read_ocean_bc_nml). All defaults reproduce a closed-wall run (bit-identical to nmls that omit this block). The west/east/south/north edge-type enum lists every arm of ocean_bc_type_from_string (rdb_ocean_boundary_types.F90), not just the subset named in the config-type docstring — that function is what the parsed string is actually fed to, and the native reader accepted (and validate_config did not reject) any of its arms on any edge, so the schema must not narrow that.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_bdrag(cfg, schema)

&ocean_bdrag_nml: bottom-drag selector + coefficients. form enum mirrors parse_bdrag_variant in rdb_ocean_bottom_drag.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_bt(cfg, schema)

&ocean_bt_nml: split-explicit barotropic substep controls.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_cavity_dyn(cfg, schema)

&ocean_cavity_dyn (P5.1 static ice-shelf cavity geometry: the prescribed draft + the barotropic datum that absorbs it).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_cavity_melt(cfg, schema)

&ocean_cavity_melt (P2b ice-shelf basal-melt thermodynamics: the three-equation interface, its exchange law and the far-field sampling depth). The exchange_law and ice_conduction enums MIRROR parse_cavity_exchange_law / parse_cavity_ice_mode in rdb_ocean_cavity_melt — the two lists move together, and validate_config re-checks them belt-and-braces so a RESERVED law is refused by name rather than silently falling through the kernel’s dispatch.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_continuity(cfg, schema)

&ocean_continuity_nml: continuity-PPM positivity controls.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_coriolis(cfg, schema)

&ocean_coriolis_nml: Coriolis-advection scheme selector. form enum mirrors parse_pv_variant in rdb_coriolis_adv (canonical names; short aliases hk/energy are not advertised).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_data(cfg, schema)

&ocean_data_nml: the shared time-varying NetCDF input reader (PR-14). Two knobs, no per-field entries — see ocean_data_config_t. Registration of individual (file, variable, destination) triples is programmatic, via each consumer’s own namelist group calling ocean_data_input_register_2d/_3d at setup.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_dataovr(cfg, schema)

&ocean_dataovr_nml: file-backed surface forcing (PR-15). Flat per-tag knobs (<tag>_file, <tag>_var, <tag>_scale, <tag>_add) rather than a MOM6-style parallel-array data table — the schema engine has no string-array key type, and the set of recognised tags is fixed by the slots they feed, so a flat layout is both expressible today and self-documenting in docs/generated_nml_knobs.md.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_debug(cfg, schema)

&ocean_debug_nml: forensic probes (all heavy, all default off).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_diag(cfg, schema)

&ocean_diag_nml: ocean diag-manager output controls. dt_out is interpreted in time_unit and converted by the post-parse cascade in read_config. vgrid enum is {layer, z_fixed}.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_eos(cfg, schema)

&ocean_eos_nml: equation-of-state variant selector, the freezing-point (liquidus) coefficient set, and the potential-density reference pressure. eos enum mirrors parse_eos_variant in rdb_eos; tfreeze_set mirrors parse_tfreeze_set in the same module.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_forcing(cfg, schema)

&ocean_forcing_nml: surface-flux component-set gate (PR-12). One knob, deliberately — components are filled by fillers, not by scalar namelist knobs (that would be a knob-per-component, all dead in v1).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_geothermal(cfg, schema)

&ocean_geothermal_nml: geothermal bottom-heat-flux switch + scalar flux. Bed-side analogue of the surface heat flux.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_grid(cfg, schema)

&ocean_grid_nml: horizontal-grid generator + geometry (curvilinear-grid stream). grid_config / coriolis_scheme enums mirror parse_grid_config / parse_coriolis_scheme in rdb_ocean_metrics.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_hdiff(cfg, schema)

&ocean_hdiff_nml: along-coordinate tracer Laplacian (rdb_ocean_hdiff_tracer). Not the neutral/isopycnal path — that is &ocean_redi_nml, already reachable.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_hvisc(cfg, schema)

&ocean_hvisc_nml: lateral-viscosity closure + coefficients. lateral_closure enum mirrors parse_lateral_closure in rdb_ocean_lateral_mix.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_ic(cfg, schema)

&ocean_ic_nml: initial-condition overlay + EOS reference state. ic_config enum mirrors the IC dispatch in rdb_ocean_state (default “” keeps the analytical T(z) IC).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_ice(cfg, schema)

&ocean_ice_nml: sea-ice model switch + category/layer counts (SIS2 port scaffold) + the PR-3c v1 restoring atmospheric-forcing scalars. Default off ⇒ byte-identical.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_ice_ic(cfg, schema)

&ocean_ice_ic_nml: sea-ice ANALYTIC initial-condition path (PR 24). Default conc_config="zero" ⇒ byte-identical. "file" is deliberately NOT in the allowed= list — file-backed ICs are PR-14 (v1.1), out of scope here.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_isopycnal(cfg, schema)

&ocean_isopycnal_nml: grounding-stability controls for the Lagrangian vertical coordinate.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_mpi(cfg, schema)

&ocean_mpi_nml: multi-rank MPI debug / tuning controls.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_pgf(cfg, schema)

&ocean_pgf_nml: pressure-gradient-force kernel selector + knobs. form enum mirrors parse_opgf_variant in rdb_ocean_pressure_force.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_psurf(cfg, schema)

&ocean_psurf (PR-17 atmospheric surface-pressure loading / inverse barometer).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_restore(cfg, schema)

&ocean_restore_nml: surface buoyancy restoring (MOM6 RESTOREBUOY). Piston-velocity relaxation of top-layer T / S toward scalar targets. Default OFF ⇒ bit-identical.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_sponge(cfg, schema)

&ocean_sponge_nml: the map-driven sponge (PR-23). Default enable = .false. ⇒ the legacy &ocean_bc_nml band kernels run unchanged ⇒ bit-identical. No damp_max / idamp_file / *_var keys in v1 — those validate and do nothing until PR-23b adds their consumer (CLAUDE.md trap class “dead knobs”).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_tdrag(cfg, schema)

&ocean_tdrag_nml: ice-shelf TOP-drag selector + coefficients. form enum mirrors parse_tdrag_variant in rdb_ocean_top_drag.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_thermo(cfg, schema)

&ocean_thermo_nml: thermodynamics switch + scalar surface fluxes.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_tides(cfg, schema)

&ocean_tides (C1 equilibrium astronomical body-force tide).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_topo(cfg, schema)

&ocean_topo_nml: basin geometry + surface forcing + Coriolis tilt. topo_config / wind_config enums mirror the dispatch select-cases in rdb_ocean_state / rdb_ocean_setup.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_tracers(cfg, schema)

&ocean_tracers_nml: prognostic-tracer registry switches.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_vdiff(cfg, schema)

&ocean_vdiff_nml: backward-Euler vertical-friction folding knobs.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_vmix(cfg, schema)

&ocean_vmix_nml: vertical-mixing module switches + knobs.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_wetdry(cfg, schema)

&ocean_wetdry_nml: dynamic wetting/drying for the BT substep. Design + validation numbers: docs/ocean_wetdry_plan.md.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_ocean_zinit(cfg, schema)

&ocean_zinit_nml: z-level T/S initial-condition overlay (A2). Default enable = .false. is a no-op (analytical IC unchanged).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_output(cfg, schema)

&output_nml: file output + I/O + forcing/restart/gauge files.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_physics(cfg, schema)

&physics_nml: barotropic physics + bottom drag + wind stress.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_porous(cfg, schema)

&ocean_porous (Adcroft 2013 porous barriers: subgrid sill/strait narrowing of the C-grid transport face widths).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_redi(cfg, schema)

&ocean_redi (continuous neutral / along-isopycnal tracer diffusion, capability [3]).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_sim(cfg, schema)

&sim_nml: the simulation regime selector.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_slopes(cfg, schema)

&ocean_slopes (Griffies 1998 isopycnal-slope diagnostics).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_tidal_mixing(cfg, schema)

&ocean_tidal_mixing (St-Laurent/Simmons internal-tide mixing).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_time(cfg, schema)

&time_nml: time-integration controls. t_end is interpreted in time_unit and converted to seconds by the post-parse cascade in read_config; dt_fixed/dt_max stay in seconds. time_unit is a plain string (the cascade validates its set).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_tracer(cfg, schema)

&tracer_nml: salinity + temperature IC/EOS/bounds + sediment.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_varmix(cfg, schema)

&ocean_varmix (spatially-varying GM/Redi coefficients, [4]).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_vcoord(cfg, schema)

&vcoord_nml: vertical-coordinate + ALE-remap controls. vcoord_type / remap_method / zstar_stretching are enums with the canonical sets accepted by the rdb_vcoord parsers.

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine register_wavespeed(cfg, schema)

&ocean_wavespeed (B1 first-baroclinic wave speed + Rd).

Arguments

Type IntentOptional Attributes Name
type(config_t), intent(in), target :: cfg
type(nml_schema_t), intent(inout) :: schema

private subroutine split_to_lines(text, lines, n_lines)

Split a newline-separated buffer into a fixed-len character array (one record per line, trailing CR stripped) for internal-file reads + the schema line walker.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: text
character(len=:), intent(out), allocatable :: lines(:)
integer, intent(out) :: n_lines

private subroutine warn_unknown_bc(bc_str, param_name)

Warn if a BC string does not match any known type

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: bc_str
character(len=*), intent(in) :: param_name