Ограниченная задача трех тел: необходимо создать орбиту вокруг двух массивных тел.

У меня есть задание, и часть его включает в себя запуск спутника на орбиту Земли и Луны хотя бы один раз. Как бы то ни было, независимо от того, как я устанавливаю свое начальное условие или параметризую свое положение и время, меняю его, мой спутник не будет вращаться вокруг Луны и не вернется. Обратите внимание, что и Луна, и Земля лежат на оси x, система находится в их совместном вращении, я использую Рунге Кутта четвертого порядка для моделирования орбиты.

Обновление 1: после некоторого предложения из комментариев ниже моего сценария, чтобы объяснить проблему немного больше, когда я запускаю свой код, спутник выходит по спирали и не вращается по орбите, я также добавил график спутника

Обновление 2: Для тех, кому интересно, откуда я взял свой термин ускорения для спутника и почему он включает в себя Кориолиса и центробежную силу, а также гравитационную силу между спутником и Землей, а также спутником и луной, см. эту ссылку http://farside.ph.utexas. edu/teaching/336k/Newtonhtml/node123.html и глава 7 этого http://farside.ph.utexas.edu/teaching/336k/Newton.pdf

Обновлено 3:Исправлена ​​ошибка в положении спутника и опечатка в комментариях кода,обновлено изображение, которое соответствовало исправлению в коде

from pylab import plot,show,xlabel,ylabel,cla,clf
from numpy import linspace,exp,sin,cos,zeros,array,pi ,exp



M2 = 5.972e24 # M Earth kg
M1 = 7.34767309e22 # M moon kg
G= 6.6742e-11
R=3.844e8 #m Earth-moon distance
R_e =6371e3 # Earth radius
R_m = 1737e3 # Moon radius
M_0 = ((M2 - M1)/(M2 + M1))
alpha = pi/3
omega_0 = ((G*(M2 + M1))/(R**3))**(1/2)
T_a = (2*pi)/omega_0 # System period

def dot_p(a,b):
    n= len(a)
    d=0
    for i in range(n):
        d = d+ a[i]*b[i]
    return d

def abs_v(x):
    return (dot_p(x,x))**(1/2)

r_1 = array([(M2*R)/(M2 + M1),0,0],float) # Position of Moon
r_2 = array([-(M1*R)/(M2 + M1),0,0],float) #Position of Earth
omega =  array([0,0,omega_0],float) #Angular velocity of Earth and Moon

def F(r,t):
    r1 = r[0,:] #Earth position
    vr1 = r[1,:] #Earth velocity
    r2 = r[2,:] #Moon position
    vr2 = r[3,:] #Moon velocity
    r3 = array([R*cos(t),.5*R*sin(2*t),0],float)  +r[4,:] #Satellite position Figure 8 parameterization
    vr3 = r[5,:] #Satellite velocity
    fr1 = -G*M2*(r1 -r2)/(abs_v((r1-r2))**3)
    fr2 = -G*M1*(r2 -r1)/(abs_v((r2-r1))**3) 
    fr3 = (G*M1*(r3 -r_1)/(abs_v((r3-r_1))**3)) -(G*M2*(r3 -r_2)/(abs_v((r3-r_2))**3)) +2*omega_0*array([vr3[1],-vr3[0],0],float)+ (omega_0**2)*array([r3[0],r3[1],0],float) #Gravitational interaction of Satellite with Earth, Moon, Coriolis, and Centrifugal forces
    return array((vr1,fr1 ,vr2,fr2,vr3,fr3),float)



def RungeKutta4o(g,ksi10,vksi10,ksi20,vksi20,ksi30,vksi30,a,b): #Runge Kutta 4th order
    N=1000
    M = 6    
    h = float((b-a)/N)
    t = linspace(a,b,N)
    x1 = zeros((N,3),float)
    x2 = zeros((N,3),float)
    x3 = zeros((N,3),float)
    vx1 = zeros((N,3),float)
    vx2 = zeros((N,3),float)
    vx3 = zeros((N,3),float)
    r = array((ksi10,vksi10,ksi20,vksi20,ksi30,vksi30),float)
    k1 = zeros((M,3),float)
    k2 = zeros((M,3),float)
    k3 = zeros((M,3),float)
    k4 = zeros((M,3),float)
    for i in range(N):
        x1[i,:] = r[1,:]
        vx1[i,:] = r[0,:]
        x2[i,:] = r[3,:]
        vx2[i,:] = r[2,:]
        x3[i,:] = r[5,:]
        vx3[i,:] = r[4,:]
        k1 = h*g(r,t[i])
        k2 = h*g(r +.5*k1,t[i]+.5*h)
        k3 = h*g(r +.5*k2,t[i]+ .5*h)
        k4 = h*g(r +k3,t[i]+h)
        r += (1/6)*(k1 + 2*k2 + 2*k3 + k4)
    return t,x1,x2,x3,vx1,vx2,vx3 

