Hufeisenbahnen und Integration in C

Ich studiere einen besonderen Fall des eingeschränkten Dreikörperproblems. Es wurde festgestellt, dass einige Objekte einem Hufeisenbahnmuster folgen, und ich versuche, etwas durch einen Integrationscode in C zu sortieren. Ich folge einigen Ratschlägen im Artikel Families of periodic Horseshoe Orbits in the Restricted Three Body Problem . was mir ideale Anfangsbedingungen und die Gleichungen im Schwerpunktsystem gibt. (m ist die Masse der Erde und die daraus folgende Position der Sonne im Bezugssystem des Massenmittelpunkts, (x,y) sind die Koordinaten des dritten Körpers, der als masselos angenommen wird (wie es das eingeschränkte Problem erfordert).

Ö = ( X 2 + j 2 ) / 2 + ( 1 M ) R 1 + M R 2 + ( 1 M ) M 2
R 1 2 = ( X M ) 2 + j 2

R 2 2 = ( X M + 1 ) 2 + j 2
A ( X ) = D Ö D X + 2 v ( j )
A ( j ) = D Ö D j 2 v ( X )

Die Positionen von „Sonne“ und „Erde“ sind auf (m,0) und (m-1,0) im selben Bezugssystem festgelegt. (Rotierendes Bezugssystem, vorausgesetzt, die Erde hat eine kreisförmige Umlaufbahn.)

Aus all dem habe ich die Gleichungen zur Beschreibung des Systems berechnet:

A ( X ) = X + ( M 1 ) ( X M ) ( ( X M ) 2 + j 2 ) 1 .5 2 M ( X M + 1 ) ( ( X M + 1 ) 2 + j 2 ) 1 .5 + 2 v ( j )
A ( j ) = j j ( 1 M ) ( ( X M ) 2 + j 2 ) 1 .5 2 j M ( ( X M + 1 ) 2 + j 2 ) 1 .5 2 v ( X )

Ich habe den Algorithmus von Runge-Kutta 4 verwendet, um diese Gleichungen zu integrieren. (Ich weiß, dass der Code ziemlich umständlich ist, aber ich kann einfach keine Zeiger verwenden und ich verwende überall Strukturen).

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define dt 0.0001
#define N 100

typedef struct{
    long double x,y;
}vec;

typedef struct{
    vec k1,k2,k3,k4;
}runge;

typedef struct{
    runge r,v;
}big;

double dS,dE,m;

double accx(double,double,double);
double accy(double,double,double);
void rad(vec);
big rungekutta(vec,vec);
vec moto(vec,runge);
double jacobi(vec);

int main(){
  vec r,v;
    big f;
    double J,t;
    int i,Num;
    FILE* s1;
    s1=fopen("HorseShoe.dat","w");

    Num=(int)N/dt;
    scanf("%Lf",&r.x);
    scanf("%Lf",&r.y);
    scanf("%Lf",&v.x);
    scanf("%Lf",&v.y);
    scanf("%lf",&m);

    for(i=0;i<Num;i++){
        t=(i+1)*dt;
        rad(r);
        f=rungekutta(r,v);
        r=moto(r,f.r);
        v=moto(v,f.v);
        J=jacobi(r);
        fprintf(s1,"%lf\t%Lf\t%Lf\t%Lf\t%Lf\t%lf\n",t,r.x,r.y,v.x,v.y,J);
    }
return 0;
}

void rad(vec r){
    dS=pow(r.x-m,2)+pow(r.y,2);
    dE=pow(r.x-m+1,2)+pow(r.y,2);
}

double jacobi(vec r){
    return pow(r.x,2)+pow(r.y,2)+2*(1-m)/dS+2*m/dE+m*(1-m);
}

double accx(double x,double y,double v){
    return x-(x-m)*(1-m)/pow(pow(x-m,2)+pow(y,2),1.5)-m*(x-m+1)/pow(pow(x-m+1,2)+pow(y,2),1.5)+2*v;
}

double accy(double x,double y,double v){
    return y-(1-m)*y/pow(pow(y,2)+pow(x-m,2),1.5)-m*y/pow(pow(y,2)+pow(x-m+1,2),1.5)-2*v;
}

big rungekutta(vec r,vec v){
    big f;
    f.r.k1.x=v.x;
    f.r.k1.y=v.y;
    f.v.k1.x=accx(r.x,r.y,v.y);
    f.v.k1.y=accy(r.x,r.y,v.x);
    f.r.k2.x=v.x+f.v.k1.x*dt/2;
    f.r.k2.y=v.y+f.v.k1.y*dt/2;
    f.v.k2.x=accx(r.x+f.r.k1.x*dt/2,r.y+f.r.k1.y*dt/2,v.y+f.v.k1.y*dt/2);
    f.v.k2.y=accy(r.x+f.r.k1.x*dt/2,r.y+f.r.k1.y*dt/2,v.x+f.v.k1.x*dt/2);
    f.r.k3.x=v.x+f.v.k2.x*dt/2;
    f.r.k3.y=v.y+f.v.k2.y*dt/2;
    f.v.k3.x=accx(r.x+f.r.k2.x*dt/2,r.y+f.r.k2.y*dt/2,v.y+f.v.k2.y*dt/2);
    f.v.k3.y=accy(r.x+f.r.k2.x*dt/2,r.y+f.r.k2.y*dt/2,v.x+f.v.k2.x*dt/2);
    f.r.k4.x=v.x+f.v.k3.x*dt;
    f.r.k4.y=v.y+f.v.k3.y*dt;
    f.v.k4.x=accx(r.x+f.r.k3.x*dt,r.y+f.r.k3.y*dt,v.y+f.v.k3.y*dt);
    f.v.k4.y=accy(r.x+f.r.k3.x*dt,r.y+f.r.k3.y*dt,v.x+f.v.k3.x*dt);
    return f;
}

vec moto(vec r,runge rk){
    r.x+=(rk.k1.x+2*rk.k2.x+2*rk.k3.x+rk.k4.x)*dt/6;
    r.y+=(rk.k1.y+2*rk.k2.y+2*rk.k3.y+rk.k4.y)*dt/6;
    return r;
}

Wenn ich die Ergebnisse zeichne, erhalte ich nur eine Spirale, während ich mit den gegebenen Eingaben eine Hufeisenbahn erhalten sollte. Ich habe viele verschiedene Eingaben ausprobiert (m = 0,0001 und m = 0,000003, letzteres entspricht den tatsächlichen Werten der Erd- und Sonnenmassen (Sonnenmasse beträgt 1 m)).

Ich kann einfach nicht sehen, was falsch ist (wahrscheinlich alles :D), kann mir bitte jemand helfen?

Die Leute können vielleicht besser helfen, wenn Sie erklären, was Ihre Variablen (in den Gleichungen) sind: O, x, y, m, r1/2 usw. Außerdem macht Ihre Frage nicht klar, was das Problem ist, das Sie sind Begegnung. „Ich kann nicht sehen, was los ist“ – was soll man bekommen, und was bekommt man stattdessen?
Bevor ich fortfahre, würde ich gerne zwei Dinge sehen: Einen Link zu dem Referenzpapier, das Sie verwendet haben, um zu sehen, ob Sie einen Fehler in Ihrer Mathematik gemacht haben, und Ihre Eingaben. Ich vermute, Ihre Eingänge könnten ausgeschaltet sein. Dies ist ein nicht standardmäßiges Einheitensystem, in dem die Masse der Erde angegeben ist M sollte ungefähr sein 3 × 10 6 , die Masse der Sonne ist 1 minus dieser kleinen Zahl und der Betrag des Positionsvektors ( X , j ) ist ungefähr 1. Die Zeit scheint auch skaliert zu sein. Dies ist kein Ort für SI-Einheiten.
Ich habe gerade die Frage bearbeitet und die von Ihnen gestellten Details hinzugefügt (Entschuldigung, wenn ich etwas chaotisch bin, erste Frage hier). Ich habe G = 1 verwendet, natürlich konnte ich keine SI-Einheiten verwenden;)
Ich habe viele der in den Artikeln angegebenen Eingaben verwendet (mindestens eine pro Bahnfamilie), ich gebe Ihnen ein Beispiel. (x0=0.864394016091,y0=0,vx=0,vy=0.288028401448,m=0.0001)
Wow, ich habe gerade den Fehler gefunden, ich komme mir jetzt so blöd vor.. Danke trotzdem ;)
Sie können gerne eine Antwort auf Ihre eigene Frage posten, in der Sie detailliert beschreiben, was falsch war und wie Sie es behoben haben. Dies kann sich in Zukunft für andere als nützlich erweisen, die sich dieser Frage stellen!
Nur eine kleine, aber wichtige Bemerkung: 4ᵗʰ-Ordnung Runge-Kutta ist nicht symplektisch , das heißt, sie ändert die gesamte Orbitalenergie im Laufe der Zeit, zunächst langsam, aber in ihrer Schwere exponentiell zunehmend. Abhängig von Ihrem gewünschten Integrationsintervall sollten Sie RK4 besser zugunsten von etwas fallen lassen, das besser für die Himmelsmechanik geeignet ist. Siehe zum Beispiel dieses Papier für Hintergrundinformationen und Empfehlungen.

