In [1]:
# Configure Jupyter so figures appear in the notebook
%matplotlib inline
# Configure Jupyter to display the assigned value after an assignment
%config InteractiveShell.ast_node_interactivity='last_expr_or_assign'
# import functions from the modsim.py module
from modsim import *
In [2]:
# Here are the units we'll need
s = UNITS.second
N = UNITS.newton
kg = UNITS.kilogram
m = UNITS.meter
year = UNITS.year
Out[2]:
In [3]:
# And an inition condition (with everything in SI units)
# distance from the sun to the earth at perihelion
R = Vector(147e9, 0) * m
# initial velocity
V = Vector(0, -30300) * m/s
init = State(R=R, V=V)
Out[3]:
In [4]:
# Making a system object
r_earth = 6.371e6 * m
r_sun = 695.508e6 * m
t_end = (1 * year).to_base_units()
system = System(init=init,
G=6.674e-11 * N / kg**2 * m**2,
m1=1.989e30 * kg,
r_final=r_sun + r_earth,
m2=5.972e24 * kg,
t_end=t_end)
Out[4]:
In [5]:
# Here's a function that computes the force of gravity
def universal_gravitation(state, system):
"""Computes gravitational force.
state: State object with distance r
system: System object with m1, m2, and G
returns: Vector
"""
R, V = state
G, m1, m2 = system.G, system.m1, system.m2
# make sure the result is a vector, either
# by forcing it, or by putting v.hat() on
# the left
force = -G * m1 * m2 / R.mag2 * R.hat()
return Vector(force)
force = -R.hat() * G * m1 * m2 / R.mag2
return force
In [6]:
universal_gravitation(init, system)
Out[6]:
In [7]:
# The slope function
def slope_func(state, t, system):
"""Compute derivatives of the state.
state: position, velocity
t: time
system: System object containing `g`
returns: derivatives of y and v
"""
R, V = state
F = universal_gravitation(state, system)
A = F / system.m2
return V, A
In [8]:
# Always test the slope function!
slope_func(init, 0, system)
Out[8]:
In [9]:
# Here's an event function that stops the simulation
# before the collision
def event_func(state, t, system):
R, V = state
return R.mag - system.r_final
In [10]:
# Always test the event function!
event_func(init, 0, system)
Out[10]:
In [11]:
# Finally we can run the simulation
system.set(dt=system.t_end/1000)
results, details = run_euler(system, slope_func)
details
Out[11]:
In [12]:
def plot_trajectory(R):
x = R.extract('x') / 1e9
y = R.extract('y') / 1e9
plot(x, y)
plot(0, 0, 'yo')
decorate(xlabel='x distance (million km)',
ylabel='y distance (million km)')
In [13]:
plot_trajectory(results.R)
In [14]:
error = results.last_row() - system.init
Out[14]:
In [15]:
error.R.mag
Out[15]:
In [16]:
error.V.mag
Out[16]:
In [17]:
# Ralston
system.set(dt=system.t_end/1000)
results, details = run_ralston(system, slope_func)
details
Out[17]:
In [18]:
plot_trajectory(results.R)
In [19]:
error = results.last_row() - system.init
Out[19]:
In [20]:
error.R.mag
Out[20]:
In [21]:
error.V.mag
Out[21]:
In [24]:
xs = results.R.extract('x') * 1.1
ys = results.R.extract('y') * 1.1
def draw_func(state, t):
set_xlim(xs)
set_ylim(ys)
x, y = state.R
plot(x, y, 'b.')
plot(0, 0, 'yo')
decorate(xlabel='x distance (million km)',
ylabel='y distance (million km)')
In [25]:
system.set(dt=system.t_end/100)
results, details = run_ralston(system, slope_func)
animate(results, draw_func)
In [ ]: