Experiment definitions¶
Grid, Execution, Forcing and Experiment are definitions you can
import directly from veris. They run in Python on the host, the computer
that controls the calculation, and cannot change in place. They check inputs
and combine supplied values with defaults from the model’s named tables of
settings and physical constants. They do not create model arrays or choose a
JAX backend, the CPU or GPU system that will run the calculation:
from veris import Execution, Experiment, Forcing, Grid
experiment = Experiment(
grid=Grid(nx=6, ny=8),
settings={"dtype": "float32", "deltatDyn": 600, "deltatTherm": 600},
constants={"rhoIce": 910},
initial_conditions={"hIceMean": 1.0, "hSnowMean": 0.05, "Area": 0.8},
forcing=Forcing(
constant={"uWind": 5.0, "ocSalt": 34.7},
series={"Qnet": [80.0, 100.0, 120.0]},
),
execution=Execution(backend="cpu"),
steps=3,
)
Use veris.initialize_experiment() to create model arrays and the
Simulation lifecycle interface to control runs from Python. Initialization and presets
describes preset providers, which supply starting fields, and lower-level array
creation. These operations run on the host. Enable JAX x64 before requesting
float64 arrays (see Model settings).
Declarative files¶
Experiment.from_file(path, overrides=...) reads version 1 or 2 JSON data
files. If the version is omitted, it means 1. Unsupported versions and duplicate
or unknown keys produce clear errors. The definition starts with preset
defaults, then applies file values and finally explicit Python overrides, using
the merge rules above. You can write a runnable definition as:
{
"schema_version": 1,
"preset": "island",
"grid": {"nx": 6, "ny": 8},
"settings": {"dtype": "float32", "nEVPsteps": 2},
"scenario": {"islandWindSpeed": 4.0},
"forcing": {"series": {"Qnet": [80.0, 100.0, 120.0]}},
"steps": 3
}
Output durations use {"microseconds": integer}. Files you write by hand can
also use {"seconds": number} if the duration is an exact number of
microseconds. A calendar origin is its starting date and time. Gregorian origins
use ISO-format dates without a timezone. Fixed-calendar origins use objects
with integer year, month, day and optional time components. See
Export modes for exports of supplied inputs and resolved values.
Dimensions, units and precedence¶
Grid.nx and Grid.ny count global physical cells, the cells in the
full modeled area, excluding all halos. Halos are extra cells around each grid
piece that hold boundary or neighboring values. Constant and initial-condition
arrays are single values or (nx, ny) fields. Forcing series have shape
(time,) or (time, nx, ny). A staggered grid places different fields at
cell centers, faces and corners. All these fields use the same extents with
(x, y) ordering. The numerical State uses two halo cells at every partition
boundary, where a partition is a grid piece. For example, Grid(12, 8) on
partitions=(3, 2) has local physical extents (4, 4) and packed storage
shape (24, 16). Packed storage includes every partition’s halos.
Settings and constants use the defaults and units listed in
Model settings and Physical constants. Supplied
overrides take precedence over table defaults. Constants inherit the model
dtype, its numerical data type. A conflicting constants dtype is rejected.
Use Grid for dimensions and Execution for sharding, which splits arrays
across devices. Those controls cannot also appear in settings. The resolved
objects are available as experiment.configuration and
experiment.physical_constants. Simulation binds them for its trajectory;
pure advance also accepts dynamic physical-parameter continuations.
Their numerical grid extents remain local to each partition.
Initial conditions and forcing use the units in State fields:
thickness in meters, temperatures in kelvin, the absolute temperature scale,
concentration between zero and one, and heat fluxes in W/m² with Qnet and
Qsw positive upward. Concentration is the fraction of a cell covered by ice.
A heat flux is heat transferred per unit area per unit time. Initial conditions
accept ice fields that evolve during a run. Loads computed from other fields,
grid geometry, distances and areas are not independent initial conditions.
Forcing accepts prescribed atmospheric and ocean fields rather than evolving
ice fields. Definitions copy input arrays and mappings and prevent changes in
place, so editing the original inputs does not change the definition.
The accepted field names below are generated from the input sets used by the
code. Inputs must contain finite real values, with no infinities or undefined
numerical values. Ice/snow thickness, wind speed and salinity are nonnegative.
Temperatures in kelvin are positive, and concentration Area lies in [0, 1].
Initial conditions and constant forcing are single values or physical 2D arrays.
Series put time in the first dimension, as described above. load_fields
accepts any of these names from serial records sampled at a single instant.
Geometry, masks and independent grid distances and areas require initialization.
Name |
Units |
Description |
|---|---|---|
|
1 |
Sea ice cover fraction |
|
K |
Ice/ snow surface temperature |
|
m |
Mean ice thickness |
|
m |
Mean snow thickness |
|
N m-1 |
Stress trace sigma11 + sigma22 |
|
N m-1 |
Stress tensor component |
|
N m-1 |
Normal-stress difference sigma11 - sigma22 |
|
m s-1 |
Zonal ice velocity |
|
m s-1 |
Meridional ice velocity |
Name |
Units |
Description |
|---|---|---|
|
K |
Atmospheric temperature |
|
W m-2 |
Downward longwave radiation |
|
W m-2 |
Net heat flux out of the ocean |
|
W m-2 |
Surface shortwave heatflux (+ = upwards) |
|
W m-2 |
Downward shortwave radiation |
|
kg kg-1 |
Atmospheric specific humidity |
|
m s-1 |
Evaporation rate over open ocean (freshwater flux, <0 increases salinity) |
|
g kg-1 |
Ocean surface salinity |
|
m s-1 |
Precipitation rate (freshwater flux) |
|
m s-1 |
Runoff into ocean |
|
m s-1 |
Snowfall rate |
|
m |
Sea surface height anomaly |
|
Pa |
Surface pressure |
|
K |
Ocean surface temperature |
|
m s-1 |
Zonal ocean surface velocity |
|
m s-1 |
Zonal wind velocity |
|
m s-1 |
Meridional ocean surface velocity |
|
m s-1 |
Meridional wind velocity |
|
m s-1 |
Total wind speed |
User-supplied OceanGeometry uses physical arrays without halos. maskT,
maskU and maskV have shape (nx, ny, z). The last dimension must be
nonempty, and the last level holds the surface masks. Masks mark wet cells with
values in [0, 1]; zero means dry. dxt/dxu are positive x-spacing vectors
of length nx. dyt/dyu are positive y-spacing vectors of length ny.
All spacings are in meters. area_t, area_u and area_v are positive
(nx, ny) areas in m². ht is the existing signed bottom elevation in
meters; coriolis_t is a frequency in s⁻¹. Initialization uses the established
equations for ocean grid distances and areas, closes blocked velocity faces,
and computes load and inverse thickness with regularization to handle thin ice.
Fractional wet masks retain supplied ice amounts averaged over each cell.
Explicit TSurf initial conditions override the grid’s default temperature.
A custom runnable experiment requires geometry. Creating arrays from defaults
alone does not define one.
Builtins are island, dynamics and growth. Their scenario controls use
the maintained setup tables. Grid supplies dimensions; scenario does not
also accept nx, ny, steps or dtype. Island initialization keeps initial
Qnet/Qsw coupling outputs at zero and queues prescribed heat for each
timestep. Growth feeds computed heat fluxes into later steps unless heat is
explicitly prescribed. Explicit winds determine wSpeed unless it is
supplied separately.
Series override constants with the same field name. forcing.at(0) selects
the first step’s prescribed inputs without advancing a position tracker through
the series. A missing field keeps its current State value, allowing computed heat
fluxes to feed into later steps. Veris checks spatial shapes, series lengths
and configured duration before execution. Requesting a position beyond the
series raises an exhaustion error.
Physics modes are coupled, dynamics and thermodynamics. Dynamics
computes ice motion and transport; thermodynamics computes freezing and melting.
Coupled mode combines both and requires equal dynamics and thermodynamic
timesteps. Model time uses the active timestep and microsecond precision on
the host. Unsupported sub-microsecond values and clock overflow produce clear
errors. backend=None honors the caller’s JAX selection. cpu and gpu
request resources; initialization determines which devices are available.
Explicit meshes¶
All builtins and custom geometry, initial fields and forcing use the same public
initializer for arrays split across devices. For example, start a fresh Python
process with JAX_NUM_CPU_DEVICES=2 before importing JAX, then run:
import jax
from veris import Execution, Experiment, Grid, Simulation
mesh = jax.make_mesh((2, 1), ("x", "y"), devices=jax.devices("cpu"))
experiment = Experiment.builtin(
"island", grid=Grid(12, 8), steps=2,
settings={"dtype": "float32", "nEVPsteps": 2},
execution=Execution(backend="cpu", partitions=(2, 1)),
)
with Simulation.initialize(experiment, mesh=mesh) as simulation:
result = simulation.run()
simulation.snapshot("sharded-final.nc", variables=("hIceMean", "Area"))
Input arrays keep their full-grid physical shapes. Each process initializes only the packed State regions it can access. Spatial series split only the spatial dimensions; their time axis stays whole. The caller keeps ownership of the mesh. For multiple processes, initialize JAX distributed services before listing devices and keep responsibility for closing those services. See Parallel dynamics. Complete distributed restart is unsupported. Checks of local CPU sharding do not establish correctness on GPUs or across multiple computers; those need their own verification.
Definitions are constructed only on the host. The pure numerical API consists
of veris.advance for one timestep and veris.step() to repeat timesteps
without Python side effects. See Scan rollouts and checkpointing for JIT, which
compiles functions for execution, and differentiation, which measures how
results change with inputs. JAX can compute derivatives with respect to initial
State and supplied JAX forcing arrays. Fixed definitions, settings, constants
and host input checks stay outside that path.
- class veris.model.experiment.Grid(nx: int = 8, ny: int = 12)[source]¶
Bases:
objectGlobal physical grid extents in (x, y) order, excluding all halos.
Staggered center/face/corner fields share the same storage lengths. Existing Configuration nx/ny still describe local physical cells per partition.
- class veris.model.experiment.Execution(backend: str | None = None, partitions: tuple[int, int] = (1, 1), distributed: DistributedExecution | None = None, all_devices: bool = False)[source]¶
Bases:
objectExecution resource request, separate from static numerical settings.
backend=None honors the caller’s JAX choice; cpu/gpu requests that backend. Partitions specify the explicit x/y mesh shape, with (1,1) serial by default. Construction never initializes distributed JAX or enumerates devices.
- class veris.model.experiment.Experiment(grid: Grid = _DefaultInput.SHARED, settings: Mapping[str, ~typing.Any]=<factory>, constants: Mapping[str, ~typing.Any]=<factory>, physics: str = _DefaultInput.SHARED, geometry: OceanGeometry | None = None, initial_conditions: Mapping[str, ~typing.Any]=<factory>, forcing: Forcing = <factory>, execution: Execution = _DefaultInput.SHARED, steps: int = _DefaultInput.SHARED, output: OutputSettings | None = _DefaultInput.SHARED, preset: str | None = None, profile: str | None = None, scenario: Mapping[str, ~typing.Any]=<factory>)[source]¶
Bases:
objectOne experiment’s independent numerical, physical, input and host controls.
settings, constants, scenario and forcing retain authored inputs. Inherited defaults and dtype-normalized values live in configuration, physical_constants, resolved_settings, resolved_scenario and resolved_forcing. with_overrides merges authored values before resolving them again, preserving shared defaults < preset < configuration < explicit overrides precedence. Grid owns global nx/ny; Execution owns use_sharding. Physical constants inherit the numerical dtype. Initial conditions and forcing use global physical arrays without halos, in VARIABLES units. Geometry is host input to runnable initialization, rather than an array default allocation.
physics selects coupled, dynamics or thermodynamics. Coupled execution requires equal dynamics and thermodynamic timesteps; subcycling is not implied. steps specifies the total requested trajectory. output=None disables scheduled output. Definition construction allocates no model/device arrays.
- classmethod builtin(name: str, **options: Any) Experiment[source]¶
Define a registered scientific preset using its authoritative defaults.
Grid defaults come from the public Grid registry, except the growth column uses its scenario’s 2 by 2 grid. Explicit options override preset settings; scenario contains only experiment-specific coefficients.
- classmethod from_file(path: str | Path, *, overrides: Mapping[str, Any] | None = None) Experiment[source]¶
Read versioned JSON with registry < file < Python override precedence.
- to_dict(*, mode: str = 'resolved') dict[str, Any][source]¶
Export pinned resolved values or sparse authored controls as fresh JSON data.
- with_overrides(overrides: Mapping[str, Any]) Experiment[source]¶
Merge explicit grouped overrides into authored inputs and revalidate.
Shared defaults < preset < authored configuration < these overrides. Nested mappings merge by key; arrays, sequences, None and scalar values replace whole values. The preceding definition remains unchanged.
- class veris.model.forcing.Forcing(constant: Mapping[str, ~typing.Any]=<factory>, series: Mapping[str, ~typing.Any]=<factory>)[source]¶
Bases:
objectImmutable constant and timestep-indexed prescribed field values.
Constants accept scalars or (nx, ny) arrays. Series accept (time,) or (time, nx, ny) arrays and override constants of the same name. All series share a nonzero length. Fields absent from both groups keep their current State value, allowing legacy recursive heat fluxes. Values use VARIABLES units, including kelvin and positive-upward Qnet/Qsw in W m-2.
Export modes¶
experiment.to_dict() defaults to mode="resolved" and fixes all values
that the model will use, including the profile identity. mode="authored"
keeps only the caller’s supplied inputs, leaving omitted groups and values
omitted. Reading authored data and then changing dtype/scenario recomputes
inherited defaults. Resolved data keeps the deliberately fixed literal values.
Both return independent data suitable for JSON. Derived single values are
reconstructed from the stored inputs. Returned arrays and containers do not
share storage with the definition. Schema version 1 remains supported;
profile/distributed/all-device declarations use version 2. Use veris inspect
to inspect or export from the command line without selecting devices.