rdb_ocean_console_stats Module

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.


Uses

  • module~~rdb_ocean_console_stats~~UsesGraph module~rdb_ocean_console_stats rdb_ocean_console_stats ieee_arithmetic ieee_arithmetic module~rdb_ocean_console_stats->ieee_arithmetic iso_fortran_env iso_fortran_env module~rdb_ocean_console_stats->iso_fortran_env module~rdb_console_stats rdb_console_stats module~rdb_ocean_console_stats->module~rdb_console_stats module~rdb_constants rdb_constants module~rdb_ocean_console_stats->module~rdb_constants module~rdb_efp rdb_efp module~rdb_ocean_console_stats->module~rdb_efp module~rdb_grid rdb_grid module~rdb_ocean_console_stats->module~rdb_grid module~rdb_halo rdb_halo module~rdb_ocean_console_stats->module~rdb_halo module~rdb_ice_column rdb_ice_column module~rdb_ocean_console_stats->module~rdb_ice_column module~rdb_multilayer_state rdb_multilayer_state module~rdb_ocean_console_stats->module~rdb_multilayer_state module~rdb_ocean_halo_counters rdb_ocean_halo_counters module~rdb_ocean_console_stats->module~rdb_ocean_halo_counters module~rdb_ocean_metrics rdb_ocean_metrics module~rdb_ocean_console_stats->module~rdb_ocean_metrics pic_logger pic_logger module~rdb_ocean_console_stats->pic_logger pic_strings pic_strings module~rdb_ocean_console_stats->pic_strings module~rdb_console_stats->ieee_arithmetic module~rdb_console_stats->module~rdb_constants module~rdb_console_stats->module~rdb_efp module~rdb_console_stats->pic_logger module~rdb_console_stats->pic_strings pic_types pic_types module~rdb_constants->pic_types module~rdb_efp->ieee_arithmetic module~rdb_efp->iso_fortran_env module~rdb_grid->module~rdb_constants module~rdb_halo->iso_fortran_env module~rdb_halo->module~rdb_constants module~rdb_halo->module~rdb_efp module~rdb_halo->pic_logger module~rdb_comm_env rdb_comm_env module~rdb_halo->module~rdb_comm_env module~rdb_decomp rdb_decomp module~rdb_halo->module~rdb_decomp pic_mpi_lib pic_mpi_lib module~rdb_halo->pic_mpi_lib module~rdb_ice_column->module~rdb_constants module~rdb_ice_enthalpy rdb_ice_enthalpy module~rdb_ice_column->module~rdb_ice_enthalpy module~rdb_ice_mass rdb_ice_mass module~rdb_ice_column->module~rdb_ice_mass module~rdb_ice_optics rdb_ice_optics module~rdb_ice_column->module~rdb_ice_optics module~rdb_multilayer_state->iso_fortran_env module~rdb_multilayer_state->module~rdb_constants module~rdb_multilayer_state->module~rdb_efp module~rdb_multilayer_state->module~rdb_grid module~rdb_multilayer_state->pic_logger module~rdb_error_ring rdb_error_ring module~rdb_multilayer_state->module~rdb_error_ring module~rdb_mem_report rdb_mem_report module~rdb_multilayer_state->module~rdb_mem_report module~rdb_tracer rdb_tracer module~rdb_multilayer_state->module~rdb_tracer module~rdb_ocean_halo_counters->iso_fortran_env module~rdb_ocean_halo_counters->pic_strings module~rdb_ocean_metrics->iso_fortran_env module~rdb_ocean_metrics->module~rdb_constants module~rdb_ocean_metrics->module~rdb_grid module~rdb_ocean_metrics->pic_logger module~rdb_ocean_metrics->pic_strings module~rdb_ocean_metrics->module~rdb_error_ring module~rdb_io_netcdf rdb_io_netcdf module~rdb_ocean_metrics->module~rdb_io_netcdf module~rdb_ocean_metrics->module~rdb_mem_report module~rdb_ocean_bipolar rdb_ocean_bipolar module~rdb_ocean_metrics->module~rdb_ocean_bipolar module~rdb_ocean_fold rdb_ocean_fold module~rdb_ocean_metrics->module~rdb_ocean_fold module~rdb_ocean_status rdb_ocean_status module~rdb_ocean_metrics->module~rdb_ocean_status netcdf netcdf module~rdb_ocean_metrics->netcdf module~rdb_comm_env->iso_fortran_env module~rdb_comm_env->module~rdb_constants module~rdb_comm_env->pic_mpi_lib module~rdb_config rdb_config module~rdb_decomp->module~rdb_config module~rdb_error_ring->pic_logger module~rdb_ice_enthalpy->module~rdb_constants module~rdb_ice_mass->module~rdb_constants module~rdb_ice_mass->module~rdb_ice_enthalpy module~rdb_ice_optics->module~rdb_constants module~rdb_ice_optics->module~rdb_ice_enthalpy module~rdb_io_netcdf->iso_fortran_env module~rdb_io_netcdf->module~rdb_constants module~rdb_io_netcdf->pic_logger module~rdb_io_netcdf->pic_strings module~rdb_io_netcdf->module~rdb_error_ring module~rdb_io_netcdf->netcdf iso_c_binding iso_c_binding module~rdb_io_netcdf->iso_c_binding module~rdb_mem_report->iso_fortran_env module~rdb_mem_report->module~rdb_constants module~rdb_mem_report->pic_logger module~rdb_mem_report->pic_strings module~rdb_ocean_bipolar->module~rdb_constants module~rdb_ocean_fold->module~rdb_constants 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 module~rdb_config->module~rdb_constants module~rdb_config->pic_logger module~rdb_config->pic_strings module~rdb_config->module~rdb_error_ring module~rdb_config->module~rdb_ice_enthalpy module~rdb_config->module~rdb_ocean_status module~rdb_ice_init rdb_ice_init module~rdb_config->module~rdb_ice_init module~rdb_nml_schema rdb_nml_schema module~rdb_config->module~rdb_nml_schema pic_ascii pic_ascii module~rdb_config->pic_ascii module~rdb_ice_init->module~rdb_constants module~rdb_ice_init->module~rdb_grid module~rdb_ice_init->module~rdb_ice_column module~rdb_ice_init->module~rdb_multilayer_state module~rdb_ice_init->module~rdb_ocean_metrics module~rdb_ice_init->module~rdb_ice_enthalpy module~rdb_ice_state rdb_ice_state module~rdb_ice_init->module~rdb_ice_state module~rdb_nml_schema->module~rdb_constants module~rdb_nml_schema->pic_logger module~rdb_nml_schema->module~rdb_error_ring

