rdb_ocean_bottom_drag Module


Uses

  • module~~rdb_ocean_bottom_drag~~UsesGraph module~rdb_ocean_bottom_drag rdb_ocean_bottom_drag iso_fortran_env iso_fortran_env module~rdb_ocean_bottom_drag->iso_fortran_env module~rdb_constants rdb_constants module~rdb_ocean_bottom_drag->module~rdb_constants module~rdb_grid rdb_grid module~rdb_ocean_bottom_drag->module~rdb_grid module~rdb_mem_report rdb_mem_report module~rdb_ocean_bottom_drag->module~rdb_mem_report module~rdb_multilayer_state rdb_multilayer_state module~rdb_ocean_bottom_drag->module~rdb_multilayer_state module~rdb_ocean_metrics rdb_ocean_metrics module~rdb_ocean_bottom_drag->module~rdb_ocean_metrics module~rdb_scratch_3d rdb_scratch_3d module~rdb_ocean_bottom_drag->module~rdb_scratch_3d pic_types pic_types module~rdb_constants->pic_types module~rdb_grid->module~rdb_constants module~rdb_mem_report->iso_fortran_env module~rdb_mem_report->module~rdb_constants pic_logger pic_logger module~rdb_mem_report->pic_logger pic_strings pic_strings module~rdb_mem_report->pic_strings module~rdb_multilayer_state->iso_fortran_env module~rdb_multilayer_state->module~rdb_constants module~rdb_multilayer_state->module~rdb_grid module~rdb_multilayer_state->module~rdb_mem_report module~rdb_efp rdb_efp module~rdb_multilayer_state->module~rdb_efp module~rdb_error_ring rdb_error_ring module~rdb_multilayer_state->module~rdb_error_ring module~rdb_tracer rdb_tracer module~rdb_multilayer_state->module~rdb_tracer module~rdb_multilayer_state->pic_logger module~rdb_ocean_metrics->iso_fortran_env module~rdb_ocean_metrics->module~rdb_constants module~rdb_ocean_metrics->module~rdb_grid module~rdb_ocean_metrics->module~rdb_mem_report module~rdb_ocean_metrics->module~rdb_error_ring module~rdb_io_netcdf rdb_io_netcdf module~rdb_ocean_metrics->module~rdb_io_netcdf module~rdb_ocean_bipolar rdb_ocean_bipolar module~rdb_ocean_metrics->module~rdb_ocean_bipolar module~rdb_ocean_fold rdb_ocean_fold module~rdb_ocean_metrics->module~rdb_ocean_fold module~rdb_ocean_status rdb_ocean_status module~rdb_ocean_metrics->module~rdb_ocean_status netcdf netcdf module~rdb_ocean_metrics->netcdf module~rdb_ocean_metrics->pic_logger module~rdb_ocean_metrics->pic_strings module~rdb_scratch_3d->iso_fortran_env module~rdb_scratch_3d->module~rdb_constants module~rdb_scratch_3d->module~rdb_mem_report module~rdb_efp->iso_fortran_env ieee_arithmetic ieee_arithmetic module~rdb_efp->ieee_arithmetic module~rdb_error_ring->pic_logger module~rdb_io_netcdf->iso_fortran_env module~rdb_io_netcdf->module~rdb_constants module~rdb_io_netcdf->module~rdb_error_ring module~rdb_io_netcdf->netcdf module~rdb_io_netcdf->pic_logger module~rdb_io_netcdf->pic_strings iso_c_binding iso_c_binding module~rdb_io_netcdf->iso_c_binding module~rdb_ocean_bipolar->module~rdb_constants module~rdb_ocean_fold->module~rdb_constants module~rdb_tracer->iso_fortran_env module~rdb_tracer->module~rdb_constants module~rdb_tracer->module~rdb_grid module~rdb_tracer->module~rdb_mem_report

