protocol_codec Module

Uses json-fortran. Mirrors the Python cortex/protocol.py opcode set.



Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: protocol_version = 1
integer, public, parameter :: MAX_PRIMITIVES = 64

Upper bound on the number of primitives a single COPY_SOLUTION request may list. Any legitimate request names at most the four 1D Euler primitives (x, rho, u, p); the cap is set generously above that to reject an untrusted request that lists a huge (or duplicated) primitive set purely to force a large allocation.

integer, public, parameter :: MAX_CONFIG_ENTRIES = 128

Upper bound on the number of config key-value pairs in a single LOAD_CONFIG_INLINE request. The schema has 62 valid keys; any larger count cannot be all-valid, so we reject it before allocating.


Derived Types

type, public ::  wire_value_t

A typed wire value, populated by =decode_set_value= or =decode_load_config_inline=. Exactly one of the typed fields is meaningful per entry, identified by =kind= (see =cfg_kind_*= in =config_schema=). Strings up to 256 chars; longer strings are rejected by the decoder with =code="type_mismatch"= so the dispatch arm has a fixed-size scratch buffer to hand to =solver_session_set_string=.

Components

Type Visibility Attributes Name Initial
integer, public :: kind = -1
integer, public :: int_value = 0
real(kind=real64), public :: real_value = 0.0_real64
logical, public :: log_value = .false.
character(len=256), public :: str_value = ''
real(kind=real64), public :: vec_value(3) = 0.0_real64

type, public ::  wire_entry_t

A (key, value) pair produced by =decode_load_config_inline=. The dispatch arm walks the array and calls =solver_session_set_*= per entry — transactional only at the codec level (validation runs before any =session % cfg= mutation; if it fails, the array is never returned).

Components

Type Visibility Attributes Name Initial
character(len=128), public :: key = ''
type(wire_value_t), public :: value

Functions

private pure function itoa(n) result(s)

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

Return Value character(len=:), allocatable


Subroutines

public subroutine decode_frame_header(bytes, op, id)

Arguments

Type IntentOptional Attributes Name
integer(kind=int8), intent(in) :: bytes(:)
character(len=*), intent(out) :: op
character(len=*), intent(out) :: id

public subroutine decode_load_namelist(bytes, path, case_dir)

Arguments

Type IntentOptional Attributes Name
integer(kind=int8), intent(in) :: bytes(:)
character(len=*), intent(out) :: path
character(len=*), intent(out), optional :: case_dir