Antworten (1)

Ich werde weder Ihre Gleichungen noch Ihren Code sorgfältig durchgehen, aber da Sie die genauen Startpositionen, die Sie verwendet haben, nicht erwähnt haben, vermute ich, dass Sie nicht zuerst nach einem stabilen Hufeisenbahn-Zustandsvektor gelöst haben .

Die Positionen von Sonne und Erde sind im synodischen (rotierenden) Rahmen fixiert. Aber wo hast du deinen Astroiden angefangen? Für eine bestimmte Startposition müssen Sie dem Asteroiden auch die richtige Startgeschwindigkeit (Geschwindigkeit und Richtung) geben, sonst ist er möglicherweise nicht stabil und wandert einfach ab oder dreht sich um, wie Sie erwähnt haben.

Schauen Sie sich diese Antwort an , in der ich die richtigen Gleichungen zeige und dann nach stabilen Hufeisenbahnen löse, bevor ich sie zeichne.

Ich beginne mit einer Position auf der x-Achse, gegenüber der Erde und etwas weiter oder näher von der Sonne entfernt als die Erde. Dann starte ich es mit geringer Geschwindigkeit (im rotierenden Rahmen) genau in Richtung der y-Achse. Ich beobachte, wie es zur Erde driftet und dann als Bumerang zurück in die Region des Startgebiets. Wenn es die x-Achse wieder kreuzt, überprüfe ich, um zu sehen, wie nahe die Geschwindigkeit an y ist. Ich verwende einen Optimierungs-Nulllöser, brentqum die Anfangsgeschwindigkeit anzupassen, bis die Rückkehrgeschwindigkeit genau in die entgegengesetzte Richtung zeigt.

