Test dell'integratore simplettico del 3 ° ordine contro 4 ° ordine con risultato strano


10

Nella mia risposta a una domanda sull'MSE riguardante una simulazione di fisica hamiltoniana 2D, ho suggerito di utilizzare un integratore simplettico di ordine superiore .

Quindi ho pensato che sarebbe stata una buona idea dimostrare gli effetti di diversi passaggi temporali sull'accuratezza globale dei metodi con ordini diversi, e ho scritto ed eseguito uno script Python / Pylab in tal senso. Per confronto ho scelto:

La cosa strana è, qualunque sia il timestep che scelgo, il metodo del 3 ° ordine di Ruth sembra essere più accurato nel mio test rispetto al metodo del 4 ° ordine di Ruth, anche di un ordine di grandezza.

La mia domanda è quindi: cosa sto facendo di sbagliato qui? Dettagli sotto.

I metodi spiegano la loro forza in sistemi con Hamiltoniani separabili , cioè quelli che possono essere scritti come

H(q,p)=T(p)+V(q)
dove q comprende tutte le coordinate di posizione, p comprende il momento coniugato, T rappresenta cinetico energia e V energia potenziale.

Nella nostra configurazione, possiamo normalizzare forze e momenti in base alle masse a cui sono applicati. Quindi le forze si trasformano in accelerazioni e i momenti si trasformano in velocità.

Gli integratori simplettici vengono con coefficienti speciali (dati, costanti) che etichetterò a1,,an e b1,,bn . Con questi coefficienti, un passo per far evolvere il sistema da tempo t a tempo t+δt assume la forma

  • Per i=1,,n :

    1. Calcola il vettore g di tutte le accelerazioni, dato il vettore q di tutte le posizioni
    2. Cambia vettore v di tutte le velocità di bigδt
    3. Cambia il vettore q di tutte le posizioni con aivδt

La saggezza ora sta nei coefficienti. Questi sono

[a1a2b1b2]=[121201](leap2)[a1a2a3b1b2b3]=[2323172434124](ruth3)[a1a2a3a4b1b2b3b4]=1223[12123212321201231](ruth4)

Per il test, ho scelto il problema del valore iniziale 1D

y+y=0y(0)=1y(0)=0
(y(t),y(t))=(cost,sint)
che ha un hamiltoniano separabile. Qui,(q,v)sono identificati con(y,y).

Ho integrato l'IVP con i metodi sopra sopra t[0,2π] con una dimensione di δt=2πN con un numero interoNscelto da qualche parte tra10e100. Tenendocontodella velocità dileap2, ho triplicatoNper quel metodo. Ho quindi tracciato le curve risultanti nello spazio delle fasi e ingrandito a(1,0) dove le curve dovrebbero idealmente arrivare di nuovo at=2π.

Ecco grafici e zoom per N=12 e N=36 :

N = 12N = 12, ingrandito

N = 36N = 36, ingrandito

Per N=12 , leap2 con passo 2π3N sembra arrivare più vicino a casa diruth4 con passo2πN . PerN=36,ruth4vince sulsalto2. Tuttavia,ruth3, con le stesse dimensioni diruth4, arriva molto più vicino a casa di entrambi gli altri, in tutte le impostazioni che ho testato finora.

Ecco lo script 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()

Ho già verificato errori semplici:

  • Nessun refuso di Wikipedia. Ho verificato i riferimenti, in particolare ( 1 , 2 , 3 ).
  • Ho corretto la sequenza dei coefficienti. Se si confronta con l'ordinamento di Wikipedia, notare che il sequenziamento dell'applicazione operatore funziona da destra a sinistra. La mia numerazione concorda con Candy / Rozmus . E se provo comunque un altro ordine, i risultati peggiorano.

I miei sospetti:

  • Ordine errato di dimensioni ridotte: forse lo schema del 3 ° ordine di Ruth ha in qualche modo costanti implicite molto più piccole, e se la dimensione del passo fosse resa davvero piccola, allora il metodo del 4 ° ordine vincerebbe? Ma ho anche provato N=360 e il metodo del 3 ° ordine è ancora superiore.
  • Test sbagliato: qualcosa di speciale nel mio test consente al metodo di Ruth di 3 ° ordine di comportarsi come un metodo di ordine superiore?

