rdb_ocean_budgets Module

Globally-integrated conservation scalars (total mass, KE, salt, heat) plus a per-kernel contributor registry, used to check a kernel’s per-cell budget accumulator against the actual state change (LHS = current_total − values_init vs RHS = Σ contributors%total_integrated). No production caller by design (PR-8): this module has no ocean_state_t slot — a consumer constructs a local type(ocean_budgets_t) (seven of Roundabout’s ocean conservation tests already do this; see tests/test_ocean_surface_flux.F90 for the idiom). It is single-rank with no MPI reduction; a production run’s global conservation report is rdb_ocean_console_stats.F90: ocean_console_stats_report, which does allreduce correctly. init_snapshot(state) captures values_init; evaluate(state) recomputes values.


Uses

  • module~~rdb_ocean_budgets~~UsesGraph module~rdb_ocean_budgets rdb_ocean_budgets iso_fortran_env iso_fortran_env module~rdb_ocean_budgets->iso_fortran_env module~rdb_constants rdb_constants module~rdb_ocean_budgets->module~rdb_constants module~rdb_grid rdb_grid module~rdb_ocean_budgets->module~rdb_grid module~rdb_mem_report rdb_mem_report module~rdb_ocean_budgets->module~rdb_mem_report module~rdb_multilayer_state rdb_multilayer_state module~rdb_ocean_budgets->module~rdb_multilayer_state module~rdb_ocean_diag_mask rdb_ocean_diag_mask module~rdb_ocean_budgets->module~rdb_ocean_diag_mask 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_multilayer_state->iso_fortran_env module~rdb_multilayer_state->module~rdb_constants module~rdb_multilayer_state->module~rdb_grid module~rdb_multilayer_state->module~rdb_mem_report module~rdb_efp rdb_efp module~rdb_multilayer_state->module~rdb_efp module~rdb_error_ring rdb_error_ring module~rdb_multilayer_state->module~rdb_error_ring module~rdb_tracer rdb_tracer module~rdb_multilayer_state->module~rdb_tracer module~rdb_multilayer_state->pic_logger module~rdb_ocean_diag_mask->iso_fortran_env module~rdb_ocean_diag_mask->module~rdb_constants module~rdb_ocean_diag_mask->module~rdb_grid module~rdb_ocean_diag_mask->module~rdb_mem_report module~rdb_efp->iso_fortran_env ieee_arithmetic ieee_arithmetic module~rdb_efp->ieee_arithmetic module~rdb_error_ring->pic_logger module~rdb_tracer->iso_fortran_env module~rdb_tracer->module~rdb_constants module~rdb_tracer->module~rdb_grid module~rdb_tracer->module~rdb_mem_report

Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: BUDGET_HEAT_TOTAL = 4
integer, public, parameter :: BUDGET_KE = 2

kinetic energy

integer, public, parameter :: BUDGET_MASS = 1
integer, public, parameter :: BUDGET_N_DEFAULT = 4
integer, public, parameter :: BUDGET_SALT_TOTAL = 3
character(len=12), private, parameter :: BUDGET_NAMES(BUDGET_N_DEFAULT) = ["mass        ", "KE          ", "salt_total  ", "heat_total  "]
integer, private, parameter :: INITIAL_CONTRIBUTOR_CAPACITY = 16

Derived Types

type, public ::  budget_contributor_t

One source/sink of a conserved quantity, populated by a physics kernel each step (adds dt·delta into per_cell) and drained at eval cadence (drain_contributors integrates per_cell·mask·dA over k into total_integrated, then zeroes per_cell). total_integrated is the cumulative RHS checked against LHS = current_total − values_init.

Components

Type Visibility Attributes Name Initial
logical, public :: device_resident = .false.

True when per_cell lives on the GPU (mapped via OpenACC by the owning kernel); drain_contributors then acc update self before integrating and acc update device after zeroing. Default false = host-only kernels / synthetic tests.

logical, public :: is_active = .false.
character(len=64), public :: name = ""

Identifier — “continuity”, “vert_diff_heat”, “surface_heat_flux”, …

real(kind=wp), public, pointer :: per_cell(:,:,:) => null()

Kernel-owned per-step accumulator; manager holds a non-owning pointer (kernel guarantees the array outlives registration).

integer, public :: quantity = 0

Tag from BUDGET_* (MASS / SALT_TOTAL / HEAT_TOTAL / …).

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

Cumulative spatial integral of contributions drained so far this run. Sign convention: positive = source.

type, public ::  ocean_budgets_t

Components

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

Per-cell T-area (m²) copied from the metrics slot via set_area. Physical integrals weight by mask%weight·areaT; falls back to grid%dx·grid%dy until set.

type(budget_contributor_t), public, allocatable :: contributors(:)
type(hgrid_t), public :: grid
logical, public :: has_snapshot = .false.

True once init_snapshot has populated values_init.

logical, public :: is_init = .false.
type(diag_mask_t), public, allocatable :: mask

Optional region mask. Default = whole interior (built lazily); reset via set_mask.

integer, public :: n_contributors = 0
integer, public :: n_contributors_max = 0
integer, public :: nbudgets = BUDGET_N_DEFAULT
real(kind=wp), public :: values(BUDGET_N_DEFAULT) = 0.0_wp
real(kind=wp), public :: values_init(BUDGET_N_DEFAULT) = 0.0_wp

