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.
type(config_t), target, intent(in) :: cfg
type(nml_schema_t), intent(inout) :: schema
type(nml_group_t) :: g
logical, pointer :: pl
real(wp), pointer :: pr
character(len=:), pointer :: ps
g%name = "ocean_cavity_melt"
g%doc = "Ice-shelf basal-melt thermodynamics: the three-equation "// &
"interface, its exchange law, and the far-field sampling depth."
pl => cfg%ocean%cavity_melt%enable
call g%add(nml_logical("enable", pl, &
"Master switch (requires &ocean_cavity_dyn_nml, "// &
"tfreeze_set='isomip' and the surface-flux "// &
"component set)"))
ps => cfg%ocean%cavity_melt%exchange_law
call g%add(nml_enum("exchange_law", ps, &
"Turbulent exchange law; laws other than "// &
"const_gamma/hj99/yung25 are RESERVED and refused "// &
"at configure", &
allowed=[character(len=12) :: "const_gamma", "hj99", &
"yung25", "jenkins91", "rosevear22", "vt19", &
"mk18", "burchard22", "jenkins21"]))
pr => cfg%ocean%cavity_melt%gamma_t
call g%add(nml_real("gamma_t", pr, &
"Dimensionless heat-transfer coefficient Gamma_T "// &
"(ISOMIP+ starting guess; tune per coordinate)", &
min=0.0_wp))
pr => cfg%ocean%cavity_melt%gamma_s
call g%add(nml_real("gamma_s", pr, &
"Dimensionless salt-transfer coefficient Gamma_S "// &
"(negative = unset = gamma_t/35)"))
pr => cfg%ocean%cavity_melt%cdrag_top
call g%add(nml_real("cdrag_top", pr, &
"Top drag coefficient for the MELT friction velocity "// &
"(no momentum drag yet - that is Phase 4)", &
min=0.0_wp))
pr => cfg%ocean%cavity_melt%u_tide
call g%add(nml_real("u_tide", pr, &
"RMS tidal velocity in the melt u* only, never the drag", &
units="m/s", min=0.0_wp))
pr => cfg%ocean%cavity_melt%ustar_min
call g%add(nml_real("ustar_min", pr, &
"Friction-velocity floor (Yung et al. 2025 eq. 14)", &
units="m/s", min=0.0_wp))
ps => cfg%ocean%cavity_melt%ice_conduction
call g%add(nml_enum("ice_conduction", ps, &
"Ice-side conduction; 'diffusive' is RESERVED and "// &
"refused (it changes the melt/freeze branch logic)", &
allowed=[character(len=10) :: "insulating", "adv_diff", &
"diffusive"]))
pr => cfg%ocean%cavity_melt%t_ice
call g%add(nml_real("t_ice", pr, &
"Ice interior temperature; read by ice_conduction="// &
"'adv_diff' only", units="degC"))
pr => cfg%ocean%cavity_melt%s_ice
call g%add(nml_real("s_ice", pr, &
"Ice salinity; must stay strictly below the far-field "// &
"salinity", units="g/kg", min=0.0_wp))
pr => cfg%ocean%cavity_melt%far_field_depth
call g%add(nml_real("far_field_depth", pr, &
"Thickness below the ice base the far-field T/S/u are "// &
"averaged over (METRES, not layers)", units="m", &
min=0.0_wp))
ps => cfg%ocean%cavity_melt%freshwater
call g%add(nml_enum("freshwater", ps, &
"Meltwater delivery: 'virtual' (default, fixed "// &
"column mass) or 'mass' (real Boussinesq volume on "// &
"the top layer)", &
allowed=[character(len=8) :: "virtual", "mass"]))
ps => cfg%ocean%cavity_melt%volume_compensation
call g%add(nml_enum("volume_compensation", ps, &
"Sea-level compensation for freshwater='mass': "// &
"'none' (default) or 'uniform_open_ocean' (remove the "// &
"melt volume again over uncovered wet cells)", &
allowed=[character(len=20) :: "none", "uniform_open_ocean"]))
call schema%add_group(g)
end subroutine register_ocean_cavity_melt