rdb_ocean_restart Module

Restart cadence + per-slot checkpoint registry for the ocean dyn-core. Each prognostic-owning slot registers its arrays at birth; the manager walks the registry to do the I/O, so new state-carrying slots join by registering rather than editing here.

Contract (MPI-native): 1. FULL local arrays — every registered array is written/read at its TOTAL local extent (interior + ghosts). Physical wall ghosts are genuine owned boundary state (nothing rebuilds them), so an interior-only write breaks the bit-exact gate; periodic/ fold/halo seam ghosts are redundant but harmless to save. 2. Decomposition + grid metadata (px, py, dims, i/j_start, nz, nghost, vcoord, tracer set) live in the file; resume requires the SAME decomposition and error-stops on mismatch. Cross-rank redistribution is an offline tool, never in-Fortran. 3. Global scalars (time, step, outer_step_count) are rank-0’s. 4. A registered field is REQUIRED by default (missing on read is FATAL); mark genuinely optional entries optional=.true..

Device sync: device_mapped arrays (default) are pulled with !$acc update self before the host NetCDF write; host-only state (device_mapped=.false.) is skipped so update self is never issued on an unmapped array. The read path runs BEFORE ocean_state_enter_data, writing the host interior so the subsequent enter_data carries values up to the device.


Uses

  • module~~rdb_ocean_restart~~UsesGraph module~rdb_ocean_restart rdb_ocean_restart module~rdb_constants rdb_constants module~rdb_ocean_restart->module~rdb_constants pic_logger pic_logger module~rdb_ocean_restart->pic_logger pic_strings pic_strings module~rdb_ocean_restart->pic_strings pic_types pic_types module~rdb_constants->pic_types

Used by

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

Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: RESTART_SCHEMA_VERSION = 1

Bumped on any non-back-compatible on-disk field-set/layout change. Written as a global attribute, validated on read.

integer, private, parameter :: MAX_RESTART_ENTRIES = 256

Fixed cap on registered fields; bump if a slot family exceeds it.


Derived Types

type, public ::  ocean_restart_t

Restart-manager lifecycle marker. The registry is built per-run by ocean_state_build_restart_registry (it holds live pointers into the freshly allocated slots), not stored here. Cadence is driven by the driver off cfg%restart_interval/cfg%output_dir.

Components

Type Visibility Attributes Name Initial
logical, public :: is_init = .false.

True between init and destroy.

Type-Bound Procedures

procedure, public, non_overridable :: destroy => ocean_restart_destroy
procedure, public, non_overridable :: init => ocean_restart_init

type, public ::  restart_entry_t

One registered checkpoint field. Holds a pointer to the slot’s host array (or host scalar) plus the interior extents needed to slice owned cells. Exactly one of p0 / p2 / p3 is associated (per rank: 0 = host scalar, 2/3 = array).

Components

Type Visibility Attributes Name Initial
logical, public :: device_mapped = .true.

.true. => write path pulls host-ward via !$acc update self first. Host-only state sets .false. so update self is never issued on an unmapped array (crashes on GPU).

logical, public :: found = .false.

PR-2 (bt-rem-from-av-rem review): set by ocean_restart_read_local when THIS entry’s variable was actually present in the file being read (always .false. before a read, and on a WRITE path registry this field is simply never consulted). Lets a caller distinguish “optional field restored from the checkpoint” from “optional field missing, left at its seeded value” for an entry whose downstream setup behaviour must differ between the two (see registry_entry_found, ocean_vmix_t%kv_from_restart) — optional alone only says whether a MISSING entry is fatal, not whether THIS read found it.

integer, public :: ng = 0

Ghost width (interior starts at ng+1 in x and y).

integer, public :: nk = 0

Third-dim extent for rank-3 fields (no vertical ghosts — layers/interfaces are all owned).

integer, public :: nx_phys = 0

Owned-cell extents in x, y.

integer, public :: ny_phys = 0

Owned-cell extents in x, y.

logical, public :: optional = .false.

.true. => read path warns-and-seeds if absent. Default .false. => a missing field is FATAL.

real(kind=wp), public, pointer :: p0 => null()

Host scalar (rank-0 persistent state, e.g. Chapman eta_old).

real(kind=wp), public, pointer :: p2(:,:) => null()

Host array for rank-2 fields (incl. ghosts).

real(kind=wp), public, pointer :: p3(:,:,:) => null()

Host array for rank-3 fields (incl. ghosts).

integer, public :: rank = 0

0 (host scalar), 2, or 3.

character(len=64), public :: tag = ""

NetCDF variable name (unique within the file).

type, public ::  restart_registry_t

Append-only registry of checkpoint fields. Slots call register_2d / register_3d from their (or the state’s) init.

Components

Type Visibility Attributes Name Initial
type(restart_entry_t), public :: entries(MAX_RESTART_ENTRIES)
integer, public :: n = 0

Type-Bound Procedures

procedure, public, non_overridable :: clear => registry_clear
procedure, public, non_overridable :: entry_found => registry_entry_found
procedure, public, non_overridable :: register_2d => registry_register_2d
procedure, public, non_overridable :: register_3d => registry_register_3d
procedure, public, non_overridable :: register_scalar => registry_register_scalar

Functions

private pure function registry_entry_found(this, tag) result(found)

Was tag actually present in the file the last time this registry was passed to ocean_restart_read_local? .false. before any read, and .false. for an unknown tag (a caller typo is a silent cold-seed, not a crash — callers that care should assert the tag exists via a successful register_* first). See restart_entry_t%found’s docstring for why this is not the same question as optional.

Arguments

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

Return Value logical


Subroutines

private subroutine ocean_restart_destroy(this)

Arguments

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

private subroutine ocean_restart_init(this)

Arguments

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

private subroutine registry_clear(this)

Arguments

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

private subroutine registry_register_2d(this, tag, arr, ng, nx_phys, ny_phys, optional, device_mapped)

Register a rank-2 owned field. arr is the full (ghosted) host array; the owned slice is (ng+1:ng+nx_phys, ng+1:ng+ny_phys).

Arguments

Type IntentOptional Attributes Name
class(restart_registry_t), intent(inout) :: this
character(len=*), intent(in) :: tag
real(kind=wp), intent(in), target :: arr(:,:)
integer, intent(in) :: ng
integer, intent(in) :: nx_phys
integer, intent(in) :: ny_phys
logical, intent(in), optional :: optional
logical, intent(in), optional :: device_mapped

private subroutine registry_register_3d(this, tag, arr, ng, nx_phys, ny_phys, optional, device_mapped)

Register a rank-3 owned field. The vertical extent is taken from size(arr,3) (layers or interfaces — both fully owned).

Arguments

Type IntentOptional Attributes Name
class(restart_registry_t), intent(inout) :: this
character(len=*), intent(in) :: tag
real(kind=wp), intent(in), target :: arr(:,:,:)
integer, intent(in) :: ng
integer, intent(in) :: nx_phys
integer, intent(in) :: ny_phys
logical, intent(in), optional :: optional
logical, intent(in), optional :: device_mapped

private subroutine registry_register_scalar(this, tag, scal, optional)

Register a host scalar (rank-0 persistent state, e.g. the Chapman eta_old_chapman_* corner values). Host-only — never device- mapped, so the write path skips update self for it.

Arguments

Type IntentOptional Attributes Name
class(restart_registry_t), intent(inout) :: this
character(len=*), intent(in) :: tag
real(kind=wp), intent(in), target :: scal
logical, intent(in), optional :: optional