简体   繁体   中英

scipy.odeint returning incorrect values for second order non-linear differential equation

I have been trying to solve the second order non-linear differential equation for Newton's Law of Universal Gravitation (inverse square law):

x(t)'' = -GM/(x**2)

for the motion of a satellite approaching the earth (in this case a point-mass) in one dimension

MS Paint技能

using numpy.odeint with a series of first order differential equations, but the operation has been yielding incorrect results when compared to Mathematica or to simplified forms of the law (∆x = (1/2)at^2).

This is the code for the program:

import numpy as np
from scipy.integrate import odeint

def deriv(x, t):            #derivative function, where x[0] is x, x[1] is x' or v, and x2 = x'' or a
    x2 = -mu/(x[0]**2)
    return x[1], x2

init = 6371000, 0          #initial values for x and x'

a_t = np.linspace(0, 20, 100)   #time scale

mu = 398600000000000      #gravitational constant

x, _ = odeint(deriv, init, a_t).T

sol = np.column_stack([a_t, x])

which yields an array with coupled a_t and x position values as the satellite approaches the earth from an initial distance of 6371000 m (the average radius of the earth). One would expect, for instance, that the object would take approximately 10 seconds to fall 1000 m at the surface from 6371000m to 6370000m (because the solution to 1000 = 1/2(9.8)(t^2) is almost exactly 10), and the mathematica solution to the differential equation puts the value at slightly above 10s as well.

数学解决方案

Yet that value according the odeint solution and the sol array is nearly 14.4.

  t                    x
  [  1.41414141e+01,   6.37001801e+06],
  [  1.43434343e+01,   6.36998975e+06],

pylab图

Is there significant error in the odeint solution, or is there a major problem in my function/odeint usage? Thanks!

(because the solution to 1000 = 1/2(9.8)(t^2) is almost exactly 10),

This is the right sanity check, but something's off with your arithmetic. Using this approximation, we get a t of

>>> (1000 / (1/2 * 9.8))**0.5
14.285714285714285

as opposed to at of ~10, which would give us only a distance of

>>> 1/2 * 9.8 * 10**2
490.00000000000006

This expectation of ~14.29 is very close to the result you observe:

>>> sol[abs((sol[:,1] - sol[0,1]) - -1000).argmin()]
array([  1.42705427e+01,   6.37000001e+06])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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