Bottom-intensified internal-tide diapycnal diffusivity. A fixed
fraction of the barotropic-to-baroclinic tidal energy conversion
E(x,y) [W m-2] dissipates locally above rough topography; the
resulting turbulent diffusivity decays exponentially upward from
the bed with scale zeta, converted to a per-layer Kd through
the stratification (1/(dz*(N^2+Omega^2))). An INTERIOR closure:
it is ADDED to the other interior diffusivities (KPP/EPBL/PP81/
kappa-shear) and goes through the single vmix_assemble gate.
References:
* Jayne & St Laurent (2001), GRL 28, “Parameterizing tidal
dissipation over rough topography” — the parameterized
conversion E = 0.5*rho*kappa*<h^2>*U_tide^2.
* St Laurent, Simmons & Garrett (2002), GRL 29, “Buoyancy forcing
by turbulence above rough topography” — the local-dissipation
fraction q and the bottom-anchored exponential vertical
structure F(z) with decay scale zeta.
* Simmons, Jayne, St Laurent & Weaver (2004), Ocean Modelling 6 —
the global implementation that combines the two.
Knob table: docs/generated_nml_knobs.md.
Discretization (conservative flux bookkeeping; St Laurent 2002):
a downward TKE flux is tracked and the power dissipated IN each
layer is converted to Kd = TKE_lay / (rho*dz*(N^2+Omega^2)).
With the Adcroft-reciprocal normalization Inv_int =
1/(1-exp(-H/zeta)) the column-integrated deposited power is
exactly q*mu*E (energy conservation, to round-off). The
continuum equivalent is
Kd(z) = [qmuE/(rho(N^2+Omega^2))] *
exp(-z/zeta) / (zeta(1-exp(-H/zeta))),
z measured UPWARD from the bed.
Interface convention (same as rdb_ocean_vmix / EPBL /
kappa-shear): kd_int(:,:,K) lives at the bottom interface of
layer K; global kd_int(:,:,1) is the bed and kd_int(:,:,nz+1)
the free surface, both forced to exactly 0. Layers are bottom-up:
k=1 bed, k=nz surface. The exp-decay anchors at the BED (k=1) and
the sweep runs k=1 -> nz. The per-layer Kd_add(k) is split 50/50
across the layer’s two bounding interfaces (St Laurent 2002
interface deposition; see divergence note D2).
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private, | parameter | :: | NZL | = | NZ_STACK_MAX |
Maximum number of layers a single column kernel can solve. |
| integer, | private, | parameter | :: | NZLI | = | NZ_STACK_MAX+1 |
Interface array dimension (= NZL + 1). |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| logical, | public | :: | e_compute | = | .false. |
v1.1 state-dependent E: when on, |
|
| real(kind=wp), | public, | allocatable | :: | e_in(:,:) |
Bottom internal-tide energy input E (W m-2), (nx,ny). |
||
| real(kind=wp), | public | :: | e_max | = | 1.0e3_wp |
TKE_itide_max cap on E (W m-2). |
|
| real(kind=wp), | public | :: | e_uniform | = | 0.0_wp |
Uniform bottom energy input E (W m-2); default 0 => inert even when enabled (structural path live, physics zero). |
|
| logical, | public | :: | enable | = | .false. |
Master switch. Default off — existing namelists and tests
stay bit-identical. Requires |
|
| type(eos_t), | public | :: | eos |
Value copy of |
|||
| real(kind=wp), | public | :: | frac_rough | = | 0.1_wp |
Roughness clamp: |
|
| real(kind=wp), | public | :: | gamma | = | 0.3333_wp |
Local-dissipation fraction |
|
| real(kind=wp), | public | :: | h2_rough | = | 0.0_wp |
Sub-grid topographic roughness variance |
|
| logical, | public | :: | is_init | = | .false. |
True between |
|
| real(kind=wp), | public | :: | kappa_h2 | = | 1.0_wp |
KAPPA_H2_FACTOR for the v1.1 E recompute. |
|
| real(kind=wp), | public | :: | kappa_itides | = | 6.2832e-4_wp |
Topographic wavenumber kappa (m^-1) for the v1.1 E recompute. |
|
| real(kind=wp), | public, | allocatable | :: | kd_int(:,:,:) |
Tidal diffusivity at interfaces (m^2/s), (nx,ny,nz+1), global bottom-up: zero at bed (K=1) and surface (K=nz+1). |
||
| real(kind=wp), | public | :: | kd_max | = | 1.0e-2_wp |
Per-layer physical Kd cap (m^2/s); < 0 => no cap. Distinct
from the |
|
| real(kind=wp), | public | :: | min_zbot | = | 0.0_wp |
Mask off where column depth H < min_zbot (m). |
|
| real(kind=wp), | public | :: | mu | = | 0.2_wp |
Mixing efficiency Gamma_mix (MU_ITIDES). |
|
| real(kind=wp), | public | :: | omega2 | = | OMEGA_EARTH**2 |
Rotation floor Omega^2 (s^-2) on N^2; physics, not merely a 1/0 guard. The floor is plain Omega^2 (Melet et al. 2013 efficiency rescaling N^2/(N^2+Omega^2)), not (2*Omega)^2. |
|
| real(kind=wp), | public | :: | prandtl_tidal | = | 1.0_wp |
Kv = prandtl_tidal * Kd into the momentum solve. |
|
| real(kind=wp), | public | :: | rho0 | = | 1035.0_wp |
Boussinesq reference density (kg/m^3). |
|
| real(kind=wp), | public | :: | utide | = | 0.0_wp |
RMS barotropic tidal velocity amplitude (m/s) for v1.1 E. |
|
| real(kind=wp), | public | :: | zeta | = | 500.0_wp |
Bottom decay scale (m) (INT_TIDE_DECAY_SCALE). |
| procedure, public, non_overridable :: bytes => ocean_tidal_mixing_bytes | |
| procedure, public, non_overridable :: destroy => ocean_tidal_mixing_destroy | |
| procedure, public, non_overridable :: enter_data => ocean_tidal_mixing_enter_data | |
| procedure, public, non_overridable :: exit_data => ocean_tidal_mixing_exit_data | |
| procedure, public, non_overridable :: init => ocean_tidal_mixing_init | |
| procedure, public, non_overridable :: set_e_uniform => ocean_tidal_mixing_set_e_uniform |
.true. iff tidal mixing is enabled but has no energy source
(PR-6 fail-loud): enable .and. e_uniform <= 0 .and. .not.
e_compute. The bottom-intensified diffusivity Kd ∝ E, so a
zero prescribed e_uniform with the e_compute estimator off
makes Kd ≡ 0 exactly — the closure runs its whole flux sweep
for nothing. e_compute=.true. supplies E internally, so that
is NOT inert; a disabled closure is not “inert” either (it is
simply off). Drives a configure abort.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| logical, | intent(in) | :: | enable | |||
| real(kind=wp), | intent(in) | :: | e_uniform | |||
| logical, | intent(in) | :: | e_compute |
Counted allocatable footprint of the tidal mixing 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_tidal_mixing_t), | intent(in) | :: | this |
Run tidal mixing over the domain: fill this%kd_int (interface
diffusivity). Call at thermo cadence with the thermo dt.
Outer shim: dereferences the tracer-registry hTr arrays on the
host (the array-of-DT indirection blocks NVHPC device codegen),
then forwards to the column kernel. dt is unused (the steady
diagnostic Kd does not integrate in time) but carried for
signature parity with the other interior closures.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_tidal_mixing_t), | intent(inout) | :: | this | |||
| type(multilayer_state_t), | intent(in) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt |
Fold the tidal diffusivity into the vmix interface fields,
ADDITIVELY (interior-diffusivity semantics; St Laurent tidal
mixing is an interior source like kappa-shear). Called EVERY
stage (PP81 rewrites kv/kt each stage; kd_int itself refreshes
at thermo cadence). Interior interfaces only — K=1 (bed) and
K=nzp1 (surface) stay zero in both source and target.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_tidal_mixing_t), | intent(in) | :: | this | |||
| integer, | intent(in) | :: | nx |
Interface-field extents (explicit shape: assumed-shape
dummies in a |
||
| integer, | intent(in) | :: | ny |
Interface-field extents (explicit shape: assumed-shape
dummies in a |
||
| integer, | intent(in) | :: | nzp1 |
Interface-field extents (explicit shape: assumed-shape
dummies in a |
||
| real(kind=wp), | intent(inout) | :: | kv(nx,ny,nzp1) |
Momentum viscosity at interfaces; gets prandtl_tidal*kd. |
||
| real(kind=wp), | intent(inout) | :: | kt(nx,ny,nzp1) |
Tracer diffusivity at interfaces; gets kd. |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_tidal_mixing_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_tidal_mixing_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_tidal_mixing_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_tidal_mixing_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_tidal_mixing_t), | intent(inout) | :: | this |
Allocate the persistent fields. Always allocates (configure
runs after init, so enable is not known yet); the off-cost is
one 2D field + one interface field.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_tidal_mixing_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in), | optional | :: | nz_ml |
Fill the bottom energy field e_in with a uniform value.
Host loop (setup phase); call after init, before enter_data.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_tidal_mixing_t), | intent(inout) | :: | this | |||
| real(kind=wp), | intent(in) | :: | e_value |
Per-column St-Laurent flux-bookkeeping sweep. One
do concurrent (j, i) over owned cells; each column is a serial
upward sweep k=1(bed) -> nz(surface) over fixed-size local()
arrays (register-resident). Bottom-up global indexing
throughout — no surface-down flip (the decay anchors at the bed).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_tidal_mixing_t), | intent(inout) | :: | this | |||
| type(multilayer_state_t), | intent(in) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | hT(:,:,:) |
Temperature tracer hTr (degC*m), host-dereferenced. |
||
| real(kind=wp), | intent(in) | :: | hS(:,:,:) |
Salinity tracer hTr (PSU*m), host-dereferenced. |