rdb_ocean_tides Module

Equilibrium (astronomical) body-force tidal forcing state for the ocean dyn-core (capability C1). Fills a GPU-resident equilibrium tide elevation eta_eq(x,y) from a small set of harmonic constituents; the barotropic momentum solve then drives -g grad(eta - eta_forcing) (pure surface body force), where eta_forcing = eta_eq + eta_sal folds in the scalar self-attraction & loading (C2) surface elevation eta_sal = beta_sal*eta (Ray 1998; Accad & Pekeris 1978). With eta_sal = beta*eta the surface term becomes the effective-gravity -g(1-beta) grad(eta); beta is lagged one outer step (uses the stage-start barotropic eta). SAL is opt-in (use_sal, default off) — off ⇒ eta_forcing == eta_eq, bit-identical to C1. MOM6 divergence (intentional): MOM6 scalar SAL scales the whole (eta - eta_eq) by (1-beta) (its dgeo_de), damping the body tide by beta too; we apply the Accad-Pekeris load eta_sal = beta*eta to the ocean surface only (body tide at full strength). Both are valid scalar approximations; they differ by g*beta*grad(eta_eq) (~9% of the tidal forcing at beta=0.09). Internal-tide drag (C4) and OBC-tide reconciliation (C3) remain out of scope; the dead use_itd/ itd_coeff/itd_global_scale scaffolding for C4 was removed (PR-8) — PR-29 (barotropic linear wave drag) lands its own lwd_drag_u/v map on a different type instead.

Per-outer-step update decomposes the sum-over-constituents into a host-side scalar update (amp_cos, amp_sin; nconst cos/sin calls) times a precomputed device-resident spatial structure (cos_struct, sin_struct, built once at init from lat/lon), so the device kernel does NO per-cell trigonometry and NO reduction — 2 mul + 1 add per constituent per cell.


Uses

  • module~~rdb_ocean_tides~~UsesGraph module~rdb_ocean_tides rdb_ocean_tides iso_fortran_env iso_fortran_env module~rdb_ocean_tides->iso_fortran_env module~rdb_constants rdb_constants module~rdb_ocean_tides->module~rdb_constants module~rdb_grid rdb_grid module~rdb_ocean_tides->module~rdb_grid module~rdb_mem_report rdb_mem_report module~rdb_ocean_tides->module~rdb_mem_report module~rdb_ocean_tide_astro rdb_ocean_tide_astro module~rdb_ocean_tides->module~rdb_ocean_tide_astro 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_ocean_tide_astro->iso_fortran_env module~rdb_ocean_tide_astro->module~rdb_constants

Used by

  • module~~rdb_ocean_tides~~UsedByGraph module~rdb_ocean_tides rdb_ocean_tides module~rdb_ocean_dyn rdb_ocean_dyn module~rdb_ocean_dyn->module~rdb_ocean_tides module~rdb_ocean_setup rdb_ocean_setup module~rdb_ocean_setup->module~rdb_ocean_tides 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_tides 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_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 :: TIDES_NCONST_DEFAULT = 8

Standard constituents: M2 S2 N2 K2 K1 O1 P1 Q1.


Derived Types

type, public ::  ocean_tides_t

Components

Type Visibility Attributes Name Initial
real(kind=wp), public, allocatable :: amp_c(:)

(nconst) equilibrium amplitudes A (m).

real(kind=wp), public, allocatable :: amp_cos(:)

(nconst) per-step scratch Alovefcos(omeganow+V+u).

real(kind=wp), public, allocatable :: amp_sin(:)

(nconst) per-step scratch Alovef*sin(…).

real(kind=wp), public :: beta_sal = 0.0_wp

Scalar SAL factor beta (~0.085-0.12; C2).

real(kind=wp), public, allocatable :: cos_struct(:,:,:)

(nx,ny,3) cos-part spatial structure per species slice.

logical, public :: enable = .false.

Master switch (default off => bit-identical).

real(kind=wp), public, allocatable :: eta_eq(:,:)

(nx,ny) equilibrium tide elevation (m) at cell centres.

real(kind=wp), public, allocatable :: eta_forcing(:,:)

(nx,ny) combined seam field eta_eq + eta_sal — the surface elevation the barotropic PGF drives -g grad(eta - .) against.

real(kind=wp), public, allocatable :: eta_sal(:,:)

(nx,ny) scalar-SAL elevation (m); beta_sal*eta (C2).

real(kind=wp), public, allocatable :: f_nodal(:)

(nconst) nodal amplitude factor (fixed at nodal_ref_date).

logical, public :: is_init = .false.

True between init and destroy (tracks GPU attachment too).

real(kind=wp), public, allocatable :: love_c(:)

(nconst) Love-number factors.

integer, public :: nconst = 0

Number of active harmonic constituents.

real(kind=wp), public, allocatable :: omega_c(:)

(nconst) angular frequencies (rad/s).

real(kind=wp), public, allocatable :: phase0(:)

(nconst) equilibrium argument V_c at ref_date (rad).

real(kind=wp), public, allocatable :: sin_struct(:,:,:)

(nx,ny,3) sin-part spatial structure per species slice.

integer, public, allocatable :: species_c(:)

(nconst) structure-slice index 1/2/3 (diurnal/semidi/long-per).

real(kind=wp), public :: t_epoch = 0.0_wp

Seconds from ref_date to the model’s t=0 (v1: 0).

real(kind=wp), public, allocatable :: u_nodal(:)

(nconst) nodal phase (rad).

logical, public :: use_sal = .false.

Apply scalar self-attraction & loading (C2).

Type-Bound Procedures

procedure, public, non_overridable :: bytes => ocean_tides_bytes
procedure, public, non_overridable :: destroy => ocean_tides_destroy
procedure, public, non_overridable :: enter_data => ocean_tides_enter_data
procedure, public, non_overridable :: exit_data => ocean_tides_exit_data
procedure, public, non_overridable :: init => ocean_tides_init