Wenn das stimmt, dann wird die Umlaufbahn periodisch und sich wiederholend sein, und wir können sie unter den Einschränkungen des CR3BP als abgestandene Umlaufbahn bezeichnen.


Aus dieser Antwort (dort gibt es noch viel mehr zu lesen, einschließlich mehrerer Referenzen!):

X ¨ = X + 2 j ˙ ( 1 μ ) ( X + μ ) R 1 3 μ ( X 1 + μ ) R 2 3
j ¨ = j 2 X ˙ ( 1 μ ) j R 1 3 μ j R 2 3
z ¨ = ( 1 μ ) z R 1 3 μ z R 2 3

Geben Sie hier die Bildbeschreibung ein

oben: Halbzyklen einiger wackeliger Hufeisenbahnen

Geben Sie hier die Bildbeschreibung ein

oben: Zeiten bis zum ersten Kreuzen der x-Achse der gleichen wackeligen Hufeisenbahnen, die zur Berechnung der Halbzykluszeiten verwendet werden.

Geben Sie hier die Bildbeschreibung ein

oben: Zykluszeiten aus dieser Berechnung (schwarze Punkte) versus aus der synodischen Periodenschätzungsmethode (rote Punkte). Gute qualitative Übereinstimmung. Auch die Startgeschwindigkeiten y an jedem Startpunkt in x.

unten: Python-Skript für diese Plots.

def x_acc(x, ydot):
    r1    = np.abs(x-x1)
    r2    = np.abs(x-x2)
    xddot = x + 2*ydot  -  ((1-mu)/r1**3)*(x+mu) - (mu/r2**3)*(x-(1-mu))
    return xddot

def C_calc(x, y, z, xdot, ydot, zdot):
    r1 = np.sqrt((x-x1)**2 + y**2 + z**2)
    r2 = np.sqrt((x-x2)**2 + y**2 + z**2)
    C = (x**2 + y**2 + 2.*(1-mu)/r1 + 2.*mu/r2 - (xdot**2 + ydot**2 + zdot**2))
    return C

