rdb_ocean_data_input Module

Generic, decomposition-aware, device-resident reader for time-varying NetCDF fields field(x, y[, z], t). Owns the file handles, the time axis, the bracket bookkeeping, the H->D motion (only when the bracket advances), and the per-step linear-in-time blend kernel. Owns NO field names and NO state-slot mapping: a consumer registers its own (file, variable, destination) triple via ocean_data_input_register_2d/_3d (or the edge-segment variants for OBC files) and gets back an opaque id.

The binding seam (see PLAN_PR14_netcdf_input_reader.md §13):

  • The reader never touches state. It blends on-device into the caller’s own, caller-MAPPED, explicit-shape, WHOLE (never a section) array, at a registration-time offset (dest_i0, dest_j0). Passing a section into an explicit-shape dummy would trigger a host copy-in/out and silently detach from the device map — never do that.
  • The consumer owns the halo exchange (physical cells only are filled) and the vertical (k) orientation — a source file’s z axis is read AS STORED; nothing here flips it. A 3-D field read from a surface-first source file is handed back bottom-last; if that’s wrong for your consumer, flip it there.
  • &ocean_data_nml carries no per-field entries — only max_fields/verbose. Each consumer defines its own file/ variable keys in its own namelist group.
  • Out-of-range time is an ABORT by default (DATA_OOR_ERROR); DATA_OOR_CLAMP is opt-in per field.
  • No in-core horizontal interpolation (files are pre-regridded to the model’s global horizontal extent), no vertical remapping of a source z axis, no calendar. Time interpolation is linear between the two bracketing records; DATA_TIME_CYCLIC wraps a climatology through an explicit period; DATA_TIME_STATIC reads record 1 once and never touches the file again.
  • Time interpolation is a PURE function of t — no reader-side restart state. A resumed run reproduces every field bit-for-bit from t_current alone.
  • ocean_data_input_update_all(this, t) refreshes every registered field’s bracket (+ pushes any new slab to the device) and is the driver’s one-line per-step hook — a no-op when nfields == 0 (every shipped namelist today). It does NOT write into any consumer array (the reader stores the registration-time dest shape as metadata only, never a pointer). Each consumer then calls update_2d/_3d with its OWN array at its own point in the step, and that call is checked against the t update_all most recently refreshed with — calling update_2d/_3d before update_all has run this step’s t is a fail-loud ordering bug, not a silent stale read.
  • ocean_data_input_fill_static_host is a one-shot HOST-side fill for DATA_TIME_STATIC fields, legal at SETUP time before the destination is device-mapped (PR-24 ice IC, PR-30 tidal maps). Touches no device memory; fails loud on a non-static field.

Storage order: files must be FORTRAN-ordered (x, y[, z], t) — v1 detects a horizontal-dimension mismatch and aborts rather than silently transposing (a transposed field is exactly the class of bug the analytical tests are built to catch); regrid/reorder the file if this trips.


Uses

  • module~~rdb_ocean_data_input~~UsesGraph module~rdb_ocean_data_input rdb_ocean_data_input iso_fortran_env iso_fortran_env module~rdb_ocean_data_input->iso_fortran_env module~rdb_config rdb_config module~rdb_ocean_data_input->module~rdb_config module~rdb_constants rdb_constants module~rdb_ocean_data_input->module~rdb_constants module~rdb_error_ring rdb_error_ring module~rdb_ocean_data_input->module~rdb_error_ring module~rdb_grid rdb_grid module~rdb_ocean_data_input->module~rdb_grid module~rdb_io_netcdf rdb_io_netcdf module~rdb_ocean_data_input->module~rdb_io_netcdf module~rdb_mem_report rdb_mem_report module~rdb_ocean_data_input->module~rdb_mem_report module~rdb_ocean_status rdb_ocean_status module~rdb_ocean_data_input->module~rdb_ocean_status netcdf netcdf module~rdb_ocean_data_input->netcdf pic_ascii pic_ascii module~rdb_ocean_data_input->pic_ascii pic_logger pic_logger module~rdb_ocean_data_input->pic_logger pic_strings pic_strings module~rdb_ocean_data_input->pic_strings module~rdb_config->module~rdb_constants module~rdb_config->module~rdb_error_ring module~rdb_config->module~rdb_ocean_status module~rdb_config->pic_ascii module~rdb_config->pic_logger module~rdb_config->pic_strings module~rdb_ice_enthalpy rdb_ice_enthalpy module~rdb_config->module~rdb_ice_enthalpy 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_types pic_types module~rdb_constants->pic_types module~rdb_error_ring->pic_logger module~rdb_grid->module~rdb_constants module~rdb_io_netcdf->iso_fortran_env module~rdb_io_netcdf->module~rdb_constants module~rdb_io_netcdf->module~rdb_error_ring module~rdb_io_netcdf->netcdf module~rdb_io_netcdf->pic_logger module~rdb_io_netcdf->pic_strings 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_ice_enthalpy->module~rdb_constants module~rdb_ice_init->module~rdb_constants module~rdb_ice_init->module~rdb_grid module~rdb_ice_init->module~rdb_ice_enthalpy module~rdb_ice_column rdb_ice_column module~rdb_ice_init->module~rdb_ice_column module~rdb_ice_state rdb_ice_state module~rdb_ice_init->module~rdb_ice_state module~rdb_multilayer_state rdb_multilayer_state module~rdb_ice_init->module~rdb_multilayer_state module~rdb_ocean_metrics rdb_ocean_metrics module~rdb_ice_init->module~rdb_ocean_metrics module~rdb_nml_schema->module~rdb_constants module~rdb_nml_schema->module~rdb_error_ring module~rdb_nml_schema->pic_logger module~rdb_ice_column->module~rdb_constants 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_ice_state->iso_fortran_env module~rdb_ice_state->module~rdb_constants module~rdb_ice_state->module~rdb_grid module~rdb_ice_state->module~rdb_mem_report module~rdb_ice_state->module~rdb_ice_enthalpy module~rdb_ice_state->module~rdb_ice_column module~rdb_multilayer_state->iso_fortran_env module~rdb_multilayer_state->module~rdb_constants module~rdb_multilayer_state->module~rdb_error_ring module~rdb_multilayer_state->module~rdb_grid module~rdb_multilayer_state->module~rdb_mem_report module~rdb_multilayer_state->pic_logger module~rdb_efp rdb_efp module~rdb_multilayer_state->module~rdb_efp module~rdb_tracer rdb_tracer module~rdb_multilayer_state->module~rdb_tracer module~rdb_ocean_metrics->iso_fortran_env module~rdb_ocean_metrics->module~rdb_constants module~rdb_ocean_metrics->module~rdb_error_ring module~rdb_ocean_metrics->module~rdb_grid module~rdb_ocean_metrics->module~rdb_io_netcdf module~rdb_ocean_metrics->module~rdb_mem_report module~rdb_ocean_metrics->module~rdb_ocean_status module~rdb_ocean_metrics->netcdf module~rdb_ocean_metrics->pic_logger module~rdb_ocean_metrics->pic_strings 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_efp->iso_fortran_env ieee_arithmetic ieee_arithmetic module~rdb_efp->ieee_arithmetic 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_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

