Zaawansowane · Orbity trzech ciał

Lekcja 8: Siły i całkowanie

Zbuduj w Pythonie wzór „Orbity trzech ciał” i po drodze naucz się:

  • grawitacja Newtona jako wektory
  • pętle zagnieżdżone po parach ciał
  • metoda żabiego skoku (leapfrog)
  • tablica trójwymiarowa: krok × ciało × współrzędna
  • sprawdzanie symulacji tym, co nie może się zmieniać

Najpierw obejrzyj

Film gra z YouTube po kliknięciu.

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

Nie masz Pythona na tym komputerze? Notatnik uruchamia ten sam skrypt, zadania i odpowiedzi w przeglądarce, w Google Colab. Notatnik jest po angielsku.

Linijka po linijce

  1. def pull(p):

    Przyspieszenie każdego ciała od grawitacji dwóch pozostałych.

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

    Grawitacja G·m / r² wzdłuż kierunku d / r razem dają d / r³; tutaj G i masy są równe 1.

  3. vel += acc * dt / 2

    Żabi skok: pół kroku prędkości, cały krok położenia, potem druga połowa kroku z nowymi siłami.

  4. pos += vel * dt

    Położenia przesuwają się z prędkościami zmienionymi w połowie.

  5. track = np.array(track)

    Wszystkie kroki jako jedna tablica: track[krok, ciało, x albo y].

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

    Trzy ciała tam, gdzie skończyły, na jednym wspólnym torze, w odstępach jednej trzeciej okresu.

Twoja kolej

  1. Gdzie jest środek masy na końcu?

    Podpowiedź

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

    Odpowiedź

    W (0, 0) z dokładnością do około 10⁻¹³: pęd całkowity jest zerowy, więc środek masy się nie porusza.

  2. Ustaw turn = 15, jak w filmie. Co się dzieje i gdzie jest teraz środek masy?

    Podpowiedź

    Porównaj start z położeniami po jednym okresie.

    Odpowiedź

    Tory przestają się zamykać: po jednym okresie trzy ciała są razem około 2 jednostki od miejsca startu. Obrót jednej prędkości daje też układowi pęd, więc środek masy dryfuje, na końcu do około (−0.81, 0.67).

  3. Zwiększ dt dziesięć razy, do 0.005. Czy ósemka nadal się zamyka?

    Podpowiedź

    Zmierz, jak daleko od startu są ciała po jednym okresie.

    Odpowiedź

    Tak, ale mniej dokładnie: po jednym okresie trzy ciała są razem około 0,006 od startu, wobec około 0,0001 przy dt = 0.0005.

Quiz

1. Dlaczego d / |d|³, a nie d / |d|²?
2. Co sprawia, że żabi skok jest lepszy od jednego kroku Eulera?
3. Czym jest track[-1, :, 0]?
4. Dlaczego w ósemce środek masy stoi w miejscu?
5. Kto udowodnił, że ósemka istnieje?

Fiszki

Przeczytaj przód, powiedz sobie, co jest z tyłu, potem otwórz kartę.

  • Grawitacja na ciało i

    Σ G·mⱼ·(rⱼ − rᵢ) / |rⱼ − rᵢ|³ po pozostałych ciałach j.

  • Żabi skok

    Pół kroku prędkości, cały krok położenia, znów pół kroku prędkości.

  • Orbita okresowa

    Start, który po jednym okresie wraca dokładnie do siebie.

  • Środek masy

    Średnie położenie ważone masą; porusza się tylko wtedy, gdy pęd całkowity nie jest zerowy.

  • Chaos

    Najmniejsza zmiana na starcie rośnie, aż ruch staje się zupełnie inny.

Te fiszki na osobnej stronie →