Ice-shelf basal-melt slot: the 2-D interface state plus the parameter bundles the kernel is called with.
Every array is (nx_total, ny_total) when enable, (1,1)
otherwise — the z_draft gating convention, latched in
ocean_state_init_from_config BEFORE init so the allocation
gate can read it.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public, | allocatable | :: | active(:,:) |
Composed solve mask (0/1): |
||
| real(kind=wp), | public | :: | cdrag_top | = | 2.5e-3_wp |
Top drag coefficient for the MELT friction velocity only. |
|
| real(kind=wp), | public, | allocatable | :: | comp_scale(:,:) |
Per-cell top-layer thickness RATIO |
||
| real(kind=wp), | public | :: | comp_withdrawal_step | = | 0.0_wp |
Thickness (m) the compensation sink removed from each open -ocean column this thermo step; zero when compensation is off. |
|
| type(ocean_cavity_const_t), | public | :: | const |
Thermodynamic + turbulence constants. Flat POD, left at the
ISOMIP+ protocol values (Asay-Davis et al. (2016) Table 4):
|
|||
| logical, | public | :: | enable | = | .false. |
|
|
| real(kind=wp), | public, | allocatable | :: | f_cor(:,:) |
Cell-centred Coriolis parameter (1/s), from the same
|
||
| real(kind=wp), | public | :: | far_field_depth | = | 10.0_wp |
Thickness (m) below the ice base the far field is averaged over. See the module docstring: metres, not layers. |
|
| integer, | public | :: | freshwater | = | CAVITY_FW_VIRTUAL |
|
|
| real(kind=wp), | public, | allocatable | :: | gamma_s(:,:) |
Haline exchange velocity (m/s), same convention. |
||
| real(kind=wp), | public, | allocatable | :: | gamma_t(:,:) |
Thermal exchange velocity (m/s) the column’s solve converged
on — NOT |
||
| type(ocean_cavity_ice_t), | public | :: | ice |
Ice-conduction selector + |
|||
| logical, | public | :: | is_init | = | .false. |
Set by |
|
| real(kind=wp), | public, | allocatable | :: | melt(:,:) |
Canonical melt mass flux (kg/m^2/s), > 0 melting. |
||
| real(kind=wp), | public | :: | melt_volume_step | = | 0.0_wp |
Domain-integrated meltwater VOLUME (m^3) added this thermo step over the INTERIOR (ghosts excluded, globally combined). Diagnostic + the input the compensation sink spends. |
|
| integer, | public | :: | n_no_root_step | = | 0 |
Active columns returning |
|
| integer(kind=int64), | public | :: | n_no_root_total | = | 0_int64 |
Running total of |
|
| integer, | public | :: | n_nonfinite_step | = | 0 |
Active columns returning |
|
| integer, | public | :: | n_not_converged_step | = | 0 |
Active columns returning |
|
| integer(kind=int64), | public | :: | n_not_converged_total | = | 0_int64 |
Running total, drained to the console like
|
|
| integer, | public | :: | n_other_step | = | 0 |
Active columns returning any other non-OK status
( |
|
| integer(kind=int64), | public | :: | n_other_total | = | 0_int64 |
Running total of every other non-OK, non-fatal status. |
|
| integer, | public | :: | n_thin_step | = | 0 |
Columns this thermo step whose top layer could NOT give up
the thickness the real-mass path asked of it without falling
through |
|
| integer(kind=int64), | public | :: | n_thin_total | = | 0_int64 |
Running total of |
|
| real(kind=wp), | public | :: | open_area | = | 0.0_wp |
Interior wet area (m^2) the ice does NOT cover, globally combined — the denominator of the uniform sink. |
|
| type(ocean_cavity_exchange_t), | public | :: | par |
Exchange-law selector + coefficients. Flat POD; its
|
|||
| real(kind=wp), | public, | allocatable | :: | q_ocean(:,:) |
Turbulent heat flux ocean → interface (W/m^2), > 0 cools the ocean. |
||
| real(kind=wp), | public | :: | rho0 | = | 1035.0_wp |
Boussinesq reference density (kg/m^3) — THE density that
converts the melt MASS flux into a thickness tendency, and
the same one |
|
| real(kind=wp), | public, | allocatable | :: | s_b(:,:) |
Interface salinity (g/kg). |
||
| real(kind=wp), | public, | allocatable | :: | s_far(:,:) |
Far-field salinity (g/kg), same average. |
||
| real(kind=wp), | public | :: | s_ice | = | 0.0_wp |
Ice salinity (g/kg). |
|
| integer, | public, | allocatable | :: | status(:,:) |
|
||
| real(kind=wp), | public, | allocatable | :: | t_b(:,:) |
Interface temperature (degC), on the liquidus. |
||
| real(kind=wp), | public, | allocatable | :: | t_far(:,:) |
Far-field temperature (degC), thickness-weighted over
|
||
| real(kind=wp), | public, | allocatable | :: | u_far(:,:) |
Far-field x velocity at the cell CENTRE (m/s), same average. |
||
| real(kind=wp), | public | :: | u_tide | = | 1.0e-2_wp |
RMS tidal velocity (m/s) in the melt |
|
| real(kind=wp), | public, | allocatable | :: | ustar(:,:) |
Melt friction velocity (m/s). |
||
| real(kind=wp), | public | :: | ustar_min | = | 1.0e-4_wp |
Friction-velocity floor (m/s). |
|
| real(kind=wp), | public, | allocatable | :: | v_far(:,:) |
Far-field y velocity at the cell CENTRE (m/s), same average. |
||
| integer, | public | :: | volume_comp | = | CAVITY_VC_NONE |
|
Counted allocatable footprint (0 when unallocated). One
arr_bytes term per array — add one here when an array joins
the type.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_cavity_flux_t), | intent(in) | :: | this |
Release the slot. is_init is cleared FIRST.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_cavity_flux_t), | intent(inout) | :: | this |
Type-bound wrapper — delegates to the non-polymorphic impl so the device-attach map base is the heap object, not a polymorphic stack box.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_cavity_flux_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_cavity_flux_t), | intent(inout) | :: | this |
Allocate the slot. Gated on enable (latched by
ocean_state_init_from_config before this runs), so a run
without a cavity pays fourteen (1,1) placeholders.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_cavity_flux_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
type :: ocean_cavity_flux_t !! Ice-shelf basal-melt slot: the 2-D interface state plus the !! parameter bundles the kernel is called with. !! !! Every array is `(nx_total, ny_total)` when `enable`, `(1,1)` !! otherwise — the `z_draft` gating convention, latched in !! `ocean_state_init_from_config` BEFORE `init` so the allocation !! gate can read it. logical :: is_init = .false. !! Set by `init` after every allocation succeeds; cleared by !! `destroy` first. Always test this, never `allocated(...)`. logical :: enable = .false. !! `&ocean_cavity_melt_nml enable`, latched before `init`. ! ---- Knobs the kernel is called with (host scalars) ---- real(wp) :: far_field_depth = 10.0_wp !! Thickness (m) below the ice base the far field is averaged !! over. See the module docstring: metres, not layers. real(wp) :: cdrag_top = 2.5e-3_wp !! Top drag coefficient for the MELT friction velocity only. real(wp) :: u_tide = 1.0e-2_wp !! RMS tidal velocity (m/s) in the melt `u*`. real(wp) :: ustar_min = 1.0e-4_wp !! Friction-velocity floor (m/s). real(wp) :: s_ice = 0.0_wp !! Ice salinity (g/kg). integer :: freshwater = CAVITY_FW_VIRTUAL !! `&ocean_cavity_melt_nml freshwater`, parsed. !! `CAVITY_FW_VIRTUAL` (default) ⇒ `ocean_cavity_mass_step` is !! an immediate return and the path is byte-identical. integer :: volume_comp = CAVITY_VC_NONE !! `&ocean_cavity_melt_nml volume_compensation`, parsed. !! Requires `freshwater = CAVITY_FW_MASS` (validate_config). real(wp) :: rho0 = 1035.0_wp !! Boussinesq reference density (kg/m^3) — THE density that !! converts the melt MASS flux into a thickness tendency, and !! the same one `ocean_surface_flux_t%rho0` divides the surface !! tracer sources by. Assigned at configure from the single !! `rho_0` of record; the literal is only the pre-configure type !! default. The two MUST agree or the salt undo is not the !! exact negation of what the apply kernel stamped, which is !! asserted at configure. type(ocean_cavity_exchange_t) :: par !! Exchange-law selector + coefficients. Flat POD; its !! `f_cor` member is unused here (the driver substitutes the !! per-column `f_cor` array). type(ocean_cavity_ice_t) :: ice !! Ice-conduction selector + `T_ice`. Flat POD. type(ocean_cavity_const_t) :: const !! Thermodynamic + turbulence constants. Flat POD, left at the !! ISOMIP+ protocol values (Asay-Davis et al. (2016) Table 4): !! `rho_w`, `c_w`, `alpha_T`, `beta_S` here are the MELT LAW's !! own calibrated constants, NOT copies of the model's !! Boussinesq `rho_0` — the same "out of scope on purpose" !! category as `RHO_WATER` and `&ocean_ice_nml rho_ocean` in !! `src/core/ocean/README.md`'s reference-density table. !! Overriding them would break ISOMIP+ comparability, which is !! the reason this path exists. ! ---- Static, filled once at configure ---- real(wp), allocatable :: f_cor(:, :) !! Cell-centred Coriolis parameter (1/s), from the same !! `fill_coriolis_centre` every other slot uses. Read by !! `hj99` only, as `|f|`; the law does not exist at `f = 0`. ! ---- Per-step interface state (all device-resident) ---- real(wp), allocatable :: active(:, :) !! Composed solve mask (0/1): `cover_frac` AND wet AND "the !! far-field sample found mass". This is what the kernel's !! `cover` argument is given. real(wp), allocatable :: t_far(:, :) !! Far-field temperature (degC), thickness-weighted over !! `far_field_depth`. real(wp), allocatable :: s_far(:, :) !! Far-field salinity (g/kg), same average. real(wp), allocatable :: u_far(:, :) !! Far-field x velocity at the cell CENTRE (m/s), same average. real(wp), allocatable :: v_far(:, :) !! Far-field y velocity at the cell CENTRE (m/s), same average. real(wp), allocatable :: ustar(:, :) !! Melt friction velocity (m/s). real(wp), allocatable :: t_b(:, :) !! Interface temperature (degC), on the liquidus. real(wp), allocatable :: s_b(:, :) !! Interface salinity (g/kg). real(wp), allocatable :: melt(:, :) !! **Canonical** melt mass flux (kg/m^2/s), > 0 melting. real(wp), allocatable :: q_ocean(:, :) !! Turbulent heat flux ocean → interface (W/m^2), > 0 cools the !! ocean. real(wp), allocatable :: gamma_t(:, :) !! Thermal exchange velocity (m/s) the column's solve converged !! on — NOT `par%gamma_t_coeff`, which is the dimensionless !! coefficient. Under `hj99` / `yung25` it is an implicit !! function of the converged interface state, so it is stored !! rather than re-derived: a diagnostic that rebuilt it from !! `u*` alone would report the NEUTRAL value instead of the !! stratification-suppressed one. Zero where inactive. real(wp), allocatable :: gamma_s(:, :) !! Haline exchange velocity (m/s), same convention. integer, allocatable :: status(:, :) !! `CAVITY_MELT_*` per column; `CAVITY_MELT_OK` where inactive. real(wp), allocatable :: comp_scale(:, :) !! Per-cell top-layer thickness RATIO `h_new/h_old` left behind !! by the `volume_compensation` sink, exactly `1` everywhere the !! sink did not act. Every PASSIVE tracer's top-layer load is !! multiplied by it (`cavity_comp_scale_tracer_impl`) so the !! removed parcel carries that cell's own concentration and !! changes none of them. Allocated with the rest of the slot !! (full size iff `enable`); left at `1` when !! `volume_comp = CAVITY_VC_NONE`. ! ---- Status counters (host scalars, reduced off the device) ---- integer :: n_nonfinite_step = 0 !! Active columns returning `NONFINITE_INPUT`/`NONFINITE_STATE` !! this step. **FATAL** — the driver fails loud. integer :: n_not_converged_step = 0 !! Active columns returning `NOT_CONVERGED` this step (zero melt !! applied there — the kernel's documented safe state). integer :: n_no_root_step = 0 !! Active columns returning `NO_PHYSICAL_ROOT` this step. integer :: n_other_step = 0 !! Active columns returning any other non-OK status !! (`BAD_INPUT`, `NO_CORIOLIS`, `LAW_DOMAIN`, ...). integer(int64) :: n_not_converged_total = 0_int64 !! Running total, drained to the console like !! `continuity_t%n_limited_total`. int64 because a !! long run with one stubborn column can exceed 2e9. integer(int64) :: n_no_root_total = 0_int64 !! Running total of `NO_PHYSICAL_ROOT`. integer(int64) :: n_other_total = 0_int64 !! Running total of every other non-OK, non-fatal status. integer :: n_thin_step = 0 !! Columns this thermo step whose top layer could NOT give up !! the thickness the real-mass path asked of it without falling !! through `H_CAVITY_FLOOR` — a FREEZING column (`m < 0`) whose !! top layer is thinner than `|m|*dt/rho_0`, or a compensation !! sink deeper than the open-ocean top layer. The withdrawal is !! CLAMPED to what is there ABOVE the floor (so `h` stays !! strictly above the vanish marker, never on or below it) and !! the count is FATAL: a clamped withdrawal is a !! withdrawal the tracked mass source no longer matches, so !! continuing would print a budget that silently stopped !! closing. Same stance as the non-finite melt column. integer(int64) :: n_thin_total = 0_int64 !! Running total of `n_thin_step`, for the record. real(wp) :: melt_volume_step = 0.0_wp !! Domain-integrated meltwater VOLUME (m^3) added this thermo !! step over the INTERIOR (ghosts excluded, globally combined). !! Diagnostic + the input the compensation sink spends. real(wp) :: open_area = 0.0_wp !! Interior wet area (m^2) the ice does NOT cover, globally !! combined — the denominator of the uniform sink. real(wp) :: comp_withdrawal_step = 0.0_wp !! Thickness (m) the compensation sink removed from each open !! -ocean column this thermo step; zero when compensation is off. contains procedure, non_overridable :: init => ocean_cavity_flux_init procedure, non_overridable :: destroy => ocean_cavity_flux_destroy procedure, non_overridable :: enter_data => ocean_cavity_flux_enter_data procedure, non_overridable :: exit_data => ocean_cavity_flux_exit_data procedure, non_overridable :: bytes => ocean_cavity_flux_bytes end type ocean_cavity_flux_t