🧮 Numerical Methods · Physics
📅 Березень 2026 ⏱ ≈ 10 хв читання 🔵 Intermediate

ODE Solvers: Euler, RK4, and Leapfrog Compared

Every physics simulation — falling apples, orbiting planets, bouncing molecules — secretly solves a differential equation every frame. The choice of method determines whether your simulation is stable and energy-conserving or slowly diverges into chaos.

1. What Is an ODE?

An Ordinary Differential Equation (ODE) expresses a state's rate of change as a function of the state itself. Newton's second law is a classic example:

Newton's second law as an ODE system dv/dt = F(x, v, t) / m (velocity changes due to force)
dx/dt = v (position changes due to velocity)

Given initial conditions x(0) and v(0), an ODE solver advances the system in small time steps Δt, approximating the exact solution. The error per step and the long-term behaviour depend heavily on the algorithm.

2. Euler's Method

The simplest possible scheme: take the derivative at the current point and step in that direction by Δt.

Forward (Explicit) Euler x(t + Δt) = x(t) + Δt · ẋ(t)
v(t + Δt) = v(t) + Δt · a(t)
Avoid Euler for long simulations: A planet orbiting with Euler integration will slowly spiral away from the Sun — not because physics is wrong, but because the integrator is non-conservative.

3. Midpoint & Heun Methods

A simple improvement: evaluate the derivative at an intermediate point. Heun's method (predictor–corrector):

Heun's method (RK2) k1 = f(t, y)
k2 = f(t + Δt, y + Δt·k1) (predicted endpoint)
y(t + Δt) = y + (Δt/2)·(k1 + k2)

Both are 2nd order — much more accurate than Euler with only 2× the cost. Still non-symplectic; energy still drifts over very long runs.

4. Runge–Kutta 4th Order (RK4)

The workhorse of scientific computing. RK4 evaluates four derivative estimates per step and takes their weighted average:

RK4 update k1 = f(t, y)
k2 = f(t + Δt/2, y + (Δt/2)·k1)
k3 = f(t + Δt/2, y + (Δt/2)·k2)
k4 = f(t + Δt, y + Δt·k3)

y(t + Δt) = y + (Δt/6)·(k1 + 2k2 + 2k3 + k4)
Rule of thumb: RK4 is ideal for trajectory calculations with a known end time (rocket manoeuvres, ODE-based animations). For indefinitely long simulations (molecular dynamics, long-term orbital mechanics), use Leapfrog or other symplectic solvers instead.

5. Leapfrog / Verlet Integration

The Leapfrog (Störmer–Verlet) integrator staggers position and velocity by half a time step — positions and velocities "leapfrog" past each other:

Leapfrog (velocity Verlet form) v(t + Δt/2) = v(t) + (Δt/2)·a(t)
x(t + Δt) = x(t) + Δt · v(t + Δt/2)
a(t + Δt) = F(x(t + Δt)) / m (re-evaluate force)
v(t + Δt) = v(t + Δt/2) + (Δt/2)·a(t + Δt)
Why is leapfrog symplectic? It preserves the volume of phase space (Liouville's theorem). This is the discrete analogue of Hamilton's equations, which also conserve phase-space volume.

6. Symplectic vs. Non-Symplectic

A symplectic integrator exactly conserves a slightly perturbed Hamiltonian H' (close to the true H). This prevents systematic energy growth or decay, making the simulation stable for arbitrarily long times.

Non-symplectic methods (Euler, RK4) do not satisfy this property. Their energy errors grow without bound, eventually ruining long simulations even if the per-step error is tiny.

7. Comparison Table

Method Order Evals/step Symplectic Energy long-term Best for
Euler (forward) 1st 1 No Grows Demos, learning only
Symplectic Euler 1st 1 Yes Stable Fast games, many particles
Midpoint / Heun 2nd 2 No Slow drift Short animations
RK4 4th 4 No Very slow drift Precise trajectories
Leapfrog / Verlet 2nd 1 Yes Oscillates ≈ const Orbital, molecular dynamics
Yoshida 4th 4th 3 Yes Oscillates ≈ const High-accuracy long runs

8. JavaScript Implementation

All three integrators for a simple harmonic oscillator a = −ω²·x (spring without damping):

const omega = 1.0;                  // angular frequency
const dt    = 0.05;                  // time step (seconds)

function accel(x) { return -omega * omega * x; }

// ── Forward Euler ───────────────────────────────────
function stepEuler(x, v) {
  const a = accel(x);
  return { x: x + dt * v,  v: v + dt * a };
}

// ── RK4 ────────────────────────────────────────────
function stepRK4(x, v) {
  const k1x = v,                     k1v = accel(x);
  const k2x = v + 0.5*dt*k1v,       k2v = accel(x + 0.5*dt*k1x);
  const k3x = v + 0.5*dt*k2v,       k3v = accel(x + 0.5*dt*k2x);
  const k4x = v + dt*k3v,            k4v = accel(x + dt*k3x);
  return {
    x: x + (dt/6) * (k1x + 2*k2x + 2*k3x + k4x),
    v: v + (dt/6) * (k1v + 2*k2v + 2*k3v + k4v)
  };
}

// ── Leapfrog (Velocity Verlet) ─────────────────────
function stepLeapfrog(x, v) {
  const vHalf = v   + 0.5 * dt * accel(x);   // half-step velocity
  const xNew  = x   + dt   * vHalf;             // full-step position
  const vNew  = vHalf + 0.5 * dt * accel(xNew); // half-step velocity again
  return { x: xNew, v: vNew };
}

// Energy of a harmonic oscillator (should be conserved)
function energy(x, v) { return 0.5*v*v + 0.5*omega*omega*x*x; }
Tip: Plug these into a simple render loop and plot energy(x, v) over time. You will see Euler's energy grow linearly, RK4's grow very slowly, and Leapfrog's oscillate tightly around the initial value.

9. Which Method Should You Use?

Cannon-es & Rapier (the physics engines powering this site) use variations of symplectic Euler and impulse-based solvers. They sacrifice some accuracy in exchange for extreme stability and rigid-body collision resolution.

Explore the n-body and orbital simulations on this site — they use Leapfrog integration so that planets orbit stably for millions of simulated years without spiralling away.

🪐 Open Orbital Simulation →