rdb_ocean_cavity_flux Module


Uses

  • module~~rdb_ocean_cavity_flux~~UsesGraph module~rdb_ocean_cavity_flux rdb_ocean_cavity_flux iso_fortran_env iso_fortran_env module~rdb_ocean_cavity_flux->iso_fortran_env module~rdb_constants rdb_constants module~rdb_ocean_cavity_flux->module~rdb_constants module~rdb_eos rdb_eos module~rdb_ocean_cavity_flux->module~rdb_eos module~rdb_grid rdb_grid module~rdb_ocean_cavity_flux->module~rdb_grid module~rdb_mem_report rdb_mem_report module~rdb_ocean_cavity_flux->module~rdb_mem_report module~rdb_multilayer_state rdb_multilayer_state module~rdb_ocean_cavity_flux->module~rdb_multilayer_state module~rdb_ocean_cavity_melt rdb_ocean_cavity_melt module~rdb_ocean_cavity_flux->module~rdb_ocean_cavity_melt module~rdb_ocean_metrics rdb_ocean_metrics module~rdb_ocean_cavity_flux->module~rdb_ocean_metrics module~rdb_ocean_surface_flux rdb_ocean_surface_flux module~rdb_ocean_cavity_flux->module~rdb_ocean_surface_flux pic_types pic_types module~rdb_constants->pic_types module~rdb_eos->module~rdb_constants module~rdb_eos->module~rdb_grid module~rdb_grid->module~rdb_constants module~rdb_mem_report->iso_fortran_env module~rdb_mem_report->module~rdb_constants pic_logger pic_logger module~rdb_mem_report->pic_logger pic_strings pic_strings module~rdb_mem_report->pic_strings module~rdb_multilayer_state->iso_fortran_env module~rdb_multilayer_state->module~rdb_constants module~rdb_multilayer_state->module~rdb_grid module~rdb_multilayer_state->module~rdb_mem_report module~rdb_efp rdb_efp module~rdb_multilayer_state->module~rdb_efp module~rdb_error_ring rdb_error_ring module~rdb_multilayer_state->module~rdb_error_ring module~rdb_tracer rdb_tracer module~rdb_multilayer_state->module~rdb_tracer module~rdb_multilayer_state->pic_logger module~rdb_ocean_cavity_melt->module~rdb_constants module~rdb_ocean_cavity_melt->module~rdb_eos ieee_arithmetic ieee_arithmetic module~rdb_ocean_cavity_melt->ieee_arithmetic module~rdb_ocean_metrics->iso_fortran_env module~rdb_ocean_metrics->module~rdb_constants module~rdb_ocean_metrics->module~rdb_grid module~rdb_ocean_metrics->module~rdb_mem_report module~rdb_ocean_metrics->module~rdb_error_ring module~rdb_io_netcdf rdb_io_netcdf module~rdb_ocean_metrics->module~rdb_io_netcdf module~rdb_ocean_bipolar rdb_ocean_bipolar module~rdb_ocean_metrics->module~rdb_ocean_bipolar module~rdb_ocean_fold rdb_ocean_fold module~rdb_ocean_metrics->module~rdb_ocean_fold module~rdb_ocean_status rdb_ocean_status module~rdb_ocean_metrics->module~rdb_ocean_status netcdf netcdf module~rdb_ocean_metrics->netcdf module~rdb_ocean_metrics->pic_logger module~rdb_ocean_metrics->pic_strings module~rdb_ocean_surface_flux->iso_fortran_env module~rdb_ocean_surface_flux->module~rdb_constants module~rdb_ocean_surface_flux->module~rdb_grid module~rdb_ocean_surface_flux->module~rdb_mem_report module~rdb_ocean_surface_flux->module~rdb_multilayer_state module~rdb_efp->iso_fortran_env module~rdb_efp->ieee_arithmetic module~rdb_error_ring->pic_logger module~rdb_io_netcdf->iso_fortran_env module~rdb_io_netcdf->module~rdb_constants module~rdb_io_netcdf->module~rdb_error_ring module~rdb_io_netcdf->netcdf module~rdb_io_netcdf->pic_logger module~rdb_io_netcdf->pic_strings iso_c_binding iso_c_binding module~rdb_io_netcdf->iso_c_binding module~rdb_ocean_bipolar->module~rdb_constants module~rdb_ocean_fold->module~rdb_constants module~rdb_tracer->iso_fortran_env module~rdb_tracer->module~rdb_constants module~rdb_tracer->module~rdb_grid module~rdb_tracer->module~rdb_mem_report