Used by

  • module~~rdb_ocean_bottom_drag~~UsedByGraph module~rdb_ocean_bottom_drag rdb_ocean_bottom_drag module~rdb_barotropic_coupling rdb_barotropic_coupling module~rdb_barotropic_coupling->module~rdb_ocean_bottom_drag module~rdb_ocean_bt_budget_probe rdb_ocean_bt_budget_probe module~rdb_ocean_bt_budget_probe->module~rdb_ocean_bottom_drag module~rdb_ocean_dyn rdb_ocean_dyn module~rdb_ocean_dyn->module~rdb_ocean_bottom_drag module~rdb_ocean_dyn->module~rdb_barotropic_coupling module~rdb_ocean_dyn->module~rdb_ocean_bt_budget_probe module~rdb_ocean_setup rdb_ocean_setup module~rdb_ocean_setup->module~rdb_ocean_bottom_drag module~rdb_ocean_setup->module~rdb_ocean_dyn module~rdb_ocean_state rdb_ocean_state module~rdb_ocean_setup->module~rdb_ocean_state module~rdb_ocean_state->module~rdb_ocean_bottom_drag module~rdb_ocean_state->module~rdb_ocean_dyn proc~validate_config validate_config proc~validate_config->module~rdb_ocean_bottom_drag module~rdb_driver rdb_driver module~rdb_driver->module~rdb_ocean_dyn module~rdb_driver->module~rdb_ocean_state module~rdb_ocean_engine rdb_ocean_engine module~rdb_driver->module~rdb_ocean_engine module~rdb_handle rdb_handle module~rdb_handle->module~rdb_ocean_state module~rdb_handle->module~rdb_ocean_engine module~rdb_ocean_api rdb_ocean_api module~rdb_ocean_api->module~rdb_ocean_dyn module~rdb_ocean_api->module~rdb_handle module~rdb_ocean_diag_derived rdb_ocean_diag_derived module~rdb_ocean_api->module~rdb_ocean_diag_derived module~rdb_ocean_diag_fills rdb_ocean_diag_fills module~rdb_ocean_api->module~rdb_ocean_diag_fills module~rdb_ocean_api->module~rdb_ocean_engine module~rdb_ocean_diag_derived->module~rdb_ocean_state module~rdb_ocean_diag_derived->module~rdb_ocean_diag_fills module~rdb_ocean_diag_fills->module~rdb_ocean_state module~rdb_ocean_engine->module~rdb_ocean_dyn module~rdb_ocean_engine->module~rdb_ocean_setup module~rdb_ocean_engine->module~rdb_ocean_state module~rdb_ocean_engine->module~rdb_ocean_diag_derived module~rdb_ocean_engine->module~rdb_ocean_diag_fills

Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: BDRAG_INVALID = -1

Sentinel returned by parse_bdrag_variant for an unrecognised string (PR-6 fail-loud). Linear (τ = ρ·r·u) and quadratic (τ = ρ·C_d·|u|·u) have different coefficient dimensions and energy-decay laws, so a typo must abort rather than silently pick one.

integer, public, parameter :: BDRAG_LINEAR = 1

Linear Rayleigh drag. Use for analytic / regression tests where energy decay rate must be predictable.

integer, public, parameter :: BDRAG_QUADRATIC = 2

Log-layer / quadratic drag. Production default.

real(kind=wp), private, parameter :: SIDE_H_VANISH = 1.5e-4_wp

Layer-thickness threshold below which a cross-stream neighbour layer counts as “blocked by sloping bathymetry” for the channel-drag perimeter fraction (matches the H_VANISHED dynamic-vanish role used elsewhere in the ocean core).


Derived Types

type, public ::  ocean_bottom_drag_t

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
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

Functions

public pure function bdrag_variant_is_implemented(code) result(ok)

.true. only for a bottom-drag variant with a real kernel (BDRAG_LINEAR / BDRAG_QUADRATIC). BDRAG_INVALID returns .false.. The single gate validate_config consumes (PR-6).

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: code

Return Value logical

public pure function parse_bdrag_variant(name) result(code)

