conatus.model.Simulation¶
- class conatus.model.Simulation(comp, *, scheme, dt, backend='cpu', **solver_kw)[source]¶
Bases:
objectTime integration of a compiled IVP (
Model.simulate): scheme and dt are explicit.- Parameters:
comp (Compiled)
scheme (str)
dt (float)
backend (str)
solver_kw (Any)
- property t: float¶
Current simulation time.
- property dt: float¶
Time step (fixed at
simulate; the run never changes it on its own: only an explicit Studioseton a step declared settable bywatch(settable=...), recorded).
- property iteration: int¶
Number of steps taken.
- initial(*, layout=None, check=True, t=None, **values)[source]¶
Initial state by unknown name: callables of coordinate names (
T=lambda x, z: -z, preferred: unambiguous), numbers, or arrays of grid values with exactly the shape ofsim.grid(name)(e.g. the state of another simulation at the same N; the layout is the grid ofgrid(), components first, then the coordinates in order, i.e.np.meshgrid(x, z, indexing="ij")); unknowns not given start at zero (declared by explain()).On a grid with two axes of the same size the shape cannot tell
indexing="ij"from NumPy’s default"xy"(transposed): such an array is refused unless it is one returned bysim.grid(...)orlayout="ij"declares it.Callable data are checked (
conatus.model.initial_check): non-finite values are refused, and so are clearly wrong data (relative spectral tail beyond the resolution aboveINITIAL_TAIL_REFUSEon some axis, or a jump at the ends of a periodic axis: an aliased mode, a function not periodic on the box), naming the axis; data that are only not fully resolved (tail betweenINITIAL_TAIL_TOLandINITIAL_TAIL_REFUSE, e.g. the coarse N of a resolution study) give oneInitialDataWarning, recorded byexplain().check=Falsesilences both (declared byexplain()).t: the time at which this state is given (default 0). Time-dependent forcing and boundary data are evaluated from it, every output row and checkpoint carries times t + k dt,run(until=...)is read on that clock, checkpoints record it (a chain continued byresume_or_start()with anothertis refused) andexplain()states it. In a model with an unknown namedt(which then has no time),t=is that unknown’s data.- Parameters:
layout (str | None)
check (bool)
t (Any)
values (Any)
- Return type:
- run(until=None, *, steps=None, callback=None, every=None, record=None, cache=False, on_stop='raise')[source]¶
Advance to time
until(must be a whole number of steps: dt is never changed) or bystepssteps.callback(sim)runs everyeverysteps (both or neither), with this Simulation as argument, like the functions ofwatch()(the expertIVPSolver.runpasses the solver). A watched simulation (watch()) also calls the watch everypollsteps; astopfrom the Studio raisesStopRunout of here (the run ends where it is).record/cache: the run registry, asIVPSolver.run(conatus.runs): withrecordgiven, the recorded run is returned; otherwise this Simulation (chaining).on_stop: what a Studiostopdoes:"raise"(default, v0.1) raisescn.StopRunout of here;"return"ends the run where it is and returns normally, so that the post-processing afterrun()still runs (sim.stoppedthen holds the reason).- Parameters:
until (float | None)
steps (int | None)
callback (Callable | None)
every (int | None)
record (Any)
cache (bool)
on_stop (str)
- watch(run_id, *, film=None, stats=None, every_s=0.5, scalars_every_s=0.25, poll=10, film_mb=256.0, max_px=384, max_px3d=48, spool=None, checkpoint_dir=None, meta=None, controls_every_s=1.0, settable=None)[source]¶
Make the run visible live in the Studio, with its film.
film: the views, a list of field names (["T", "u.x"]) or{name: source}with a source = a field name, a functionf(sim)orcn.view(...)(scale, slice, 3D mode); the first is the default view.stats:{name: f(sim) | cn.series(...) | cn.spectrum(...) | cn.profile(...)}.every_s: wall seconds between two frames of a view;scalars_every_s: between two evaluations of the numbers;poll: steps between two calls of the watch;controls_every_s: wall seconds between two reads of the Studio commands.settable={"dt": (lo, hi)}: the time step may be changed from the Studio or an agent (commandset, bounds checked, Runge-Kutta schemes only: a multistep scheme, SBDF* or CNAB*, is refused withsettablebecause its history was built with one dt; recorded as an event). Note the units:every_s,scalars_every_sandcontrols_every_sare wall-clock seconds,pollis in steps (output(every=)andcheckpoints(every=)count steps). The Studio shows nothing else (no hidden physics); the numbers of the run are unchanged (tests/studio/test_watch.py). Defaults are declared byexplain(). Returns theWatch.- Parameters:
run_id (str)
film (Any)
stats (Mapping[str, Any] | None)
every_s (float)
scalars_every_s (float)
poll (int)
film_mb (float)
max_px (int)
max_px3d (int)
spool (str | Path | None)
checkpoint_dir (str | Path | None)
meta (Mapping[str, Any] | None)
controls_every_s (float)
settable (Mapping[str, Any] | None)
- output(path, tasks, *, every, mode=None, initial=True)[source]¶
Write
tasksto the HDF5 analysis filepatheveryeverysteps duringrun()(cn.io.AnalysisFile):["T", "u.x"](grid values of unknowns or components) or{name: name | f(sim)}.initial(default True): the state at the start of the nextrun()is written too (the row of t = 0 on a fresh start; never twice: a resumed chain already holds it), declared by explain();initial=False: the first row is at iterationevery.modeis required if the file exists ("w"replaces,"a"appends,"resume"appends after a restart from an older checkpoint, dropping the rows after the current iteration: declared by explain()). Rows holdsim_time,iterationand the provenance of the run; read back withcn.io.read(path).- Parameters:
path (str | Path)
tasks (Any)
every (int)
mode (str | None)
initial (bool)
- particles(positions, *, path=None, every=None, velocity='u', at_walls='refuse', mode=None, initial=True)[source]¶
Passive tracer particles advected during
run()(conatus.model.particles).positions: (P, d) in coordinate order or{coord: array}. The velocity at a particle is the exact spectral series ofvelocityat its position; each flow step advances the particles by one RK4 step, the midpoint velocity interpolated in time (cubic, last four flow states): order 4 in a steady flow, 3 in an unsteady one. Periodic axes: unwrapped positions (also written wrapped).at_walls:"refuse"(a step ending outside the walls raises) or"clip"(put back on the wall, counted).path+every: an HDF5 file of thecn.iolayout (position, position_unwrapped, velocity, wall_clips; dims t, particle, component;modeandinitialasoutput()). Cartesian boxes, CPU and GPU. Returns theTracers(positions(),velocities(),explain()).- Parameters:
positions (Any)
path (str | Path | None)
every (int | None)
velocity (str)
at_walls (str)
mode (str | None)
initial (bool)
- dye(name, path, *, every, mode=None, initial=True, field=True)[source]¶
Write the dye
name(declared bym.dye, or any scalar unknown) and its conservation diagnostics everyeverysteps duringrun()(conatus.model.dye.DyeFile): grid values (field=True),mass= integ(c),variance,minimum,maximumand the spectraltail;modeandinitialasoutput(). Read back withcn.io.read(path).- Parameters:
name (str)
path (str | Path)
every (int)
mode (str | None)
initial (bool)
field (bool)
- checkpoints(directory, *, every, keep=2, grids=False)[source]¶
Exact restart files
directory/checkpoint_<iteration>.h5everyeverysteps duringrun(), thekeepmost recent kept (cn.io.CheckpointSeries; defaultconatus.io.checkpoint.CHECKPOINT_KEEP= 2: the latest and the one before it). The next job resumes withsim.restart(cn.io.latest(directory)).- Parameters:
directory (str | Path)
every (int)
keep (int)
grids (bool)
- properties(*, every, **props)[source]¶
Global flow properties evaluated every
everysteps duringrun()(the role of Dedalus’GlobalFlowProperty):props.max("Re"),min,grid_average,volume_average,integral. A property is an unknown or component name or a functionf(sim)of grid values (conatus.diagnostics.properties).- Parameters:
every (int)
props (Any)
- save(path, *, grids=False)[source]¶
Checkpoint now: state, multistep history and clock (
.h5: HDF5 with provenance, readable bycn.io.read;.npz: NumPy). A restart continues bit-for-bit. A suffix naming another format (.hdf,.nc, …) is refused: it used to be written as a NumPy file with.npzappended (review of the inputs audit).- Parameters:
path (str | Path)
grids (bool)
- Return type:
Path
- restart(path, *, allow=())[source]¶
Continue from a checkpoint (
save/checkpoints); the scheme, dt, resolution and options must be those of the file (checked, never adapted), and so must the model, its equations, its parameters and its box: a difference is refused with the list of what differs.allownames what may differ deliberately, e.g.allow=("kappa",)to continue this state at a new kappa (also"parameters","model","equations","geometry"); it is printed byexplain()and carried by every later checkpoint.None(whatcn.io.latestreturns for an empty directory) is refused with an explanation.- Parameters:
path (str | Path | None)
allow (Any)
- Return type:
- resume_or_start(directory, *, allow=(), check=True, t=None, **initial)[source]¶
One script for every job of a chain: continue from the latest checkpoint of
directory(cn.io.latest) if it holds one, else start frominitial(asinitial(); the directory is created). Afterwards anoutput()withoutmodecreates its file on a fresh start ("w"; an existing file is refused, never replaced silently:mode="w"replaces it explicitly) and continues it after a restart ("resume": rows written after the checkpoint are dropped, the exact restart writes them again). Which branch was taken, and each output’s mode, are declared byexplain(). Call it beforeoutput()andcheckpoints(). The checkpoint must be a state of this run (model, equations, parameters, resolution, box:restart();allow=names what may differ);checkis passed toinitial()on a fresh start. Both checkpoint formats are found (checkpoint_*.h5andcheckpoint_*.npz).t: the start time of a fresh start (initial()); on a resume it must be the start time recorded by the chain’s checkpoints (refused otherwise: the script would describe another run).- Parameters:
directory (str | Path)
allow (Any)
check (bool)
t (Any)
initial (Any)
- Return type:
- unwatch()[source]¶
Stop watching: the final status is sent and the telemetry writer stops.
- Return type:
None
- flowmap(T, *, t0=None, checkpoints=None)[source]¶
Exact discrete tangent and adjoint of this simulation over the horizon
T(conatus.adjoint.FlowMap:jvp,vjp, Revolve withcheckpointsslots;t0required when the equations depend on time). The state vectors are those ofsim.solver(sim.solver.X); the tau unknowns are carried, never shown. Calling the map,Φ(X0), leaves this simulation where it was (state, time, iteration, multistep history): the map runs the solver and puts them back (review of the state audit, F6:sim.flowmap(T)(X0)used to move the simulation to X_N at time t0 + T).- Parameters:
T (float)
t0 (float | None)
checkpoints (int | None)
- nlop(*, T, E0, fields=None, t0=None, checkpoints=None, **kw)[source]¶
Nonlinear optimal perturbation of this simulation (
NLOP.from_solver): maximise the energy ½∫|u|² dV at time T over seeds of energyE0.fields: the velocity unknowns by default (declared withm.velocity); pressure and taus never enter the energy.- Parameters:
T (float)
E0 (float)
fields (tuple[str, ...] | None)
t0 (float | None)
checkpoints (int | None)
kw (Any)
- lyapunov(n_vectors, *, transient, align, T, reortho_every, inner, n_blocks, seed, starts=None, zero_mean=(), project=None, covariant=False, clv_window=None, clv_backward=None, clv_every=1, clv_checkpoints=None, progress=None)[source]¶
Lyapunov exponents (and covariant Lyapunov vectors) of this simulation’s discrete map (
conatus.chaos.lyapunov_spectrum): then_vectorsleading exponents with their standard errors, from the exact tangent of the step (same scheme, same dt), on one or several trajectories integrated as one batch (CPU or GPU, the backend of the simulation). Durations are times, each a whole number of steps (transient,align) or of intervalsreortho_every * dt(T,clv_window,clv_backward), never rounded:transient: trajectory only;align: trajectory and tangent vectors (alignment, no averaging);T: averaging time per trajectory, inn_blocksblocks;inner:"euclidean"(on the state vector of coefficients) or a positive diagonal weight;seed: the random initial tangent vectors;starts: None (the current state), an array (B, n) of states, or a list ofsim.initialkeyword dicts (B trajectories); the simulation’s state is not advanced;zero_mean=("u",): tangent vectors restricted to zero mean for these unknowns (all axes periodic: the invariant subspace of conserved means, e.g. Kuramoto–Sivashinsky), orproject=f(V -> P V) for another invariant subspace;covariant=True: the CLVs of Ginelli et al. (2007) over a window of lengthclv_windowendingclv_backwardbefore the end (backward transient), kept everyclv_everyinterval;clv_checkpoints=sbounds the memory (s checkpoints and one recomputation, seelyapunov_spectrum).
The result (
LyapunovResult) hasexplain()(exponents ± errors, Kaplan–Yorke dimension, CLV memory, covariance residual, principal angles),angles(j),pair_angle(i, j),domination(tau)(domination of the Oseledets splitting, entangled clusters, physical-mode count) andclv_grid(name, i)(a CLV as grid values).- Parameters:
n_vectors (int)
transient (float)
align (float)
T (float)
reortho_every (int)
inner (Any)
n_blocks (int)
seed (int)
starts (Any)
zero_mean (Any)
project (Callable | None)
covariant (bool)
clv_window (float | None)
clv_backward (float | None)
clv_every (int)
clv_checkpoints (int | None)
progress (Callable | None)
- grid(name)[source]¶
Values of an unknown on the grid (
coordinate(c)gives the points). On a sine/cosine axis only the physical interval [a, b] is returned (N + 1 points, both walls included), not the doubled period.- Parameters:
name (str)
- Return type:
ndarray
- evaluate(expr)[source]¶
Grid values of an expression of the current state written as in the equations (
"dz(T)","0.5*u@u","Ra*T - p"): unknowns, given fields, parameters and the timet; on the grid ofgrid()(constant directions broadcast). An expression constant in space (a full integral"integ(u@u)/2", a parameter) is returned as a number (Python float or complex; a vector: its components), not as a grid array. The pseudospectral products are those of the right-hand side (dealiased grid, then the first N modes kept). Cartesian geometries (the curvilinear evaluators keep their own layouts: refused there).- Parameters:
expr (str)
- Return type:
Any
- coordinate(name)[source]¶
Grid points of coordinate
namematchinggrid()(a sine/cosine axis: the N + 1 points of [a, b]; disk, annulus, pipe, sphere, ball, shell: the solver’s own grids).- Parameters:
name (str)
- Return type:
ndarray
- coeffs(name)[source]¶
Spectral coefficients (expert layout; a sine/cosine axis: the RealFourier(2N) coefficients of the doubled period, cos/-sin pairs, half of them zero by parity).
- Parameters:
name (str)
- Return type:
ndarray
- cfl(velocity='u', safety=REQUIRED)[source]¶
CFL time step of the current state (a stability indicator, not an error control).
safetyhas no default (REQUIREDinhelp()): it scales the returned step (0.5 before v0.1).- Parameters:
velocity (str)
safety (float)
- Return type:
float
- explain(*, full=False)[source]¶
The run in a few lines: resolution, scheme, time step, backend, the summary of the model’s decisions, the initial state, the checks, outputs and warnings.
full=True: every automatic decision of the compiled model (term-by-term split, taus and their modes, gauge, bases) and the whole solver layout.- Parameters:
full (bool)
- Return type:
str