Used by

  • module~~rdb_ocean_cavity_flux~~UsedByGraph module~rdb_ocean_cavity_flux rdb_ocean_cavity_flux module~rdb_ocean_dyn rdb_ocean_dyn module~rdb_ocean_dyn->module~rdb_ocean_cavity_flux module~rdb_ocean_engine rdb_ocean_engine module~rdb_ocean_engine->module~rdb_ocean_cavity_flux module~rdb_ocean_engine->module~rdb_ocean_dyn module~rdb_ocean_state rdb_ocean_state module~rdb_ocean_engine->module~rdb_ocean_state module~rdb_ocean_diag_derived rdb_ocean_diag_derived module~rdb_ocean_engine->module~rdb_ocean_diag_derived module~rdb_ocean_diag_fills rdb_ocean_diag_fills module~rdb_ocean_engine->module~rdb_ocean_diag_fills module~rdb_ocean_setup rdb_ocean_setup module~rdb_ocean_engine->module~rdb_ocean_setup module~rdb_ocean_state->module~rdb_ocean_cavity_flux module~rdb_ocean_state->module~rdb_ocean_dyn module~rdb_driver rdb_driver module~rdb_driver->module~rdb_ocean_dyn module~rdb_driver->module~rdb_ocean_engine module~rdb_driver->module~rdb_ocean_state module~rdb_handle rdb_handle module~rdb_handle->module~rdb_ocean_engine module~rdb_handle->module~rdb_ocean_state module~rdb_ocean_api rdb_ocean_api module~rdb_ocean_api->module~rdb_ocean_dyn module~rdb_ocean_api->module~rdb_ocean_engine module~rdb_ocean_api->module~rdb_handle module~rdb_ocean_api->module~rdb_ocean_diag_derived module~rdb_ocean_api->module~rdb_ocean_diag_fills module~rdb_ocean_diag_derived->module~rdb_ocean_state module~rdb_ocean_diag_derived->module~rdb_ocean_diag_fills module~rdb_ocean_diag_fills->module~rdb_ocean_state module~rdb_ocean_setup->module~rdb_ocean_dyn module~rdb_ocean_setup->module~rdb_ocean_state

Variables

Type Visibility Attributes Name Initial
real(kind=wp), public, parameter :: H_CAVITY_FLOOR = 2.0_wp*H_VANISHED

Thickness (m) a clamped top-layer WITHDRAWAL is allowed to leave behind — one full marker ABOVE H_VANISHED, not on it.

H_VANISHED is the D4 skip/merge MARKER, and every gate in the tree tests it with a strict >: a layer sitting exactly ON the marker reads as VANISHED. So clamping a melt or compensation withdrawal to H_VANISHED exactly — which is what these kernels used to do, with an in-line comment arguing for landing on the marker — hands the next ALE remap a layer it treats as empty: ocean_remap_tracer_column’s c = hTr/h guard returns 0 there, so the layer’s heat and salt content is DELETED, silently and at the next thermo step. One ulp above the marker it is preserved. A clamped withdrawal is already a fail-loud condition (cavity_mass_thin_is_fatal), but the abort happens AFTER the state is written, so the value written has to survive being read.