Used by

  • module~~rdb_ocean_data_input~~UsedByGraph module~rdb_ocean_data_input rdb_ocean_data_input module~rdb_ocean_data_forcing rdb_ocean_data_forcing module~rdb_ocean_data_forcing->module~rdb_ocean_data_input module~rdb_ocean_engine rdb_ocean_engine module~rdb_ocean_engine->module~rdb_ocean_data_input module~rdb_ocean_engine->module~rdb_ocean_data_forcing module~rdb_ocean_state rdb_ocean_state module~rdb_ocean_engine->module~rdb_ocean_state module~rdb_ocean_diag_derived rdb_ocean_diag_derived module~rdb_ocean_engine->module~rdb_ocean_diag_derived module~rdb_ocean_diag_fills rdb_ocean_diag_fills module~rdb_ocean_engine->module~rdb_ocean_diag_fills module~rdb_ocean_setup rdb_ocean_setup module~rdb_ocean_engine->module~rdb_ocean_setup module~rdb_ocean_state->module~rdb_ocean_data_input module~rdb_ocean_state->module~rdb_ocean_data_forcing module~rdb_driver rdb_driver module~rdb_driver->module~rdb_ocean_engine module~rdb_driver->module~rdb_ocean_state module~rdb_handle rdb_handle module~rdb_handle->module~rdb_ocean_engine module~rdb_handle->module~rdb_ocean_state module~rdb_ocean_api rdb_ocean_api module~rdb_ocean_api->module~rdb_ocean_engine module~rdb_ocean_api->module~rdb_handle module~rdb_ocean_api->module~rdb_ocean_diag_derived module~rdb_ocean_api->module~rdb_ocean_diag_fills 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 module~rdb_ocean_setup->module~rdb_ocean_state

Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: DATA_EDGE_EAST = 2
integer, public, parameter :: DATA_EDGE_NORTH = 4
integer, public, parameter :: DATA_EDGE_SOUTH = 3
integer, public, parameter :: DATA_EDGE_WEST = 1
integer, public, parameter :: DATA_OOR_CLAMP = 2
integer, public, parameter :: DATA_OOR_ERROR = 1
integer, public, parameter :: DATA_TIME_CYCLIC = 2
integer, public, parameter :: DATA_TIME_LINEAR = 1
integer, public, parameter :: DATA_TIME_STATIC = 3
real(kind=wp), private, allocatable :: data_input_ws(:,:,:)

Derived Types

type, public ::  data_input_field_t

One registered (file, variable, destination-shape) triple. Array-of-derived-type element — NEVER dereference this from inside a do concurrent/device-kernel body (outer-shim + flat-impl rule); every place this type is touched below is a host-side registry walk that hands plain explicit-shape arrays to a pure flat-impl kernel.

Components

Type Visibility Attributes Name Initial
logical, public :: active = .false.
real(kind=wp), public :: add_offset = 0.0_wp
real(kind=wp), public :: cycle_period = 0.0_wp
integer, public :: dest_i0 = 1
integer, public :: dest_j0 = 1
integer, public :: dest_n1 = 0
integer, public :: dest_n2 = 0
integer, public :: dest_n3 = 1
real(kind=wp), public, allocatable :: f0(:,:,:)

Bracketing records, shape (nx, ny, nz). Device-mapped by ocean_data_input_t%enter_data.

real(kind=wp), public, allocatable :: f1(:,:,:)

Bracketing records, shape (nx, ny, nz). Device-mapped by ocean_data_input_t%enter_data.

integer, public :: i0 = 1
logical, public :: is_3d = .false.
integer, public :: j0 = 1
integer, public :: ncid = -1
integer, public :: nreads = 0

Slab-read counter (test hook — T4 asserts exactly one read for a STATIC field’s whole run).

integer, public :: nt = 0
integer, public :: nx = 0
integer, public :: ny = 0
integer, public :: nz = 1
integer, public :: oor = DATA_OOR_ERROR
logical, public :: oor_warned = .false.
integer, public :: rec0 = -1

Currently-loaded record indices (1-based file record numbers); -1 = nothing loaded yet.

integer, public :: rec1 = -1

Currently-loaded record indices (1-based file record numbers); -1 = nothing loaded yet.

real(kind=wp), public :: scale = 1.0_wp
real(kind=wp), public, allocatable :: t_axis(:)

File time axis, converted to seconds (scale + t_offset NOT applied here — t_offset is applied to the QUERY time, not the axis; see data_input_refresh_brackets).

real(kind=wp), public :: t_last = -huge(1.0_wp)

Model time update_all most recently refreshed this field at. update_2d/_3d asserts the caller’s t matches (fail loud on an ordering bug — see module docstring). Ignored for DATA_TIME_STATIC (never refreshed after registration).

real(kind=wp), public :: t_offset = 0.0_wp
integer, public :: time_mode = DATA_TIME_LINEAR
integer, public :: varid = -1
real(kind=wp), public :: w = 0.0_wp

Current blend weight: f = (1-w)*f0 + w*f1.

type, public ::  ocean_data_input_t

