Órbitas em ferradura e integração em C

8

Estou estudando um caso particular do problema restrito de três corpos. Verificou-se que alguns objetos seguem um padrão de órbita em ferradura e estou tentando resolver algo através de um código de integração em C. Estou seguindo alguns conselhos no artigo Famílias de órbitas em ferradura periódicas no problema restrito de três corpos , o que me dá condições iniciais ideais e as equações no sistema do centro de massa. (m é a massa da Terra e a conseqüente posição do sol no sistema de referência do centro de massa, (x, y) são as coordenadas do terceiro corpo, assumidas sem massa (conforme requer o problema restrito).

O=(x2+y2)/2+(1m)r1+mr2+(1m)m2
r1 12=(x-m)2+y2

r22=(x-m+1 1)2+y2
uma(x)=dOdx+2v(y)
uma(y)=dOdy-2v(x)

As posições do "sol" e "terra" são fixadas em (m, 0) e (m-1,0), no mesmo sistema de referência. (sistema de referência rotativo, assumindo que a Terra tenha uma órbita circular.)

De tudo isso, calculei as equações para descrever o sistema:

a (x) = x + \ dfrac {(m-1) (xm)} {((xm) ^ 2 + y ^ 2) ^ 1,5} - \ dfrac {2m (x-m + 1)} {((x (xm) ^ 2 + y ^ 2) ^ 1,5} + 2v (y)

uma(x)=x+(m-1 1)(x-m)((x-m)2+y2)1 1.5-2m(x-m+1 1)((x-m+1 1)2+y2)1 1.5+2v(y)
uma(y)=y-y(1 1-m)((x-m)2+y2)1 1.5-2ym((x-m+1 1)2+y2)1 1.5-2v(x)

Eu usei o algoritmo do Runge-Kutta 4 para integrar essas equações. (Eu sei que o código é bastante perturbador, mas eu simplesmente não posso usar ponteiros e uso estruturas em todos os lugares).

#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;
}

Traçando os resultados, eu apenas recebo uma espiral; enquanto estiver usando as entradas fornecidas, devo obter uma órbita em ferradura. Eu tentei muitas entradas diferentes (m = 0,0001 em = 0,000003, a última está em escala com os valores reais das massas da Terra e do Sol (a massa do sol é de 1 m)).

Eu simplesmente não consigo ver o que está errado (provavelmente tudo: D), alguém pode me ajudar?

Elisa
fonte
As pessoas podem ser mais capazes de ajudar se você explicar quais são suas variáveis ​​(nas equações): O, x, y, m, r1 / 2 etc. Além disso, sua pergunta não deixa claro qual é o problema. encontro. "Eu não consigo ver o que há de errado" - o que você deve receber e o que você recebe?
21416 Alex
Antes de prosseguir, gostaria de ver duas coisas: Um link para o documento de referência que você usou para verificar se você cometeu algum erro em sua matemática e suas informações. Eu suspeito que suas entradas podem estar desativadas. Este é um sistema não-padrão de unidades em que a massa da Terra deve ser cerca de , a massa do Sol é 1 menos esse número pequeno e a magnitude do vetor de posição é aproximadamente 1. O tempo também parece estar em escala. Este não é um local para unidades SI. m3×10-6(x,y)
David Hammen
Acabei de editar a pergunta, adicionando os detalhes que você pediu (desculpe se estou um pouco confusa, primeira pergunta aqui). I usado L = 1, é claro que não podia utilizar as unidades do SI;)
Elisa
5
Sinta-se à vontade para postar uma resposta para sua própria pergunta, detalhando o que estava errado e como você o corrigiu. Isso pode ser útil para outras pessoas no futuro que chegarem a essa pergunta!
Zephyr
2
Apenas uma observação pequena, mas importante: 4ᵗʰ ordem Runge-Kutta não é simplética , ou seja, altera a energia orbital total ao longo do tempo, lenta no início, mas aumentando exponencialmente em sua gravidade. Dependendo do intervalo de integração desejado, é melhor abandonar o RK4 em favor de algo mais adequado para a mecânica celeste. Veja, por exemplo, este documento para alguns antecedentes e recomendações.
Rody Oldenhuis

Respostas:

1

Não examinarei suas equações com cuidado nem seu código, mas como você não mencionou as posições iniciais exatas que utilizou, meu palpite é que você não resolveu primeiro um vetor de estado de órbita em ferradura estável primeiro.

As posições do Sol e da Terra são fixas no quadro sinódico (rotativo). Mas por onde você começou seu astroide? Para uma determinada posição inicial, você também deve fornecer ao asteróide a velocidade inicial correta (velocidade e direção), caso contrário ele poderá não ser estável e apenas se afastar ou espiralar como você mencionou.

Dê uma olhada nesta resposta, onde mostro as equações corretas e depois resolvo órbitas em ferradura estáveis ​​antes de plotá-las.

Começo com uma posição no eixo x, oposta à Terra, e um pouco mais distante ou mais próxima do Sol do que a Terra. Então eu o lanço com uma velocidade baixa (na estrutura rotativa) exatamente na direção do eixo y. Observo-o deslizar em direção à Terra e depois bumerangue de volta à região da área inicial. Quando ele cruza o eixo x novamente, verifico se a velocidade está próxima de y. Eu uso um solucionador de zero de otimização brentqpara ajustar a velocidade inicial até que a velocidade de retorno esteja exatamente na direção oposta.

Se isso for verdade, a órbita será periódica e repetida, e podemos chamá-la de órbita obsoleta sob as restrições do CR3BP.


A partir desta resposta (há muito mais para ler lá, incluindo várias referências!):

x¨=x+2y˙-(1 1-μ)(x+μ)r1 13-μ(x-1 1+μ)r23
y¨=y-2x˙-(1 1-μ)yr1 13-μyr23
z¨=-(1 1-μ)zr1 13-μzr23

insira a descrição da imagem aqui

acima: semi-ciclos de algumas órbitas em ferradura bambas

insira a descrição da imagem aqui

acima: tempos para as primeiras travessias do eixo x das mesmas órbitas em ferradura bambas, usadas para calcular os tempos de meio ciclo.

insira a descrição da imagem aqui

acima: tempos de ciclo deste cálculo (pontos pretos) versus o método de estimativa do período sinódico (pontos vermelhos). Bom acordo qualitativo. Também as velocidades y iniciais em cada ponto inicial em x.

abaixo: Script Python para esses gráficos.

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()
uhoh
fonte