| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public | :: | dt_last_eval | = | 0.0_wp |
Wall time at last evaluation pass (s). |
|
| procedure(diag_emit_proc), | public, | pointer, nopass | :: | emit_post_fire | => | null() |
Optional post-fire hook the manager calls after the log
line. |
| logical, | public | :: | enabled | = | .true. |
Master switch. Phase 6 reads from namelist. |
|
| type(hgrid_t), | public | :: | grid |
Cached grid (scalar-only struct, cheap to copy). Derived
diagnostic fills read |
|||
| logical, | public | :: | is_init | = | .false. |
True between |
|
| integer, | public | :: | n_rho_out | = | 0 | ||
| integer, | public | :: | n_sigma_out | = | 0 | ||
| integer, | public | :: | n_zstar_out | = | 0 | ||
| type(ocean_diag_nc_stream_t), | public | :: | nc_stream | ||||
| integer, | public | :: | nvars | = | 0 |
Live count of registered diagnostics. |
|
| integer, | public | :: | nvars_max | = | 0 |
Capacity of |
|
| integer, | public | :: | nz_out | = | 0 | ||
| logical, | public | :: | on_device | = | .false. |
|
|
| real(kind=wp), | public, | allocatable | :: | rho_out(:) |
Output isopycnal bin edges (kg/m^3). |
||
| real(kind=wp), | public, | allocatable | :: | send_buf(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | sigma_out(:) |
Output sigma levels: cumulative fractions (0..1, shallow->deep). |
||
| type(diag_var_t), | public, | allocatable | :: | vars(:) | |||
| real(kind=wp), | public, | allocatable | :: | z_out(:) |
Output z-levels (m, positive up; surface at index nz_out). |
||
| real(kind=wp), | public, | allocatable | :: | zstar_out(:) |
Output z* reference interface depths (m, positive-down; deepest = reference total depth H_ref). Per-column grid stretched by col_h / H_ref (SSH-tracking). |
Counted allocatable footprint of the diagnostics slot: the flat
remap-level arrays, the host NetCDF staging buffer, AND the
per-variable registry buffers (0 when unallocated). One
arr_bytes term per array — add a term here when a new allocatable
joins the type; new diag_var_t buffers go in diag_var_bytes.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(in) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(inout) | :: | this |
Turn OFF the registered diagnostic name so the dispatcher skips
it entirely (no fill, no fold, no emit). Fail-loud if name
matches no registered var — a typo must not silently leave a
diagnostic running. Lists the registered names on abort.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(inout) | :: | this | |||
| character(len=*), | intent(in) | :: | name |
Attach each registered var’s per-buffer allocatables to the device.
Called by ocean_state_enter_data after register_default_diags
has populated vars(:) — buffers are sized at register time, so
the descriptors here are valid.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(inout) | :: | this |
Detach in reverse order of enter_data. Idempotency-safe via
is_init gate — repeated calls without intervening enter_data
become no-ops once the manager is destroyed.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(inout) | :: | this |
Allocate an empty registry sized at INITIAL_CAPACITY slots.
Subsequent register calls grow the array via doubling.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
.true. iff a diagnostic named name is registered (enabled or
not). Registration state only — says nothing about whether it
will actually fire (see enabled); a disabled diagnostic is
still registered and this returns .true. for it.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(in) | :: | this | |||
| character(len=*), | intent(in) | :: | name |
Register a new diagnostic variable. Grows the registry via
capacity doubling on overflow. Buffer allocation depends on
output_vgrid:
* LAYER (default): one output_buffer(n1, n2, n3) —
fill writes directly into it.
* Z_FIXED (or any non-LAYER target): two buffers —
layer_buffer(n1, n2, n3) for the fill, plus
output_buffer(n1, n2, this%nz_out) for the remapped
result. Caller must have configured nz_out via
set_output_z_levels first, and bind a remap proc.
Caller binds fill to a routine that knows how to populate
the layer-native buffer from the state handle.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(inout) | :: | this | |||
| character(len=*), | intent(in) | :: | name | |||
| character(len=*), | intent(in) | :: | units | |||
| procedure(diag_fill_proc) | :: | fill | ||||
| integer, | intent(in) | :: | n1 | |||
| integer, | intent(in) | :: | n2 | |||
| integer, | intent(in) | :: | n3 | |||
| character(len=*), | intent(in), | optional | :: | long_name | ||
| character(len=*), | intent(in), | optional | :: | standard_name | ||
| integer, | intent(in), | optional | :: | time_op | ||
| real(kind=wp), | intent(in), | optional | :: | dt_out | ||
| integer, | intent(in), | optional | :: | output_vgrid | ||
| procedure(diag_remap_proc), | optional | :: | remap | |||
| type(diag_mask_t), | intent(in), | optional | :: | mask | ||
| logical, | intent(in), | optional | :: | is_extensive | ||
| logical, | intent(in), | optional | :: | has_missing |
Configure the isopycnal (DENSITY) output grid — monotone-increasing
target potential densities (kg/m³). Stored copy; must be called
BEFORE any register with output_vgrid == DIAG_VGRID_DENSITY so
the manager knows the output buffer shape (one cell per target).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(inout) | :: | this | |||
| real(kind=wp), | intent(in) | :: | rho(:) | |||
| integer, | intent(out), | optional | :: | ierr |
Configure the terrain-following (SIGMA) output grid — cumulative
sigma fractions (0..1, monotone shallow->deep). Stored copy; must
be called BEFORE any register with output_vgrid ==
DIAG_VGRID_SIGMA so the manager knows the output buffer shape.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(inout) | :: | this | |||
| real(kind=wp), | intent(in) | :: | sigma(:) | |||
| integer, | intent(out), | optional | :: | ierr |
Configure the fixed-z output grid. Stored copy; the original
z array is not retained. Must be called BEFORE any
register with output_vgrid == DIAG_VGRID_Z_FIXED so the
manager knows the output buffer shape.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(inout) | :: | this | |||
| real(kind=wp), | intent(in) | :: | z(:) | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero ( |
Configure the SSH-tracking (ZSTAR) output grid — reference interface
depths (m, positive-down, monotone shallow->deep; deepest = H_ref).
Stored copy; must be called BEFORE any register with
output_vgrid == DIAG_VGRID_ZSTAR so the manager knows the buffer
shape.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(inout) | :: | this | |||
| real(kind=wp), | intent(in) | :: | zstar(:) | |||
| integer, | intent(out), | optional | :: | ierr |
Advance every registered variable. Behaviour by time_op:
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_diag_t), | intent(inout) | :: | this | |||
| class(*), | intent(in) | :: | state_handle | |||
| real(kind=wp), | intent(in) | :: | dt | |||
| real(kind=wp), | intent(in) | :: | t |
type :: ocean_diag_t logical :: is_init = .false. !! True between `init` and `destroy`. Prefer this to !! `allocated(...)` — tracks GPU device attachment too. logical :: on_device = .false. !! `.true.` between `enter_data` and `exit_data`. The emit-time !! statistics reduction reads `output_buffer` where it actually !! lives: on the device via `do concurrent ... reduce` when mapped, !! on the host otherwise (unit tests that skip `enter_data`). A !! device read of an unmapped buffer under `-gpu=mem:separate` !! would return garbage silently, so this is not optional. ! ---- Registry ---- integer :: nvars = 0 !! Live count of registered diagnostics. integer :: nvars_max = 0 !! Capacity of `vars(:)`. Grown via reallocation on !! `register` overflow. type(diag_var_t), allocatable :: vars(:) ! ---- Output vertical grids ---- ! Configured at init from the namelist. The manager looks up ! `vars(i)%output_vgrid` and dispatches the remap onto the ! matching array. Phase 6 wires the remap kernels. integer :: nz_out = 0 real(wp), allocatable :: z_out(:) !! Output z-levels (m, positive up; surface at index nz_out). integer :: n_rho_out = 0 real(wp), allocatable :: rho_out(:) !! Output isopycnal bin edges (kg/m^3). integer :: n_sigma_out = 0 real(wp), allocatable :: sigma_out(:) !! Output sigma levels: cumulative fractions (0..1, shallow->deep). integer :: n_zstar_out = 0 real(wp), allocatable :: zstar_out(:) !! Output z* reference interface depths (m, positive-down; deepest = !! reference total depth H_ref). Per-column grid stretched by !! col_h / H_ref (SSH-tracking). ! ---- I/O-server send buffer ---- ! Pre-allocated, reused across diag pushes. Sized to the ! largest registered variable's `output_buffer`. Sending uses ! a zero-copy `c_loc` view into this buffer. real(wp), allocatable :: send_buf(:, :, :) ! ---- Triggering scalars ---- logical :: enabled = .true. !! Master switch. Phase 6 reads from namelist. real(wp) :: dt_last_eval = 0.0_wp !! Wall time at last evaluation pass (s). ! ---- NetCDF stream ---- ! Inline state (no `use netcdf` here); the writer module ! `rdb_ocean_diag_netcdf` opens / writes / closes against this. type(ocean_diag_nc_stream_t) :: nc_stream procedure(diag_emit_proc), pointer, nopass :: emit_post_fire => null() !! Optional post-fire hook the manager calls after the log !! line. `rdb_ocean_diag_netcdf::open_stream` binds this to !! the NetCDF writer; unbound = log-only behaviour. type(hgrid_t) :: grid !! Cached grid (scalar-only struct, cheap to copy). Derived !! diagnostic fills read `grid%nghost` from here (and the !! per-cell spacing from `state%metrics` directly — design D5); !! they only see `state_handle` so the grid has to be reachable !! through the state composition. contains procedure, non_overridable :: init => ocean_diag_init procedure, non_overridable :: destroy => ocean_diag_destroy procedure, non_overridable :: register => ocean_diag_register procedure, non_overridable :: disable => ocean_diag_disable procedure, non_overridable :: is_registered => ocean_diag_is_registered procedure, non_overridable :: step => ocean_diag_step procedure, non_overridable :: set_output_z_levels => ocean_diag_set_output_z_levels procedure, non_overridable :: set_output_density_levels => ocean_diag_set_output_density_levels procedure, non_overridable :: set_output_sigma_levels => ocean_diag_set_output_sigma_levels procedure, non_overridable :: set_output_zstar_levels => ocean_diag_set_output_zstar_levels procedure, non_overridable :: enter_data => ocean_diag_enter_data procedure, non_overridable :: exit_data => ocean_diag_exit_data procedure, non_overridable :: bytes => ocean_diag_bytes end type ocean_diag_t