ocean_sponge_t Derived Type

type, public :: ocean_sponge_t

Map-driven sponge state: per-cell Idamp [1/s] + a 3-D reference state. See the module docstring for the physics + the MOM6 divergences. Value-semantics slot (no CS pointer, no associated(CS) guards) per src/core/ocean/README.md.


Inherited by

type~~ocean_sponge_t~~InheritedByGraph type~ocean_sponge_t ocean_sponge_t type~ocean_state_t ocean_state_t type~ocean_state_t->type~ocean_sponge_t sponge type~ocean_engine_t ocean_engine_t type~ocean_engine_t->type~ocean_state_t state type~ocean_handle_t ocean_handle_t type~ocean_handle_t->type~ocean_state_t state type~ocean_handle_t->type~ocean_engine_t engine

Components

Type Visibility Attributes Name Initial
character(len=16), public :: damp_source = "band"

How idamp_h/idamp_u/idamp_v are filled. "band" (only value implemented in v1): cosine ramp from every bc%<edge>%bc_type == OBC_SPONGE edge tag, summed at overlaps (§3.2 of the plan). "file" recognised but aborts at validate_config (PR-23b, needs the PR-14 reader).

logical, public :: enable = .false.

Master switch. Default .false. ⇒ the legacy band kernels run unchanged ⇒ existing nmls + tests are bit-identical.

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

Inverse damping time for tracers + (deferred) thickness, 1/s, shape (nx_total, ny_total). Zero outside the sponge and in every ghost cell — Idamp = 0 IS the sponge mask (no separate width/extent bookkeeping).

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

Inverse damping time for u_face_x_layer, 1/s, shape (nx_total+1, ny_total) (matches the u-face stagger).

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

Inverse damping time for v_face_y_layer, 1/s, shape (nx_total, ny_total+1) (matches the v-face stagger).

integer, public :: idx_s = 0

Tracer-registry index of salinity; see idx_t.

integer, public :: idx_t = 0

Tracer-registry index of temperature, latched at configure so the per-step refresh needs no registry walk (and no array-of-derived-types device indirection). 0 = not registered ⇒ the temperature refresh is skipped.

logical, public :: is_init = .false.

True once init has run (only called when enable, mirroring the gated-closure convention — epbl/kshear/… — so a disabled sponge never allocates the (potentially large) ref_tracer).

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

target_source="linear_z": dS/dz (PSU/m), z positive UP.

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

target_source="linear_z": dT/dz (degC/m), z positive UP.

real(kind=wp), public :: lin_s_ref = 35.0_wp

target_source="linear_z": S (PSU) at the z = 0 datum.

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

target_source="linear_z": T (degC) at the z = 0 datum.

integer, public :: n_tracers = 0

Registered tracer count — sizes ref_tracer’s 4th dimension.

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

Reference tracer CONCENTRATION (not hTr) — PSU, degC, … per the registered tracer’s own units — shape (nx_total, ny_total, nz, n_tracers), indexed by the multilayer tracer-registry index (matches ms%idx_salinity / ms%idx_temperature).

logical, public :: relax_h = .false.

Interior-interface thickness damping. NOT IMPLEMENTED in PR-23 v1 (deferred to PR-23b alongside the file-backed targets — docs/plans/PLAN_PR23_real_sponge.md §14 Q1); enable=.true., relax_h=.true. aborts fail-loud at validate_config.

logical, public :: relax_tracers = .true.

Relax every registered tracer’s concentration toward ref_tracer.

logical, public :: relax_uv = .true.

Relax u_face_x_layer/v_face_y_layer toward u_ref/v_ref. Default .true. matches the legacy path (momentum is the one thing today’s sponge always damps); MOM6’s SPONGE_UV defaults .false. — a deliberate divergence to preserve legacy parity.

character(len=16), public :: target_source = "ic"

Reference-state source. "ic": ocean_sponge_snapshot_reference copies the seeded initial condition. "linear_z": the analytic affine geopotential profile below, re-evaluated on the LIVE layer geometry by ocean_sponge_refresh_target once per outer step — see that routine’s docstring for why re-evaluated rather than frozen. "file" recognised but aborts at validate_config (PR-23b).

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

Reference x-velocity, shape (nx_total+1, ny_total, nz) — matches ms%u_face_x_layer.

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

