ocean_diag_t Derived Type

type, public :: ocean_diag_t


Inherits

type~~ocean_diag_t~~InheritsGraph type~ocean_diag_t ocean_diag_t type~diag_var_t diag_var_t type~ocean_diag_t->type~diag_var_t vars type~hgrid_t hgrid_t type~ocean_diag_t->type~hgrid_t grid type~ocean_diag_nc_stream_t ocean_diag_nc_stream_t type~ocean_diag_t->type~ocean_diag_nc_stream_t nc_stream type~diag_mask_t diag_mask_t type~diag_var_t->type~diag_mask_t mask

Inherited by

type~~ocean_diag_t~~InheritedByGraph type~ocean_diag_t ocean_diag_t type~ocean_state_t ocean_state_t type~ocean_state_t->type~ocean_diag_t diag type~ocean_engine_t ocean_engine_t type~ocean_engine_t->type~ocean_state_t state type~ocean_handle_t ocean_handle_t type~ocean_handle_t->type~ocean_state_t state type~ocean_handle_t->type~ocean_engine_t engine

Components

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. rdb_ocean_diag_netcdf::open_stream binds this to the NetCDF writer; unbound = log-only behaviour.

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

logical, public :: is_init = .false.

True between init and destroy. Prefer this to allocated(...) — tracks GPU device attachment too.

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 vars(:). Grown via reallocation on register overflow.

integer, public :: nz_out = 0
logical, public :: 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.

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


Type-Bound Procedures

procedure, public, non_overridable :: bytes => ocean_diag_bytes

  • private pure function ocean_diag_bytes(this) result(nbytes)

    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.

    Arguments

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

    Return Value integer(kind=int64)

procedure, public, non_overridable :: destroy => ocean_diag_destroy

procedure, public, non_overridable :: disable => ocean_diag_disable

  • private subroutine ocean_diag_disable(this, name)

    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.

    Arguments

    Type IntentOptional Attributes Name
    class(ocean_diag_t), intent(inout) :: this
    character(len=*), intent(in) :: name

procedure, public, non_overridable :: enter_data => ocean_diag_enter_data

  • private subroutine ocean_diag_enter_data(this)

    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.

    Read more…

    Arguments

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

procedure, public, non_overridable :: exit_data => ocean_diag_exit_data

  • private subroutine ocean_diag_exit_data(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.

    Arguments

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

procedure, public, non_overridable :: init => ocean_diag_init

  • private subroutine ocean_diag_init(this, grid)

    Allocate an empty registry sized at INITIAL_CAPACITY slots. Subsequent register calls grow the array via doubling.

    Arguments

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

procedure, public, non_overridable :: is_registered => ocean_diag_is_registered

  • private pure function ocean_diag_is_registered(this, name) result(yes)

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

    Arguments

    Type IntentOptional Attributes Name
    class(ocean_diag_t), intent(in) :: this
    character(len=*), intent(in) :: name

    Return Value logical

procedure, public, non_overridable :: register => ocean_diag_register

  • private subroutine ocean_diag_register(this, name, units, fill, n1, n2, n3, long_name, standard_name, time_op, dt_out, output_vgrid, remap, mask, is_extensive, has_missing)

    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.

    Read more…

    Arguments

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

procedure, public, non_overridable :: set_output_density_levels => ocean_diag_set_output_density_levels

  • private subroutine ocean_diag_set_output_density_levels(this, rho, ierr)

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

    Arguments

    Type IntentOptional Attributes Name
    class(ocean_diag_t), intent(inout) :: this
    real(kind=wp), intent(in) :: rho(:)
    integer, intent(out), optional :: ierr

procedure, public, non_overridable :: set_output_sigma_levels => ocean_diag_set_output_sigma_levels

  • private subroutine ocean_diag_set_output_sigma_levels(this, sigma, 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.

    Arguments

    Type IntentOptional Attributes Name
    class(ocean_diag_t), intent(inout) :: this
    real(kind=wp), intent(in) :: sigma(:)
    integer, intent(out), optional :: ierr

procedure, public, non_overridable :: set_output_z_levels => ocean_diag_set_output_z_levels

  • private subroutine ocean_diag_set_output_z_levels(this, z, 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.

    Arguments

    Type IntentOptional Attributes Name
    class(ocean_diag_t), intent(inout) :: this
    real(kind=wp), intent(in) :: z(:)
    integer, intent(out), optional :: ierr

    Non-zero (OCEAN_STATUS_ERR_SETUP) when size(z) > NZ_STACK_MAX, when present; absent behaves as today (error stop). (F5 residual, P2.4)

procedure, public, non_overridable :: set_output_zstar_levels => ocean_diag_set_output_zstar_levels

  • private subroutine ocean_diag_set_output_zstar_levels(this, zstar, ierr)

    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.

    Arguments

    Type IntentOptional Attributes Name
    class(ocean_diag_t), intent(inout) :: this
    real(kind=wp), intent(in) :: zstar(:)
    integer, intent(out), optional :: ierr

procedure, public, non_overridable :: step => ocean_diag_step

  • private subroutine ocean_diag_step(this, state_handle, dt, t)

    Advance every registered variable. Behaviour by time_op:

    Read more…

    Arguments

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

Source Code

   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