B
    d@4                 @   s   d dl Z d dlZddlmZmZmZ dZdZdZdZ	i Z
i Zi Zi Zdd	 Zd
d Zdd Zdd Zdd Zdd Zd!ddZd"ddZeeddZd#ddZeje_d$dd ZdS )%    N   )
_getspline	_qnmomega
_checkspingư>g{Gz?d   Fc             C   s$   | dkrt d| dkr tddS )z1Checks that the spin weight is a supported value.)r   zs must be either -2, -1, or 0r   z only s=-2 is currently supportedN)
ValueErrorNotImplementedError)s r   ]/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/pykerr/harmonics.py_checkspinweight   s    r   c             C   sT   t |  tdd|||t}tdd|||t}|| d||   }|dk rP| }|S )a  Returns the angular separation constant for a Kerr BH.

    Parmeters
    ---------
    spin : float
        The dimensionless spin. Must be in [-0.9999, 0.9999].
    l : int
        The l index.
    m : int
        The m index.
    n : int
        The overtone number (where n=0 is the fundamental mode).

    Returns
    -------
    complex :
        The complex separation constant.
    almreZimy              ?r   )r   r   _realm_splines_imalm_splinesconj)spinlmnZresplineZimspliner   r   r   r   kerr_alm#   s    r   c             C   s   d| d  | d|  d  S )zLeaver's alpha coefficient for the Slm (Eq. 20 of Leaver).

    Note: we use jj in place of Leaver's n so as not to confuse with the
    overtone index.
    r   r      r   )jjk1r   r   r   _alpha@   s    r   c             C   s,   | | d  d|  || d d|    | S )zLeaver's beta coefficient for the Slm (Eq. 20 of Leaver).

    Note: we use jj in place of Leaver's n so as not to confuse with the
    overtone index.
    r   r   r   )r   r   k2awalmtermr   r   r   _betaI   s    r    c             C   s   d| | | | |  S )zLeaver's gamma coefficient for the Slm (Eq. 20 of Leaver).

    Note: we use jj in place of Leaver's n so as not to confuse with the
    overtone index.
    r   r   )r   r   r   r   r   r   r   r   _gammaR   s    r!   c             C   s   | dkr|S | S )z/Convenience function to set tolerance defaults.Nr   )argdefaultr   r   r   _setdefault[   s    r$   r     Tc
             C   s   |	rdyJ|dk r,t dt|d|||t}
nt dt|d|||t}
|
| S  tk
rb   Y nX t|t}t|t}t|t	}t
jdt
j|d}t|| |||||||dd
}dt
j t
j| | jt
| |d	 d
 d S )a  Calculate the normalization constant for a spheroidal harmonic.

    The normalization is such that:

    .. math::

        \int_{0}^{2\pi}\int_{0}^{\pi} |{}_{-s}S_{\ell m}(J,\theta,\phi)|^2
            \sin(\theta)\mathrm{d}\theta \mathrm{d}\phi = 1

    where :math:`J` is the spin of the black hole.

    The integral is calulcated using the trapezoidal rule.

    Parameters
    ----------
    spin : float
        The dimensionless spin of the black hole.
    l : int
        The l index. Up to m=7 is supported.
    m : int
        The m index. All +/-m for the given l are supported.
    n : int
        The overtone number (where n=0 is the fundamental mode). Up to n=7 is
        supported.
    s : int, optional
        The spin number. Must be either 0, -1, or -2. Default is -2.
    npoints : int, optional
        The number of points to use in the integral. Default is 1000.
    tol : float, optional
        Tolerance used to determine when to stop the sum over coefficients
        :math:`c_n = a_n (1 + \cos(theta))^n` in the spheroidal harmonics (see
        Eq. 18 of Leaver). The sum stops when :math:`|c_n|` is less than the
        given value. If ``None`` (the default) will use
        :const:`pykerr.harmonics.TOL`.
    maxtol : float, optional
        Maximum allowed error in the sum over coefficients in the spheroidal
        harmonics. If no :math:`c_n` up to :math:`n` = ``max_recursion``
        satisfies :math:`|c_n| <` ``tol``, then the sum will be done up to
        the smallest :math:`|c_n|` such that :math:`|c_n|` < ``maxtol``. If
        no :math:`|c_n|` is < ``maxtol``, then a ValueError will be raised.
        If set to ``None`` (the default), will use
        :const:`pykerr.harmonics.MAXTOL`.
    max_recursion : int, optional
        Maximum number of terms that will be used in the sum over coefficients
        in the spheroidal harmonics (see Eq. 18 of Leaver). If ``None`` (the
        default), will use :const:`pykerr.harmonics.MAX_RECURSION`.
    use_cache : bool, optional
        Use tabulated values in the cached data, if available. A cubic spline
        is used to interpolate to spins that are not in the cache. Default is
        True.
    r   z	s{}nmnormNzs{}norm)numF)r   tolmaxtolmax_recursion	normalizer   r   )Zdxg      )r   formatabs_normnm_splines_norm_splinesKeyErrorr$   TOLMAXTOLMAX_RECURSIONnumpyZlinspacepi
spheroidalZtrapzr   realsin)r   r   r   r   r   Znpointsr'   r(   r)   	use_cacheZsplineZthetasslmr   r   r   slmnorm`   s$    5



