| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public, | allocatable | :: | Q_heat(:,:) |
2D net surface heat flux (W/m^2, positive downward),
shape |
||
| real(kind=wp), | public | :: | Q_heat_const | = | 0.0_wp |
Scalar fill source for |
|
| real(kind=wp), | public, | allocatable | :: | Q_salt(:,:) |
2D net surface salt flux (kg salt/m^2/s, positive salinifies),
shape |
||
| real(kind=wp), | public | :: | Q_salt_const | = | 0.0_wp |
Scalar fill source for |
|
| real(kind=wp), | public | :: | cp | = | SEAWATER_CP |
Specific heat capacity (J/kg/K). |
|
| real(kind=wp), | public, | allocatable | :: | evap(:,:) |
Evaporative mass flux (kg/m^2/s, <= 0 — MOM6 convention,
|
||
| real(kind=wp), | public, | allocatable | :: | fprec(:,:) |
Frozen precipitation / snowfall (kg/m^2/s, >= 0). |
||
| real(kind=wp), | public, | allocatable | :: | frunoff(:,:) |
Frozen (calving/ice) runoff (kg/m^2/s, >= 0). |
||
| real(kind=wp), | public | :: | h_min | = | 1.0e-3_wp |
Floor on the surface-layer thickness in the |
|
| logical, | public | :: | has_heat | = | .false. |
True when |
|
| logical, | public | :: | has_mass_flux | = | .false. |
Host-side latch — set by a filler after writing ANY of
|
|
| logical, | public | :: | has_q_sw | = | .false. |
Host-side latch — set by a filler after writing |
|
| logical, | public | :: | has_restore_S | = | .false. |
True when SSS restoring is active ( |
|
| logical, | public | :: | has_restore_T | = | .false. |
True when SST restoring is active ( |
|
| logical, | public | :: | has_salt | = | .false. |
True when |
|
| logical, | public | :: | has_sw | = | .false. |
True when shortwave penetration is active (set by
|
|
| real(kind=wp), | public, | allocatable | :: | heat_added(:,:) |
Restoring / flux-adjustment / “other” net heat term not
decomposed into the radiative/turbulent bands above (W/m^2,
either sign; MOM6 |
||
| real(kind=wp), | public, | allocatable | :: | heat_cavity(:,:) |
Ice-shelf cavity basal-melt heat component (W/m^2, same
positive-DOWN-into-the-ocean convention as every other heat
band; |
||
| real(kind=wp), | public, | allocatable | :: | heat_content_fprec(:,:) |
Enthalpy carried by |
||
| real(kind=wp), | public, | allocatable | :: | heat_content_frunoff(:,:) |
Enthalpy carried by |
||
| real(kind=wp), | public, | allocatable | :: | heat_content_lprec(:,:) |
Enthalpy carried by |
||
| real(kind=wp), | public, | allocatable | :: | heat_content_lrunoff(:,:) |
Enthalpy carried by |
||
| real(kind=wp), | public, | allocatable | :: | heat_content_massin(:,:) |
Assembler output — do NOT write. Sum of the six
|
||
| real(kind=wp), | public, | allocatable | :: | heat_content_massout(:,:) |
Assembler output — do NOT write. |
||
| real(kind=wp), | public, | allocatable | :: | heat_content_seaice_melt(:,:) |
Enthalpy carried by |
||
| real(kind=wp), | public, | allocatable | :: | heat_content_vprec(:,:) |
Enthalpy carried by |
||
| logical, | public | :: | is_init | = | .false. |
True between |
|
| real(kind=wp), | public, | allocatable | :: | lprec(:,:) |
Liquid precipitation (kg/m^2/s, >= 0 into the ocean). |
||
| real(kind=wp), | public, | allocatable | :: | lrunoff(:,:) |
Liquid river runoff (kg/m^2/s, >= 0). |
||
| real(kind=wp), | public, | allocatable | :: | p_surf(:,:) |
Assembled total (Pa, >= 0) — |
||
| real(kind=wp), | public, | allocatable | :: | p_surf_atm(:,:) |
Input component. Atmospheric surface-pressure load (Pa, >= 0). Filled by an external reader / configure-time scalar seed — the sea-ice path never writes this field. Ships zeroed with no consumer in this PR (the inverse- barometer PGF fold is a same-release-cycle follow-up). |
||
| real(kind=wp), | public | :: | q_assembled | = | 0.0_wp |
Host latch, 1 once |
|
| real(kind=wp), | public, | allocatable | :: | q_lat(:,:) |
Latent heat flux (W/m^2, typically < 0, positive down). |
||
| real(kind=wp), | public, | allocatable | :: | q_lw(:,:) |
Net longwave (W/m^2, typically < 0, positive down). |
||
| real(kind=wp), | public, | allocatable | :: | q_sens(:,:) |
Sensible heat flux (W/m^2, typically < 0, positive down). |
||
| real(kind=wp), | public, | allocatable | :: | q_sw(:,:) |
Shortwave into the ocean (W/m^2, >= 0, positive down). |
||
| real(kind=wp), | public | :: | restore_S_target | = | 0.0_wp |
Scalar target SSS (PSU). |
|
| real(kind=wp), | public | :: | restore_T_target | = | 0.0_wp |
Scalar target SST (degC). Read by-value into the device
|
|
| real(kind=wp), | public | :: | restore_piston_S | = | 0.0_wp |
SSS piston velocity (m/s). |
|
| real(kind=wp), | public | :: | restore_piston_T | = | 0.0_wp |
SST piston velocity (m/s), seeded from |
|
| real(kind=wp), | public | :: | rho0 | = | 1035.0_wp |
Boussinesq reference density (kg/m^3) — the ASSIGNED FROM CONFIG by |
|
| real(kind=wp), | public, | allocatable | :: | salt_cavity(:,:) |
Ice-shelf cavity basal-melt salt component, same units
and sign as The fixed-mass dilution equivalent.
is the exact fixed-mass equivalent of adding mass Under Under |
||
| real(kind=wp), | public, | allocatable | :: | salt_flux(:,:) |
Net surface salt-flux COMPONENT (kg salt/m^2/s, positive
salinifies) — a filler writes this (e.g. the ice brine
coupler); the assembler adds |
||
| real(kind=wp), | public, | allocatable | :: | seaice_melt(:,:) |
Sea-ice melt-water mass flux (kg/m^2/s, >0 = melt into the ocean, <0 = formation / freezing withdraws mass). |
||
| real(kind=wp), | public | :: | sw_band_ratio | = | 0.58_wp |
Band-1 weight |
|
| logical, | public | :: | sw_from_qsw | = | .false. |
Selects the irradiance source for shortwave penetration and
the boundary-layer SW coupling. |
|
| real(kind=wp), | public | :: | sw_pen_frac | = | 0.0_wp |
Penetrating fraction of |
|
| real(kind=wp), | public | :: | sw_zeta1 | = | 0.35_wp |
Band-1 e-folding depth (m) — the rapidly-absorbed red/near-IR band. |
|
| real(kind=wp), | public | :: | sw_zeta2 | = | 23.0_wp |
Band-2 e-folding depth (m) — the slowly-absorbed blue/green band. |
|
| logical, | public | :: | use_components | = | .false. |
Master gate ( |
|
| real(kind=wp), | public, | allocatable | :: | vprec(:,:) |
Virtual precipitation (kg/m^2/s, either sign — SSS-restoring
convention; NOT wired to the restoring kernel in v1, see
|
Counted allocatable footprint of the surface flux slot (0 when unallocated). One arr_bytes term per array — add a term here when a new allocatable joins the type.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_surface_flux_t), | intent(in) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_surface_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 (AMD libomptarget cross-slot-overlap fix).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_surface_flux_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_surface_flux_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_surface_flux_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
Configure-time gate for the PR-12 component set
(&ocean_forcing_nml enable_components). init runs before the
namelist gate is known, so allocation happens HERE rather than in
init: enable = .false. (default) leaves use_components
false and allocates nothing — bit-identical, zero extra device
memory. enable = .true. allocates the full component set
(source=0.0_wp) and flips the gate so
ocean_surface_flux_assemble stops early-returning. Must be
called BEFORE enter_data (rdb_ocean_state.F90’s orchestrator)
so the freshly-allocated arrays get mapped. Re-entrant: calling
again with a different enable deallocates first.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_surface_flux_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| logical, | intent(in) | :: | enable |
Seed the atmospheric surface-pressure INPUT component
p_surf_atm (Pa) uniformly from a scalar namelist value (PR-17
&ocean_psurf_nml p_surf_const). Full overwrite of the pristine
atmospheric base; the assembled total p_surf is built from it
once per outer step in p_surf_update_seam. No-op when the
component set is not allocated (use_components=.false.) — the
&ocean_psurf_nml enable guard in validate_config already
requires enable_components=.true., so a live consumer never hits
the no-op. Host only — call enter_data afterwards (or !$acc
update device if already mapped) to sync to the GPU.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_surface_flux_t), | intent(inout) | :: | this | |||
| real(kind=wp), | intent(in) | :: | p_surf_val |
Seed the surface buoyancy restoring (MOM6 RESTOREBUOY)
parameters and set the has_restore_T / has_restore_S gates.
Sibling to set_surface_flux_const / set_sw_penetration —
kept separate so existing callers are unchanged. The piston
velocities arrive in m/day (the MOM6 FLUXCONST_* unit) and
are converted to MKS m/s here. Effective-enable guard:
has_restore_* = enable_* .and. piston /= 0, so an enabled
switch with a zero piston is a silent no-op (rather than
restoring everything toward the 0-degC / 0-PSU default target).
Host only; all knobs are read host-side as by-value arguments to
the device _impl, so no extra device sync beyond copyin(this).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_surface_flux_t), | intent(inout) | :: | this | |||
| logical, | intent(in) | :: | enable_T | |||
| logical, | intent(in) | :: | enable_S | |||
| real(kind=wp), | intent(in) | :: | piston_t_day | |||
| real(kind=wp), | intent(in) | :: | piston_s_day | |||
| real(kind=wp), | intent(in) | :: | T_target | |||
| real(kind=wp), | intent(in) | :: | S_target |
Fill Q_heat / Q_salt uniformly from scalar values and set
the has_heat / has_salt flags so the apply-tracers kernel
fires. Mirrors set_wind_stress_const on the stress side.
Host only — call enter_data afterwards (or !$acc update
device if already mapped) to sync to the GPU.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_surface_flux_t), | intent(inout) | :: | this | |||
| real(kind=wp), | intent(in) | :: | q_heat_val | |||
| real(kind=wp), | intent(in) | :: | q_salt_val |
Seed the shortwave-penetration band parameters and set the
has_sw gate (sw_pen_frac /= 0). Sibling to
set_surface_flux_const — kept separate so existing callers of
the heat/salt setter are unchanged. Host only; the scalars are
read host-side by the apply kernel (they parameterise the
by-value arguments passed into the device _impl), so no extra
device sync is needed beyond the existing copyin(this).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_surface_flux_t), | intent(inout) | :: | this | |||
| real(kind=wp), | intent(in) | :: | sw_pen_frac | |||
| real(kind=wp), | intent(in) | :: | sw_band_ratio | |||
| real(kind=wp), | intent(in) | :: | sw_zeta1 | |||
| real(kind=wp), | intent(in) | :: | sw_zeta2 | |||
| character(len=*), | intent(in), | optional | :: | sw_source |
type :: ocean_surface_flux_t logical :: is_init = .false. !! True between `init` and `destroy`. logical :: has_heat = .false. !! True when `Q_heat` carries a non-zero fill (set by !! `set_surface_flux_const` when `q_heat_val /= 0`). !! Any future field-fill path (A3 data-override, A4 restoring) !! MUST set `has_heat = .true.` after writing into `Q_heat` !! so the apply-tracers kernel fires. Host-side flag only !! (early-return guard in `ocean_surface_flux_apply_tracers`). logical :: has_salt = .false. !! True when `Q_salt` carries a non-zero fill (set by !! `set_surface_flux_const` when `q_salt_val /= 0`). !! Same contract as `has_heat` for any field-fill path. real(wp) :: rho0 = 1035.0_wp !! Boussinesq reference density (kg/m^3) — the `dt/(rho0*cp)` heat !! and `dt/rho0` salt divisors applied to EVERY surface tracer !! source, including whatever the sea-ice coupler writes into !! `Q_heat`/`Q_salt`. !! !! ASSIGNED FROM CONFIG by `configure_ocean_reference_density`, !! which copies the single rho0 of record (`&ocean_ic_nml rho_0` !! -> `eos%rho0`). The literal here is only the pre-configure !! type default; do not read it as the value a run uses. Host !! scalar: the divisor is folded into the `inv_scale` argument on !! the host, so the assignment owes no `!$acc update device`. real(wp) :: cp = SEAWATER_CP !! Specific heat capacity (J/kg/K). real(wp) :: h_min = 1.0e-3_wp !! Floor on the surface-layer thickness in the `1/h_top` !! division — keeps the kernel finite when the top layer !! pinches out. real(wp) :: Q_heat_const = 0.0_wp !! Scalar fill source for `Q_heat(:,:)`. Seeded from !! `&ocean_thermo_nml q_heat` by `set_surface_flux_const`. !! Kept for diagnostic logging; kernels read `Q_heat` directly. real(wp) :: Q_salt_const = 0.0_wp !! Scalar fill source for `Q_salt(:,:)`. Seeded from !! `&ocean_thermo_nml q_salt` by `set_surface_flux_const`. logical :: has_sw = .false. !! True when shortwave penetration is active (set by !! `set_sw_penetration` when `sw_pen_frac /= 0`). Host-side !! gate only — `ocean_surface_flux_apply_sw_penetration` !! early-returns unless this is set, so the default-off path !! leaves the surface-flux deposition byte-for-byte unchanged. logical :: sw_from_qsw = .false. !! Selects the irradiance source for shortwave penetration and !! the boundary-layer SW coupling. `.false.` (default): the !! source is the NET heat flux `Q_heat` (`sw_source="net_heat"`, !! legacy, bit-identical). `.true.` (`sw_source="q_sw"`): the !! source is the dedicated `q_sw` component (>= 0), which !! removes the night-time negative-`I0` hazard where !! `sw_pen_frac*Q_heat < 0` drives unphysical negative !! irradiance down the two-band profile. Set by !! `set_sw_penetration`; host-side gate only (never a device !! reduction) — the shim selects the source array on the host so !! the conditionally-allocated `q_sw` is never dereferenced in a !! device kernel. real(wp) :: sw_pen_frac = 0.0_wp !! Penetrating fraction of `Q_heat` carried below the surface !! layer as a two-band exponential (Paulson & Simpson 1977). !! 0 = off (all of `Q_heat` lands at `k = nz`, legacy path). real(wp) :: sw_band_ratio = 0.58_wp !! Band-1 weight `R` of the two-band irradiance decay. Jerlov !! type I (clear open ocean) default. real(wp) :: sw_zeta1 = 0.35_wp !! Band-1 e-folding depth (m) — the rapidly-absorbed !! red/near-IR band. real(wp) :: sw_zeta2 = 23.0_wp !! Band-2 e-folding depth (m) — the slowly-absorbed !! blue/green band. logical :: has_restore_T = .false. !! True when SST restoring is active (`enable_restore_temp .and. !! restore_piston_T /= 0`). Host-side gate only — !! `ocean_surface_restore_apply_tracers` early-returns unless !! this or `has_restore_S` is set, so the default-off path is !! byte-for-byte unchanged. logical :: has_restore_S = .false. !! True when SSS restoring is active (`enable_restore_salt .and. !! restore_piston_S /= 0`). real(wp) :: restore_piston_T = 0.0_wp !! SST piston velocity (m/s), seeded from `&ocean_restore_nml !! piston_t` (m/day) via `/86400`. The surface relaxation rate !! for a top layer of thickness `h_top` is !! `lambda = restore_piston_T / h_top` [1/s]. real(wp) :: restore_piston_S = 0.0_wp !! SSS piston velocity (m/s). real(wp) :: restore_T_target = 0.0_wp !! Scalar target SST (degC). Read by-value into the device !! `_impl` kernel — no per-cell field (so no extra device !! array, the `enter_data` orchestrator is untouched). A !! 2D-field target is the documented A4-v2 follow-up. real(wp) :: restore_S_target = 0.0_wp !! Scalar target SSS (PSU). real(wp), allocatable :: Q_heat(:, :) !! 2D net surface heat flux (W/m^2, positive downward), !! shape `(nx, ny)`. Fill via `set_surface_flux_const` for !! spatially-uniform forcing (the default); Area-A3 override !! or Area-A4 restoring writes the field directly. real(wp), allocatable :: Q_salt(:, :) !! 2D net surface salt flux (kg salt/m^2/s, positive salinifies), !! shape `(nx, ny)`. ! ---- PR-12 component set — allocated iff `use_components` ---- logical :: use_components = .false. !! Master gate (`&ocean_forcing_nml enable_components`). `.false.` !! (default): none of the arrays below are allocated, !! `ocean_surface_flux_assemble` is a no-op, and `Q_heat`/`Q_salt` !! are filled exactly as today — bit-identical. `.true.`: !! allocates the component set (`set_components`) and the !! assembler rebuilds `Q_heat`/`Q_salt` every thermo step. real(wp) :: q_assembled = 0.0_wp !! Host latch, 1 once `ocean_surface_flux_assemble` has derived !! `Q_heat`/`Q_salt` from the component set. From then on the !! two arrays are CARRIED state: the assembler runs at the END of !! a thermo step and the steps up to the next one read what it !! left (SST-dependent terms included), so with `use_components` !! they are checkpointed, and this latch tells a warm restart !! that the checkpointed arrays are an assembly to resume from !! (0 => an older checkpoint or none yet: the configure-time !! seed stands). A real, not a logical, because the restart !! registry carries real scalars. logical :: has_mass_flux = .false. !! Host-side latch — set by a filler after writing ANY of !! `evap`/`lprec`/`fprec`/`vprec`/`lrunoff`/`frunoff`/ !! `seaice_melt`. Cheap early-return gate for a future !! freshwater kernel (real-mass PR). Same contract as !! `has_heat` (`:56-62`) — never set from a device reduction. logical :: has_q_sw = .false. !! Host-side latch — set by a filler after writing `q_sw` !! (e.g. an ice `sw_thru` coupler). **Not** the same as !! `has_sw` below (that gates shortwave *penetration*, an !! unrelated pre-existing switch) — do not conflate the two. real(wp), allocatable :: q_sw(:, :) !! Shortwave into the ocean (W/m^2, **>= 0**, positive down). real(wp), allocatable :: q_lw(:, :) !! Net longwave (W/m^2, typically **< 0**, positive down). real(wp), allocatable :: q_lat(:, :) !! Latent heat flux (W/m^2, typically **< 0**, positive down). real(wp), allocatable :: q_sens(:, :) !! Sensible heat flux (W/m^2, typically **< 0**, positive down). real(wp), allocatable :: heat_added(:, :) !! Restoring / flux-adjustment / "other" net heat term not !! decomposed into the radiative/turbulent bands above (W/m^2, !! either sign; MOM6 `heat_added`). The v1 ice coupler's !! `heat_flux_diag` lands here (§5.4 of the PR-12 plan) — !! it is already a net W/m^2, not further decomposable. real(wp), allocatable :: heat_cavity(:, :) !! **Ice-shelf cavity basal-melt heat component** (W/m^2, same !! positive-DOWN-into-the-ocean convention as every other heat !! band; `&ocean_cavity_melt_nml`). OWNED by !! `rdb_ocean_cavity_flux`; written `heat_cavity = -q_ocean`, !! where `q_ocean = rho_w*c_w*gamma_t*(T_w - T_b) > 0` is the !! kernel's turbulent heat flux OCEAN -> INTERFACE, so warm !! water under a shelf COOLS the top of the column. It is a !! SEPARATE field from `heat_added` precisely because the !! sea-ice coupler full-overwrites `heat_added` — two writers !! on one slot clobber silently (cavity x sea ice is refused !! today, but the ownership rule must not depend on that). !! Zero unless a cavity melt step ran. real(wp), allocatable :: evap(:, :) !! Evaporative mass flux (kg/m^2/s, **<= 0** — MOM6 convention, !! `(-1)*flux out of the ocean`). v1: enthalpy + salt !! bookkeeping only — does NOT change column mass (real !! freshwater is a named follow-up, see the module docstring). real(wp), allocatable :: lprec(:, :) !! Liquid precipitation (kg/m^2/s, **>= 0** into the ocean). real(wp), allocatable :: fprec(:, :) !! Frozen precipitation / snowfall (kg/m^2/s, **>= 0**). real(wp), allocatable :: vprec(:, :) !! Virtual precipitation (kg/m^2/s, either sign — SSS-restoring !! convention; NOT wired to the restoring kernel in v1, see !! `set_restore` below and the module docstring's follow-up note). real(wp), allocatable :: lrunoff(:, :) !! Liquid river runoff (kg/m^2/s, **>= 0**). real(wp), allocatable :: frunoff(:, :) !! Frozen (calving/ice) runoff (kg/m^2/s, **>= 0**). real(wp), allocatable :: seaice_melt(:, :) !! Sea-ice melt-water mass flux (kg/m^2/s, **>0** = melt into !! the ocean, **<0** = formation / freezing withdraws mass). real(wp), allocatable :: heat_content_lprec(:, :) !! Enthalpy carried by `lprec` (W/m^2). A filler that writes !! `lprec` MUST fill this — the v1 convenience is !! `SEAWATER_CP * T_source * lprec`. The source (not the !! ocean) owns this enthalpy — see the module docstring §(d). real(wp), allocatable :: heat_content_fprec(:, :) !! Enthalpy carried by `fprec` (W/m^2). real(wp), allocatable :: heat_content_vprec(:, :) !! Enthalpy carried by `vprec` (W/m^2). real(wp), allocatable :: heat_content_lrunoff(:, :) !! Enthalpy carried by `lrunoff` (W/m^2). real(wp), allocatable :: heat_content_frunoff(:, :) !! Enthalpy carried by `frunoff` (W/m^2). real(wp), allocatable :: heat_content_seaice_melt(:, :) !! Enthalpy carried by `seaice_melt` (W/m^2). real(wp), allocatable :: heat_content_massin(:, :) !! **Assembler output — do NOT write.** Sum of the six !! `heat_content_<flux>` companions above (W/m^2, >= 0 for warm !! inflow). Filled by `ocean_surface_flux_assemble`. real(wp), allocatable :: heat_content_massout(:, :) !! **Assembler output — do NOT write.** `SEAWATER_CP * T_sst * !! evap` (W/m^2, <= 0 since `evap <= 0`) — the enthalpy the ocean !! loses with evaporating mass, computed from the ocean's own !! surface temperature (the ocean, not a filler, owns this !! number). There is deliberately NO `heat_content_evap` field !! — see the PR-12 plan §11.6. Filled by !! `ocean_surface_flux_assemble`. real(wp), allocatable :: salt_flux(:, :) !! Net surface salt-flux COMPONENT (kg salt/m^2/s, **positive !! salinifies**) — a filler writes this (e.g. the ice brine !! coupler); the assembler adds `Q_salt_const` to produce !! `Q_salt`. Virtual in v1 (no column-mass change). real(wp), allocatable :: salt_cavity(:, :) !! **Ice-shelf cavity basal-melt salt component**, same units !! and sign as `salt_flux` (positive salinifies; !! `&ocean_cavity_melt_nml`). OWNED by `rdb_ocean_cavity_flux` !! and never written by the ice coupler, which full-overwrites !! `salt_flux`. !! !! **The fixed-mass dilution equivalent.** !! !! `salt_cavity = -m_mass*(S_far - s_ice)` !! !! is the exact fixed-mass equivalent of adding mass `m_mass` at !! salinity `s_ice` — see the derivation in !! `rdb_ocean_cavity_flux`'s module docstring. Melting !! (`m_mass > 0`, `S_far > s_ice`) therefore FRESHENS. !! !! Under `&ocean_cavity_melt_nml freshwater="virtual"` (the !! default) that IS the meltwater's whole effect: no mass moves. !! !! Under `freshwater="mass"` the meltwater is a REAL volume !! source on the top layer and this component is NOT the !! salinity tendency any more — but it is STILL assembled into !! `Q_salt` unchanged, because `Q_salt` is also what KPP and !! EPBL read to build `B_0`, and this term is the dominant !! (freshening) part of the surface buoyancy flux there. !! `ocean_cavity_mass_step` takes the increment back out of the !! SALINITY TRACER (and out of the pseudo-salt mirror) in the !! same stage, as the exact negation of what !! `apply_surface_src_2d_impl` stamped. So: one field, two !! readers, and only the tracer reader is corrected. real(wp), allocatable :: p_surf_atm(:, :) !! **Input component.** Atmospheric surface-pressure load !! (Pa, >= 0). Filled by an external reader / configure-time !! scalar seed — the sea-ice path never writes this field. !! Ships zeroed with no consumer in this PR (the inverse- !! barometer PGF fold is a same-release-cycle follow-up). real(wp), allocatable :: p_surf(:, :) !! **Assembled total** (Pa, >= 0) — `p_surf_atm` plus any ice !! mass-loading term, **full overwrite, never `+=`** (a `+=` !! ratchets the load across outer steps with no bound). No !! consumer in this PR; ships zeroed alongside `p_surf_atm` so !! the follow-up PGF fold needs no further plumbing. contains procedure, non_overridable :: init => ocean_surfflux_init procedure, non_overridable :: destroy => ocean_surfflux_destroy procedure, non_overridable :: enter_data => ocean_surfflux_enter_data procedure, non_overridable :: exit_data => ocean_surfflux_exit_data procedure, non_overridable :: set_surface_flux_const => ocean_surfflux_set_const procedure, non_overridable :: set_sw_penetration => ocean_surfflux_set_sw procedure, non_overridable :: set_restore => ocean_surfflux_set_restore procedure, non_overridable :: set_components => ocean_surfflux_set_components procedure, non_overridable :: set_p_surf_const => ocean_surfflux_set_p_surf_const procedure, non_overridable :: bytes => ocean_surface_flux_bytes end type ocean_surface_flux_t