Моделирование солнечной системы с помощью закона Ньютона

Я сделал симуляцию на С++ с законом Ньютона и протестировал ее, сравнивая положения планет с положением из Калькулятора Солнечной системы Дона Кросса (который я преобразовал из JavaScript в С++)
http://cosinekitty.com/solar_system.html

То, что я делаю, это каждый временной шаг (обычно 1 секунда, но шаг 0,2 секунды очень похож на шаг 10 секунд):

  1. Рассчитать ускорение ( "=" Ньютон Форзес × дельта-время)
  2. Скорость обновления и позиции
  3. Сравните позиции с результатами алгоритмов солнечного калькулятора Don Cross.
    Но после 10 дней моделирования я получаю это отклонение расстояния (до калькулятора от Don Cross):

М е р с ты р у   4498,7   к м

В е н ты с   Икс   1939,8   к м

Е а р т час   Икс   10614,6   к м

М о о н   Икс   7800,2   к м

М а р с   Икс   445,2   к м

С е р е с   Икс   129,5   к м

п а л л а с   Икс   432,4   к м

Дж ты н о   Икс   151,4   к м

В е с т а   Икс   157,6   к м

я г а   Икс   73,6   к м

г а с п р а   455,3   к м

9 п / Т 1   241,5   к м

19 п / Б   402,7   к м

67 п / С г   533,2   к м

81 п / Вт 2   110,7   к м

Дж ты п я т е р   172,3   к м

С а т ты р н   261,2   к м

U р а н ты с   71,4   к м

Н е п т ты н е   31,3   к м

п л ты т о   Икс     45,7   к м

Как вы видите, у некоторых планет отклонения небольшие, а у некоторых большие, поэтому мой вопрос: могут ли Ньютоновы быть точными? или Don Cross Солнечной системы калькулятор не? Или в этом районе есть черная материя? Или что еще?