Used by

  • module~~rdb_ocean_console_stats~~UsedByGraph module~rdb_ocean_console_stats rdb_ocean_console_stats module~rdb_driver rdb_driver module~rdb_driver->module~rdb_ocean_console_stats module~rdb_ocean_dyn rdb_ocean_dyn module~rdb_driver->module~rdb_ocean_dyn module~rdb_ocean_engine rdb_ocean_engine module~rdb_driver->module~rdb_ocean_engine module~rdb_ocean_state rdb_ocean_state module~rdb_driver->module~rdb_ocean_state module~rdb_ocean_dyn->module~rdb_ocean_console_stats module~rdb_ocean_api rdb_ocean_api module~rdb_ocean_api->module~rdb_ocean_dyn module~rdb_ocean_api->module~rdb_ocean_engine module~rdb_handle rdb_handle 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_engine->module~rdb_ocean_dyn module~rdb_ocean_setup rdb_ocean_setup 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 module~rdb_ocean_setup->module~rdb_ocean_dyn module~rdb_ocean_setup->module~rdb_ocean_state module~rdb_ocean_state->module~rdb_ocean_dyn module~rdb_handle->module~rdb_ocean_engine module~rdb_handle->module~rdb_ocean_state 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

Variables

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 ocean_budget_* helpers (and, via them, the unit tests) all read this constant, so a mutation here is caught by test_ocean_conservation_salt_heat. Note: the per-stage accumulate calls in rdb_solver.F90 and rdb_ocean_dyn.F90 pass the literal 0.5_wp stage weight directly; those sites are consistent by convention rather than by reference to this constant.


Functions

