Periodic conservation + stability scalars printed to stdout at the
driver’s status_interval cadence (separate from the diag manager’s
NetCDF). Mirrors MOM6’s “MOM Day N:” status line:
Total mass — Σ h·areaT·ρ_0 (kg)Total KE — Σ 0.5·h·(u_c²+v_c²)·areaT·ρ_0 (J)Mean salinity — Σ hS·areaT / Σ h·areaT (PSU)Mean temp — Σ hT·areaT / Σ h·areaT (°C)Max CFL — max (|u_c|·dt·idxT + |v_c|·dt·idyT)Reductions run on device. Tracer sums go through a flat-impl helper
to dodge the registry deep deref (ms%tracers(idx)%hTr — NVHPC
can’t follow inside an inlined reduction kernel). Initial values
captured on the first call; later calls report relative drift.
Re-exported from rdb_console_stats so the driver keeps a single
import for the ocean path; the reference-snapshot state + the line
format now live in the shared module (coastal uses the same).
Production export, not a test hook: rdb_ocean_dyn accumulates the
console mass out in EFP bins with it inside a device kernel, so
it must not sit under RDB_ENABLE_TESTING.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private, | parameter | :: | RK2_STAGE_WEIGHT | = | 0.5_wp |
RK2 stage weight: all per-cell budget accumulators (surface,
geothermal, hdiff, horiz_adv) store the raw SUM over both RK2
stages; the outer-step state change from each process is
0.5·(that sum) because rk2_average halves. The reporter and
the |
Whether a tracer’s closed budget (out/src residual) should be
reported. .true. iff the tracer is registered (tracer_idx > 0)
AND the horizontal-advection accumulator is complete AND no
un-instrumented interior source is active.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | tracer_idx | |||
| logical, | intent(in) | :: | horiz_adv_budget_valid |
Console out term for a conserved tracer: the boundary transport
out of the domain, from the horizontal-advection + horizontal-
diffusion budgets.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | adv_sum | |||
| real(kind=wp), | intent(in) | :: | hdiff_sum | |||
| real(kind=wp), | intent(in), | optional | :: | stage_weight |
See |
Console src term for a conserved tracer: the surface (+ any other
source, e.g. geothermal) contribution to the outer-step budget.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | source_sum | |||
| real(kind=wp), | intent(in), | optional | :: | stage_weight |
Per-outer-step weight that converts the accumulator’s raw sum
into the state change it must match. Absent ⇒ |
The per-outer-step weight that turns the salt/heat budget ACCUMULATORS into the state change they must account for.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| logical, | intent(in) | :: | is_pc |
Console src term for the sea-ice frazil clamp (PR 1): the heat
the clamp ADDS to the ocean warming the supercooled surface layer
up to T_f (the matching deficit is banked on ice%frazil_heat).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | frazil_sum |
Assemble the total HEAT source integral (pre-weight, pre-ρ) that
feeds ocean_budget_src: surface flux + geothermal bottom flux +
(PR-23) the map-driven sponge’s tracer-relaxation source.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | surface_sum | |||
| real(kind=wp), | intent(in) | :: | geothermal_sum | |||
| real(kind=wp), | intent(in) | :: | sponge_sum |
Assemble the total SALT source integral (pre-weight, pre-ρ) that
feeds ocean_budget_src: surface flux + (PR-23) the map-driven
sponge’s tracer-relaxation source. Mirror of ocean_heat_src_sum
without the geothermal term (salt has no geothermal analogue).
sponge_sum is ms%salt_budget_sponge’s area-weighted reduction —
zero unless &ocean_sponge_nml enable=.true., relax_tracers=.true..
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | surface_sum | |||
| real(kind=wp), | intent(in) | :: | sponge_sum |
Per-cell advective CFL from the C-grid face-velocity pairs and metric
inverses: cfl = (|u_c|·idx + |v_c|·idy)·dt, with u_c/v_c the
face averages. !$acc routine seq so it inlines into the reduction
loops below — same module ⇒ NVHPC keeps it inlined (and it’s a
status-cadence cold path regardless). Sole home of the CFL formula,
shared by the gated + un-gated compute_max_cfl loops.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | u_l | |||
| real(kind=wp), | intent(in) | :: | u_r | |||
| real(kind=wp), | intent(in) | :: | v_l | |||
| real(kind=wp), | intent(in) | :: | v_r | |||
| real(kind=wp), | intent(in) | :: | idx | |||
| real(kind=wp), | intent(in) | :: | idy | |||
| real(kind=wp), | intent(in) | :: | dt |
max (|u_c|·dt·idxT + |v_c|·dt·idyT) over PHYSICAL cells (ghosts excluded). idxT/idyT are metric inverses (= 1/dx,1/dy on uniform).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | u_face(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | v_face(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | idxT(:,:) | |||
| real(kind=wp), | intent(in) | :: | idyT(:,:) | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| integer, | intent(in) | :: | nghost | |||
| real(kind=wp), | intent(in), | optional | :: | h_layer(:,:,:) |
Centre-cell thickness (m). Required together with |
|
| real(kind=wp), | intent(in), | optional | :: | vanish_tol |
Cells with h_layer <= vanish_tol are excluded. Required
together with |
Σ h_layer(i,j,k)·areaT(i,j) over PHYSICAL cells (ghosts
excluded). Explicit OpenACC reduction — the sum() intrinsic on
a present-mapped array silently runs host-side under NVHPC
non-managed mode and returns the stale host shadow.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | h_layer(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | areaT(:,:) | |||
| integer, | intent(in) | :: | nghost |
EFP twin of compute_total_h: order-invariant fixed-point
Sigma h_layer*areaT over PHYSICAL cells. K-SLAB BLOCKED: a host
loop over k, one device reduction(+:e1..e6) per slab, then a
host-side efp_carry combining the slab into the running total
– keeps each device reduction block within EFP_MAX_SUMMANDS
(SS3.3/SS6.3 of the plan; MOM6’s i/j block-partition arithmetic is
NOT ported – the k-slab is simpler and sufficient at
EFP_PREC_WIDTH = 36). Ghost exclusion + extent clamping copied
VERBATIM from compute_total_h – a divergence here would
silently change what is summed between the FP and EFP paths.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | h_layer(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | areaT(:,:) | |||
| integer, | intent(in) | :: | nghost |
Σ 0.5·h·(u_c²+v_c²)·areaT over PHYSICAL cells (ghosts excluded), using cell-centred face averages. Direct OpenACC reduction.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | h_layer(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | u_face(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | v_face(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | areaT(:,:) | |||
| integer, | intent(in) | :: | nghost |
EFP twin of compute_total_ke. See compute_total_h_efp for the
k-slab blocking design; face-averaging + extent clamping copied
verbatim from compute_total_ke.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | h_layer(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | u_face(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | v_face(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | areaT(:,:) | |||
| integer, | intent(in) | :: | nghost |
Σ hTr(i,j,k)·areaT(i,j) over PHYSICAL cells (ghosts excluded).
Same explicit-reduction pattern as compute_total_h.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | hTr(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | areaT(:,:) | |||
| integer, | intent(in) | :: | nghost |
EFP twin of compute_total_tracer. See compute_total_h_efp
for the k-slab blocking design; ghost exclusion + extent clamping
copied verbatim from compute_total_tracer.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | hTr(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | areaT(:,:) | |||
| integer, | intent(in) | :: | nghost |
In-module !$acc routine seq duplicate of rdb_efp::efp_decompose
– six SCALAR bin outputs (not an int64(6) array) so the call
sites below can accumulate directly into
reduction(+:e1..e6,epoison) clauses (OpenACC has no portable
array reduction). Duplicated rather than called from rdb_efp
because NVHPC’s device codegen does not inline a
pure !$acc routine seq helper across a module boundary (CLAUDE.md
Gotchas); test_efp_impl_matches_canonical (RDB_ENABLE_TESTING-
gated) pins this copy bin-for-bit against the canonical procedure
over the same magnitude table – compute_ice_totals’s docstring
documents the identical pattern for ice_cell_concentration_impl.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=real64), | intent(in) | :: | r | |||
| integer(kind=int64), | intent(out) | :: | e1 | |||
| integer(kind=int64), | intent(out) | :: | e2 | |||
| integer(kind=int64), | intent(out) | :: | e3 | |||
| integer(kind=int64), | intent(out) | :: | e4 | |||
| integer(kind=int64), | intent(out) | :: | e5 | |||
| integer(kind=int64), | intent(out) | :: | e6 | |||
| integer(kind=int64), | intent(out) | :: | epoison |
Compute current totals + means + max-CFL and emit a MOM6-style
console block via the shared console_stats_report formatter.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(console_stats_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| type(multilayer_state_t), | intent(in) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | t | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| integer, | intent(in) | :: | step | |||
| logical, | intent(in), | optional | :: | horiz_adv_budget_valid |
When |
|
| real(kind=wp), | intent(in), | optional | :: | cfl_vanish_tol |
When present: vanish-gated MaxCFL (Phase 3). Absent ⇒ un-gated. |
|
| real(kind=wp), | intent(in), | optional | :: | heat_budget_frazil(:,:,:) |
Sea-ice frazil heat-budget accumulator ( |
|
| real(kind=wp), | intent(in), | optional | :: | ice_part_size(:,:,0:) |
Sea-ice category area fractions ( |
|
| real(kind=wp), | intent(in), | optional | :: | ice_m_ice(:,:,:) |
Sea-ice mass per category (two-mode convention, |
|
| integer, | intent(in), | optional | :: | ice_ncat |
Category count (selects the lumped vs ITD gather mode). |
|
| integer, | intent(in) | :: | compute_rank |
Caller’s compute-communicator rank (0 = print, others silent). |
||
| logical, | intent(in), | optional | :: | reproducing_sums |
|
|
| real(kind=wp), | intent(in), | optional | :: | budget_stage_weight |
Per-outer-step weight for the salt/heat budget accumulators, from
|
|
| type(conservation_budget_t), | intent(out), | optional | :: | budget_out |
Hands the computed closed-budget totals ( |
Σ wet_T·areaT, Σ ci·areaT and Σ (mice/ICE_RHO_ICE)·areaT over
PHYSICAL cells (ghosts excluded) — ci/mice from the two-mode
per-cell gather (ice_cell_concentration_impl convention,
inlined; test_ocean_ice_diags pins the fills’ copy of the same
math). One pass, three reduction(+:) accumulators.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | wet_T(:,:) | |||
| real(kind=wp), | intent(in) | :: | areaT(:,:) | |||
| real(kind=wp), | intent(in) | :: | part_size(:,:,0:) | |||
| real(kind=wp), | intent(in) | :: | m_ice(:,:,:) | |||
| integer, | intent(in) | :: | ncat | |||
| integer, | intent(in) | :: | nghost | |||
| real(kind=wp), | intent(out) | :: | wet_area | |||
| real(kind=wp), | intent(out) | :: | ci_area | |||
| real(kind=wp), | intent(out) | :: | hi_area |
EFP twin of compute_ice_totals. 2D-only (no k-slab blocking
needed – one “slab” per accumulator), so a single
efp_summands_guard call suffices. THREE SEPARATE single-pass
reductions (one per accumulator, 7 reduction scalars each)
rather than one kernel combining all 21 – ice diagnostics are a
status-cadence cold path (SS11.11: “the EFP path costs ~nz times
more kernel launches… unmeasurable at status cadence”), so the
extra category-sum pass for ci/hi is free.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | wet_T(:,:) | |||
| real(kind=wp), | intent(in) | :: | areaT(:,:) | |||
| real(kind=wp), | intent(in) | :: | part_size(:,:,0:) | |||
| real(kind=wp), | intent(in) | :: | m_ice(:,:,:) | |||
| integer, | intent(in) | :: | ncat | |||
| integer, | intent(in) | :: | nghost | |||
| type(efp_t), | intent(out) | :: | wet_area_efp | |||
| type(efp_t), | intent(out) | :: | ci_area_efp | |||
| type(efp_t), | intent(out) | :: | hi_area_efp |
Fail-loud (never silent) guard: a k-slab’s physical cell count
must not exceed EFP_MAX_SUMMANDS, else a bin could overflow
int64 before the next efp_carry. 1.34e8 is an 11500^2
single-rank layer – unreachable today, but the check costs one
comparison at status cadence (CLAUDE.md: an unchecked bound “is a
silent-corruption path exactly like the NZ_STACK_MAX one”).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| character(len=*), | intent(in) | :: | name |