ocean_bottom_drag_t Derived Type

type, public :: ocean_bottom_drag_t


Inherits

type~~ocean_bottom_drag_t~~InheritsGraph type~ocean_bottom_drag_t ocean_bottom_drag_t type~scratch_3d_buffer_t scratch_3d_buffer_t type~ocean_bottom_drag_t->type~scratch_3d_buffer_t du_drag, dv_drag, lambda_side_u, lambda_side_v

Inherited by

type~~ocean_bottom_drag_t~~InheritedByGraph type~ocean_bottom_drag_t ocean_bottom_drag_t type~ocean_state_t ocean_state_t type~ocean_state_t->type~ocean_bottom_drag_t bdrag 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 :: bbl_thick_min = 0.0_wp

Minimum effective BBL thickness (m) used in the stress / h_bbl denominator (MOM6 BBL_THICK_MIN). Guards against hbbl - sum(h_bottom_layers) going to zero when the bottom layers themselves are very thin. Zero (default) leaves no floor (falls back to h_min).

real(kind=wp), public :: bed_factor = 1.0_wp

Multiplier on the bed-layer (k = k_bot) drag tendency only — layers above it are unchanged. Lets the bed get bed_factor · r while the surface keeps the nominal r (and via HBBL distribution typically gets none). Default 1.0 keeps the historical drag bit-identical. Driver writes from cfg%ocean%bdrag%bed_factor at init. See compute_distributed_drag for the kernel-side application.

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

Quadratic-drag coefficient (dimensionless). Zero disables the quadratic branch. MOM6 / ROMS default is 2.5e-3.

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

Side-wall drag coefficient (dimensionless). Zero (default) ⇒ zero side-drag rate even when channel_drag = .true..

logical, public :: channel_drag = .false.

Enable the per-layer lateral side-wall (channel) Rayleigh drag (MOM6 CHANNEL_DRAG analogue). Default .false. ⇒ the channel-drag kernels are no-ops (bit-identical). Driver writes from cfg%ocean%bdrag%channel_drag at init.

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

Background velocity floor (m/s) for the quadratic and distributed forms (MOM6 DRAG_BG_VEL). The effective bottom speed used in the stress formula is max(drag_bg_vel, |u_bbl|) so laminar-bottom cells still see damping. MOM6 production default 0.1 m/s. Zero (default) disables the floor.

type(scratch_3d_buffer_t), public :: du_drag

Drag tendency at east faces, shape (nx+1, ny, nz). In the bed-only mode only k = k_bot_u (the face’s first live layer, 1 off z_fixed) carries a non-zero value.

type(scratch_3d_buffer_t), public :: dv_drag

Drag tendency at north faces, shape (nx, ny+1, nz).

real(kind=wp), public :: h_min = 1.0e-3_wp

Floor on the bottom-layer thickness inside the u / h_bot division — keeps the kernel finite when the bottom layer pinches out under ZSTAR_FULL.

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

Bottom-boundary-layer thickness (m) over which the drag is distributed (MOM6 HBBL). When zero (default), the drag is applied to the bed layer only — historical behaviour, bit-identical to prior production. Positive values activate the distributed-drag form: the stress is spread across the bottom hbbl metres so very thin bed layers don’t see all the damping at once.

logical, public :: implicit = .false.

Backward-Euler (implicit) bottom drag when .true.: u^{n+1} = u/(1 + dt·λ), unconditionally stable for any bottom-layer thickness (matches MOM6’s implicit bottom-BC drag). Default .false. = explicit forward-Euler tendency, bit-identical to the historical path but conditionally unstable on thin shelf bottom layers (dt·λ > 1). Driver writes from cfg%ocean%bdrag%implicit at init.

logical, public :: implicit_fold = .false.

When .true., also fill the bed-layer (k = k_bot) Rayleigh RATE fields lambda_bot_u/v (1/s) in compute_tendencies so the vdiff solver can fold the drag into its tridiagonal diagonal (&ocean_vdiff_nml implicit_drag). The explicit du_drag tendency is then NOT applied by the driver (gated off) to avoid double-counting. Default .false. ⇒ the rate fields stay zero and the explicit path is unchanged (bit-identical). Driver sets this from cfg%ocean%vdiff%implicit_drag at configure.

