Mesoscale eddy kinetic energy parameterization. Carries a single 2D
vertically-averaged eddy-energy field meke(nx,ny) [m^2/s^2], sourced
by the GM potential-energy release, damped by an implicit
(backward-Euler) bottom drag, transported laterally (harmonic-mass
Laplacian + optional biharmonic + advection), and fed back as a
thickness/tracer diffusivity kh = khcoeff·sqrt(2·gamma_t²·E)·Lmix
added (geom mean) into VarMix’s per-face KhTh before GM’s CFL clamp —
closing the GM↔eddy-energy loop. Updated via a Strang split each
thermo step.
Clean-room (no source ported). meke is PROGNOSTIC (restart-persistent).
Default off (&ocean_meke_nml enable = .false.) ⇒ meke_step never
called ⇒ bit-identical. Bottom-up convention (k=1 bed, k=nz surface);
only the column mass sum touches k and it is orientation-independent.
References: Jansen, Adcroft, Hallberg & Held (2015); Eden & Greatbatch (2008); Marshall, Maddison & Berloff (2012).
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private, | parameter | :: | BACKSCATTER_CFL | = | 0.8_wp |
Forward-Euler viscous-CFL safety coefficient for the backscatter
lower bound (MOM6 |
| real(kind=wp), | private, | parameter | :: | MASS_NEGLECT | = | 1.0e-30_wp |
Floor in the harmonic-mass denominator (MOM6 |
Mesoscale eddy kinetic energy state. All fields default to the
inert (enable=.false.) configuration so an ocean run that never
sets &ocean_meke_nml is bit-identical.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public | :: | advection_factor | = | 0.0_wp |
Scaling on the barotropic-transport advection of MEKE (nondim); 0 (default) ⇒ the advection stage is skipped ⇒ bit-identical. |
|
| real(kind=wp), | public | :: | alpha_deform | = | 0.0_wp |
Weight on the deformation length scale Ldeform (nondim). |
|
| real(kind=wp), | public | :: | alpha_eady | = | 0.0_wp |
Weight on the Eady length scale Leady (needs VarMix SN) (nondim). |
|
| real(kind=wp), | public | :: | alpha_frict | = | 0.0_wp |
Weight on the frictional-arrest length scale Lfrict (nondim). |
|
| real(kind=wp), | public | :: | alpha_grid | = | 0.0_wp |
Weight on the grid length scale Lgrid (nondim). |
|
| real(kind=wp), | public | :: | alpha_rhines | = | 0.0_wp |
Weight on the Rhines length scale Lrhines = sqrt(Ueddy/beta)
(nondim). Default 0 ⇒ beta term inert; > 0 activates the
Rhines scale (needs |
|
| logical, | public | :: | backscatter | = | .false. |
Master switch for the MEKE → momentum negative-viscosity
energy return (capability Gap 2). Default |
|
| real(kind=wp), | public, | allocatable | :: | baro_hu(:,:) |
Depth-integrated u-face mass transport (kg/s), |
||
| real(kind=wp), | public, | allocatable | :: | baro_hv(:,:) |
Depth-integrated v-face mass transport (kg/s), |
||
| real(kind=wp), | public, | allocatable | :: | barotr_fac2(:,:) |
gamma_t^2 (nondim), |
||
| real(kind=wp), | public | :: | bgsrc | = | 0.0_wp |
Background energy source (m^2/s^3). |
|
| real(kind=wp), | public, | allocatable | :: | bottom_fac2(:,:) |
gamma_b^2 (nondim), |
||
| real(kind=wp), | public | :: | cb | = | 25.0_wp |
Coefficient in the gamma_bot (bottomFac2) expression (nondim). |
|
| real(kind=wp), | public | :: | cd_scale | = | 0.0_wp |
Ratio of bottom eddy velocity to column-mean eddy velocity (nondim); enters bottomFac2. |
|
| real(kind=wp), | public | :: | cdrag | = | 2.5e-3_wp |
Bottom drag coefficient for MEKE (nondim). Copied from
|
|
| real(kind=wp), | public | :: | ct | = | 50.0_wp |
Coefficient in the gamma_bt (barotrFac2) expression (nondim). |
|
| real(kind=wp), | public | :: | damping | = | 0.0_wp |
Local depth-independent linear MEKE dissipation rate (1/s). |
|
| real(kind=wp), | public, | allocatable | :: | del2(:,:) |
Laplacian of MEKE workspace (biharmonic), |
||
| real(kind=wp), | public, | allocatable | :: | depth_tot(:,:) |
Total column thickness (m), |
||
| real(kind=wp), | public | :: | dtscale | = | 1.0_wp |
Scale factor accelerating MEKE time-stepping (nondim). |
|
| logical, | public | :: | enable | = | .false. |
Master switch. Off ⇒ |
|
| real(kind=wp), | public, | allocatable | :: | f_centre(:,:) |
|f| at cell centres (1/s), |
||
| real(kind=wp), | public | :: | frcoeff | = | -1.0_wp |
Efficiency of mean->eddy frictional conversion (nondim); < 0
(default) ⇒ off ⇒ bit-identical. When >= 0, adds the frictional
source |
|
| real(kind=wp), | public | :: | gmcoeff | = | -1.0_wp |
Efficiency of PE->MEKE conversion (nondim). < 0 ⇒ GM source off. |
|
| real(kind=wp), | public, | allocatable | :: | i_mass(:,:) |
1 / column mass (m^2/kg), |
||
| logical, | public | :: | is_init | = | .false. |
True between |
|
| real(kind=wp), | public | :: | k4 | = | -1.0_wp |
Background biharmonic diffusion of MEKE (m^4/s). < 0 ⇒ off. |
|
| real(kind=wp), | public, | allocatable | :: | ke_diss_ws(:,:) |
Staged hvisc KE-dissipation rate (kg/s³, ≤0), |
||
| real(kind=wp), | public | :: | kh | = | -1.0_wp |
Background lateral diffusion of MEKE (m^2/s). < 0 ⇒ diffusion stage off. |
|
| real(kind=wp), | public, | allocatable | :: | kh_diff(:,:) |
Derived MEKE diffusivity kh (m^2/s), |
||
| real(kind=wp), | public | :: | khcoeff | = | 1.0_wp |
Scaling converting MEKE into Kh (nondim). <= 0 ⇒ closure off. |
|
| real(kind=wp), | public | :: | khmeke_fac | = | 0.0_wp |
Factor relating |
|
| real(kind=wp), | public | :: | khth_fac | = | 0.0_wp |
Factor on the geometric-mean kh added into VarMix’s KhTh face field (nondim). 0 (default) ⇒ feedback inert ⇒ bit-identical. |
|
| real(kind=wp), | public | :: | khtr_fac | = | 0.0_wp |
Factor on the geometric-mean kh added into VarMix’s KhTr face field (nondim). 0 (default) ⇒ inert. |
|
| real(kind=wp), | public, | allocatable | :: | ku(:,:) |
Derived harmonic backscatter viscosity Ku (m²/s), |
||
| real(kind=wp), | public, | allocatable | :: | le(:,:) |
Mixing length scale Lmix (m), |
||
| real(kind=wp), | public, | allocatable | :: | mass_ws(:,:) |
Column mass (kg/m^2), |
||
| real(kind=wp), | public, | allocatable | :: | meke(:,:) |
Eddy kinetic energy E (m^2/s^2), |
||
| real(kind=wp), | public | :: | min_gamma2 | = | 1.0e-4_wp |
Floor on gamma_b^2 / gamma_t^2 (nondim). |
|
| integer, | public | :: | nx_total | = | 0 | ||
| integer, | public | :: | ny_total | = | 0 | ||
| integer, | public | :: | nz_ml | = | 0 | ||
| real(kind=wp), | public, | allocatable | :: | rd_ws(:,:) |
Staged copy of |
||
| real(kind=wp), | public, | allocatable | :: | sn_u_ws(:,:) |
Staged copy of |
||
| real(kind=wp), | public, | allocatable | :: | sn_v_ws(:,:) |
Staged copy of |
||
| real(kind=wp), | public, | allocatable | :: | src(:,:) |
Aggregate source (m^2/s^3), |
||
| real(kind=wp), | public, | allocatable | :: | u_bbl2(:,:) |
Resolved bed-layer speed² (m²/s²) at cell centres, |
||
| real(kind=wp), | public, | allocatable | :: | uflux(:,:) |
u-face MEKE flux workspace, |
||
| real(kind=wp), | public | :: | uscale | = | 0.0_wp |
Background (e.g. tidal) eddy velocity scale for bottom drag (m/s). |
|
| logical, | public | :: | use_bbl_drag | = | .false. |
Add the resolved bed-layer eddy velocity |
|
| real(kind=wp), | public, | allocatable | :: | vflux(:,:) |
v-face MEKE flux workspace, |
||
| real(kind=wp), | public | :: | visc_coeff_ku | = | 0.0_wp |
MOM6 |
| procedure, public, non_overridable :: bytes => ocean_meke_bytes | |
| procedure, public, non_overridable :: destroy => ocean_meke_destroy | |
| procedure, public, non_overridable :: enter_data => ocean_meke_enter_data | |
| procedure, public, non_overridable :: exit_data => ocean_meke_exit_data | |
| procedure, public, non_overridable :: init => ocean_meke_init | |
| procedure, public, non_overridable :: set_f_centre => ocean_meke_set_f_centre |
Harmonic inverse mixing length 1/Lmix = Sum aX/LX over the five
length scales (deformation, frictional, Rhines, Eady, grid). Each
scale is gated aX*LX > 0 so a zero weight or a degenerate scale
contributes nothing. Returns 1/Lmix (0 ⇒ Lmix degenerate).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | ueddy | |||
| real(kind=wp), | intent(in) | :: | sn | |||
| real(kind=wp), | intent(in) | :: | beta | |||
| real(kind=wp), | intent(in) | :: | area | |||
| real(kind=wp), | intent(in) | :: | rd_over_dx | |||
| real(kind=wp), | intent(in) | :: | depth | |||
| real(kind=wp), | intent(in) | :: | cdrag | |||
| real(kind=wp), | intent(in) | :: | a_deform | |||
| real(kind=wp), | intent(in) | :: | a_rhines | |||
| real(kind=wp), | intent(in) | :: | a_eady | |||
| real(kind=wp), | intent(in) | :: | a_frict | |||
| real(kind=wp), | intent(in) | :: | a_grid |
Counted allocatable footprint of the MEKE 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_meke_t), | intent(in) | :: | this |
Inject the MEKE harmonic backscatter into the per-face resolved
harmonic viscosity (capability Gap 2, v1). Subtracts a face-average
of the cell-centred ku field from ah_face_x/ah_face_y so the
NET coefficient A_net = A_resolved − Ku can go NEGATIVE — that
negative viscosity is the energy return into the momentum tendency
(the hvisc Laplacian kernel reads these same face fields).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(ocean_meke_t), | intent(in) | :: | this | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| real(kind=wp), | intent(inout) | :: | ah_face_x(:,:,:) | |||
| real(kind=wp), | intent(inout) | :: | ah_face_y(:,:,:) |
Advance the MEKE field one thermo step (Strang split), update the
derived diffusivity kh_diff, and feed the geometric-mean kh into
VarMix’s per-face KhTh/KhTr (the GM↔MEKE feedback). Run once per
outer step at thermo cadence, after varmix_compute and before
gm_compute_transports (MEKE reads gm%gm_src from the previous
thermo step — a one-step lag). No-op when enable=.false.,
uninitialised, or the GM slot is absent.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(ocean_meke_t), | intent(inout) | :: | this | |||
| type(ocean_gm_t), | intent(in) | :: | gm | |||
| type(ocean_varmix_t), | intent(inout), | optional | :: | varmix | ||
| type(ocean_wave_speed_t), | intent(in), | optional | :: | wavespeed | ||
| type(multilayer_state_t), | intent(in) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| real(kind=wp), | intent(in), | optional | :: | ke_diss_ext(:,:) |
hvisc KE-dissipation rate |
Upwind flux-form advection of E by the barotropic mass transport.
advFac = adv_fac/sdt
uflux(I) = baroHu(I)advFacE_upwind (E_{I-1} if baroHu>0 else E_I)
E += sdtIareaTI_mass((uflux_{i-1}-uflux_i)+(vflux_{j-1}-vflux_j))
Conservative on a closed domain (interior faces only; the
divergence telescopes ⇒ Sum Earea*mass conserved). adv_fac=0
never reaches here (gated by the caller) ⇒ default bit-identity.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| real(kind=wp), | intent(in) | :: | sdt | |||
| real(kind=wp), | intent(in) | :: | adv_fac | |||
| real(kind=wp), | intent(in) | :: | iareaT(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | i_mass(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | baro_hu(nx+1,ny) | |||
| real(kind=wp), | intent(in) | :: | baro_hv(nx,ny+1) | |||
| real(kind=wp), | intent(inout) | :: | uflux(nx+1,ny) | |||
| real(kind=wp), | intent(inout) | :: | vflux(nx,ny+1) | |||
| real(kind=wp), | intent(inout) | :: | meke(nx,ny) |
harmonic viscosity and floor the net at the CFL-stable minimum.
Explicit-shape dummies for NVHPC stdpar (no descriptor walk).
The backscatter coefficient is z-independent in v1 (BS_struct=1),
so the cell-centred ku(i,j) is broadcast to every layer.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| real(kind=wp), | intent(in) | :: | cfl_safety | |||
| real(kind=wp), | intent(in) | :: | ku(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | idxCu(nx+1,ny) | |||
| real(kind=wp), | intent(in) | :: | idyCu(nx+1,ny) | |||
| real(kind=wp), | intent(in) | :: | idxCv(nx,ny+1) | |||
| real(kind=wp), | intent(in) | :: | idyCv(nx,ny+1) | |||
| real(kind=wp), | intent(inout) | :: | ah_face_x(nx+1,ny,nz) | |||
| real(kind=wp), | intent(inout) | :: | ah_face_y(nx,ny+1,nz) |
Depth-integrated, mass-weighted barotropic transport through each
C-grid face: baroHu(I,j) = Sum_k rho_face * mass_flux_x_layer,
where mass_flux_*_layer is the per-layer VOLUME transport (m^3/s,
= uh_facedy) and rho_face the two-cell average density. The
result is a MASS transport (kg/s) so the advective divergence pairs
exactly with IareaT*I_mass (1/(areamass)) ⇒ Sum Earea*mass is
conserved. Array-edge faces carry zero transport (closed domain).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | rho0 | |||
| logical, | intent(in) | :: | have_rho | |||
| real(kind=wp), | intent(in) | :: | mflux_x(nx+1,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | mflux_y(nx,ny+1,nz) | |||
| real(kind=wp), | intent(in) | :: | rho_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(out) | :: | baro_hu(nx+1,ny) | |||
| real(kind=wp), | intent(out) | :: | baro_hv(nx,ny+1) |
Resolved bed-layer speed² at cell centres:
u_bbl2 = u_c² + v_c² with u_c = ½(u_face(i)+u_face(i+1)),
v_c = ½(v_face(j)+v_face(j+1)), each face read on ITS OWN bed
layer k_bot_u/v (the first layer live on both sides counting up;
1 off z_fixed ⇒ the historical k=1 read). Under z_fixed the
layers below are inert fillers whose velocity the closed-face mask
has zeroed, so a k = 1 read reported a motionless bed. The
bottom eddy velocity the MEKE drag law needs (MOM6 drag_rate_visc).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | u_face(nx+1,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | v_face(nx,ny+1,nz) | |||
| integer, | intent(in) | :: | k_bot_u(nx+1,ny) | |||
| integer, | intent(in) | :: | k_bot_v(nx,ny+1) | |||
| real(kind=wp), | intent(inout) | :: | u_bbl2(nx,ny) |
Implicit (backward-Euler) bottom-drag half-step.
drag_rate = rho0i_masssqrt(cdrag^2(max(0,2bf2E)+u_bbl2+uscale^2)) [1/s]
damp_rate = damping + drag_ratebf2 ; =0 where E<0
E <- E/(1 + sdt_dampdamp_rate)
rho0*i_mass = rho0/(Sum_k rho_kh_k) ~= 1/depth_tot [1/m], so
drag_rate ~= cdrag|U_d|/H – the MOM6 GV%H_to_RZ * I_mass factor.
Without it drag_rate is m^3/(kgs), not a
rate. i_mass=0 on dry columns still gives drag_rate=0.
u_bbl2 is the resolved bed-layer speed² (MOM6 drag_rate_visc);
it is 0 unless use_bbl_drag is set, so the default is bit-identical.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| real(kind=wp), | intent(in) | :: | sdt_damp | |||
| real(kind=wp), | intent(in) | :: | damping | |||
| real(kind=wp), | intent(in) | :: | cdrag | |||
| real(kind=wp), | intent(in) | :: | uscale | |||
| real(kind=wp), | intent(in) | :: | rho0 | |||
| real(kind=wp), | intent(in) | :: | i_mass(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | bottom_fac2(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | u_bbl2(nx,ny) | |||
| real(kind=wp), | intent(inout) | :: | meke(nx,ny) |
Add the geometric mean of neighbour kh_diff into VarMix’s per-face
KhTh (and KhTr) base BEFORE GM’s CFL clamp:
khth_u(i,j) += khth_facsqrt(kh(i-1,j)kh(i,j))
khth_fac=0 ⇒ nothing added ⇒ bit-identical seam.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| real(kind=wp), | intent(in) | :: | khth_fac | |||
| real(kind=wp), | intent(in) | :: | khtr_fac | |||
| real(kind=wp), | intent(in) | :: | kh_diff(nx,ny) | |||
| real(kind=wp), | intent(inout) | :: | khth_u(nx+1,ny) | |||
| real(kind=wp), | intent(inout) | :: | khth_v(nx,ny+1) | |||
| real(kind=wp), | intent(inout) | :: | khtr_u(nx+1,ny) | |||
| real(kind=wp), | intent(inout) | :: | khtr_v(nx,ny+1) |
Derived diffusivity kh = khcoeff*sqrt(2*max(0,gamma_t2*E))*Lmix.
khcoeff<=0 ⇒ kh left at 0.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| real(kind=wp), | intent(in) | :: | khcoeff | |||
| real(kind=wp), | intent(in) | :: | barotr_fac2(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | meke(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | le(nx,ny) | |||
| real(kind=wp), | intent(out) | :: | kh_diff(nx,ny) |
Derived harmonic backscatter viscosity
ku = visc_coeff_ku*sqrt(2*max(0,E))*Lmix (m²/s), matching MOM6
MEKE%Ku = MEKE_VISCOSITY_COEFF_KU*sqrt(2*MEKE)*Lmix. Unlike the
kh closure (which carries the barotropic-mode factor gamma_t2
inside the eddy velocity), MOM6’s Ku uses the PLAIN sqrt(2*MEKE) —
no vertical-structure factor — so gamma_t2 is deliberately absent
here (vertical structure BS_struct = 1; EBT/SQG deferred).
Off ⇒ ku left at 0 (bit-identical seam). Always ≥ 0; the SIGN of
the momentum effect is set by the subtraction downstream.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| logical, | intent(in) | :: | backscatter | |||
| real(kind=wp), | intent(in) | :: | visc_coeff_ku | |||
| real(kind=wp), | intent(in) | :: | meke(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | le(nx,ny) | |||
| real(kind=wp), | intent(out) | :: | ku(nx,ny) |
Harmonic-mass Laplacian diffusion of MEKE (+ optional biharmonic). Flux-form, conservative on a closed domain (interior faces only; array-edge faces carry zero flux). Kh_u = max(0,kh_bg) + khmeke_fac0.5(kh_i+kh_{i+1}), CFL-capped 0.25 uflux = Kh_u(dy_cuidxCu)[2 m_i m_{i+1}/(m_i+m_{i+1}+eps)](E_i-E_{i+1}) E += sdtiareaTi_mass((uflux_{i-1}-uflux_i)+(vflux_{j-1}-vflux_j)) Biharmonic: del2 = iareaT(d uflux’ + d vflux’) with the bare-gradient flux uflux’ = (dy_cuidxCu)(E_{i+1}-E_i); then a harmonic-mass flux of del2 with CFL cap 0.3 and E += that divergence (additive).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| real(kind=wp), | intent(in) | :: | sdt | |||
| real(kind=wp), | intent(in) | :: | kh_bg | |||
| real(kind=wp), | intent(in) | :: | k4 | |||
| real(kind=wp), | intent(in) | :: | khmeke_fac | |||
| logical, | intent(in) | :: | kh_flux_enabled | |||
| real(kind=wp), | intent(in) | :: | dy_cu(nx+1,ny) | |||
| real(kind=wp), | intent(in) | :: | dx_cv(nx,ny+1) | |||
| real(kind=wp), | intent(in) | :: | idxCu(nx+1,ny) | |||
| real(kind=wp), | intent(in) | :: | idyCv(nx,ny+1) | |||
| real(kind=wp), | intent(in) | :: | iareaT(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | i_mass(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | mass(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | kh_diff(nx,ny) | |||
| real(kind=wp), | intent(inout) | :: | uflux(nx+1,ny) | |||
| real(kind=wp), | intent(inout) | :: | vflux(nx,ny+1) | |||
| real(kind=wp), | intent(inout) | :: | del2(nx,ny) | |||
| real(kind=wp), | intent(inout) | :: | meke(nx,ny) |
Fill the structure factors gamma_b^2 (bottom_fac2) and gamma_t^2
(barotr_fac2) plus the mixing length le (Lmix) at each cell
centre. Ldeform/Lfrict drives both gammas; Lmix is the harmonic
sum of the alpha-weighted scales. beta = |grad f| from centred
f_centre differences scaled by idxT/idyT (zero when f_centre
is unfilled ⇒ Rhines inert). SN = 0.25*(sn_u(i)+sn_u(i-1)+
sn_v(j)+sn_v(j-1)) only when aEady>0.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| real(kind=wp), | intent(in) | :: | cd_scale | |||
| real(kind=wp), | intent(in) | :: | cb | |||
| real(kind=wp), | intent(in) | :: | ct | |||
| real(kind=wp), | intent(in) | :: | min_gamma2 | |||
| real(kind=wp), | intent(in) | :: | cdrag | |||
| real(kind=wp), | intent(in) | :: | a_deform | |||
| real(kind=wp), | intent(in) | :: | a_rhines | |||
| real(kind=wp), | intent(in) | :: | a_eady | |||
| real(kind=wp), | intent(in) | :: | a_frict | |||
| real(kind=wp), | intent(in) | :: | a_grid | |||
| real(kind=wp), | intent(in) | :: | areaT(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | idxT(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | idyT(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | f_centre(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | depth_tot(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | meke(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | rd_over_dx(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | sn_u(nx+1,ny) | |||
| real(kind=wp), | intent(in) | :: | sn_v(nx,ny+1) | |||
| real(kind=wp), | intent(out) | :: | bottom_fac2(nx,ny) | |||
| real(kind=wp), | intent(out) | :: | barotr_fac2(nx,ny) | |||
| real(kind=wp), | intent(out) | :: | le(nx,ny) |
Column mass mass = Sum_k rho*max(h,H_VANISHED) (kg/m^2), its
inverse i_mass (0 where mass<=0), depth_tot = Sum_k h (m), and
mass_ws = mass (the harmonic-mass input for the lateral flux).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | rho0 | |||
| logical, | intent(in) | :: | have_rho | |||
| real(kind=wp), | intent(in) | :: | h_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | rho_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(out) | :: | i_mass(nx,ny) | |||
| real(kind=wp), | intent(out) | :: | depth_tot(nx,ny) | |||
| real(kind=wp), | intent(out) | :: | mass_ws(nx,ny) |
Aggregate source src = bgsrc + gmcoeff*I_mass*gm_src
- frcoeff*I_mass*ke_diss and the explicit bump E += sdt*src.
gmcoeff<0 ⇒ GM source off; frcoeff<0 ⇒ frictional source off.
ke_diss is the lateral-viscosity KE dissipation rate (≤0), so
-frcoeff*I_mass*ke_diss ≥ 0 is a mean→eddy source (0 ⇒ inert).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| real(kind=wp), | intent(in) | :: | bgsrc | |||
| real(kind=wp), | intent(in) | :: | gmcoeff | |||
| real(kind=wp), | intent(in) | :: | frcoeff | |||
| real(kind=wp), | intent(in) | :: | sdt | |||
| real(kind=wp), | intent(in) | :: | i_mass(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | gm_src(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | ke_diss(nx,ny) | |||
| real(kind=wp), | intent(inout) | :: | src(nx,ny) | |||
| real(kind=wp), | intent(inout) | :: | meke(nx,ny) |
Copy rd_over_dx onto the device workspace. Thermo-cadence; explicit-shape; on-device (source slot is device-resident).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| real(kind=wp), | intent(in) | :: | rd_in(nx,ny) | |||
| real(kind=wp), | intent(out) | :: | rd_ws(nx,ny) |
Copy the SN faces onto the device workspaces. Thermo-cadence; explicit-shape; on-device (VarMix slot is device-resident).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| real(kind=wp), | intent(in) | :: | sn_u_in(nx+1,ny) | |||
| real(kind=wp), | intent(in) | :: | sn_v_in(nx,ny+1) | |||
| real(kind=wp), | intent(out) | :: | sn_u_ws(nx+1,ny) | |||
| real(kind=wp), | intent(out) | :: | sn_v_ws(nx,ny+1) |
Zero a device-resident 2D workspace (absent-source fallback).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | n1 | |||
| integer, | intent(in) | :: | n2 | |||
| real(kind=wp), | intent(out) | :: | a(n1,n2) |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_meke_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_meke_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_meke_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_meke_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_meke_t), | intent(inout) | :: | this |
Allocate the prognostic field, the derived diffusivity, and the
Strang-stage workspaces. Always allocates (configure runs after
init); setup uses plain host allocation (no do concurrent before
enter_data).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_meke_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in), | optional | :: | nz_ml |
Copy a pre-filled cell-centre Coriolis magnitude |f| (1/s) onto the
MEKE slot, so beta = |grad f| for the Rhines length is live. The
caller (setup) builds f_centre with the same metrics_fill_coriolis
path the Coriolis / VarMix / EPBL slots use (handles beta-plane AND
spherical). Host loop — call after init, before enter_data.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_meke_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | f_centre(grid%nx_total,grid%ny_total) |