Source code for galpy.potential.SteadyLogSpiralPotential
###############################################################################
# SteadyLogSpiralPotential: a steady-state spiral potential
###############################################################################
import numpy
from ..util import conversion
from .planarPotential import planarPotential
_degtorad= numpy.pi/180.
[docs]class SteadyLogSpiralPotential(planarPotential):
"""Class that implements a steady-state spiral potential
.. math::
\\Phi(R,\\phi) = \\frac{\\mathrm{amp}\\times A}{\\alpha}\\,\\cos\\left(\\alpha\,\ln R - m\\,(\\phi-\\Omega_s\\,t-\\gamma)\\right)
Can be grown in a similar way as the DehnenBarPotential, but using :math:`T_s = 2\pi/\Omega_s` to normalize :math:`t_{\mathrm{form}}` and :math:`T_{\mathrm{steady}}`.
"""
[docs] def __init__(self,amp=1.,omegas=0.65,A=-0.035,
alpha=-7.,m=2,gamma=numpy.pi/4.,p=None,
tform=None,tsteady=None,ro=None,vo=None):
"""
NAME:
__init__
PURPOSE:
initialize a logarithmic spiral potential
INPUT:
amp - amplitude to be applied to the potential (default:
1., A below)
gamma - angle between sun-GC line and the line connecting the peak of the spiral pattern at the Solar radius (in rad; default=45 degree; or can be Quantity)
A - amplitude (alpha*potential-amplitude; default=0.035; can be Quantity
omegas= - pattern speed (default=0.65; can be Quantity)
m= number of arms
Either provide:
a) alpha=
b) p= pitch angle (rad; can be Quantity)
tform - start of spiral growth / spiral period (default: -Infinity)
tsteady - time from tform at which the spiral is fully grown / spiral period (default: 2 periods)
OUTPUT:
(none)
HISTORY:
2011-03-27 - Started - Bovy (NYU)
"""
planarPotential.__init__(self,amp=amp,ro=ro,vo=vo)
gamma= conversion.parse_angle(gamma)
p= conversion.parse_angle(p)
A= conversion.parse_energy(A,vo=self._vo)
omegas= conversion.parse_frequency(omegas,ro=self._ro,vo=self._vo)
self._omegas= omegas
self._A= A
self._m= m
self._gamma= gamma
if not p is None:
self._alpha= self._m/numpy.tan(p)
else:
self._alpha= alpha
self._ts= 2.*numpy.pi/self._omegas
if not tform is None:
self._tform= tform*self._ts
else:
self._tform= None
if not tsteady is None:
self._tsteady= self._tform+tsteady*self._ts
else:
if self._tform is None: self._tsteady= None
else: self._tsteady= self._tform+2.*self._ts
self.hasC= True
def _evaluate(self,R,phi=0.,t=0.):
"""
NAME:
_evaluate
PURPOSE:
evaluate the potential at R,phi,t
INPUT:
R - Galactocentric cylindrical radius
phi - azimuth
t - time
OUTPUT:
Phi(R,phi,t)
HISTORY:
2011-03-27 - Started - Bovy (NYU)
"""
if not self._tform is None:
if t < self._tform:
smooth= 0.
elif t < self._tsteady:
deltat= t-self._tform
xi= 2.*deltat/(self._tsteady-self._tform)-1.
smooth= (3./16.*xi**5.-5./8*xi**3.+15./16.*xi+.5)
else: #spiral is fully on
smooth= 1.
else:
smooth= 1.
return smooth*self._A/self._alpha*numpy.cos(self._alpha*numpy.log(R)
-self._m*(phi-self._omegas*t
-self._gamma))
def _Rforce(self,R,phi=0.,t=0.):
"""
NAME:
_Rforce
PURPOSE:
evaluate the radial force for this potential
INPUT:
R - Galactocentric cylindrical radius
phi - azimuth
t - time
OUTPUT:
the radial force
HISTORY:
2010-11-24 - Written - Bovy (NYU)
"""
if not self._tform is None:
if t < self._tform:
smooth= 0.
elif t < self._tsteady:
deltat= t-self._tform
xi= 2.*deltat/(self._tsteady-self._tform)-1.
smooth= (3./16.*xi**5.-5./8*xi**3.+15./16.*xi+.5)
else: #spiral is fully on
smooth= 1.
else:
smooth= 1.
return smooth*self._A/R*numpy.sin(self._alpha*numpy.log(R)
-self._m*(phi-self._omegas*t
-self._gamma))
def _phiforce(self,R,phi=0.,t=0.):
"""
NAME:
_phiforce
PURPOSE:
evaluate the azimuthal force for this potential
INPUT:
R - Galactocentric cylindrical radius
phi - azimuth
t - time
OUTPUT:
the azimuthal force
HISTORY:
2010-11-24 - Written - Bovy (NYU)
"""
if not self._tform is None:
if t < self._tform:
smooth= 0.
elif t < self._tsteady:
deltat= t-self._tform
xi= 2.*deltat/(self._tsteady-self._tform)-1.
smooth= (3./16.*xi**5.-5./8*xi**3.+15./16.*xi+.5)
else: #spiral is fully on
smooth= 1.
else:
smooth= 1.
return -smooth*self._A/self._alpha*self._m*numpy.sin(self._alpha*numpy.log(R)
-self._m*(phi
-self._omegas*t
-self._gamma))
def wavenumber(self,R):
"""
NAME:
wavenumber
PURPOSE:
return the wavenumber at radius R (d f(R)/ d R in Phi_a(R) = F(R) e^[i f(R)]; see Binney & Tremaine 2008)
INPUT:
R - Cylindrical radius
OUTPUT:
wavenumber at R
HISTORY:
2014-08-23 - Written - Bovy (IAS)
"""
return self._alpha/R
def OmegaP(self):
"""
NAME:
OmegaP
PURPOSE:
return the pattern speed
INPUT:
(none)
OUTPUT:
pattern speed
HISTORY:
2011-10-10 - Written - Bovy (IAS)
"""
return self._omegas
def m(self):
"""
NAME:
m
PURPOSE:
return the number of arms
INPUT:
(none)
OUTPUT:
number of arms
HISTORY:
2014-08-23 - Written - Bovy (IAS)
"""
return self._m
def tform(self): #pragma: no cover
"""
NAME:
tform
PURPOSE:
return formation time of the bar
INPUT:
(none)
OUTPUT:
tform in normalized units
HISTORY:
2011-03-08 - Written - Bovy (NYU)
"""
return self._tform