Optional case directory to anchor relative file paths (grid, …) against. Absent in the request -> returned empty (solver falls back to the namelist's own directory). Backward-compatible with older clients.

public subroutine decode_keyed_request(bytes, key)

Decode the {"args":{"key":}} shape shared by GET_ and SET_. SET adds a value field; SET decoders call this first to extract the key, then decode value separately.

Arguments

Type IntentOptional Attributes Name
integer(kind=int8), intent(in) :: bytes(:)
character(len=*), intent(out) :: key

public subroutine decode_set_value(bytes, expected_kind, value, ok, code, message)

Decode the {"args":{"key":"...","value":}} request shape used by SET_. Caller passes =expected_kind= obtained from =schema_lookup= so this routine knows which JSON field to pull. Returns =ok=.false.= with =code="type_mismatch"= when the value is missing or the wrong JSON type.

Arguments

Type IntentOptional Attributes Name
integer(kind=int8), intent(in) :: bytes(:)
integer, intent(in) :: expected_kind
type(wire_value_t), intent(out) :: value
logical, intent(out) :: ok
character(len=*), intent(out) :: code
character(len=*), intent(out) :: message

public subroutine decode_load_config_inline(bytes, entries, n_entries, ok, code, message, dim, case_dir)

Decode {"args":{"config":{key1:v1,key2:v2,...}}}. Walks every key, resolves it against =config_schema= via =schema_lookup=, and validates the corresponding value's JSON type. On the first unknown / mistyped entry returns =ok=.false.= with the offending key carried in =message=. Bounds checking is delegated to the caller (the SET dispatch path runs =solver_session_set_*= which re-validates against schema bounds); this decoder only validates type-level shape.

Arguments

Type IntentOptional Attributes Name
integer(kind=int8), intent(in) :: bytes(:)
type(wire_entry_t), intent(out), allocatable :: entries(:)
integer, intent(out) :: n_entries
logical, intent(out) :: ok
character(len=*), intent(out) :: code
character(len=*), intent(out) :: message
integer, intent(out), optional :: dim

Problem dimension the inline config targets. Absent -> 1 (older clients, 1D-only). Controls which schema (config_schema vs config_schema_2d) the keys are validated against, so a dim=2 config with 2D-only keys decodes.

character(len=*), intent(out), optional :: case_dir

Optional case directory anchoring relative file paths (grid_file, …). Absent -> returned empty; the caller then leaves paths untouched.

public subroutine decode_advance(bytes, max_steps)

Arguments

Type IntentOptional Attributes Name
integer(kind=int8), intent(in) :: bytes(:)
integer, intent(out) :: max_steps

public subroutine decode_run_to_end(bytes, every_steps, every_seconds)

Arguments

Type IntentOptional Attributes Name
integer(kind=int8), intent(in) :: bytes(:)
integer, intent(out) :: every_steps
real(kind=real64), intent(out) :: every_seconds

public subroutine decode_copy_solution(bytes, n_prims, prim_names)

Arguments

Type IntentOptional Attributes Name
integer(kind=int8), intent(in) :: bytes(:)
integer, intent(out) :: n_prims
character(len=16), intent(out), allocatable :: prim_names(:)

public subroutine decode_write_result(bytes, path)

Arguments

Type IntentOptional Attributes Name
integer(kind=int8), intent(in) :: bytes(:)
character(len=*), intent(out) :: path

public subroutine decode_write_checkpoint(bytes, base)

Arguments

Type IntentOptional Attributes Name
integer(kind=int8), intent(in) :: bytes(:)
character(len=*), intent(out) :: base

public subroutine encode_reply_ok(req_id, request_op, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
character(len=*), intent(in) :: request_op
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_reply_error(req_id, request_op, code, message, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
character(len=*), intent(in) :: request_op
character(len=*), intent(in) :: code
character(len=*), intent(in) :: message
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_push(op, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: op
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_hello_push(build, n_ranks, header_bytes)

Arguments

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

HELLO push carries handshake metadata inside args per IPC

integer, intent(in) :: n_ranks
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_progress_tick(iteration, sim_time, dt, residual, wallclock_s, header_bytes)

Encode a PROGRESS_TICK push frame (spec §3.2). Rank 0 only.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: iteration
real(kind=real64), intent(in) :: sim_time
real(kind=real64), intent(in) :: dt
real(kind=real64), intent(in) :: residual
real(kind=real64), intent(in) :: wallclock_s
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_error_push(code, message, header_bytes)

Encode a server-pushed ERROR frame (spec §3.2). Rank 0 only. Always followed by parallel_fatal; the supervisor reads this frame, then observes socket EOF + non-zero exit and raises WorkerError.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: code
character(len=*), intent(in) :: message
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_initialize_reply(req_id, n_global, n_ranks, header_bytes, nx, ny)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
integer, intent(in) :: n_global
integer, intent(in) :: n_ranks
integer(kind=int8), intent(out), allocatable :: header_bytes(:)
integer, intent(in), optional :: nx
integer, intent(in), optional :: ny

public subroutine encode_advance_reply(req_id, steps_taken, finished, iteration, sim_time, dt, residual, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
integer, intent(in) :: steps_taken
logical, intent(in) :: finished
integer, intent(in) :: iteration
real(kind=real64), intent(in) :: sim_time
real(kind=real64), intent(in) :: dt
real(kind=real64), intent(in) :: residual
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_run_to_end_reply(req_id, iteration, sim_time, dt, residual, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
integer, intent(in) :: iteration
real(kind=real64), intent(in) :: sim_time
real(kind=real64), intent(in) :: dt
real(kind=real64), intent(in) :: residual
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_copy_solution_reply(req_id, n, prim_names, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
integer, intent(in) :: n
character(len=*), intent(in) :: prim_names(:)
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_copy_solution_reply_2d(req_id, nx, ny, prim_names, header_bytes)

2D COPY_SOLUTION reply header: like the 1D encoder but with the grid shape (nx, ny) alongside n = nx*ny, so the client can reshape each offset block C-order to (ny, nx). Offsets are byte offsets in request order, one block of nx*ny little-endian float64 per primitive, packed i-fastest (x-contiguous) to match solution_gather_2d.write_global_field.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
integer, intent(in) :: nx
integer, intent(in) :: ny
character(len=*), intent(in) :: prim_names(:)
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_write_result_reply(req_id, path, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
character(len=*), intent(in) :: path
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_write_checkpoint_reply(req_id, files, header_bytes)

WRITE_CHECKPOINT reply header: data.files is the list of file paths actually written by rank 0 (protocol.md §WRITE_CHECKPOINT). v1 always writes a single file; files is kept as a JSON array for forward compatibility with a future multi-file checkpoint format.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
character(len=*), intent(in) :: files(:)
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_get_integer_reply(req_id, value, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
integer, intent(in) :: value
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_get_real_reply(req_id, value, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
real(kind=real64), intent(in) :: value
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_get_logical_reply(req_id, value, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
logical, intent(in) :: value
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_get_string_reply(req_id, value, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
character(len=*), intent(in) :: value
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_get_real3_reply(req_id, value, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
real(kind=real64), intent(in) :: value(3)
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_get_progress_reply(req_id, iteration, sim_time, residual, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
integer, intent(in) :: iteration
real(kind=real64), intent(in) :: sim_time
real(kind=real64), intent(in) :: residual
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine encode_get_point_count_reply(req_id, n_global, header_bytes)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: req_id
integer, intent(in) :: n_global
integer(kind=int8), intent(out), allocatable :: header_bytes(:)

public subroutine schema_lookup(key, idx, expected_kind, ok, message)

Resolve a wire-protocol key against the configuration schema.

Read more…

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: key
integer, intent(out) :: idx
integer, intent(out) :: expected_kind
logical, intent(out) :: ok
character(len=*), intent(out) :: message

private subroutine schema_lookup_dim(dim, key, idx, expected_kind, ok, message)

Resolve a wire key against the schema for dim — the single dimension-selection point for config schemas on the wire path (spec 4.3). A 3D schema plugs in here as one new case.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: dim
character(len=*), intent(in) :: key
integer, intent(out) :: idx
integer, intent(out) :: expected_kind
logical, intent(out) :: ok
character(len=*), intent(out) :: message

private pure subroutine bytes_to_string(b, s)

Arguments

Type IntentOptional Attributes Name
integer(kind=int8), intent(in) :: b(:)
character(len=:), intent(out), allocatable :: s

private pure subroutine string_to_bytes(s, b)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: s
integer(kind=int8), intent(out), allocatable :: b(:)