2*H_VANISHED is the convention the rest of the tree already uses where a producer must land ABOVE the marker on purpose — compute_target_h_rho_impl’s h_floor_eff = max(zstar_h_min, 2*H_VANISHED) and seed_land_h_floor’s max(angstrom_h, 2*H_VANISHED). Written as a multiple of the constant of record rather than as a literal, so it cannot drift from it.


Derived Types

type, public ::  ocean_cavity_flux_t

Ice-shelf basal-melt slot: the 2-D interface state plus the parameter bundles the kernel is called with.

Read more…

Components

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

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

logical, public :: enable = .false.

&ocean_cavity_melt_nml enable, latched before init.

real(kind=wp), public, 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.

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

&ocean_cavity_melt_nml freshwater, parsed. CAVITY_FW_VIRTUAL (default) ⇒ ocean_cavity_mass_step is an immediate return and the path is byte-identical.

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

type(ocean_cavity_ice_t), public :: ice

Ice-conduction selector + T_ice. Flat POD.

logical, public :: is_init = .false.

Set by init after every allocation succeeds; cleared by destroy first. Always test this, never allocated(...).

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 NO_PHYSICAL_ROOT this step.

integer(kind=int64), public :: n_no_root_total = 0_int64

Running total of NO_PHYSICAL_ROOT.

integer, public :: n_nonfinite_step = 0

Active columns returning NONFINITE_INPUT/NONFINITE_STATE this step. FATAL — the driver fails loud.

integer, public :: n_not_converged_step = 0

Active columns returning NOT_CONVERGED this step (zero melt applied there — the kernel’s documented safe state).

integer(kind=int64), public :: 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, public :: n_other_step = 0

Active columns returning any other non-OK status (BAD_INPUT, NO_CORIOLIS, LAW_DOMAIN, …).

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 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(kind=int64), public :: n_thin_total = 0_int64

Running total of n_thin_step, for the record.

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 f_cor member is unused here (the driver substitutes the per-column f_cor array).

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

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(:,:)

CAVITY_MELT_* per column; CAVITY_MELT_OK where inactive.

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

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 u*.

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

&ocean_cavity_melt_nml volume_compensation, parsed. Requires freshwater = CAVITY_FW_MASS (validate_config).

Type-Bound Procedures

procedure, public, non_overridable :: bytes => ocean_cavity_flux_bytes
procedure, public, non_overridable :: destroy => ocean_cavity_flux_destroy
procedure, public, non_overridable :: enter_data => ocean_cavity_flux_enter_data
procedure, public, non_overridable :: exit_data => ocean_cavity_flux_exit_data
procedure, public, non_overridable :: init => ocean_cavity_flux_init

Functions

public pure function cavity_comp_withdrawal(vol_melt, area_open) result(dw)

The uniform per-unit-area thickness the uniform_open_ocean sink removes: vol_melt/area_open, and exactly zero when there is no open ocean to remove it from (a fully ice-covered domain — the sink then does nothing rather than dividing by zero, and the volume stays in, which the mass budget reports honestly as a growing total).

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: vol_melt

Meltwater volume this step (m^3); either sign.

real(kind=wp), intent(in) :: area_open

Uncovered wet area (m^2), >= 0.

Return Value real(kind=wp)

public pure function cavity_mass_thin_is_fatal(n_thin) result(is_fatal)

Is this step’s clamped-withdrawal tally a FAIL-LOUD condition?

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n_thin

n_thin_step.

Return Value logical

public pure function cavity_melt_status_is_fatal(n_nonfinite) result(is_fatal)

Is this step’s status tally a FAIL-LOUD condition?

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n_nonfinite

n_nonfinite_step from cavity_status_counts_impl.

Return Value logical

private pure function ocean_cavity_flux_bytes(this) result(nbytes)

Counted allocatable footprint (0 when unallocated). One arr_bytes term per array — add one here when an array joins the type.

Arguments

