Ice-shelf top-drag slot. Every array is full size when
enable, a (1,1) / (1,1,1) placeholder otherwise — the
ocean_cavity_flux_t gating convention, latched in
ocean_state_init_from_config BEFORE init so the allocation
gate can read it.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public | :: | c_drag | = | 0.0_wp |
Quadratic drag coefficient (dimensionless). ISOMIP+ 2.5e-3. Zero disables the quadratic branch. |
|
| real(kind=wp), | public, | allocatable | :: | cover_t(:,:) |
CELL-CENTRED ice-cover mask, shape (nx, ny) — a configure-time
copy of |
||
| real(kind=wp), | public, | allocatable | :: | cover_u(:,:) |
Face ice-cover mask at east faces, shape (nx+1, ny): the OR of
the two abutting cells’ |
||
| real(kind=wp), | public, | allocatable | :: | cover_v(:,:) |
Face ice-cover mask at north faces, shape (nx, ny+1). |
||
| real(kind=wp), | public | :: | drag_bg_vel | = | 0.0_wp |
Background velocity floor (m/s) in the quadratic speed,
|
|
| type(scratch_3d_buffer_t), | public | :: | du_drag |
Top-drag tendency at east faces, shape (nx+1, ny, nz). Only layers inside the top boundary layer carry a non-zero value. |
|||
| type(scratch_3d_buffer_t), | public | :: | dv_drag |
Top-drag tendency at north faces, shape (nx, ny+1, nz). |
|||
| logical, | public | :: | enable | = | .false. |
|
|
| real(kind=wp), | public | :: | h_min | = | 1.0e-3_wp |
Floor on the top-layer face thickness inside the |
|
| real(kind=wp), | public | :: | htbl | = | 0.0_wp |
Top-boundary-layer thickness (m) the stress is distributed
over (the mirror of |
|
| logical, | public | :: | implicit | = | .false. |
Backward-Euler top drag in this kernel: the tendency is formed
as |
|
| logical, | public | :: | implicit_fold | = | .false. |
|
|
| logical, | public | :: | is_init | = | .false. |
True between |
|
| real(kind=wp), | public, | allocatable | :: | lambda_top_u(:,:) |
Top-layer (k=nz) Rayleigh RATE lambda (1/s) at east faces,
shape (nx+1, ny): |
||
| real(kind=wp), | public, | allocatable | :: | lambda_top_v(:,:) |
Top-layer Rayleigh rate at north faces, shape (nx, ny+1). |
||
| real(kind=wp), | public | :: | r_linear | = | 0.0_wp |
Linear Rayleigh coefficient (1/s). Zero disables the linear branch even when the variant tag selects it. |
|
| real(kind=wp), | public | :: | rho0 | = | 0.0_wp |
Boussinesq reference density (kg/m^3) — |
|
| real(kind=wp), | public, | allocatable | :: | stress_top(:,:) |
Cell-centred magnitude of the top stress (N/m^2),
|
||
| real(kind=wp), | public | :: | tbl_thick_min | = | 0.0_wp |
Minimum effective TBL thickness (m) in the |
|
| integer, | public | :: | variant | = | TDRAG_QUADRATIC |
Active drag variant ( |
Counted allocatable footprint of the top-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_top_drag_t), | intent(in) | :: | this |
Release the slot. is_init is cleared FIRST.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_top_drag_t), | intent(inout) | :: | this |
Type-bound wrapper — delegates to the non-polymorphic impl so the device-attach map base is the heap object, not a polymorphic box.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_top_drag_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_top_drag_t), | intent(inout) | :: | this |
Allocate the slot. Gated on enable (latched before this runs),
so a run without an ice shelf pays five (1,1) placeholders and
two (1,1,1) scratch buffers.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_top_drag_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in), | optional | :: | nz_ml |
type :: ocean_top_drag_t !! Ice-shelf top-drag slot. Every array is full size when !! `enable`, a `(1,1)` / `(1,1,1)` placeholder otherwise — the !! `ocean_cavity_flux_t` gating convention, latched in !! `ocean_state_init_from_config` BEFORE `init` so the allocation !! gate can read it. logical :: is_init = .false. !! True between `init` and `destroy`. Always test this, never !! `allocated(...)`. logical :: enable = .false. !! `&ocean_tdrag_nml enable`, latched before `init`. Off ⇒ !! placeholders, no kernel launch, byte-identical. integer :: variant = TDRAG_QUADRATIC !! Active drag variant (`TDRAG_*`). real(wp) :: r_linear = 0.0_wp !! Linear Rayleigh coefficient (1/s). Zero disables the linear !! branch even when the variant tag selects it. real(wp) :: c_drag = 0.0_wp !! Quadratic drag coefficient (dimensionless). ISOMIP+ 2.5e-3. !! Zero disables the quadratic branch. real(wp) :: h_min = 1.0e-3_wp !! Floor on the top-layer face thickness inside the `u/h_top` !! division — keeps the kernel finite when the top layer pinches !! out. Matches the bottom-drag `h_min`. real(wp) :: htbl = 0.0_wp !! Top-boundary-layer thickness (m) the stress is distributed !! over (the mirror of `hbbl`). Zero (default) = layer-`nz`-only !! mode. real(wp) :: drag_bg_vel = 0.0_wp !! Background velocity floor (m/s) in the quadratic speed, !! `|U_eff| = max(drag_bg_vel, |U_tbl|)` (the mirror of MOM6 !! DRAG_BG_VEL). UNLIKE the bottom-drag slot, this is honoured !! in BOTH the layer-only and distributed modes — the two kernels !! are one code path here. Zero (default) ⇒ no floor ⇒ the !! layer-only quadratic branch is the exact algebraic mirror of !! `ocean_bottom_drag_compute_tendencies`. real(wp) :: tbl_thick_min = 0.0_wp !! Minimum effective TBL thickness (m) in the `stress / h_tbl` !! denominator (mirror of BBL_THICK_MIN). Zero (default) falls !! back to `h_min`. logical :: implicit = .false. !! Backward-Euler top drag in this kernel: the tendency is formed !! as `-lambda*u/(1 + dt*lambda)` so the standalone apply gives !! `u^{n+1} = u/(1 + dt*lambda)`. Unconditionally stable for any !! layer thickness. Default `.false.` = explicit forward Euler. logical :: implicit_fold = .false. !! `&ocean_vdiff_nml implicit_top_drag`: fill `lambda_top_u/v` !! so the vdiff solver can fold the drag into its `k = nz` !! diagonal, and let the driver SKIP the explicit apply. Default !! `.false.` ⇒ the rate fields stay zero. real(wp) :: rho0 = 0.0_wp !! Boussinesq reference density (kg/m^3) — `eos%rho0` via !! `configure_ocean_reference_density`. Used ONLY to turn the !! kinematic drag into the `stress_top` diagnostic; no dynamics !! reads it. type(scratch_3d_buffer_t) :: du_drag !! Top-drag tendency at east faces, shape (nx+1, ny, nz). Only !! layers inside the top boundary layer carry a non-zero value. type(scratch_3d_buffer_t) :: dv_drag !! Top-drag tendency at north faces, shape (nx, ny+1, nz). real(wp), allocatable :: cover_u(:, :) !! Face ice-cover mask at east faces, shape (nx+1, ny): the OR of !! the two abutting cells' `cover_frac` (see the module !! docstring). STATIC — filled once at configure. real(wp), allocatable :: cover_v(:, :) !! Face ice-cover mask at north faces, shape (nx, ny+1). real(wp), allocatable :: cover_t(:, :) !! CELL-CENTRED ice-cover mask, shape (nx, ny) — a configure-time !! copy of `metrics%cover_frac`. Held on the slot (rather than !! reaching into `metrics` per step) so the kernel signature !! carries exactly the fields it reads. Used only by the !! `stress_top` diagnostic, which is cell-centred. real(wp), allocatable :: lambda_top_u(:, :) !! Top-layer (k=nz) Rayleigh RATE lambda (1/s) at east faces, !! shape (nx+1, ny): `C_d*|U|/h_nz` (quadratic, `|U|` frozen at !! u^n) or `r` (linear), already cover- and wet-masked. Consumed !! by `vdiff_apply_momentum` as the `+dt*lambda` add on the !! `k = nz` diagonal. Zero unless `implicit_fold`. real(wp), allocatable :: lambda_top_v(:, :) !! Top-layer Rayleigh rate at north faces, shape (nx, ny+1). real(wp), allocatable :: stress_top(:, :) !! Cell-centred magnitude of the top stress (N/m^2), !! `rho_0 * |a_drag| * h_tbl` — see the module docstring. Write !! only here; the KPP/EPBL `ustar_shelf` consumer is a later PR. contains procedure, non_overridable :: init => ocean_top_drag_init procedure, non_overridable :: destroy => ocean_top_drag_destroy procedure, non_overridable :: enter_data => ocean_top_drag_enter_data procedure, non_overridable :: exit_data => ocean_top_drag_exit_data procedure, non_overridable :: bytes => ocean_top_drag_bytes end type ocean_top_drag_t