W mojej odpowiedzi na pytanie dotyczące MSE dotyczące symulacji fizyki Hamiltoniana 2D zasugerowałem użycie integratora symplektycznego wyższego rzędu .
Potem pomyślałem, że dobrym pomysłem może być wykazanie wpływu różnych kroków czasowych na globalną dokładność metod z różnymi zamówieniami. Napisałem i uruchomiłem skrypt Python / Pylab w tym celu. Do porównania wybrałem:
- ( leap2 ) Przykład drugiego rzędu Wikipedii, który znam, chociaż znam go pod nazwą leapfrog ,
- ( ruth3 ) Integrator symplektyczny trzeciego rzędu Rutha ,
- ( ruth4 ) Integrator symplektyczny czwartego rzędu Rutha .
Dziwną rzeczą jest to, że niezależnie od wybranego przeze mnie przedziału czasu metoda trzeciego rzędu Rutha wydaje się być bardziej dokładna w moim teście niż metoda czwartego rzędu Rutha, nawet o rząd wielkości.
Moje pytanie brzmi zatem: co tutaj robię źle? Szczegóły poniżej.
Metody rozwijają swoją siłę w układach z separowalnymi hamiltonianami, tj. W tych, które można zapisać jako
gdzie obejmuje wszystkie współrzędne pozycji,
zawiera sprzężoną pęd,
reprezentuje kinetykę energia i energia potencjalna
W naszym ustawieniu możemy znormalizować siły i momenty według mas, do których są przyłożone. W ten sposób siły zamieniają się w przyspieszenia, a momenty w prędkości.
Integratory symplektyczne mają specjalne (podane, stałe) współczynniki, które i . Przy tych współczynnikach przybiera postać jeden etap ewolucji systemu od czasu do czasu
Dla :
- Oblicz wektor wszystkich przyspieszeń, biorąc pod uwagę wektor wszystkich pozycji
- Zmień wektor wszystkich prędkości o
- Zmiana wektora wszystkich pozycjach przez
Mądrość leży teraz w współczynnikach. Są to
Do testowania wybrałem problem wartości początkowej 1D
Zintegrowałem IVP z powyższymi metodami w stosunku do ze skokiem wielkości z liczbą całkowitą wybraną gdzieś pomiędzy a . Biorąc pod uwagę szybkość skoku 2 , potroiłem dla tej metody. Następnie wykreśliłem otrzymane krzywe w przestrzeni fazowej i powiększyłem w gdzie krzywe powinny idealnie dotrzeć ponownie przy .N(1,0)t=2π
Oto wykresy i powiększenia dla i :
Dla , skok 2 z krokiem wielkości zdarza się zbliżać do domu niż ruth4 z krokiem wielkości . Dla , ruth4 wygranych ponad leap2 . Jednak ruth3 , z tym samym krokiem co ruth4 , zbliża się znacznie do domu niż oba pozostałe, we wszystkich testowanych do tej pory ustawieniach.2 π 2π
Oto skrypt Python / Pylab:
import numpy as np
import matplotlib.pyplot as plt
def symplectic_integrate_step(qvt0, accel, dt, coeffs):
q,v,t = qvt0
for ai,bi in coeffs.T:
v += bi * accel(q,v,t) * dt
q += ai * v * dt
t += ai * dt
return q,v,t
def symplectic_integrate(qvt0, accel, t, coeffs):
q = np.empty_like(t)
v = np.empty_like(t)
qvt = qvt0
q[0] = qvt[0]
v[0] = qvt[1]
for i in xrange(1, len(t)):
qvt = symplectic_integrate_step(qvt, accel, t[i]-t[i-1], coeffs)
q[i] = qvt[0]
v[i] = qvt[1]
return q,v
c = np.math.pow(2.0, 1.0/3.0)
ruth4 = np.array([[0.5, 0.5*(1.0-c), 0.5*(1.0-c), 0.5],
[0.0, 1.0, -c, 1.0]]) / (2.0 - c)
ruth3 = np.array([[2.0/3.0, -2.0/3.0, 1.0], [7.0/24.0, 0.75, -1.0/24.0]])
leap2 = np.array([[0.5, 0.5], [0.0, 1.0]])
accel = lambda q,v,t: -q
qvt0 = (1.0, 0.0, 0.0)
tmax = 2.0 * np.math.pi
N = 36
fig, ax = plt.subplots(1, figsize=(6, 6))
ax.axis([-1.3, 1.3, -1.3, 1.3])
ax.set_aspect('equal')
ax.set_title(r"Phase plot $(y(t),y'(t))$")
ax.grid(True)
t = np.linspace(0.0, tmax, 3*N+1)
q,v = symplectic_integrate(qvt0, accel, t, leap2)
ax.plot(q, v, label='leap2 (%d steps)' % (3*N), color='black')
t = np.linspace(0.0, tmax, N+1)
q,v = symplectic_integrate(qvt0, accel, t, ruth3)
ax.plot(q, v, label='ruth3 (%d steps)' % N, color='red')
q,v = symplectic_integrate(qvt0, accel, t, ruth4)
ax.plot(q, v, label='ruth4 (%d steps)' % N, color='blue')
ax.legend(loc='center')
fig.show()
Sprawdziłem już proste błędy:
- Brak literówki w Wikipedii. Sprawdziłem referencje, w szczególności ( 1 , 2 , 3 ).
- Mam prawidłową sekwencję współczynników. Jeśli porównasz z zamówieniami Wikipedii, zauważ, że sekwencjonowanie aplikacji operatora działa od prawej do lewej. Moja numeracja zgadza się z Candy / Rozmus . A jeśli spróbuję jeszcze raz zamówić, wyniki będą gorsze.
Moje podejrzenia:
- Zła kolejność stopni: Może schemat Rutha trzeciego rzędu ma w jakiś sposób znacznie mniejsze implikowane stałe, a jeśli rozmiar kroku byłby naprawdę mały, to metoda czwartego rzędu wygrałaby? Ale nawet wypróbowałem , a metoda trzeciego rzędu wciąż jest lepsza.
- Błędny test: Coś specjalnego w moim teście pozwala metodzie Rutha trzeciego rzędu zachowywać się jak metoda wyższego rzędu?