cla()   # Clear axis
clf()
r_i0 = r_2 + array([0,R_e+300e3,0],float) # Satellite is initially in Earth orbit
vr_i0 = array([11000,0,0],float) # Initial velocity of satellite
t,R1,R2,R3,vR1,vR2,vR3  = RungeKutta4o(F,r_1,omega,r_2,omega,r_i0,vr_i0,0,10*T_a ) 
plot(R3[:,0],R3[:,1])  #Plots the Satellite orbit R3[:,0] is the x position of the satellite and R3[:,1] is the y position of the satellite
show() 

введите описание изображения здесь

Добро пожаловать на StackExchange! Если вы еще этого не сделали, подумайте о том, чтобы отправиться на экскурсию . Это не сайт для отладки программ, поэтому сначала вам нужно будет сделать хотя бы некоторые из них самостоятельно. Например, что происходит, когда вы запускаете его? Можете ли вы решить задачу с двумя телами (в основном с одним телом) и вывести свой спутник хотя бы на орбиту Земли? Я запустил ваш скрипт, а R3 даже не изменился - ваш спутник даже не двигается, так что у вас, вероятно, простая проблема с отладкой скрипта.
Сначала постарайтесь заставить более простую симуляцию работать правильно , а затем постепенно усложняйте ее. Алгоритм RK4 работает корректно - самостоятельно отлаживался? Кажется странным - ты размеришь к 1 , к 2 , к 3 , к 4 как массивы, а затем сразу назначать их как скаляры. На самом деле то, как написан алгоритм RK4, предполагает, что вы на самом деле не знакомы с python или numpy. Изучите их первыми!
@uhoh Сначала я сделал более простое моделирование, оно сработало, я предположил, что мой спутник движется, потому что я могу построить его положение. Когда я запускаю код, он разворачивается.
@uhoh, моя функция возвращает массивы, поэтому я написал ее так, поэтому присваиваю массивы при запуске кода
@ uhoh Вам нужно запустить R3[:,0], так как R - это просто постоянное расстояние
@uhoh Я добавил изображение того, что я рисую, и при запуске print(R3[:,0]) я получаю много разных значений
@uhoh хорошо, и спасибо за предложение, это помогло мне немного прояснить мой вопрос
Ага! Я использую Python 2 (общий для науки/инженерии), поэтому anything**(1/2)возвращает 1.0и 1/6возвращает ноль, поскольку Python 2 использует целочисленную математику для целочисленных типов, он не преобразуется в числа с плавающей запятой. Теперь я могу получить твою спираль, ура! Первое предложение, ваш временной шаг hсоставляет 0,01 месяца или около 6,5 часов. Вам нужно использовать гораздо меньшие временные шаги порядка минут, чтобы управлять орбитой вокруг Земли. Во-вторых, в CR3BP вы просто оставляете Землю и Луну неподвижными, вы не рассчитываете их движение. При вычислении ускорения должно учитываться только положение космического корабля (не говорите «Сила»).
Для лучшего python попробуйте перестать использовать так много массивов, если он станет медленным. В цикле каждый раз, когда вы вычисляете новую позицию, добавляйте ее в файл list. Когда вы закончите, преобразуйте список в массив. И, как я уже сказал, не позволяйте никакой информации о Земле или Луне даже попасть в расчеты. Весь смысл использования формализма CR3BP состоит в том, чтобы свести задачу к задаче с одним телом во вращающейся системе отсчета с эффективной силой, включающей центробежную.
Посмотрите на Python в этом вопросе , где я делаю гало-орбиты. Обычно CR3BP решается в безразмерных или приведенных единицах. Расстояние Земля-Луна равно 1,0, а период Земля-Луна равен 2 π (безразмерный). Вы также можете увидеть более удобный способ использования numpy для выполнения математических операций. В данном случае я использовал scipy.odeintвместо ручного RK4. Я рекомендую вам сначала убедиться, что ваш RK4 дает тот же ответ, что и odeint.
@uhoh Я сохраняю положение Земли и Луны постоянным и не меняю их, поэтому я использую r_1, r_2, которые не меняются. Для членов второй производной я сохраняю гравитационные члены, потому что спутник все еще находится в своем потенциале, и его энергия будет меняться в зависимости от его расстояния относительно них, и мне была поставлена ​​​​проблема с этими членами там, но без там расстояния, изменяющиеся только относительные расстояние спутника относительно них.
@uhoh Я не уверен, что вы имеете в виду, написанный третьей стороной. Я написал сценарий на основе параметров, которые мне дали.
Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что он спрашивает, почему плохо продуманный сторонний алгоритм не работает, по-видимому, не зная из первых рук, как он работает.
@uhoh, если вы не хотите помочь, хорошо, но ваши предложения не помогают мне с основной частью моего вопроса, а именно, как изменить текущую траекторию, чтобы она вращалась вокруг обоих тел, чтобы программа работала быстрее, а работа в нормализованных единицах не изменить фундаментальную форму кривой, с которой мне нужна была помощь.
@uhoh Даже если я уберу условия силы со спутников, что не имеет смысла, учитывая, как я уже сказал, что спутник все еще находится в потенциале системы, поэтому я сохраняю эти условия, он все равно не меняет спиральный узор, а только его величину.
@uhoh Поскольку вы так уверены, что я не понимаю эту тему, возможно, вам следует прочитать главу 7 этой книги, которая показывает, что уравнения движения в совместно вращающемся эталоне, в котором работает эта программа, такие, как я указал в моем вопросе выше . a = Fnet - F_coriolis F_centrifugal farside.ph.utexas.edu/teaching/336k/Newton.pdf , теперь я поставил ссылку выше в вопросе, который показывает, почему мое уравнение имеет смысл здесь также является ссылкой farside.ph.utexas .edu/teaching/336k/Newtonhtml/node123.html
Они не должны быть большими двумерными массивами, и их не нужно пересчитывать на каждом временном шаге. Вы вычисляете их один раз в основной программе. Добавление ссылки на математику чрезвычайно полезно для тех, кто хочет помочь в отладке; +1по математике! Поскольку вам потребуются временные шаги в 1 минуту или, возможно, несколько секунд с RK4, для двухнедельной миссии потребуется от 200 000 до 1 000 000 временных шагов. Если вы хотите хранить в памяти дюжину массивов размером 3 x 1 000 000 и выталкивать их из кэша, эта программа будет работать очень медленно.
@uhoh Спасибо за голосование, вы говорите, что списки были бы более эффективными в этом отношении с точки зрения скорости?
Я повторю свою рекомендацию: scipy.odeintсначала вы должны заставить его работать, а затем попытаться увидеть, возможно ли это даже с RK4, для которого требуются гораздо меньшие временные шаги, чем алгоритмы гораздо более высокого порядка с переменным размером шага в odeint. Опять же, посмотрите на питона здесь . Самый быстрый способ заставить программу работать — заставить ее работать по одной за раз. Гораздо быстрее, чем просто опубликовать неработающий скрипт в stackexchange.
Python управляет большими списками очень гибкими, эффективными и оптимизированными способами. Массивы NumPy — это большие тупые блоки памяти. Они чрезвычайно быстры для многих операций, но не для произвольного доступа или индексированного доступа из явного цикла Python.
Вот RK4 на питоне . В нем есть 2D-массивы, потому что в этом случае я сделал то же, что и вы, — предварительно выделил и заполнил массивы, но здесь все в порядке, потому что n=1000только, и я сделал это, потому что это # written for readability, not speed. Потому n=1000000что вы отбрасываете большие массивы и только .append()каждую новую позицию в список. Каждая позиция может быть небольшим массивом или списком. Кстати, я только что проверил это, и это все еще работает. Если вы загрузите блендер и вставите этот скрипт в редактор скриптов и нажмете «Выполнить», он создаст работающую анимацию.
Раскручивание предполагает, что ваша симуляция не сохраняет энергию, что может быть вызвано либо использованием слишком длинного временного шага интеграции, либо ошибкой в ​​​​вашем алгоритме интеграции.
@djr Это очень хороший момент. Однако в показанных данных временной шаг составляет 6,5 часов , то есть четыре полных оборота вокруг Земли, и кажется, что он начинается в точке примерно в 300 км от центра Земли! Изменение их не помогает, спираль надежна, что означает, что это просто мусор. Это плохо написанный, никогда не работавший сценарий, размещенный в надежде, что кто-то каким-то волшебным образом заставит его работать или просто опубликует новый.
@djr может ли это быть также из-за того, что метод RK4 имеет тенденцию не экономить энергию, и вам нужен адаптивный метод, чтобы исправить это?
Это может быть проблемой для любой схемы численного интегрирования, особенно если временной шаг слишком велик. Как указал @uhoh, вы используете 6,5-часовые временные интервалы, что слишком долго. Добейтесь, чтобы этот метод работал правильно, прежде чем беспокоиться о других.

Ответы (1)

То, о чем вы просите, называется траекторией свободного возврата .

Я не буду отлаживать вашу программу или решать проблему за вас (это ваша домашняя работа), но передам несколько советов, данных Бейтом, Мюллером и Уайтом*:

  • Существует более одного решения.
  • Не ждите точного решения, какими бы ни были ваши начальные условия.
  • Начните с использования исправленного конического метода.

Затем вы можете уточнить приблизительный ответ с помощью более точного численного интегрирования. Если ваш интегратор дает совершенно другой ответ, чем исправленные коники, попробуйте ввести несколько простых орбит Земли и посмотрите, имеют ли ответы смысл. Вы можете проверить орбиту с помощью аналитического метода для возмущений Луны. Скорее всего глючит интегратор.

Используйте аппроксимацию с заплатками, чтобы понять, как на эволюцию системы влияют небольшие изменения начальных условий. Подумайте о том, что происходит в точках исправления.

*Основы астродинамики, 1971, Дувр, упражнение 7.12 на с. 354.