In [1]:
%matplotlib inline
import pymc as pm
import matplotlib.pyplot as plt
import numpy as np

In [2]:
# Define key parameters, Values from Zahnle 1998
vp = 13.070  # Orbital velocity of Jupiter, [km/s]
R_j =  71398.0 # jovian radii [km]
G = 6.67*10**(-11) # Universal Gravitational Constant [m3 kg−1 s−2]

moon = 'Ganymede'

v_orb = {'Io' : 17.3, 
         'Europa' : 13.7,
         'Ganymede' : 10.9,
         'Callisto' : 8.2}  # Orbital velocity of Jupiter's Moons, [km/s]

R_sat = {'Io' : 1820,
         'Europe' : 1570,
         'Ganymede' : 2630,
         'Callisto' : 2400} # Radius [km]

a_sat = {'Io' : 5.9*R_j,
         'Europa' : 9.4*R_j,
         'Ganymede' : 15.0*R_j,
         'Callisto' : 26.4*R_j} # Semimajor axis of orbit [km]

g = {'Io' : 1.81,
     'Europa' : 1.31,
     'Ganymede' : 1.43,
     'Callisto' : 1.25} # Surface Gravity [m/s2]

def v_esc(key,g=g,r=R_sat):
    return np.sqrt(2*g[key]*R_sat[key]*1000)/1000 # Calculates surface velocity from the python dictionaries [km/s]

#1: Encounter Velocities with the Planet


In [24]:
# Calculate distribution of encounter velocities
x1 = pm.Uniform('x1', lower=0.0, upper=1.0) # Uniformly distributed random number

def Vinf_eval(vp=vp,x1=x1): 
    return 0.3*vp*(1-0.45* np.log(1/(x1+0.2)-0.832))

def Uinf_eval(vp=vp,x1=x1,v_orb=v_orb[moon]):
    return Vinf_eval(vp,x1)/v_orb

@pm.deterministic
def Vinf(vp=vp,x1=x1): 
    return Vinf_eval(vp,x1)

@pm.deterministic
def Uinf(vp=vp,x1=x1,v_orb=v_orb[moon]):
    return Uinf_eval(vp,x1,v_orb)

In [25]:
#Create Model and 
M = pm.Model([x1, Vinf])
mcmc = pm.MCMC(M)

In [26]:
#Generate Distribution
mcmc.sample(40000, 10000, 1)
Vinf_samples = mcmc.trace('Vinf')[:]

# Plot distribution of encounter velocities
nbins = 50
plt.figure(figsize=(12,6))
ax1 = plt.subplot(121)
ax1.hist(Vinf_samples,bins=nbins,normed=True)

# Plot culmulative distribution of encounter velocities
ax2 = plt.subplot(122)
ax2.hist(Vinf_samples,bins=nbins,cumulative=True,normed=True)
plt.show()

print "Min V_inf : %f"    %  Vinf_samples.min()
print "Max V_inf : %f"    %  Vinf_samples.max()
print "Median V_inf : %f" %  np.median(Vinf_samples)


 [-----------------100%-----------------] 40000 of 40000 complete in 2.2 sec
Min V_inf : 1.402459
Max V_inf : 15.545260
Median V_inf : 4.835585

#2: Inclination


In [27]:
#Calculate Distribution of Inclinations
x2 = pm.Uniform('x2', lower=0.0, upper=1.0) # Uniformly distributed random number

def inclination(x2=x2):
    return np.arccos(1-2*x2)

In [28]:
# Plot culmulative distribution of inclinations
# Kluge Fix to Populate a list for now so we can check as we go
inclination_samples = [inclination(x2.random()) for i in range(10000)]
values, base = np.histogram(inclination_samples,bins=50)
cumulative = np.cumsum(values)
plt.figure(figsize=(6,6))
ax1 = plt.subplot(111)
plt.plot(base[:-1]*180/np.pi, cumulative, '.')
plt.show()


#3: Eccentricity


In [29]:
x3 = pm.Uniform('x3', lower=0.0, upper=1.0) # Uniformly distributed random number

#WARNING, THERE IS AN ERROR IN ZAHNLE 2001
def eccentricity(Uinf=Uinf,x3=x3):
    UU_inf = (Uinf)**2
    return np.sqrt(1+x3*UU_inf*(UU_inf+2))

In [31]:
ecc_samples = [eccentricity(Uinf_eval(vp,x1.random()),x3.random()) for i in range(10000)]

In [32]:
plt.figure(figsize=(6,6))
ax1 = plt.subplot(111)
ax1 = plt.hist(ecc_samples,nbins)


Periapse


In [49]:
def periapse(Uinf=Uinf,eccen='Nan'):
    UU_inf = Uinf**2
    return (eccen-1)/UU_inf

In [50]:
periapse_samples = [periapse(Uinf_eval(vp,x1.random()),eccentricity(Uinf_eval(vp,x1.random()),x3.random())) for i in range(10000)]

In [52]:
plt.figure(figsize=(6,6))
ax1 = plt.subplot(111)
ax1 = plt.hist(periapse_samples,nbins)


Impact Velocities

Impact probabilities and impact velocities are estimated using Opik’s formul as written for hyperbolic orbits.

We assume that the satellite’s orbit is circular. The normalized encounter velocity U ≡ venc/vorb is given as:


In [54]:
def U(e,q,i):
    return np.sqrt(3-(1-e)/q-2*np.cos(i)*np.sqrt(q*(1+e)))

U_samples = [U() for i in range(10000)]


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-54-55e140e3d051> in <module>()
      2     return np.sqrt(3-(1-e)/q-2*np.cos(i)*np.sqrt(q*(1+e)))
      3 