Functions

private pure function ocean_tides_bytes(this) result(nbytes)

Counted allocatable footprint of the tides 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_tides_t), intent(in) :: this

Return Value integer(kind=int64)


Subroutines

public subroutine tides_build_struct(this, geolat, geolon, nx, ny)

Build the (nx,ny,3) cos/sin spatial-structure arrays from cell- centre latitude/longitude (degrees), via the angle-sum fold cos(theta + nlambda) = cos(theta)cos(nlambda) - sin(theta)sin(n*lambda). Plain host loop over all cells incl. ghosts (before enter_data). slice 1 diurnal (n=1): G1 = sin(2 phi) slice 2 semidiurnal(n=2): G2 = cos^2 phi slice 3 long-period(n=0): G0 = 1/2 - 3/2 sin^2 phi

Arguments

Type IntentOptional Attributes Name
class(ocean_tides_t), intent(inout) :: this
real(kind=wp), intent(in) :: geolat(nx,ny)
real(kind=wp), intent(in) :: geolon(nx,ny)
integer, intent(in) :: nx
integer, intent(in) :: ny

public subroutine tides_configure_astronomy(this, cat_idx, nconst, dref, dnodal, add_nodal, nx, ny)

Allocate the active-constituent arrays + 2D fields and fill the catalog copies + astronomy (phase0, nodal f/u) at the reference and nodal reference day numbers. Host-side setup (before enter_data). cat_idx(1:nconst) are catalog indices (1..TIDES_CATALOG_SIZE).

Arguments

Type IntentOptional Attributes Name
class(ocean_tides_t), intent(inout) :: this
integer, intent(in) :: cat_idx(nconst)
integer, intent(in) :: nconst
real(kind=wp), intent(in) :: dref
real(kind=wp), intent(in) :: dnodal
logical, intent(in) :: add_nodal
integer, intent(in) :: nx
integer, intent(in) :: ny

public subroutine tides_update_eta_eq(this, t)

Refresh eta_eq(x,y) for the current outer-step time t (s). Host recomputes the nconst amplitude scalars, pushes them to the device, then a do concurrent fills eta_eq with no per-cell trig and no reduction. Held static across the inner barotropic substep loop.

Arguments

Type IntentOptional Attributes Name
type(ocean_tides_t), intent(inout) :: this
real(kind=wp), intent(in) :: t

public subroutine tides_update_eta_sal(this, eta_current)

Refresh the combined seam field eta_forcing for the current outer step. Scalar self-attraction & loading (C2): when use_sal, eta_sal = beta_sal*eta_current and eta_forcing = eta_eq + eta_sal; otherwise eta_forcing = eta_eq (bit-identical to C1). eta_current is the lagged (stage-start, previous outer step) barotropic surface elevation. Host does no work; the fill is a single explicit-shape do concurrent. Must be called AFTER tides_update_eta_eq (reads the fresh eta_eq).

Arguments

Type IntentOptional Attributes Name
type(ocean_tides_t), intent(inout) :: this
real(kind=wp), intent(in) :: eta_current(:,:)

private subroutine ocean_tides_destroy(this)

Arguments

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

private subroutine ocean_tides_enter_data(this)

Attach the device-resident tide arrays. Only when enabled. select-type -> non-poly _impl (AMD libomptarget class-box rule).

Arguments

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

private subroutine ocean_tides_enter_data_impl(this)

Arguments

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

private subroutine ocean_tides_exit_data(this)

Arguments

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

private subroutine ocean_tides_exit_data_impl(this)

Arguments

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

private subroutine ocean_tides_init(this, grid)

Minimal init — the real allocation + astronomy fill happens in tides_configure_astronomy / tides_build_struct once the namelist + metrics are available (host, before enter_data).

Arguments

Type IntentOptional Attributes Name
class(ocean_tides_t), intent(inout) :: this
type(hgrid_t), intent(in) :: grid

private subroutine tides_update_eta_eq_impl(nx, ny, nconst, species_c, amp_cos, amp_sin, cos_struct, sin_struct, eta_eq)

Flat-impl device fill (explicit-shape dummies — no descriptor walk). eta_eq(i,j) = sum_c amp_cos(c)cos_struct(i,j,m) + amp_sin(c)sin_struct(i,j,m), m = species_c(c). Contiguous index (i) innermost.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx
integer, intent(in) :: ny
integer, intent(in) :: nconst
integer, intent(in) :: species_c(nconst)
real(kind=wp), intent(in) :: amp_cos(nconst)
real(kind=wp), intent(in) :: amp_sin(nconst)
real(kind=wp), intent(in) :: cos_struct(nx,ny,3)
real(kind=wp), intent(in) :: sin_struct(nx,ny,3)
real(kind=wp), intent(out) :: eta_eq(nx,ny)

private subroutine tides_update_eta_sal_impl(nx, ny, use_sal, beta_sal, eta_current, eta_eq, eta_sal, eta_forcing)

Flat-impl device fill (explicit-shape dummies). Loop-invariant use_sal branch kept INSIDE the single do concurrent (one launch, uniform branch is ~free). Off ⇒ pure copy of eta_eq into eta_forcing ⇒ bit-identical. Contiguous index (i) innermost.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx
integer, intent(in) :: ny
logical, intent(in) :: use_sal
real(kind=wp), intent(in) :: beta_sal
real(kind=wp), intent(in) :: eta_current(nx,ny)
real(kind=wp), intent(in) :: eta_eq(nx,ny)
real(kind=wp), intent(inout) :: eta_sal(nx,ny)
real(kind=wp), intent(out) :: eta_forcing(nx,ny)