logical, public :: is_init = .false.

True between init and destroy.

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

Bed-layer (k = k_bot_u) bottom-drag Rayleigh RATE λ (1/s) at east faces, shape (nx+1, ny). λ = c_d·|U_bbl|/h_kb (quadratic) or r (linear), |U| frozen at uⁿ. Consumed by vdiff_apply_ momentum as the +dt·λ diagonal add when implicit_drag. Zero unless implicit_fold = .true..

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

Bed-layer bottom-drag Rayleigh rate λ (1/s) at north faces, shape (nx, ny+1).

type(scratch_3d_buffer_t), public :: lambda_side_u

Per-layer side-drag Rayleigh RATE (1/s) at east faces, shape (nx+1, ny, nz). Stored (not a tendency) so the apply can use the implicit form u/(1+dt*lambda). Zero where no lateral perimeter is blocked (all-wet / flat-bottom).

type(scratch_3d_buffer_t), public :: lambda_side_v

Per-layer side-drag Rayleigh rate (1/s) at north faces, shape (nx, ny+1, nz).

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

Linear Rayleigh coefficient (1/s). Zero disables the linear branch even if the variant tag selects it.

integer, public :: variant = BDRAG_QUADRATIC

Active drag variant.


Type-Bound Procedures

procedure, public, non_overridable :: bytes => ocean_bottom_drag_bytes

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

    Counted allocatable footprint of the bottom drag 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_bottom_drag_t), intent(in) :: this

    Return Value integer(kind=int64)

procedure, public, non_overridable :: destroy => ocean_bdrag_destroy

procedure, public, non_overridable :: enter_data => ocean_bdrag_enter_data

procedure, public, non_overridable :: exit_data => ocean_bdrag_exit_data

procedure, public, non_overridable :: init => ocean_bdrag_init

  • private subroutine ocean_bdrag_init(this, grid, nz_ml)

    Arguments

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