----> 4 U_samples = [U() for i in range(10000)]

TypeError: U() takes exactly 3 arguments (0 given)

In [55]:
def Ux(e,q):
    return np.sqrt(2-(1-e)/q-q(1+e))

In [56]:
def Uy(e,q,i):
    return np.cos(i)*np.sqrt(q*(1+e))-1

In [57]:
def Uz(e,q,i):
    return np.sin(i)*np.sqrt(q*(1-e))

Opik Impact Probabilities


In [58]:
def imact_probabilities(i,U,Ux,U_inf,R_sat,a_sat,v_orb,v_esc,R_j):
    Pstar = ( R_sat/a_sat )**2 *( 1+(v_esc/(v_orb*U))**2 )*(U/Ux)/(np.pi*np.sin(i))
    w = (2+ U_inf**2)/(2 + (R_j/a_sat)*U_inf**2 )
    return w*Pstar

#4: Azimuth


In [59]:
x4 = pm.Uniform('x4', lower=0.0, upper=1.0) # Uniformly distributed random number

def azimuth_eval(x4=x4):
    return np.pi*(1-2*x4)

#5: Impact Incidence Angle


In [60]:
x5 = pm.Uniform('x5', lower=0.0, upper=1.0) # Uniformly distributed random number

def theta(x5=x5):
    return np.arccos(np.sqrt(x5))

Gravitational Focusing


In [60]:

Starting to Put it all Together


In [20]:
@pm.deterministic
def impact_event(x1=x1,x2=x2,x3=x3,x4=x4,x5=x5):
    Uinf = Uinf_eval(x1)
    return Uinf


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-20-8ec1f6bf3303> in <module>()
      1 @pm.deterministic
----> 2 def impact_event(x1=x1,x2=x2,x3=x3,x4=x4,x5=x5):
      3     Uinf = Uinf_eval(x1)
      4     return Uinf

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pymc/InstantiationDecorators.pyc in deterministic(__func__, **kwds)
    248 
    249     if __func__:
--> 250         return instantiate_n(__func__)
    251 
    252     return instantiate_n

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pymc/InstantiationDecorators.pyc in instantiate_n(__func__)
    241         junk, parents = _extract(
    242             __func__, kwds, keys, 'Deterministic', probe=False)
--> 243         return Deterministic(parents=parents, **kwds)
    244 
    245     keys = ['eval']

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pymc/PyMCObjects.pyc in __init__(self, eval, doc, name, parents, dtype, trace, cache_depth, plot, verbose, jacobians, jacobian_formats)
    433                           trace=trace,
    434                           plot=plot,
--> 435                           verbose=verbose)
    436 
    437         # self._value.force_compute()

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pymc/Node.pyc in __init__(self, doc, name, parents, cache_depth, trace, dtype, plot, verbose)
    214         self.extended_children = set()
    215 
--> 216         Node.__init__(self, doc, name, parents, cache_depth, verbose=verbose)
    217 
    218         if self.dtype is None:

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pymc/Node.pyc in __init__(self, doc, name, parents, cache_depth, verbose)
    125 
    126         # Initialize
--> 127         self.parents = parents
    128 
    129     def _get_parents(self):

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pymc/Node.pyc in _set_parents(self, new_parents)
    148 
    149         # Get new lazy function
--> 150         self.gen_lazy_function()
    151 
    152     parents = property(

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pymc/PyMCObjects.pyc in gen_lazy_function(self)
    444                                    cache_depth=self._cache_depth)
    445 
--> 446         self._value.force_compute()
    447 
    448         self._jacobians = {}

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pymc/LazyFunction.so in pymc.LazyFunction.LazyFunction.force_compute (pymc/LazyFunction.c:2409)()

<ipython-input-20-8ec1f6bf3303> in impact_event(x1, x2, x3, x4, x5)
      1 @pm.deterministic
      2 def impact_event(x1=x1,x2=x2,x3=x3,x4=x4,x5=x5):
----> 3     Uinf = Uinf_eval(x1)
      4     return Uinf

NameError: global name 'Uinf_eval' is not defined

In [21]:
mtest = pm.Model([x1,x2,x3,x4,x5,impact_event])


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-21-06a9e6050e0c> in <module>()
----> 1 mtest = pm.Model([x1,x2,x3,x4,x5,impact_event])

NameError: name 'impact_event' is not defined

In [22]:
mcmc = pm.MCMC(mtest)


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-22-abcaaee676cf> in <module>()
----> 1 mcmc = pm.MCMC(mtest)

NameError: name 'mtest' is not defined

In [23]:
#Generate Distribution
mcmc.sample(40000, 10000, 1)
Vinf_samples = mcmc.trace('impact_event')[:]


 [-----------------100%-----------------] 40000 of 40000 complete in 2.2 sec
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-23-3d6fd77f9459> in <module>()
      1 #Generate Distribution
      2 mcmc.sample(40000, 10000, 1)
----> 3 Vinf_samples = mcmc.trace('impact_event')[:]

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pymc/Model.pyc in trace(self, name, chain)
    834         """
    835         if isinstance(name, str):
--> 836             return self.db.trace(name, chain)
    837         elif isinstance(name, Variable):
    838             return self.db.trace(name.__name__, chain)

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pymc/database/base.pyc in trace(self, name, chain)
    372           the ith call to `sample`.
    373         """
--> 374         trace = copy.copy(self._traces[name])
    375         trace._chain = chain
    376         return trace

KeyError: 'impact_event'

In [ ]:


In [ ]:


In [ ]: