ocean_cavity_melt_config_t Derived Type

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).

GEOMETRY IS A DIFFERENT GROUP. The draft, the cover mask and the barotropic datum are &ocean_cavity_dyn_nml’s, and this group REQUIRES it: without a draft there is no interface to melt and cover_frac is identically zero. The split is the per-concern sub-namelist convention, and it is also the honest one — a datum-only cavity run is a legitimate configuration.

VIRTUAL OR REAL MASS — freshwater picks (Phase 3). "virtual" (default, bit-identical) delivers the meltwater as a virtual salt flux at fixed column mass; "mass" adds the real Boussinesq volume to the top layer and lets the dilution happen by itself. See that knob, and docs/CAPABILITIES_AND_LIMITATIONS.md.

enable = .false. (default) ⇒ no slot arrays, no kernel, no component written, byte-identical. Knob table: docs/generated_nml_knobs.md.


Inherited by

type~~ocean_cavity_melt_config_t~~InheritedByGraph type~ocean_cavity_melt_config_t ocean_cavity_melt_config_t type~ocean_config_t ocean_config_t type~ocean_config_t->type~ocean_cavity_melt_config_t cavity_melt type~config_t config_t type~config_t->type~ocean_config_t ocean type~ocean_handle_t ocean_handle_t type~ocean_handle_t->type~config_t cfg

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: 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.

"virtual" (default ⇒ bit-identical) — no mass moves. The dilution is emulated at FIXED column mass by the exact fixed-mass equivalent salt flux -m*(S_far - s_ice) (derivation in rdb_ocean_cavity_flux’s module docstring).

"mass" — the meltwater is a REAL Boussinesq VOLUME source on the top layer, dh = m*dt/rho_0, and the salinity falls by dilution on its own. The virtual salt flux is then NOT also applied to the tracer (that would double-count); it is RETAINED in the assembled Q_salt solely as the surface buoyancy forcing KPP/EPBL read for B_0, and removed again from salinity (and from the pseudo-salt mirror) by the same in-stage kernel that adds the volume. The top layer’s heat additionally gains the enthalpy of the added water, m*c_w*T_b.

"mass" is refused (fail loud, naming the follow-up) together with dynamic wet/dry and with a windowed tracer-advection ratio > 1.

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".

"none" (default) — nothing; the domain fills up. Correct for a short run and for a domain with an open boundary that can pass the volume out.

"uniform_open_ocean" — each thermo step the domain-integrated melt volume is removed again, spread UNIFORMLY (per unit area) over the wet cells the ice does NOT cover, each parcel carrying that cell’s own T and S so no concentration there is changed. Tracked as a mass, salt and heat SINK in all three console budgets. This is the sea-level compensation ISOMIP+ Sect. 3.1.3 allows for the closed Ocean3/4 domains; Ocean0-2 have a restoring sponge that does not remove volume, so without it their cavity fills at metres per year.


Source Code

   type :: 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`).
      !!
      !! GEOMETRY IS A DIFFERENT GROUP.  The draft, the cover mask and
      !! the barotropic datum are `&ocean_cavity_dyn_nml`'s, and this
      !! group REQUIRES it: without a draft there is no interface to melt
      !! and `cover_frac` is identically zero.  The split is the
      !! per-concern sub-namelist convention, and it is also the honest
      !! one — a datum-only cavity run is a legitimate configuration.
      !!
      !! VIRTUAL OR REAL MASS — `freshwater` picks (Phase 3).
      !! `"virtual"` (default, bit-identical) delivers the meltwater as a
      !! virtual salt flux at fixed column mass; `"mass"` adds the real
      !! Boussinesq volume to the top layer and lets the dilution happen
      !! by itself.  See that knob, and
      !! `docs/CAPABILITIES_AND_LIMITATIONS.md`.
      !!
      !! `enable = .false.` (default) ⇒ no slot arrays, no kernel, no
      !! component written, byte-identical.  Knob table:
      !! `docs/generated_nml_knobs.md`.
      logical :: 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) :: 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(wp) :: 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.
      real(wp) :: 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(wp) :: 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.
      real(wp) :: 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(wp) :: 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) :: 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(wp) :: 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(wp) :: 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(wp) :: 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) :: freshwater = "virtual"
         !! How the meltwater reaches the ocean.
         !!
         !! `"virtual"` (**default ⇒ bit-identical**) — no mass moves.
         !! The dilution is emulated at FIXED column mass by the exact
         !! fixed-mass equivalent salt flux `-m*(S_far - s_ice)`
         !! (derivation in `rdb_ocean_cavity_flux`'s module docstring).
         !!
         !! `"mass"` — the meltwater is a REAL Boussinesq VOLUME source
         !! on the top layer, `dh = m*dt/rho_0`, and the salinity falls
         !! by dilution on its own.  The virtual salt flux is then NOT
         !! also applied to the tracer (that would double-count); it is
         !! RETAINED in the assembled `Q_salt` solely as the surface
         !! buoyancy forcing KPP/EPBL read for `B_0`, and removed again
         !! from salinity (and from the pseudo-salt mirror) by the same
         !! in-stage kernel that adds the volume.  The top layer's heat
         !! additionally gains the enthalpy of the added water,
         !! `m*c_w*T_b`.
         !!
         !! `"mass"` is refused (fail loud, naming the follow-up)
         !! together with dynamic wet/dry and with a windowed
         !! tracer-advection ratio > 1.
      character(len=32) :: volume_compensation = "none"
         !! What to do with the volume `freshwater="mass"` adds to a
         !! CLOSED domain.  Requires `freshwater="mass"`.
         !!
         !! `"none"` (default) — nothing; the domain fills up.  Correct
         !! for a short run and for a domain with an open boundary that
         !! can pass the volume out.
         !!
         !! `"uniform_open_ocean"` — each thermo step the
         !! domain-integrated melt volume is removed again, spread
         !! UNIFORMLY (per unit area) over the wet cells the ice does
         !! NOT cover, each parcel carrying that cell's own T and S so
         !! no concentration there is changed.  Tracked as a mass, salt
         !! and heat SINK in all three console budgets.  This is the
         !! sea-level compensation ISOMIP+ Sect. 3.1.3 allows for the
         !! closed Ocean3/4 domains; Ocean0-2 have a restoring sponge
         !! that does not remove volume, so without it their cavity
         !! fills at metres per year.
   end type ocean_cavity_melt_config_t