Source Code

   type :: ocean_bottom_drag_t
      logical :: is_init = .false.
         !! True between `init` and `destroy`.
      integer :: variant = BDRAG_QUADRATIC
         !! Active drag variant.
      real(wp) :: r_linear = 0.0_wp
         !! Linear Rayleigh coefficient (1/s).  Zero disables the
         !! linear branch even if the variant tag selects it.
      real(wp) :: c_drag = 0.0_wp
         !! Quadratic-drag coefficient (dimensionless).  Zero
         !! disables the quadratic branch.  MOM6 / ROMS default
         !! is 2.5e-3.
      real(wp) :: h_min = 1.0e-3_wp
         !! Floor on the bottom-layer thickness inside the
         !! `u / h_bot` division — keeps the kernel finite when
         !! the bottom layer pinches out under ZSTAR_FULL.
      real(wp) :: hbbl = 0.0_wp
         !! Bottom-boundary-layer thickness (m) over which the drag
         !! is distributed (MOM6 HBBL).  When zero (default), the
         !! drag is applied to the bed layer only — historical
         !! behaviour, bit-identical to prior production.  Positive
         !! values activate the distributed-drag form: the stress
         !! is spread across the bottom `hbbl` metres so very thin
         !! bed layers don't see all the damping at once.
      real(wp) :: drag_bg_vel = 0.0_wp
         !! Background velocity floor (m/s) for the quadratic and
         !! distributed forms (MOM6 DRAG_BG_VEL).  The effective
         !! bottom speed used in the stress formula is
         !! `max(drag_bg_vel, |u_bbl|)` so laminar-bottom cells
         !! still see damping.  MOM6 production default 0.1 m/s.
         !! Zero (default) disables the floor.
      real(wp) :: bbl_thick_min = 0.0_wp
         !! Minimum effective BBL thickness (m) used in the
         !! `stress / h_bbl` denominator (MOM6 BBL_THICK_MIN).
         !! Guards against `hbbl - sum(h_bottom_layers)` going to
         !! zero when the bottom layers themselves are very thin.
         !! Zero (default) leaves no floor (falls back to `h_min`).
      real(wp) :: bed_factor = 1.0_wp
         !! Multiplier on the bed-layer (`k = k_bot`) drag tendency only —
         !! layers above it are unchanged.  Lets the bed get
         !! `bed_factor · r` while the surface keeps the nominal `r`
         !! (and via HBBL distribution typically gets none).  Default
         !! `1.0` keeps the historical drag bit-identical.  Driver
         !! writes from `cfg%ocean%bdrag%bed_factor` at init.  See
         !! `compute_distributed_drag` for the kernel-side application.
      logical :: implicit = .false.
         !! Backward-Euler (implicit) bottom drag when `.true.`:
         !! `u^{n+1} = u/(1 + dt·λ)`, unconditionally stable for any
         !! bottom-layer thickness (matches MOM6's implicit bottom-BC
         !! drag).  Default `.false.` = explicit forward-Euler tendency,
         !! bit-identical to the historical path but conditionally
         !! unstable on thin shelf bottom layers (`dt·λ > 1`).  Driver
         !! writes from `cfg%ocean%bdrag%implicit` at init.

      logical :: channel_drag = .false.
         !! Enable the per-layer lateral side-wall (channel) Rayleigh
         !! drag (MOM6 CHANNEL_DRAG analogue).  Default `.false.` ⇒ the
         !! channel-drag kernels are no-ops (bit-identical).  Driver
         !! writes from `cfg%ocean%bdrag%channel_drag` at init.
      real(wp) :: cdrag_side = 0.0_wp
         !! Side-wall drag coefficient (dimensionless).  Zero (default)
         !! ⇒ zero side-drag rate even when `channel_drag = .true.`.

      type(scratch_3d_buffer_t) :: du_drag
         !! Drag tendency at east faces, shape (nx+1, ny, nz).
         !! In the bed-only mode only `k = k_bot_u` (the face's first live
         !! layer, `1` off `z_fixed`) carries a non-zero value.
      type(scratch_3d_buffer_t) :: dv_drag
         !! Drag tendency at north faces, shape (nx, ny+1, nz).

      logical :: implicit_fold = .false.
         !! When `.true.`, also fill the bed-layer (`k = k_bot`) Rayleigh RATE
         !! fields `lambda_bot_u/v` (1/s) in `compute_tendencies` so the
         !! vdiff solver can fold the drag into its tridiagonal diagonal
         !! (`&ocean_vdiff_nml implicit_drag`).  The explicit `du_drag`
         !! tendency is then NOT applied by the driver (gated off) to avoid
         !! double-counting.  Default `.false.` ⇒ the rate fields stay zero
         !! and the explicit path is unchanged (bit-identical).  Driver sets
         !! this from `cfg%ocean%vdiff%implicit_drag` at configure.

      real(wp), allocatable :: lambda_bot_u(:, :)
         !! Bed-layer (`k = k_bot_u`) bottom-drag Rayleigh RATE λ (1/s) at
         !! east faces, shape (nx+1, ny).  `λ = c_d·|U_bbl|/h_kb` (quadratic) or
         !! `r` (linear), `|U|` frozen at uⁿ.  Consumed by `vdiff_apply_
         !! momentum` as the `+dt·λ` diagonal add when `implicit_drag`.
         !! Zero unless `implicit_fold = .true.`.
      real(wp), allocatable :: lambda_bot_v(:, :)
         !! Bed-layer bottom-drag Rayleigh rate λ (1/s) at north faces,
         !! shape (nx, ny+1).

      type(scratch_3d_buffer_t) :: lambda_side_u
         !! Per-layer side-drag Rayleigh RATE (1/s) at east faces,
         !! shape (nx+1, ny, nz).  Stored (not a tendency) so the apply
         !! can use the implicit form `u/(1+dt*lambda)`.  Zero where no
         !! lateral perimeter is blocked (all-wet / flat-bottom).
      type(scratch_3d_buffer_t) :: lambda_side_v
         !! Per-layer side-drag Rayleigh rate (1/s) at north faces,
         !! shape (nx, ny+1, nz).
   contains
      procedure, non_overridable :: init => ocean_bdrag_init
      procedure, non_overridable :: destroy => ocean_bdrag_destroy
      procedure, non_overridable :: enter_data => ocean_bdrag_enter_data
      procedure, non_overridable :: exit_data => ocean_bdrag_exit_data
      procedure, non_overridable :: bytes => ocean_bottom_drag_bytes
   end type ocean_bottom_drag_t