astrodynx.prop.adaptive_steps

Contents

astrodynx.prop.adaptive_steps#

astrodynx.prop.adaptive_steps(orbdyn, x0, t1, max_steps=4096, solver=Tsit5(), stepsize_controller=PIDController(rtol=1e-08, atol=1e-08))[source]#

Propagate orbital state using Cowell’s method with adaptive step sizes.

This function solves the orbital dynamics differential equation using an adaptive step size integrator that automatically adjusts the time step based on local error estimates. This provides optimal balance between accuracy and computational efficiency.

Parameters:
  • orbdyn (OrbDynx) – Orbital dynamics configuration containing the differential equation terms, static arguments, and optional events.

  • x0 (ArrayLike) – (6,)Initial state vector [x, y, z, vx, vy, vz] in canonical units. Position components are in distance units, velocity components are in distance/time units.

  • t1 (DTypeLike) – Final integration time in canonical time units. Must be positive for forward propagation.

  • max_steps (int) – Maximum number of integration steps before terminating unconditionally. Prevents infinite loops and controls computational cost. Defaults to 4096.

  • solver (AbstractSolver) – Numerical integration method. Defaults to diffeq.Tsit5() (5th-order Runge-Kutta method with embedded error estimation).

  • stepsize_controller (AbstractStepSizeController) – Adaptive step size controller.

Return type:

Solution

Returns:

Integration solution containing
  • ts: Array of time points where solution was saved (variable spacing)

  • ys: Array of state vectors at each time point

  • stats: Integration statistics including step counts and rejections

  • result: Integration termination status

Notes

The adaptive step size controller automatically adjusts the time step to maintain the specified error tolerances. This results in smaller steps during periods of rapid change (e.g., near periapsis) and larger steps during smoother motion (e.g., near apoapsis).

The initial step size is set to 1% of the total integration time (t1 * 0.01), which provides a reasonable starting point for most orbital scenarios.

The solution is saved at the initial time and at every accepted step, providing a complete trajectory with optimal time resolution.

Examples

Orbital propagation with adaptive steps:

>>> import jax.numpy as jnp
>>> from astrodynx import diffeq
>>> import astrodynx as adx
>>> def vector_field(t, x, args):
...     acc = adx.gravity.point_mass_grav(t, x, args)
...     return jnp.concatenate([x[3:], acc])
>>> orbdyn = adx.prop.OrbDynx(
...     terms=diffeq.ODETerm(vector_field),
...     args={"mu": 1.0}
... )
>>> x0 = jnp.array([1.0, 0.0, 0.0, 0.0, 1.0, 0.0])
>>> t1 = jnp.pi*2  # One orbital period
>>> sol = adx.prop.adaptive_steps(orbdyn, x0, t1)
>>> xf = sol.ys[jnp.isfinite(sol.ts)][-1]

Eccentric orbit with J2 perturbations and event detection:

>>> def perturbed_field(t, x, args):
...     acc = adx.gravity.point_mass_grav(t, x, args)
...     acc += adx.gravity.j2_acc(t, x, args)
...     return jnp.concatenate([x[3:], acc])
>>> orbdyn = adx.prop.OrbDynx(
...     terms=diffeq.ODETerm(perturbed_field),
...     args = {"mu": 1.0, "rmin": 0.7, "J2": 1e-6, "R_eq": 1.0},
...     event = diffeq.Event(adx.events.radius_islow)
... )
>>> x0 = jnp.array([1.0, 0.0, 0.0, 0.0, 0.9, 0.0])
>>> sol = adx.prop.adaptive_steps(orbdyn, x0, t1)
>>> xf = sol.ys[jnp.isfinite(sol.ts)][-1]
>>> expected = jnp.array([-0.59,0.36, 0.,-0.58,-1.16, 0.])