使用Runge-Kutta-4方法在Python(物理)中模拟轨道

时间:2018-11-04 13:51:34

标签: python physics runge-kutta

我正在尝试实施RK4方法来解决火箭绕地球飞行的轨道。最终,该代码将用于更复杂的太阳能系统仿真,但是我只是想首先使其在此简单系统中工作。 我的代码在下面-我希望有人可以告诉我它有什么问题。 我的故障排除工作历时很长,但没有取得成果,但我将总结一下发现的内容:

  • 相信加速度函数是正确且正确的,因为它给出了可信的值并与我的计算器/大脑相符
  • 问题似乎出在下一个“ r”值的计算中-当您运行此代码时,将出现一个xy图形,表明火箭最初掉向地球,然后反弹再次离开,然后返回。此时,我打印了所有相关值,发现尽管火箭明显沿y方向正向运动,但“ v”和“ a”在两个分量中均为负值。这使我认为新“ r”的计算与物理学不一致。

  • 火箭落入地球的速度比其预期的快得多,这也令人怀疑(从技术上讲,它不应完全落入地球,因为初始速度已设置为所需的轨道速度)

无论哪种方式,如果有人能找到该错误,我将不胜感激,因为到目前为止,我一直无法做到这一点。

from __future__ import division
import numpy as np
import matplotlib.pyplot as plt


mE = 5.9742e24      #earth mass
mM = 7.35e22        #moon mass
dM = 379728240.5    #distance from moon to barycentre
dE = 4671759.5      #distance from earth to barycentre

s = 6.4686973e7     #hypothesised distance from moon to Lagrange-2 point
sr = 6.5420e7       #alternate L2 distance

def Simulate(iterations):

    x = dM                                                  #initialise     rocket positions
    y = 0
    a = 10                                                  #set the time step
    xdot = 0.                                                #initialise rocket velocity
    ydot = -((6.6726e-11)*mE/x)**0.5
    rocket_history_x, rocket_history_y = [[] for _ in range(2)] 
    history_mx, history_my = [[] for _ in range(2)]
    history_ex, history_ey = [[] for _ in range(2)]
    sep_history, step_history = [[] for _ in range(2)]      #create lists to store data in
    history_vx, history_vy = [[] for _ in range(2)]
    history_ax, history_ay = [[] for _ in range(2)]
    n = 1500
    m = 10000                                               #n,m,p are for storing every nth, mth and pth value to the lists
    p = 60000
    r = np.array((x,y))                                        #create rocket position vector
    v = np.array((xdot, ydot))                                 #create rocket velocity vector

    for i in range(iterations):

        xe, ye = 0, 0                                            #position of earth
        re = np.array((xe,ye))                                     #create earth position vector

        phi = np.arctan2((r[1]-ye),(r[0]-xe))                       #calculate phi, the angle between the rocket and the earth, as measured from the earth
        r_hat_e = np.array((np.cos(phi), np.sin(phi)))             #create vector along which earth's acceleration acts

        def acc(r):                                                             #define the acceleration vector function
            return ((-6.6726e-11)*(mE)/abs(np.dot((r-re),(r-re))))*r_hat_e

        k1v = acc(r)                                             #use RK4 method
        k1r = v
        k2v = acc(r + k1r*(a/2))            #acc(r + (a/2)*v)
        k2r = v * (a/2) * k1v               # v*acc(r) 
        k3v = acc(r + k2r*(a/2))            #acc(r + (a/2)*v*acc(r))
        k3r = v * k2v * (a/2)               #v*(a/2)*acc(r + (a/2)*v)
        k4v = acc(r + k3r*a)                #acc(r + (a**2/2)*v*acc(r + (a/2)*v))
        k4r = v * k3v * a                   #v*a*acc(r + (a/2)*v*acc(r))  

        v = v + (a/6) * (k1v + 2*k2v + 2*k3v + k4v)              #update v
        r = r + (a/6) * (k1r + 2*k2r + 2*k3r + k4r)              #update r

        sep = np.sqrt(np.dot((r-re),(r-re)))                    #separation of rocket and earth, useful for visualisation/trouble-shooting


        if i% n == 0: # Check for the step
            rocket_history_x.append(r[0])
            rocket_history_y.append(r[1])
            history_ex.append(xe)
            history_ey.append(ye)
            sep_history.append(sep)                             #putting data into lists for plotting and troubleshooting
            step_history.append(i)
            history_ax.append(acc(r)[0])
            history_ay.append(acc(r)[1])
            history_vx.append(v[0])
            history_vy.append(v[1])

        #if i% m == 0: # Check for the step
            #print r
            #print acc(r)
        #if i% p == 0: # Check for the step
            #print ((a/6)*(k1v + 2*k2v + 2*k3v + k4v))
            #print ((a/6)*(k1r + 2*k2r + 2*k3r + k4r))
            #print k1v, k2v, k3v, k4v
            #print k1r, k2r, k3r, k4r


    return rocket_history_x, rocket_history_y, history_ex, history_ey, history_mx, history_my, sep_history, step_history, history_ax, history_ay, history_vx, history_vy



x , y, xe, ye, mx, my, sep, step, ax, ay, vx, vy = Simulate(130000)


#print x,y,vx,vy,ax,ay,step

print ("Plotting graph...")



plt.figure()
plt.subplot(311)

plt.plot(x, y, linestyle='--', color = 'green')
#plt.plot(mx, my, linestyle='-', color = 'blue')
plt.plot(xe, ye, linestyle='-', color = 'red')
#plt.plot(xm, ym)
plt.xlabel("Orbit X")
plt.ylabel("Orbit Y")
'''
plt.plot(step, vy)
plt.ylabel("vy")
'''
plt.subplot(312)
plt.plot(step, sep)
plt.xlabel("steps")
plt.ylabel("separation")

plt.subplot(313)
plt.plot(step, ay)
plt.ylabel("ay")



plt.show()



print("Simulation Complete")

1 个答案:

答案 0 :(得分:0)

您最严重的错误是在v斜率的计算中,您使用了乘法而不是加法。

    k1v = acc(r)                         #use RK4 method
    k1r =     v
    k2v = acc(r + (a/2) * k1r)            
    k2r =     v + (a/2) * k1v            
    k3v = acc(r + (a/2) * k2r)            
    k3r =     v + (a/2) * k2v          
    k4v = acc(r +  a    * k3r)                
    k4r =     v +  a    * k3v                

第二个错误是您在更改状态的加速度计算中使用了来自其他状态的值。这可能会将方法的阶数降低到1。这可能不会明显改变该图,但是在较长的积分时间内会有较大的误差。使用

     def acc(r):                                                             #define the acceleration vector function                                                
         return ((-6.6726e-11)*(mE)/abs(np.dot((r-re),(r-re)))**1.5)*(r-re)                                                                                          

plots of the orbit