rdb_massless Module

Pure column helpers that merge vanished (sub-H_VANISHED) layers into a “massive” grid (nzc <= nz) so the column solver never divides by a vanished thickness: thickness-weighted means onto the merged grid, plus the inverse interpolation of an interface quantity back to the original interfaces. Reference: Jackson, Hallberg & Legg (2008), JPO 38, 1033.

ORDERING (load-bearing): LOCAL SURFACE-DOWN indices — local k=1 = surface, k=nz = bed; interfaces K=1 (surface) … K=nz+1 (bed). The consumer does the global(bed-up) <-> local(surface-down) flip; the helper never sees global indices.

MERGE DIRECTION (do not invent a symmetric rule): walking surface-down, a merged layer opens only when the current cluster already has mass AND the incoming layer is massive (> h_min). So a vanished layer folds into the preceding (surfaceward) massive layer; a leading surface run folds into the first massive layer beneath; a trailing bed run folds into the last massive layer above.

GPU NOTE: !$acc routine seq, callable cross-module from the kappa-shear do concurrent column kernel. NVHPC will NOT inline across the module boundary, but these run once per column per compute (thermo cadence), so the divergence cost is acceptable. All arrays are fixed-size NZ_STACK_MAX(+1) explicit-shape locals (no descriptor walk, no alloc).


Uses

  • module~~rdb_massless~~UsesGraph module~rdb_massless rdb_massless module~rdb_constants rdb_constants module~rdb_massless->module~rdb_constants pic_types pic_types module~rdb_constants->pic_types

Used by

  • module~~rdb_massless~~UsedByGraph module~rdb_massless rdb_massless module~rdb_ocean_kappa_shear rdb_ocean_kappa_shear module~rdb_ocean_kappa_shear->module~rdb_massless module~rdb_ocean_dyn rdb_ocean_dyn module~rdb_ocean_dyn->module~rdb_ocean_kappa_shear module~rdb_ocean_state rdb_ocean_state module~rdb_ocean_state->module~rdb_ocean_kappa_shear module~rdb_ocean_state->module~rdb_ocean_dyn 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_state module~rdb_ocean_engine->module~rdb_ocean_diag_derived module~rdb_ocean_engine->module~rdb_ocean_diag_fills module~rdb_ocean_setup rdb_ocean_setup module~rdb_ocean_engine->module~rdb_ocean_setup module~rdb_ocean_setup->module~rdb_ocean_dyn module~rdb_ocean_setup->module~rdb_ocean_state

Variables

Type Visibility Attributes Name Initial
integer, private, parameter :: NZL = NZ_STACK_MAX

Layer-array dimension (must match the consumer’s NZL).

integer, private, parameter :: NZLI = NZ_STACK_MAX+1

Interface-array dimension (= NZL + 1).


Subroutines

public pure subroutine massless_build_maps(h, nz, h_min, nzc, hc, kc, kf)

Build the merged massive-layer grid and the maps kc, kf. kc(k) (k=1..nz) = merged-layer index original layer k folds into; kc(nz+1) = nzc+1 is the bed sentinel. kf(K) = fractional position of original interface K inside merged layer kc(K) (0 = coincides with a merged interface -> pure lookup; (0,1) = interior -> linear blend in massless_interp_back). Identity case (no layer < h_min): nzc==nz, kc(k)==k, kf(k)==0, hc==h bit-for-bit.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: h(NZL)

Local surface-down layer thicknesses (m), >= 0.

integer, intent(in) :: nz
real(kind=wp), intent(in) :: h_min

Merge threshold (H_VANISHED).

integer, intent(out) :: nzc

Number of merged massive layers (<= nz).

real(kind=wp), intent(out) :: hc(NZL)

Merged thicknesses (m), valid 1..nzc.

integer, intent(out) :: kc(NZLI)

Layer/interface -> merged index, valid 1..nz+1 (sentinel at nz+1).

real(kind=wp), intent(out) :: kf(NZLI)

Fractional interface weight, valid 1..nz+1.

public pure subroutine massless_interp_back(qc, kc, kf, nz, q)

Inverse map: interpolate an interface quantity qc(1:nzc+1) on the merged grid back to the original nz+1 interfaces. kf==0 takes a pure lookup; interior interfaces take the linear blend between merged interfaces kc(K) and kc(K)+1 (in range since kf>0 only when kc(K) < nzc+1). Identity case: kf==0 everywhere -> q==qc.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: qc(NZLI)

Interface quantity on the merged grid (valid 1..nzc+1).

integer, intent(in) :: kc(NZLI)
real(kind=wp), intent(in) :: kf(NZLI)
integer, intent(in) :: nz
real(kind=wp), intent(out) :: q(NZLI)

Interface quantity on the original grid (filled 1..nz+1).

public pure subroutine massless_merge_fields(h, kc, nz, nzc, u, v, t, s, uc, vc, tc, sc)

Thickness-weighted merged means for u, v, T, S — the solver receives MEANS, not integrals, and must not re-divide. Accumulation runs in the same surface-down k order as massless_build_maps so the column-integral conservation holds to round-off.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: h(NZL)
integer, intent(in) :: kc(NZLI)
integer, intent(in) :: nz
integer, intent(in) :: nzc
real(kind=wp), intent(in) :: u(NZL)
real(kind=wp), intent(in) :: v(NZL)
real(kind=wp), intent(in) :: t(NZL)
real(kind=wp), intent(in) :: s(NZL)
real(kind=wp), intent(out) :: uc(NZL)
real(kind=wp), intent(out) :: vc(NZL)
real(kind=wp), intent(out) :: tc(NZL)
real(kind=wp), intent(out) :: sc(NZL)