Почему объекты в моделировании гравитации испытывают внезапные большие ускорения?

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

Через некоторое время планета в конце концов начнет двигаться вокруг Солнца по закону Ньютона.

Мой текущий подход таков: в любой момент я вычисляю значение гравитационной силы, которую солнце оказывает на планету ( М п масса планеты и М с масса Солнца):

Ф "=" г М п М с р 2

Затем я нахожу значение ускорения для планеты с помощью

А "=" Ф М п

Затем я нахожу угол, θ , линии, соединяющей центр планеты с центром солнца.

Затем я создаю вектор ускорения вдоль этой линии, создавая его компоненты x и y:

А Икс "=" А потому что θ А у "=" А грех θ

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

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

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

Если я правильно понял, проблема в том, что мое ускорение является функцией расстояния, поэтому я не могу интегрировать его, чтобы получить положение планеты, потому что для этого потребуется ускорение как функция времени. Я прав? Какое правильное решение?

Мой ответ на другой вопрос может быть полезен.
Кроме того, NBabel проводит набор н -коды тела, написанные на нескольких популярных языках (Fortran, C, C++, Python и т.д.); вам может быть интересно просмотреть эти коды.
Я удалил некоторые комментарии не по теме. Напоминаем всем, что комментарии предназначены для запроса разъяснений и предложений по улучшению поста, а также для временного указания связанных ресурсов. Точно не за ответ на вопрос!
что-то вроде этого документа решит вашу проблему.
Недавно я также наблюдал это явление при моделировании гравитации. Самая основная настройка, возможно, заключается в расчете гравитационного действия, так как оно будет на полшага опережать время приложения. Это означает, что ошибка квантования может как замедлить объекты, так и ускорить их. Это может быть связано с «интеграцией Verlet».
Я рекомендую перед использованием более сложных решений не допускать, чтобы расстояние (r) между солнцем и планетой становилось равным нулю. Наименьшее расстояние должно равняться радиусу солнца (R) + «разумное» расстояние (d), которое позволит избежать столкновения планеты с солнцем. Если вы хотите разрешить столкновение, проверьте расчет расстояния и, если 0 или отрицательное значение, «разбейте» планету взрывом, пропорциональным размеру планеты.

Ответы (5)

Если вам действительно нужен симулятор общей гравитации (т. е. тот, который будет обрабатывать более двух тел), то есть методы уменьшения ошибки, связанной с симуляцией, но нет никаких методов устранения ошибки. Ниже приведены несколько подходов — ни один из этих подходов не идеален, поскольку существует баланс между физической точностью, программированием и скоростью вычислений, а также сокращением поведения экранирования.

  1. Адаптивные временные шаги - когда ваша частица испытывает большие изменения в ускорении (т.е. когда она быстро движется рядом с массивным телом), вы можете уменьшить временной шаг г т так вы «пропускаете» меньше времени. Это повысит физическую точность симуляции, но также замедлит симуляцию (и замедлит ее неравномерно), так что это не лучший подход, если вы хотите, чтобы она выглядела хорошо в реальном времени.

  2. Твердые сферы - превращайте свои массы в твердые сферы, которые отскакивают друг от друга. Это уменьшит накопление ошибок, так как массы не будут приближаться друг к другу. Это может увеличить физическую точность симуляции, если только вы не возражаете против планет, которые подпрыгивают, как резиновые мячи (что, я полагаю, справедливое возражение — вы также можете сделать их неэластичными сферами, что, вероятно, более точно для планет).

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

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

Если вам нужна помощь в понимании реализации одного из этих методов, я могу объяснить более подробно.

Да, я думал о решении 2 и 3, но дело в том, что я хотел бы избежать подобных трюков, я использую эту симуляцию, чтобы улучшить свои знания в области исчисления, и я почти уверен, что есть способ решить проблему. используй это. Спасибо, в любом случае. И решение 4 действительно интересное.
Неупругие сферы на самом деле реализовать проще: заменить два исходных тела одним новым, просуммировав массы и просуммировав импульсы, разделив суммарный импульс на новую массу, чтобы получить новую скорость.

