Skip to content Skip to sidebar Skip to footer

Python Implementation Of N-body Problem Issue

I am currently trying to implement the N-body problem using Euler's method for solving differential equations. However, the graphical outputs do not seem correct, and I'm not sure

Solution 1:

There are 3 steps to a correctly looking plot.

First and most important, get the implementation of the physical model right. r3 is supposed to contain the third powers of the distances, thus the third power of the square root has exponent 1.5

r3 = np.nan_to_num(np.sum(np.abs(dr)**2, axis=-1)**(1.5)).reshape((pos.shape[0],pos.shape[0],1))

This then give the cleaned up plot

enter image description here

Note the differences in the scales, one would have to horizontally compress the image to get the same scale in both directions.

Second, this means that the initial velocity is too large, the stars flee from each other. These velocities might be right in the position where the stars are closest together. As a quick fix, divide the velocities by 10. This gives the plot

enter image description here

Better initial values could be obtained by evaluating and transforming the supposedly more realistic data from https://towardsdatascience.com/modelling-the-three-body-problem-in-classical-mechanics-using-python-9dc270ad7767 or use the Kepler laws with the more general data from http://www.solstation.com/orbits/ac-absys.htm

Third, the mass center is not at the origin and has a non-zero velocity. Normalize the initial values for that

# center of mass
    com_p = np.sum(np.multiply(mass, pos),axis=0) / np.sum(mass,axis=0)
    com_v = np.sum(np.multiply(mass, vel),axis=0) / np.sum(mass,axis=0)
    for p in pos: p -= com_p
    for v in vel: v -= com_v

(or apply suitable broadcasting magic instead of the last two lines) to get the plot that you were probably expecting.

enter image description here

That the orbits spiral outwards is typical for the Euler method, as the individual steps move along the tangents to the convex ellipses of the exact solution.

The same only using RK4 with 5-day time steps gives prefect looking ellipses

enter image description here

For the RK4 implementation the most important step is to package the non-trivial derivatives computation into a separate sub-procedure

defrun_sim(bodies, t, dt, method = "RK4"):
    ...
    
    defacc(pos):
        dr = np.nan_to_num(pos[None,:] - pos[:,None]) 
        r3 = np.nan_to_num(np.sum(np.abs(dr)**2, axis=-1)**(1.5)).reshape((pos.shape[0],pos.shape[0],1))
        return G * np.sum((np.nan_to_num(np.divide(dr, r3)) * np.tile(mass,(pos.shape[0],1)).reshape(pos.shape[0],pos.shape[0],1)), axis=1)

Then one can take the Euler step out of the time loop

    def Euler_step(pos, vel, dt):
        a = acc(pos);
        return pos+vel*dt, vel+a*dt

and similarly implement the RK4 step

    def RK4_step(pos, vel, dt):
        v1 = vel
        a1 = acc(pos) 
        v2 = vel + a1*0.5*dt
        a2 = acc(pos+v1*0.5*dt) 
        v3 = vel + a2*0.5*dt
        a3 = acc(pos+v2*0.5*dt)
        v4 = vel + a3*dt
        a4 = acc(pos+v3*dt) 
        returnpos+(v1+2*v2+2*v3+v4)/6*dt, vel+(a1+2*a2+2*a3+a4)/6*dt

Select the method like

stepper = RK4_step if method == "RK4" else Euler_step

and then the time loop takes the generic form

    N = floor(t/dt)
    ...
    for i in range(1,N+1):
        pos, vel = stepper(pos, vel, dt)
        plt_pos[i] = pos
        plt_vel[i] = vel

Post a Comment for "Python Implementation Of N-body Problem Issue"