Components

Type Visibility Attributes Name Initial
type(data_input_field_t), public, allocatable :: fields(:)
logical, public :: is_init = .false.
integer, public :: nfields = 0
integer, public :: nfields_max = 0
logical, public :: verbose = .false.

Type-Bound Procedures

procedure, public, non_overridable :: bytes => ocean_data_input_bytes
procedure, public, non_overridable :: destroy => ocean_data_input_destroy
procedure, public, non_overridable :: enter_data => ocean_data_input_enter_data
procedure, public, non_overridable :: exit_data => ocean_data_input_exit_data
procedure, public, non_overridable :: init => ocean_data_input_init

Functions

public function data_input_dims_ok(filename, var, nx_phys, ny_phys, is_3d, nz_src) result(ok)

Self-contained, non-erroring dimension validator — the single-rank (i_offset_global = j_offset_global = 0) testable twin of register_common’s inline checks; mirrors zinit_dims_ok. Opens filename, inspects var’s rank and lengths, and returns .false. on any mismatch, missing variable, or I/O error — NEVER aborts, so test code can probe the false branch without a subprocess/death-test harness (the house convention — see zinit_dims_ok).

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: filename
character(len=*), intent(in) :: var
integer, intent(in) :: nx_phys
integer, intent(in) :: ny_phys
logical, intent(in) :: is_3d
integer, intent(in), optional :: nz_src

Return Value logical

public function data_input_time_mode_from_string(tag) result(mode)

Translate a namelist/registration-time string into a DATA_TIME_* code. Fail-loud on anything not covered by data_input_time_mode_is_implemented — an unrecognised tag must never silently fall back to a default mode.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: tag

Return Value integer

public pure function data_input_time_mode_is_implemented(tag) result(ok)

.true. iff tag (case-insensitive) names a shipped time mode. Drives the fail-loud dispatch in data_input_time_mode_from_string — house idiom, see lateral_closure_is_implemented.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: tag

Return Value logical

private pure function dims_geometry_ok(nd, expect_nd, d_horiz1, d_horiz2, expect1, expect2) result(ok)

Low-level geometry check used inline by register_common: .true. iff the variable has the expected rank and its two validated-length dims are each at least as long as required (decomposition-safe: a subdomain slab only needs offset+extent to fit, not to equal the file’s global length). Never aborts.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nd
integer, intent(in) :: expect_nd
integer, intent(in) :: d_horiz1
integer, intent(in) :: d_horiz2
integer, intent(in) :: expect1
integer, intent(in) :: expect2

Return Value logical

private pure function ocean_data_input_bytes(this) result(nbytes)

Counted allocatable footprint (0 when unallocated). Summed over every registered field’s f0/f1 — the t_axis is small (nt reals) and intentionally excluded, matching the house convention of counting device-resident footprint only.

Arguments

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

Return Value integer(kind=int64)

private function reg_io_ok(local_ierr, ierr, ncid) result(ok)

Translate a raw nc_check-style status (0 = ok) from one of the nc_* reader calls in register_common into the caller’s ierr contract: .true. on success; on failure, .false. with ierr = OCEAN_STATUS_ERR_IO when ierr is present (closing ncid first, when given, so a mid-registration failure does not leak the file handle), or error stops with a generic message when ierr is absent — the SPECIFIC reason was already logged by nc_check/fail before this returns, so the legacy (no ierr) log output is unchanged; only the raw error stop text is generic (same idiom as rdb_bathymetry::bathy_io_ok, P0.1 F1/F2).

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: local_ierr
integer, intent(out), optional :: ierr
integer, intent(in), optional :: ncid

Return Value logical


Subroutines

public pure subroutine data_input_locate(t_axis, nt, mode, cycle_period, t, n0, n1, w, out_of_range)

Bracket search + blend weight for a query time t (already in file-time units/offset — the caller applies t_offset/t_scale before calling). nt == 1 is degenerate: always returns n0 = n1 = 1, w = 0, never out of range.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: t_axis(nt)
integer, intent(in) :: nt
integer, intent(in) :: mode
real(kind=wp), intent(in) :: cycle_period
real(kind=wp), intent(in) :: t
integer, intent(out) :: n0
integer, intent(out) :: n1
real(kind=wp), intent(out) :: w
logical, intent(out) :: out_of_range

