pythonnumerical-integrationverlet-integration

Verlet Integration in Python resulting in particles running away


My fallowing code (was supposed to) solve the equation of motion for two bodies but the result is the particles running way and I wasn't able to find where is the error

import numpy as np
import matplotlib.pyplot as plt

plt.style.use('ggplot')

DIM = 2
N = 2
ITER = 1000

def acc(r, v, a):
    for i in range(N - 1):
        for j in range(i+1, N):
            r2 = 0.0
            rij = [0.0, 0.0]
            for k in range(DIM):
                rij[k] = r[i][k] - r[j][k]
                r2 += rij[k] * rij[k]
            fg = -1.0 /np.power(np.sqrt(r2), 3)
            for k in range(DIM):
                a[i][k] += fg * rij[k]
                a[j][k] -= fg * rij[k]
    return a

def verlet(r, v, a, dt):
    for i in range(N):
        for k in range(DIM):
            v[i][k] += 0.5 * a[i][k] * dt 
            r[i][k] += v[i][k] * dt
    a = acc(r, v, a)
    for i in range(N):
        for k in range(DIM):
            v[i][k] += 0.5 * a[i][k] * dt
    return [r,v]


r = np.zeros((N, DIM))
v = np.zeros((N ,DIM))
a = np.zeros((N, DIM))  

r[0] = [0.5,0.0]
v[0] = [0.0,1.0]

r[1] = [-0.5,0.0]
v[1] = [0.0,-1.0]

dt = 0.01
plt.ion()
for i in range(ITER):
    r,v = verlet(r, v, a, dt)
    plt.scatter(r[0][0], r[0][1])
    plt.scatter(r[1][0], r[1][1],color='yellow')
    plt.pause(0.00005)

And I used the algorithm described in velocity Verlet


Solution

  • Acceleration doesn't accumulate over time, the way velocity and position do: it should be computed from scratch at each step of the process. So,

    1. Remove a from the argument list of both acc and verlet
    2. Initialize a by zeros at the beginning of acc.
    3. Move the call a = acc(r, v) to the beginning of verlet.

    You will see the articles rotating around each other, as expected.

    correct motions

    Unrelated to your issue but important for effective use of NumPy: get rid of loops over vector coordinates, leave it for NumPy to add and subtract vectors. I rewrote acc method in this way:

    def acc(r, v):
        a = np.zeros((N, DIM))  
        for i in range(N - 1):
            for j in range(i+1, N):
                rij = r[i, :] - r[j, :]
                r2 = np.dot(rij, rij)
                fg = -1.0 /np.power(np.sqrt(r2), 3)
                a[i, :] += fg * rij
                a[j, :] -= fg * rij
        return a