rdb_ocean_surface_flux Module


Uses

  • module~~rdb_ocean_surface_flux~~UsesGraph module~rdb_ocean_surface_flux rdb_ocean_surface_flux iso_fortran_env iso_fortran_env module~rdb_ocean_surface_flux->iso_fortran_env module~rdb_constants rdb_constants module~rdb_ocean_surface_flux->module~rdb_constants module~rdb_grid rdb_grid module~rdb_ocean_surface_flux->module~rdb_grid module~rdb_mem_report rdb_mem_report module~rdb_ocean_surface_flux->module~rdb_mem_report module~rdb_multilayer_state rdb_multilayer_state module~rdb_ocean_surface_flux->module~rdb_multilayer_state pic_types pic_types module~rdb_constants->pic_types 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_efp->iso_fortran_env ieee_arithmetic ieee_arithmetic module~rdb_efp->ieee_arithmetic module~rdb_error_ring->pic_logger 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_surface_flux~~UsedByGraph module~rdb_ocean_surface_flux rdb_ocean_surface_flux module~rdb_ice_basal_flux rdb_ice_basal_flux module~rdb_ice_basal_flux->module~rdb_ocean_surface_flux module~rdb_ice_frazil rdb_ice_frazil module~rdb_ice_frazil->module~rdb_ocean_surface_flux module~rdb_ice_ocean_coupler rdb_ice_ocean_coupler module~rdb_ice_ocean_coupler->module~rdb_ocean_surface_flux module~rdb_ocean_cavity_flux rdb_ocean_cavity_flux module~rdb_ocean_cavity_flux->module~rdb_ocean_surface_flux module~rdb_ocean_data_forcing rdb_ocean_data_forcing module~rdb_ocean_data_forcing->module~rdb_ocean_surface_flux module~rdb_ocean_dyn rdb_ocean_dyn module~rdb_ocean_dyn->module~rdb_ocean_surface_flux module~rdb_ocean_dyn->module~rdb_ocean_cavity_flux module~rdb_ocean_epbl rdb_ocean_epbl module~rdb_ocean_dyn->module~rdb_ocean_epbl module~rdb_ocean_geothermal rdb_ocean_geothermal module~rdb_ocean_dyn->module~rdb_ocean_geothermal module~rdb_ocean_vmix rdb_ocean_vmix module~rdb_ocean_dyn->module~rdb_ocean_vmix module~rdb_ocean_mle rdb_ocean_mle module~rdb_ocean_dyn->module~rdb_ocean_mle module~rdb_continuity rdb_continuity module~rdb_ocean_dyn->module~rdb_continuity module~rdb_ocean_engine rdb_ocean_engine module~rdb_ocean_engine->module~rdb_ocean_surface_flux module~rdb_ocean_engine->module~rdb_ice_basal_flux module~rdb_ocean_engine->module~rdb_ice_frazil module~rdb_ocean_engine->module~rdb_ice_ocean_coupler module~rdb_ocean_engine->module~rdb_ocean_cavity_flux module~rdb_ocean_engine->module~rdb_ocean_data_forcing module~rdb_ocean_engine->module~rdb_ocean_dyn module~rdb_ocean_engine->module~rdb_ocean_geothermal module~rdb_ocean_setup rdb_ocean_setup module~rdb_ocean_engine->module~rdb_ocean_setup 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_ice_transport rdb_ice_transport module~rdb_ocean_engine->module~rdb_ice_transport module~rdb_ocean_epbl->module~rdb_ocean_surface_flux module~rdb_ocean_geothermal->module~rdb_ocean_surface_flux module~rdb_ocean_setup->module~rdb_ocean_surface_flux module~rdb_ocean_setup->module~rdb_ocean_dyn module~rdb_ocean_setup->module~rdb_ocean_epbl module~rdb_ocean_setup->module~rdb_ocean_geothermal module~rdb_ocean_setup->module~rdb_ocean_state module~rdb_ocean_setup->module~rdb_ocean_vmix module~rdb_ocean_state->module~rdb_ocean_surface_flux module~rdb_ocean_state->module~rdb_ocean_cavity_flux module~rdb_ocean_state->module~rdb_ocean_data_forcing module~rdb_ocean_state->module~rdb_ocean_dyn module~rdb_ocean_state->module~rdb_ocean_epbl module~rdb_ocean_state->module~rdb_ocean_vmix module~rdb_ocean_state->module~rdb_ocean_mle module~rdb_ocean_state->module~rdb_continuity module~rdb_ocean_vmix->module~rdb_ocean_surface_flux proc~validate_config validate_config proc~validate_config->module~rdb_ocean_surface_flux proc~validate_config->module~rdb_ocean_vmix 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_mle->module~rdb_ocean_epbl module~rdb_continuity->module~rdb_ocean_mle module~rdb_ice_transport->module~rdb_continuity

Variables

Type Visibility Attributes Name Initial
real(kind=wp), public, parameter :: SEAWATER_CP = 3992.0_wp
real(kind=wp), private, parameter :: SECONDS_PER_DAY = 86400.0_wp

Derived Types

type, public ::  ocean_surface_flux_t

Components

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

2D net surface salt flux (kg salt/m^2/s, positive salinifies), shape (nx, ny).

real(kind=wp), public :: Q_salt_const = 0.0_wp

Scalar fill source for Q_salt(:,:). Seeded from &ocean_thermo_nml q_salt by set_surface_flux_const.

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, (-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(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 1/h_top division — keeps the kernel finite when the top layer pinches out.

logical, public :: 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, public :: 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, public :: 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.

logical, public :: has_restore_S = .false.

True when SSS restoring is active (enable_restore_salt .and. restore_piston_S /= 0).

logical, public :: 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, public :: 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.

logical, public :: 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.

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 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(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; &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(kind=wp), public, allocatable :: heat_content_fprec(:,:)

Enthalpy carried by fprec (W/m^2).

real(kind=wp), public, allocatable :: heat_content_frunoff(:,:)

Enthalpy carried by frunoff (W/m^2).

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

Enthalpy carried by lrunoff (W/m^2).

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

Enthalpy carried by seaice_melt (W/m^2).

real(kind=wp), public, allocatable :: heat_content_vprec(:,:)

Enthalpy carried by vprec (W/m^2).

logical, public :: is_init = .false.

True between init and destroy.

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

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

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

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

Read more…
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 Q_salt_const to produce Q_salt. Virtual in v1 (no column-mass change).

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 R of the two-band irradiance decay. Jerlov type I (clear open ocean) default.

logical, public :: 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(kind=wp), public :: 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(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 (&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(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 set_restore below and the module docstring’s follow-up note).

Type-Bound Procedures

procedure, public, non_overridable :: bytes => ocean_surface_flux_bytes
procedure, public, non_overridable :: destroy => ocean_surfflux_destroy
procedure, public, non_overridable :: enter_data => ocean_surfflux_enter_data
procedure, public, non_overridable :: exit_data => ocean_surfflux_exit_data
procedure, public, non_overridable :: init => ocean_surfflux_init
procedure, public, non_overridable :: set_components => ocean_surfflux_set_components
procedure, public, non_overridable :: set_p_surf_const => ocean_surfflux_set_p_surf_const
procedure, public, non_overridable :: set_restore => ocean_surfflux_set_restore
procedure, public, non_overridable :: set_surface_flux_const => ocean_surfflux_set_const
procedure, public, non_overridable :: set_sw_penetration => ocean_surfflux_set_sw

Functions

public pure function sw_pe_cost_shape(tau) result(phi)

In-layer potential-energy-cost shape function Phi(tau) for the EPBL TKE ledger, tau = h/zeta the in-layer optical depth of a single band. It is the fraction of the pure-skin PE cost that homogenising an EXPONENTIALLY distributed in-layer heating actually incurs (Paulson & Simpson 1977 profile; the EPBL energetics of Reichl & Hallberg 2018):

Read more…

Arguments

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

Return Value real(kind=wp)

public pure function sw_source_is_implemented(name) result(ok)

Fail-loud predicate for the &ocean_thermo_nml sw_source selector — validate_config aborts on any string this rejects. The two recognised sources are the net-heat legacy path and the PR-12 q_sw component.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: name

Return Value logical

public pure function sw_transmission(d, R, zeta1, zeta2) result(trans)

Two-band (Paulson & Simpson 1977) normalised downward irradiance transmission at depth d below the free surface, T(d) = R·exp(-d/zeta1) + (1-R)·exp(-d/zeta2), T(0) = 1. This is THE single shared definition — the SW deposition kernel, the KPP MXL_SW/LV1_SW boundary-layer correction, and the EPBL in-layer PE-cost ledger all consume it, so the three consumers cannot disagree about where the sunlight went. Marked !$acc routine seq so it inlines into same-module device kernels and is callable from cross-module do concurrent kernels.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: d
real(kind=wp), intent(in) :: R
real(kind=wp), intent(in) :: zeta1
real(kind=wp), intent(in) :: zeta2

Return Value real(kind=wp)

private pure function ocean_surface_flux_bytes(this) result(nbytes)

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.

Arguments

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

Return Value integer(kind=int64)


Subroutines

public pure subroutine ocean_surface_flux_apply_cover_const(sf, cover_frac)

Mask the STATIC scalar Q_heat / Q_salt fill with the ice-shelf cover, for the use_components = .false. path only.

Read more…

Arguments

Type IntentOptional Attributes Name
type(ocean_surface_flux_t), intent(inout) :: sf
real(kind=wp), intent(in) :: cover_frac(:,:)

Ice-cover fraction at cell centres (metrics%cover_frac).

public subroutine ocean_surface_flux_apply_sw_penetration(grid, sf, ms, dt, active, cover_frac)

Additive correction that redistributes the penetrating shortwave fraction of Q_heat through the upper water column as a two-band exponential (Paulson & Simpson 1977; Jerlov types), instead of leaving all of it deposited at the surface layer by ocean_surface_flux_apply_tracers.

Read more…

Arguments

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

Optional — absent ⇒ no-op (no forcing configured).

type(multilayer_state_t), intent(inout) :: ms
real(kind=wp), intent(in) :: dt
logical, intent(in), optional :: active

Optional thermo-cadence gate. Present-and-false ⇒ early return; absent ⇒ kernel runs.

real(kind=wp), intent(in), optional :: cover_frac(:,:)

Optional ice-shelf cover fraction (metrics%cover_frac, v1 binary). Present ⇒ the penetrating irradiance is scaled by 1 - cover_frac, so a covered column absorbs NOTHING — no sunlight reaches the ocean through several hundred metres of ice. Needed even on the sw_source="net_heat" branch, where Q_heat is already assembler-masked: this kernel’s job is to MOVE a surface lump down the column, and on a masked column the lump it would remove was never deposited (the same argument &ocean_wetdry_nml makes for a dry column). Absent ⇒ the original kernel, byte-identical.

public subroutine ocean_surface_flux_apply_tracers(grid, sf, ms, dt, active, wet_dyn)

Add the surface heat + salt fluxes directly to the top tracer layer. Operates in hTr space (concentration· thickness): for temperature d(hT_top)/dt = Q_heat(i,j) / (rho_0 · cp) For salinity d(hS_top)/dt = Q_salt(i,j) / rho_0 (Both expressed in units that match the hTr convention: hTr = T·h so the forcing has units of T·h/s = K·m/s. Q_heat / (rho_0·cp) has units (W/m^2)/(kg/m^3·J/kg/K) = K·m/s ✓.)

Read more…

Arguments

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

Optional — when absent the kernel is a no-op (no surface forcing configured).

type(multilayer_state_t), intent(inout) :: ms
real(kind=wp), intent(in) :: dt
logical, intent(in), optional :: active

Optional gate (thermo cadence). Absent ⇒ kernel runs; present-and-false ⇒ early return.

real(kind=wp), intent(in), optional :: wet_dyn(:,:)

Optional DYNAMIC cell wet mask (wet/dry, docs/ocean_wetdry_plan.md §4.4) composed multiplicatively with the static ms%wet_mask — surface fluxes must not enter a dynamically dry column (heating a mm-scale residual sliver blows its temperature up). Absent ⇒ the original static-mask path, byte-identical.

public pure subroutine ocean_surface_flux_assemble(grid, sf, ms, active, cover_frac)

The single gate that derives Q_heat/Q_salt from the component set (§3.1/§3.3 of the PR-12 plan) — the exact analogue of vmix_assemble: fillers contribute components, this routine alone derives the net fields every downstream kernel reads. A no-op unless sf%use_components — with components off, Q_heat / Q_salt are exactly what set_surface_flux_const (or a field-override path) left them, byte-for-byte.

Read more…

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
type(ocean_surface_flux_t), intent(inout) :: sf
type(multilayer_state_t), intent(in) :: ms
logical, intent(in), optional :: active

Optional thermo-cadence gate. Present-and-false ⇒ early return; absent ⇒ kernel runs (matches ocean_surface_flux_apply_tracers’s convention).

real(kind=wp), intent(in), optional :: cover_frac(:,:)

Optional ice-shelf cover fraction (metrics%cover_frac, v1 binary). Present ⇒ every ATMOSPHERIC contribution (Q_heat_const, q_sw, q_lw, q_lat, q_sens, heat_added, both mass-enthalpy terms, Q_salt_const, salt_flux) is scaled by 1 - cover_frac, while the cavity’s OWN heat_cavity / salt_cavity pass through unmasked. This is the single place those two groups are still distinguishable — see the module docstring for why the mask lives here and not at apply time. Absent ⇒ the original kernel, byte-identical.

public subroutine ocean_surface_restore_apply_tracers(grid, sf, ms, dt, active, cover_frac)

Surface buoyancy restoring (MOM6 RESTOREBUOY): relax the top-layer (k = nz) temperature / salinity toward scalar targets with a piston velocity p [m/s]. Unlike ocean_surface_flux_apply_tracers (which reads a pre-filled static Q_* field), the restoring flux is DYNAMIC — it depends on the live SST / SSS each thermo step — so it is computed in-kernel from (target - surface_concentration) rather than a stored field. This keeps the const-flux path byte-for-byte unchanged and adds no second device sync of Q_*.

Read more…

Arguments

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

Optional — absent ⇒ no-op (no forcing configured).

type(multilayer_state_t), intent(inout) :: ms
real(kind=wp), intent(in) :: dt
logical, intent(in), optional :: active

Optional thermo-cadence gate. Present-and-false ⇒ early return; absent ⇒ kernel runs.

real(kind=wp), intent(in), optional :: cover_frac(:,:)

Optional ice-shelf cover fraction (metrics%cover_frac, v1 binary). Present ⇒ the restoring increment is scaled by 1 - cover_frac, so a covered column is NOT relaxed toward an atmospheric target — under a shelf the surface is a melting ice interface, and restoring there would overwhelm the melt signal with a number the atmosphere never set. Absent ⇒ the original kernel, byte-identical.

private pure subroutine apply_surface_restore_2d_cover_impl(hTr, budget, h_layer, wet_mask, cover_frac, dt_piston, tgt, h_min, nz, nx, ny)

Ice-shelf-cover twin of apply_surface_restore_2d_impl: the open-water factor 1 - cover_frac composes multiplicatively with wet_mask, so a covered column receives EXACTLY zero restoring — and, because the same factor multiplies the budget mirror, exactly zero restoring shows up in the heat/salt surface budget there too. Separate _impl, not an in-loop present() test (house idiom).

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: hTr(nx,ny,nz)
real(kind=wp), intent(inout) :: budget(nx,ny,nz)
real(kind=wp), intent(in) :: h_layer(nx,ny,nz)
real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: cover_frac(nx,ny)
real(kind=wp), intent(in) :: dt_piston
real(kind=wp), intent(in) :: tgt
real(kind=wp), intent(in) :: h_min
integer, intent(in) :: nz
integer, intent(in) :: nx
integer, intent(in) :: ny

private pure subroutine apply_surface_restore_2d_impl(hTr, budget, h_layer, wet_mask, dt_piston, tgt, h_min, nz, nx, ny)

Stamp the per-step restoring increment dt·p·(target - surf)· wet_mask onto the top layer (k = nz) of a tracer’s hTr array and mirror it into the matching budget contributor. Explicit-shape dummies so NVHPC stdpar compiles device kernels against static bounds.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: hTr(nx,ny,nz)
real(kind=wp), intent(inout) :: budget(nx,ny,nz)
real(kind=wp), intent(in) :: h_layer(nx,ny,nz)
real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: dt_piston
real(kind=wp), intent(in) :: tgt
real(kind=wp), intent(in) :: h_min
integer, intent(in) :: nz
integer, intent(in) :: nx
integer, intent(in) :: ny

private pure subroutine apply_surface_src_2d_dyn_impl(hTr, budget, wet_mask, wet_dyn, Q_field, inv_scale, k_top, nz, nx, ny)

Wet/dry variant of apply_surface_src_2d_impl: the DYNAMIC cell wet mask composes multiplicatively with the static one, so a dynamically dry column (total depth below &ocean_wetdry_nml dry_depth) receives NO surface flux — heating a mm-scale residual sliver would blow its temperature up (docs/ocean_wetdry_plan.md §4.4). Separate _impl (not an in-loop optional test): the knob-off path keeps the original kernel untouched, byte-identical.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: hTr(nx,ny,nz)
real(kind=wp), intent(inout) :: budget(nx,ny,nz)
real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: wet_dyn(nx,ny)
real(kind=wp), intent(in) :: Q_field(nx,ny)
real(kind=wp), intent(in) :: inv_scale
integer, intent(in) :: k_top(nx,ny)

See apply_surface_src_2d_impl.

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

private pure subroutine apply_surface_src_2d_dyn_nobudget_impl(hTr, wet_mask, wet_dyn, Q_field, inv_scale, k_top, nz, nx, ny)

Wet/dry NOBUDGET twin — see apply_surface_src_2d_nobudget_impl and apply_surface_src_2d_dyn_impl.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: hTr(nx,ny,nz)
real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: wet_dyn(nx,ny)
real(kind=wp), intent(in) :: Q_field(nx,ny)
real(kind=wp), intent(in) :: inv_scale
integer, intent(in) :: k_top(nx,ny)

See apply_surface_src_2d_impl.

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

private pure subroutine apply_surface_src_2d_impl(hTr, budget, wet_mask, Q_field, inv_scale, k_top, nz, nx, ny)

Stamp inv_scale · Q_field(i,j) · wet_mask(i,j) onto the first LIVE layer (k_top(i,j)) of a tracer’s hTr array, mirror into the matching budget contributor. Explicit-shape dummies so NVHPC stdpar can compile device kernels against static bounds.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: hTr(nx,ny,nz)
real(kind=wp), intent(inout) :: budget(nx,ny,nz)
real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: Q_field(nx,ny)
real(kind=wp), intent(in) :: inv_scale
integer, intent(in) :: k_top(nx,ny)

ms%k_top — the first LIVE layer counting down from the top. nz on every column that has no top-side filler (which is every column on every coordinate but z_fixed under a rigid top), so this reads the same memory as the literal nz it replaced and the arithmetic is bit-identical.

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

private pure subroutine apply_surface_src_2d_nobudget_impl(hTr, wet_mask, Q_field, inv_scale, k_top, nz, nx, ny)

Byte-for-byte copy of apply_surface_src_2d_impl with the budget dummy and its accumulation line removed — the pseudo-salt mirror of salinity’s surface flux, which by contract (budget_id = TRACER_BUDGET_NONE) must not touch salt_budget_surface. Separate _impl, not an in-loop present(budget) test (house idiom, see apply_surface_src_2d_dyn_impl’s docstring) — this keeps the production S/T impl untouched and the increment hTr receives bit-identical to salinity’s.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: hTr(nx,ny,nz)
real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: Q_field(nx,ny)
real(kind=wp), intent(in) :: inv_scale
integer, intent(in) :: k_top(nx,ny)

See apply_surface_src_2d_impl. The SAME index salinity used, so the pseudo-salt increment stays bit-identical to salinity’s and the deviation keeps measuring transport.

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

private pure subroutine apply_sw_penetration_cover_impl(hTr, budget, h_layer, k_bot, wet_mask, cover_frac, sw_src, inv_scale, sw_pen_frac, R, zeta1, zeta2, nz, nx, ny)

Ice-shelf-cover twin of apply_sw_penetration_impl: the open-water factor 1 - cover_frac composes multiplicatively with wet_mask into the column irradiance I0, so a fully covered column neither removes the surface lump nor deposits a profile — it is left EXACTLY untouched. Separate _impl, not an in-loop present() test (house idiom, see apply_surface_src_2d_dyn_impl) — the cover-off path keeps the original kernel byte-identical.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: hTr(nx,ny,nz)
real(kind=wp), intent(inout) :: budget(nx,ny,nz)
real(kind=wp), intent(in) :: h_layer(nx,ny,nz)
integer, intent(in) :: k_bot(nx,ny)

ms%k_bot — the first LIVE layer counting up from the bed. The opaque-bed residual lands HERE, not on k = 1: under z_fixed the layers below are inert fillers (1 elsewhere ⇒ unchanged).

real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: cover_frac(nx,ny)
real(kind=wp), intent(in) :: sw_src(nx,ny)
real(kind=wp), intent(in) :: inv_scale
real(kind=wp), intent(in) :: sw_pen_frac
real(kind=wp), intent(in) :: R
real(kind=wp), intent(in) :: zeta1
real(kind=wp), intent(in) :: zeta2
integer, intent(in) :: nz
integer, intent(in) :: nx
integer, intent(in) :: ny

private pure subroutine apply_sw_penetration_impl(hTr, budget, h_layer, k_bot, wet_mask, sw_src, inv_scale, sw_pen_frac, R, zeta1, zeta2, nz, nx, ny)

Per-column two-band shortwave redistribution. Explicit-shape dummies so NVHPC stdpar compiles device kernels against static bounds. Difference form (I(d_top) - I(d_bot)) — no division by h, so a vanishing layer (h → 0 ⇒ d_top == d_bot) absorbs zero automatically with no guard. The transmission T(d) is the shared sw_transmission (same-module ⇒ inlined by NVHPC), so the deposition and the boundary-layer coupling cannot diverge.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: hTr(nx,ny,nz)
real(kind=wp), intent(inout) :: budget(nx,ny,nz)
real(kind=wp), intent(in) :: h_layer(nx,ny,nz)
integer, intent(in) :: k_bot(nx,ny)

ms%k_bot — the first LIVE layer counting up from the bed. The opaque-bed residual lands HERE, not on k = 1: under z_fixed the layers below are inert fillers (1 elsewhere ⇒ unchanged).

real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: sw_src(nx,ny)
real(kind=wp), intent(in) :: inv_scale
real(kind=wp), intent(in) :: sw_pen_frac
real(kind=wp), intent(in) :: R
real(kind=wp), intent(in) :: zeta1
real(kind=wp), intent(in) :: zeta2
integer, intent(in) :: nz
integer, intent(in) :: nx
integer, intent(in) :: ny

private subroutine ocean_surfflux_alloc_components(this, grid)

Allocate the 22-field component set + the two p_surf* fields, all source=0.0_wp, shape (nx_total, ny_total). Private — called only from set_components.

Arguments

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

private pure subroutine ocean_surfflux_assemble_cover_impl(heat_content_massin, heat_content_massout, Q_heat, Q_salt, q_sw, q_lw, q_lat, q_sens, heat_added, heat_cavity, heat_content_lprec, heat_content_fprec, heat_content_vprec, heat_content_lrunoff, heat_content_frunoff, heat_content_seaice_melt, evap, salt_flux, salt_cavity, hTr_T, h_layer, wet_mask, cover_frac, Q_heat_const, Q_salt_const, cp, h_min, nz, nx, ny)

Ice-shelf-cover twin of ocean_surfflux_assemble_impl: the open-water factor open_f = 1 - cover_frac multiplies the ATMOSPHERIC group and NOT the cavity group. Grouping, spelt out because it is the whole point of this kernel:

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: heat_content_massin(nx,ny)
real(kind=wp), intent(inout) :: heat_content_massout(nx,ny)
real(kind=wp), intent(inout) :: Q_heat(nx,ny)
real(kind=wp), intent(inout) :: Q_salt(nx,ny)
real(kind=wp), intent(in) :: q_sw(nx,ny)
real(kind=wp), intent(in) :: q_lw(nx,ny)
real(kind=wp), intent(in) :: q_lat(nx,ny)
real(kind=wp), intent(in) :: q_sens(nx,ny)
real(kind=wp), intent(in) :: heat_added(nx,ny)
real(kind=wp), intent(in) :: heat_cavity(nx,ny)
real(kind=wp), intent(in) :: heat_content_lprec(nx,ny)
real(kind=wp), intent(in) :: heat_content_fprec(nx,ny)
real(kind=wp), intent(in) :: heat_content_vprec(nx,ny)
real(kind=wp), intent(in) :: heat_content_lrunoff(nx,ny)
real(kind=wp), intent(in) :: heat_content_frunoff(nx,ny)
real(kind=wp), intent(in) :: heat_content_seaice_melt(nx,ny)
real(kind=wp), intent(in) :: evap(nx,ny)
real(kind=wp), intent(in) :: salt_flux(nx,ny)
real(kind=wp), intent(in) :: salt_cavity(nx,ny)
real(kind=wp), intent(in) :: hTr_T(nx,ny,nz)
real(kind=wp), intent(in) :: h_layer(nx,ny,nz)
real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: cover_frac(nx,ny)
real(kind=wp), intent(in) :: Q_heat_const
real(kind=wp), intent(in) :: Q_salt_const
real(kind=wp), intent(in) :: cp
real(kind=wp), intent(in) :: h_min
integer, intent(in) :: nz
integer, intent(in) :: nx
integer, intent(in) :: ny

private pure subroutine ocean_surfflux_assemble_impl(heat_content_massin, heat_content_massout, Q_heat, Q_salt, q_sw, q_lw, q_lat, q_sens, heat_added, heat_cavity, heat_content_lprec, heat_content_fprec, heat_content_vprec, heat_content_lrunoff, heat_content_frunoff, heat_content_seaice_melt, evap, salt_flux, salt_cavity, hTr_T, h_layer, wet_mask, Q_heat_const, Q_salt_const, cp, h_min, nz, nx, ny)

Flat do concurrent kernel — explicit-shape dummies, integer dims declared first (decl-order, ifx #8586). See ocean_surface_flux_assemble for the physics; this is the arithmetic verbatim.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: heat_content_massin(nx,ny)
real(kind=wp), intent(inout) :: heat_content_massout(nx,ny)
real(kind=wp), intent(inout) :: Q_heat(nx,ny)
real(kind=wp), intent(inout) :: Q_salt(nx,ny)
real(kind=wp), intent(in) :: q_sw(nx,ny)
real(kind=wp), intent(in) :: q_lw(nx,ny)
real(kind=wp), intent(in) :: q_lat(nx,ny)
real(kind=wp), intent(in) :: q_sens(nx,ny)
real(kind=wp), intent(in) :: heat_added(nx,ny)
real(kind=wp), intent(in) :: heat_cavity(nx,ny)
real(kind=wp), intent(in) :: heat_content_lprec(nx,ny)
real(kind=wp), intent(in) :: heat_content_fprec(nx,ny)
real(kind=wp), intent(in) :: heat_content_vprec(nx,ny)
real(kind=wp), intent(in) :: heat_content_lrunoff(nx,ny)
real(kind=wp), intent(in) :: heat_content_frunoff(nx,ny)
real(kind=wp), intent(in) :: heat_content_seaice_melt(nx,ny)
real(kind=wp), intent(in) :: evap(nx,ny)
real(kind=wp), intent(in) :: salt_flux(nx,ny)
real(kind=wp), intent(in) :: salt_cavity(nx,ny)
real(kind=wp), intent(in) :: hTr_T(nx,ny,nz)
real(kind=wp), intent(in) :: h_layer(nx,ny,nz)
real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: Q_heat_const
real(kind=wp), intent(in) :: Q_salt_const
real(kind=wp), intent(in) :: cp
real(kind=wp), intent(in) :: h_min
integer, intent(in) :: nz
integer, intent(in) :: nx
integer, intent(in) :: ny

private pure subroutine ocean_surfflux_cover_const_impl(Q_heat, Q_salt, cover_frac, nx, ny)

Flat do concurrent kernel behind ocean_surface_flux_apply_cover_const — explicit-shape dummies, integer dims first (decl-order, ifx #8586).

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: Q_heat(nx,ny)
real(kind=wp), intent(inout) :: Q_salt(nx,ny)
real(kind=wp), intent(in) :: cover_frac(nx,ny)
integer, intent(in) :: nx
integer, intent(in) :: ny

private subroutine ocean_surfflux_dealloc_components(this)

Deallocate the component set (no-op on an already-unallocated slot — every deallocate is if (allocated(...))-guarded). Shared by destroy and by set_components re-entry.

Arguments

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

private subroutine ocean_surfflux_destroy(this)

Arguments

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

private subroutine ocean_surfflux_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 (AMD libomptarget cross-slot-overlap fix).

Arguments

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

private subroutine ocean_surfflux_enter_data_impl(this)

Arguments

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

private subroutine ocean_surfflux_exit_data(this)

Arguments

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

private subroutine ocean_surfflux_exit_data_impl(this)

Arguments

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

private subroutine ocean_surfflux_init(this, grid)

Arguments

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

private subroutine ocean_surfflux_set_components(this, grid, enable)

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.

Arguments

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

private subroutine ocean_surfflux_set_const(this, q_heat_val, q_salt_val)

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.

Arguments

Type IntentOptional 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

private subroutine ocean_surfflux_set_p_surf_const(this, p_surf_val)

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.

Read more…

Arguments

Type IntentOptional Attributes Name
class(ocean_surface_flux_t), intent(inout) :: this
real(kind=wp), intent(in) :: p_surf_val

private subroutine ocean_surfflux_set_restore(this, enable_T, enable_S, piston_t_day, piston_s_day, T_target, S_target)

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

Arguments

Type IntentOptional 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

private subroutine ocean_surfflux_set_sw(this, sw_pen_frac, sw_band_ratio, sw_zeta1, sw_zeta2, sw_source)

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

Read more…

Arguments

Type IntentOptional 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