def deriv(X, t): 
    x, y, z, xdot, ydot, zdot = X
    r1 = np.sqrt((x-x1)**2 + y**2 + z**2)
    r2 = np.sqrt((x-x2)**2 + y**2 + z**2)
    xddot = x + 2*ydot  -  ((1-mu)/r1**3)*(x+mu) - (mu/r2**3)*(x-(1-mu))
    yddot = y - 2*xdot  -  ((1-mu)/r1**3)*y      - (mu/r2**3)*y
    zddot =             -  ((1-mu)/r1**3)*z      - (mu/r2**3)*z
    return np.hstack((xdot, ydot, zdot, xddot, yddot, zddot))

# http://cosweb1.fau.edu/~jmirelesjames/hw4Notes.pdf

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint as ODEint
from scipy.optimize import brentq

halfpi, pi, twopi = [f*np.pi for f in (0.5, 1, 2)]

mu = 0.001

x1 = -mu
x2 = 1. - mu

x = np.linspace(-1.4, 1.4, 1201)
y = np.linspace(-1.4, 1.4, 1201)

Y, X = np.meshgrid(y, x, indexing='ij')
Z    = np.zeros_like(X)

xdot, ydot, zdot = [np.zeros_like(X) for i in range(3)]

C = C_calc(X, Y, Z, xdot, ydot, zdot)
C[C>8] = np.nan

if True:
    plt.figure()
    plt.imshow(C)
    plt.colorbar()
    levels = np.arange(2.9, 3.2, 0.04) 
    CS = plt.contour(C, levels,
                 origin='lower',
                 linewidths=2) 
    plt.show()

ydot0s   = np.linspace(-0.08, 0.08, 20)
x0ydot0s = []
for ydot0 in ydot0s:
    x0, infob =  brentq(x_acc, -1.5, -0.5, args=(ydot0), xtol=1E-11, rtol=1E-11,
                           maxiter=100, full_output=True, disp=True)
    x0ydot0s.append((x0, ydot0))

states = [np.array([x0, 0, 0, 0, ydot0, 0]) for (x0, ydot0) in x0ydot0s]

times  = np.arange(0, 150, 0.01)

results = []
for X0 in states:
    answer, info = ODEint(deriv, X0, times, atol = 1E-11, full_output=True)
    results.append(answer.T.copy())

resultz = []
for x0ydot0, thing in zip(x0ydot0s, results):
    y     = thing[1]
    check = y[2:]*y[1:-1] < 0
    zc    = np.argmax(y[2:]*y[1:-1] < 0) + 1
    if zc > 10:
        resultz.append((thing, zc, x0ydot0))

if True:
    plt.figure()
    hw = 1.6
    for j, (thing, zc, x0ydot0) in enumerate(resultz):
        x, y = thing[:2,:zc]
        plt.plot(x, y)
    plt.xlim(-hw, hw)
    plt.ylim(-hw, hw)
    plt.plot([x1], [0], 'ok')
    plt.plot([x2], [0], 'ok')
    plt.show()

if True:
    plt.figure()
    for j, (thing, zc, x0ydot0) in enumerate(resultz):
        x, y = thing[:2]
        plt.plot(times[:zc], y[:zc])
    plt.show()

if True:
    plt.figure()
    for j, (thing, zc, x0ydot0) in enumerate(resultz):
        x0, ydot0 = x0ydot0
        cycle_time = 2. * times[zc] / twopi
        ratio = abs(x0/x2)
        T_simple_model = twopi * abs(x0/x2)**1.5
        T_synodic_simple_model = 1. / (1. - twopi/T_simple_model) # https://astronomy.stackexchange.com/a/25002/7982
        plt.subplot(2, 1, 1)
        plt.plot(x0, cycle_time, 'ok')
        plt.plot(x0, abs(T_synodic_simple_model), 'or')
        plt.subplot(2, 1, 2)
        plt.plot(x0, ydot0, 'ok')
    plt.subplot(2, 1, 1)
    plt.xlabel('x0', fontsize=16)
    plt.ylabel('cycle times (periods)', fontsize=16)
    plt.subplot(2, 1, 2)
    plt.xlabel('x0', fontsize=16)
    plt.ylabel('ydot0', fontsize=16)
    plt.show()