public pure function ocean_budget_is_active(tracer_idx, horiz_adv_budget_valid) result(active)

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.

Read more…

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: tracer_idx
logical, intent(in) :: horiz_adv_budget_valid

Return Value logical

public pure function ocean_budget_out(adv_sum, hdiff_sum, stage_weight) result(out)

Console out term for a conserved tracer: the boundary transport out of the domain, from the horizontal-advection + horizontal- diffusion budgets.

Read more…

Arguments

Type IntentOptional 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 ocean_budget_src. Absent ⇒ RK2_STAGE_WEIGHT (0.5).

Return Value real(kind=wp)

public pure function ocean_budget_src(source_sum, stage_weight) result(src)

Console src term for a conserved tracer: the surface (+ any other source, e.g. geothermal) contribution to the outer-step budget.

Read more…

Arguments

Type IntentOptional 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 ⇒ RK2_STAGE_WEIGHT (0.5), the historical SSP-RK2 value — so every existing caller is bit-identical. Supply ocean_budget_stage_weight(is_pc) rather than a literal: that function is the sole home of the mapping.

Return Value real(kind=wp)

public pure function ocean_budget_stage_weight(is_pc) result(w)

The per-outer-step weight that turns the salt/heat budget ACCUMULATORS into the state change they must account for.

Read more…

Arguments

Type IntentOptional Attributes Name
logical, intent(in) :: is_pc

Return Value real(kind=wp)

public pure function ocean_frazil_heat_src(frazil_sum) result(src)

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).

Read more…

Arguments

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

Return Value real(kind=wp)

public pure function ocean_heat_src_sum(surface_sum, geothermal_sum, sponge_sum) result(s)

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.

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: surface_sum
real(kind=wp), intent(in) :: geothermal_sum
real(kind=wp), intent(in) :: sponge_sum

Return Value real(kind=wp)

public pure function ocean_salt_src_sum(surface_sum, sponge_sum) result(s)

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..

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: surface_sum
real(kind=wp), intent(in) :: sponge_sum

Return Value real(kind=wp)

private pure function cfl_cell_value(u_l, u_r, v_l, v_r, idx, idy, dt) result(cfl)

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.

Arguments

Type IntentOptional 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

Return Value real(kind=wp)

private function compute_max_cfl(u_face, v_face, idxT, idyT, dt, nghost, h_layer, vanish_tol) result(max_cfl)

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).

Read more…

Arguments

Type IntentOptional 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 vanish_tol.

real(kind=wp), intent(in), optional :: vanish_tol

Cells with h_layer <= vanish_tol are excluded. Required together with h_layer.

Return Value real(kind=wp)

private function compute_total_h(h_layer, areaT, nghost) result(total)

Σ 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.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: h_layer(:,:,:)
real(kind=wp), intent(in) :: areaT(:,:)
integer, intent(in) :: nghost

Return Value real(kind=wp)

private function compute_total_h_efp(h_layer, areaT, nghost) result(total)

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.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: h_layer(:,:,:)
real(kind=wp), intent(in) :: areaT(:,:)
integer, intent(in) :: nghost

Return Value type(efp_t)

private function compute_total_ke(h_layer, u_face, v_face, areaT, nghost) result(total)

Σ 0.5·h·(u_c²+v_c²)·areaT over PHYSICAL cells (ghosts excluded), using cell-centred face averages. Direct OpenACC reduction.

Arguments

Type IntentOptional 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

Return Value real(kind=wp)

private function compute_total_ke_efp(h_layer, u_face, v_face, areaT, nghost) result(total)

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.

Arguments

Type IntentOptional 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

Return Value type(efp_t)

private function compute_total_tracer(hTr, areaT, nghost) result(total)

Σ hTr(i,j,k)·areaT(i,j) over PHYSICAL cells (ghosts excluded). Same explicit-reduction pattern as compute_total_h.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: hTr(:,:,:)
real(kind=wp), intent(in) :: areaT(:,:)
integer, intent(in) :: nghost

Return Value real(kind=wp)

private function compute_total_tracer_efp(hTr, areaT, nghost) result(total)

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.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: hTr(:,:,:)
real(kind=wp), intent(in) :: areaT(:,:)
integer, intent(in) :: nghost