Translate a namelist string into a BDRAG_* code. An unrecognised string returns BDRAG_INVALID (PR-6 fail-loud — a typo must not silently select the quadratic default over the linear form or vice versa; the two obey different physics).

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: name

Return Value integer

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)


Subroutines

public subroutine ocean_bottom_drag_apply_tendencies(this, ms, dt, no_wait)

no_wait (optional, default .false.): when .true. the apply DC loops run on OpenACC queue 1 and the routine returns WITHOUT syncing, so the batched velocity-apply chain in run_stage_split !$acc wait(1)s ONCE. Default ⇒ blocking (safe for the unsplit run_stage). Not pure because of the async/wait directives.

Arguments

Type IntentOptional Attributes Name
type(ocean_bottom_drag_t), intent(in) :: this
type(multilayer_state_t), intent(inout) :: ms
real(kind=wp), intent(in) :: dt
logical, intent(in), optional :: no_wait

public pure subroutine ocean_bottom_drag_compute_tendencies(grid, this, ms, dt)

Fill du_drag / dv_drag with the bottom-layer drag acceleration on each face’s first LIVE layer k_bot_u/v (≡ 1 off z_fixed); every other layer gets zero in the bed-only mode (default). When hbbl > 0 the stress is distributed across the bottom-most hbbl metres — every layer with cumulative_depth_from_bed_top ≤ hbbl gets a proportional share of the drag tendency.

Read more…

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
type(ocean_bottom_drag_t), intent(inout) :: this
type(multilayer_state_t), intent(in) :: ms
real(kind=wp), intent(in) :: dt

Outer-step length (s); only read when this%implicit.

public subroutine ocean_channel_drag_apply_tendencies(this, ms, dt, no_wait)

Apply the per-layer side drag IMPLICITLY: u <- u / (1 + dt·lambda_side_u), v <- v / (1 + dt·lambda_side_v). The implicit (backward-Euler) form is unconditionally stable on thin layers where an explicit u - dt·lambda·u would overshoot. lambda ≡ 0 (default-off / all-wet / flat-bottom) ⇒ division by 1 ⇒ exact no-op. no_wait semantics mirror ocean_bottom_drag_apply_tendencies. Not pure (async/wait).

Arguments

Type IntentOptional Attributes Name
type(ocean_bottom_drag_t), intent(in) :: this
type(multilayer_state_t), intent(inout) :: ms
real(kind=wp), intent(in) :: dt
logical, intent(in), optional :: no_wait

public pure subroutine ocean_channel_drag_compute_tendencies(grid, metrics, this, ms)

Per-layer lateral side-wall (channel) Rayleigh RATE (lambda_side_u/v, 1/s) for every velocity face whose cross-stream perimeter is partially blocked by land or a vanished (sloping-bathymetry) neighbour layer — fires at EVERY layer k that intersects the obstruction, not just the bed. f_blocked = perimeter fraction blocked, summed over the two flanking wet_q corners (each weighted 0.5), with a corner also counted blocked when its two cross-stream cells’ min h_layer < SIDE_H_VANISH. lambda = cdrag_side·|U_face|·f_blocked/max(W, eps), W the cross-stream face length (dyCu u-face, dxCv v-face). All-wet / flat-bottom ⇒ f_blocked ≡ 0 ⇒ lambda ≡ 0 (no-op); channel_drag=.false. or cdrag_side=0 short-circuits to zero.

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
type(ocean_metrics_t), intent(in) :: metrics
type(ocean_bottom_drag_t), intent(inout) :: this
type(multilayer_state_t), intent(in) :: ms

private pure subroutine compute_channel_drag_rates(lambda_u, lambda_v, u_face, v_face, h_layer, wet_q, dyCu, dxCv, channel_drag, cdrag_side, nx_u, ny_u, nx_v, ny_v, nx, ny, nz)

