Физическая система Луна-Земля, проблемы с орбитой Луны

Я пытаюсь получить траектории орбиты Земли и Луны вокруг Солнца с помощью LeapFrog. Мне удалось получить правильную орбиту Земли, но в случае с Луной мне не удалось заставить ее вращаться вокруг Земли, в то время как обе вращаются вокруг Солнца. Я думаю, что это может быть проблема начальных условий, но я не уверен, это код, который я написал:

#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;

double Grav = 6.6726e-11;        // m^3/kg/s^2 (Universal gravitational constant)
double Msun = 1.989e30;          // kg
double Mearth = 5.973e24;        // kg
double Mmoon = 7.349e22;         // kg
double Dse = 1.496e11;           // distance Sun-Earth in meters
double Dem = 3.844e8;            // distance Earth-Moon in meters
int nsteps = 100;                  // Timesteps per orbit


void LeapFrog(int n)
{
    // Initial Conditions
    double x0 = Dse;
    double y0 = 0;

    double vx0 = 0;
    double vy0 = sqrt(Grav * Msun / Dse);

    double px0 = Mearth * vx0;
    double py0 = Mearth * vy0;

    // Initial Conditions for Moon
    double xm0 = Dse + Dem;
    double ym0 = 0;

    double vxm0 = sqrt(Grav * Mearth / Dem);  // La velocidad en x es opuesta a la velocidad orbital de la Tierra
    double vym0 = vy0;   // La velocidad en y es igual a la velocidad orbital de la Tierra

    double pxm0 = Mmoon * vxm0;
    double pym0 = Mmoon * vym0;

    // Timestep
    double dt = (2 * 3.141592654 * Dse / vy0) / nsteps;      // fraction of a year

    
    // Create a file for saving the coordinates of Earth
    ofstream earthFile("LFEarth.dat");
    // Create a file for saving the coordinates of Moon
    ofstream moonFile("LFMoon.dat");

    earthFile << x0 << " " << y0 << '\n';
    moonFile << xm0 << " " << ym0 << '\n';

    for (int i = 0; i < n; i++)
    {
        // Update Earth position
        double x = x0 + dt * px0 / (2 * Mearth);
        double y = y0 + dt * py0 / (2 * Mearth);

        // Update Moon position
        double xm = xm0 + dt * pxm0 / (2 * Mmoon);
        double ym = ym0 + dt * pym0 / (2 * Mmoon);

        // Calculate distances to the Sun
        double r_earth_sun = sqrt(x * x + y * y);
        double r_moon_sun = sqrt(xm * xm + ym * ym);
        double r_moon_earth = sqrt((xm-x)*(xm-x) + (ym-y)*(ym-y));

        // Update Earth momentum
        double px = px0 - dt * Grav * Msun * Mearth * x / pow(r_earth_sun, 3) - dt * Grav * Mmoon * Mearth * (x - xm) / pow(r_moon_earth, 3);
        double py = py0 - dt * Grav * Msun * Mearth * y / pow(r_earth_sun, 3) - dt * Grav * Mmoon * Mearth * y / pow(r_moon_earth, 3);

        // Update Moon momentum
        double pxm = pxm0 - dt * Grav * (Msun * Mmoon) * (xm) / pow(r_moon_sun, 3) - dt * Grav * (Mearth * Mmoon) * (xm - x) / pow(r_moon_earth, 3);
        double pym = pym0 - dt * Grav * (Msun * Mmoon) * (ym) / pow(r_moon_sun, 3) - dt * Grav * (Mearth * Mmoon) * (ym - y) / pow(r_moon_earth, 3);

        // Another Step for Earth position
        double x2 = x + dt * px / (2 * Mearth);
        double y2 = y + dt * py / (2 * Mearth);

        // Another Step for Moon position
        double xm2 = xm + dt * pxm / (2 * Mmoon);
        double ym2 = ym + dt * pym / (2 * Mmoon);

        earthFile << x2 << " " << y2 << std::endl;
        moonFile << xm2 << " " << ym2 << std::endl;

        // Initialise the values for the following step
        x0 = x2;
        y0 = y2;

        xm0 = xm2;
        ym0 = ym2;

        px0 = px;
        py0 = py;

        pxm0 = pxm;
        pym0 = pym;
    }
    // Close the files
    earthFile.close();
    moonFile.close();
}

