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 |
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 |
| 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 | ||
|---|---|---|---|---|---|---|
| class(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) |
type :: ocean_meke_t !! 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. logical :: is_init = .false. !! True between `init` and `destroy`; gate on this (never on !! `allocated`, which misses the GPU mapping). logical :: enable = .false. !! Master switch. Off ⇒ `meke_step` is never called. Requires !! `&ocean_gm_nml enable` (needs `gm%gm_src`); loud configure check. ! ---- Source / sink coefficients ---- real(wp) :: gmcoeff = -1.0_wp !! Efficiency of PE->MEKE conversion (nondim). < 0 ⇒ GM source off. real(wp) :: frcoeff = -1.0_wp !! Efficiency of mean->eddy frictional conversion (nondim); < 0 !! (default) ⇒ off ⇒ bit-identical. When >= 0, adds the frictional !! source `-frcoeff*i_mass*ke_diss` from the lateral-viscosity KE !! dissipation (`hvisc%ke_diss`). real(wp) :: bgsrc = 0.0_wp !! Background energy source (m^2/s^3). real(wp) :: damping = 0.0_wp !! Local depth-independent linear MEKE dissipation rate (1/s). ! ---- Lateral transport ---- real(wp) :: kh = -1.0_wp !! Background lateral diffusion of MEKE (m^2/s). < 0 ⇒ diffusion !! stage off. real(wp) :: k4 = -1.0_wp !! Background biharmonic diffusion of MEKE (m^4/s). < 0 ⇒ off. real(wp) :: khmeke_fac = 0.0_wp !! Factor relating `meke%kh` (the derived diffusivity) to the !! diffusivity used for MEKE's own lateral spreading (nondim). real(wp) :: advection_factor = 0.0_wp !! Scaling on the barotropic-transport advection of MEKE (nondim); !! 0 (default) ⇒ the advection stage is skipped ⇒ bit-identical. ! ---- KhTh closure ---- real(wp) :: khcoeff = 1.0_wp !! Scaling converting MEKE into Kh (nondim). <= 0 ⇒ closure off. real(wp) :: cd_scale = 0.0_wp !! Ratio of bottom eddy velocity to column-mean eddy velocity !! (nondim); enters bottomFac2. real(wp) :: cb = 25.0_wp !! Coefficient in the gamma_bot (bottomFac2) expression (nondim). real(wp) :: ct = 50.0_wp !! Coefficient in the gamma_bt (barotrFac2) expression (nondim). real(wp) :: min_gamma2 = 1.0e-4_wp !! Floor on gamma_b^2 / gamma_t^2 (nondim). real(wp) :: uscale = 0.0_wp !! Background (e.g. tidal) eddy velocity scale for bottom drag (m/s). real(wp) :: dtscale = 1.0_wp !! Scale factor accelerating MEKE time-stepping (nondim). real(wp) :: cdrag = 2.5e-3_wp !! Bottom drag coefficient for MEKE (nondim). Copied from !! `&ocean_bdrag_nml cdrag_side` at configure if that is > 0, !! else this default; enters drag_rate + Lfrict. logical :: use_bbl_drag = .false. !! Add the resolved bed-layer eddy velocity `|u_bed|²` to the MEKE !! bottom-drag rate `drag_rate = rho0·i_mass·sqrt(cdrag²·(2·bf2·E + !! |u_bed|² + uscale²))` (MOM6 `drag_rate_visc`). Default off ⇒ the !! `u_bbl²` workspace stays 0 ⇒ bit-identical to the prior drag. ! ---- Length-scale alpha weights (default all 0 ⇒ Lmix path inert) ---- real(wp) :: alpha_deform = 0.0_wp !! Weight on the deformation length scale Ldeform (nondim). real(wp) :: 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 `f_centre` filled, done at setup). real(wp) :: alpha_eady = 0.0_wp !! Weight on the Eady length scale Leady (needs VarMix SN) (nondim). real(wp) :: alpha_frict = 0.0_wp !! Weight on the frictional-arrest length scale Lfrict (nondim). real(wp) :: alpha_grid = 0.0_wp !! Weight on the grid length scale Lgrid (nondim). ! ---- Feedback seam factors ---- real(wp) :: 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(wp) :: khtr_fac = 0.0_wp !! Factor on the geometric-mean kh added into VarMix's KhTr face !! field (nondim). 0 (default) ⇒ inert. ! ---- Backscatter (negative-viscosity momentum energy return, v1) ---- logical :: backscatter = .false. !! Master switch for the MEKE → momentum negative-viscosity !! energy return (capability Gap 2). Default `.false.` ⇒ the !! `ku` field stays 0 and `meke_backscatter_apply` adds nothing !! ⇒ bit-identical. When `.true.`, `meke_step` fills `ku` and the !! driver subtracts it from the per-face harmonic viscosity, !! returning eddy energy to the resolved flow. HARMONIC only in !! v1 (the biharmonic `Au` return + EBT/SQG vertical structure !! `BS_struct` are deferred). Needs `enable=.true.` (so `meke_step` !! runs and refreshes `ku`) — inert otherwise. real(wp) :: visc_coeff_ku = 0.0_wp !! MOM6 `MEKE_VISCOSITY_COEFF_KU` — the nondimensional efficiency !! of the harmonic backscatter viscosity !! `Ku = visc_coeff_ku·sqrt(2·gamma_t²·E)·Lmix` (m²/s). May be !! negative in MOM6 (negative viscosity); here it is the magnitude !! coefficient and the SIGN of the momentum effect is set by the !! SUBTRACTION in `meke_backscatter_apply` (`A_net = A − Ku`), so a !! positive `visc_coeff_ku` returns energy. 0 (default) ⇒ inert. ! ---- Cached extents ---- integer :: nx_total = 0 integer :: ny_total = 0 integer :: nz_ml = 0 ! ---- Prognostic + derived 2D fields ---- real(wp), allocatable :: meke(:, :) !! Eddy kinetic energy E (m^2/s^2), `(nx,ny)`. PROGNOSTIC — !! restart-persistent. real(wp), allocatable :: kh_diff(:, :) !! Derived MEKE diffusivity kh (m^2/s), `(nx,ny)`; fed (geom-mean) !! into VarMix's face KhTh/KhTr. real(wp), allocatable :: le(:, :) !! Mixing length scale Lmix (m), `(nx,ny)` (diagnostic). real(wp), allocatable :: ku(:, :) !! Derived harmonic backscatter viscosity Ku (m²/s), `(nx,ny)`; !! `ku = visc_coeff_ku·sqrt(2·gamma_t²·E)·Lmix`. Zero unless !! `backscatter`. Subtracted (face-averaged, stability-floored) !! from the resolved harmonic viscosity by `meke_backscatter_apply`. ! ---- Strang-stage workspace ---- real(wp), allocatable :: i_mass(:, :) !! 1 / column mass (m^2/kg), `(nx,ny)`. real(wp), allocatable :: depth_tot(:, :) !! Total column thickness (m), `(nx,ny)`; used in Lfrict. real(wp), allocatable :: bottom_fac2(:, :) !! gamma_b^2 (nondim), `(nx,ny)`. real(wp), allocatable :: barotr_fac2(:, :) !! gamma_t^2 (nondim), `(nx,ny)`. real(wp), allocatable :: src(:, :) !! Aggregate source (m^2/s^3), `(nx,ny)`. real(wp), allocatable :: uflux(:, :) !! u-face MEKE flux workspace, `(nx+1,ny)`. real(wp), allocatable :: vflux(:, :) !! v-face MEKE flux workspace, `(nx,ny+1)`. real(wp), allocatable :: del2(:, :) !! Laplacian of MEKE workspace (biharmonic), `(nx,ny)`. real(wp), allocatable :: mass_ws(:, :) !! Column mass (kg/m^2), `(nx,ny)`; the harmonic-mass input for the !! lateral flux (= 1/i_mass where i_mass>0). real(wp), allocatable :: u_bbl2(:, :) !! Resolved bed-layer speed² (m²/s²) at cell centres, `(nx,ny)`; !! filled from `ms` when `use_bbl_drag`, else 0. Feeds `meke_drag`. real(wp), allocatable :: ke_diss_ws(:, :) !! Staged hvisc KE-dissipation rate (kg/s³, ≤0), `(nx,ny)`; copied !! from `hv%ke_diss` when the frictional source is wired, else 0. !! Feeds `meke_source` as `-frcoeff·i_mass·ke_diss`. real(wp), allocatable :: rd_ws(:, :) !! Staged copy of `wavespeed%rd_over_dx` (nondim), `(nx,ny)`; zero !! when wavespeed absent ⇒ Ldeform→0. real(wp), allocatable :: f_centre(:, :) !! |f| at cell centres (1/s), `(nx,ny)`; filled by `set_f_centre` !! from the same beta-plane the Coriolis slot uses (mirrors EPBL / !! kappa-shear). Drives `beta = |grad f|` for the Rhines length. !! Zero until filled ⇒ Rhines weight inert (alpha_rhines default 0). real(wp), allocatable :: sn_u_ws(:, :) !! Staged copy of `varmix%sn_u` (1/s), `(nx+1,ny)`; zero when VarMix !! absent ⇒ Eady scale inert. real(wp), allocatable :: sn_v_ws(:, :) !! Staged copy of `varmix%sn_v` (1/s), `(nx,ny+1)`. real(wp), allocatable :: baro_hu(:, :) !! Depth-integrated u-face mass transport (kg/s), `(nx+1,ny)`; !! the barotropic transport that advects E. Filled only when !! `advection_factor > 0`. real(wp), allocatable :: baro_hv(:, :) !! Depth-integrated v-face mass transport (kg/s), `(nx,ny+1)`. contains procedure, non_overridable :: init => ocean_meke_init procedure, non_overridable :: destroy => ocean_meke_destroy procedure, non_overridable :: enter_data => ocean_meke_enter_data procedure, non_overridable :: exit_data => ocean_meke_exit_data procedure, non_overridable :: set_f_centre => ocean_meke_set_f_centre procedure, non_overridable :: bytes => ocean_meke_bytes end type ocean_meke_t