Type IntentOptional Attributes Name
class(ocean_cavity_flux_t), intent(in) :: this

Return Value integer(kind=int64)


Subroutines

public pure subroutine cavity_comp_apply_impl(nx, ny, nz, dw, wet_mask, cover_frac, h_layer, hTr_S, hTr_T, salt_budget, heat_budget, scale, n_thin)

The volume_compensation = "uniform_open_ocean" sink: remove dw metres of the top layer from every wet cell the ice does NOT cover, the removed parcel carrying that cell’s own T and S so no concentration there changes.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx

First dimension (ghosts included).

integer, intent(in) :: ny

Second dimension.

integer, intent(in) :: nz

Layer count; only k = nz is touched.

real(kind=wp), intent(in) :: dw

Thickness (m) to remove from each open-ocean column.

real(kind=wp), intent(in) :: wet_mask(nx,ny)

Static wet (1) / land (0) mask.

real(kind=wp), intent(in) :: cover_frac(nx,ny)

Ice-cover fraction (v1 binary).

real(kind=wp), intent(inout) :: h_layer(nx,ny,nz)

Layer thickness (m).

real(kind=wp), intent(inout) :: hTr_S(nx,ny,nz)

h*S.

real(kind=wp), intent(inout) :: hTr_T(nx,ny,nz)

h*T.

real(kind=wp), intent(inout) :: salt_budget(nx,ny,nz)

ms%salt_budget_surface.

real(kind=wp), intent(inout) :: heat_budget(nx,ny,nz)

ms%heat_budget_surface.

real(kind=wp), intent(out) :: scale(nx,ny)

h_new/h_old where the sink acted, exactly 1 elsewhere.

integer, intent(out) :: n_thin

Columns whose withdrawal had to be clamped.

public pure subroutine cavity_comp_scale_tracer_impl(nx, ny, nz, scale, hTr)

Apply the compensation sink’s top-layer ratio to one PASSIVE tracer’s load. Unconditional (scale = 1 off the sink), so there is no mask branch inside the kernel.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx

First dimension.

integer, intent(in) :: ny

Second dimension.

integer, intent(in) :: nz

Layer count.

real(kind=wp), intent(in) :: scale(nx,ny)

h_new/h_old from cavity_comp_apply_impl.

real(kind=wp), intent(inout) :: hTr(nx,ny,nz)

The tracer’s h*C.

public pure subroutine cavity_far_field_impl(nx, ny, nz, far_depth, cover, wet_mask, h_layer, hTr_T, hTr_S, u_face_x, v_face_y, active, t_far, s_far, u_far, v_far)

Thickness-weighted mean of (T, S, u, v) over far_depth METRES below the ice base, with a PARTIAL last layer.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx

First dimension (ghosts included).

integer, intent(in) :: ny

Second dimension.

integer, intent(in) :: nz

Layer count; k = nz is the surface / ice-base layer.

real(kind=wp), intent(in) :: far_depth

Sampling thickness (m), > 0.

real(kind=wp), intent(in) :: cover(nx,ny)

Ice-cover fraction (v1 binary).

real(kind=wp), intent(in) :: wet_mask(nx,ny)

Static wet (1) / land (0) mask.

real(kind=wp), intent(in) :: h_layer(nx,ny,nz)

Layer thickness (m).

real(kind=wp), intent(in) :: hTr_T(nx,ny,nz)

h*T (degC m).

real(kind=wp), intent(in) :: hTr_S(nx,ny,nz)

h*S ((g/kg) m).

real(kind=wp), intent(in) :: u_face_x(nx+1,ny,nz)

Zonal face velocity (m/s).

real(kind=wp), intent(in) :: v_face_y(nx,ny+1,nz)

Meridional face velocity (m/s).

real(kind=wp), intent(out) :: active(nx,ny)

Composed solve mask, 0 or 1.

real(kind=wp), intent(out) :: t_far(nx,ny)