Return Value type(efp_t)


Subroutines

public pure subroutine efp_decompose_impl(r, e1, e2, e3, e4, e5, e6, epoison)

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.

Read more…

Arguments

Type IntentOptional 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

public subroutine ocean_console_stats_report(this, grid, metrics, ms, t, dt, step, horiz_adv_budget_valid, cfl_vanish_tol, heat_budget_frazil, ice_part_size, ice_m_ice, ice_ncat, compute_rank, reproducing_sums, budget_stage_weight, budget_out)

Compute current totals + means + max-CFL and emit a MOM6-style console block via the shared console_stats_report formatter.

Read more…

Arguments

Type IntentOptional 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 .false. the horizontal-advection accumulator is incomplete (windowed path); revert to raw drift for salt/heat.

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 (ocean_sea_ice_t% heat_budget_frazil, K·m per cell) — folded into heat_src at FULL weight (ocean_frazil_heat_src) so the closed heat budget still closes with ice on. Absent (ice off — the driver passes the slot’s unallocated array, which an optional dummy sees as absent) ⇒ bit-identical.

real(kind=wp), intent(in), optional :: ice_part_size(:,:,0:)

Sea-ice category area fractions (ocean_sea_ice_t%part_size, category 0 = open water). Absent (ice off — the driver passes the slot’s unallocated array, seen as absent) ⇒ no ice line ⇒ bit-identical. Lower bound 0 declared so category indexing matches the state array.

real(kind=wp), intent(in), optional :: ice_m_ice(:,:,:)

Sea-ice mass per category (two-mode convention, rdb_ice_state).

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

raw_salt/raw_age/ice-area reductions and their cross-rank combine through the order-invariant EFP path (rdb_efp + halo_allreduce_efp_list, ONE collective) instead of the FP !$acc parallel loop reduction(+:acc) kernels + SEVEN separate halo_allreduce_sum calls. Absent / .false. (default) ⇒ the FP path below runs VERBATIM — byte-identical console output. The salt/heat closed-budget out/src terms (section (d) below) take the EFP path too (one extra collective per active budget), so every printed number is independent of the rank count; the primary totals feeding the Error residual also get the efp_real_diff treatment. The cumulative mass_out is accumulated per step in EFP bins too (mass_out_efp_on, set from this knob); the cavity-only mass_src stays an FP running sum (single-rank path).

real(kind=wp), intent(in), optional :: budget_stage_weight

Per-outer-step weight for the salt/heat budget accumulators, from ocean_budget_stage_weight(is_pc). Absent ⇒ the historical SSP-RK2 0.5 ⇒ bit-identical. MUST be 1.0 under &ocean_bt_nml split_scheme="pred_corr", whose single prognostic tracer update fills the accumulators once per step rather than twice; without it the reported src/out are exactly half and the closed-budget residual reads ~5e-4 instead of ~1e-13.

type(conservation_budget_t), intent(out), optional :: budget_out

Hands the computed closed-budget totals (mass_out/salt_out/ heat_out/*_src/*_active, section (d) below) back to the caller instead of only formatting them into the printed console line. Absent ⇒ inert (no behaviour change; existing callers are untouched). Consumer: tests/mpi/test_ocean_decomp_bitid_mpi, which asserts these are bit-identical across every px x py factorisation of each case (compare_budget), and, on the periodic_sponge case, against the serial reference too (check_periodic_sponge_serial_out) — the EFP reproducing_sums path (default on) makes the boundary out terms order-invariant across rank counts, exactly like the totals.

private subroutine compute_ice_totals(wet_T, areaT, part_size, m_ice, ncat, nghost, wet_area, ci_area, hi_area)

Σ 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.

Arguments

Type IntentOptional 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

private subroutine compute_ice_totals_efp(wet_T, areaT, part_size, m_ice, ncat, nghost, wet_area_efp, ci_area_efp, hi_area_efp)

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.

Read more…

Arguments

Type IntentOptional 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

private subroutine efp_summands_guard(nx, ny, name)

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”).

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx
integer, intent(in) :: ny
character(len=*), intent(in) :: name