Advanced · Three-body orbits

Lesson 8: Forces and integration

Build the three-body orbits in Python, and learn on the way:

  • Newton’s gravity as vectors
  • nested loops over pairs of bodies
  • the leapfrog method of integration
  • a 3-D array: step × body × coordinate
  • checking a simulation by what must not change

Watch it first

Plays from YouTube after a click.

three-body-orbits.py
"""Three bodies: the figure-eight orbit, from the starting values computed by Carles Simo
(in Chenciner and Montgomery, 2000). G = 1, three masses of 1.
Run: python three-body-orbits.py   (needs: pip install numpy matplotlib)
"""
import numpy as np
import matplotlib.pyplot as plt

plt.style.use("dark_background")

x1 = np.array([0.97000436, -0.24308753])
V = np.array([-0.93240737, -0.86473146])  # the velocity of body 3
pos = np.array([x1, -x1, [0.0, 0.0]])
vel = np.array([-V / 2, -V / 2, V])
period, dt = 6.32591398, 0.0005
turn = 0  # degrees to turn the first velocity by (the film breaks the eight with 15)

a = np.radians(turn)
vel[0] = [vel[0, 0] * np.cos(a) - vel[0, 1] * np.sin(a), vel[0, 0] * np.sin(a) + vel[0, 1] * np.cos(a)]


def pull(p):
    """Each body's acceleration: the sum of the other two's gravity, G*m / r**2 towards each"""
    acc = np.zeros_like(p)
    for i in range(3):
        for j in range(3):
            if i != j:
                d = p[j] - p[i]
                acc[i] += d / np.linalg.norm(d) ** 3
    return acc


track = []
acc = pull(pos)
for _ in range(int(3 * period / dt)):  # three periods, leapfrog steps (they keep the energy well)
    vel += acc * dt / 2
    pos += vel * dt
    acc = pull(pos)
    vel += acc * dt / 2
    track.append(pos.copy())
track = np.array(track)

colours = ["#5eead4", "#f0abfc", "#f5c76b"]
plt.figure(figsize=(7, 4))
for body in range(3):  # all three run along the same track, a third of a period apart
    plt.plot(track[:, body, 0], track[:, body, 1], color=colours[body], linewidth=1)
plt.scatter(track[-1, :, 0], track[-1, :, 1], c=colours, s=80, zorder=3)
plt.axis("equal")
plt.axis("off")
plt.show()

# Try: turn = 15 -> the three tracks no longer close; the eight falls apart

No Python on this computer? The notebook runs the same script, the exercises and the answers in your browser, on Google Colab.

Line by line

  1. def pull(p):

    The acceleration of each body, from the gravity of the other two.

  2. acc[i] += d / np.linalg.norm(d) ** 3

    Gravity G·m / r² along the direction d / r together make d / r³; here G and the masses are 1.

  3. vel += acc * dt / 2

    Leapfrog: half a step of velocity, a whole step of position, then the other half step with the new forces.

  4. pos += vel * dt

    The positions move with the half-updated velocities.

  5. track = np.array(track)

    All the steps as one array: track[step, body, x or y].

  6. plt.scatter(track[-1, :, 0], track[-1, :, 1], c=colours, s=80, zorder=3)

    The three bodies where they ended, on one shared track, a third of a period apart.

Try it yourself

  1. Where is the centre of mass at the end?

    Hint

    track[-1].mean(axis=0).

    Answer

    At (0, 0) to within about 10⁻¹³: the total momentum is zero, so it never moves.

  2. Set turn = 15, as in the film. What happens, and where does the centre of mass go now?

    Hint

    Compare the start with the positions after one period.

    Answer

    The tracks no longer close: after one period the three bodies are, together, about 2 units away from where they began. Turning one velocity also gives the system some momentum, so the centre of mass drifts, to about (−0.81, 0.67) at the end.

  3. Make dt ten times bigger, 0.005. Does the eight still close?

    Hint

    Measure how far the bodies are from the start after one period.

    Answer

    Yes, but less exactly: after one period the three are, together, about 0.006 away from the start, against about 0.0001 with dt = 0.0005.

Quiz

1. Why d / |d|³ and not d / |d|²?
2. What makes leapfrog better than one Euler step?
3. What is track[-1, :, 0]?
4. Why does the centre of mass stay still in the figure-eight?
5. Who proved that the figure-eight exists?

Flashcards

Read the front, say the back to yourself, then open the card.

  • Gravity on body i

    Σ G·mⱼ·(rⱼ − rᵢ) / |rⱼ − rᵢ|³ over the other bodies j.

  • Leapfrog

    Half a velocity step, a whole position step, another half velocity step.

  • Periodic orbit

    A start that comes back exactly to itself after one period.

  • Centre of mass

    The average position weighted by mass; it moves only if the total momentum is not zero.

  • Chaos

    The tiniest change at the start grows until the motion is completely different.

These flashcards on their own page →