Brionus коснулся ключевого момента — адаптивных временных шагов. Когда вы начнете получать большие ускорения, уменьшите размер приращений времени. Кроме того, когда вы не сильно ускоряетесь, увеличьте размер.

Достаточно стандартный способ сделать это — рассчитать изменение позиции за один шаг. Затем разрежьте шаг пополам и, начиная с той же начальной точки, вычислите 2 последовательных шага положения. Сравните два последних изменения положения и, если они отличаются на какой-то заданный коэффициент (скажем, 10^-6), замените первоначальный временной шаг на меньший шаг и повторите вычисления. Если два шага совпали, попробуйте вычисление с временным шагом, в два раза превышающим исходный.

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

РЕДАКТИРОВАТЬ. В ответ на запрос о «подходе к исчислению»:

Подход к расчету, который вы использовали, будет работать для действительно простого симулятора, но он игнорирует взаимодействие между несолнечными телами, а также предполагает, что центральное солнце не движется. Чтобы справиться с этим, используйте более общий подход. Сохраните значения (x,y,z) (Vx,Vy,Vz) и (Mx,My,Mz) для ваших тел в массивах, проиндексированных таким же образом. Тогда гравитационное притяжение между любыми двумя телами будет просто вычисляться как (Fx, Fy, Fz), где

Ф н "=" Δ н Δ Икс 2 + Δ у 2 + Δ г 2 г М а М б Δ Икс 2 + Δ у 2 + Δ г 2
Рассчитайте каждый компонент отдельно и интегрируйте отдельно, чтобы получить новые скорости и положения. Также обратите внимание, что вам нужно будет рассчитать Н ( Н 1 ) значения для N тел (включая солнце), но это тело A притягивает тело B точно так же сильно, как тело B притягивает тело A, поэтому вам нужно выполнить численное вычисление только половины кажущейся суммы, хотя вам нужно будет осторожно меняйте знак, чтобы правильно получить другую половину значений. (Причина, по которой Н ( Н 1 ) скорее, чем Н 2 заключается в том, что вы не рассчитываете притяжение тела на себя.)

Для простого симулятора вы можете использовать интеграцию Эйлера. Учитывая силу, действующую на тело и его массу, для очень малого Δ т ты можешь сказать

Δ В "=" Ф Δ т М
и когда вы знаете и первоначальную скорость V, и изменение скорости, изменение положения Δ п является
Δ п "=" ( В + Δ В ) Δ т

Для коротких временных масштабов и очень малых Δ т это будет работать, но в основном вы пытаетесь аппроксимировать неправильную кривую прямыми сегментами, и в конечном итоге вы увидите большие и растущие ошибки. Таким образом, в течение более длительных периодов времени вы захотите использовать более сложные алгоритмы. Как заметил Зелдридж, Рунге-Кутта — хорошо известная альтернатива.

ВТОРОЕ РЕДАКТИРОВАНИЕ. Кроме того, при обновлении значений выполняйте каждый набор расчетов на основе одних и тех же исходных условий для всех тел. То есть, если вы вычисляете Vnew и Pnew для тела A, не вычисляйте результаты для тела B, используя обновленное Pnew для тела A. Вычислите весь новый массив значений V и P, затем замените старые значения как блок. .

Комментарии не для расширенного обсуждения; этот разговор был перемещен в чат .

Если вас не интересует полная симуляция n тел, и вы примете модель, в которой Солнце намного массивнее всех планет, вы можете сильно упростить ситуацию. У нас есть аналитическое решение задачи двух тел, так что вы можете применить солнечную гравитацию таким образом. Для каждой планеты, зная ее положение и скорость, вы можете вычислить ее угловой момент и энергию, а затем получить орбиту. Это позволяет вычислить положение планеты в конце временного шага, игнорируя притяжение всех планет. В нулевом порядке вы закончите, потому что игнорируете взаимодействие планет-планет. Если вы хотите применить взаимодействие планета-планета, вы можете вычислить силу, действующую на планету. я со всех остальных планет и применить ускорение на весь временной шаг. Поскольку сила намного меньше гравитации Солнца, изменение положения будет небольшим. Это уменьшит ваши ошибки, примерно как отношение сил на планете от других планет к силе от солнца. Затем вы можете применить адаптивные временные шаги и сохранение энергии, которые предлагают другие респонденты.

