tracmass.runsetup#

Resolve settings-driven arguments of the integrators.

Covers monitor / recorder (lifecycle-managed here via manage_run_io()) and no_wflux (a plain bool derived from the move_vertically setting via resolve_no_wflux()).

The multi-window integration routines (time_dependent(), time_dependent_patched(), time_dependent_streaming()) each accept a monitor and a recorder argument. Historically the caller had to build a RunMonitor / ParticleRecorder and drive its context manager by hand:

with (RunMonitor(backend="rich") as mon,
      ParticleRecorder("run.parquet") as rec):
    tracmass.time_dependent_patched(..., monitor=mon, recorder=rec)

The manage_run_io() decorator removes that boilerplate. Applied to an integrator it accepts the same two arguments in any of four forms and owns the lifecycle of whatever it constructs itself:

value

behaviour

an instance

used as-is; the caller owns its lifecycle

a str

RunMonitor(backend=...) / ParticleRecorder(...) built here and entered on an ExitStack

None

feature disabled

omitted (_UNSET)

built from tracmass.config settings and entered on the ExitStack

“Entered on the ExitStack” means the object’s __exit__ runs automatically when the integrator returns or raises, so a with block around the call is no longer required.

Settings keys consulted for the omitted (_UNSET) case#

runmonitor_backend

Backend for the auto-built RunMonitor ("print", "log", or "rich"). Default "print".

output_name

Filename stem for the auto-built recorder. Setting it also enables auto-recording. Default stem when auto-recording via auto_record: trm_{active-env}.

auto_record

Truthy value enables auto-recording even when output_name is unset.

base_output_dir

Directory the auto-built recorder writes into. Default: current directory.

use_sub_folder

When truthy, the auto-built recorder writes into a sub-directory of base_output_dir named after output_name, else the active environment. Default False. Missing directories are created.

The auto-built filename is {stem}_{forward|reverse}_{dtm_start.date()}.parquet — the direction token comes from grid.reverse and the date from fluxes.dtm.

When neither output_name nor auto_record is set, an omitted recorder resolves to None (no trajectory file) — the historical default.

Vertical advection#

move_vertically

When an integrator’s no_wflux argument is not passed explicitly, resolve_no_wflux() sets no_wflux = not move_vertically from this setting (default True — particles do move vertically, matching the historical no_wflux=False default). An explicit no_wflux= always wins. The ECCO2 adapter reads the same setting for its include_wflux argument (see tracmass.config.move_vertically()).

Particle batching#

n_particle_batches

When an integrator’s n_particle_batches argument is not passed explicitly, resolve_n_particle_batches() takes it from this setting (default 1 — no batching). An explicit value always wins; both are clamped to >= 1. The full-grid integrators (steady_state(), time_dependent()) act on it with a particle-batched lax.while_loop; the streaming integrators accept it for API symmetry only.

Ramp-up saves#

rampup_windows / rampup_substeps

When an integrator’s rampup_windows / rampup_substeps arguments are not passed, resolve_rampup() takes them from these settings (defaults 0 — no ramp-up — and 5). During the first rampup_windows windows positions are also saved rampup_substeps - 1 times inside each window, as event_type="rampup" rows; rampup_metadata() describes the resulting save times in the trajectory file.

tracmass.runsetup.resolve_no_wflux(no_wflux)[source]#

Normalise an integrator no_wflux argument to a plain bool.

Parameters:

no_wflux (bool or _UNSET) – An explicit bool is returned unchanged (the caller always wins). _UNSET (the argument was omitted) is resolved from settings as not move_vertically() — see tracmass.config.move_vertically().

Returns:

bool

Return type:

bool

tracmass.runsetup.resolve_n_particle_batches(n_particle_batches)[source]#

Normalise an integrator n_particle_batches argument to a plain int.

Parameters:

n_particle_batches (int or _UNSET) – An explicit value is returned as max(1, int(...)) (the caller always wins). _UNSET (the argument was omitted) is resolved from the n_particle_batches setting — see tracmass.config.n_particle_batches() (default 1).

Returns:

int – Batching factor, clamped to >= 1.

Return type:

int

tracmass.runsetup.resolve_rampup(rampup_windows, rampup_substeps)[source]#

Normalise the integrators’ ramp-up arguments to (windows, substeps).

Parameters:
  • rampup_windows (int or _UNSET) – Number of leading windows saved more often. _UNSET → the rampup_windows setting, default 0 (no ramp-up).

  • rampup_substeps (int or _UNSET) – Saves per window during ramp-up (5 → every timestep / 5). _UNSET → the rampup_substeps setting, default 5.

Returns:

tuple[int, int] – (rampup_windows, rampup_substeps); (0, 1) when ramp-up is off (either is 0 / 1).

Raises:

ValueError – If either is negative / below 1, or not an integer.

Return type:

tuple[int, int]

tracmass.runsetup.window_ends(win, rampup_windows, rampup_substeps)[source]#

Normalised times at which window win stops to save positions.

[win + 1] normally; [win + 1/k, win + 2/k, ..., win + 1] with k = rampup_substeps during the first rampup_windows windows. All but the last are ramp-up saves; the last is the next window’s snapshot.

Parameters:
  • win (int)

  • rampup_windows (int)

  • rampup_substeps (int)

Return type:

list[float]

tracmass.runsetup.rampup_metadata(n_windows, timestep_seconds, rampup_windows, rampup_substeps)[source]#

Run-metadata keys describing when positions are saved.

Returns:

dict – rampup_windows, rampup_substeps and save_dt_seconds: the time between consecutive saved positions (snapshot and rampup rows, in file order), one entry per interval, so the n-th save is at sum(save_dt_seconds[:n]) after the start. Covers the planned n_windows; a run that stops early (no active particles left) saves fewer.

Parameters:
  • n_windows (int)

  • timestep_seconds (float)

  • rampup_windows (int)

  • rampup_substeps (int)

Return type:

dict

tracmass.runsetup.resolve_n_windows(n_windows, fluxes)[source]#

Normalise an integrator n_windows argument to a plain int.

Parameters:
  • n_windows (int or None) – An explicit value is returned unchanged (the caller always wins). None is resolved from fluxes.n_windows — the number of windows from fluxes.dtm to the dtm_end given to tracmass.gcm.new_flux() — falling back to 1 when no dtm_end was given (or fluxes is not a LazyFluxFields).

  • fluxes (LazyFluxFields or FluxFields) – The flux buffer passed to the integrator.

Returns:

int

Return type:

int

tracmass.runsetup.resolve_seed_freq(seed_freq)[source]#

Normalise an integrator seed_freq argument.

Parameters:

seed_freq (str or None or _UNSET) – A pandas frequency ("30D", "MS", …) or None (seed once) is returned unchanged; the caller always wins. _UNSET (the argument was omitted) is resolved from seed_freq in the [env.seed] settings table, default None.

Returns:

str or None – The frequency, or None when particles are seeded only at the start (also for an empty string or false).

Return type:

str | None

tracmass.runsetup.seed_windows(seed_freq, dtm_start, timestep, n_windows, reverse=False)[source]#

Windows at whose start a repeat seed is released.

The seed times are dtm_start stepped by the pandas offset seed_freq — forward in time, or backward for a backward run — and each is placed on the window that starts at it. A seed time inside a window moves to the start of the next window. The initial seed (window 0) is not included.

Parameters:
  • seed_freq (str or None) – Pandas frequency string, e.g. "30D", "7D", "MS" (month starts) or "QS". None → no repeat seeds.

  • dtm_start (str or pd.Timestamp) – Start time of window 0.

  • timestep (pd.Timedelta or datetime.timedelta) – Window length.

  • n_windows (int) – Number of windows in the run; seeds at or after its end are dropped.

  • reverse (bool, optional) – Backward run (windows step back in time). Default False.

Returns:

list of int – Sorted, unique window indices, all in 1 .. n_windows - 1.

Raises:

ValueError – If seed_freq is not a valid pandas frequency.

Return type:

list[int]

Examples

>>> seed_windows("10D", "2010-06-01", pd.Timedelta("1D"), 30)
[10, 20]
>>> seed_windows("MS", "2010-06-15", pd.Timedelta("1D"), 40)
[16]
tracmass.runsetup.reseed(state, seed, win, tseas)[source]#

Append a copy of seed released at the start of window win.

The copy’s clock is moved forward by win windows (tt and t0 by win * tseas seconds, ts by win) and its iteration counter is reset, so it starts as a fresh set of particles at that time. Active flags and reasons come from seed (particles seeded inactive stay so).

Parameters:
  • state (ParticleState) – Current state of the run.

  • seed (ParticleState) – The run’s initial state, as passed to the integrator.

  • win (int) – Window index of the release.

  • tseas (float) – Window length in seconds.

Returns:

ParticleState – ParticleState.concat(state, shifted_seed): existing particles keep their indices (and output id), the new ones follow.

tracmass.runsetup.seed_metadata(seed_freq, windows)[source]#

Run-metadata keys describing repeat seeding.

Returns:

dict – seed_freq and seed_windows (the windows of the repeat releases, without the initial one at window 0); empty when seed_freq is None.

Parameters:
Return type:

dict

tracmass.runsetup.traj_max_seconds(traj_max_time, dtm_start=None, reverse=False)[source]#

Convert a trajectory lifetime to seconds.

