subroutine register_ocean_vmix(cfg, schema)
!! `&ocean_vmix_nml`: vertical-mixing module switches + knobs.
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
integer, pointer :: pi
character(len=:), pointer :: ps
g%name = "ocean_vmix"
g%doc = "Vertical-mixing module switches + knobs."
pl => cfg%ocean%vmix%use_closure
call g%add(nml_logical("use_closure", pl, "Master switch for the interior closure (PP81)"))
pl => cfg%ocean%vmix%use_kpp
call g%add(nml_logical("use_kpp", pl, "KPP surface-boundary-layer overlay (needs use_closure)"))
pl => cfg%ocean%vmix%direct_stress
call g%add(nml_logical("direct_stress", pl, "Spread wind stress over hmix_stress (MOM6 DIRECT_STRESS)"))
pr => cfg%ocean%vmix%hmix_stress
call g%add(nml_real("hmix_stress", pr, "Surface-slab thickness for direct_stress", units="m"))
pr => cfg%ocean%vmix%kv_ml_invz2
call g%add(nml_real("kv_ml_invz2", pr, "Near-surface 1/(z hmix)^2 viscosity (MOM6 KV_ML_INVZ2)", &
units="m^2/s"))
pr => cfg%ocean%vmix%hmix_fixed
call g%add(nml_real("hmix_fixed", pr, "Mixed-layer thickness for the KV_ML_INVZ2 profile", units="m"))
pl => cfg%ocean%vmix%harmonic_visc
call g%add(nml_logical("harmonic_visc", pl, "Harmonic-mean face thickness in vdiff (MOM6 HARMONIC_VISC)"))
pi => cfg%ocean%vmix%dt_therm_ratio
call g%add(nml_int("dt_therm_ratio", pi, "Thermo step runs at ratio*dt_dyn (MOM6 DT_THERM)", min=1))
pi => cfg%ocean%vmix%dt_tracer_advect_ratio
call g%add(nml_int("dt_tracer_advect_ratio", pi, &
"Horizontal tracer advect runs at ratio*dt_dyn (MOM6 DT_TRACER_ADVECT)", min=1))
ps => cfg%ocean%vmix%tracer_recon
call g%add(nml_enum("tracer_recon", ps, &
"Windowed tracer-advect drain face reconstruction (ocean): ppm|weno5|weno7|weno9", &
allowed=[character(len=8) :: "ppm", "weno5", "weno7", "weno9"]))
pr => cfg%ocean%vmix%kv_max
call g%add(nml_real("kv_max", pr, "Assembly ceiling on kv; huge=off (MOM6 Kd_max momentum)", &
units="m^2/s"))
pr => cfg%ocean%vmix%kd_max
call g%add(nml_real("kd_max", pr, "Assembly ceiling on kt/ks; huge=off (MOM6 Kd_max)", &
units="m^2/s"))
pi => cfg%ocean%vmix%kd_smooth_iterations
call g%add(nml_int("kd_smooth_iterations", pi, "1-2-1 smoothing passes on kv/kt (MOM6 Kd_smooth)", min=0))
pl => cfg%ocean%vmix%vmix_guard
call g%add(nml_logical("vmix_guard", pl, "Debug-gated negative/NaN diffusivity guard (assembly)"))
! C7 Bryan-Lewis + Henyey depth-varying background.
pl => cfg%ocean%vmix%bkgnd_profile
call g%add(nml_logical("bkgnd_profile", pl, "Bryan-Lewis depth-varying background diffusivity"))
pr => cfg%ocean%vmix%bkgnd_kd_sfc
call g%add(nml_real("bkgnd_kd_sfc", pr, "Bryan-Lewis surface-asymptote background Kd", units="m^2/s"))
pr => cfg%ocean%vmix%bkgnd_kd_deep
call g%add(nml_real("bkgnd_kd_deep", pr, "Bryan-Lewis deep-asymptote background Kd", units="m^2/s"))
pr => cfg%ocean%vmix%bkgnd_z0
call g%add(nml_real("bkgnd_z0", pr, "Bryan-Lewis transition-centre depth", units="m"))
pr => cfg%ocean%vmix%bkgnd_delta
call g%add(nml_real("bkgnd_delta", pr, "Bryan-Lewis transition half-width", &
units="m", min=1.0e-6_wp))
pr => cfg%ocean%vmix%bkgnd_prandtl
call g%add(nml_real("bkgnd_prandtl", pr, "Background Prandtl number Kv_bg=prandtl*Kd_bg", &
min=0.0_wp))
pl => cfg%ocean%vmix%bkgnd_henyey
call g%add(nml_logical("bkgnd_henyey", pl, &
"Henyey IGW latitude factor on the scalar background "// &
"(excludes bkgnd_profile; needs a non-cartesian grid)"))
pr => cfg%ocean%vmix%bkgnd_kd_min
call g%add(nml_real("bkgnd_kd_min", pr, &
"Minimum background Kd under the Henyey scaling "// &
"(negative = 0.01*kt_bg)", units="m^2/s"))
pr => cfg%ocean%vmix%bkgnd_henyey_n0_2omega
call g%add(nml_real("bkgnd_henyey_n0_2omega", pr, &
"Henyey N0/(2*Omega) reference stratification ratio", &
min=1.0_wp))
pr => cfg%ocean%vmix%bkgnd_henyey_max_lat
call g%add(nml_real("bkgnd_henyey_max_lat", pr, &
"Latitude poleward of which the Henyey factor floors", &
units="degN", min=0.0_wp))
! PP81 interior closure + KPP BL-depth constants — route to the
! OCEAN vmix slot (see rdb_ocean_setup.F90:configure_ocean_lateral).
! Do NOT confuse with the similarly-named &nonhydrostatic_nml
! kpp_ri_crit/kpp_cs_nonlocal/kpp_c_vt2, which drove the coastal KPP
! and are VESTIGIAL since that path was carved out — nothing reads
! them. These &ocean_vmix_nml keys are the live ones.
pr => cfg%ocean%vmix%pp81_nu0
call g%add(nml_real("pp81_nu0", pr, "PP81 Richardson-dependent viscosity scale", &
units="m^2/s", min=0.0_wp))
pr => cfg%ocean%vmix%pp81_nu_bg
call g%add(nml_real("pp81_nu_bg", pr, "PP81 background viscosity (also seeds vmix%kv_bg)", &
units="m^2/s", min=0.0_wp))
pr => cfg%ocean%vmix%pp81_kappa_bg
call g%add(nml_real("pp81_kappa_bg", pr, &
"PP81 background diffusivity (also seeds vmix%kt_bg/ks_bg)", &
units="m^2/s", min=0.0_wp))
pr => cfg%ocean%vmix%pp81_alpha
call g%add(nml_real("pp81_alpha", pr, &
"PP81 Richardson-number scaling coefficient (paper value 5)", &
min=1.0e-12_wp))
pr => cfg%ocean%vmix%shear2_floor
call g%add(nml_real("shear2_floor", pr, &
"Floor on |du/dz|^2+|dv/dz|^2 in the PP81 Ri denominator", &
units="1/s^2", min=1.0e-30_wp))
pr => cfg%ocean%vmix%kpp_ri_crit
call g%add(nml_real("kpp_ri_crit", pr, "Critical bulk Richardson number for KPP BL-depth", &
min=1.0e-12_wp))
pr => cfg%ocean%vmix%kpp_cs_nonlocal
call g%add(nml_real("kpp_cs_nonlocal", pr, &
"KPP non-local (counter-gradient) transport coefficient C_s", &
min=0.0_wp))
pr => cfg%ocean%vmix%kpp_c_vt2
call g%add(nml_real("kpp_c_vt2", pr, &
"KPP unresolved-turbulence V_t^2 coefficient (0 disables V_t^2)", &
min=0.0_wp))
! E4: source of the alpha/beta pair the KPP B_0 and the
! double-diffusion density ratio use. The `allowed=` list must stay
! in lockstep with `parse_buoyancy_coeffs` (rdb_ocean_vmix.F90).
ps => cfg%ocean%vmix%buoyancy_coeffs
call g%add(nml_enum("buoyancy_coeffs", ps, &
"Source of alpha/beta for KPP B_0 + double diffusion: "// &
"constant (scalar &ocean_ic_nml pair) | eos (active EOS derivatives)", &
allowed=[character(len=8) :: "constant", "eos"]))
call schema%add_group(g)
end subroutine register_ocean_vmix