В этом посте Physics.SE обсуждаются параметризованные положения тел на орбите.

Другой подход к программированию в пошаговой анимации заключается в назначении переменных положения и импульса каждому из объектов. В терминах программирования у нас есть имя объекта, масса, местоположение x/y/z и импульс px/py/pz. Между каждым кадром для каждого объекта сначала рассчитайте его расстояние до каждого другого объекта и вычислите силу гравитации на этом объекте на основе закона обратной силы Ньютона; во-вторых, добавить силу к импульсу; наконец, добавьте импульс к местоположению (px=px+forcex, x=x+px).

Вы можете получить очень хорошую анимацию с помощью этого метода, где точность ограничена только точностью вычислений, частотой вычислений и начальным положением/импульсом каждого из объектов. Пример этого метода можно найти на http://www.animatedphysics.com/planets/Moon_Orbit.htm .

WRT ваша проблема «Основная проблема с этим подходом заключается в том, что как только планета достигает расстояния близкого к нулю от солнца, она получает огромное ускорение и на следующей итерации она просто слишком далеко от солнца и просто продолжает двигаться прямая линия, прямо из экрана». Это очень серьезная проблема. Если вы позволяете одному объекту приближаться к другому объекту сколь угодно близко, сила между объектами становится сколь угодно большой (поэтому объект внезапно выпрыгивает из поля зрения, как вы это чувствовали), независимо от того, насколько малы временные шаги, которые вы используете.

Я думаю, было бы очень поучительно, если бы @Brionius мог расширить свой вариант 4.

Основываясь на физической модели, которую вы принимаете (что только «солнце» оказывает гравитационное воздействие на «планеты» и что мы игнорируем гравитационное воздействие планет на солнце или друг на друга), что, безусловно, является достаточно приличным началом. точка (не говоря уже о достаточно хорошей для Кеплера по отношению к нашей собственной Солнечной системе), есть два основных момента, которые необходимо осознать:

