''' Bow shock model by Vignes et al.
- :class:`BowshockVignes` provides default bow shock model
- :class:`BowshockVignesScaled` provides a bow shock model of your own scaling
'''
import numpy as _np
[docs]class BowshockVignes:
r""" Vignes et al, (TBC) model for bow shock position.
>>> bsx, bsr = BowshockVignes.xr()
Conic curve (hyperbola) model with a formulation of
.. math::
x &= R \cos\theta + x_0 \\
y &= R \sin\theta
with
.. math::
R = \frac{L}{1+\epsilon\cos\theta}
The parameters are
.. math::
L &= 2.04 \\
\epsilon &= 1.03 \\
x_0 &= 0.64
in the unit of Martian radii.
"""
L = 2.04
e = 1.03
x0 = 0.64
[docs] @classmethod
def xr(self):
''' Return the bow shock position.
:returns: The array with shape of (2, 180). Unit is in Rm.
>>> print(BowshockVignes.xr()[:, 50])
[1.49948598 0.77115753]
'''
L, e, x0 = self.L, self.e, self.x0
theta = _np.linspace(0, 150 * _np.pi / 180., 180)
r = L / (1 + e * _np.cos(theta))
x = r * _np.cos(theta) + x0
y = r * _np.sin(theta)
return _np.array([x, y])
[docs] @classmethod
def inside(self, x, y, z):
''' Return True if s/c is in bow shock.
>>> print(BowshockVignes.inside(1.2, 0, 0))
True
>>> print(BowshockVignes.inside(3, 0, 0))
False
'''
L, e, x0 = self.L, self.e, self.x0
xx = x - x0
yy = _np.sqrt(y ** 2 + z ** 2)
theta = _np.arctan2(yy, xx)
rr2 = xx ** 2 + yy ** 2
rb = L / (1 + e * _np.cos(theta))
rb2 = rb ** 2
return rr2 < rb2
class _Hyperbola:
def __init__(self, L, e, x0):
self.L = L
self.e = e
self.x0 = x0
def xr(self):
''' Return the bow shock position.
:returns: The array with shape of (2, 180). Unit is in Rm.
>>> print(BowshockVignes.xr()[:, 50])
[1.49948598 0.77115753]
'''
L, e, x0 = self.L, self.e, self.x0
if e > 1:
maxangle = _np.arccos(-1 / e)
else:
maxangle = _np.pi
theta = _np.linspace(0, maxangle, 180, endpoint=False)
r = L / (1 + e * _np.cos(theta))
x = r * _np.cos(theta) + x0
y = r * _np.sin(theta)
return _np.array([x, y])
def inside(self, x, y, z=0):
''' Return True if s/c is in bow shock.
>>> print(BowshockVignes.inside(1.2, 0, 0))
True
>>> print(BowshockVignes.inside(3, 0, 0))
False
'''
L, e, x0 = self.L, self.e, self.x0
xx = x - x0
yy = _np.sqrt(y ** 2 + z ** 2)
theta = _np.arctan2(yy, xx)
rr2 = xx ** 2 + yy ** 2
rb = L / (1 + e * _np.cos(theta))
rb2 = rb ** 2
return rr2 < rb2
[docs]def BowshockVignesScaled(scale=1):
""" Vignes et al., while scaled by changing the parameter L.
:param scale: Default 1.
:return: A Vignes model with scaled by the given scale.
10% bigger model is obtained as follows
>>> vig10 = BowshockVignesScaled(1.1) # 10% bigger model
>>> x10, r10 = vig10.xr()
>>> plt.plot(x10, r10) # doctest: +SKIP
>>> vig10.inside(0, 2.7, 0)
True
>>> x00, r00 = BowshockVignes.xr()
>>> plt.plot(x00, r00) # doctest: +SKIP
>>> BowshockVignes.inside(0, 2.7, 0)
False
"""
return _Hyperbola(2.04 * scale, 1.03, 0.64)