JAustin
JAustin

Reputation: 900

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 skills

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.

The mathematica solution

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 figure

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

Upvotes: 0

Views: 565

Answers (1)

DSM
DSM

Reputation: 353489

(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 a t 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])

Upvotes: 1

Related Questions