1) СУЩЕСТВУЮТ законные орбиты (или, правильнее, назовем их траекториями), на которых планета не привязана к солнцу! То есть планета вместо того, чтобы двигаться по траектории, которая остается вблизи Солнца и периодически вращается вокруг него, может, в полном соответствии с законами Ньютона, двигаться по курсу, уводящему ее за пределы Солнечной системы и никогда не возвращающемуся ( и это может произойти даже после того, как планета совершит первоначальный сближение с Солнцем, что может навести на мысль, что она выходит на орбиту). Также, учитывая произвольные начальные скорости планет, мы не должны ожидать, что эти траектории будут редкими или необычными, хотя они могут быть и не теми, которые вас интересуют. Решение законов движения Ньютона вместе с его законом гравитации говорит нам, что траектория планеты будет одного из трех типов: эллиптического, параболического или гиперболического. Только первые из них, эллиптические траектории, замкнуты или ограничены. Теперь вполне возможно, даже вероятно, что наблюдаемые вами «убегающие» траектории действительно связаны с числовыми артефактами недостаточно точного алгоритма моделирования, но, вероятно, вам следует подтвердить, что это правда, в качестве первого шага, проверив что начальные скорости, которые вы приписываете планетам, достаточно малы, чтобы они не переводили планету на параболическую или гиперболическую траекторию. Если вы хотите полностью исключить такие траектории, как кажется, вы это делаете, было бы разумно написать свой код таким образом, чтобы пользователь не мог выбирать начальные скорости, которые привели бы к ним. Тест прост; просто потребуй этого что "убегающие" траектории, которые вы наблюдаете, на самом деле являются результатом численных артефактов недостаточно точного алгоритма моделирования, но вам, вероятно, следует подтвердить, что это правда, в качестве первого шага, проверив, что начальные скорости, которые вы приписываете планетам достаточно малы, чтобы планета не находилась на параболической или гиперболической траектории. Если вы хотите полностью исключить такие траектории, как кажется, вы это делаете, было бы разумно написать свой код таким образом, чтобы пользователь не мог выбирать начальные скорости, которые привели бы к ним. Тест прост; просто потребуй этого что "убегающие" траектории, которые вы наблюдаете, на самом деле являются результатом численных артефактов недостаточно точного алгоритма моделирования, но вам, вероятно, следует подтвердить, что это правда, в качестве первого шага, проверив, что начальные скорости, которые вы приписываете планетам достаточно малы, чтобы планета не находилась на параболической или гиперболической траектории. Если вы хотите полностью исключить такие траектории, как кажется, вы это делаете, было бы разумно написать свой код таким образом, чтобы пользователь не мог выбирать начальные скорости, которые привели бы к ним. Тест прост; просто потребуй этого но, вероятно, вам следует подтвердить, что это правда, в качестве первого шага, проверив, что начальные скорости, которые вы приписываете планетам, достаточно малы, чтобы они не переводили планету на параболическую или гиперболическую траекторию. Если вы хотите полностью исключить такие траектории, как кажется, вы это делаете, было бы разумно написать свой код таким образом, чтобы пользователь не мог выбирать начальные скорости, которые привели бы к ним. Тест прост; просто потребуй этого но, вероятно, вам следует подтвердить, что это правда, в качестве первого шага, проверив, что начальные скорости, которые вы приписываете планетам, достаточно малы, чтобы они не переводили планету на параболическую или гиперболическую траекторию. Если вы хотите полностью исключить такие траектории, как кажется, вы это делаете, было бы разумно написать свой код таким образом, чтобы пользователь не мог выбирать начальные скорости, которые привели бы к ним. Тест прост; просто потребуй этого Тест прост; просто потребуй этого Тест прост; просто потребуй этого в 2 < г М / р , где в - начальная полная скорость планеты и р - расстояние от Солнца до планеты в момент измерения начальной скорости. Возможно, вы захотите пойти еще дальше и потребовать, чтобы эксцентриситет всех эллиптических орбит был достаточно мал, чтобы планета не покидала экран (как это может быть, например, для кометоподобного объекта Галлея, который, хотя и связан с нашим Солнцем, изменяет расстояние до Солнца в 70 раз за 76-летний период обращения). Требуя, чтобы а 1 2 р в 2 г М , так называемая «большая полуось» орбиты, меньше, чем расстояние от солнца до края экрана, вы можете быть уверены, что любые планеты, которые покидают экран, никогда не возвращаются и представляют собой либо параболические /гиперболические траектории или, если они были исключены, числовые артефакты.

2) Возможно, более важным, поскольку он может значительно улучшить простоту, точность и эффективность вашего кода, является то, что законы Ньютона при ваших физических предположениях полностью разрешимы , а это означает, что нет необходимости моделировать физику ( !). Это называется проблемой двух тел (несмотря на то, что существует несколько планет, мы предполагаем, что они не взаимодействуют друг с другом, поэтому путь каждой планеты полностью определяется ее взаимодействием ровно с одним другим объектом, Солнцем), и, по сути, это расчет, сделанный Кеплером, чтобы показать, что планеты движутся по эллиптическим орбитам. Как-то сложно записать Икс и у позиции как функция времени при произвольном начальном положении и скорости планеты, поэтому я не буду делать это здесь, но статья в Википедии об «орбитах Кеплера» и ссылки в ней содержат все уравнения, которые нужно было бы массировать, чтобы получить желаемый результат (обратите внимание, что здесь предполагается, что мы берем направление перигелия / афелия орбиты, чтобы выровнять его с одной из осей координат, и для восстановления более общего результата потребуется выполнить изменение базиса). На самом деле я сотрудник Wolfram Alpha, и я удивлен, что у нас нет параметрических результатов для Икс и у как функция времени для задачи Кеплера, доступной на нашем сайте. Но я буду работать над тем, чтобы исправить это в будущем и обновить свой ответ здесь, если/когда я это сделаю! Однако достаточно сказать, что если вы не заботитесь о межпланетных взаимодействиях, то моделирование законов Ньютона определенно не является правильным подходом к этой проблеме, и такие вещи, как адаптивные временные шаги, хотя они и работали бы, были бы неэффективны. массовое излишество.