In meiner Antwort auf eine Frage zu MSE bezüglich einer 2D-Hamiltonschen Physiksimulation habe ich vorgeschlagen, einen symplektischen Integrator höherer Ordnung zu verwenden .
Dann hielt ich es für eine gute Idee, die Auswirkungen verschiedener Zeitschritte auf die globale Genauigkeit von Methoden mit unterschiedlichen Ordnungen zu demonstrieren, und schrieb und führte ein Python / Pylab-Skript zu diesem Zweck aus. Zum Vergleich habe ich gewählt:
- ( leap2 ) Wikipedia's Beispiel 2. Ordnung, mit dem ich vertraut bin, obwohl ich es unter dem Namen leapfrog kenne ,
- ( ruth3 ) Ruths symplektischer Integrator 3. Ordnung ,
- ( ruth4 ) Ruths symplektischer Integrator 4. Ordnung .
Das Seltsame ist, egal welchen Zeitschritt ich wähle, Ruths Methode 3. Ordnung scheint in meinem Test genauer zu sein als Ruths Methode 4. Ordnung, selbst um eine Größenordnung.
Meine Frage ist daher: Was mache ich hier falsch? Details unten.
Die Methoden entfalten ihre Stärke in Systemen mit trennbaren Hamiltonianern, dh solchen, die als
wobei alle Positionskoordinaten umfasst ,
die konjugierten Impulse umfasst,
die Kinetik darstellt Energie und potentielle Energie.
In unserem Setup können wir Kräfte und Impulse durch die Massen normalisieren, auf die sie angewendet werden. So werden Kräfte zu Beschleunigungen und Impulse zu Geschwindigkeiten.
Die symplektischen Integratoren kommen mit speziellen (gegebenen, konstanten) Koeffizienten, die ich mit und . Mit diesen Koeffizienten nimmt ein Schritt zum Entwickeln des Systems vom Zeitpunkt zum Zeitpunkt die Form an
Für :
- Berechnen Sie den Vektor aller Beschleunigungen unter Berücksichtigung des Vektors aller Positionen
- Ändern Sie den Vektor aller Geschwindigkeiten um
- Ändern Sie den Vektor aller Positionen um
Die Weisheit liegt nun in den Koeffizienten. Dies sind
Zum Testen habe ich das 1D-Anfangswertproblem
das einen trennbaren Hamilton-Operator hat. Hier werden mit identifiziert .
Ich habe das IVP mit den obigen Methoden über mit einer Schrittgröße von mit einer ganzen Zahl die irgendwo zwischen und . Unter Berücksichtigung der Geschwindigkeit von leap2 habe ich für diese Methode verdreifacht . Ich habe dann die resultierenden Kurven im Phasenraum aufgezeichnet und auf gezoomt, wo die Kurven idealerweise wieder bei ankommen sollten .N(1,0)t=2π
Hier sind Diagramme und Zooms für und :
Für kommt Sprung2 mit der Schrittgröße näher zu Hause als ruth4 mit der Schrittgröße . Für , ruth4 gewinnt über leap2 . Allerdings kommt ruth3 mit der gleichen Schrittgröße wie ruth4 in allen Einstellungen, die ich bisher getestet habe , viel näher zu Hause an als die beiden anderen.2 π 2π
Hier ist das Python / Pylab-Skript:
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()
Ich habe bereits nach einfachen Fehlern gesucht:
- Kein Wikipedia-Tippfehler. Ich habe insbesondere die Referenzen überprüft ( 1 , 2 , 3 ).
- Ich habe die richtige Koeffizientenfolge. Wenn Sie mit der Bestellung von Wikipedia vergleichen, beachten Sie, dass die Sequenzierung der Operatoranwendung von rechts nach links funktioniert. Meine Nummerierung stimmt mit Candy / Rozmus überein . Und wenn ich trotzdem eine andere Bestellung versuche, werden die Ergebnisse schlechter.
Mein Verdacht:
- Falsche Schrittgrößenreihenfolge: Vielleicht hat Ruths Schema 3. Ordnung irgendwie viel kleinere implizite Konstanten, und wenn die Schrittgröße wirklich klein gemacht würde, würde die Methode 4. Ordnung gewinnen? Aber ich habe sogar ausprobiert , und die Methode 3. Ordnung ist immer noch überlegen.
- Falscher Test: Etwas Besonderes an meinem Test lässt Ruths Methode 3. Ordnung wie eine Methode höherer Ordnung verhalten?