Sampled temperature (degC); 0 where inactive.

real(kind=wp), intent(out) :: s_far(nx,ny)

Sampled salinity (g/kg); 0 where inactive.

real(kind=wp), intent(out) :: u_far(nx,ny)

Sampled centred x velocity (m/s); 0 where inactive.

real(kind=wp), intent(out) :: v_far(nx,ny)

Sampled centred y velocity (m/s); 0 where inactive.

public pure subroutine cavity_flux_fill_impl(nx, ny, s_ice, active, melt, q_ocean, s_far, heat_cavity, salt_cavity)

Fill the two OWNED surface-flux components from the solved interface. FULL OVERWRITE of the whole plane, never += — the same rule the sea-ice coupler’s fillers follow, and for the same reason (a += ratchets across outer steps with no bound).

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx

First dimension (ghosts included).

integer, intent(in) :: ny

Second dimension.

real(kind=wp), intent(in) :: s_ice

Ice salinity (g/kg).

real(kind=wp), intent(in) :: active(nx,ny)

Composed solve mask.

real(kind=wp), intent(in) :: melt(nx,ny)

Melt mass flux (kg/m^2/s), > 0 melting.

real(kind=wp), intent(in) :: q_ocean(nx,ny)

Ocean → interface heat flux (W/m^2).

real(kind=wp), intent(in) :: s_far(nx,ny)

Far-field salinity the solve used (g/kg).

real(kind=wp), intent(out) :: heat_cavity(nx,ny)

Heat component (W/m^2), positive down into the ocean.

real(kind=wp), intent(out) :: salt_cavity(nx,ny)

Virtual salt component, positive salinifies.

public pure subroutine cavity_mass_apply_impl(nx, ny, nz, dt_over_rho0, inv_rho0_dt, s_ice, active, melt, s_far, t_b, h_layer, hTr_S, hTr_T, salt_budget, heat_budget, k_top, n_thin)

The real-mass top-layer source: add the meltwater VOLUME to h_layer at the first LIVE layer k_top(i,j), replace the virtual salt flux the assembler stamped with the real advective salt w*s_ice, and add the enthalpy dh*T_b — mirroring both tracer increments into the existing surface budget contributors.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx

First dimension (ghosts included).

integer, intent(in) :: ny

Second dimension.

integer, intent(in) :: nz

Layer count; k = nz is the surface / ice-base layer.

real(kind=wp), intent(in) :: dt_over_rho0

dt/rho_0 (m^3 s / kg) — multiplies melt to give dh.

real(kind=wp), intent(in) :: inv_rho0_dt

The same dt/rho_0, used to undo the surface-flux stamp.

real(kind=wp), intent(in) :: s_ice

Ice salinity (g/kg).

real(kind=wp), intent(in) :: active(nx,ny)

Composed solve mask; 1 only on covered, wet, sampled columns.

real(kind=wp), intent(in) :: melt(nx,ny)

Melt mass flux (kg/m^2/s), > 0 melting.

real(kind=wp), intent(in) :: s_far(nx,ny)

Far-field salinity (g/kg) the solve used. The VIRTUAL salt component -melt*(s_far - s_ice) is REBUILT from it here, with the same expression cavity_flux_fill_impl uses, rather than read back off sf: on a covered column the assembler’s open-water factor is exactly zero, so Q_salt IS that component bit for bit, and rebuilding it keeps this kernel free of the surface-flux slot.

real(kind=wp), intent(in) :: t_b(nx,ny)

Interface temperature (degC): the temperature the meltwater joins the column at.

real(kind=wp), intent(inout) :: h_layer(nx,ny,nz)

Layer thickness (m); only k = k_top(i,j) is touched.

real(kind=wp), intent(inout) :: hTr_S(nx,ny,nz)

h*S ((g/kg) m).

real(kind=wp), intent(inout) :: hTr_T(nx,ny,nz)