Parameters:
  • traj_max_time (str or pd.Timedelta or float or None) – The longest a particle may live, counted from its release. A pd.Timedelta string ("30D", "12h", "2W"), or calendar months / quarters / years as "M", "Q", "Y" with an optional count ("1M", "6M", "2Y"). A number is taken as seconds; None means no limit.

  • dtm_start (str or pd.Timestamp, optional) – The run’s start time. Calendar units have no fixed length, so they are measured from here (backward for a backward run): "1M" from 2010-02-01 is 28 days. Needed only for calendar units.

  • reverse (bool, optional) – Backward run.

Returns:

float – Lifetime in seconds (1e20 for no limit).

Raises:

ValueError – If traj_max_time cannot be parsed, is not positive, or is in calendar units without dtm_start.

Return type:

float

tracmass.runsetup.resolve_timax(timax_seconds, traj_max_time, dtm_start=None, reverse=False)[source]#

Resolve the trajectory lifetime of an integrator call.

Parameters:
  • timax_seconds (float or _UNSET) – Lifetime in seconds. An explicit value wins.

  • traj_max_time (str or None or _UNSET) – Lifetime as a pandas-style string, see traj_max_seconds(). _UNSET is resolved from the traj_max_time setting, default no limit.

  • dtm_start (str or pd.Timestamp, optional) – The run’s start time, for calendar units.

  • reverse (bool, optional) – Backward run.

Returns:

tuple[float, dict] – timax_seconds and run-metadata keys (traj_max_time and timax_seconds; empty without a limit).

Raises:

ValueError – If both arguments are given explicitly.

Return type:

tuple[float, dict]

tracmass.runsetup.resolve_monitor(monitor, stack)[source]#

Normalise monitor to a RunMonitor instance or None.

Parameters:
  • monitor (RunMonitor or str or None or _UNSET) – See the module docstring for the four accepted forms.

  • stack (contextlib.ExitStack) – A monitor constructed here is registered on this stack so its __exit__ runs when the integrator returns or raises. A monitor passed in by the caller is returned untouched.

Returns:

RunMonitor or None

Return type:

RunMonitor | None

tracmass.runsetup.resolve_recorder(recorder, stack, *, dtm_start=None, reverse=False)[source]#

Normalise recorder to a ParticleRecorder instance or None.

Parameters:
  • recorder (ParticleRecorder or str or os.PathLike or None or _UNSET) – See the module docstring for the four accepted forms.

  • stack (contextlib.ExitStack) – A recorder constructed here is registered on this stack so its Parquet writer is closed when the integrator returns or raises. A recorder passed in by the caller is returned untouched.

  • dtm_start (pandas.Timestamp or datetime-like, optional) – Start timestamp of the run, used only for the auto-built filename.

  • reverse (bool, optional) – Direction of the run (grid.reverse). Selects the forward / reverse token in the auto-built filename. Default False.

Returns:

ParticleRecorder or None

Return type:

ParticleRecorder | None

tracmass.runsetup.run_metadata(fn, grid, fluxes)[source]#

Describe a run for the "tracmass.run" metadata of its trajectory file.

Parameters:
  • fn (callable) – The integrator; its name is stored as integrator.

  • grid (GridFields) – Supplies the run direction and time step.

  • fluxes (LazyFluxFields or FluxFields) – Supplies the start / end time and the GCM adapter (fluxes_fn).

Returns:

dict – JSON-serialisable; keys whose value is unknown are left out:

gcm

Adapter name ("glorys", "ecco2", …) when fluxes_fn is a tracmass.gcm adapter, else fluxes_fn ("module.qualname") for a custom flux function.

gcm_product

The adapter’s data product (tracmass.seagrid.<gcm>.settings ["product"]), e.g. "glorys12v1".

gcm_subset

The adapter’s subset setting, unset edges left out.

env

Active tracmass.toml environment.

integrator

Name of the integrator function.

direction

"forward" or "reverse".

dtm_start, dtm_end, timestep_seconds

Time span of the run and the GCM timestep.

tracmass_version, created

Package version and creation time (UTC, ISO 8601).

Return type:

dict

tracmass.runsetup.manage_run_io(fn)[source]#

Decorate an integrator to own its monitor / recorder lifecycle.

The wrapped function is always called with monitor and recorder already normalised to an instance or None (via resolve_monitor() / resolve_recorder()), with verbose debug output on if the verbose setting is true (tracmass.verbose), wrapped in a contextlib.ExitStack that closes any object constructed on the caller’s behalf when the integrator returns or raises. The function body no longer interprets sentinels or constructs these objects itself.

Parameters:

fn (callable) – An integrator called as fn(state, grid, fluxes, ...) — grid supplies the run direction (grid.reverse) and fluxes the run start timestamp (fluxes.dtm) for the auto-built recorder filename — and which accepts keyword-only monitor and recorder parameters. The recorder’s grid_offset is set from grid.i_offset / grid.j_offset so it writes full-grid positions, and run_metadata() is added to its metadata (keys already there are kept).

Returns:

callable – Wrapper carrying fn’s name, docstring and signature via functools.wraps().

Return type:

Callable