void CGravitator::CalcAceleration(double timeseconds){
unsigned int i,j,iend;
if (sunStatic)iend=m_np-1;
else iend=m_np;
for (i = 0; i < iend; i++) {
        m_planetas[i].aceleration.set(0,0,0);
        CVector3 totalGravitationalForce;                                       
        // Loop through all bodies in the universe to calculate their gravitational pull on the object (TODO: Ignore very far away objects for better performance)


     for (j = 0; j < m_np; j++) {
            if (i == j) continue; // No need to calculate the gravitational pull of a body on itself as it will always be 0.                                
            double distancia =CVector3::Distancia(m_planetas[i].pos,m_planetas[j].pos);
            double force = KGNEWTON * m_planetas[i].masa * m_planetas[j].masa / pow(distancia, 2);
            CVector3 forceDirection = CVector3::Normalize(m_planetas[j].pos - m_planetas[i].pos);
            
            totalGravitationalForce += forceDirection * force;
        }
            CVector3 incspeed = totalGravitationalForce / m_planetas[i].masa ;          
        m_planetas[i].aceleration += incspeed * timeseconds;
        
    
}
Вы рассчитываете все силы между телами или только силы между каждым телом и Солнцем?
Кстати, довольно легко изменить ваш код с интеграции Эйлера на симплектический интегратор, такой как Verlet или Leapfrog, и вы сможете использовать гораздо больший временной шаг.
«Может ли Ньютон быть точным? Или калькулятор Солнечной системы Дон Кросса нет?» При написании нового кода моделирования всегда полезно сравнить его с чем-то более хорошо зарекомендовавшим себя. Но когда результаты различаются, по умолчанию следует исходить из того, что ошибка связана с вашим кодом.
Если вы переносите код, использующий тот же метод, рекомендуется проверить, что одни и те же входные данные (положение планет, временной шаг и т. д.) дают одинаковый результат, как предлагает jkej. Это больше похоже на упражнение по кодированию. Изучение проблем с помощью определенных численных методов является более математическим, а то, почему определенные методы лучше для определенных систем, является более физическим.
Здравствуйте, я суммирую все силы между всеми телами. Солнце начинается с (0,0,0) и может двигаться или нет (флажок), но движение солнца или нет дало очень похожие результаты. Мой код из перевода С++ дает те же результаты, что и исходный код Javascript, а код Ньютона очень прост, поэтому ошибки в коде нет.
И после суммы кода ускорения ускорьтесь до скорости и добавьте скорость * дельта-время к положению для каждой планеты. Я не знаю, если это метод Элулера
@LuisALberto Да. Вычисление мгновенной скорости и ускорения, а затем использование их вместе с Δ т обновить положение и скорость за один шаг самым простым разумным способом является прямой метод Эйлера. Некоторые более сложные общие методы используют новые положения и скорости для внесения поправок перед переходом к следующему временному шагу. Это приведет вас в страну Рунге-Кутта.
Это не обзор кода , поэтому я не буду делать это ответом, а дам несколько советов по числовой стабильности и производительности. # 1 Вы сначала умножаете, а затем делите на m_planetas[i].masa. Отмените их. (И измените «силу» в именах ваших переменных на «ускорение».) # 2 Сначала вы (предположительно) берете квадратный корень внутри, CVector3::Distanciaа затем возводите в квадрат расстояние. Отмените их тоже. И № 3 да, избегайте интеграции Эйлера. И # 4, пожалуйста, включите в свой вопрос код обновления фактической скорости и положения — в нем могут быть ошибки или числовые неточности, которые влияют на ваши результаты.
@LuisALberto, вы используете двойную точность (или более высокую точность) для вычислений с плавающей запятой?
Численное интегрирование, особенно движения планет, очень сложно. Некоторые методы практически не работают, некоторые совершенно нестабильны, а некоторые требуют очень тонкой настройки для получения точных результатов. Проблема не в Ньютоне: проблема в численном интегрировании.
Один из способов перепроверить вашу программу — вычислить общий импульс всех объектов в вашей системе. Это не должно меняться, поэтому любое изменение представляет собой какую-то ошибку. У вас всегда будет немного, но оно должно быть очень маленьким.
Да, интегрирование по Эйлеру - это "очевидный" алгоритм: Δ в "=" а Δ т , Δ Икс "=" в Δ т . Вместо массы более точно использовать стандартный гравитационный параметр ; Horizons использует значения, которые немного отличаются от тех, что указаны в Википедии.
Что вы используете для начальных положений и скоростей планет? Вы используете для этого программу Don Cross или Horizons? Кстати, среднее расстояние между центром Солнца и барицентром Солнечной системы составляет ~ 830 000 км, с максимальным значением около 1,5 млн км. В этом ответе у меня есть график (созданный с использованием Horizons) .
В опубликованном коде много неправильных вещей. Самым важным на сегодняшний день является то, что техника не использует скорость. а Δ т (ускорение, умноженное на временной шаг) — изменение скорости. Это не скорость планеты. Вам нужно интегрировать положение и скорость, что означает, что вам нужны начальное положение и начальная скорость.
@DavidHammen: Это очень хороший момент. Мы не знаем, что делает код OP с m_planetas[i].aceleration, так как они не опубликовали остальную часть, но значение, которое они хранят в этом векторе, не является ускорением. ( incspeed является ускорением, по крайней мере, при условии, что totalGravitationalForceэто действительно сила, но тогда оно умножается на интервал времени.)
Будет ли вычислительная наука лучшим местом для ответа на этот вопрос?
Код, который я сейчас использую, взят из Википедии Verlet Newton (но результаты немного отличаются от приведенных выше). Скорости и положения теперь взяты из файлов Horizon. Я также использовал библиотеку точности GMP, но это то же самое. Я также пытался найти массу солнца (по коду), но ошибка уменьшилась только вдвое. Возможно, скорость файлов Horizon (дельта-время 1 минута) в данный момент не идеальна (ньютоновская дельта-время составляет 0,1 секунды). А может быть, существует неоднородная черная материя?
Я обнаружил, что скорость Горизонта для каждого времени не является точной скоростью в это время, это средняя скорость до следующего временного шага, потому что добавление положения + скорость дает следующую позицию (и не точно, потому что x и y идеальны, а z нет¿ ¿¿¿WTF????. Таким образом, если с помощью файла Horizon необходимо найти начальную скорость, чтобы настроить Newton в порядке для расчета шага времени меньше, чем Horizon, потому что крошечная ошибка в начале будет расти и расти.

Ответы (3)

Вам нужно использовать лучший численный метод. Метод Эйлера, как известно, плох для орбитальной механики, потому что численные ошибки всегда накапливаются. В частности, метод Эйлера не сохраняет энергию, поэтому вы получаете орбиты, которые просто волшебным образом набирают энергию и выходят из-под контроля.

Вам нужно использовать что-то вроде метода Верле или какой-либо другой симплектический интегратор.

https://en.wikipedia.org/wiki/Verlet_integration

https://en.wikipedia.org/wiki/Symplectic_integrator

Спасибо, но я использовал код Verlet из Википедии и получил те же результаты.
Я бы рекомендовал использовать эфемериды JPL для проверки ваших вычислений: ssd.jpl.nasa.gov/horizons
Спасибо, я попытался разобрать файлы Horizon, но получил более серьезные ошибки! Также его минимальный временной шаг составляет 0,5 секунды. Поскольку некоторые планеты используют один и тот же код (в исходниках Дона Кросса), а те, у которых большие ошибки, имеют меньшие константы, я попробую с библиотекой точности, такой как gmp, но это утомительно.
Сомневаюсь, что gmp поможет. Вы просто будете иметь неточные позиции с высокой точностью.
Вам не нужно использовать симплектический интегратор. Например, JPL не использует его. Они используют интегратор семейства Адамса с переменным размером шага и переменным порядком. Может Коуэлл или Гаусс-Джексон? Это относится к семейству числовых интеграторов Адамса, и это положение и скорость различаются.
Дейк, ты прав, главная ошибка в том, что ты идешь не той дорогой. Я снова беру данные из файлов Horizon, и ошибка связана с расстоянием от солнца (Меркурий самый большой). Так что я думаю, что это масса, потому что это не точно. Сначала я смоделирую несколько массовых солнц и возьму лучшее с минимальной ошибкой на Горизонт. Затем отправляйтесь планета за планетой, делая то же самое.
@LuisALberto Но Меркурий - не самая большая ошибка, Земля и Луна, и это то, что меня действительно озадачивает в вашем вопросе. Обычно Меркурий всегда имеет самую большую ошибку (по нескольким причинам), поэтому, если что-то еще является самой большой (Земля-Луна), что устраняет большинство обычных виновников с одной причиной (несимплектическая интеграция, плохая G, плохая масса Солнца и т. д. .) Что отличает систему Земля-Луна, так это большой угловой наклон орбиты Луны и большую массу Луны по сравнению с ее первичной (Землей). Мне кажется, что что-то не так с исходными данными или z-вычислениями.

Помимо недостатков численного метода, указанных в другом ответе, моделирование орбиты Меркурия должно учитывать гравитацию Юпитера, а также релятивистские эффекты. Это объясняет лишь небольшую часть отклонения, но его следует учитывать, когда численный метод станет лучше.

По-видимому , прецессия перигелия Меркурия из-за притяжения Юпитера и релятивистских эффектов составляет около 574 угловых секунд за столетие, или 1,57E-2 угловых секунды в день. При окружности орбиты около 3,6E8 км и угловой секунде, равной 1,296E-6 оборота, это составляет около 4,3 км, или 43 км за 10 дней.

Хотя разница в положении перигелия напрямую не переводится в разницу в местоположении, она должна дать представление об эффекте.

спасибо, это дает мне представление о величине ошибки

Ошибка исходила из источников данных. Теперь я заменил на NAIF cspice.lib и скачал общий файл SPK только для планет, и ошибка действительно мала без других гравитационных тел, таких как астеориды и кометы. Очень просто использовать только 2 функции (furnsh_c и spkezr_c), include и lib.
Закодировано с помощью vc6++ pure win 32. Я запустил makeall.bat из разархивированного спайса (не смог заставить его работать в MFC).
Также временной шаг может составлять любую долю секунды, поэтому спайс и ньютон синхронизируются. Итак, Ньютон сказал мне, что черной материи не существует.
Вот результаты без гравитации астероидов и комет за 10 дней и без поправок в cpsice spkezr_c

ошибка расстояния в км ньютон (Верле) от spice
time = 864000,250
MERCURY BARYCENTER = 5,511496277969209e+002
SATURN BARYCENTER = 8.535731413118873e+001
VENUS BARYCENTER = 2.701394194074592e+002
URANUS BARYCENTER = 8.651056255887706e+001
EARTH = 9.664941717935676e+001
NEPTUNE BARYCENTER = 8.654038466254323e+001
MOON = 1.208560265740111e+002
MARS BARYCENTER = 5.954829440293592e+001
PLUTO BARYCENTER = 8.661640570487361E+001
Jupiter BaryCenter = 8.256645190275238E+001
Общее расстояние ошибок = 1,525933904320919e+003
Time Ini Gregorian
= 2000 январь 01: 00: 00.000 Время.