Quỹ đạo móng ngựa và tích hợp trong C


8

Tôi đang nghiên cứu một trường hợp cụ thể của vấn đề ba cơ thể bị hạn chế. Người ta phát hiện ra rằng một số vật thể theo mô hình quỹ đạo móng ngựa và tôi đang cố gắng sắp xếp thứ gì đó thông qua mã tích hợp trong C. Tôi đang làm theo một số lời khuyên trong bài viết Các gia đình có quỹ đạo hình móng ngựa định kỳ trong vấn đề ba thân bị hạn chế , cung cấp cho tôi các điều kiện ban đầu lý tưởng và các phương trình ở trung tâm của hệ thống đại chúng. (m là khối lượng của Trái đất và vị trí của mặt trời ở trung tâm của hệ quy chiếu khối lượng, (x, y) là tọa độ của vật thể thứ ba, giả định không có khối lượng (như vấn đề hạn chế yêu cầu).

O=(x2+y2)/2+(1m)r1+mr2+(1m)m2
r12=(xm)2+y2

r22=(xm+1)2+y2
a(x)=dOdx+2v(y)
a(y)=dOdy2v(x)

Vị trí của "mặt trời" và "trái đất" được cố định là (m, 0) và (m-1,0), trong cùng một hệ quy chiếu. (hệ quy chiếu quay, giả sử trái đất có quỹ đạo tròn.)

Từ tất cả những điều này tôi đã tính toán các phương trình để mô tả hệ thống:

a(x)=x+(m1)(xm)((xm)2+y2)1.52m(xm+1)((xm+1)2+y2)1.5+2v(y)
a(y)=yy(1m)((xm)2+y2)1.52ym((xm+1)2+y2)1.52v(x)

Tôi đã sử dụng thuật toán của Runge-Kutta 4 để tích hợp các phương trình đó. (Tôi biết mã này khá khó hiểu, nhưng tôi không thể sử dụng con trỏ và tôi sử dụng cấu trúc ở mọi nơi).

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

Vẽ kết quả Tôi chỉ nhận được một vòng xoắn ốc, trong khi sử dụng các đầu vào đã cho, tôi sẽ có được quỹ đạo hình móng ngựa. Tôi đã thử nhiều đầu vào khác nhau, (m = 0,0001 và m = 0,000003, đầu vào có tỷ lệ với các giá trị thực tế của khối lượng Trái đất và Mặt trời (khối lượng mặt trời là 1 m)).

Tôi chỉ không thể nhìn thấy những gì sai (có thể là tất cả mọi thứ: D), bất cứ ai có thể xin vui lòng giúp tôi?


Mọi người có thể giúp đỡ tốt hơn nếu bạn giải thích các biến của bạn (trong các phương trình) là gì: O, x, y, m, r1 / 2, v.v. Ngoài ra, câu hỏi của bạn không làm rõ vấn đề là bạn là ai gặp phải "Tôi không thể nhìn thấy những gì sai" - bạn dự định sẽ nhận được gì và thay vào đó bạn nhận được gì?
Alex

Trước khi tiếp tục, tôi muốn xem hai điều: Liên kết đến tài liệu tham khảo mà bạn đã sử dụng để xem bạn có mắc lỗi trong toán học và các đầu vào của bạn không. Tôi nghi ngờ đầu vào của bạn có thể được tắt. Đây là một hệ đơn vị phi tiêu chuẩn, trong đó khối lượng của Trái đất phải bằng khoảng , khối lượng của Mặt trời nhỏ hơn 1 số nhỏ này và độ lớn của vectơ vị trí là khoảng 1. Thời gian dường như cũng được thu nhỏ lại. Đây không phải là nơi dành cho các đơn vị SI. m3×106(x,y)
David Hammen

Tôi vừa chỉnh sửa câu hỏi thêm chi tiết bạn đã hỏi (xin lỗi nếu tôi hơi lộn xộn, câu hỏi đầu tiên ở đây). Tôi đã sử dụng G = 1, tất nhiên tôi không thể sử dụng các đơn vị SI;)
Elisa

