Привет, Хабр! Сегодня мы отправимся в увлекательное путешествие по просторам Вселенной, не вставая из-за компьютера. Задумывались ли вы, как планеты удерживаются на своих орбитах, почему галактики не разлетаются в разные стороны, и что заставляет яблоки падать на землю (да-да, снова этот старина Ньютон)? Ответ один – гравитация! Эта невидимая, но всемогущая сила правит бал во Вселенной, от мельчайших пылинок до гигантских скоплений галактик. Мы разберёмся, как из простых законов рождаются сложные и красивые взаимодействия, напишем код, который оживит наши виртуальные миры, и, возможно, даже почувствуем себя немного демиургами, управляющими судьбами звёзд.

Что такое гравитация и с чем её едят?

Итак, прежде чем мы начнём кодить наш симулятор, давайте немного освежим в памяти, что же такое гравитация. Если отбросить сложные формулы и заумные определения, то гравитация – это фундаментальное взаимодействие, которое заставляет любые два объекта, обладающие массой, притягиваться друг к другу. Да-да, не только Земля притягивает яблоко, но и яблоко (пусть и очень-очень слабо) притягивает Землю!

Впервые математически описал этот закон Исаак Ньютон в своём знаменитом труде "Математические начала натуральной философии". Его закон всемирного тяготения гласит, что сила притяжения F между двумя телами пропорциональна произведению их масс (m1 и m2) и обратно пропорциональна квадрату расстояния (r) между ними:

F = G * (m1 * m2) / r^2

Где G – это гравитационная постоянная, эдакий коэффициент пропорциональности, который определяет силу гравитационного взаимодействия во Вселенной. Звучит просто, не так ли? Но именно этот, на первый взгляд, незамысловатый закон управляет движением планет, формированием звёзд и галактик, и даже такими экзотическими объектами, как чёрные дыры.

Конечно, позже Альберт Эйнштейн в своей Общей теории относительности (ОТО) предложил более глубокое понимание гравитации, описав её не как силу, а как проявление искривления пространства-времени массивными телами. Представьте себе натянутую простыню, на которую положили тяжёлый шар – он создаст углубление, и любой другой, более лёгкий шарик, катящийся мимо, будет отклоняться к нему, как будто притягиваясь. Это очень упрощённая аналогия, но она помогает понять суть ОТО. Для наших целей, симуляции движения планет или звёзд в "обычных" условиях, ньютоновской гравитации будет более чем достаточно. Она проще в расчётах и даёт очень точные результаты для большинства астрофизических задач, не связанных с экстремальными гравитационными полями или скоростями, близкими к скорости света.

От теории к симуляции: как заставить компьютеры считать гравитацию?

Хорошо, с теорией разобрались. Но как заставить компьютер симулировать это взаимодействие для множества тел? Ведь в реальных системах, будь то Солнечная система или целая галактика, тел может быть очень много, и каждое из них взаимодействует с каждым другим! Это так называемая "задача N тел" (N-body problem).

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

Основная идея численного моделирования гравитационного взаимодействия заключается в следующем:

  1. Задаём начальные условия: для каждого тела (частицы) в нашей системе мы определяем его массу, начальное положение (координаты x, y, z) и начальную скорость (компоненты vx, vy, vz).

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

  3. Вычисляем ускорение: зная силу и массу частицы (второй закон Ньютона, F=ma), мы находим её ускорение (a = F/m).

  4. Обновляем скорость и положение: используя вычисленное ускорение и небольшой временной шаг (dt), мы обновляем скорость частицы, а затем, зная новую скорость, обновляем её положение. Существуют различные численные методы для этого шага (например, метод Эйлера, метод Верле, методы Рунге-Кутты), которые отличаются точностью и вычислительной сложностью.

  5. Повторяем: шаги 2-4 повторяются многократно, продвигая систему во времени и позволяя нам наблюдать за эволюцией её состояния.