h*T (degC m).

real(kind=wp), intent(inout) :: salt_budget(nx,ny,nz)

ms%salt_budget_surface.

real(kind=wp), intent(inout) :: heat_budget(nx,ny,nz)

ms%heat_budget_surface.

integer, intent(in) :: k_top(nx,ny)

ms%k_top — the first LIVE layer counting down from the top, nz wherever nothing vanishes against the top. Under a quasi-geopotential coordinate beneath the shelf k = nz is an inert filler on every covered column: growing IT would put the meltwater where the remap drain deletes it, and shrinking it would trip the fatal thin-withdrawal clamp on every column at once (a filler is already AT the marker).

integer, intent(out) :: n_thin

Columns whose withdrawal had to be clamped.

public pure subroutine cavity_mass_salt_mirror_impl(nx, ny, nz, dt_over_rho0, inv_rho0_dt, s_ice, active, melt, s_far, hTr, k_top)

The pseudo-salt mirror of cavity_mass_apply_impl’s SALT increment, with no budget accumulation — budget_id = NONE, so it must not touch salt_budget_surface.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx

First dimension.

integer, intent(in) :: ny

Second dimension.

integer, intent(in) :: nz

Layer count.

real(kind=wp), intent(in) :: dt_over_rho0

dt/rho_0.

real(kind=wp), intent(in) :: inv_rho0_dt

The same dt/rho_0 (see the sibling’s docstring).

real(kind=wp), intent(in) :: s_ice

Ice salinity (g/kg).

real(kind=wp), intent(in) :: active(nx,ny)

Composed solve mask.

real(kind=wp), intent(in) :: melt(nx,ny)

Melt mass flux (kg/m^2/s).

real(kind=wp), intent(in) :: s_far(nx,ny)

Far-field salinity (g/kg); the virtual component being undone is rebuilt from it, exactly as in the sibling.

real(kind=wp), intent(inout) :: hTr(nx,ny,nz)

Pseudo-salt h*C.

integer, intent(in) :: k_top(nx,ny)

The SAME first-live-layer index the salt branch used — the mirror’s whole contract is that its increment is bit-identical to salinity’s, which includes landing on the same row.

public pure subroutine cavity_mass_totals_impl(nx, ny, nghost, dt_over_rho0, active, wet_mask, cover_frac, melt, areaT, vol_melt, area_open)

The two INTERIOR integrals the mass budget and the compensation sink need, reduced on device in one pass:

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx

First dimension (ghosts included).

integer, intent(in) :: ny

Second dimension.

integer, intent(in) :: nghost

Halo width to exclude on every side.

real(kind=wp), intent(in) :: dt_over_rho0

dt/rho_0.

real(kind=wp), intent(in) :: active(nx,ny)

Composed solve mask.

real(kind=wp), intent(in) :: wet_mask(nx,ny)

Static wet (1) / land (0) mask.

real(kind=wp), intent(in) :: cover_frac(nx,ny)

Ice-cover fraction (v1 binary).

real(kind=wp), intent(in) :: melt(nx,ny)

Melt mass flux (kg/m^2/s).

real(kind=wp), intent(in) :: areaT(nx,ny)

Cell area (m^2).

real(kind=wp), intent(out) :: vol_melt

Meltwater volume this step (m^3).

real(kind=wp), intent(out) :: area_open

Uncovered wet area (m^2).

public pure subroutine cavity_status_counts_impl(nx, ny, active, status, n_nonfinite, n_not_converged, n_no_root, n_other)

Reduce the per-column status plane into four counts, ON DEVICE.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx

First dimension.

integer, intent(in) :: ny

Second dimension.

real(kind=wp), intent(in) :: active(nx,ny)

Composed solve mask.

integer, intent(in) :: status(nx,ny)

CAVITY_MELT_* per column.

integer, intent(out) :: n_nonfinite