public pure subroutine data_input_time_scale_from_units(units, scale, ok)

CF units attribute (“seconds since …”, “hours since …”, …) -> a multiplier converting the raw file time axis to seconds. Only the leading unit word matters (no calendar, no reference date — see module docstring). ok = .false. for an unrecognised leading word; caller decides the fallback.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: units
real(kind=wp), intent(out) :: scale
logical, intent(out) :: ok

public subroutine ocean_data_input_fill_static_host(this, id, n1, n2, dest)

One-shot HOST-side fill of a DATA_TIME_STATIC field. Copies the already-read record-1 slab into dest at the registration-time offsets. Touches NO device memory — callable at setup, before dest is mapped. Plain host do loops (NOT do concurrent — on -stdpar=gpu a bare do concurrent is unconditionally offloaded regardless of whether dest is mapped, which is exactly the silent-stale-write bug this routine exists to avoid). Fails loud for any non-static field.

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(in) :: this
integer, intent(in) :: id
integer, intent(in) :: n1
integer, intent(in) :: n2
real(kind=wp), intent(inout) :: dest(n1,n2)

public subroutine ocean_data_input_fill_static_host_3d(this, id, n1, n2, n3, dest)

3-D twin of fill_static_host.

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(in) :: this
integer, intent(in) :: id
integer, intent(in) :: n1
integer, intent(in) :: n2
integer, intent(in) :: n3
real(kind=wp), intent(inout) :: dest(n1,n2,n3)

public subroutine ocean_data_input_load_static_2d(file, var, grid, n1, n2, dest_i0, dest_j0, dest, ierr)

One-shot STATIC 2-D read: register, fill, close. The setup-time convenience wrapper over register_2d(time_mode="static") + fill_static_host for a field that is read ONCE and never updated — a prescribed, time-constant geometry rather than a forcing. &ocean_cavity_dyn_nml draft_config="file" is the first consumer.

Read more…

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: file
character(len=*), intent(in) :: var
type(hgrid_t), intent(in) :: grid
integer, intent(in) :: n1

Shape of dest — the FULL ghosted (nx_total, ny_total).

integer, intent(in) :: n2

Shape of dest — the FULL ghosted (nx_total, ny_total).

integer, intent(in) :: dest_i0

Destination index of the first PHYSICAL cell (nghost + 1).

integer, intent(in) :: dest_j0

Destination index of the first PHYSICAL cell (nghost + 1).

real(kind=wp), intent(inout) :: dest(n1,n2)
integer, intent(out), optional :: ierr

Non-zero on a registry / file / dimension failure when present; absent behaves as the rest of the reader (error stop).

public subroutine ocean_data_input_register_2d(this, file, var, grid, dest_n1, dest_n2, dest_i0, dest_j0, id, time_mode, cycle_period, t_offset, t_scale, scale, add_offset, oor, nx_extra, ny_extra, ierr)

Register a 2-D time-varying field f(x, y, t). Opens the file now and keeps the handle for the run. See the module docstring for the destination-offset contract.

Read more…

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(inout) :: this
character(len=*), intent(in) :: file
character(len=*), intent(in) :: var
type(hgrid_t), intent(in) :: grid
integer, intent(in) :: dest_n1
integer, intent(in) :: dest_n2
integer, intent(in) :: dest_i0
integer, intent(in) :: dest_j0
integer, intent(out) :: id
character(len=*), intent(in), optional :: time_mode
real(kind=wp), intent(in), optional :: cycle_period
real(kind=wp), intent(in), optional :: t_offset
real(kind=wp), intent(in), optional :: t_scale
real(kind=wp), intent(in), optional :: scale
real(kind=wp), intent(in), optional :: add_offset
integer, intent(in), optional :: oor
integer, intent(in), optional :: nx_extra
integer, intent(in), optional :: ny_extra
integer, intent(out), optional :: ierr

