Windowed, greppable per-field statistics printed at the split-RK2 phase seams, so (a) two runs can be diffed log-to-log to find the FIRST diverging operator, and (b) a non-finite value is attributed to the phase that MINTED it, not the phase that noticed it (the nan-catch in the truncation / BT fold names the messenger only).
Row format (fixed-width, grep “CHKSUM”):
CHKSUM
bits is a decomposition-INVARIANT POPCNT reduction (int64 sum of
the population count of each element’s IEEE-754 bit pattern) —
identical across rank counts / loop orders, so a serial log diffs
against a decomposed run and the first mismatching bits names the
diverging operator. sum/min/max stay per-rank.
All reductions run device-side (!$acc parallel loop reduction,
inert on host builds) — no D->H field copies, so a death-window
sample cadence is affordable on GPU. NaN semantics: min/max
reductions are NaN-blind (comparisons with NaN are FALSE), so a
contaminated field can print plausible min/max — nonfin is the
authoritative corruption signal; sum goes NaN with the field.
Gated by &ocean_debug_nml chksum with an optional
[chksum_start_step, chksum_end_step] outer-step window (mirrors
debug_ke_attr). Default off => bit-identical (untaken branches).
Single-rank semantics: sums are per-rank (no halo reduction);
multi-rank runs print one row set per rank.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | public, | parameter | :: | LOC_H | = | 1 |
Tracer / thickness cell centre — extents |
| integer, | public, | parameter | :: | LOC_Q | = | 4 |
Vorticity / corner point — extents |
| integer, | public, | parameter | :: | LOC_U | = | 2 |
Arakawa-C u-face (west/east) — extents |
| integer, | public, | parameter | :: | LOC_V | = | 3 |
Arakawa-C v-face (south/north) — extents |
Grid-location-aware checksum: derives the array extents from
grid + loc (no hand-written bounds at the call site), runs
the device-side reductions, and emits one CHKSUM row. Resolves
by rank — 3D field trio / 2D BT-work variant.
Location-aware 3D checksum: derives (nx, ny) from grid + loc
and nz from the array, so a new instrumentation site is one
line with no hand-written bounds. Gated by the probe window.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | arr(:,:,:) | |||
| character(len=*), | intent(in) | :: | label | |||
| character(len=*), | intent(in) | :: | field | |||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | step | |||
| type(chksum_probe_t), | intent(inout) | :: | probe | |||
| integer, | intent(in) | :: | loc |
2D twin of rdb_debug_chksum_3d (BT-work fields).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | arr(:,:) | |||
| character(len=*), | intent(in) | :: | label | |||
| character(len=*), | intent(in) | :: | field | |||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | step | |||
| type(chksum_probe_t), | intent(inout) | :: | probe | |||
| integer, | intent(in) | :: | loc |
Config + one-shot header state. Lives on ocean_dyn_t;
host-only (never device-mapped).
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| logical, | public | :: | enable | = | .false. |
Master gate — |
|
| integer, | public | :: | end_step | = | 0 |
Last outer step to sample (0 = no upper bound). |
|
| logical, | public | :: | header_done | = | .false. |
Column-header row emitted. |
|
| logical, | public | :: | interior | = | .false. |
Restrict every reduction to PHYSICAL cells (exclude the whole
ghost ring). Default |
|
| integer, | public | :: | start_step | = | 0 |
First outer step to sample (0 = from the start). |
One field’s reduction bundle.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer(kind=int64), | public | :: | bits | = | 0_int64 |
Decomposition-invariant bitcount: the wrapped int64 sum of
POPCNT over the IEEE-754 bit pattern of every reduced element.
Unlike the FP |
|
| real(kind=wp), | public | :: | maxv | = | 0.0_wp |
NaN-blind extrema (see module docstring). |
|
| real(kind=wp), | public | :: | minv | = | 0.0_wp | ||
| integer, | public | :: | nonfin | = | 0 |
Count of non-finite entries — the corruption signal. |
|
| real(kind=wp), | public | :: | total | = | 0.0_wp |
Plain (non-compensated) sum — bitwise-stable per build, so log-diffable between two runs of the SAME binary; NaN when the field is contaminated. |
Gate: enabled AND inside the step window.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(chksum_probe_t), | intent(in) | :: | probe | |||
| integer, | intent(in) | :: | step |
Interior argmax of |arr|: first-encountered strict maximum over
i ∈ [i0, i1], j ∈ [j0, j1], all k (the ghost ring is excluded
by the caller’s bounds). Host-side (debug-window cadence only).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | arr(n1,n2,n3) | |||
| integer, | intent(in) | :: | n1 | |||
| integer, | intent(in) | :: | n2 | |||
| integer, | intent(in) | :: | n3 | |||
| integer, | intent(in) | :: | i0 | |||
| integer, | intent(in) | :: | i1 | |||
| integer, | intent(in) | :: | j0 | |||
| integer, | intent(in) | :: | j1 | |||
| integer, | intent(out) | :: | im | |||
| integer, | intent(out) | :: | jm | |||
| integer, | intent(out) | :: | km | |||
| real(kind=wp), | intent(out) | :: | amax |
Sample the BT substep’s 2D in/out fields at the fold seam:
the fold delta is bt_ubt_end - ubt_at_n - dt*F_bt_u, so these
four (+ eta) name which INPUT went non-finite when the fold’s
loud count fires — the “what fed it” the nan-catch cannot see.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(barotropic_workstate_t), | intent(in) | :: | bt_work | |||
| type(chksum_probe_t), | intent(inout) | :: | probe | |||
| character(len=*), | intent(in) | :: | label | |||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | step |
Hot-face anatomy at a phase seam: interior argmax |u| and |v|
with the local thickness pair (donor/receiver cells), the
per-face viscous remnant, and the column context (thickness of
the layer below/above at the max face). The forensic question
this answers: WHICH face takes the explicit dt·F kick, is it an
outcrop edge (massive|vanished thickness pair), and is visc_rem
actually small there (i.e. would MOM6’s attenuation have caught
it)? Row format (grep “HOTFACE”):
HOTFACE
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(multilayer_state_t), | intent(inout) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | visc_rem_u(:,:,:) | |||
| real(kind=wp), | intent(in) | :: | visc_rem_v(:,:,:) | |||
| type(chksum_probe_t), | intent(inout) | :: | probe | |||
| character(len=*), | intent(in) | :: | label | |||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | step |
Map a grid-location tag (LOC_{H,U,V,Q}) to the field’s 2D
extents on the Arakawa-C grid — u/v faces carry the extra
wall-normal row/column, the corner both. This is the single
place the C-grid extent convention lives; call sites pass loc.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | loc | |||
| integer, | intent(out) | :: | nx | |||
| integer, | intent(out) | :: | ny |
Sample the prognostics (h, u, v, every tracer) at a phase seam. Call
AFTER the phase named by label; drains device queues first so
the async apply chain has landed. Bounds come from the
location-aware API (LOC_H / LOC_U / LOC_V), not hand-written.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(multilayer_state_t), | intent(in) | :: | ms | |||
| type(chksum_probe_t), | intent(inout) | :: | probe | |||
| character(len=*), | intent(in) | :: | label | |||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | step |
2D twin of chksum_stats_3d (BT work fields).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | arr(nx,ny) | |||
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| type(chksum_stats_t), | intent(out) | :: | stats | |||
| integer, | intent(in), | optional | :: | i0 |
Optional index window (default: the whole array) — see the 3D twin. |
|
| integer, | intent(in), | optional | :: | i1 |
Optional index window (default: the whole array) — see the 3D twin. |
|
| integer, | intent(in), | optional | :: | j0 |
Optional index window (default: the whole array) — see the 3D twin. |
|
| integer, | intent(in), | optional | :: | j1 |
Optional index window (default: the whole array) — see the 3D twin. |
Device-side sum/min/max/nonfinite over an explicit-shape 3D
field. No present clause: present_or_copyin reads the device
copy in production and copies-in host data in unmapped unit
tests (same convention as the BT fold’s loud count).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | arr(nx,ny,nz) | |||
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny | |||
| integer, | intent(in) | :: | nz | |||
| type(chksum_stats_t), | intent(out) | :: | stats | |||
| integer, | intent(in), | optional | :: | i0 |
Optional index window (default: the whole array). Used by the
probe’s |
|
| integer, | intent(in), | optional | :: | i1 |
Optional index window (default: the whole array). Used by the
probe’s |
|
| integer, | intent(in), | optional | :: | j0 |
Optional index window (default: the whole array). Used by the
probe’s |
|
| integer, | intent(in), | optional | :: | j1 |
Optional index window (default: the whole array). Used by the
probe’s |
Physical-cell index range for a grid-location tag: the ghost
ring excluded. Face locations carry one MORE physical entry
than cell centres in their staggered direction (an x-face array
spans nx_phys + 1 faces), which is why LOC_U/LOC_Q extend
i1 by one and LOC_V/LOC_Q extend j1.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | loc | |||
| integer, | intent(out) | :: | i0 | |||
| integer, | intent(out) | :: | i1 | |||
| integer, | intent(out) | :: | j0 | |||
| integer, | intent(out) | :: | j1 |
Emit one CHKSUM row (write(*,…) like the KE_ATTR probe — probe output bypasses the logger by design: greppable, no prefix, survives logger-level filtering).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(chksum_probe_t), | intent(inout) | :: | probe | |||
| character(len=*), | intent(in) | :: | label | |||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | step | |||
| character(len=*), | intent(in) | :: | field | |||
| type(chksum_stats_t), | intent(in) | :: | stats |
One HOTFACE row (see chksum_hotface docstring for columns).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | label | |||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | step | |||
| character(len=*), | intent(in) | :: | comp | |||
| integer, | intent(in) | :: | i | |||
| integer, | intent(in) | :: | j | |||
| integer, | intent(in) | :: | k | |||
| real(kind=wp), | intent(in) | :: | val | |||
| real(kind=wp), | intent(in) | :: | h_left | |||
| real(kind=wp), | intent(in) | :: | h_right | |||
| real(kind=wp), | intent(in) | :: | rem | |||
| real(kind=wp), | intent(in) | :: | h_dn | |||
| real(kind=wp), | intent(in) | :: | h_up |
2D twin of rdb_debug_chksum_3d (BT-work fields).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | arr(:,:) | |||
| character(len=*), | intent(in) | :: | label | |||
| character(len=*), | intent(in) | :: | field | |||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | step | |||
| type(chksum_probe_t), | intent(inout) | :: | probe | |||
| integer, | intent(in) | :: | loc |
Location-aware 3D checksum: derives (nx, ny) from grid + loc
and nz from the array, so a new instrumentation site is one
line with no hand-written bounds. Gated by the probe window.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | arr(:,:,:) | |||
| character(len=*), | intent(in) | :: | label | |||
| character(len=*), | intent(in) | :: | field | |||
| integer, | intent(in) | :: | stage | |||
| integer, | intent(in) | :: | step | |||
| type(chksum_probe_t), | intent(inout) | :: | probe | |||
| integer, | intent(in) | :: | loc |