Reputation: 900
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
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],
Is there significant error in the odeint solution, or is there a major problem in my function/odeint usage? Thanks!
Upvotes: 0
Views: 565
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