Non-zero (OCEAN_STATUS_ERR_SETUP/OCEAN_STATUS_ERR_IO) on a registry/file/dimension failure when present; absent behaves as today (error stop).

public subroutine ocean_data_input_register_3d(this, file, var, grid, nz_src, dest_n1, dest_n2, dest_n3, dest_i0, dest_j0, id, time_mode, cycle_period, t_offset, t_scale, scale, add_offset, oor, ierr)

Register a 3-D time-varying field f(x, y, z, t). nz_src is the source z-level count (the consumer’s own concern — the reader validates it against the file’s z dim and does NOT flip or remap k; see the module docstring).

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(inout) :: this
character(len=*), intent(in) :: file
character(len=*), intent(in) :: var
type(hgrid_t), intent(in) :: grid
integer, intent(in) :: nz_src
integer, intent(in) :: dest_n1
integer, intent(in) :: dest_n2
integer, intent(in) :: dest_n3
integer, intent(in) :: dest_i0
integer, intent(in) :: dest_j0
integer, intent(out) :: id
character(len=*), intent(in), optional :: time_mode
real(kind=wp), intent(in), optional :: cycle_period
real(kind=wp), intent(in), optional :: t_offset
real(kind=wp), intent(in), optional :: t_scale
real(kind=wp), intent(in), optional :: scale
real(kind=wp), intent(in), optional :: add_offset
integer, intent(in), optional :: oor
integer, intent(out), optional :: ierr

public subroutine ocean_data_input_register_segment_2d(this, file, var, grid, edge, dest_n1, dest_n2, id, time_mode, cycle_period, t_offset, t_scale, scale, add_offset, oor, ierr)

Register a 2-D OBC-segment field. The degenerate horizontal axis (x for west/east, y for south/north) reads as start=1, count=1; the along-edge axis slices from the global index range exactly as register_2d does. dest_i0/dest_j0 are implied by edge (degenerate axis -> index 1; along-edge axis -> grid%nghost + 1) — not arguments (see module docstring).

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(inout) :: this
character(len=*), intent(in) :: file
character(len=*), intent(in) :: var
type(hgrid_t), intent(in) :: grid
integer, intent(in) :: edge
integer, intent(in) :: dest_n1
integer, intent(in) :: dest_n2
integer, intent(out) :: id
character(len=*), intent(in), optional :: time_mode
real(kind=wp), intent(in), optional :: cycle_period
real(kind=wp), intent(in), optional :: t_offset
real(kind=wp), intent(in), optional :: t_scale
real(kind=wp), intent(in), optional :: scale
real(kind=wp), intent(in), optional :: add_offset
integer, intent(in), optional :: oor
integer, intent(out), optional :: ierr

public subroutine ocean_data_input_register_segment_3d(this, file, var, grid, edge, nz_src, dest_n1, dest_n2, dest_n3, id, time_mode, cycle_period, t_offset, t_scale, scale, add_offset, oor, ierr)

3-D twin of register_segment_2d (PR-22 OBC segment files).

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(inout) :: this
character(len=*), intent(in) :: file
character(len=*), intent(in) :: var
type(hgrid_t), intent(in) :: grid
integer, intent(in) :: edge
integer, intent(in) :: nz_src
integer, intent(in) :: dest_n1
integer, intent(in) :: dest_n2
integer, intent(in) :: dest_n3
integer, intent(out) :: id
character(len=*), intent(in), optional :: time_mode
real(kind=wp), intent(in), optional :: cycle_period
real(kind=wp), intent(in), optional :: t_offset
real(kind=wp), intent(in), optional :: t_scale
real(kind=wp), intent(in), optional :: scale
real(kind=wp), intent(in), optional :: add_offset
integer, intent(in), optional :: oor
integer, intent(out), optional :: ierr

public subroutine ocean_data_input_update_2d(this, id, t, n1, n2, dest)

Blend field id’s current bracket into the caller’s WHOLE, device-mapped dest(n1, n2) array at the registration-time offset. t must equal the value update_all most recently refreshed this field with (fail-loud ordering check — a consumer calling this before update_all has run for the current step is a real bug, not a silent stale read). Exempt for DATA_TIME_STATIC fields, whose bracket never changes.

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(in) :: this
integer, intent(in) :: id
real(kind=wp), intent(in) :: t
integer, intent(in) :: n1
integer, intent(in) :: n2
real(kind=wp), intent(inout) :: dest(n1,n2)

