Prognostic interior shear-mixing closure: shear-driven turbulence is modelled as a diffusivity field kappa(z) and a TKE field Q(z) at layer interfaces, coupled through two steady-state vertical diffusion-reaction equations solved per column, iteratively to convergence, with internal adaptive time-substepping as the column re-stratifies within one model step. Unlike algebraic Richardson-number schemes (PP81, LMD94) the diffusivity diffuses in z with a stratification/rotation/boundary-limited decay length, so resolved shear layers entrain at the right rate even when the Richardson number is marginal; the closure is self-limiting and relaxes the column toward Ri >~ Ri_c.
Reference: Jackson, Hallberg & Legg (2008), “A Parameterization
of Shear-Driven Turbulence for Ocean Climate Models”, J. Phys.
Oceanogr. 38, 1033-1053. Knob table: docs/generated_nml_knobs.md.
Place in the stack: an INTERIOR closure. It coexists with the
surface boundary-layer schemes (KPP or EPBL) and with
PP81/background; its kappa is ADDED to the other interior
diffusivities (kt += kd_int) and its viscosity (prandtl_turb *
kd_int) added to kv. Not mutually exclusive with anything.
Runs at thermo cadence (kappa_shear_compute); the merge into
vmix%kv / vmix%kt runs every RK2 stage
(kappa_shear_merge_into_kv_kt).
Interface convention (same as rdb_ocean_vmix / EPBL):
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 column solver itself runs surface-down (local
k=1 = surface); the gather/scatter loops carry the index flip
(global K = nz+2 - K_local).
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private, | parameter | :: | H_TINY_CORNER | = | 0.5_wp*H_DIV_EPS |
Sub-roundoff thickness added to the 2-point thickness-weight denominator of the corner u/v average (pure 1/0 armour). |
| real(kind=wp), | private, | parameter | :: | MASK_SUM_EPS | = | 1.0e-36_wp |
Armour added to a MASK sum (a nondimensional wet-cell count), so an all-land denominator gives 0/1e-36 = 0 rather than 0/0. |
| 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 | :: | at_vertex | = | .false. |
Solve the JHL08 columns at C-grid CORNERS (vorticity points)
instead of tracer points, then average the corner Kd back to
tracer points (MOM6 |
|
| real(kind=wp), | public | :: | c_n | = | 0.24_wp |
TKE decay vs N (TKE_N_DECAY_CONST). |
|
| real(kind=wp), | public | :: | c_s | = | 0.14_wp |
TKE decay vs shear (TKE_SHEAR_DECAY_CONST). |
|
| logical, | public | :: | enable | = | .false. |
Master switch. Default off — existing namelists and tests
stay bit-identical. Requires |
|
| type(eos_t), | public | :: | eos | ||||
| real(kind=wp), | public, | allocatable | :: | f_centre(:,:) |
|f| at cell centres (1/s); filled by |
||
| real(kind=wp), | public, | allocatable | :: | f_corner(:,:) |
SIGNED Coriolis f at C-grid corners (1/s), |
||
| real(kind=wp), | public | :: | fri_curvature | = | -0.97_wp |
Ri-function curvature (FRI_CURVATURE). |
|
| logical, | public | :: | is_init | = | .false. |
True between |
|
| real(kind=wp), | public | :: | kappa_0 | = | 1.0e-7_wp |
Background diffusivity (m^2/s); also the pre-step kappa. |
|
| real(kind=wp), | public | :: | kappa_seed | = | 1.0_wp |
Iteration seed diffusivity (m^2/s). |
|
| real(kind=wp), | public | :: | kappa_trunc | = | 1.0e-9_wp |
Diffusivity below this -> 0 (m^2/s). |
|
| real(kind=wp), | public, | allocatable | :: | kd_corner(:,:,:) |
Corner diffusivity at interfaces (m^2/s), |
||
| real(kind=wp), | public, | allocatable | :: | kd_int(:,:,:) |
Kappa-shear 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 | :: | lambda | = | 0.82_wp |
Buoyancy length-scale coefficient (KAPPA_BUOY_SCALE_COEF). |
|
| real(kind=wp), | public | :: | lz_rescale | = | 1.0_wp |
Boundary-distance length-scale rescale (LZ_RESCALE). |
|
| logical, | public | :: | massless_merge | = | .false. |
is merged onto its massive sub-grid (rdb_massless), solved on
|
|
| integer, | public | :: | max_inner_it | = | 50 |
Inner Picard iteration cap (MAX_RINO_IT). |
|
| integer, | public | :: | max_substep_it | = | 13 |
Outer adaptive substep cap (MAX_KAPPA_SHEAR_IT). |
|
| real(kind=wp), | public | :: | prandtl_turb | = | 1.0_wp |
Kv = prandtl_turb * Kd into the momentum solve. |
|
| real(kind=wp), | public | :: | rho0 | = | 1035.0_wp |
Boussinesq reference density (kg/m^3). |
|
| real(kind=wp), | public | :: | ri_crit | = | 0.25_wp |
Critical Richardson number (MOM6 RINO_CRIT). |
|
| real(kind=wp), | public | :: | shearmix_rate | = | 0.089_wp |
Source-rate coefficient (SHEARMIX_RATE). |
|
| real(kind=wp), | public | :: | src_max_chg | = | 10.0_wp |
Adaptive-dt source-change tolerance band. |
|
| real(kind=wp), | public | :: | tke_bg | = | 0.0_wp |
Background TKE (m^2/s^2); Q is a denominator, floored. |
|
| real(kind=wp), | public, | allocatable | :: | tke_int(:,:,:) |
Time-mean TKE at interfaces (m^2/s^2), same shape/convention — diagnostic (currently filled to 0; reserved for the TKE budget diag). Vertex mode zeroes it (corner TKE not carried). |
||
| real(kind=wp), | public | :: | tol_err | = | 0.1_wp |
Picard convergence tolerance (KAPPA_SHEAR_TOL_ERR). |
|
| real(kind=wp), | public | :: | vel_underflow | = | 0.0_wp |
Velocity snap-to-zero magnitude (m/s) in the projection. |
|
| real(kind=wp), | public | :: | vertex_geomean_kdmin | = | 0.0_wp |
Floor (m^2/s) applied to each corner Kd BEFORE the geometric
mean (MOM6 |
|
| logical, | public | :: | vertex_geometric_mean | = | .false. |
Corner->centre averaging: geometric mean of the 4 corner Kd
(MOM6 |
| procedure, public, non_overridable :: bytes => ocean_kappa_shear_bytes | |
| procedure, public, non_overridable :: destroy => ocean_kappa_shear_destroy | |
| procedure, public, non_overridable :: enter_data => ocean_kappa_shear_enter_data | |
| procedure, public, non_overridable :: exit_data => ocean_kappa_shear_exit_data | |
| procedure, public, non_overridable :: init => ocean_kappa_shear_init | |
| procedure, public, non_overridable :: init_vertex => ocean_kappa_shear_init_vertex | |
| procedure, public, non_overridable :: set_f_centre => ocean_kappa_shear_set_f_centre | |
| procedure, public, non_overridable :: set_f_corner => ocean_kappa_shear_set_f_corner |
Largest dt_test <= dt_rem such that, after mixing for
0.5*dt_test with kappa_out_s, the regenerated source stays
within the tolerance bands of the accepted-state source
(design doc section 5.3): a halving pass followed by a 5-step
refinement pass.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | dt_rem | |||
| integer, | intent(in) | :: | itt_outer | |||
| integer, | intent(in) | :: | max_substep_it | |||
| real(kind=wp), | intent(in) | :: | ri_crit | |||
| real(kind=wp), | intent(in) | :: | shearmix_rate | |||
| real(kind=wp), | intent(in) | :: | fri_curvature | |||
| real(kind=wp), | intent(in) | :: | src_max_chg | |||
| real(kind=wp), | intent(in) | :: | tol_err | |||
| real(kind=wp), | intent(in) | :: | vel_underflow | |||
| real(kind=wp), | intent(in) | :: | dbuoy_t(NZLI) | |||
| real(kind=wp), | intent(in) | :: | dbuoy_s(NZLI) | |||
| real(kind=wp), | intent(in) | :: | h_s(NZL) | |||
| real(kind=wp), | intent(in) | :: | u_cur(NZL) | |||
| real(kind=wp), | intent(in) | :: | v_cur(NZL) | |||
| real(kind=wp), | intent(in) | :: | t_cur(NZL) | |||
| real(kind=wp), | intent(in) | :: | s_cur(NZL) | |||
| real(kind=wp), | intent(in) | :: | kappa_out_s(NZLI) | |||
| real(kind=wp), | intent(in) | :: | kappa_src_s(NZLI) | |||
| real(kind=wp), | intent(in) | :: | local_src_s(NZLI) | |||
| real(kind=wp), | intent(in) | :: | local_src_avg_s(NZLI) | |||
| integer, | intent(in) | :: | ks_kap | |||
| integer, | intent(in) | :: | ke_kap | |||
| real(kind=wp), | intent(in) | :: | idz_int_s(NZLI) |
Shear-source function K_src at one interface (JHL08 eq. for the source term): nonzero only where N^2 < Ri_c * S^2.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | ri_crit | |||
| real(kind=wp), | intent(in) | :: | shearmix_rate | |||
| real(kind=wp), | intent(in) | :: | fri_curvature | |||
| real(kind=wp), | intent(in) | :: | n2 | |||
| real(kind=wp), | intent(in) | :: | s2 |
Counted allocatable footprint of the kappa-shear 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_kappa_shear_t), | intent(in) | :: | this |
Run kappa-shear 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. Velocities reach the
kernel as the C-grid face arrays, face-averaged to tracer
points inside (same source as the PP81 interior shear).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_kappa_shear_t), | intent(inout) | :: | this | |||
| type(multilayer_state_t), | intent(in) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| real(kind=wp), | intent(in), | optional | :: | wet_t(:,:) |
Halo-valid tracer-cell wet mask ( |
|
| real(kind=wp), | intent(in), | optional | :: | wet_u(:,:) |
u-face open mask ( |
|
| real(kind=wp), | intent(in), | optional | :: | wet_v(:,:) |
v-face open mask ( |
Fold the kappa-shear diffusivity into the vmix interface
fields, ADDITIVELY (MOM6 interior-diffusivity semantics).
Called EVERY stage (the interior closure rewrites kv/kt each
stage; kd_int itself refreshes at thermo cadence). Interior
interfaces only — K=1 (bed) and K=nz+1 (surface) stay zero in
both source and target.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_kappa_shear_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_turb*kd (column mode) or nothing (vertex mode — see above). |
||
| real(kind=wp), | intent(inout) | :: | kt(nx,ny,nzp1) |
Tracer diffusivity at interfaces; gets kd. |
Corner -> tracer-point averaging (MOM6 vertex form, Pass C).
Cell (i,j) reads its four corners SW=(i,j), SE=(i+1,j),
NW=(i,j+1), NE=(i+1,j+1) — a read-only corner stencil into an
own-cell write, safe as its own do concurrent but NEVER
fusable with the corner solve (kd_corner is the required
snapshot). Two modes:
arithmetic (default): 0.25 * ((SW+NE) + (NW+SE))
geometric: 4th root of the product of the four corner
values, each floored at kdmin first — a geometric mean is
0 if ANY factor is 0, which would otherwise blank Kd along
every shear-zone edge. The floor applies to the CORNER
values only, never the output: a land cell still gets
exactly 0 via the wet_t multiply.
Endpoints (bed K=1, surface K=nzp1) are forced to exactly 0.
tke_int is zeroed — the vertex form does not carry a
cell-centred TKE (corner TKE deliberately not materialised).
Bracketing is reproducible-sum ordering; keep literal.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nzp1 | |||
| logical, | intent(in) | :: | geometric | |||
| real(kind=wp), | intent(in) | :: | kdmin | |||
| real(kind=wp), | intent(in) | :: | wet_t(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | kd_corner(nx+1,ny+1,nzp1) | |||
| real(kind=wp), | intent(out) | :: | kd_int(nx,ny,nzp1) | |||
| real(kind=wp), | intent(out) | :: | tke_int(nx,ny,nzp1) |
Assemble the surface-down column at corner (ic,jc) from the 2x2 cell patch + 4 adjacent faces (JHL08 vertex form; the interpolation recipes of the reference implementation): u,v : 2-point THICKNESS-weighted average across the corner, with the face thickness itself a mask-weighted 2-cell average (recomputed inline — deterministic, so the repeated evaluation is bitwise identical to MOM6’s precomputed h_at_u/h_at_v Pass A, non-OBC-bug form). T,S : 4-cell mask-AND-thickness-weighted average. The registry stores hTr = hT, which is exactly the weighted quantity, so we sum wethTr directly. h : 4-cell mask-weighted average (no thickness weight — it IS the thickness). Returns RAW h (no floor) — the caller decides floor vs massless-merge exactly as the column path does. The deliberate (SW+NE)+(SE+NW) bracketing is reproducible-sum ordering — do not reassociate.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz | |||
| integer, | intent(in) | :: | ic | |||
| integer, | intent(in) | :: | jc | |||
| real(kind=wp), | intent(in) | :: | h_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | u_face(nx+1,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | v_face(nx,ny+1,nz) | |||
| real(kind=wp), | intent(in) | :: | hT(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | hS(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | wet_t(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | wet_u(nx+1,ny) | |||
| real(kind=wp), | intent(in) | :: | wet_v(nx,ny+1) | |||
| real(kind=wp), | intent(out) | :: | h_sd(NZL) | |||
| real(kind=wp), | intent(out) | :: | u_sd(NZL) | |||
| real(kind=wp), | intent(out) | :: | v_sd(NZL) | |||
| real(kind=wp), | intent(out) | :: | t_sd(NZL) | |||
| real(kind=wp), | intent(out) | :: | s_sd(NZL) |
Per-column JHL08 solve. One do concurrent (j, i) over owned
cells; every column is solved serially in surface-down order.
Per-thread work is fixed-size local() arrays (L1 layout —
all live in GPU registers, no shared memory); the column solve
bodies are the same-module pure !$acc routine seq helpers below.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_kappa_shear_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. |
||
| real(kind=wp), | intent(in) | :: | dt |
Per-CORNER JHL08 solve (MOM6 vertex form, Pass B). One
do concurrent (jc, ic) over the interior corners
[2,nx]x[2,ny] — the set whose full 2x2 cell patch exists
in-array, which covers every corner any owned tracer cell
needs (nghost >= 1). Ring corners stay 0.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_kappa_shear_t), | intent(inout) | :: | this | |||
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| real(kind=wp), | intent(in) | :: | h_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | u_face(nx+1,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | v_face(nx,ny+1,nz) | |||
| real(kind=wp), | intent(in) | :: | hT(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | hS(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | wet_t(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | wet_u(nx+1,ny) | |||
| real(kind=wp), | intent(in) | :: | wet_v(nx,ny+1) |
The inner Picard solve (design doc section 5.4): alternate a TKE tridiagonal sweep (Dirichlet surface, e1 tail below the deepest active interface) with a kappa tridiagonal sweep (smooth truncation ramp + active-range tracking) until the Picard increment converges. Scratch arrays are supplied by the caller to avoid double-allocating per-thread stack.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | tke_min | |||
| real(kind=wp), | intent(in) | :: | f2_val | |||
| real(kind=wp), | intent(in) | :: | ri_crit | |||
| real(kind=wp), | intent(in) | :: | shearmix_rate | |||
| real(kind=wp), | intent(in) | :: | fri_curvature | |||
| real(kind=wp), | intent(in) | :: | c_n2 | |||
| real(kind=wp), | intent(in) | :: | c_s2 | |||
| real(kind=wp), | intent(in) | :: | ilambda2 | |||
| real(kind=wp), | intent(in) | :: | kappa_0 | |||
| real(kind=wp), | intent(in) | :: | kappa_trunc | |||
| real(kind=wp), | intent(in) | :: | tke_bg | |||
| real(kind=wp), | intent(in) | :: | tol_err | |||
| integer, | intent(in) | :: | max_inner_it | |||
| real(kind=wp), | intent(in) | :: | n2_in(NZLI) | |||
| real(kind=wp), | intent(in) | :: | s2_in(NZLI) | |||
| real(kind=wp), | intent(in) | :: | kappa_seed(NZLI) | |||
| real(kind=wp), | intent(inout) | :: | k_q_io(NZLI) | |||
| real(kind=wp), | intent(in) | :: | idz_s(NZL) | |||
| real(kind=wp), | intent(in) | :: | hint_s(NZLI) | |||
| real(kind=wp), | intent(in) | :: | il2_s(NZLI) | |||
| real(kind=wp), | intent(in) | :: | e1_s(NZLI) | |||
| real(kind=wp), | intent(out) | :: | tke_o(NZLI) | |||
| real(kind=wp), | intent(out) | :: | kappa_o(NZLI) | |||
| real(kind=wp), | intent(inout) | :: | ksrc_sc(NZLI) | |||
| real(kind=wp), | intent(inout) | :: | tkedec_sc(NZLI) | |||
| real(kind=wp), | intent(inout) | :: | aq_sc(NZL) | |||
| real(kind=wp), | intent(inout) | :: | dq_sc(NZLI) | |||
| real(kind=wp), | intent(inout) | :: | cq_sc(NZLI) | |||
| real(kind=wp), | intent(inout) | :: | dk_sc(NZLI) | |||
| real(kind=wp), | intent(inout) | :: | ck_sc(NZLI) | |||
| real(kind=wp), | intent(inout) | :: | ild2_sc(NZLI) |
Build the thickness-derived interface grids that the iteration reuses: 1/h, the interface 1/dz, the harmonic-mean interface FV cell thicknesses h_Int (Sum h_Int = Sum h), and the inverse boundary length scale squared (design doc section 5.1).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | lz_rescale | |||
| real(kind=wp), | intent(in) | :: | h_sd(NZL) | |||
| real(kind=wp), | intent(out) | :: | idz_o(NZL) | |||
| real(kind=wp), | intent(out) | :: | idz_int_o(NZLI) | |||
| real(kind=wp), | intent(out) | :: | hint_o(NZLI) | |||
| real(kind=wp), | intent(out) | :: | il2_o(NZLI) |
Mix (u0,v0,T0,S0) implicitly with kappa_ps over dt_now,
restricted to the layer band [ks,ke], and recompute N^2/S^2 at
interfaces (band edges blend mixed inside / original outside).
Backward-Euler tridiagonal; no-slip for u,v iff the band
reaches the bed (ke==nz), insulating T,S. N^2 floored at 0
(design doc section 5.5).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | dt_now | |||
| integer, | intent(in) | :: | ks | |||
| integer, | intent(in) | :: | ke | |||
| real(kind=wp), | intent(in) | :: | vel_underflow | |||
| real(kind=wp), | intent(in) | :: | dbuoy_t(NZLI) | |||
| real(kind=wp), | intent(in) | :: | dbuoy_s(NZLI) | |||
| real(kind=wp), | intent(in) | :: | h_sd(NZL) | |||
| real(kind=wp), | intent(in) | :: | idz_int_s(NZLI) | |||
| real(kind=wp), | intent(in) | :: | u0(NZL) | |||
| real(kind=wp), | intent(in) | :: | v0(NZL) | |||
| real(kind=wp), | intent(in) | :: | t0(NZL) | |||
| real(kind=wp), | intent(in) | :: | s0(NZL) | |||
| real(kind=wp), | intent(in) | :: | kappa_ps(NZLI) | |||
| real(kind=wp), | intent(out) | :: | u_o(NZL) | |||
| real(kind=wp), | intent(out) | :: | v_o(NZL) | |||
| real(kind=wp), | intent(out) | :: | t_o(NZL) | |||
| real(kind=wp), | intent(out) | :: | s_o(NZL) | |||
| real(kind=wp), | intent(out) | :: | c1_o(NZLI) | |||
| real(kind=wp), | intent(out) | :: | n2_o(NZLI) | |||
| real(kind=wp), | intent(out) | :: | s2_o(NZLI) |
Full JHL08 column solve in surface-down indices (design doc
section 5.1-5.2): background kappa_0 pre-step (no-slip bed for
u,v; insulating T,S), frozen interface buoyancy derivatives,
e1 tail recursion, then the adaptive predictor-corrector outer
loop driving the Picard inner solve. Returns the time-mean
diffusivity kappa_avg_sd and TKE tke_avg_sd over dt.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| real(kind=wp), | intent(in) | :: | f2_val | |||
| real(kind=wp), | intent(in) | :: | rho0 | |||
| real(kind=wp), | intent(in) | :: | ri_crit | |||
| real(kind=wp), | intent(in) | :: | shearmix_rate | |||
| real(kind=wp), | intent(in) | :: | fri_curvature | |||
| real(kind=wp), | intent(in) | :: | c_n | |||
| real(kind=wp), | intent(in) | :: | c_s | |||
| real(kind=wp), | intent(in) | :: | lambda | |||
| real(kind=wp), | intent(in) | :: | kappa_0 | |||
| real(kind=wp), | intent(in) | :: | kappa_seed_in | |||
| real(kind=wp), | intent(in) | :: | kappa_trunc | |||
| real(kind=wp), | intent(in) | :: | tke_bg | |||
| real(kind=wp), | intent(in) | :: | tol_err | |||
| integer, | intent(in) | :: | max_inner_it | |||
| integer, | intent(in) | :: | max_substep_it | |||
| real(kind=wp), | intent(in) | :: | src_max_chg | |||
| real(kind=wp), | intent(in) | :: | vel_underflow | |||
| type(eos_t), | intent(in) | :: | eos |
Shared EOS handle (by value) for the buoyancy derivatives. |
||
| real(kind=wp), | intent(in) | :: | h_sd(NZL) | |||
| real(kind=wp), | intent(in) | :: | u_sd(NZL) | |||
| real(kind=wp), | intent(in) | :: | v_sd(NZL) | |||
| real(kind=wp), | intent(in) | :: | t_sd(NZL) | |||
| real(kind=wp), | intent(in) | :: | s_sd(NZL) | |||
| real(kind=wp), | intent(in) | :: | idz_s(NZL) | |||
| real(kind=wp), | intent(in) | :: | idz_int_s(NZLI) | |||
| real(kind=wp), | intent(in) | :: | hint_s(NZLI) | |||
| real(kind=wp), | intent(in) | :: | il2_s(NZLI) | |||
| real(kind=wp), | intent(out) | :: | kappa_avg_sd(NZLI) | |||
| real(kind=wp), | intent(out) | :: | tke_avg_sd(NZLI) |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_kappa_shear_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_kappa_shear_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_kappa_shear_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_kappa_shear_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_kappa_shear_t), | intent(inout) | :: | this |
Allocate the persistent fields. Always allocates (configure
runs after init, so enable is not known yet); the off-cost
is the f_centre + two interface fields.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_kappa_shear_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in), | optional | :: | nz_ml |
Allocate the vertex-mode corner fields and set at_vertex.
Called at CONFIGURE time (after init, before enter_data) —
deliberately NOT from init, so the (nx+1,ny+1,nz+1) corner
carrier is only ever allocated when the vertex form is actually
selected (~327 MB at 1000x800x50).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_kappa_shear_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | nz_ml |
Fill f_centre with the beta-plane Coriolis magnitude at cell
centres: |f_0 + beta*(y - y_ref)|. Mirrors EPBL’s
set_f_centre. Call after init, before enter_data.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_kappa_shear_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | f_0 | |||
| real(kind=wp), | intent(in) | :: | beta | |||
| real(kind=wp), | intent(in) | :: | y_ref |
Fill f_corner with the SIGNED beta-plane Coriolis at C-grid
corners: f_0 + beta(y - y_ref), corner row j at
y = (j-1-nghost)dy (half a cell below centre row j — corner
(i,j) is the SW corner of cell (i,j)). Bit-identical to
metrics_fill_coriolis’s beta-plane corner fill. Call after
init_vertex, before enter_data.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_kappa_shear_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | f_0 | |||
| real(kind=wp), | intent(in) | :: | beta | |||
| real(kind=wp), | intent(in) | :: | y_ref |