int main()
{
    LeapFrog(nsteps * 10);                   // Ten orbits
    return 0;
}

И вот что я получил: Физическая система Луна-Земля, проблемы с орбитой Луны

Я ожидал, что Луна будет вращаться вокруг Земли, в то время как они оба вращаются вокруг Солнца.

Не могли бы вы также записать дифференциальные уравнения, которые вы решаете с помощью вашего алгоритма? Если вы решите их с помощью внешних инструментов, таких как Mathematica или Matlab, используя методы Рунге-Кутты более высокого порядка, получите ли вы правильные результаты?

pptaszni 18.04.2024 11:40

Не проверял ваш код, но подозреваю, что проблема в шаге по времени. Для моделирования вращения Солнца по орбите Земли лучший временной шаг составляет пару дней. Теперь в случае Луны это полностью потерпит неудачу, поскольку этот временной шаг просто слишком велик, а аппроксимация LeapFrog недостаточно хороша. Поэтому, пожалуйста, указывайте параметры моделирования в виде чисел в соответствующих единицах измерения.

Marek R 18.04.2024 11:40
godbolt.org/z/fKxcsGjd7 3,6 дня, когда одно вращение занимает 29 дней, это определенно большой шаг во времени. По сути, после 9 шагов Луна должна совершить полный оборот вокруг Земли.
Marek R 18.04.2024 11:51

Похоже, проблема с начальными условиями: вы смещаете Луну относительно Земли по оси X (xm0 = Dse + Dem), а это значит, что ее начальная скорость относительно Земли должна быть по оси Y. Но ваша начальная скорость также направлена ​​​​по оси X (vxm0 = sqrt(Grav * Mearth / Dem)): ваша луна начинает улетать от Земли.

Abstraction 18.04.2024 12:36

В расчете py также очевидная опечатка.

Abstraction 18.04.2024 12:42

Примечание: найдите функцию hypot и замените вызовы sqrt.

j6t 18.04.2024 12:42

@j6t: Я не уверен, что hypot лучше. Это позволяет избежать переполнения, но это требует времени. Если мы работаем в области, где сумма квадратов не переполняется, какую выгоду это даст hypot? Возможно, это читается более красиво, но это можно сделать с помощью пользовательской функции.

Eric Postpischil 18.04.2024 15:01

@EricPostpischil Позволяет писать аргументы в линейной форме вместо квадратов. Короче код, меньше ошибок. Да, определяемая пользователем функция тоже может это сделать.

j6t 18.04.2024 16:01
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
8
123
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем коде есть ряд ошибок... и в ваших ожиданиях.

На все это ссылались другие люди в комментариях:

(1) Вам нужно больше шагов на (земную) орбиту. Ведь в году 12 лунных месяцев (примерно).

(2) Выражение для py неверно, поскольку оно требует относительного смещения Луны и Земли.

(3) Ваши начальные условия немного неверны (альтернативная версия представлена ​​в виде комментария в коде ниже).

Но еще не упомянуты ваши ожидания в конечном итоге.

(4) Если вы нанесете траектории ОБА Земли и Луны на одном и том же графике, то, поскольку расстояние между Землей и Солнцем примерно в 500 раз больше, чем между Землей и Луной, вам понадобится и монитор, и зрение лучше, чем у меня, чтобы увидеть разница в орбитах.

В приведенный ниже код я добавляю еще один выходной файл «LFrelative.dat» (извините!), который показывает только положение Луны относительно Земли. На графике это дает орбиту нашего ближайшего небесного тела — обратите внимание, что масштаб совершенно другой.

#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;

const double Grav = 6.6726e-11;        // m^3/kg/s^2 (Universal gravitational constant)
const double Msun = 1.989e30;          // kg
const double Mearth = 5.973e24;        // kg
const double Mmoon = 7.349e22;         // kg
const double Dse = 1.496e11;           // distance Sun-Earth in meters
const double Dem = 3.844e8;            // distance Earth-Moon in meters
const int nsteps = 1000;               // Timesteps per orbit
const double PI = 4 * atan( 1.0 );