public subroutine ocean_data_input_update_3d(this, id, t, n1, n2, n3, dest)

3-D twin of update_2d.

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(in) :: this
integer, intent(in) :: id
real(kind=wp), intent(in) :: t
integer, intent(in) :: n1
integer, intent(in) :: n2
integer, intent(in) :: n3
real(kind=wp), intent(inout) :: dest(n1,n2,n3)

public subroutine ocean_data_input_update_all(this, t)

Driver hook: refresh every registered field’s bracket for model time t (reading + pushing a new slab to the device only when the bracket actually advances). No-op when nfields == 0 — every shipped namelist today. Does NOT write into any consumer array (see module docstring) — call update_2d/_3d afterwards for that.

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(inout) :: this
real(kind=wp), intent(in) :: t

private subroutine check_fresh(this, id, t)

Ordering guard: update_2d/_3d must be called with the same t update_all most recently refreshed this field’s bracket with (skipped for STATIC — its bracket never changes, so “freshness” is meaningless). Catches a consumer calling update_2d/_3d before update_all has run this step, which would otherwise silently blend a stale bracket.

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(in) :: this
integer, intent(in) :: id
real(kind=wp), intent(in) :: t

private subroutine check_registered(this, id, is_3d, n1, n2, n3)

Fail-loud guard shared by every per-step/fill accessor: id must name an active field of the right rank, and the caller’s dest shape must match what was declared at registration.

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(in) :: this
integer, intent(in) :: id
logical, intent(in) :: is_3d
integer, intent(in) :: n1
integer, intent(in) :: n2
integer, intent(in), optional :: n3

private pure subroutine data_input_blend_2d_impl(nxs, nys, dn1, dn2, i0, j0, f0, f1, w, dest)

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nxs
integer, intent(in) :: nys
integer, intent(in) :: dn1
integer, intent(in) :: dn2
integer, intent(in) :: i0
integer, intent(in) :: j0
real(kind=wp), intent(in) :: f0(nxs,nys)
real(kind=wp), intent(in) :: f1(nxs,nys)
real(kind=wp), intent(in) :: w
real(kind=wp), intent(inout) :: dest(dn1,dn2)

private pure subroutine data_input_blend_3d_impl(nxs, nys, nzs, dn1, dn2, dn3, i0, j0, f0, f1, w, dest)

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nxs
integer, intent(in) :: nys
integer, intent(in) :: nzs
integer, intent(in) :: dn1
integer, intent(in) :: dn2
integer, intent(in) :: dn3
integer, intent(in) :: i0
integer, intent(in) :: j0
real(kind=wp), intent(in) :: f0(nxs,nys,nzs)
real(kind=wp), intent(in) :: f1(nxs,nys,nzs)
real(kind=wp), intent(in) :: w
real(kind=wp), intent(inout) :: dest(dn1,dn2,dn3)

private subroutine data_input_read_slab_impl(fld, rec, into_f1)

Host-ONLY NetCDF slab read for file record rec -> fld%f0 (default) or fld%f1 (into_f1 = .true.), applying scale/add_offset once at read. Uses the module-level host workspace (registration/bracket-advance-time only — never a per-step allocation). Deliberately carries NO !$acc directive: called both before enter_data (STATIC field, at registration) and after it (LINEAR/CYCLIC bracket advance) — the caller pushes to the device itself, only when that is actually correct (data_input_refresh_brackets).

Arguments

Type IntentOptional Attributes Name
type(data_input_field_t), intent(inout) :: fld
integer, intent(in) :: rec
logical, intent(in), optional :: into_f1

private subroutine data_input_refresh_brackets(this, id, t)

Host-side registry walk (outer shim) for field id.

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(inout) :: this
integer, intent(in) :: id
real(kind=wp), intent(in) :: t

private subroutine data_input_workspace_cleanup()

Arguments

None

