| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | public, | parameter | :: | BDRAG_INVALID | = | -1 |
Sentinel returned by |
| 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 |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public | :: | bbl_thick_min | = | 0.0_wp |
Minimum effective BBL thickness (m) used in the
|
|
| real(kind=wp), | public | :: | bed_factor | = | 1.0_wp |
Multiplier on the bed-layer ( |
|
| 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 |
|
| logical, | public | :: | channel_drag | = | .false. |
Enable the per-layer lateral side-wall (channel) Rayleigh
drag (MOM6 CHANNEL_DRAG analogue). Default |
|
| 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
|
|
| type(scratch_3d_buffer_t), | public | :: | du_drag |
Drag tendency at east faces, shape (nx+1, ny, nz).
In the bed-only mode only |
|||
| 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
|
|
| 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 |
|
| logical, | public | :: | implicit | = | .false. |
Backward-Euler (implicit) bottom drag when |
|
| logical, | public | :: | implicit_fold | = | .false. |
When |
|
| logical, | public | :: | is_init | = | .false. |
True between |
|
| real(kind=wp), | public, | allocatable | :: | lambda_bot_u(:,:) |
Bed-layer ( |
||
| 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 |
|||
| 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. |
| 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 |
.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).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | 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).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | name |
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.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_bottom_drag_t), | intent(in) | :: | this |
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.
| Type | Intent | Optional | 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 |
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.
| Type | Intent | Optional | 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 |
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).
| Type | Intent | Optional | 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 |
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.
| Type | Intent | Optional | 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 |
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).
| Type | Intent | Optional | 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 |
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.
| Type | Intent | Optional | 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) |
|
||
| integer, | intent(in) | :: | k_bot_v(nx_v,ny_v) |
|
||
| 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 |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_bottom_drag_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_bottom_drag_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bottom_drag_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_bottom_drag_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bottom_drag_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_bottom_drag_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in), | optional | :: | nz_ml |