Reference y-velocity, shape (nx_total, ny_total+1, nz) — matches ms%v_face_y_layer.

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

Geopotential DEPTH of the top of the water column (m, positive down), shape (nx_total, ny_total). 0 in the open ocean (the free-surface datum), metrics%z_draft(i,j) under an ice shelf. Latched ONCE at configure — the draft is static by design — so the per-step linear_z refresh is self-contained and the sponge slot never has to reach into ocean_metrics_t. Same role z_top plays in rdb_ocean_z_init::build_z_ctr; without it a geopotential target would land z_draft metres too shallow on every shelf column and tilt with the ice base.


Type-Bound Procedures

procedure, public, non_overridable :: bytes => ocean_sponge_bytes

  • private pure function ocean_sponge_bytes(this) result(nbytes)

    Counted allocatable footprint (0 when enable=.false. — every array is unallocated then). tools/check_bytes_accounting.py reconciles this against the measured device mapping.

    Arguments

    Type IntentOptional Attributes Name
    class(ocean_sponge_t), intent(in) :: this

    Return Value integer(kind=int64)

procedure, public, non_overridable :: destroy => ocean_sponge_destroy

procedure, public, non_overridable :: enter_data => ocean_sponge_enter_data

  • private subroutine ocean_sponge_enter_data(this)

    Type-bound wrapper — delegates to the non-polymorphic impl so the device-attach map base is the heap object, not a polymorphic stack box (AMD libomptarget cross-slot-overlap fix; copied verbatim from rdb_ocean_surface_flux.F90).

    Arguments

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

procedure, public, non_overridable :: exit_data => ocean_sponge_exit_data

procedure, public, non_overridable :: init => ocean_sponge_init

  • private subroutine ocean_sponge_init(this, grid, nz_ml, n_tracers)

    Allocate the maps + reference-state arrays. Call ONLY when this%enable (the gated-closure convention, mirroring epbl/kshear/…) — the caller sets enable before calling, and ocean_state_init only reaches this when this%enable is .true. (see rdb_ocean_state.F90). ref_tracer is sized at max(n_tracers, 1) so an as-yet-empty tracer registry never trips a zero-extent allocate.

    Arguments

    Type IntentOptional Attributes Name
    class(ocean_sponge_t), intent(inout) :: this
    type(hgrid_t), intent(in) :: grid
    integer, intent(in) :: nz_ml
    integer, intent(in) :: n_tracers