Звучит довольно прямолинейно, но дьявол, как всегда, в деталях. Основная вычислительная сложность кроется в шаге 2 – расчёте сил. Если у нас N частиц, то для каждой из них нужно рассчитать N-1 взаимодействие. Итого, на каждом шаге нам нужно выполнить порядка N^2 операций. Это называется прямым суммированием. Для небольшого количества тел (десятки, сотни) это вполне приемлемо. Но что если мы хотим смоделировать галактику, состоящую из миллионов или миллиардов звёзд? N^2 становится астрономически большим числом, и прямой расчёт займёт вечность даже на самых мощных суперкомпьютерах.

Ускоряем расчёты

Именно здесь на сцену выходят более продвинутые и хитрые алгоритмы, которые позволяют значительно сократить количество вычислений без существенной потери точности. Два наиболее известных из них – это метод Барнса-Хата (Barnes-Hut) и метод Particle Mesh (PM).

Метод Барнса-Хата (Barnes-Hut):

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

Представьте, что вы смотрите на далёкое скопление звёзд. Вы не видите каждую звезду по отдельности, а воспринимаете их как единое светящееся пятно. Метод Барнса-Хата делает нечто похожее: он рекурсивно делит всё пространство симуляции на ячейки (обычно с помощью дерева октантов в 3D или квадродерева в 2D). Если ячейка находится достаточно далеко от рассматриваемой частицы и её размер достаточно мал по сравнению с расстоянием до неё, то все частицы внутри этой ячейки аппроксимируются одной суперчастицей. Если же ячейка близко или слишком велика, мы продолжаем деление, пока не дойдём до отдельных частиц или достаточно мелких ячеек.

Этот подход позволяет сократить количество вычислений с O(N^2) до O(N log N), что является огромным выигрышем для больших N. Конечно, это вносит некоторую погрешность, но для многих космологических симуляций она вполне допустима.

Метод Particle Mesh (PM):

Этот метод использует совершенно другой подход. Вместо прямого расчёта сил между частицами, он сначала распределяет массу частиц по узлам регулярной сетки (mesh), наложенной на пространство симуляции. Затем, используя эту сеточную плотность, он решает уравнение Пуассона (которое связывает гравитационный потенциал с распределением масс) с помощью быстрых алгоритмов, таких как Быстрое Преобразование Фурье (БПФ, FFT). Получив гравитационный потенциал на сетке, можно вычислить силу гравитации в каждом узле сетки. Наконец, сила, действующая на каждую частицу, интерполируется из значений в ближайших узлах сетки.

Метод PM очень эффективен для моделирования крупномасштабной структуры Вселенной, где важны дальнодействующие гравитационные силы. Его сложность составляет примерно O(N log N) или даже O(N), если N сопоставимо с количеством узлов сетки. Однако он хуже справляется с моделированием плотных областей и близких взаимодействий частиц, так как разрешение ограничено размером ячейки сетки. Часто его комбинируют с другими методами (например, Particle-Particle Particle-Mesh, или P3M), где дальнодействующие силы считаются через сетку, а близкодействующие – прямым суммированием или методом Барнса-Хата.

Для нашей сегодняшней статьи мы сосредоточимся на прямом суммировании, так как оно наиболее просто для понимания и реализации, и отлично подходит для симуляции небольших систем, таких как наша Солнечная система. Но знание о существовании более продвинутых методов, таких как Барнс-Хат и PM, важно для понимания того, как учёные моделируют действительно большие космические структуры.

Кодим гравитацию

Итоговая программа
Итоговая программа

Ну что ж, друзья, теория – это, конечно, хорошо, но пора переходить к практике! Как говорится, меньше слов – больше кода. Сейчас мы с вами напишем тот самый симулятор гравитации на Python, который позволит нам воочию увидеть, как планеты кружатся вокруг Солнца, и даже поэкспериментировать с собственными звёздными системами. Готовы почувствовать себя немного программистом-астрофизиком? Тогда поехали!

Для начала, нам понадобятся несколько библиотек: numpy для эффективной работы с массивами (ведь у нас будут координаты, скорости, силы – всё это удобно представлять в виде векторов и матриц) и matplotlib для визуализации наших космических танцев. Если у вас их ещё нет, то самое время установить:

pip install numpy matplotlib

А теперь – сам код! Я буду приводить его по частям и подробно комментировать каждый шаг, чтобы вы не только скопировали его, но и поняли, что там происходит под капотом.

Шаг 1: Определяем класс для наших частиц (планет, звёзд и т.д.)

Давайте создадим класс Particle, который будет представлять собой отдельный объект в нашей симуляции. У каждой частицы будут свои свойства: масса, текущие координаты, текущая скорость, имя (для красоты) и цвет (для наглядности на графике). А ещё мы будем хранить историю её перемещений (путь), чтобы потом красиво отрисовать траекторию.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# Константы
G = 6.67430e-11  # Гравитационная постоянная, м^3 кг^-1 с^-2
DT = 3600 * 24   # Шаг по времени (1 день в секундах)

class Particle:
    def __init__(self, mass, x, y, vx, vy, name="Particle", color=\'blue\'):
        self.mass = float(mass) # Масса частицы в кг
        self.pos = np.array([float(x), float(y)], dtype=float) # Положение [x, y] в метрах
        self.vel = np.array([float(vx), float(vy)], dtype=float) # Скорость [vx, vy] в м/с
        self.name = name
        self.color = color
        self.path = [self.pos.copy()] # Список для хранения траектории
        self.acc = np.zeros(2, dtype=float) # Текущее ускорение, инициализируем нулями

    def update_force(self, force):
        # Обновляем ускорение на основе силы (F=ma => a=F/m)
        self.acc = force / self.mass

    def update_velocity(self, dt):
        # Обновляем скорость на основе ускорения и шага времени (v = v0 + a*dt)
        self.vel += self.acc * dt

    def update_position(self, dt):
        # Обновляем положение на основе скорости и шага времени (x = x0 + v*dt)
        self.pos += self.vel * dt
        self.path.append(self.pos.copy()) # Добавляем новую точку в траекторию

Что тут у нас?

  • В init мы инициализируем все основные параметры частицы. Обратите внимание, что координаты и скорости – это numpy массивы, что упростит нам векторные вычисления.

  • update_force просто вычисляет ускорение на основе приложенной силы.

  • update_velocity и update_position – это простейшая реализация метода Эйлера для численного интегрирования. Мы предполагаем, что на небольшом временном шаге dt ускорение постоянно, и на основе этого обновляем скорость, а затем, используя новую скорость, обновляем положение. Для более точных симуляций можно использовать более сложные методы (например, Верле или Рунге-Кутты), но для наглядности Эйлер нам вполне подойдёт.

  • Мы также определили гравитационную постоянную G и временной шаг DT. DT здесь равен одному дню в секундах – это значит, что на каждом шаге наша симуляция будет продвигаться вперёд на один день.

Шаг 2: Функция для расчёта гравитационной силы

Теперь напишем функцию, которая будет считать ту самую силу притяжения между двумя частицами по закону Ньютона.

def calculate_gravitational_force(p1, p2):
    # Вектор, направленный от p1 к p2
    r_vec = p2.pos - p1.pos
    # Расстояние между частицами
    r_mag = np.linalg.norm(r_vec)

    # Избегаем деления на ноль, если частицы оказались в одной точке
    if r_mag == 0:
        return np.zeros(2) # Возвращаем нулевую силу

    # Единичный вектор, направленный от p1 к p2
    r_hat = r_vec / r_mag

    # "Смягчение" для предотвращения слишком больших сил на малых расстояниях
    # Это помогает стабилизировать симуляцию при близких прохождениях
    # и избежать "улетания" частиц из-за огромных ускорений.
    # Значение softening_factor можно подбирать.
    softening_factor = 1e9 # Для масштабов Солнечной системы
    
    # Величина силы по закону Ньютона, с учётом смягчения
    force_mag = (G * p1.mass * p2.mass) / (r_mag**2 + softening_factor**2)
    
    # Вектор силы, действующей на p1 со стороны p2
    force_vec = force_mag * r_hat
    return force_vec

Здесь всё по формуле: считаем вектор расстояния r_vec, его модуль r_mag, затем единичный вектор r_hat. Важный момент – softening_factor. Зачем он нужен? При очень близком сближении частиц знаменатель r_mag^2 становится очень маленьким, а сила – огромной. Это может привести к нереалистично большим ускорениям и

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

Шаг 3: Задаём начальные условия – наша Солнечная система (в миниатюре)

Теперь самое интересное – создадим объекты для нашей симуляции. Возьмём упрощённые данные для Солнца и нескольких планет. Массы указаны в килограммах, расстояния – в метрах от Солнца (по оси X, для простоты), скорости – в м/с (начальная скорость по оси Y, чтобы они начали двигаться по орбите).

# --- Начальные условия для симуляции Солнечной системы (упрощенно) ---
# Массы в кг, расстояния в метрах, скорости в м/с

# Солнце (почти неподвижно в центре, но для общности зададим ему нулевую скорость)
sun = Particle(mass=1.989e30, x=0, y=0, vx=0, vy=0, name="Sun", color=\'yellow\')

# Земля
earth_mass = 5.972e24
earth_distance = 1.496e11 # Среднее расстояние от Земли до Солнца (1 астрономическая единица)
earth_velocity = 29780   # Средняя орбитальная скорость Земли
earth = Particle(earth_mass, earth_distance, 0, 0, earth_velocity, name="Earth", color=\'blue\')

# Марс
mars_mass = 0.64171e24
mars_distance = 2.279e11 # Среднее расстояние от Марса до Солнца
mars_velocity = 24070   # Средняя орбитальная скорость Марса
mars = Particle(mars_mass, mars_distance, 0, 0, mars_velocity, name="Mars", color=\'red\')

# Венера
venus_mass = 4.867e24
venus_distance = 1.082e11 # Среднее расстояние от Венеры до Солнца
venus_velocity = 35020   # Средняя орбитальная скорость Венеры
venus = Particle(venus_mass, venus_distance, 0, 0, venus_velocity, name="Venus", color=\'orange\')

# Меркурий
mercury_mass = 0.330e24 # Масса Меркурия
mercury_distance = 0.579e11 # Среднее расстояние от Меркурия до Солнца
mercury_velocity = 47360    # Средняя орбитальная скорость Меркурия
mercury = Particle(mercury_mass, mercury_distance, 0, 0, mercury_velocity, name="Mercury", color=\'gray\')

# Собираем все наши частицы в один список
particles = [sun, earth, mars, venus, mercury]

Конечно, это очень упрощённая модель: мы не учитываем эллиптичность орбит, их наклонения, взаимодействие планет друг с другом на начальном этапе (хотя в цикле симуляции оно будет!). Но для демонстрации принципа – самое то!

Шаг 4: Основной цикл симуляции и магия анимации

А вот и сердце нашего симулятора – цикл, в котором будут происходить все расчёты и обновления, и код для анимации с помощью matplotlib.animation.FuncAnimation. Эта функция позволяет создавать "живые" графики, обновляя их на каждом кадре.

# --- Основной цикл симуляции и визуализация ---
fig, ax = plt.subplots() # Создаём фигуру и оси для графика
ax.set_aspect(\'equal\')    # Делаем масштабы по осям одинаковыми, чтобы круги были кругами
ax.set_xlabel("X (m)")
ax.set_ylabel("Y (m)")
ax.set_title("Симуляция гравитации (Солнечная система)")

# Динамически настраиваем пределы отображения, чтобы все поместилось
# Находим максимальное начальное расстояние от Солнца
max_initial_dist = 0
if len(particles) > 1:
    max_initial_dist = max(np.linalg.norm(p.pos) for p in particles if p.name != "Sun")
if max_initial_dist == 0: # Если только Солнце или все в центре
    max_initial_dist = 1e11 # Некое значение по умолчанию

ax.set_xlim(-max_initial_dist * 1.5, max_initial_dist * 1.5)
ax.set_ylim(-max_initial_dist * 1.5, max_initial_dist * 1.5)

# Создаём объекты для отображения частиц (точки) и их траекторий (линии)
scatter_plots = [ax.plot([], [], \'o\', markersize=10 if p.name == "Sun" else 5, color=p.color, label=p.name)[0] for p in particles]
path_plots = [ax.plot([], [], \'-\\, color=p.color, alpha=0.5)[0] for p in particles]

ax.legend() # Показываем легенду (имена планет)
ax.grid(True) # Включаем сетку для наглядности

# Функция инициализации для анимации (что нарисовать в самом начале)
def init():
    for plot in scatter_plots:
        plot.set_data([], [])
    for plot in path_plots:
        plot.set_data([], [])
    return scatter_plots + path_plots

# Функция, которая будет вызываться для каждого кадра анимации
def animate(frame_num):
    # 1. Рассчитываем силы, действующие на каждую частицу
    forces = {p.name: np.zeros(2, dtype=float) for p in particles} # Словарь для хранения сил
    for i in range(len(particles)):
        for j in range(i + 1, len(particles)):
            p1 = particles[i]
            p2 = particles[j]
            force_on_p1 = calculate_gravitational_force(p1, p2)
            forces[p1.name] += force_on_p1
            forces[p2.name] -= force_on_p1 # Сила действия равна силе противодействия

    # 2. Обновляем состояние каждой частицы
    for p in particles:
        p.update_force(forces[p.name])
        p.update_velocity(DT)
        p.update_position(DT)

    # 3. Обновляем данные на графике
    for idx, p in enumerate(particles):
        scatter_plots[idx].set_data(p.pos[0], p.pos[1]) # Новое положение точки
        path_data = np.array(p.path).T # Преобразуем список точек пути в удобный формат
        path_plots[idx].set_data(path_data[0], path_data[1]) # Рисуем траекторию
    
    # Динамически обновляем заголовок, чтобы видеть, какой день симуляции
    ax.set_title(f"Симуляция гравитации (Солнечная система) - День: {frame_num}")

    return scatter_plots + path_plots

# Количество кадров анимации (сколько дней будем симулировать)
num_frames = 365 * 2 # Симулируем два земных года

# Создаём и запускаем анимацию!
# fig - наша фигура
# animate - функция, вызываемая на каждом кадре
# frames - количество кадров
# init_func - функция инициализации
# blit=True - оптимизация отрисовки (перерисовываются только изменившиеся элементы)
# interval - задержка между кадрами в миллисекундах
ani = animation.FuncAnimation(fig, animate, frames=num_frames, init_func=init, blit=True, interval=20)

# Показываем окно с анимацией
plt.show()

print("Симуляция завершена.")

Разберём ключевые моменты в animate(frame_num):

  1. Расчёт сил: Мы проходимся по всем уникальным парам частиц (чтобы не считать силу дважды и не считать силу частицы на саму себя). Для каждой пары вызываем нашу calculate_gravitational_force. Сила, действующая на первую частицу, равна по модулю и противоположна по направлению силе, действующей на вторую (третий закон Ньютона). Эти силы накапливаются для каждой частицы.

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

  3. Обновление графики: Для каждой частицы мы обновляем положение её точки на графике (scatter_plots) и перерисовываем её траекторию (path_plots), используя накопленные в p.path координаты.

Функция FuncAnimation берёт на себя всю рутину по вызову animate нужное количество раз (num_frames) и отображению результата.

И вуаля! Если вы всё сделали правильно, после запуска скрипта (python имя_файла.py) должно появиться окно, в котором вы увидите, как наши планеты начинают своё грациозное движение вокруг Солнца. Вы увидите, как Земля и другие планеты рисуют свои орбиты. Магия!

Что дальше? Поле для экспериментов!

Этот код – лишь отправная точка. Вот несколько идей, как его можно улучшить или с чем поэкспериментировать:

  • Добавить больше планет: Юпитер, Сатурн с их огромными массами внесут заметные изменения!

  • Трёхмерная симуляция: Сейчас у нас всё в 2D. Попробуйте расширить до 3D (добавить z-координату, изменить расчёт силы и визуализацию).

  • Более точные методы интегрирования: Замените метод Эйлера на метод Верле или Рунге-Кутты 4-го порядка. Сравните результаты и производительность.

  • Визуализация энергии: Рассчитывайте и отображайте полную кинетическую, потенциальную и суммарную энергию системы. В идеальной замкнутой системе полная энергия должна сохраняться (с учётом погрешностей численного метода).

Как видите, простор для творчества огромен. Главное – не бояться экспериментировать и углубляться в детали.

Комментарии (15)


  1. Jijiki
    13.05.2025 09:28

    спасибо за статью, в метод Верле или Рунге-Кутты можно попасть переделав расчет физики на positionBased физику ) читал в одной из статей в интернете )

    но я пока так и не дошел в 3д до неё ) слишком сложная тема покачто, физика это же система отношений обьектов )

    если бы солвер можно было бы повесить на лямбда замыкаловку поидее вроде можно подумать что как ) или через бинды(functional)


    1. bfDeveloper
      13.05.2025 09:28

      в метод Верле или Рунге-Кутты

      Верле - да, позиционный, Рунге-Кутты - нет, он - обобщение Эйлера на любой порядок, хотя чаще имеется в виду РК четвёртого порядка.


  1. Dair_Targ
    13.05.2025 09:28

    Ради эксперимента попробуйте построить график энергии системы со временем - он может неприятно удивить.

    Ещё, если вы запустите свои расчёты в обратном направлении по времени, то тела не будут в исходные координаты приходить. Для того, что бы это обходить, нужно "leapfrog"-подход для рассчёта сил использовать, подробнее тут, 2.8.

    Последний раз, когда я изучал вопрос - наилучшим способом численного решения задачи N>>1 тел был gyrfalcON. Это такое интересное решение, которое а) легко работает для миллионов и десятков миллионов объектов б) считает каждый шаг за O(N) (не `O(N logN)` !) и в) ещё и энергию сохраняет при длительном моделировании.


  1. nerudo
    13.05.2025 09:28

    Тот кто нас моделирует тоже что-то наоптимизировал, а у нас потом спутники замедляются (см. Эффект «Пионера»).


  1. Tzimie
    13.05.2025 09:28

    А что насчёт проблемы быстрых пролетов частиц друг рядом с другом?


    1. Nikuson Автор
      13.05.2025 09:28

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


      1. Tzimie
        13.05.2025 09:28

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

        5.0

        4.0

        2.8

        1.6

        0.0001

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


  1. chrm
    13.05.2025 09:28

    "которое заставляет любые два объекта, обладающие массой, притягиваться друг к другу" и каким образом тогда безмассовый фотон изменяет свою траекторию пролетая возле массивного тела (эффект линзирования)?


    1. Nikuson Автор
      13.05.2025 09:28

      В статье модель Ньютона. Фотон, как безмассовая частица, действительно не взаимодействует с гравитацией в ньютоновском смысле. Его отклонение объясняется только в рамках общей теории относительности, где гравитация трактуется как искривление пространства-времени, и свет движется по геодезическим линиям в этом искривлённом пространстве.


      1. chrm
        13.05.2025 09:28

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


  1. Ergistael
    13.05.2025 09:28

    Лет 15+ назад, я плохо помню, но тут была статья с расчетами Солнечной системы на миллионы лет вперед. Вроде, жуткая нестабильность: изменение начальных условий на сантиметры приводило к столкновению то одних планет, то других... Кажется, автор потом в Америку уехал, но это совсем о другом.


  1. KohINoor
    13.05.2025 09:28

    Да-да, не только Земля притягивает яблоко, но и яблоко (пусть и очень-очень слабо) притягивает Землю!

    А разве не одинаково?


    1. konst90
      13.05.2025 09:28

      Одинаково. Речь видимо о перемещении, вызванным этими притяжениями.


  1. Vlad2027
    13.05.2025 09:28

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


    1. TsarS
      13.05.2025 09:28

      А интересно, а на каком количестве уперлись в потолок?