Type-Bound Procedures

procedure, public, non_overridable :: bytes => ocean_budgets_bytes
procedure, public, non_overridable :: destroy => ocean_budgets_destroy
procedure, public, non_overridable :: drain_contributors => ocean_budgets_drain_contributors
procedure, public, non_overridable :: evaluate => ocean_budgets_evaluate
procedure, public, non_overridable :: init => ocean_budgets_init
procedure, public, non_overridable :: init_snapshot => ocean_budgets_init_snapshot
procedure, public, non_overridable :: register_contributor => ocean_budgets_register_contributor
procedure, public, non_overridable :: set_area => ocean_budgets_set_area
procedure, public, non_overridable :: set_mask => ocean_budgets_set_mask

Functions

public pure function budget_total_ke(ms, mask, areaT) result(total)

Total KE: Σ over masked interior of 0.5·h·(u²+v²)·areaT·weight, u/v averaged from C-grid faces to centres. Public only for tests.

Arguments

Type IntentOptional Attributes Name
type(multilayer_state_t), intent(in) :: ms
type(diag_mask_t), intent(in) :: mask
real(kind=wp), intent(in) :: areaT(:,:)

Return Value real(kind=wp)

public pure function budget_total_mass(ms, mask, areaT) result(total)

Total mass: Σ over masked interior of h_layer·areaT·weight over k. Units: m³. Public only for the unit-test suite.

Arguments

Type IntentOptional Attributes Name
type(multilayer_state_t), intent(in) :: ms
type(diag_mask_t), intent(in) :: mask
real(kind=wp), intent(in) :: areaT(:,:)

Return Value real(kind=wp)

public pure function budget_total_tracer(ms, it, mask, areaT) result(total)

Total tracer content: Σ over masked interior of hTr·areaT·weight over k. hTr is thickness-weighted, so this is ∫(tracer·volume), the conserved quantity. Public only for the unit-test suite.

Arguments

Type IntentOptional Attributes Name
type(multilayer_state_t), intent(in) :: ms
integer, intent(in) :: it
type(diag_mask_t), intent(in) :: mask
real(kind=wp), intent(in) :: areaT(:,:)

Return Value real(kind=wp)

private pure function ocean_budgets_bytes(this) result(nbytes)

Counted allocatable footprint of the conservation budgets (own accumulator; registry contributors are counted by their owning slot) slot (0 when unallocated).

Arguments

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

Return Value integer(kind=int64)


Subroutines

private subroutine budget_area_field(this, areaT)

Per-cell T-area (m²) for physical integrals: cached metrics areaT once set_area has run, else uniform grid%dx·grid%dy.

Arguments

Type IntentOptional Attributes Name
type(ocean_budgets_t), intent(in) :: this
real(kind=wp), intent(out), allocatable :: areaT(:,:)

private subroutine ocean_budgets_destroy(this)

Arguments

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

private subroutine ocean_budgets_drain_contributors(this)

For each contributor: integrate per_cell·mask·areaT (over k) into total_integrated, then zero per_cell for the next window.

Arguments

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

private subroutine ocean_budgets_evaluate(this, ms)

Recompute this%values(:) from the current multilayer state. Honours this%mask — sums are weighted by mask%weight · areaT.

Arguments

Type IntentOptional Attributes Name
class(ocean_budgets_t), intent(inout) :: this
type(multilayer_state_t), intent(in) :: ms

private subroutine ocean_budgets_init(this, grid)

Arguments

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

private subroutine ocean_budgets_init_snapshot(this, ms)

Snapshot values_init from the current state. Call once after the IC is set + the EOS has run, before stepping.

Arguments

Type IntentOptional Attributes Name
class(ocean_budgets_t), intent(inout) :: this
type(multilayer_state_t), intent(in) :: ms

private subroutine ocean_budgets_register_contributor(this, name, quantity, per_cell, device_resident)

Register a per-kernel contributor: store a non-owning pointer to the kernel-owned per_cell + metadata. Set device_resident when per_cell is GPU-mapped (drain syncs it). Idempotent on name (re-registering updates the pointer, resets the integral).

Arguments

Type IntentOptional Attributes Name
class(ocean_budgets_t), intent(inout) :: this
character(len=*), intent(in) :: name
integer, intent(in) :: quantity
real(kind=wp), intent(in), target :: per_cell(:,:,:)
logical, intent(in), optional :: device_resident

private subroutine ocean_budgets_set_area(this, areaT)

Cache the per-cell T-area (m²) from the metrics slot. After this, physical integrals weight by mask%weight·areaT; before it they fall back to grid%dx·grid%dy (= areaT on uniform Cartesian).

Arguments

Type IntentOptional Attributes Name
class(ocean_budgets_t), intent(inout) :: this
real(kind=wp), intent(in) :: areaT(:,:)

private subroutine ocean_budgets_set_mask(this, mask)

Override the default global mask. Useful for regional conservation diagnostics — “mass north of 30°S stays at FP.”

Arguments

Type IntentOptional Attributes Name
class(ocean_budgets_t), intent(inout) :: this
type(diag_mask_t), intent(in) :: mask