"r:           c       #      C   s  t |t}t |t}t |	t}	t| t| }t||||}t||||}|| }dt	||  }dt	||  }d| d| | d  || || d   |d  ||d   | }d}d| }d}tj
|	td}|d |d< td|}td||||}|}| | | }ttjtj}xt	||kr||	k r|||  }|||< t||}t|||||}t|||||}|| ||   | }|}|}|d7 }qW ||	krt	| } ||  }t	||k r| d }trtd|t	|| ||||||	 t	||krPd	t	|| ||||||}!trH|!d
dtt|7 }!t|!|d|  }t|| d| |  d| |  d| |  }"|
r|"t||||||||	|d	9 }"||"9 }|d| dtd||   9 }|S )ag
  Calculate the spin-weighted spheroidal harmonic.

    See Eq. 18 of E. W. Leaver (1985)
    [`doi:10.1098/rspa.1985.0119` <https://doi.org/10.1098/rspa.1985.0119>].
    Solutions for the angular separation constants :math:`A_{\ell m}` are
    from Berti, Cardoso, & Starinets CQG26, 163001 (2009) [arXiv:0905.2975].

    Parameters
    ----------
    theta : float
        The polar angle of the observer with respect to the black hole's
        spin.
    spin : float
        The dimensionless spin of the black hole.
    l : int
        The l index. Up to l=7 is supported.
    m : int
        The m index. All +/-m for the given l are supported.
    n : int
        The overtone number (where n=0 is the fundamental mode). Up to n=7 is
        supported.
    s : int, optional
        The spin number. Must be either 0, -1, or -2. Default is -2.
    phi : float, optional
        The azimuthal angle of the observer. Default is 0.
    tol : float, optional
        Tolerance used to determine when to stop the sum over coefficients
        :math:`c_n = a_n (1 + \cos(theta))^n` in the spheroidal harmonics (see
        Eq. 18 of Leaver). The sum stops when :math:`|c_n|` is less than the
        given value. If ``None`` (the default) will use
        :const:`pykerr.harmonics.TOL`.
    maxtol : float, optional
        Maximum allowed error in the sum over coefficients in the spheroidal
        harmonics. If no :math:`c_n` up to :math:`n` = ``max_recursion``
        satisfies :math:`|c_n| <` ``tol``, then the sum will be done up to
        the smallest :math:`|c_n|` such that :math:`|c_n|` < ``maxtol``. If
        no :math:`|c_n|` is < ``maxtol``, then a ValueError will be raised.
        If set to ``None`` (the default), will use
        :const:`pykerr.harmonics.MAXTOL`.
    max_recursion : int, optional
        Maximum number of terms that will be used in the sum over coefficients
        in the spheroidal harmonics (see Eq. 18 of Leaver). If ``None`` (the
        default), will use :const:`pykerr.harmonics.MAX_RECURSION`.
    normalize : bool, optional
        Normalize the harmonic before returning. The normalization is such
        that the harmonic integrates to 1 over the unit sphere.
    use_cache : bool, optional
        If normalizing, use tabulated normalization constants in the cached
        data, if available. A cubic spline is used to interpolate to spins that
        are not in the cache. Otherwise, the normalization constant will be
        calculated on the fly by numerically integrating over theta. Default is
        True.

    Returns
    -------
    slm : complex
        The value of the spheroidal harmonic.
    g      ?r   r   g      ?)Zdtypey                r   zDid not get to target tolerance of {} for Slm. Actual tolerance is {}. Parameters: theta={}, spin={}, l={}, m={}, n={}, s={}, phi={}zMax recursion exceeded without satisfying maxtol. Smallest abs(term): {}. Parameters: theta={}, spin={}, l={}, m={}, n={}, s={}, phi={}.z
 Terms:
{}
Ny              ?)r   r'   r(   r)   r8   r   )r$   r0   r1   r2   r   r3   cosr   r   r,   Zzeroscomplexr   r    infr!   ZargminDEBUGloggingdebugr+   joinmapstrr	   sumexpr:   max)#thetar   r   r   r   r   phir'   r(   r)   r*   r8   ur   omegar   r   r   r   r   Zb_nZa0r9   Zalpha0Zbeta0Za_nm1Za_nZc_nZalpha_nZbeta_nZgamma_nZa_np1ZminidxmsgZnormr   r   r   _pyslm   sl    =



D


2rN      c             C   s:   t | |||||||||	|
|}t|tjr6|tj}|S )N)_npslm
isinstancer3   ZndarrayZastyper>   )rI   r   r   r   r   r   rJ   r'   r(   r)   r*   r8   outr   r   r   r5   @  s
    r5   c          	      s   yddl m  W n tk
r,   tdY nX y | |S  tk
r   t| } t|}t| |}t fdd|D |j	S X dS )a  Calculate the spin-weighted spherical harmonic.

    Uses functions from lal.

    Parameters
    ----------
    theta : float or array
        The polar angle.
    l : int
        The l index.
    m : int
        The m index.
    s : int, optional
        The spin number. Default is -2.
    phi : float or array, optional
        The azimuthal angle. Default is 0.

    Returns
    -------
    complex :
        The value of the spherical harmonic.
    r   )SpinWeightedSphericalHarmonicz[lalsuite must be installed to generate the spherical harmonics. Run `pip install lalsuite`.c                s    g | ]\}} ||qS r   r   ).0incrJ   )
_sphericalr   r   r   r   r   
<listcomp>q  s   zspherical.<locals>.<listcomp>N)
ZlalrS   ImportError	TypeErrorr3   Z
atleast_1d	broadcastarrayZreshapeshape)rI   r   r   r   rJ   Zincphir   )rV   r   r   r   r   	sphericalM  s    

r]   )r   r%   NNNT)r   r;   NNNTT)r   r;   NNNTT)r   r;   )rA   r3   Zqnmr   r   r   r0   r1   r2   r@   r   r   r.   r-   r   r   r   r    r!   r$   r:   rN   Z
frompyfuncrP   r5   __doc__r]   r   r   r   r   <module>   s4   			 
K 
  
	