void LeapFrog(int n)
{
    // Initial Conditions
    double x0 = Dse;
    double y0 = 0;

    double vx0 = 0;
    double vy0 = sqrt(Grav * Msun / Dse);

    double px0 = Mearth * vx0;
    double py0 = Mearth * vy0;

    // Initial Conditions for Moon
    double xm0 = x0;                             //                           <--M
    double ym0 = Dem;                            //                              |
    double vxm0 = sqrt(Grav * Mearth / Dem);     //  S---------------------------E
    double vym0 = vy0;                      

    double pxm0 = Mmoon * vxm0;
    double pym0 = Mmoon * vym0;

    // Timestep
    double dt = (2 * PI * Dse / vy0) / nsteps;      // fraction of a year
    
    // Create a file for saving the coordinates of Earth
    ofstream earthFile("LFEarth.dat");
    // Create a file for saving the coordinates of Moon
    ofstream moonFile("LFMoon.dat");
    ofstream relativeFile("LFRelative.dat");

    earthFile    << x0       << " " << y0        << '\n';
    moonFile     << xm0      << " " << ym0       << '\n';
    relativeFile << xm0 - x0 << " " << ym0 - y0  << '\n';

    for (int i = 0; i < n; i++)
    {
        // Update Earth position
        double x = x0 + dt * px0 / (2 * Mearth);
        double y = y0 + dt * py0 / (2 * Mearth);

        // Update Moon position
        double xm = xm0 + dt * pxm0 / (2 * Mmoon);
        double ym = ym0 + dt * pym0 / (2 * Mmoon);

        // Calculate distances to the Sun
        double r_earth_sun = sqrt(x * x + y * y);
        double r_moon_sun = sqrt(xm * xm + ym * ym);
        double r_moon_earth = sqrt((xm-x)*(xm-x) + (ym-y)*(ym-y));

        // Update Earth momentum
        double px = px0 - dt * Grav * Msun * Mearth * x / pow(r_earth_sun, 3) - dt * Grav * Mmoon * Mearth * (x - xm) / pow(r_moon_earth, 3);
        double py = py0 - dt * Grav * Msun * Mearth * y / pow(r_earth_sun, 3) - dt * Grav * Mmoon * Mearth * (y - ym) / pow(r_moon_earth, 3);

        // Update Moon momentum
        double pxm = pxm0 - dt * Grav * Msun * Mmoon * xm / pow(r_moon_sun, 3) - dt * Grav * Mearth * Mmoon * (xm - x) / pow(r_moon_earth, 3);
        double pym = pym0 - dt * Grav * Msun * Mmoon * ym / pow(r_moon_sun, 3) - dt * Grav * Mearth * Mmoon * (ym - y) / pow(r_moon_earth, 3);

        // Another Step for Earth position
        double x2 = x + dt * px / (2 * Mearth);
        double y2 = y + dt * py / (2 * Mearth);

        // Another Step for Moon position
        double xm2 = xm + dt * pxm / (2 * Mmoon);
        double ym2 = ym + dt * pym / (2 * Mmoon);

        earthFile    << x2       << "  " << y2       << std::endl;
        moonFile     << xm2      << "  " << ym2      << std::endl;
        relativeFile << xm2 - x2 << "  " << ym2 - y2 << std::endl;

        // Initialise the values for the following step
        x0 = x2;
        y0 = y2;

        xm0 = xm2;
        ym0 = ym2;

        px0 = px;
        py0 = py;

        pxm0 = pxm;
        pym0 = pym;
    }
    // Close the files
    earthFile.close();
    moonFile.close();
    relativeFile.close();
}

int main()
{
    LeapFrog(nsteps * 10);             // Ten orbits
    return 0;
}

Земля и Луна в масштабе СОЛНЕЧНОЙ ОРБИТЫ:

ОРБИТА ЛУНЫ ОТНОСИТЕЛЬНО ЗЕМЛИ – обратите внимание на разницу в масштабе:

Это имеет большой смысл, меня это очень смутило, спасибо за ответ!

ivanlosarcos 19.04.2024 15:48

Другие вопросы по теме