Ch.1 · ODE Integration
Overview
Almost every simulation in astrophysics reduces to integrating a system of ordinary differential equations (ODEs). The choice of integrator affects accuracy, stability, and whether conserved quantities (energy, angular momentum) remain conserved over long runs.
Initial value problems
We want to solve:
For a particle of unit mass in a 1D potential , the state vector is and the right-hand side is .
Euler method
The simplest integrator advances the state by one step :
This is first-order accurate — global error — and almost never used in practice. For Hamiltonian systems it is not symplectic and energy drifts linearly with time.
Runge-Kutta methods
The classic 4th-order Runge-Kutta (RK4) evaluates at four points per step:
Global error is . RK4 is excellent for dissipative systems, but not symplectic: it injects or removes energy from Hamiltonian systems over long integrations.
Leapfrog / Störmer-Verlet
For Hamiltonian systems write . The leapfrog is:
This is 2nd-order and symplectic: it conserves a modified Hamiltonian exactly, so energy error is bounded (oscillates) rather than drifting.
import numpy as np
def leapfrog(q, p, h, grad_V):
"""One leapfrog step for separable Hamiltonian H = p^2/2 + V(q)."""
p = p - 0.5 * h * grad_V(q) # half kick
q = q + h * p # drift (grad_T = p for unit mass)
p = p - 0.5 * h * grad_V(q) # half kick
return q, p
def run(q0, p0, T, h, grad_V):
q, p = np.array(q0, float), np.array(p0, float)
E0 = 0.5 * np.dot(p, p) # + V(q0), track relative error
n_steps = int(T / h)
E_err = []
for _ in range(n_steps):
q, p = leapfrog(q, p, h, grad_V)
E = 0.5 * np.dot(p, p)
E_err.append(E - E0)
return q, p, np.array(E_err)Adaptive timestepping
For problems with multiple timescales (e.g. tight binaries in a cluster), a fixed is either wasteful or inaccurate. Embedded RK pairs (Dormand-Prince, Cash-Karp) estimate the local truncation error cheaply and adjust :
where is the estimated error and is the tolerance.
scipy.integrate.solve_ivp implements this with method='RK45'.
When to use what
- Dissipative / non-Hamiltonian ODE: use adaptive RK45 (
scipy.integrate.solve_ivp) - Hamiltonian, smooth potential: leapfrog with fixed
- Hamiltonian, close encounters: leapfrog with individual adaptive (Aarseth criterion)
- High accuracy, smooth: 4th-order symplectic (Forest-Ruth or PEFRL)