Plot orbit of two body using rk4

元气小坏坏 提交于 2021-01-29 11:10:26

问题


I've been trying to solve the two body problem using rk4 in python. I have some problem with the plot however and can't seem to get an orbit instead it's just a slightly bent line.

I've tried to change the stepsize and initial values but it hasn't gotten me anywhere. Here is my code of the sun and earth system.

from __future__ import division 
import numpy as np
from numpy import linalg as LA
import matplotlib.pyplot as plt
#from VPython import * 
#from VPython.graph import *


AU=1.5e11
a=AU  #semi major axis
e=0.1 #eccentricity
ms = 2E30
me = 5.98E24
h=10**(-6) 
G=6.67e-11
step=600 #timestep

#sun=sphere(pos=vec(0,0,0),radius=0.1*AU,color=color.yellow)
#earth=sphere(pos=vec(1*AU,0,0),radius=0.1*AU)

sunpos=np.array([0,0,0])
earthpos=np.array([a,0,0])

#scene.range=1.3*AU
#scene.autoscale=0

earthv=np.array([0,35000,0])
sunv=np.array([0,-35000,0])

norme=np.sqrt(abs(earthpos[0]**2+earthpos[1]**2+earthpos[2]**2-sunpos[0]**2+sunpos[1]**2+sunpos[2]**2))
norma=np.sqrt(abs(-(earthpos[0]**2+earthpos[1]**2+earthpos[2]**2)+(sunpos[0]**2+sunpos[1]**2+sunpos[2]**2)))

eartha=G*ms*(earthpos-sunpos)/norme**3
suna=G*me*(sunpos-earthpos)/norma**3

xarray=[]
yarray=[]
zarray=[]
xarray.append(earthpos[0])
yarray.append(earthpos[1])
zarray.append(earthpos[2])

#trail = curve(color = earth.color)

#k1 = [vector(0,0,0),vector(0,0,0), vector(0,0,0), vector(0,0,0)] 
#k2 = [vector(0,0,0),vector(0,0,0), vector(0,0,0), vector(0,0,0)] 
#k3 = [vector(0,0,0),vector(0,0,0), vector(0,0,0), vector(0,0,0)] 
#k4 = [vector(0,0,0),vector(0,0,0), vector(0,0,0), vector(0,0,0)]
t=0
T=10**9
while t<T:
    k1v1=h*earthv
    k1v2=h*sunv
    k1a1=eartha
    k1a2=suna
    earthpos=earthpos+.5*k1v1
    sunpos=sunpos+.5*k1v2
    earthv=earthv+.5*k1a1
    sunv=sunv+.5*k1a2
    norme=np.sqrt(abs(earthpos[0]**2+earthpos[1]**2+earthpos[2]**2-sunpos[0]**2+sunpos[1]**2+sunpos[2]**2))
    norma=np.sqrt(abs(-(earthpos[0]**2+earthpos[1]**2+earthpos[2]**2)+(sunpos[0]**2+sunpos[1]**2+sunpos[2]**2)))
    eartha=G*ms*(earthpos-sunpos)/norme**3
    suna=G*me*(sunpos-earthpos)/norma**3


    k2v1=h*earthv
    k2v2=h*sunv
    k2a1=eartha
    k2a2=suna
    earthpos=earthpos+.5*k2v1
    sunpos=sunpos+.5*k2v2
    earthv=earthv+.5*k2a1
    sunv=sunv+.5*k2a2
    norme=np.sqrt(abs(earthpos[0]**2+earthpos[1]**2+earthpos[2]**2-sunpos[0]**2+sunpos[1]**2+sunpos[2]**2))
    norma=np.sqrt(abs(-(earthpos[0]**2+earthpos[1]**2+earthpos[2]**2)+(sunpos[0]**2+sunpos[1]**2+sunpos[2]**2)))
    eartha=G*ms*(earthpos-sunpos)/norme**3
    suna=G*me*(sunpos-earthpos)/norma**3

    k3v1=h*earthv
    k3v2=h*sunv
    k3a1=eartha
    k3a2=suna
    earthpos=earthpos+k3v1
    sunpos=sunpos+k3v2
    earthv=earthv+k3a1
    sunv=sunv+k3a2
    norme=np.sqrt(abs(earthpos[0]**2+earthpos[1]**2+earthpos[2]**2-sunpos[0]**2+sunpos[1]**2+sunpos[2]**2))
    norma=np.sqrt(abs(-(earthpos[0]**2+earthpos[1]**2+earthpos[2]**2)+(sunpos[0]**2+sunpos[1]**2+sunpos[2]**2)))
    eartha=G*ms*(earthpos-sunpos)/norme**3
    suna=G*me*(sunpos-earthpos)/norma**3

    k4v1=h*earthv
    k4v2=h*sunv
    k4a1=eartha
    k4a2=suna
    earthpos=earthpos+1/6*(k1v1+2*k2v1+2*k3v1+k4v1)
    sunpos=sunpos+1/6*(k1v2+2*k2v2+2*k3v2+k4v2)
    earthv=earthv+1/6*(k1a1+2*k2a1+2*k3a1+k4a1)
    sunv=sunv+1/6*(k1a2+2*k2a2+2*k3a2+k4a2)
    norme=np.sqrt(abs(earthpos[0]**2+earthpos[1]**2+earthpos[2]**2-sunpos[0]**2+sunpos[1]**2+sunpos[2]**2))
    norma=np.sqrt(abs(-(earthpos[0]**2+earthpos[1]**2+earthpos[2]**2)+(sunpos[0]**2+sunpos[1]**2+sunpos[2]**2)))
    eartha=G*ms*(earthpos-sunpos)/norme**3
    suna=G*me*(sunpos-earthpos)/norma**3
    xarray.append(earthpos[0])
    yarray.append(earthpos[1])
    zarray.append(earthpos[2])

    t=t+step

plt.plot(xarray,yarray)

Here is the plot I'm getting.


回答1:


  • Please read again what the Euclidean distance is. In the most simple python implementation

    norme=sum( (earthpos-sunpos)**2 )**0.5
    

    That is, first compute the coordinate differences, then square them, then add them, then take the square root of the sum.

  • Also, it seems that you at no point multiply the accelerations with the step size.

  • The force directions seem to be pointing outwards, not inwards like an attracting force.

  • During the RK4 step, the base state is not to be changed, all modifications are relative to that unchanged base state.

To correct all that and make the code more compact, you can use the following ideas:

Define the gravitation force/acceleration computations as

def accelerations(earthpos, sunpos):
    norme=sum( (earthpos-sunpos)**2 )**0.5
    gravit = G*(earthpos-sunpos)/norme**3
    suna = me*gravit
    eartha = -ms*gravit
    return eartha, suna

and then the RK4 step can be shortened to

eartha, suna = accelerations(earthpos, sunpos)
k1v1 = h*earthv
k1v2=h*sunv
k1a1=h*eartha
k1a2=h*suna

eartha, suna = accelerations(earthpos+0.5*k1v1, sunpos+0.5*k1v2)
k2v1 = h*(earthv+0.5*k1a1)
k2v2=h*(sunv+0.5*k1a2)
k2a1=h*eartha
k2a2=h*suna

eartha, suna = accelerations(earthpos+0.5*k2v1, sunpos+0.5*k2v2)
k3v1 = h*(earthv+0.5*k2a1)
k3v2=h*(sunv+0.5*k2a2)
k3a1=h*eartha
k3a2=h*suna

etc.



来源:https://stackoverflow.com/questions/57253590/plot-orbit-of-two-body-using-rk4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!