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.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public | :: | cdrag_top | = | 2.5e-3_wp |
Top drag coefficient |
|
| logical, | public | :: | enable | = | .false. |
Master switch. Requires |
|
| character(len=32), | public | :: | exchange_law | = | "const_gamma" |
Turbulent exchange-velocity law. |
|
| real(kind=wp), | public | :: | far_field_depth | = | 10.0_wp |
Thickness (m) below the ice base over which the far-field
|
|
| character(len=16), | public | :: | freshwater | = | "virtual" |
How the meltwater reaches the ocean.
|
|
| real(kind=wp), | public | :: | gamma_s | = | -1.0_wp |
Dimensionless salt-transfer coefficient |
|
| real(kind=wp), | public | :: | gamma_t | = | 2.2e-2_wp |
Dimensionless heat-transfer coefficient |
|
| character(len=32), | public | :: | ice_conduction | = | "insulating" |
Ice-side heat conduction. |
|
| real(kind=wp), | public | :: | s_ice | = | 0.0_wp |
Ice salinity (g/kg), |
|
| real(kind=wp), | public | :: | t_ice | = | -25.0_wp |
Ice interior temperature (degC), read by
|
|
| 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 |
|
| 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
|
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