简体   繁体   English

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

[英]Using Runge-Kutta-4 method to simulate an orbit in Python (Physics)

I'm trying to implement an RK4 method to solve for the orbit of a rocket around the Earth. 我正在尝试实现RK4方法来解决火箭绕地球运行的轨道。 Eventually this code will be used for more complex solar system simulations, but I'm just trying to get it working in this simple system first. 最终,该代码将用于更复杂的太阳能系统仿真,但是我只是想首先使其在此简单系统中工作。 My code is below - I'm hoping someone can tell me what is wrong with it. 我的代码在下面-我希望有人可以告诉我它有什么问题。 My trouble-shooting efforts have been long and unfruitful, but I'll summarise what I've found: 我的故障排除工作历时很长,但没有取得成果,但我将总结一下发现的内容:

  • I believe the acceleration function is fine and correct, as it gives believable values and agrees with my calculator/brain 相信加速度函数是正确且正确的,因为它给出了可信的值并与我的计算器/大脑一致
  • It appears as though the problem lies somewhere in the calculation of the next "r" value - when you run this code, an xy graph will appear, showing that the rocket initially falls in towards the Earth, then bounces away again, then back. 问题似乎出在下一个“ r”值的计算中-运行该代码时,将出现一个xy图,表明火箭最初掉落到地球,然后再次反弹,然后返回。 I printed all the relevant values at this point, and found that "v" and "a" were negative in both components, despite the rocket clearly moving in the positive y direction. 此时,我打印了所有相关值,发现尽管火箭明显沿y方向正向运动,但“ v”和“ a”在两个分量中均为负值。 This makes me think that the calculation of the new "r" is in disagreement with the physics. 这使我认为新“ r”的计算与物理学不一致。

  • The rocket is falling to Earth much faster than it should, which is also suspicious (technically it shouldn't fall into Earth at all, since the initial velocity is set to the required orbital velocity) 火箭降落到地球的速度比其应有的快得多,这也令人怀疑(从技术上讲,它不应完全落入地球,因为初始速度已设置为所需的轨道速度)

Either way I would greatly appreciate if anyone could find the error, as I have been unable up to this point. 无论哪种方式,如果有人能找到该错误,我将不胜感激,因为到目前为止,我一直无法这样做。

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")

Your most grave error is that in the computation of the v slopes, you used multiplication instead of addition. 您最严重的错误是在计算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                

A second error is that you use a value from a different state in the acceleration computation of the changed states. 第二个错误是您在更改状态的加速度计算中使用了来自其他状态的值。 This might reduce the order of the method down to 1. Which might not change this plot visibly but will have larger errors over longer integration periods. 这可能会将方法的阶数降低到1。这可能不会明显改变该图,但是在较长的积分时间内会有较大的误差。 Use 采用

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

轨道图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM