Reference
Derived systems¶
Wrappers that re-present an existing system through a new lens while
keeping the System protocol intact, so analysis functions
compose with them transparently. Prose introduction:
the mental model.
PoincareMap
¶
PoincareMap(
system: Any,
plane: tuple,
*,
direction: int = +1,
dt: float = 0.01,
max_time: float = 10000.0,
)
Bases: DerivedSystem
Present a flow as the discrete map of its crossings through a hyperplane.
One step() advances the underlying system until the trajectory
crosses the section plane in the chosen direction, refines the crossing
point by cubic Hermite interpolation of the bracketing samples (using the
system's numeric RHS for endpoint derivatives — O(dt⁴) accuracy), and
returns the full-dimensional crossing state.
Because a PoincareMap is a discrete system, everything written for
maps applies to flows through it — e.g. an orbit diagram over a
PoincareMap is a bifurcation diagram of the flow.
| PARAMETER | DESCRIPTION |
|---|---|
system
|
A continuous-time system (ODE or DDE).
TYPE:
|
plane
|
Either
TYPE:
|
direction
|
Count only crossings with
TYPE:
|
dt
|
March step used for crossing detection. The refinement makes the
crossing itself far more accurate than
TYPE:
|
max_time
|
Raise if no crossing is found within this much time (e.g. the plane misses the attractor).
TYPE:
|
Examples:
>>> pmap = PoincareMap(Rossler(), plane=(0, 0.0), direction=+1)
>>> section = pmap.trajectory(500) # 500 crossings
>>> section.y.shape
(500, 3)
Source code in src/tsdynamics/derived/poincare.py
step
¶
Advance to the n-th next crossing and return it (full-dim coords).
Source code in src/tsdynamics/derived/poincare.py
set_state
¶
set_state(u: Any) -> None
Overwrite the inner flow state and reset crossing bookkeeping.
reinit
¶
Restart the inner flow and clear crossing bookkeeping.
Source code in src/tsdynamics/derived/poincare.py
trajectory
¶
trajectory(
steps: int = 100, *, transient: int = 0, **kwargs: Any
) -> Trajectory
Collect crossings as a trajectory.
t holds the continuous crossing times; y the full-dimensional
crossing states. transient crossings are discarded first.
Source code in src/tsdynamics/derived/poincare.py
StroboscopicMap
¶
Bases: DerivedSystem
Present a forced flow as the discrete map of once-per-period samples.
One step() advances the underlying continuous system by exactly one
forcing period and returns the new state. Orbit diagrams over a
StroboscopicMap are the standard way to study forced oscillators
(Duffing, forced van der Pol, ...).
| PARAMETER | DESCRIPTION |
|---|---|
system
|
A continuous-time system.
TYPE:
|
period
|
Sampling period (the forcing period).
TYPE:
|
Examples:
>>> smap = StroboscopicMap(ForcedVanDerPol(), period=2 * np.pi / 0.63)
>>> samples = smap.trajectory(300, transient=100)
Source code in src/tsdynamics/derived/stroboscopic.py
step
¶
Advance n periods (default 1) and return the new state.
trajectory
¶
trajectory(
steps: int = 100, *, transient: int = 0, **kwargs: Any
) -> Trajectory
Collect steps once-per-period samples (after transient periods).
Source code in src/tsdynamics/derived/stroboscopic.py
TangentSystem
¶
Bases: DerivedSystem
Evolve a system together with k deviation (tangent) vectors.
Each step() advances the state and the deviation vectors, then
QR-reorthonormalises; :meth:growths exposes the per-step logarithmic
stretch factors log |diag R| and :meth:exponents their running
time-average — the Lyapunov spectrum estimate.
Implementation per family
- Maps: pure NumPy —
W ← J(x)·Wwith the hand-written/compiled_jacobian, then QR. - ODEs: a thin wrapper over the compiled variational equations
(
jitcode_lyap), which JiTCODE builds by symbolic differentiation — no Python-side Jacobian evaluation in the hot loop. - DDEs: not supported — tangent dynamics of a DDE lives in an
infinite-dimensional history space; use
DelaySystem.lyapunov_spectrumwhich wrapsjitcdde_lyap.
Examples:
>>> tang = TangentSystem(Henon(), k=2)
>>> tang.reinit([0.1, 0.1])
>>> for _ in range(5000):
... tang.step()
>>> tang.exponents() # ≈ [0.42, -1.62]
Source code in src/tsdynamics/derived/tangent.py
reinit
¶
reinit(
u: Any | None = None,
*,
t: float | None = None,
params: dict | None = None,
**kwargs: Any,
) -> None
Restart state, deviation vectors, and accumulated growth sums.
Source code in src/tsdynamics/derived/tangent.py
step
¶
Advance state + deviation vectors and reorthonormalise.
For maps n_or_dt is the number of iterations (QR after each);
for ODEs it is the time increment (default 0.1).
Returns the new state.
Source code in src/tsdynamics/derived/tangent.py
state
¶
state() -> ndarray
Return a copy of the current base-system state.
Source code in src/tsdynamics/derived/tangent.py
set_state
¶
set_state(u: Any) -> None
Overwrite the base state (map mode only — ODE tangent vectors would desync).
Source code in src/tsdynamics/derived/tangent.py
deviations
¶
deviations() -> ndarray
Return the current orthonormal deviation vectors, shape (dim, k) (maps only).
Source code in src/tsdynamics/derived/tangent.py
EnsembleSystem
¶
Many copies of one system, advanced synchronously from different states.
Used for two-trajectory Lyapunov estimates, basin sampling, and ensemble statistics. Members are independent copies — parameters are shared at construction, states are per-member.
| PARAMETER | DESCRIPTION |
|---|---|
system
|
The template system (copied per member; the original is untouched).
TYPE:
|
states
|
One initial state per member. |
Examples:
>>> ens = EnsembleSystem(Lorenz(), [[1, 1, 1], [1.001, 1, 1]])
>>> ens.step(0.01)
array([[...], [...]])
Source code in src/tsdynamics/derived/ensemble.py
step
¶
Advance every member and return the stacked states, shape (m, dim).
set_states
¶
set_states(states: Any) -> None
Overwrite every member's state.
Source code in src/tsdynamics/derived/ensemble.py
ProjectedSystem
¶
ProjectedSystem(
system: Any,
components: Any,
*,
complete: Callable[[ndarray], Any] | None = None,
)
Bases: DerivedSystem
View a system through a subset of its components.
The full system is stepped underneath; only state()/step()
outputs are projected. set_state needs the inverse direction and
therefore requires a complete callable mapping a projected state back
to a full state.
| PARAMETER | DESCRIPTION |
|---|---|
system
|
The full system.
TYPE:
|
components
|
Component indices (or names, when the system declares
TYPE:
|
complete
|
TYPE:
|
Examples:
Source code in src/tsdynamics/derived/projected.py
variables
property
¶
Component names of the projected view (the inner names, subset).
Overrides :class:DerivedSystem's pass-through (which would return the
inner system's full names and mislabel the projected columns). Returns
None when the inner system declares no variables.
step
¶
Advance the full system; return the projected new state.
set_state
¶
set_state(u: Any) -> None
Overwrite the state (projected inputs need a complete callable).
Source code in src/tsdynamics/derived/projected.py
reinit
¶
Restart the full system (projected inputs need a complete callable).
Source code in src/tsdynamics/derived/projected.py
trajectory
¶
trajectory(*args: Any, **kwargs: Any) -> Trajectory
Full-system trajectory with projected columns.
Source code in src/tsdynamics/derived/projected.py
DerivedSystem
¶
DerivedSystem(system: Any)
Base for wrappers that present an existing system through a new lens.
A derived system implements the :class:~tsdynamics.families.System protocol
by delegating to a wrapped system, transforming what "one step" or "the
state" means (Poincaré crossings, stroboscopic samples, projections...).
Parameters and metadata are forwarded to the wrapped system, and
with_params re-parametrizes the inner system and rebuilds the
wrapper, so parameter sweeps compose: an orbit diagram over a
PoincareMap is a bifurcation diagram of the underlying flow.
Source code in src/tsdynamics/derived/_base.py
with_params
¶
with_params(**overrides: Any) -> DerivedSystem
Return a new wrapper of the same kind around a re-parametrized copy.
copy
¶
copy() -> DerivedSystem