Проблема в создании алгоритма перепрыгивания для задачи с 3 телами с использованием Python - PullRequest
0 голосов
/ 30 октября 2018

Я пытаюсь написать код для задачи с тремя телами с помощью алгоритма чехарды. В качестве руководства я использую "Moving Stars Around" от Piet Hut & Jun Makino.

Коды в руководстве написаны на C, но я пытаюсь следовать точному рабочему процессу, используя Python для начала, прежде чем экспериментировать с ним.

Ниже приведена моя попытка следовать коду из раздела 5.1 .

import numpy as np

N = 3       #number of bodies
m = 1       #mass
dt = 0.01   #timestep
t_end = 10  #duration

r = [] 
v = []
a = [[0, 0, 0] for i in range(N)]

for i in range(N):
    phi = i * 2 * np.pi/3
    r.append([np.cos(phi), np.sin(phi), 0])

for i in range(N):
    for j in range(i+1, N):
        rji = []
        for k in range(3):
            rji.append(r[j][k] - r[i][k])
        r2 = 0
        for k in range(3):
            r2 += rji[k]**2
        r3 = r2 * np.sqrt(r2)
        for k in range(3):
            a[i][k] += m * rji[k] / r3
            a[j][k] -= m * rji[k] / r3


v_abs = np.sqrt(-a[0][0])
for i in range(N):
    phi = i * 2 * np.pi/3
    v.append([-v_abs * np.sin(phi),
              v_abs * np.cos(phi), 0])


ekin = 0
epot = 0
for i in range(N):

    for j in range(i+1, N):
        rji = [0, 0, 0]
        for k in range(3):
            rji[k] = r[j][k] - r[i][k]
        r2 = 0
        for k in range(3):
            r2 += rji[k]**2
        d = np.sqrt(r2)
        epot -= m**2 / d

    for k in range(3):
        ekin += 0.5 * m * v[i][k]**2

e_in = ekin + epot
print('Initial total energy E_in = ', e_in)


dt_out = 0.01
t_out = dt_out

for t in np.arange(0, t_end, dt):

    for i in range(N):
        for k in range(3):
            v[i][k] += a[i][k] * dt/2
        for k in range(3):
            r[i][k] += v[i][k] * dt

    for i in range(N):
        for k in range(3):
            a[i][k] = 0

    for i in range(N):
        for j in range(i+1, N):
            rji = []
        for k in range(3):
            rji.append(r[j][k] - r[i][k])
        r2 = 0
        for k in range(3):
            r2 += rji[k]**2
        r3 = r2 * np.sqrt(r2)
        for k in range(3):
            a[i][k] += m * rji[k] / r3
            a[j][k] -= m * rji[k] / r3

    for i in range(N):
        for k in range(3):
            v[i][k] += a[i][k] * dt/2
        '''
        if t >= t_out:
            for i in range(N):
                print(r[i][k], ' ')
            for k in range(N):
                print(v[i][k], ' ')
        '''
        t_out += dt_out


epot = 0
ekin = 0
for i in range(N):

    for j in range(i+1, N):
        rji = [0, 0, 0]
        for k in range(3):
            rji[k] = r[j][k] - r[i][k]
        r2 = 0
        for k in range(3):
            r2 += rji[k]**2
        d = np.sqrt(r2)
        epot -= m**2 / d

    for k in range(3):
        ekin += 0.5 * m * v[i][k]**2

e_out = ekin + epot
print('Final total energy E_out = ', e_out)
print('absolute energy error: E_out - E_in = ', e_out - e_in)
print('relative energy error: (E_out - E_in)/E_in = ', (e_out - e_in)/e_in)

Я определил временной шаг dt = 0.01 и продолжительность t_end = 10 в отличие от запроса ввода. В разделе 5.4 результаты должны быть:

|gravity> g++ -o leapfrog2 leapfrog2.C
|gravity> leapfrog2 > leapfrog2_0.01_10.out
Please provide a value for the time step
0.01
and for the duration of the run
10
Initial total energy E_in = -0.866025
Final total energy E_out = -0.866025
absolute energy error: E_out - E_in = 2.72254e-10
relative energy error: (E_out - E_in) / E_in = -3.14372e-10

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

Initial total energy E_in =  -0.8660254037844386
Final total energy E_out =  -0.39922101519288833
absolute energy error: E_out - E_in =  0.46680438859155027
relative energy error: (E_out - E_in)/E_in =  -0.5390192788244604

и, конечно, после того, как я изобразил свои результаты, они не идут по кругу.

Мне интересно, если я допустил ошибку при переводе кода. Любая помощь будет оценена!

1 Ответ

0 голосов
/ 31 октября 2018

Добро пожаловать в переполнение стека!

Прежде всего, ошибка - это классическая проблема с Python: часть вашего кода имеет неправильный отступ. В частности:

for i in range(N):
    for j in range(i+1, N):
        rji = []
    for k in range(3):
        rji.append(r[j][k] - r[i][k])
    r2 = 0
    for k in range(3):
        r2 += rji[k]**2
    r3 = r2 * np.sqrt(r2)
    for k in range(3):
        a[i][k] += m * rji[k] / r3
        a[j][k] -= m * rji[k] / r3

скорее должно быть:

for i in range(N):
    for j in range(i+1, N):
        rji = []
        for k in range(3):
            rji.append(r[j][k] - r[i][k])
        r2 = 0
        for k in range(3):
            r2 += rji[k]**2
        r3 = r2 * np.sqrt(r2)
        for k in range(3):
            a[i][k] += m * rji[k] / r3
            a[j][k] -= m * rji[k] / r3

Позвольте дать вам совет: если вы пытаетесь изучать python, читая книгу, попробуйте написать версию, которая выполняет свою работу (например, ту, которую мы обсуждаем здесь), а затем приложите усилия, чтобы сделать ее более понятной. идиоматическое. Используя numpy, вы можете удалить большинство (если не все) циклов в пространственных измерениях (как минимум!).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...