Per-column first-baroclinic internal gravity-wave speed cg1
(m/s) and first-mode Rossby radius Rd (m), plus Rd/dx (the
GM/Redi/MEKE resolution ratio). Solves the rigid-lid
Sturm-Liouville eigenproblem discretised from layer thicknesses
and per-interface reduced gravities gprime = (g/rho0)*max(0,drho)
(rho_layer authoritative); largest c^2 via a fixed-budget
Sturm-count bisection (no early exit -> warp-divergence-free).
Reference: Chelton et al. (1998).
Vertical ordering (load-bearing): rdb is bottom-up (k=1 bed, k=nz surface); the eigensolve is surface-down so the column kernel FLIPS on gather (local k_loc=1 is the surface layer).
Diagnostic, default off (&ocean_wavespeed_nml enable=.false.) ⇒
kernel never called, bit-identical.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private, | parameter | :: | C2_SCALE | = | 1.0_wp/(4096.0_wp*4096.0_wp) |
Per-row determinant rescale |
| real(kind=wp), | private, | parameter | :: | F_DENOM_FLOOR | = | 1.0e-10_wp |
Floor on the Rd denominator (guards f = beta = 0). |
| real(kind=wp), | private, | parameter | :: | I_RESCALE | = | 1.0_wp/(1024.0_wp**4) | |
| real(kind=wp), | private, | parameter | :: | LAM_SEED | = | 1.0e-20_wp |
Tiny lower seed for the doubling prelude (below any physical eigenvalue). |
| integer, | private, | parameter | :: | MAX_DBL | = | 128 |
Cap on the Sturm-count doubling prelude (data-dependent trip count, but O(1) det evals; the inner bisection stays fixed). |
| integer, | private, | parameter | :: | MAX_ITT | = | 40 |
Fixed bisection budget — no early exit (GPU-divergence-free). |
| real(kind=wp), | private, | parameter | :: | MIN_SPEED2 | = | 1.0e-8_wp |
|
| real(kind=wp), | private, | parameter | :: | RD_GUARD | = | 1.0e-20_wp |
Inside-sqrt guard for the smooth equatorial Rd blend. |
| real(kind=wp), | private, | parameter | :: | RESCALE | = | 1024.0_wp**4 |
Dynamic-rescale ceiling to keep |
| real(kind=wp), | private, | parameter | :: | TOL_MERGE | = | 0.001_wp |
Relative backtracking-merge threshold (MOM6 wave_speed_tol
default). The criterion is relative to the column’s own
stratification scale |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public, | allocatable | :: | beta_centre(:,:) |
|grad f| at cell centres (1/(m*s)); static, filled at
configure by |
||
| real(kind=wp), | public, | allocatable | :: | cg1(:,:) |
First-baroclinic gravity-wave speed (m/s). |
||
| logical, | public | :: | enable | = | .false. |
Master switch. Default off — bit-identity preserved. |
|
| real(kind=wp), | public, | allocatable | :: | f_centre(:,:) |
|f| at cell centres (1/s); filled by |
||
| logical, | public | :: | is_init | = | .false. |
True between |
|
| real(kind=wp), | public | :: | mono_n2_depth | = | -1.0_wp |
depth. |
|
| integer, | public | :: | n_wavespeed | = | 1 |
diagnostic). Default every step (cheap when default-off). |
|
| real(kind=wp), | public, | allocatable | :: | rd(:,:) |
First-mode Rossby deformation radius (m). |
||
| real(kind=wp), | public, | allocatable | :: | rd_over_dx(:,:) |
Rd / dx (nondim) — the B2 resolution ratio. |
||
| real(kind=wp), | public | :: | rho0 | = | 1035.0_wp |
Boussinesq reference density (kg/m^3) for |
|
| logical, | public | :: | use_ebt | = | .false. |
DEFERRED: pressure-Neumann / equivalent-barotropic variant. |
| procedure, public :: build_static => ocean_wave_speed_build_static | |
| procedure, public, non_overridable :: bytes => ocean_wave_speed_bytes | |
| procedure, public :: destroy => ocean_wave_speed_destroy | |
| procedure, public :: enter_data => ocean_wave_speed_enter_data | |
| procedure, public :: exit_data => ocean_wave_speed_exit_data | |
| procedure, public :: init => ocean_wave_speed_init |
Smooth equatorial Rd blend: Rd = cg1/sqrt(f^2 + 2betacg1). Reduces to cg1/|f| away from the equator and sqrt(cg1/(2*beta)) at f=0; a small inside-sqrt guard + denominator floor handle f = beta = 0.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | cg1 | |||
| real(kind=wp), | intent(in) | :: | fabs | |||
| real(kind=wp), | intent(in) | :: | beta |
Sign of det(M(lam)) on rows 2..kc (Sturm/Hallberg recursion).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | igu(NZ_STACK_MAX+1) | |||
| real(kind=wp), | intent(in) | :: | igl(NZ_STACK_MAX+1) | |||
| integer, | intent(in) | :: | kc | |||
| real(kind=wp), | intent(in) | :: | lam |
Counted allocatable footprint of the wave speed 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_wave_speed_t), | intent(in) | :: | this |
Number of Sturm-sequence sign changes (eigenvalues < lam) via the three-term determinant recursion with dynamic rescaling.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | igu(NZ_STACK_MAX+1) | |||
| real(kind=wp), | intent(in) | :: | igl(NZ_STACK_MAX+1) | |||
| integer, | intent(in) | :: | kc | |||
| real(kind=wp), | intent(in) | :: | lam |
First-baroclinic wave speed for ONE column. h_rak/rho_rak
are in Roundabout ordering (k=1 bed, k=nz surface), fixed-size
NZ_STACK_MAX arrays; only 1..nz are read. Returns cg1 (m/s),
0 for land / homogeneous / kc<2 / sub-floor columns.
Gathers+flips surface-down, backtracking convective merge,
symmetric tridiag, fixed-budget Sturm-count bisection.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | h_rak(NZ_STACK_MAX) | |||
| real(kind=wp), | intent(in) | :: | rho_rak(NZ_STACK_MAX) | |||
| real(kind=wp), | intent(in) | :: | rho0 | |||
| real(kind=wp), | intent(out) | :: | cg1 |
Fill this%cg1, this%rd, this%rd_over_dx over the domain.
rho_layer is a top-level allocatable that reaches the device
directly, so no outer-shim tracer dereference is needed (unlike
EPBL/kappa-shear). Call at the n_wavespeed cadence.
Host guards + dereference here; the explicit-shape do
concurrent kernel lives in wavespeed_compute_impl
(outer-shim + flat-impl pattern — mirrors varmix_compute).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(ocean_wave_speed_t), | intent(inout) | :: | this | |||
| type(multilayer_state_t), | intent(in) | :: | ms |
Copy a pre-filled cell-centre Coriolis magnitude |f| (1/s) onto
the slot (mirror of ocean_meke_set_f_centre — the caller
builds f_centre via fill_coriolis_centre /
metrics_fill_coriolis, which handles beta-plane AND
planetary/spherical), and fill the static beta_centre =
|grad f| field with the SAME centred-difference stencil
meke_length_scales uses (edge rows/columns left at 0 -> the
extratropical Rd = cg1/|f| branch there).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_wave_speed_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| real(kind=wp), | intent(in) | :: | f_centre(grid%nx_total,grid%ny_total) |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_wave_speed_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_wave_speed_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_wave_speed_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_wave_speed_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_wave_speed_t), | intent(inout) | :: | this |
Allocate the persistent (nx, ny) fields. Always allocates
(configure runs after init, so enable is not known yet);
the off-state footprint is four 2D arrays.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_wave_speed_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
Flat-impl wavespeed kernel (explicit-shape; NVHPC
descriptor-walk-free). Per-column Sturm-Liouville solve
(wavespeed_cg1_column) + the deformation-radius blend
(wavespeed_rd), then the metres-denominated resolution ratio
rd_over_dx = rd / dxT.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | rho0 | |||
| real(kind=wp), | intent(in) | :: | h_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | rho_layer(nx,ny,nz) | |||
| real(kind=wp), | intent(in) | :: | wet_mask(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | f_centre(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | beta_centre(nx,ny) | |||
| real(kind=wp), | intent(in) | :: | dxT(nx,ny) | |||
| real(kind=wp), | intent(out) | :: | cg1(nx,ny) | |||
| real(kind=wp), | intent(out) | :: | rd(nx,ny) | |||
| real(kind=wp), | intent(out) | :: | rd_over_dx(nx,ny) |