ocean_mle_t Derived Type

type, public :: ocean_mle_t

Fox-Kemper mixed-layer-eddy restratification state. All fields default to the inert (enable=.false.) configuration so an ocean run that never sets &ocean_foxkemper_nml is bit-identical.


Inherited by

type~~ocean_mle_t~~InheritedByGraph type~ocean_mle_t ocean_mle_t type~ocean_state_t ocean_state_t type~ocean_state_t->type~ocean_mle_t mle type~ocean_engine_t ocean_engine_t type~ocean_engine_t->type~ocean_state_t state type~ocean_handle_t ocean_handle_t type~ocean_handle_t->type~ocean_state_t state type~ocean_handle_t->type~ocean_engine_t engine

Components

Type Visibility Attributes Name Initial
real(kind=wp), public, allocatable :: b_ml(:,:)

ML-averaged buoyancy b_bar (m/s^2), (nx,ny).

real(kind=wp), public :: bodner_mstar = 0.5_wp

Mechanical (u*) weight in w'u' = (mstar·u*³+nstar·w*³)^{2/3}.

real(kind=wp), public :: bodner_nstar = 0.066_wp

Convective (w*) weight; w*³ = max(0,-b0)·mld from epbl%b0.

real(kind=wp), public :: ce = 0.0625_wp

FK08 coefficient Ce (typical 0.06-0.08).

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

Bodner efficiency coefficient Cr (nondim).

logical, public :: enable = .false.

Master switch. Off => mle_compute_transports is a no-op and the folds add nothing => bit-identity preserved.

real(kind=wp), public :: f_floor = 1.0e-5_wp

|f| regularisation floor (1/s); ~|f| at 4 degN.

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

Accumulated ML thickness on the grid (<= mld) (m), (nx,ny).

logical, public :: is_init = .false.

True between init and destroy; tracks GPU attachment.

real(kind=wp), public :: min_wstar2 = 1.0e-24_wp

Floor on w'u' (m²/s²), pure 1/0 armour.

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

Running-mean MLD filter time-scale (s). 0 ⇒ filter off (instantaneous EPBL MLD, bit-identical). Positive ⇒ the MLD resets instantly to a deeper value but decays over this scale when the diagnosed MLD retreats, bounding Psi ~ MLD² growth under a thinning/oscillating boundary layer.

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

Running-mean filtered MLD (m), (nx,ny); persistent across steps. Only used when mld_decay_time > 0. Lazily seeded from the first instantaneous MLD (the < 0 sentinel marks the unseeded state so the running mean starts from the true value rather than a spurious zero — MOM6 seeds from a restart field).

integer, public :: nx_total = 0
integer, public :: ny_total = 0
integer, public :: nz_ml = 0
logical, public :: resolution_taper = .false.

Resolution-function taper hook. Hard config error if on without the resolution function (deferred).

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

mu cubic-tail extension below the ML base. Default 0 ⇒ exact FK08 mu (the tail itself is deferred).

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

FK x-face transport (m^3/s), (nx+1,ny,nz_ml). Filled once per outer step at thermo cadence, then folded into continuity every dynamics call via mle_fold_x. At dt_therm_ratio > 1 the stale values are re-folded on non-thermo steps (over-applies FK; still conservative since sum_k a(k) = 0).

logical, public :: use_bodner = .false.

Bodner et al. (2023) frontogenesis-arrest variant. When true the Ce/|f| timescale is replaced by ts_bod = Cr·Δs·|f|·h/w'u' (a timescale [s], so it drops into the same uDml formula); the frontal-arrest length enters inline as |f|·h/w'u'. Default off.

logical, public :: use_mom_mixrate = .false.

Use the FK11 momentum-mixrate timescale instead of the bare Ce/|f| floor form. Production-recommended; default off.

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

FK y-face transport (m^3/s), (nx,ny+1,nz_ml); same limitation.


Type-Bound Procedures

procedure, public, non_overridable :: bytes => ocean_mle_bytes

  • private pure function ocean_mle_bytes(this) result(nbytes)

    Counted allocatable footprint of the MLE / Fox-Kemper 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_mle_t), intent(in) :: this

    Return Value integer(kind=int64)

procedure, public :: destroy => ocean_mle_destroy

procedure, public :: enter_data => ocean_mle_enter_data

procedure, public :: exit_data => ocean_mle_exit_data

procedure, public :: init => ocean_mle_init

  • private subroutine ocean_mle_init(this, grid, nz_ml)

    Allocate the 2D ML diagnostics + per-layer face transports. Always allocates (configure runs after init); the off-state footprint is two 2D + two face-shaped 3D arrays.

    Arguments

    Type IntentOptional Attributes Name
    class(ocean_mle_t), intent(inout) :: this
    type(hgrid_t), intent(in) :: grid
    integer, intent(in), optional :: nz_ml