Count of NONFINITE_INPUT + NONFINITE_STATE.

integer, intent(out) :: n_not_converged

Count of NOT_CONVERGED.

integer, intent(out) :: n_no_root

Count of NO_PHYSICAL_ROOT.

integer, intent(out) :: n_other

Count of every other non-OK status.

public subroutine ocean_cavity_flux_step(grid, cav, metrics, ms, eos, sf, active)

One cavity basal-melt update: sample the far field, solve the three-equation interface on every covered column, deliver the two owned surface-flux components, and account for the solver status.

Read more…

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid

Horizontal grid (for nx_total/ny_total).

type(ocean_cavity_flux_t), intent(inout) :: cav

The cavity-melt slot.

type(ocean_metrics_t), intent(in) :: metrics

Reads cover_frac only.

type(multilayer_state_t), intent(in) :: ms

Reads h_layer, the S/T tracer loads, the face velocities, p_top (THE interface pressure) and wet_mask.

type(eos_t), intent(in) :: eos

Shared EOS handle — the liquidus. Flat POD, by value.

type(ocean_surface_flux_t), intent(inout) :: sf

Writes heat_cavity/salt_cavity and latches has_heat/has_salt host-side.

logical, intent(in), optional :: active

Thermo-cadence gate. Present-and-false ⇒ early return; absent ⇒ run (the ocean_surface_flux_assemble convention).

public subroutine ocean_cavity_mass_step(grid, metrics, cav, ms, dt, weight, active)

The real-freshwater MASS update — one call, at the THERMO cadence, from inside the RK2 stage immediately after ocean_surface_flux_apply_tracers.

Read more…

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid

Horizontal grid (nx_total/ny_total/nghost).

type(ocean_metrics_t), intent(in) :: metrics

Reads cover_frac and areaT.

type(ocean_cavity_flux_t), intent(inout) :: cav

The cavity-melt slot; reads melt/active/t_b, writes comp_scale and the thin counters.

type(multilayer_state_t), intent(inout) :: ms

Writes h_layer(:,:,nz), the S/T/passive tracer loads, the two surface budget contributors and mass_src.

real(kind=wp), intent(in) :: dt

Thermo timestep (s) — the same therm_dt the surface-flux apply was given.

real(kind=wp), intent(in) :: weight

Per-stage weight for the mass_src accumulator (0.5 per SSP-RK2 stage; 0 / 1 for the pred_corr predictor / corrector), matching ocean_accumulate_mass_out.

logical, intent(in), optional :: active

Thermo-cadence gate. Present-and-false ⇒ early return; absent ⇒ run.

private subroutine ocean_cavity_flux_destroy(this)

Release the slot. is_init is cleared FIRST.

Arguments

Type IntentOptional Attributes Name
class(ocean_cavity_flux_t), intent(inout) :: this

private subroutine ocean_cavity_flux_enter_data(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.

Arguments

Type IntentOptional Attributes Name
class(ocean_cavity_flux_t), intent(inout) :: this

private subroutine ocean_cavity_flux_enter_data_impl(this)

copyin (not create) throughout: f_cor carries a configure-time host fill that MUST reach the device, and the rest carry the zero init promised on both toolchains.

Arguments

Type IntentOptional Attributes Name
type(ocean_cavity_flux_t), intent(inout) :: this

private subroutine ocean_cavity_flux_exit_data(this)

Arguments

Type IntentOptional Attributes Name
class(ocean_cavity_flux_t), intent(inout) :: this

private subroutine ocean_cavity_flux_exit_data_impl(this)

Arguments

Type IntentOptional Attributes Name
type(ocean_cavity_flux_t), intent(inout) :: this

private subroutine ocean_cavity_flux_init(this, grid)

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.

Arguments

Type IntentOptional Attributes Name
class(ocean_cavity_flux_t), intent(inout) :: this
type(hgrid_t), intent(in) :: grid