###############################################################################
###############################################################################
import numpy
from ..util import conversion
from .planarPotential import 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,
"""
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
else:
if self._tform is None: self._tsteady= None
self.hasC= True

def _evaluate(self,R,phi=0.,t=0.):
"""
NAME:
_evaluate
PURPOSE:
evaluate the potential at R,phi,t
INPUT:
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.
deltat= t-self._tform
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:
phi - azimuth
t - time
OUTPUT:
HISTORY:
2010-11-24 - Written - Bovy (NYU)
"""
if not self._tform is None:
if t < self._tform:
smooth= 0.
deltat= t-self._tform
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:
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.
deltat= t-self._tform
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:

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