private subroutine data_input_workspace_ensure(nx, ny, nz)

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: nx
integer, intent(in) :: ny
integer, intent(in) :: nz

private subroutine ocean_data_input_destroy(this)

Arguments

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

private subroutine ocean_data_input_enter_data(this)

Type-bound wrapper — delegates to the non-polymorphic impl (the AMD libomptarget cross-slot-overlap fix; see rdb_ocean_surface_stress.F90).

Arguments

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

private subroutine ocean_data_input_enter_data_impl(this)

Arguments

Type IntentOptional Attributes Name
type(ocean_data_input_t), intent(inout) :: this

private subroutine ocean_data_input_exit_data(this)

Arguments

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

private subroutine ocean_data_input_exit_data_impl(this)

Arguments

Type IntentOptional Attributes Name
type(ocean_data_input_t), intent(inout) :: this

private subroutine ocean_data_input_init(this, cfg)

Allocate the field registry. cfg optional so ocean_state_init (which many tests call directly with no config_t in hand) can construct a default-sized (16 slots, quiet) reader identically to the scaffold it replaces; ocean_state_init_from_config re-calls this with the real cfg%ocean%data once cfg is available — safe because nothing is registered between the two calls.

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(inout) :: this
type(ocean_data_config_t), intent(in), optional :: cfg

private subroutine register_common(this, file, var, is_3d, i0, j0, nx, ny, nz, dest_i0, dest_j0, dest_n1, dest_n2, dest_n3, time_mode, cycle_period, t_offset, t_scale, scale, add_offset, oor, id, edge, ierr)

Shared registration body for register_2d/_3d/_segment_2d/_segment_3d. (i0, j0, nx, ny, nz) are FILE-side start/count (already resolved by the caller — plain global-offset slicing for the base variants, degenerate-axis geometry for the segment variants).

Arguments

Type IntentOptional Attributes Name
class(ocean_data_input_t), intent(inout) :: this
character(len=*), intent(in) :: file
character(len=*), intent(in) :: var
logical, intent(in) :: is_3d
integer, intent(in) :: i0
integer, intent(in) :: j0
integer, intent(in) :: nx
integer, intent(in) :: ny
integer, intent(in) :: nz
integer, intent(in) :: dest_i0
integer, intent(in) :: dest_j0
integer, intent(in) :: dest_n1
integer, intent(in) :: dest_n2
integer, intent(in) :: dest_n3
character(len=*), intent(in), optional :: time_mode
real(kind=wp), intent(in), optional :: cycle_period
real(kind=wp), intent(in), optional :: t_offset
real(kind=wp), intent(in), optional :: t_scale
real(kind=wp), intent(in), optional :: scale
real(kind=wp), intent(in), optional :: add_offset
integer, intent(in), optional :: oor
integer, intent(out) :: id
integer, intent(in), optional :: edge
integer, intent(out), optional :: ierr

Non-zero (OCEAN_STATUS_ERR_SETUP/OCEAN_STATUS_ERR_IO) on a registry/file/dimension failure when present; absent behaves as today (error stop).

private subroutine resolve_time_var(ncid, tdimid, tvarid, status)

Look up the time coordinate variable by the CF convention (dim name == var name); fall back to a variable literally named “time”. status is nf90_noerr iff found.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: ncid
integer, intent(in) :: tdimid
integer, intent(out) :: tvarid
integer, intent(out) :: status

private subroutine segment_geometry(grid, edge, i0, j0, nx, ny, dest_i0, dest_j0, ierr)

Degenerate-axis + along-edge slab geometry for an OBC-segment registration. i0/j0/nx/ny are FILE-side (start, count); dest_i0/dest_j0 are where the slab lands in the consumer’s staging array.

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
integer, intent(in) :: edge
integer, intent(out) :: i0
integer, intent(out) :: j0
integer, intent(out) :: nx
integer, intent(out) :: ny
integer, intent(out) :: dest_i0
integer, intent(out) :: dest_j0
integer, intent(out), optional :: ierr

Non-zero (OCEAN_STATUS_ERR_SETUP) on an unrecognised edge tag when present; absent behaves as today (error stop).