Source Code

   type :: ocean_mle_t
      !! Fox-Kemper mixed-layer-eddy restratification state.  All fields
      !! default to the inert (`enable=.false.`) configuration so an
      !! ocean run that never sets `&ocean_foxkemper_nml` is bit-identical.
      logical :: is_init = .false.
         !! True between `init` and `destroy`; tracks GPU attachment.
      logical :: enable = .false.
         !! Master switch.  Off => `mle_compute_transports` is a no-op and
         !! the folds add nothing => bit-identity preserved.
      real(wp) :: ce = 0.0625_wp
         !! FK08 coefficient Ce (typical 0.06-0.08).
      real(wp) :: f_floor = 1.0e-5_wp
         !! |f| regularisation floor (1/s); ~|f| at 4 degN.
      real(wp) :: mld_decay_time = 0.0_wp
         !! Running-mean MLD filter time-scale (s).  0 ⇒ filter off
         !! (instantaneous EPBL MLD, bit-identical).  Positive ⇒ the MLD
         !! resets instantly to a deeper value but decays over this scale
         !! when the diagnosed MLD retreats, bounding Psi ~ MLD² growth
         !! under a thinning/oscillating boundary layer.
      real(wp) :: tail_dh = 0.0_wp
         !! mu cubic-tail extension below the ML base.  Default 0 ⇒ exact
         !! FK08 mu (the tail itself is deferred).
      logical :: use_mom_mixrate = .false.
         !! Use the FK11 momentum-mixrate timescale instead of the bare
         !! Ce/|f| floor form.  Production-recommended; default off.
      logical :: resolution_taper = .false.
         !! Resolution-function taper hook.  Hard config error if on
         !! without the resolution function (deferred).
      logical :: use_bodner = .false.
         !! Bodner et al. (2023) frontogenesis-arrest variant.  When true the
         !! `Ce/|f|` timescale is replaced by `ts_bod = Cr·Δs·|f|·h/w'u'` (a
         !! timescale [s], so it drops into the same uDml formula); the
         !! frontal-arrest length enters inline as `|f|·h/w'u'`.  Default off.
      real(wp) :: cr = 0.0_wp
         !! Bodner efficiency coefficient `Cr` (nondim).
      real(wp) :: bodner_mstar = 0.5_wp
         !! Mechanical (u*) weight in `w'u' = (mstar·u*³+nstar·w*³)^{2/3}`.
      real(wp) :: bodner_nstar = 0.066_wp
         !! Convective (w*) weight; `w*³ = max(0,-b0)·mld` from `epbl%b0`.
      real(wp) :: min_wstar2 = 1.0e-24_wp
         !! Floor on `w'u'` (m²/s²), pure 1/0 armour.

      ! ---- Cached extents ----
      integer :: nx_total = 0
      integer :: ny_total = 0
      integer :: nz_ml = 0

      ! ---- 2D ML diagnostics (cell centres) ----
      real(wp), allocatable :: b_ml(:, :)
         !! ML-averaged buoyancy b_bar (m/s^2), `(nx,ny)`.
      real(wp), allocatable :: htot_ml(:, :)
         !! Accumulated ML thickness on the grid (<= mld) (m), `(nx,ny)`.
      real(wp), allocatable :: mld_filtered(:, :)
         !! Running-mean filtered MLD (m), `(nx,ny)`; persistent across
         !! steps.  Only used when `mld_decay_time > 0`.  Lazily seeded
         !! from the first instantaneous MLD (the `< 0` sentinel marks the
         !! unseeded state so the running mean starts from the true value
         !! rather than a spurious zero — MOM6 seeds from a restart field).

      ! ---- Per-layer FK transports (faces) ----
      ! k=1 bed, k=nz surface.  These are added to the continuity mass
      ! fluxes before the divergence; sum_k over each face is ~0.
      real(wp), allocatable :: uhml(:, :, :)
         !! FK x-face transport (m^3/s), `(nx+1,ny,nz_ml)`.  Filled once per
         !! outer step at thermo cadence, then folded into continuity every
         !! dynamics call via `mle_fold_x`.  At `dt_therm_ratio > 1` the
         !! stale values are re-folded on non-thermo steps (over-applies FK;
         !! still conservative since sum_k a(k) = 0).
      real(wp), allocatable :: vhml(:, :, :)
         !! FK y-face transport (m^3/s), `(nx,ny+1,nz_ml)`; same limitation.
   contains
      procedure :: init => ocean_mle_init
      procedure :: destroy => ocean_mle_destroy
      procedure :: enter_data => ocean_mle_enter_data
      procedure :: exit_data => ocean_mle_exit_data
      procedure, non_overridable :: bytes => ocean_mle_bytes
   end type ocean_mle_t