NN

@Kirill: ci sto lavorando. Modifica presto.
ccorn

1
Una cosa di cui sospetto è la scelta di un rh lineare: gli errori di troncamento dei metodi di solito dipendono da una derivata elevata di rhs, quindi se tutte le derivate alte di rhs svaniscono, potresti osservare uno strano comportamento di convergenza. Probabilmente vale la pena provare un rhs più insolito.
Kirill,

Risposte:


9

NN

ε(N)=z~(2π)-z~(0)2dovez~(t)=(y~(t),y~'(t))
z~

inserisci qui la descrizione dell'immagine

41100

Interessante. Dovrò indagare ulteriormente, magari provando altri test.

A proposito, ecco le aggiunte allo script Python per il diagramma degli errori:

def int_error(qvt0, accel, qvt1, Ns, coeffs):
    e = np.empty((len(Ns),))
    for i,N in enumerate(Ns):
        t = np.linspace(qvt0[2], qvt1[2], N+1)
        q,v = symplectic_integrate(qvt0, accel, t, coeffs)
        e[i] = np.math.sqrt((q[-1]-qvt1[0])**2+(v[-1]-qvt1[1])**2)
    return e

qvt1 = (1.0, 0.0, tmax)
Ns = [12,16,20,24,32,40,48,64,80,96,128,160,192,
      256,320,384,512,640,768,1024,1280,1536,2048,2560,3072]

fig, ax = plt.subplots(1)
ax.set_xscale('log')
ax.set_xlabel(r"$N$")
ax.set_yscale('log')
ax.set_ylabel(r"$\|z(2\pi)-z(0)\|$")
ax.set_title(r"Error after 1 period vs #steps")
ax.grid(True)
e = int_error(qvt0, accel, qvt1, Ns, leap2)
ax.plot(Ns, e, label='leap2', color='black')
e = int_error(qvt0, accel, qvt1, Ns, ruth3)
ax.plot(Ns, e, label='ruth3', color='red')
e = int_error(qvt0, accel, qvt1, Ns, ruth4)
ax.plot(Ns, e, label='ruth4', color='blue')
ax.legend(loc='upper right')
fig.show()

Non pertinente alla domanda, ma puoi inserire modifiche e aggiornamenti nella domanda stessa, anziché pubblicare come risposta separata? Questo manterrà la convenzione secondo cui le risposte dovrebbero rispondere alla domanda.
Kirill,

1
@Kirill: è una risposta. ruth3 ha davvero un ordine superiore e costanti minori qui. Scoperto a causa del tuo suggerimento di creare un diagramma degli errori del log-log. Pertanto, alla domanda viene data una risposta, e sicuramente non cambierò il punto di una domanda una volta che abbia ricevuto risposta, anche se la risposta è stata composta da me.
ccorn

Detto questo, sarei felice di accettare ulteriori analisi. (Le domande con risposta automatica vengono accettate automaticamente, ma si può cambiare che suppongo.)
ccorn

2
p00V(q)=1/q+logqV
Kirill

2
Questa è una dimostrazione di superconvergenza. Semplici problemi di test come questo finiscono per avere questo problema in molti casi. L'uso di un'equazione lineare può dare questo comportamento e molte volte i termini dispari di una serie di Taylor possono annullarsi quando ciò accade. È molto meno probabile che si verifichi un problema di test non lineare senza una soluzione analitica.
Chris Rackauckas,

2

q¨=-qq(0)=1,q˙(0)=0

inserisci qui la descrizione dell'immagine

Come previsto, i grafici per un numero crescente di sottointervalli si avvicinano sempre più a una curva limite che è il principale coefficiente di errore. In tutto tranne uno, questa convergenza è visibilmente rapida, non c'è quasi nessuna divergenza. Ciò significa che anche per passi di dimensioni relativamente grandi il termine di errore principale domina tutti gli altri termini.

p

qt=2πp

q3π/2


q¨=-peccato(q)q(0)=1.3, q˙(0)=0

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.