astronomix.time_stepping._time_loop#
Generic JAX time-integration loop driver.
Repo-agnostic: depends only on jax (and equinox’s checkpointed while loop
for reverse-mode-friendly adaptive integration). It owns the parts of a
time-stepping loop that are independent of the physics being integrated:
the loop backend — fixed-step
fori_loop/ adaptivewhile_loop/ reverse-mode-friendlycheckpointed_while_loop;collecting snapshots of the evolving state into preallocated buffers at chosen times (plus an optional final snapshot);
a host-side progress callback;
counting the number of steps taken.
The physics is supplied entirely through caller closures, so this module carries no domain knowledge and can be reused by any project:
- step(t, state, snapshot_index) -> (dt, new_state)
Advance
stateby one step. Returns the timestep actually taken (the driver advancest) and the new state.snapshot_indexis the current snapshot counter (0 when snapshots are disabled), passed through so the step can clampdtto land on snapshot times.- SnapshotSpec.record(t, state, store, index) -> store
Write whatever diagnostics are wanted for snapshot
indexinto the preallocatedstorepytree (typicallystore.field.at[index].set).- SnapshotSpec.should_record(t, index) -> bool
Whether snapshot
indexis due at the start of a step at timet(e.g. evenly spaced, or matching explicit timepoints).
state and store are opaque pytrees to the driver.
Module Contents#
Classes#
Bundles everything the driver needs to collect snapshots. |
Functions#
Float-precision-aware test that |
|
Run a time-integration loop. |
Data#
API#
- astronomix.time_stepping._time_loop.FIXED_STEP = 0#
- astronomix.time_stepping._time_loop.ADAPTIVE_WHILE = 1#
- astronomix.time_stepping._time_loop.ADAPTIVE_CHECKPOINTED = 2#
- astronomix.time_stepping._time_loop.times_close(t, target)[source]#
Float-precision-aware test that
thas reachedtarget.The tolerance is scaled by the working float epsilon and the magnitude of
target, so the test behaves correctly in both float32 and float64. A fixed absolute tolerance (e.g.1e-12) silently fails in float32, where a step landing ontargetis typically only accurate to ~1e-7·|target|.
- class astronomix.time_stepping._time_loop.SnapshotSpec[source]#
Bases:
typing.NamedTupleBundles everything the driver needs to collect snapshots.
- Attributes:
store: Preallocated output pytree the
recordcallback writes into. record:record(t, state, store, index) -> store. should_record:should_record(t, index) -> boolcrossing test. record_final: Also record the true final state once after the loop. final_index: Buffer slot the final state is written into. WhenNonethe running snapshot counter is used; for fixed-size buffers this should be the last slot (
num_snapshots - 1) so the final state att_endis captured reliably regardless of step alignment.
- store: Any = None#
- record: Callable = None#
- should_record: Callable = None#
- record_final: bool = True#
- final_index: Optional[int] = None#
- astronomix.time_stepping._time_loop.integrate(state: Any, step: Callable, t_end, *, backend: int, t_start=0.0, num_steps: Optional[int] = None, num_checkpoints: Optional[int] = None, snapshots: Optional[astronomix.time_stepping._time_loop.SnapshotSpec] = None, progress: Optional[Callable] = None)[source]#
Run a time-integration loop.
- Args:
state: Initial evolving-state pytree (opaque to the driver). step:
step(t, state, snapshot_index) -> (dt, new_state). t_end: Integration end time. backend: One ofFIXED_STEP/ADAPTIVE_WHILE/ADAPTIVE_CHECKPOINTED.t_start: Initial integration time (the loop clock starts here). num_steps: Number of steps for
FIXED_STEP. num_checkpoints: Checkpoint count forADAPTIVE_CHECKPOINTED. snapshots: ASnapshotSpec, orNoneto disable collection. progress:progress(t, t_end)host callback, orNone.- Returns:
(t, state, store, num_iterations).storeis the (possibly updated) snapshot store, orNonewhen snapshots are disabled.