Source Code

   type :: ocean_sponge_t
      !! Map-driven sponge state: per-cell `Idamp` [1/s] + a 3-D reference
      !! state. See the module docstring for the physics + the MOM6
      !! divergences. Value-semantics slot (no `CS` pointer, no
      !! `associated(CS)` guards) per `src/core/ocean/README.md`.
      logical :: is_init = .false.
         !! True once `init` has run (only called when `enable`, mirroring
         !! the gated-closure convention — epbl/kshear/... — so a disabled
         !! sponge never allocates the (potentially large) `ref_tracer`).
      logical :: enable = .false.
         !! Master switch. Default `.false.` ⇒ the legacy band kernels run
         !! unchanged ⇒ existing nmls + tests are bit-identical.
      logical :: relax_uv = .true.
         !! Relax `u_face_x_layer`/`v_face_y_layer` toward `u_ref`/`v_ref`.
         !! Default `.true.` matches the legacy path (momentum is the one
         !! thing today's sponge always damps); MOM6's `SPONGE_UV` defaults
         !! `.false.` — a deliberate divergence to preserve legacy parity.
      logical :: relax_tracers = .true.
         !! Relax every registered tracer's concentration toward
         !! `ref_tracer`.
      logical :: relax_h = .false.
         !! Interior-interface thickness damping. NOT IMPLEMENTED in PR-23
         !! v1 (deferred to PR-23b alongside the file-backed targets —
         !! `docs/plans/PLAN_PR23_real_sponge.md` §14 Q1); `enable=.true.,
         !! relax_h=.true.` aborts fail-loud at `validate_config`.
      character(len=16) :: damp_source = "band"
         !! How `idamp_h`/`idamp_u`/`idamp_v` are filled. `"band"` (only
         !! value implemented in v1): cosine ramp from every
         !! `bc%<edge>%bc_type == OBC_SPONGE` edge tag, summed at overlaps
         !! (§3.2 of the plan). `"file"` recognised but aborts at
         !! `validate_config` (PR-23b, needs the PR-14 reader).
      character(len=16) :: target_source = "ic"
         !! Reference-state source. `"ic"`:
         !! `ocean_sponge_snapshot_reference` copies the seeded initial
         !! condition. `"linear_z"`: the analytic affine geopotential
         !! profile below, re-evaluated on the LIVE layer geometry by
         !! `ocean_sponge_refresh_target` once per outer step — see that
         !! routine's docstring for why re-evaluated rather than frozen.
         !! `"file"` recognised but aborts at `validate_config` (PR-23b).
      real(wp) :: lin_t_ref = 0.0_wp
         !! `target_source="linear_z"`: T (degC) at the `z = 0` datum.
      real(wp) :: lin_dt_dz = 0.0_wp
         !! `target_source="linear_z"`: dT/dz (degC/m), **z positive UP**.
      real(wp) :: lin_s_ref = 35.0_wp
         !! `target_source="linear_z"`: S (PSU) at the `z = 0` datum.
      real(wp) :: lin_ds_dz = 0.0_wp
         !! `target_source="linear_z"`: dS/dz (PSU/m), z positive UP.
      integer :: idx_t = 0
         !! Tracer-registry index of temperature, latched at configure so
         !! the per-step refresh needs no registry walk (and no
         !! array-of-derived-types device indirection). `0` = not
         !! registered ⇒ the temperature refresh is skipped.
      integer :: idx_s = 0
         !! Tracer-registry index of salinity; see `idx_t`.
      integer :: n_tracers = 0
         !! Registered tracer count — sizes `ref_tracer`'s 4th dimension.
      real(wp), allocatable :: idamp_h(:, :)
         !! Inverse damping time for tracers + (deferred) thickness, 1/s,
         !! shape `(nx_total, ny_total)`. Zero outside the sponge and in
         !! every ghost cell — `Idamp = 0` IS the sponge mask (no separate
         !! width/extent bookkeeping).
      real(wp), allocatable :: idamp_u(:, :)
         !! Inverse damping time for `u_face_x_layer`, 1/s, shape
         !! `(nx_total+1, ny_total)` (matches the u-face stagger).
      real(wp), allocatable :: idamp_v(:, :)
         !! Inverse damping time for `v_face_y_layer`, 1/s, shape
         !! `(nx_total, ny_total+1)` (matches the v-face stagger).
      real(wp), allocatable :: ref_tracer(:, :, :, :)
         !! Reference tracer CONCENTRATION (not `hTr`) — PSU, degC, ... per
         !! the registered tracer's own units — shape `(nx_total, ny_total,
         !! nz, n_tracers)`, indexed by the multilayer tracer-registry
         !! index (matches `ms%idx_salinity` / `ms%idx_temperature`).
      real(wp), allocatable :: u_ref(:, :, :)
         !! Reference x-velocity, shape `(nx_total+1, ny_total, nz)` —
         !! matches `ms%u_face_x_layer`.
      real(wp), allocatable :: v_ref(:, :, :)
         !! Reference y-velocity, shape `(nx_total, ny_total+1, nz)` —
         !! matches `ms%v_face_y_layer`.
      real(wp), allocatable :: z_top(:, :)
         !! Geopotential DEPTH of the top of the water column (m, positive
         !! down), shape `(nx_total, ny_total)`. `0` in the open ocean (the
         !! free-surface datum), `metrics%z_draft(i,j)` under an ice shelf.
         !! Latched ONCE at configure — the draft is static by design — so
         !! the per-step `linear_z` refresh is self-contained and the
         !! sponge slot never has to reach into `ocean_metrics_t`. Same
         !! role `z_top` plays in `rdb_ocean_z_init::build_z_ctr`; without
         !! it a geopotential target would land `z_draft` metres too
         !! shallow on every shelf column and tilt with the ice base.
   contains
      procedure, non_overridable :: init => ocean_sponge_init
      procedure, non_overridable :: destroy => ocean_sponge_destroy
      procedure, non_overridable :: enter_data => ocean_sponge_enter_data
      procedure, non_overridable :: exit_data => ocean_sponge_exit_data
      procedure, non_overridable :: bytes => ocean_sponge_bytes
   end type ocean_sponge_t