5
Vui lòng gửi câu trả lời cho câu hỏi của bạn nêu chi tiết những gì sai và cách bạn sửa nó. Điều này có thể chứng minh hữu ích cho những người khác trong tương lai đến với câu hỏi này!
zephyr

2
Chỉ là một nhận xét nhỏ nhưng quan trọng: Runge-Kutta theo thứ tự 4 không phải là đối xứng , nghĩa là, nó thay đổi tổng năng lượng quỹ đạo theo thời gian, lúc đầu chậm nhưng tăng theo cấp số nhân theo mức độ nghiêm trọng. Tùy thuộc vào khoảng thời gian tích hợp mong muốn của bạn, bạn đã có RK4 tốt hơn để ủng hộ một cái gì đó phù hợp hơn với cơ học thiên thể. Xem ví dụ bài viết này cho một số nền tảng và khuyến nghị.
Rody Oldenhuis

Câu trả lời:


1

Tôi sẽ không xem xét kỹ các phương trình của bạn cũng như mã của bạn, nhưng vì bạn chưa đề cập đến các vị trí bắt đầu chính xác mà bạn đã sử dụng, tôi đoán là trước tiên bạn chưa giải quyết được một vectơ trạng thái quỹ đạo ổn định .

Các vị trí cho Mặt trời và Trái đất được cố định trong khung đồng bộ (quay). Nhưng bạn đã bắt đầu astroid ở đâu? Đối với một vị trí bắt đầu nhất định, bạn cũng phải cung cấp cho tiểu hành tinh tốc độ bắt đầu chính xác (tốc độ và hướng) nếu không nó có thể không ổn định và chỉ đi lang thang hoặc xoắn ốc xung quanh như bạn đã đề cập.

Hãy xem câu trả lời này trong đó tôi chỉ ra các phương trình chính xác và sau đó giải các quỹ đạo móng ngựa ổn định trước khi vẽ đồ thị.

Tôi bắt đầu với một vị trí trên trục x, đối diện Trái đất và cách xa hơn một chút hoặc gần Mặt trời hơn Trái đất. Sau đó, tôi phóng nó với vận tốc thấp (trong khung quay) chính xác theo hướng của trục y. Tôi quan sát nó trôi dạt về Trái đất và sau đó boomerang trở lại khu vực của khu vực bắt đầu. Khi nó đi qua trục x lần nữa, tôi kiểm tra xem vận tốc gần với y như thế nào. Tôi sử dụng một bộ giải không tối ưu hóa brentqđể điều chỉnh vận tốc ban đầu cho đến khi tốc độ quay trở lại theo hướng ngược lại.

Nếu đó là sự thật, thì quỹ đạo sẽ là định kỳ và lặp lại, và chúng ta có thể gọi nó là quỹ đạo cũ dưới sự ràng buộc của CR3BP.


Từ câu trả lời này (có rất nhiều thứ để đọc ở đó, bao gồm một số tài liệu tham khảo!):

x¨=x+2y˙(1μ)(x+μ)r13μ(x1+μ)r23
y¨=y2x˙(1μ)yr13μyr23
z¨=(1μ)zr13μzr23

nhập mô tả hình ảnh ở đây

ở trên: nửa chu kỳ của một số quỹ đạo lắc lư

nhập mô tả hình ảnh ở đây

ở trên: thời gian để giao cắt trục x đầu tiên của cùng quỹ đạo lắc lư, được sử dụng để tính thời gian nửa chu kỳ.

nhập mô tả hình ảnh ở đây

ở trên: thời gian chu kỳ từ phép tính này (chấm đen) so với phương pháp ước lượng thời gian đồng bộ (chấm đỏ). Thỏa thuận định tính tốt. Ngoài ra vận tốc y bắt đầu tại mỗi điểm bắt đầu trong x.

bên dưới: Tập lệnh Python cho các ô này.

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()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.