Device kernel for the per-layer side-drag Rayleigh rate. See ocean_channel_drag_compute_tendencies for the derivation. wet_q is (nx+1, ny+1); dyCu is (nx+1, ny) (u-face length normal to the zonal flow); dxCv is (nx, ny+1).

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(out) :: lambda_u(nx_u,ny_u,nz)
real(kind=wp), intent(out) :: lambda_v(nx_v,ny_v,nz)
real(kind=wp), intent(in) :: u_face(nx_u,ny_u,nz)
real(kind=wp), intent(in) :: v_face(nx_v,ny_v,nz)
real(kind=wp), intent(in) :: h_layer(nx,ny,nz)
real(kind=wp), intent(in) :: wet_q(nx+1,ny+1)
real(kind=wp), intent(in) :: dyCu(nx+1,ny)
real(kind=wp), intent(in) :: dxCv(nx,ny+1)
logical, intent(in) :: channel_drag
real(kind=wp), intent(in) :: cdrag_side
integer, intent(in) :: nx_u
integer, intent(in) :: ny_u
integer, intent(in) :: nx_v
integer, intent(in) :: ny_v
integer, intent(in) :: nx
integer, intent(in) :: ny
integer, intent(in) :: nz

private pure subroutine compute_distributed_drag(du_drag, dv_drag, u_face, v_face, h_layer, wet_mask, k_bot_u, k_bot_v, variant, r, c_d, hbbl, bg_vel, bbl_min, bed_factor, dt_imp, nx_u, ny_u, nx_v, ny_v, nx, ny, nz)

HBBL-distributed bottom drag. Mirrors MOM6’s LINEAR_DRAG and quadratic-with-HBBL formulations: the drag stress is spread across the bottom hbbl metres rather than dumped into the bed-most layer.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: du_drag(nx_u,ny_u,nz)
real(kind=wp), intent(inout) :: dv_drag(nx_v,ny_v,nz)
real(kind=wp), intent(in) :: u_face(nx_u,ny_u,nz)
real(kind=wp), intent(in) :: v_face(nx_v,ny_v,nz)
real(kind=wp), intent(in) :: h_layer(nx,ny,nz)
real(kind=wp), intent(in) :: wet_mask(nx,ny)
integer, intent(in) :: k_bot_u(nx_u,ny_u)

ms%k_bot_u/v — first live layer of the face, counting up.

integer, intent(in) :: k_bot_v(nx_v,ny_v)

ms%k_bot_u/v — first live layer of the face, counting up.

integer, intent(in) :: variant
real(kind=wp), intent(in) :: r
real(kind=wp), intent(in) :: c_d
real(kind=wp), intent(in) :: hbbl
real(kind=wp), intent(in) :: bg_vel
real(kind=wp), intent(in) :: bbl_min
real(kind=wp), intent(in) :: bed_factor
real(kind=wp), intent(in) :: dt_imp

Implicit timestep: dt for backward-Euler drag, 0 for explicit.

integer, intent(in) :: nx_u
integer, intent(in) :: ny_u
integer, intent(in) :: nx_v
integer, intent(in) :: ny_v
integer, intent(in) :: nx
integer, intent(in) :: ny
integer, intent(in) :: nz

private subroutine ocean_bdrag_destroy(this)

Arguments

Type IntentOptional Attributes Name
class(ocean_bottom_drag_t), intent(inout) :: this

private subroutine ocean_bdrag_enter_data(this)

Arguments

Type IntentOptional Attributes Name
class(ocean_bottom_drag_t), intent(inout) :: this

private subroutine ocean_bdrag_enter_data_impl(this)

Arguments

Type IntentOptional Attributes Name
type(ocean_bottom_drag_t), intent(inout) :: this

private subroutine ocean_bdrag_exit_data(this)

Arguments

Type IntentOptional Attributes Name
class(ocean_bottom_drag_t), intent(inout) :: this

private subroutine ocean_bdrag_exit_data_impl(this)

Arguments

Type IntentOptional Attributes Name
type(ocean_bottom_drag_t), intent(inout) :: this

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