示例#1
0
 def actionsFreqs(self,*args,**kwargs):
     """
     NAME:
        actionsFreqs
     PURPOSE:
        evaluate the actions and frequencies (jr,lz,jz,Omegar,Omegaphi,Omegaz)
     INPUT:
        Either:
           a) R,vR,vT,z,vz
           b) Orbit instance: initial condition used if that's it, orbit(t)
              if there is a time given as well
        scipy.integrate.quadrature keywords
     OUTPUT:
         (jr,lz,jz,Omegar,Omegaphi,Omegaz)
     HISTORY:
        2013-08-28 - Written - Bovy (IAS)
     """
     if ((self._c and not (kwargs.has_key('c') and not kwargs['c']))\
             or (ext_loaded and ((kwargs.has_key('c') and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5: #R,vR.vT, z, vz
             R,vR,vT, z, vz= args
         elif len(args) == 6: #R,vR.vT, z, vz, phi
             R,vR,vT, z, vz, phi= args
         else:
             meta= actionAngle(*args)
             R= meta._R
             vR= meta._vR
             vT= meta._vT
             z= meta._z
             vz= meta._vz
         if isinstance(R,float):
             R= nu.array([R])
             vR= nu.array([vR])
             vT= nu.array([vT])
             z= nu.array([z])
             vz= nu.array([vz])
         Lz= R*vT
         if self._useu0:
             #First calculate u0
             if kwargs.has_key('u0'):
                 u0= kwargs['u0']
             else:
                 E= nu.array([evaluatePotentials(R[ii],z[ii],self._pot) +vR[ii]**2./2.+vz[ii]**2./2.+vT[ii]**2./2. for ii in range(len(R))])
                 u0= actionAngleStaeckel_c.actionAngleStaeckel_calcu0(E,Lz,
                                                                      self._pot,
                                                                      self._delta)[0]
             if kwargs.has_key('u0'): kwargs.pop('u0')
         else:
             u0= None
         jr, jz, Omegar, Omegaphi, Omegaz, err= actionAngleStaeckel_c.actionAngleFreqStaeckel_c(\
             self._pot,self._delta,R,vR,vT,z,vz,u0=u0)
         if err == 0:
             return (jr,Lz,jz,Omegar,Omegaphi,Omegaz)
         else:
             raise RuntimeError("C-code for calculation actions failed; try with c=False")
     else:
         if kwargs.has_key('c') and kwargs['c'] and not self._c:
             warnings.warn("C module not used because potential does not have a C implementation",galpyWarning)
         raise NotImplementedError("actionsFreqs with c=False not implemented")
示例#2
0
    def __init__(self,*args,**kwargs):
        """
        NAME:
           __init__
        PURPOSE:
           initialize an actionAngleAdiabatic object
        INPUT:

           pot= potential or list of potentials (planarPotentials)

           gamma= (default=1.) replace Lz by Lz+gamma Jz in effective potential
        OUTPUT:
        HISTORY:
            2012-07-26 - Written - Bovy (IAS@MPIA)
        """
        if not 'pot' in kwargs: #pragma: no cover
            raise IOError("Must specify pot= for actionAngleAxi")
        self._pot= kwargs['pot']
        if self._pot == MWPotential:
            warnings.warn("Use of MWPotential as a Milky-Way-like potential is deprecated; galpy.potential.MWPotential2014, a potential fit to a large variety of dynamical constraints (see Bovy 2015), is the preferred Milky-Way-like potential in galpy",
                          galpyWarning)
        if ext_loaded and 'c' in kwargs and kwargs['c']:
            self._c= _check_c(self._pot)
            if 'c' in kwargs and kwargs['c'] and not self._c:
                warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) #pragma: no cover
        else:
            self._c= False
        self._gamma= kwargs.get('gamma',1.)
        return None
示例#3
0
    def __init__(self,*args,**kwargs):
        """
        NAME:
           __init__
        PURPOSE:
           initialize an actionAngleAdiabatic object
        INPUT:

           pot= potential or list of potentials (planarPotentials)

           gamma= (default=1.) replace Lz by Lz+gamma Jz in effective potential
        OUTPUT:
        HISTORY:
            2012-07-26 - Written - Bovy (IAS@MPIA)
        """
        if not kwargs.has_key('pot'): #pragma: no cover
            raise IOError("Must specify pot= for actionAngleAxi")
        self._pot= kwargs['pot']
        if ext_loaded and kwargs.has_key('c') and kwargs['c']:
            self._c= _check_c(self._pot)
            if kwargs.has_key('c') and kwargs['c'] and not self._c:
                warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) #pragma: no cover
        else:
            self._c= False
        if kwargs.has_key('gamma'):
            self._gamma= kwargs['gamma']
        else:
            self._gamma= 1.
        return None
示例#4
0
    def __init__(self, *args, **kwargs):
        """
        NAME:
           __init__
        PURPOSE:
           initialize an actionAngleStaeckel object
        INPUT:
           pot= potential or list of potentials (3D)

           delta= focus (can be Quantity)

           useu0 - use u0 to calculate dV (NOT recommended)

           c= if True, always use C for calculations

           order= (10) number of points to use in the Gauss-Legendre numerical integration of the relevant action, frequency, and angle integrals

           ro= distance from vantage point to GC (kpc; can be Quantity)

           vo= circular velocity at ro (km/s; can be Quantity)

        OUTPUT:

           instance

        HISTORY:

           2012-11-27 - Written - Bovy (IAS)

        """
        actionAngle.__init__(self,
                             ro=kwargs.get('ro', None),
                             vo=kwargs.get('vo', None))
        if not 'pot' in kwargs:  #pragma: no cover
            raise IOError("Must specify pot= for actionAngleStaeckel")
        self._pot = kwargs['pot']
        if self._pot == MWPotential:
            warnings.warn(
                "Use of MWPotential as a Milky-Way-like potential is deprecated; galpy.potential.MWPotential2014, a potential fit to a large variety of dynamical constraints (see Bovy 2015), is the preferred Milky-Way-like potential in galpy",
                galpyWarning)
        if not 'delta' in kwargs:  #pragma: no cover
            raise IOError("Must specify delta= for actionAngleStaeckel")
        if ext_loaded and (('c' in kwargs and kwargs['c'])
                           or not 'c' in kwargs):
            self._c = _check_c(self._pot)
            if 'c' in kwargs and kwargs['c'] and not self._c:
                warnings.warn(
                    "C module not used because potential does not have a C implementation",
                    galpyWarning)  #pragma: no cover
        else:
            self._c = False
        self._useu0 = kwargs.get('useu0', False)
        self._delta = kwargs['delta']
        self._order = kwargs.get('order', 10)
        if _APY_LOADED and isinstance(self._delta, units.Quantity):
            self._delta = self._delta.to(units.kpc).value / self._ro
        # Check the units
        self._check_consistent_units()
        return None
示例#5
0
def _integrateROrbit(vxvv,pot,t,method,dt):
    """
    NAME:
       _integrateROrbit
    PURPOSE:
       integrate an orbit in a Phi(R) potential in the R-plane
    INPUT:
       vxvv - array with the initial conditions stacked like
              [R,vR,vT]; vR outward!
       pot - Potential instance
       t - list of times at which to output (0 has to be in this!)
       method - 'odeint' or 'leapfrog'
       dt - if set, force the integrator to use this basic stepsize; must be an integer divisor of output stepsize
    OUTPUT:
       [:,3] array of [R,vR,vT] at each t
    HISTORY:
       2010-07-20 - Written - Bovy (NYU)
    """
    #First check that the potential has C
    if '_c' in method:
        if not _check_c(pot):
            if ('leapfrog' in method or 'symplec' in method):
                method= 'leapfrog'
            else:
                method= 'odeint'
            warnings.warn("Cannot use C integration because some of the potentials are not implemented in C (using %s instead)" % (method), galpyWarning)
    if method.lower() == 'leapfrog':
        #We hack this by putting in a dummy phi
        this_vxvv= nu.zeros(len(vxvv)+1)
        this_vxvv[0:len(vxvv)]= vxvv
        tmp_out, msg= _integrateOrbit(this_vxvv,pot,t,method,dt)
        #tmp_out is (nt,4)
        out= tmp_out[:,0:3]
    elif method.lower() == 'leapfrog_c' or method.lower() == 'rk4_c' \
            or method.lower() == 'rk6_c' or method.lower() == 'symplec4_c' \
            or method.lower() == 'symplec6_c' or method.lower() == 'dopr54_c':
        #We hack this by putting in a dummy phi
        this_vxvv= nu.zeros(len(vxvv)+1)
        this_vxvv[0:len(vxvv)]= vxvv
        tmp_out, msg= _integrateOrbit(this_vxvv,pot,t,method,dt)
        #tmp_out is (nt,4)
        out= tmp_out[:,0:3]
    elif method.lower() == 'odeint':
        l= vxvv[0]*vxvv[2]
        l2= l**2.
        init= [vxvv[0],vxvv[1]]
        intOut= integrate.odeint(_REOM,init,t,args=(pot,l2),
                                 rtol=10.**-8.)#,mxstep=100000000)
        out= nu.zeros((len(t),3))
        out[:,0]= intOut[:,0]
        out[:,1]= intOut[:,1]
        out[:,2]= l/out[:,0]
        msg= 0
    #post-process to remove negative radii
    neg_radii= (out[:,0] < 0.)
    out[neg_radii,0]= -out[neg_radii,0]
    _parse_warnmessage(msg)
    return (out,msg)
    def __init__(self,*args,**kwargs):
        """
        NAME:
           __init__
        PURPOSE:
           initialize an actionAngleStaeckel object
        INPUT:
           pot= potential or list of potentials (3D)

           delta= focus (can be Quantity)

           useu0 - use u0 to calculate dV (NOT recommended)

           c= if True, always use C for calculations

           ro= distance from vantage point to GC (kpc; can be Quantity)

           vo= circular velocity at ro (km/s; can be Quantity)

        OUTPUT:

           instance

        HISTORY:

           2012-11-27 - Written - Bovy (IAS)

        """
        actionAngle.__init__(self,
                             ro=kwargs.get('ro',None),vo=kwargs.get('vo',None))
        if not 'pot' in kwargs: #pragma: no cover
            raise IOError("Must specify pot= for actionAngleStaeckel")
        self._pot= kwargs['pot']
        if self._pot == MWPotential:
            warnings.warn("Use of MWPotential as a Milky-Way-like potential is deprecated; galpy.potential.MWPotential2014, a potential fit to a large variety of dynamical constraints (see Bovy 2015), is the preferred Milky-Way-like potential in galpy",
                          galpyWarning)
        if not 'delta' in kwargs: #pragma: no cover
            raise IOError("Must specify delta= for actionAngleStaeckel")
        if ext_loaded and (('c' in kwargs and kwargs['c'])
                           or not 'c' in kwargs):           
            self._c= _check_c(self._pot)
            if 'c' in kwargs and kwargs['c'] and not self._c:
                warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) #pragma: no cover
        else:
            self._c= False
        self._useu0= kwargs.get('useu0',False)
        self._delta= kwargs['delta']
        if _APY_LOADED and isinstance(self._delta,units.Quantity):
            self._delta= self._delta.to(units.kpc).value/self._ro
        # Check the units
        self._check_consistent_units()
        return None
示例#7
0
    def __init__(self, *args, **kwargs):
        """
        NAME:

           __init__

        PURPOSE:

           initialize an actionAngleTorus object

        INPUT:

           pot= potential or list of potentials (3D)

           tol= default tolerance to use when fitting tori (|dJ|/J)

           dJ= default action difference when computing derivatives (Hessian or Jacobian)

        OUTPUT:

           instance

        HISTORY:

           2015-08-07 - Written - Bovy (UofT)

        """
        if not 'pot' in kwargs:  #pragma: no cover
            raise IOError("Must specify pot= for actionAngleTorus")
        self._pot = kwargs['pot']
        if _isNonAxi(self._pot):
            raise RuntimeError(
                "actionAngleTorus for non-axisymmetric potentials is not supported"
            )
        if self._pot == MWPotential:
            warnings.warn(
                "Use of MWPotential as a Milky-Way-like potential is deprecated; galpy.potential.MWPotential2014, a potential fit to a large variety of dynamical constraints (see Bovy 2015), is the preferred Milky-Way-like potential in galpy",
                galpyWarning)
        if ext_loaded:
            self._c = _check_c(self._pot)
            if not self._c:
                raise RuntimeError(
                    'The given potential is not fully implemented in C; using the actionAngleTorus code is not supported in pure Python'
                )
        else:  # pragma: no cover
            raise RuntimeError(
                'actionAngleTorus instances cannot be used, because the actionAngleTorus_c extension failed to load'
            )
        self._tol = kwargs.get('tol', 0.001)
        self._dJ = kwargs.get('dJ', 0.001)
        return None
示例#8
0
    def __init__(self, *args, **kwargs):
        """
        NAME:

           __init__

        PURPOSE:

           initialize an actionAngleAdiabatic object

        INPUT:

           pot= potential or list of potentials (planarPotentials)

           gamma= (default=1.) replace Lz by Lz+gamma Jz in effective potential

           ro= distance from vantage point to GC (kpc; can be Quantity)

           vo= circular velocity at ro (km/s; can be Quantity)

        OUTPUT:
        
           instance

        HISTORY:

            2012-07-26 - Written - Bovy (IAS@MPIA)

        """
        actionAngle.__init__(self,
                             ro=kwargs.get('ro', None),
                             vo=kwargs.get('vo', None))
        if not 'pot' in kwargs:  #pragma: no cover
            raise IOError("Must specify pot= for actionAngleAxi")
        self._pot = flatten_potential(kwargs['pot'])
        if self._pot == MWPotential:
            warnings.warn(
                "Use of MWPotential as a Milky-Way-like potential is deprecated; galpy.potential.MWPotential2014, a potential fit to a large variety of dynamical constraints (see Bovy 2015), is the preferred Milky-Way-like potential in galpy",
                galpyWarning)
        if ext_loaded and 'c' in kwargs and kwargs['c']:
            self._c = _check_c(self._pot)
            if 'c' in kwargs and kwargs['c'] and not self._c:
                warnings.warn(
                    "C module not used because potential does not have a C implementation",
                    galpyWarning)  #pragma: no cover
        else:
            self._c = False
        self._gamma = kwargs.get('gamma', 1.)
        # Check the units
        self._check_consistent_units()
        return None
示例#9
0
    def __init__(self,*args,**kwargs):
        """
        NAME:

           __init__

        PURPOSE:

           initialize an actionAngleAdiabatic object

        INPUT:

           pot= potential or list of potentials (planarPotentials)

           gamma= (default=1.) replace Lz by Lz+gamma Jz in effective potential

           ro= distance from vantage point to GC (kpc; can be Quantity)

           vo= circular velocity at ro (km/s; can be Quantity)

        OUTPUT:
        
           instance

        HISTORY:

            2012-07-26 - Written - Bovy (IAS@MPIA)

        """
        actionAngle.__init__(self,
                             ro=kwargs.get('ro',None),vo=kwargs.get('vo',None))
        if not 'pot' in kwargs: #pragma: no cover
            raise IOError("Must specify pot= for actionAngleAxi")
        self._pot= flatten_potential(kwargs['pot'])
        if self._pot == MWPotential:
            warnings.warn("Use of MWPotential as a Milky-Way-like potential is deprecated; galpy.potential.MWPotential2014, a potential fit to a large variety of dynamical constraints (see Bovy 2015), is the preferred Milky-Way-like potential in galpy",
                          galpyWarning)
        if ext_loaded and 'c' in kwargs and kwargs['c']:
            self._c= _check_c(self._pot)
            if 'c' in kwargs and kwargs['c'] and not self._c:
                warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) #pragma: no cover
        else:
            self._c= False
        self._gamma= kwargs.get('gamma',1.)
        # Check the units
        self._check_consistent_units()
        return None
示例#10
0
    def __init__(self,*args,**kwargs):
        """
        NAME:

           __init__

        PURPOSE:

           initialize an actionAngleTorus object

        INPUT:

           pot= potential or list of potentials (3D)

           tol= default tolerance to use when fitting tori (|dJ|/J)

           dJ= default action difference when computing derivatives (Hessian or Jacobian)

        OUTPUT:

           instance

        HISTORY:

           2015-08-07 - Written - Bovy (UofT)

        """
        if not 'pot' in kwargs: #pragma: no cover
            raise IOError("Must specify pot= for actionAngleTorus")
        self._pot= kwargs['pot']
        if _isNonAxi(self._pot):
            raise RuntimeError("actionAngleTorus for non-axisymmetric potentials is not supported")
        if self._pot == MWPotential:
            warnings.warn("Use of MWPotential as a Milky-Way-like potential is deprecated; galpy.potential.MWPotential2014, a potential fit to a large variety of dynamical constraints (see Bovy 2015), is the preferred Milky-Way-like potential in galpy",
                          galpyWarning)
        if ext_loaded:
            self._c= _check_c(self._pot)
            if not self._c:
                raise RuntimeError('The given potential is not fully implemented in C; using the actionAngleTorus code is not supported in pure Python')
        else:# pragma: no cover
            raise RuntimeError('actionAngleTorus instances cannot be used, because the actionAngleTorus_c extension failed to load')
        self._tol= kwargs.get('tol',0.001)
        self._dJ= kwargs.get('dJ',0.001)
        return None
示例#11
0
    def __init__(self, *args, **kwargs):
        """
        NAME:
           __init__
        PURPOSE:
           initialize an actionAngleStaeckel object
        INPUT:
           pot= potential or list of potentials (3D)

           delta= focus

           useu0 - use u0 to calculate dV (NOT recommended)

           c= if True, always use C for calculations
        OUTPUT:
        HISTORY:
           2012-11-27 - Written - Bovy (IAS)
        """
        if not 'pot' in kwargs:  #pragma: no cover
            raise IOError("Must specify pot= for actionAngleStaeckel")
        self._pot = kwargs['pot']
        if self._pot == MWPotential:
            warnings.warn(
                "Use of MWPotential as a Milky-Way-like potential is deprecated; galpy.potential.MWPotential2014, a potential fit to a large variety of dynamical constraints (see Bovy 2015), is the preferred Milky-Way-like potential in galpy",
                galpyWarning)
        if not 'delta' in kwargs:  #pragma: no cover
            raise IOError("Must specify delta= for actionAngleStaeckel")
        if ext_loaded and (('c' in kwargs and kwargs['c'])
                           or not 'c' in kwargs):
            self._c = _check_c(self._pot)
            if 'c' in kwargs and kwargs['c'] and not self._c:
                warnings.warn(
                    "C module not used because potential does not have a C implementation",
                    galpyWarning)  #pragma: no cover
        else:
            self._c = False
        self._useu0 = kwargs.get('useu0', False)
        self._delta = kwargs['delta']
        return None
示例#12
0
    def __init__(self,*args,**kwargs):
        """
        NAME:
           __init__
        PURPOSE:
           initialize an actionAngleStaeckel object
        INPUT:
           pot= potential or list of potentials (3D)

           delta= focus

           useu0 - use u0 to calculate dV (NOT recommended)

           c= if True, always use C for calculations
        OUTPUT:
        HISTORY:
           2012-11-27 - Written - Bovy (IAS)
        """
        if not kwargs.has_key('pot'):
            raise IOError("Must specify pot= for actionAngleStaeckel")
        self._pot= kwargs['pot']
        if not kwargs.has_key('delta'):
            raise IOError("Must specify delta= for actionAngleStaeckel")
        if ext_loaded and ((kwargs.has_key('c') and kwargs['c'])
                           or not kwargs.has_key('c')):           
            self._c= _check_c(self._pot)
            if kwargs.has_key('c') and kwargs['c'] and not self._c:
                warnings.warn("C module not used because potential does not have a C implementation",galpyWarning)
        else:
            self._c= False
        if kwargs.has_key('useu0') and kwargs['useu0']:
            self._useu0= True
        else:
            self._useu0= False
        self._delta= kwargs['delta']
        return None
示例#13
0
    def __init__(self,*args,**kwargs):
        """
        NAME:
           __init__
        PURPOSE:
           initialize an actionAngleStaeckel object
        INPUT:
           pot= potential or list of potentials (3D)

           delta= focus

           useu0 - use u0 to calculate dV (NOT recommended)

           c= if True, always use C for calculations
        OUTPUT:
        HISTORY:
           2012-11-27 - Written - Bovy (IAS)
        """
        if not 'pot' in kwargs: #pragma: no cover
            raise IOError("Must specify pot= for actionAngleStaeckel")
        self._pot= kwargs['pot']
        if self._pot == MWPotential:
            warnings.warn("Use of MWPotential as a Milky-Way-like potential is deprecated; galpy.potential.MWPotential2014, a potential fit to a large variety of dynamical constraints (see Bovy 2015), is the preferred Milky-Way-like potential in galpy",
                          galpyWarning)
        if not 'delta' in kwargs: #pragma: no cover
            raise IOError("Must specify delta= for actionAngleStaeckel")
        if ext_loaded and (('c' in kwargs and kwargs['c'])
                           or not 'c' in kwargs):           
            self._c= _check_c(self._pot)
            if 'c' in kwargs and kwargs['c'] and not self._c:
                warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) #pragma: no cover
        else:
            self._c= False
        self._useu0= kwargs.get('useu0',False)
        self._delta= kwargs['delta']
        return None
示例#14
0
 def _evaluate(self, *args, **kwargs):
     """
     NAME:
        __call__ (_evaluate)
     PURPOSE:
        evaluate the actions (jr,lz,jz)
     INPUT:
        Either:
           a) R,vR,vT,z,vz[,phi]:
              1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
              2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
           b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument 
        delta= (object-wide default) can be used to override the object-wide focal length; can also be an array with length N to allow different delta for different phase-space points
        u0= (None) if object-wide option useu0 is set, u0 to use (if useu0 and useu0 is None, a good value will be computed)
        c= (object-wide default, bool) True/False to override the object-wide setting for whether or not to use the C implementation
        order= (object-wide default, int) number of points to use in the Gauss-Legendre numerical integration of the relevant action integrals  
        When not using C:
           fixed_quad= (False) if True, use Gaussian quadrature (scipy.integrate.fixed_quad instead of scipy.integrate.quad)
           scipy.integrate.fixed_quad or .quad keywords
     OUTPUT:
        (jr,lz,jz)
     HISTORY:
        2012-11-27 - Written - Bovy (IAS)
        2017-12-27 - Allowed individual delta for each point - Bovy (UofT)
     """
     delta = kwargs.pop('delta', self._delta)
     order = kwargs.get('order', self._order)
     if ((self._c and not ('c' in kwargs and not kwargs['c']))\
             or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5:  #R,vR.vT, z, vz
             R, vR, vT, z, vz = args
         elif len(args) == 6:  #R,vR.vT, z, vz, phi
             R, vR, vT, z, vz, phi = args
         else:
             self._parse_eval_args(*args)
             R = self._eval_R
             vR = self._eval_vR
             vT = self._eval_vT
             z = self._eval_z
             vz = self._eval_vz
         if isinstance(R, float):
             R = nu.array([R])
             vR = nu.array([vR])
             vT = nu.array([vT])
             z = nu.array([z])
             vz = nu.array([vz])
         Lz = R * vT
         if self._useu0:
             #First calculate u0
             if 'u0' in kwargs:
                 u0 = nu.asarray(kwargs['u0'])
             else:
                 E = nu.array([
                     _evaluatePotentials(self._pot, R[ii], z[ii]) +
                     vR[ii]**2. / 2. + vz[ii]**2. / 2. + vT[ii]**2. / 2.
                     for ii in range(len(R))
                 ])
                 u0= actionAngleStaeckel_c.actionAngleStaeckel_calcu0(\
                     E,Lz,self._pot,delta)[0]
             kwargs.pop('u0', None)
         else:
             u0 = None
         jr, jz, err= actionAngleStaeckel_c.actionAngleStaeckel_c(\
             self._pot,delta,R,vR,vT,z,vz,u0=u0,order=order)
         if err == 0:
             return (jr, Lz, jz)
         else:  #pragma: no cover
             raise RuntimeError(
                 "C-code for calculation actions failed; try with c=False")
     else:
         if 'c' in kwargs and kwargs['c'] and not self._c:  #pragma: no cover
             warnings.warn(
                 "C module not used because potential does not have a C implementation",
                 galpyWarning)
         kwargs.pop('c', None)
         if (len(args) == 5 or len(args) == 6) \
                 and isinstance(args[0],nu.ndarray):
             ojr = nu.zeros((len(args[0])))
             olz = nu.zeros((len(args[0])))
             ojz = nu.zeros((len(args[0])))
             for ii in range(len(args[0])):
                 if len(args) == 5:
                     targs = (args[0][ii], args[1][ii], args[2][ii],
                              args[3][ii], args[4][ii])
                 elif len(args) == 6:
                     targs = (args[0][ii], args[1][ii], args[2][ii],
                              args[3][ii], args[4][ii], args[5][ii])
                 tkwargs = copy.copy(kwargs)
                 try:
                     tkwargs['delta'] = delta[ii]
                 except TypeError:
                     tkwargs['delta'] = delta
                 tjr, tlz, tjz = self(*targs, **tkwargs)
                 ojr[ii] = tjr
                 ojz[ii] = tjz
                 olz[ii] = tlz
             return (ojr, olz, ojz)
         else:
             #Set up the actionAngleStaeckelSingle object
             aASingle = actionAngleStaeckelSingle(*args,
                                                  pot=self._pot,
                                                  delta=delta)
             return (aASingle.JR(**copy.copy(kwargs)),
                     aASingle._R * aASingle._vT,
                     aASingle.Jz(**copy.copy(kwargs)))
示例#15
0
 def _uminumaxvmin(self, *args, **kwargs):
     """
     NAME:
        _uminumaxvmin
     PURPOSE:
        evaluate u_min, u_max, and v_min
     INPUT:
        Either:
           a) R,vR,vT,z,vz
           b) Orbit instance: initial condition used if that's it, orbit(t)
              if there is a time given as well
         c= True/False; overrides the object's c= keyword to use C or not
     OUTPUT:
        (umin,umax,vmin)
     HISTORY:
        2017-12-12 - Written - Bovy (UofT)
     """
     delta = kwargs.pop('delta', self._delta)
     if ((self._c and not ('c' in kwargs and not kwargs['c']))\
             or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5:  #R,vR.vT, z, vz
             R, vR, vT, z, vz = args
         elif len(args) == 6:  #R,vR.vT, z, vz, phi
             R, vR, vT, z, vz, phi = args
         else:
             self._parse_eval_args(*args)
             R = self._eval_R
             vR = self._eval_vR
             vT = self._eval_vT
             z = self._eval_z
             vz = self._eval_vz
         if isinstance(R, float):
             R = nu.array([R])
             vR = nu.array([vR])
             vT = nu.array([vT])
             z = nu.array([z])
             vz = nu.array([vz])
         Lz = R * vT
         if self._useu0:
             #First calculate u0
             if 'u0' in kwargs:
                 u0 = nu.asarray(kwargs['u0'])
             else:
                 E = nu.array([
                     _evaluatePotentials(self._pot, R[ii], z[ii]) +
                     vR[ii]**2. / 2. + vz[ii]**2. / 2. + vT[ii]**2. / 2.
                     for ii in range(len(R))
                 ])
                 u0= actionAngleStaeckel_c.actionAngleStaeckel_calcu0(\
                     E,Lz,self._pot,delta)[0]
             kwargs.pop('u0', None)
         else:
             u0 = None
         umin, umax, vmin, err= \
             actionAngleStaeckel_c.actionAngleUminUmaxVminStaeckel_c(\
             self._pot,delta,R,vR,vT,z,vz,u0=u0)
         if err == 0:
             return (umin, umax, vmin)
         else:  #pragma: no cover
             raise RuntimeError(
                 "C-code for calculation actions failed; try with c=False")
     else:
         if 'c' in kwargs and kwargs['c'] and not self._c:  #pragma: no cover
             warnings.warn(
                 "C module not used because potential does not have a C implementation",
                 galpyWarning)
         kwargs.pop('c', None)
         if (len(args) == 5 or len(args) == 6) \
                 and isinstance(args[0],nu.ndarray):
             oumin = nu.zeros((len(args[0])))
             oumax = nu.zeros((len(args[0])))
             ovmin = nu.zeros((len(args[0])))
             for ii in range(len(args[0])):
                 if len(args) == 5:
                     targs = (args[0][ii], args[1][ii], args[2][ii],
                              args[3][ii], args[4][ii])
                 elif len(args) == 6:
                     targs = (args[0][ii], args[1][ii], args[2][ii],
                              args[3][ii], args[4][ii], args[5][ii])
                 tkwargs = copy.copy(kwargs)
                 try:
                     tkwargs['delta'] = delta[ii]
                 except TypeError:
                     tkwargs['delta'] = delta
                 tumin,tumax,tvmin= self._uminumaxvmin(\
                     *targs,**tkwargs)
                 oumin[ii] = tumin
                 oumax[ii] = tumax
                 ovmin[ii] = tvmin
             return (oumin, oumax, ovmin)
         else:
             #Set up the actionAngleStaeckelSingle object
             aASingle = actionAngleStaeckelSingle(*args,
                                                  pot=self._pot,
                                                  delta=delta)
             umin, umax = aASingle.calcUminUmax()
             vmin = aASingle.calcVmin()
             return (umin, umax, vmin)
示例#16
0
文件: planarOrbit.py 项目: smoh/galpy
def _integrateOrbit_dxdv(vxvv,dxdv,pot,t,method,rectIn,rectOut):
    """
    NAME:
       _integrateOrbit_dxdv
    PURPOSE:
       integrate an orbit and area of phase space in a Phi(R) potential 
       in the (R,phi)-plane
    INPUT:
       vxvv - array with the initial conditions stacked like
              [R,vR,vT,phi]; vR outward!
       dxdv - difference to integrate [dR,dvR,dvT,dphi]
       pot - Potential instance
       t - list of times at which to output (0 has to be in this!)
       method - 'odeint' or 'leapfrog'
       rectIn= (False) if True, input dxdv is in rectangular coordinates
       rectOut= (False) if True, output dxdv (that in orbit_dxdv) is in rectangular coordinates
    OUTPUT:
       [:,8] array of [R,vR,vT,phi,dR,dvR,dvT,dphi] at each t
       error message from integrator
    HISTORY:
       2010-10-17 - Written - Bovy (IAS)
    """
    #First check that the potential has C
    if '_c' in method:
        allHasC= _check_c(pot) and _check_c(pot,dxdv=True)
        if not allHasC and not 'leapfrog' in method and not 'symplec' in method:
            method= 'odeint'
            warnings.warn("Using odeint because not all used potential have adequate C implementations to integrate phase-space volumes",galpyWarning)
    #go to the rectangular frame
    this_vxvv= nu.array([vxvv[0]*nu.cos(vxvv[3]),
                         vxvv[0]*nu.sin(vxvv[3]),
                         vxvv[1]*nu.cos(vxvv[3])-vxvv[2]*nu.sin(vxvv[3]),
                         vxvv[2]*nu.cos(vxvv[3])+vxvv[1]*nu.sin(vxvv[3])])
    if not rectIn:
        this_dxdv= nu.array([nu.cos(vxvv[3])*dxdv[0]
                             -vxvv[0]*nu.sin(vxvv[3])*dxdv[3],
                             nu.sin(vxvv[3])*dxdv[0]
                             +vxvv[0]*nu.cos(vxvv[3])*dxdv[3],
                             -(vxvv[1]*nu.sin(vxvv[3])
                               +vxvv[2]*nu.cos(vxvv[3]))*dxdv[3]
                             +nu.cos(vxvv[3])*dxdv[1]-nu.sin(vxvv[3])*dxdv[2],
                             (vxvv[1]*nu.cos(vxvv[3])
                              -vxvv[2]*nu.sin(vxvv[3]))*dxdv[3]
                             +nu.sin(vxvv[3])*dxdv[1]+nu.cos(vxvv[3])*dxdv[2]])
    else:
        this_dxdv= dxdv
    if 'leapfrog' in method.lower() or 'symplec' in method.lower():
        raise TypeError('Symplectic integration for phase-space volume is not possible')
    elif method.lower() == 'rk4_c' or method.lower() == 'rk6_c' \
            or method.lower() == 'dopr54_c':
        warnings.warn("Using C implementation to integrate orbits",galpyWarning)
        #integrate
        tmp_out, msg= integratePlanarOrbit_dxdv_c(pot,this_vxvv,this_dxdv,
                                                  t,method)
    elif method.lower() == 'odeint':
        init= [this_vxvv[0],this_vxvv[1],this_vxvv[2],this_vxvv[3],
               this_dxdv[0],this_dxdv[1],this_dxdv[2],this_dxdv[3]]
        #integrate
        tmp_out= integrate.odeint(_EOM_dxdv,init,t,args=(pot,),
                                  rtol=10.**-8.)#,mxstep=100000000)
        msg= 0
    else:
        raise NotImplementedError("requested integration method does not exist")
    #go back to the cylindrical frame
    R= nu.sqrt(tmp_out[:,0]**2.+tmp_out[:,1]**2.)
    phi= nu.arccos(tmp_out[:,0]/R)
    phi[(tmp_out[:,1] < 0.)]= 2.*nu.pi-phi[(tmp_out[:,1] < 0.)]
    vR= tmp_out[:,2]*nu.cos(phi)+tmp_out[:,3]*nu.sin(phi)
    vT= tmp_out[:,3]*nu.cos(phi)-tmp_out[:,2]*nu.sin(phi)
    cp= nu.cos(phi)
    sp= nu.sin(phi)
    dR= cp*tmp_out[:,4]+sp*tmp_out[:,5]
    dphi= (cp*tmp_out[:,5]-sp*tmp_out[:,4])/R
    dvR= cp*tmp_out[:,6]+sp*tmp_out[:,7]+vT*dphi
    dvT= cp*tmp_out[:,7]-sp*tmp_out[:,6]-vR*dphi
    out= nu.zeros((len(t),8))
    out[:,0]= R
    out[:,1]= vR
    out[:,2]= vT
    out[:,3]= phi
    if rectOut:
        out[:,4:]= tmp_out[:,4:]
    else:
        out[:,4]= dR
        out[:,7]= dphi
        out[:,5]= dvR
        out[:,6]= dvT
    _parse_warnmessage(msg)
    return (out,msg)
示例#17
0
 def _actionsFreqsAngles(self, *args, **kwargs):
     """
     NAME:
        actionsFreqsAngles (_actionsFreqsAngles)
     PURPOSE:
        evaluate the actions, frequencies, and angles (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez)
     INPUT:
        Either:
           a) R,vR,vT,z,vz[,phi]:
              1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
              2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
           b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument 
        delta= (object-wide default) can be used to override the object-wide focal length; can also be an array with length N to allow different delta for different phase-space points
        u0= (None) if object-wide option useu0 is set, u0 to use (if useu0 and useu0 is None, a good value will be computed)
        c= (object-wide default, bool) True/False to override the object-wide setting for whether or not to use the C implementation
        order= (10) number of points to use in the Gauss-Legendre numerical integration of the relevant action, frequency, and angle integrals
        When not using C:
           fixed_quad= (False) if True, use Gaussian quadrature (scipy.integrate.fixed_quad instead of scipy.integrate.quad)
           scipy.integrate.fixed_quad or .quad keywords
     OUTPUT:
         (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez)
     HISTORY:
        2013-08-28 - Written - Bovy (IAS)
     """
     delta = kwargs.pop('delta', self._delta)
     order = kwargs.get('order', self._order)
     if ((self._c and not ('c' in kwargs and not kwargs['c']))\
             or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5:  #R,vR.vT, z, vz pragma: no cover
             raise IOError("Must specify phi")
         elif len(args) == 6:  #R,vR.vT, z, vz, phi
             R, vR, vT, z, vz, phi = args
         else:
             self._parse_eval_args(*args)
             R = self._eval_R
             vR = self._eval_vR
             vT = self._eval_vT
             z = self._eval_z
             vz = self._eval_vz
             phi = self._eval_phi
         if isinstance(R, float):
             R = nu.array([R])
             vR = nu.array([vR])
             vT = nu.array([vT])
             z = nu.array([z])
             vz = nu.array([vz])
             phi = nu.array([phi])
         Lz = R * vT
         if self._useu0:
             #First calculate u0
             if 'u0' in kwargs:
                 u0 = nu.asarray(kwargs['u0'])
             else:
                 E = nu.array([
                     _evaluatePotentials(self._pot, R[ii], z[ii]) +
                     vR[ii]**2. / 2. + vz[ii]**2. / 2. + vT[ii]**2. / 2.
                     for ii in range(len(R))
                 ])
                 u0= actionAngleStaeckel_c.actionAngleStaeckel_calcu0(\
                     E,Lz,self._pot,delta)[0]
             kwargs.pop('u0', None)
         else:
             u0 = None
         jr, jz, Omegar, Omegaphi, Omegaz, angler, anglephi,anglez, err= actionAngleStaeckel_c.actionAngleFreqAngleStaeckel_c(\
             self._pot,delta,R,vR,vT,z,vz,phi,u0=u0,order=order)
         # Adjustements for close-to-circular orbits
         indx = nu.isnan(Omegar) * (jr < 10.**-3.) + nu.isnan(Omegaz) * (
             jz < 10.**-3.
         )  #Close-to-circular and close-to-the-plane orbits
         if nu.sum(indx) > 0:
             Omegar[indx] = [
                 epifreq(self._pot, r, use_physical=False) for r in R[indx]
             ]
             Omegaphi[indx] = [
                 omegac(self._pot, r, use_physical=False) for r in R[indx]
             ]
             Omegaz[indx] = [
                 verticalfreq(self._pot, r, use_physical=False)
                 for r in R[indx]
             ]
         if err == 0:
             return (jr, Lz, jz, Omegar, Omegaphi, Omegaz, angler, anglephi,
                     anglez)
         else:
             raise RuntimeError(
                 "C-code for calculation actions failed; try with c=False"
             )  #pragma: no cover
     else:  #pragma: no cover
         if 'c' in kwargs and kwargs['c'] and not self._c:  #pragma: no cover
             warnings.warn(
                 "C module not used because potential does not have a C implementation",
                 galpyWarning)
         raise NotImplementedError(
             "actionsFreqs with c=False not implemented")
示例#18
0
 def __call__(self, *args, **kwargs):
     """
     NAME:
        __call__
     PURPOSE:
        evaluate the actions (jr,lz,jz)
     INPUT:
        Either:
           a) R,vR,vT,z,vz
           b) Orbit instance: initial condition used if that's it, orbit(t)
              if there is a time given as well
         c= True/False; overrides the object's c= keyword to use C or not
        scipy.integrate.quadrature keywords
     OUTPUT:
        (jr,lz,jz)
     HISTORY:
        2012-11-27 - Written - Bovy (IAS)
     """
     if ((self._c and not ('c' in kwargs and not kwargs['c']))\
             or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5:  #R,vR.vT, z, vz
             R, vR, vT, z, vz = args
         elif len(args) == 6:  #R,vR.vT, z, vz, phi
             R, vR, vT, z, vz, phi = args
         else:
             meta = actionAngle(*args)
             R = meta._R
             vR = meta._vR
             vT = meta._vT
             z = meta._z
             vz = meta._vz
         if isinstance(R, float):
             R = nu.array([R])
             vR = nu.array([vR])
             vT = nu.array([vT])
             z = nu.array([z])
             vz = nu.array([vz])
         Lz = R * vT
         if self._useu0:
             #First calculate u0
             if 'u0' in kwargs:
                 u0 = nu.asarray(kwargs['u0'])
             else:
                 E = nu.array([
                     evaluatePotentials(R[ii], z[ii], self._pot) +
                     vR[ii]**2. / 2. + vz[ii]**2. / 2. + vT[ii]**2. / 2.
                     for ii in range(len(R))
                 ])
                 u0 = actionAngleStaeckel_c.actionAngleStaeckel_calcu0(
                     E, Lz, self._pot, self._delta)[0]
             kwargs.pop('u0', None)
         else:
             u0 = None
         jr, jz, err= actionAngleStaeckel_c.actionAngleStaeckel_c(\
             self._pot,self._delta,R,vR,vT,z,vz,u0=u0)
         if err == 0:
             return (jr, Lz, jz)
         else:  #pragma: no cover
             raise RuntimeError(
                 "C-code for calculation actions failed; try with c=False")
     else:
         if 'c' in kwargs and kwargs['c'] and not self._c:  #pragma: no cover
             warnings.warn(
                 "C module not used because potential does not have a C implementation",
                 galpyWarning)
         kwargs.pop('c', None)
         if (len(args) == 5 or len(args) == 6) \
                 and isinstance(args[0],nu.ndarray):
             ojr = nu.zeros((len(args[0])))
             olz = nu.zeros((len(args[0])))
             ojz = nu.zeros((len(args[0])))
             for ii in range(len(args[0])):
                 if len(args) == 5:
                     targs = (args[0][ii], args[1][ii], args[2][ii],
                              args[3][ii], args[4][ii])
                 elif len(args) == 6:
                     targs = (args[0][ii], args[1][ii], args[2][ii],
                              args[3][ii], args[4][ii], args[5][ii])
                 tjr, tlz, tjz = self(*targs, **copy.copy(kwargs))
                 ojr[ii] = tjr
                 ojz[ii] = tjz
                 olz[ii] = tlz
             return (ojr, olz, ojz)
         else:
             #Set up the actionAngleStaeckelSingle object
             aASingle = actionAngleStaeckelSingle(*args,
                                                  pot=self._pot,
                                                  delta=self._delta)
             return (aASingle.JR(**copy.copy(kwargs)),
                     aASingle._R * aASingle._vT,
                     aASingle.Jz(**copy.copy(kwargs)))
示例#19
0
def _integrateFullOrbit(vxvv, pot, t, method, dt):
    """
    NAME:
       _integrateFullOrbit
    PURPOSE:
       integrate an orbit in a Phi(R,z,phi) potential
    INPUT:
       vxvv - array with the initial conditions stacked like
              [R,vR,vT,z,vz,phi]; vR outward!
       pot - Potential instance
       t - list of times at which to output (0 has to be in this!)
       method - 'odeint' or 'leapfrog'
       dt - if set, force the integrator to use this basic stepsize; must be an integer divisor of output stepsize
    OUTPUT:
       [:,5] array of [R,vR,vT,z,vz,phi] at each t
    HISTORY:
       2010-08-01 - Written - Bovy (NYU)
    """
    #First check that the potential has C
    if '_c' in method:
        if not ext_loaded or not _check_c(pot):
            if ('leapfrog' in method or 'symplec' in method):
                method = 'leapfrog'
            else:
                method = 'odeint'
            if not ext_loaded:  # pragma: no cover
                warnings.warn(
                    "Cannot use C integration because C extension not loaded (using %s instead)"
                    % (method), galpyWarning)
            else:
                warnings.warn(
                    "Cannot use C integration because some of the potentials are not implemented in C (using %s instead)"
                    % (method), galpyWarning)
    if method.lower() == 'leapfrog':
        #go to the rectangular frame
        this_vxvv = nu.array([
            vxvv[0] * nu.cos(vxvv[5]), vxvv[0] * nu.sin(vxvv[5]), vxvv[3],
            vxvv[1] * nu.cos(vxvv[5]) - vxvv[2] * nu.sin(vxvv[5]),
            vxvv[2] * nu.cos(vxvv[5]) + vxvv[1] * nu.sin(vxvv[5]), vxvv[4]
        ])
        #integrate
        out = symplecticode.leapfrog(_rectForce,
                                     this_vxvv,
                                     t,
                                     args=(pot, ),
                                     rtol=10.**-8)
        #go back to the cylindrical frame
        R = nu.sqrt(out[:, 0]**2. + out[:, 1]**2.)
        phi = nu.arccos(out[:, 0] / R)
        phi[(out[:, 1] < 0.)] = 2. * nu.pi - phi[(out[:, 1] < 0.)]
        vR = out[:, 3] * nu.cos(phi) + out[:, 4] * nu.sin(phi)
        vT = out[:, 4] * nu.cos(phi) - out[:, 3] * nu.sin(phi)
        out[:, 3] = out[:, 2]
        out[:, 4] = out[:, 5]
        out[:, 0] = R
        out[:, 1] = vR
        out[:, 2] = vT
        out[:, 5] = phi
    elif ext_loaded and \
            (method.lower() == 'leapfrog_c' or method.lower() == 'rk4_c' \
            or method.lower() == 'rk6_c' or method.lower() == 'symplec4_c' \
            or method.lower() == 'symplec6_c' or method.lower() == 'dopr54_c'):
        warnings.warn("Using C implementation to integrate orbits",
                      galpyWarningVerbose)
        #go to the rectangular frame
        this_vxvv = nu.array([
            vxvv[0] * nu.cos(vxvv[5]), vxvv[0] * nu.sin(vxvv[5]), vxvv[3],
            vxvv[1] * nu.cos(vxvv[5]) - vxvv[2] * nu.sin(vxvv[5]),
            vxvv[2] * nu.cos(vxvv[5]) + vxvv[1] * nu.sin(vxvv[5]), vxvv[4]
        ])
        #integrate
        tmp_out, msg = integrateFullOrbit_c(pot, this_vxvv, t, method, dt=dt)
        #go back to the cylindrical frame
        R = nu.sqrt(tmp_out[:, 0]**2. + tmp_out[:, 1]**2.)
        phi = nu.arccos(tmp_out[:, 0] / R)
        phi[(tmp_out[:, 1] < 0.)] = 2. * nu.pi - phi[(tmp_out[:, 1] < 0.)]
        vR = tmp_out[:, 3] * nu.cos(phi) + tmp_out[:, 4] * nu.sin(phi)
        vT = tmp_out[:, 4] * nu.cos(phi) - tmp_out[:, 3] * nu.sin(phi)
        out = nu.zeros((len(t), 6))
        out[:, 0] = R
        out[:, 1] = vR
        out[:, 2] = vT
        out[:, 5] = phi
        out[:, 3] = tmp_out[:, 2]
        out[:, 4] = tmp_out[:, 5]
    elif method.lower() == 'odeint' or not ext_loaded:
        vphi = vxvv[2] / vxvv[0]
        init = [vxvv[0], vxvv[1], vxvv[5], vphi, vxvv[3], vxvv[4]]
        intOut = integrate.odeint(_FullEOM,
                                  init,
                                  t,
                                  args=(pot, ),
                                  rtol=10.**-8.)  #,mxstep=100000000)
        out = nu.zeros((len(t), 6))
        out[:, 0] = intOut[:, 0]
        out[:, 1] = intOut[:, 1]
        out[:, 2] = out[:, 0] * intOut[:, 3]
        out[:, 3] = intOut[:, 4]
        out[:, 4] = intOut[:, 5]
        out[:, 5] = intOut[:, 2]
    #post-process to remove negative radii
    neg_radii = (out[:, 0] < 0.)
    out[neg_radii, 0] = -out[neg_radii, 0]
    out[neg_radii, 5] += m.pi
    return out
示例#20
0
 def _evaluate(self, *args, **kwargs):
     """
     NAME:
        _evaluate
     PURPOSE:
        evaluate the actions (jr,lz,jz)
     INPUT:
        Either:
           a) R,vR,vT,z,vz
           b) Orbit instance: initial condition used if that's it, orbit(t)
              if there is a time given as well
        scipy.integrate.quadrature keywords
        _justjr, _justjz= if True, only calculate the radial or vertical action (internal use)
     OUTPUT:
        (jr,lz,jz), where jr=[jr,jrerr], and jz=[jz,jzerr]
     HISTORY:
        2012-07-26 - Written - Bovy (IAS@MPIA)
     """
     if ((self._c and not ('c' in kwargs and not kwargs['c']))\
             or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5:  #R,vR.vT, z, vz
             R, vR, vT, z, vz = args
         elif len(args) == 6:  #R,vR.vT, z, vz, phi
             R, vR, vT, z, vz, phi = args
         else:
             self._parse_eval_args(*args)
             R = self._eval_R
             vR = self._eval_vR
             vT = self._eval_vT
             z = self._eval_z
             vz = self._eval_vz
         if isinstance(R, float):
             R = nu.array([R])
             vR = nu.array([vR])
             vT = nu.array([vT])
             z = nu.array([z])
             vz = nu.array([vz])
         Lz = R * vT
         jr, jz, err= actionAngleAdiabatic_c.actionAngleAdiabatic_c(\
             self._pot,self._gamma,R,vR,vT,z,vz)
         if err == 0:
             return (jr, Lz, jz)
         else:  #pragma: no cover
             raise RuntimeError(
                 "C-code for calculation actions failed; try with c=False")
     else:
         if 'c' in kwargs and kwargs['c'] and not self._c:
             warnings.warn(
                 "C module not used because potential does not have a C implementation",
                 galpyWarning)  #pragma: no cover
         kwargs.pop('c', None)
         if (len(args) == 5 or len(args) == 6) \
                 and isinstance(args[0],nu.ndarray):
             ojr = nu.zeros((len(args[0])))
             olz = nu.zeros((len(args[0])))
             ojz = nu.zeros((len(args[0])))
             for ii in range(len(args[0])):
                 if len(args) == 5:
                     targs = (args[0][ii], args[1][ii], args[2][ii],
                              args[3][ii], args[4][ii])
                 elif len(args) == 6:
                     targs = (args[0][ii], args[1][ii], args[2][ii],
                              args[3][ii], args[4][ii], args[5][ii])
                 tjr, tlz, tjz = self(*targs, **copy.copy(kwargs))
                 ojr[ii] = tjr
                 ojz[ii] = tjz
                 olz[ii] = tlz
             return (ojr, olz, ojz)
         else:
             #Set up the actionAngleAxi object
             self._parse_eval_args(*args)
             if isinstance(self._pot, list):
                 thispot = [p.toPlanar() for p in self._pot]
             else:
                 thispot = self._pot.toPlanar()
             if isinstance(self._pot, list):
                 thisverticalpot = [
                     p.toVertical(self._eval_R) for p in self._pot
                 ]
             else:
                 thisverticalpot = self._pot.toVertical(self._eval_R)
             aAAxi = actionAngleAxi(*args,
                                    pot=thispot,
                                    verticalPot=thisverticalpot,
                                    gamma=self._gamma)
             if kwargs.get('_justjr', False):
                 kwargs.pop('_justjr')
                 return (aAAxi.JR(**kwargs), nu.nan, nu.nan)
             elif kwargs.get('_justjz', False):
                 kwargs.pop('_justjz')
                 return (nu.nan, nu.nan, aAAxi.Jz(**kwargs))
             else:
                 return (aAAxi.JR(**kwargs), aAAxi._R * aAAxi._vT,
                         aAAxi.Jz(**kwargs))
示例#21
0
 def _EccZmaxRperiRap(self, *args, **kwargs):
     """
     NAME:
        EccZmaxRperiRap (_EccZmaxRperiRap)
     PURPOSE:
        evaluate the eccentricity, maximum height above the plane, peri- and apocenter in the adiabatic approximation
     INPUT:
        Either:
           a) R,vR,vT,z,vz[,phi]:
              1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
              2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
           b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument 
        c= (object-wide default, bool) True/False to override the object-wide setting for whether or not to use the C implementation
     OUTPUT:
        (e,zmax,rperi,rap)
     HISTORY:
        2017-12-21 - Written - Bovy (UofT)
     """
     if ((self._c and not ('c' in kwargs and not kwargs['c']))\
             or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5:  #R,vR.vT, z, vz
             R, vR, vT, z, vz = args
         elif len(args) == 6:  #R,vR.vT, z, vz, phi
             R, vR, vT, z, vz, phi = args
         else:
             self._parse_eval_args(*args)
             R = self._eval_R
             vR = self._eval_vR
             vT = self._eval_vT
             z = self._eval_z
             vz = self._eval_vz
         if isinstance(R, float):
             R = nu.array([R])
             vR = nu.array([vR])
             vT = nu.array([vT])
             z = nu.array([z])
             vz = nu.array([vz])
         rperi,Rap,zmax, err= actionAngleAdiabatic_c.actionAngleRperiRapZmaxAdiabatic_c(\
             self._pot,self._gamma,R,vR,vT,z,vz)
         if err == 0:
             rap = nu.sqrt(Rap**2. + zmax**2.)
             ecc = (rap - rperi) / (rap + rperi)
             return (ecc, zmax, rperi, rap)
         else:  #pragma: no cover
             raise RuntimeError(
                 "C-code for calculation actions failed; try with c=False")
     else:
         if 'c' in kwargs and kwargs['c'] and not self._c:
             warnings.warn(
                 "C module not used because potential does not have a C implementation",
                 galpyWarning)  #pragma: no cover
         kwargs.pop('c', None)
         if (len(args) == 5 or len(args) == 6) \
                 and isinstance(args[0],nu.ndarray):
             oecc = nu.zeros((len(args[0])))
             orperi = nu.zeros((len(args[0])))
             orap = nu.zeros((len(args[0])))
             ozmax = nu.zeros((len(args[0])))
             for ii in range(len(args[0])):
                 if len(args) == 5:
                     targs = (args[0][ii], args[1][ii], args[2][ii],
                              args[3][ii], args[4][ii])
                 elif len(args) == 6:
                     targs = (args[0][ii], args[1][ii], args[2][ii],
                              args[3][ii], args[4][ii], args[5][ii])
                 tecc, tzmax, trperi,trap= self._EccZmaxRperiRap(\
                     *targs,**copy.copy(kwargs))
                 oecc[ii] = tecc
                 ozmax[ii] = tzmax
                 orperi[ii] = trperi
                 orap[ii] = trap
             return (oecc, ozmax, orperi, orap)
         else:
             #Set up the actionAngleAxi object
             self._parse_eval_args(*args)
             if isinstance(self._pot, list):
                 thispot = [p.toPlanar() for p in self._pot]
             else:
                 thispot = self._pot.toPlanar()
             if isinstance(self._pot, list):
                 thisverticalpot = [
                     p.toVertical(self._eval_R) for p in self._pot
                 ]
             else:
                 thisverticalpot = self._pot.toVertical(self._eval_R)
             aAAxi = actionAngleAxi(*args,
                                    pot=thispot,
                                    verticalPot=thisverticalpot,
                                    gamma=self._gamma)
             rperi, Rap = aAAxi.calcRapRperi(**kwargs)
             zmax = aAAxi.calczmax(**kwargs)
             rap = nu.sqrt(Rap**2. + zmax**2.)
             return ((rap - rperi) / (rap + rperi), zmax, rperi, rap)
示例#22
0
 def _EccZmaxRperiRap(self,*args,**kwargs):
     """
     NAME:
        EccZmaxRperiRap (_EccZmaxRperiRap)
     PURPOSE:
        evaluate the eccentricity, maximum height above the plane, peri- and apocenter in the adiabatic approximation
     INPUT:
        Either:
           a) R,vR,vT,z,vz[,phi]:
              1) floats: phase-space value for single object (phi is optional) (each can be a Quantity)
              2) numpy.ndarray: [N] phase-space values for N objects (each can be a Quantity)
           b) Orbit instance: initial condition used if that's it, orbit(t) if there is a time given as well as the second argument 
        c= (object-wide default, bool) True/False to override the object-wide setting for whether or not to use the C implementation
     OUTPUT:
        (e,zmax,rperi,rap)
     HISTORY:
        2017-12-21 - Written - Bovy (UofT)
     """
     if ((self._c and not ('c' in kwargs and not kwargs['c']))\
             or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5: #R,vR.vT, z, vz
             R,vR,vT, z, vz= args
         elif len(args) == 6: #R,vR.vT, z, vz, phi
             R,vR,vT, z, vz, phi= args
         else:
             self._parse_eval_args(*args)
             R= self._eval_R
             vR= self._eval_vR
             vT= self._eval_vT
             z= self._eval_z
             vz= self._eval_vz
         if isinstance(R,float):
             R= nu.array([R])
             vR= nu.array([vR])
             vT= nu.array([vT])
             z= nu.array([z])
             vz= nu.array([vz])
         rperi,Rap,zmax, err= actionAngleAdiabatic_c.actionAngleRperiRapZmaxAdiabatic_c(\
             self._pot,self._gamma,R,vR,vT,z,vz)
         if err == 0:
             rap= nu.sqrt(Rap**2.+zmax**2.)
             ecc= (rap-rperi)/(rap+rperi)
             return (ecc,zmax,rperi,rap)
         else: #pragma: no cover
             raise RuntimeError("C-code for calculation actions failed; try with c=False")
     else:
         if 'c' in kwargs and kwargs['c'] and not self._c:
             warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) #pragma: no cover
         kwargs.pop('c',None)
         if (len(args) == 5 or len(args) == 6) \
                 and isinstance(args[0],nu.ndarray):
             oecc= nu.zeros((len(args[0])))
             orperi= nu.zeros((len(args[0])))
             orap= nu.zeros((len(args[0])))
             ozmax= nu.zeros((len(args[0])))
             for ii in range(len(args[0])):
                 if len(args) == 5:
                     targs= (args[0][ii],args[1][ii],args[2][ii],
                             args[3][ii],args[4][ii])
                 elif len(args) == 6:
                     targs= (args[0][ii],args[1][ii],args[2][ii],
                             args[3][ii],args[4][ii],args[5][ii])
                 tecc, tzmax, trperi,trap= self._EccZmaxRperiRap(\
                     *targs,**copy.copy(kwargs))
                 oecc[ii]= tecc
                 ozmax[ii]= tzmax
                 orperi[ii]= trperi
                 orap[ii]= trap
             return (oecc,ozmax,orperi,orap)
         else:
             #Set up the actionAngleAxi object
             self._parse_eval_args(*args)
             if isinstance(self._pot,list):
                 thispot= [p.toPlanar() for p in self._pot]
             else:
                 thispot= self._pot.toPlanar()
             if isinstance(self._pot,list):
                 thisverticalpot= [p.toVertical(self._eval_R) for p in self._pot]
             else:
                 thisverticalpot= self._pot.toVertical(self._eval_R)
             aAAxi= actionAngleAxi(*args,pot=thispot,
                                    verticalPot=thisverticalpot,
                                    gamma=self._gamma)
             rperi,Rap= aAAxi.calcRapRperi(**kwargs)
             zmax= aAAxi.calczmax(**kwargs)
             rap= nu.sqrt(Rap**2.+zmax**2.)
             return ((rap-rperi)/(rap+rperi),zmax,rperi,rap)
 def _evaluate(self,*args,**kwargs):
     """
     NAME:
        _evaluate
     PURPOSE:
        evaluate the actions (jr,lz,jz)
     INPUT:
        Either:
           a) R,vR,vT,z,vz
           b) Orbit instance: initial condition used if that's it, orbit(t)
              if there is a time given as well
        scipy.integrate.quadrature keywords
        _justjr, _justjz= if True, only calculate the radial or vertical action (internal use)
     OUTPUT:
        (jr,lz,jz), where jr=[jr,jrerr], and jz=[jz,jzerr]
     HISTORY:
        2012-07-26 - Written - Bovy (IAS@MPIA)
     """
     if ((self._c and not ('c' in kwargs and not kwargs['c']))\
             or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5: #R,vR.vT, z, vz
             R,vR,vT, z, vz= args
         elif len(args) == 6: #R,vR.vT, z, vz, phi
             R,vR,vT, z, vz, phi= args
         else:
             self._parse_eval_args(*args)
             R= self._eval_R
             vR= self._eval_vR
             vT= self._eval_vT
             z= self._eval_z
             vz= self._eval_vz
         if isinstance(R,float):
             R= nu.array([R])
             vR= nu.array([vR])
             vT= nu.array([vT])
             z= nu.array([z])
             vz= nu.array([vz])
         Lz= R*vT
         jr, jz, err= actionAngleAdiabatic_c.actionAngleAdiabatic_c(\
             self._pot,self._gamma,R,vR,vT,z,vz)
         if err == 0:
             return (jr,Lz,jz)
         else: #pragma: no cover
             raise RuntimeError("C-code for calculation actions failed; try with c=False")
     else:
         if 'c' in kwargs and kwargs['c'] and not self._c:
             warnings.warn("C module not used because potential does not have a C implementation",galpyWarning) #pragma: no cover
         kwargs.pop('c',None)
         if (len(args) == 5 or len(args) == 6) \
                 and isinstance(args[0],nu.ndarray):
             ojr= nu.zeros((len(args[0])))
             olz= nu.zeros((len(args[0])))
             ojz= nu.zeros((len(args[0])))
             for ii in range(len(args[0])):
                 if len(args) == 5:
                     targs= (args[0][ii],args[1][ii],args[2][ii],
                             args[3][ii],args[4][ii])
                 elif len(args) == 6:
                     targs= (args[0][ii],args[1][ii],args[2][ii],
                             args[3][ii],args[4][ii],args[5][ii])
                 tjr,tlz,tjz= self(*targs,**copy.copy(kwargs))
                 ojr[ii]= tjr
                 ojz[ii]= tjz
                 olz[ii]= tlz
             return (ojr,olz,ojz)
         else:
             #Set up the actionAngleAxi object
             self._parse_eval_args(*args)
             if isinstance(self._pot,list):
                 thispot= [p.toPlanar() for p in self._pot]
             else:
                 thispot= self._pot.toPlanar()
             if isinstance(self._pot,list):
                 thisverticalpot= [p.toVertical(self._eval_R) for p in self._pot]
             else:
                 thisverticalpot= self._pot.toVertical(self._eval_R)
             aAAxi= actionAngleAxi(*args,pot=thispot,
                                    verticalPot=thisverticalpot,
                                    gamma=self._gamma)
             if kwargs.get('_justjr',False):
                 kwargs.pop('_justjr')
                 return (aAAxi.JR(**kwargs),nu.nan,nu.nan)
             elif kwargs.get('_justjz',False):
                 kwargs.pop('_justjz')
                 return (nu.nan,nu.nan,aAAxi.Jz(**kwargs))
             else:
                 return (aAAxi.JR(**kwargs),aAAxi._R*aAAxi._vT,aAAxi.Jz(**kwargs))
示例#24
0
def _integrateOrbit(vxvv, pot, t, method, dt):
    """
    NAME:
       _integrateOrbit
    PURPOSE:
       integrate an orbit in a Phi(R) potential in the (R,phi)-plane
    INPUT:
       vxvv - array with the initial conditions stacked like
              [R,vR,vT,phi]; vR outward!
       pot - Potential instance
       t - list of times at which to output (0 has to be in this!)
       method - 'odeint' or 'leapfrog'
       dt- if set, force the integrator to use this basic stepsize; must be an integer divisor of output stepsize
    OUTPUT:
       [:,4] array of [R,vR,vT,phi] at each t
    HISTORY:
       2010-07-20 - Written - Bovy (NYU)
    """
    #First check that the potential has C
    if '_c' in method:
        if not _check_c(pot):
            if ('leapfrog' in method or 'symplec' in method):
                method = 'leapfrog'
            else:
                method = 'odeint'
            warnings.warn(
                "Cannot use C integration because some of the potentials are not implemented in C (using %s instead)"
                % (method), galpyWarning)
    if method.lower() == 'leapfrog':
        #go to the rectangular frame
        this_vxvv = nu.array([
            vxvv[0] * nu.cos(vxvv[3]), vxvv[0] * nu.sin(vxvv[3]),
            vxvv[1] * nu.cos(vxvv[3]) - vxvv[2] * nu.sin(vxvv[3]),
            vxvv[2] * nu.cos(vxvv[3]) + vxvv[1] * nu.sin(vxvv[3])
        ])
        #integrate
        tmp_out = symplecticode.leapfrog(_rectForce,
                                         this_vxvv,
                                         t,
                                         args=(pot, ),
                                         rtol=10.**-8)
        #go back to the cylindrical frame
        R = nu.sqrt(tmp_out[:, 0]**2. + tmp_out[:, 1]**2.)
        phi = nu.arccos(tmp_out[:, 0] / R)
        phi[(tmp_out[:, 1] < 0.)] = 2. * nu.pi - phi[(tmp_out[:, 1] < 0.)]
        vR = tmp_out[:, 2] * nu.cos(phi) + tmp_out[:, 3] * nu.sin(phi)
        vT = tmp_out[:, 3] * nu.cos(phi) - tmp_out[:, 2] * nu.sin(phi)
        out = nu.zeros((len(t), 4))
        out[:, 0] = R
        out[:, 1] = vR
        out[:, 2] = vT
        out[:, 3] = phi
        msg = 0
    elif method.lower() == 'leapfrog_c' or method.lower() == 'rk4_c' \
            or method.lower() == 'rk6_c' or method.lower() == 'symplec4_c' \
            or method.lower() == 'symplec6_c' or method.lower() == 'dopr54_c':
        warnings.warn("Using C implementation to integrate orbits",
                      galpyWarningVerbose)
        #go to the rectangular frame
        this_vxvv = nu.array([
            vxvv[0] * nu.cos(vxvv[3]), vxvv[0] * nu.sin(vxvv[3]),
            vxvv[1] * nu.cos(vxvv[3]) - vxvv[2] * nu.sin(vxvv[3]),
            vxvv[2] * nu.cos(vxvv[3]) + vxvv[1] * nu.sin(vxvv[3])
        ])
        #integrate
        tmp_out, msg = integratePlanarOrbit_c(pot, this_vxvv, t, method, dt=dt)
        #go back to the cylindrical frame
        R = nu.sqrt(tmp_out[:, 0]**2. + tmp_out[:, 1]**2.)
        phi = nu.arccos(tmp_out[:, 0] / R)
        phi[(tmp_out[:, 1] < 0.)] = 2. * nu.pi - phi[(tmp_out[:, 1] < 0.)]
        vR = tmp_out[:, 2] * nu.cos(phi) + tmp_out[:, 3] * nu.sin(phi)
        vT = tmp_out[:, 3] * nu.cos(phi) - tmp_out[:, 2] * nu.sin(phi)
        out = nu.zeros((len(t), 4))
        out[:, 0] = R
        out[:, 1] = vR
        out[:, 2] = vT
        out[:, 3] = phi
    elif method.lower() == 'odeint':
        vphi = vxvv[2] / vxvv[0]
        init = [vxvv[0], vxvv[1], vxvv[3], vphi]
        intOut = integrate.odeint(_EOM, init, t, args=(pot, ),
                                  rtol=10.**-8.)  #,mxstep=100000000)
        out = nu.zeros((len(t), 4))
        out[:, 0] = intOut[:, 0]
        out[:, 1] = intOut[:, 1]
        out[:, 3] = intOut[:, 2]
        out[:, 2] = out[:, 0] * intOut[:, 3]
        msg = 0
    else:
        raise NotImplementedError(
            "requested integration method does not exist")
    #post-process to remove negative radii
    neg_radii = (out[:, 0] < 0.)
    out[neg_radii, 0] = -out[neg_radii, 0]
    out[neg_radii, 3] += m.pi
    _parse_warnmessage(msg)
    return (out, msg)
示例#25
0
 def _actionsFreqsAngles(self,*args,**kwargs):
     """
     NAME:
        _actionsFreqsAngles
     PURPOSE:
        evaluate the actions, frequencies, and angles 
        (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez)
     INPUT:
        Either:
           a) R,vR,vT,z,vz,phi (MUST HAVE PHI)
           b) Orbit instance: initial condition used if that's it, orbit(t)
              if there is a time given as well
        scipy.integrate.quadrature keywords
     OUTPUT:
         (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez)
     HISTORY:
        2013-08-28 - Written - Bovy (IAS)
     """
     if ((self._c and not ('c' in kwargs and not kwargs['c']))\
             or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5: #R,vR.vT, z, vz pragma: no cover
             raise IOError("Must specify phi")
         elif len(args) == 6: #R,vR.vT, z, vz, phi
             R,vR,vT, z, vz, phi= args
         else:
             self._parse_eval_args(*args)
             R= self._eval_R
             vR= self._eval_vR
             vT= self._eval_vT
             z= self._eval_z
             vz= self._eval_vz
             phi= self._eval_phi
         if isinstance(R,float):
             R= nu.array([R])
             vR= nu.array([vR])
             vT= nu.array([vT])
             z= nu.array([z])
             vz= nu.array([vz])
             phi= nu.array([phi])
         Lz= R*vT
         if self._useu0:
             #First calculate u0
             if 'u0' in kwargs:
                 u0= nu.asarray(kwargs['u0'])
             else:
                 E= nu.array([_evaluatePotentials(self._pot,R[ii],z[ii])
                              +vR[ii]**2./2.+vz[ii]**2./2.+vT[ii]**2./2. for ii in range(len(R))])
                 u0= actionAngleStaeckel_c.actionAngleStaeckel_calcu0(E,Lz,
                                                                      self._pot,
                                                                      self._delta)[0]
             kwargs.pop('u0',None)
         else:
             u0= None
         jr, jz, Omegar, Omegaphi, Omegaz, angler, anglephi,anglez, err= actionAngleStaeckel_c.actionAngleFreqAngleStaeckel_c(\
             self._pot,self._delta,R,vR,vT,z,vz,phi,u0=u0)
         # Adjustements for close-to-circular orbits
         indx= nu.isnan(Omegar)*(jr < 10.**-3.)+nu.isnan(Omegaz)*(jz < 10.**-3.) #Close-to-circular and close-to-the-plane orbits
         if nu.sum(indx) > 0:
             Omegar[indx]= [epifreq(self._pot,r,use_physical=False) for r in R[indx]]
             Omegaphi[indx]= [omegac(self._pot,r,use_physical=False) for r in R[indx]]
             Omegaz[indx]= [verticalfreq(self._pot,r,use_physical=False) for r in R[indx]]
         if err == 0:
             return (jr,Lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez)
         else:
             raise RuntimeError("C-code for calculation actions failed; try with c=False") #pragma: no cover
     else: #pragma: no cover
         if 'c' in kwargs and kwargs['c'] and not self._c: #pragma: no cover
             warnings.warn("C module not used because potential does not have a C implementation",galpyWarning)
         raise NotImplementedError("actionsFreqs with c=False not implemented")
示例#26
0
文件: planarOrbit.py 项目: smoh/galpy
def _integrateOrbit(vxvv,pot,t,method,dt):
    """
    NAME:
       _integrateOrbit
    PURPOSE:
       integrate an orbit in a Phi(R) potential in the (R,phi)-plane
    INPUT:
       vxvv - array with the initial conditions stacked like
              [R,vR,vT,phi]; vR outward!
       pot - Potential instance
       t - list of times at which to output (0 has to be in this!)
       method - 'odeint' or 'leapfrog'
       dt- if set, force the integrator to use this basic stepsize; must be an integer divisor of output stepsize
    OUTPUT:
       [:,4] array of [R,vR,vT,phi] at each t
    HISTORY:
       2010-07-20 - Written - Bovy (NYU)
    """
    #First check that the potential has C
    if '_c' in method:
        if not _check_c(pot):
            if ('leapfrog' in method or 'symplec' in method):
                method= 'leapfrog'
            else:
                method= 'odeint'
            warnings.warn("Cannot use C integration because some of the potentials are not implemented in C (using %s instead)" % (method), galpyWarning)
    if method.lower() == 'leapfrog':
        #go to the rectangular frame
        this_vxvv= nu.array([vxvv[0]*nu.cos(vxvv[3]),
                             vxvv[0]*nu.sin(vxvv[3]),
                             vxvv[1]*nu.cos(vxvv[3])-vxvv[2]*nu.sin(vxvv[3]),
                             vxvv[2]*nu.cos(vxvv[3])+vxvv[1]*nu.sin(vxvv[3])])
        #integrate
        tmp_out= symplecticode.leapfrog(_rectForce,this_vxvv,
                                        t,args=(pot,),rtol=10.**-8)
        #go back to the cylindrical frame
        R= nu.sqrt(tmp_out[:,0]**2.+tmp_out[:,1]**2.)
        phi= nu.arccos(tmp_out[:,0]/R)
        phi[(tmp_out[:,1] < 0.)]= 2.*nu.pi-phi[(tmp_out[:,1] < 0.)]
        vR= tmp_out[:,2]*nu.cos(phi)+tmp_out[:,3]*nu.sin(phi)
        vT= tmp_out[:,3]*nu.cos(phi)-tmp_out[:,2]*nu.sin(phi)
        out= nu.zeros((len(t),4))
        out[:,0]= R
        out[:,1]= vR
        out[:,2]= vT
        out[:,3]= phi
        msg= 0
    elif method.lower() == 'leapfrog_c' or method.lower() == 'rk4_c' \
            or method.lower() == 'rk6_c' or method.lower() == 'symplec4_c' \
            or method.lower() == 'symplec6_c' or method.lower() == 'dopr54_c':
        warnings.warn("Using C implementation to integrate orbits",galpyWarning)
        #go to the rectangular frame
        this_vxvv= nu.array([vxvv[0]*nu.cos(vxvv[3]),
                             vxvv[0]*nu.sin(vxvv[3]),
                             vxvv[1]*nu.cos(vxvv[3])-vxvv[2]*nu.sin(vxvv[3]),
                             vxvv[2]*nu.cos(vxvv[3])+vxvv[1]*nu.sin(vxvv[3])])
        #integrate
        tmp_out, msg= integratePlanarOrbit_c(pot,this_vxvv,
                                             t,method,dt=dt)
        #go back to the cylindrical frame
        R= nu.sqrt(tmp_out[:,0]**2.+tmp_out[:,1]**2.)
        phi= nu.arccos(tmp_out[:,0]/R)
        phi[(tmp_out[:,1] < 0.)]= 2.*nu.pi-phi[(tmp_out[:,1] < 0.)]
        vR= tmp_out[:,2]*nu.cos(phi)+tmp_out[:,3]*nu.sin(phi)
        vT= tmp_out[:,3]*nu.cos(phi)-tmp_out[:,2]*nu.sin(phi)
        out= nu.zeros((len(t),4))
        out[:,0]= R
        out[:,1]= vR
        out[:,2]= vT
        out[:,3]= phi
    elif method.lower() == 'odeint':
        vphi= vxvv[2]/vxvv[0]
        init= [vxvv[0],vxvv[1],vxvv[3],vphi]
        intOut= integrate.odeint(_EOM,init,t,args=(pot,),
                                 rtol=10.**-8.)#,mxstep=100000000)
        out= nu.zeros((len(t),4))
        out[:,0]= intOut[:,0]
        out[:,1]= intOut[:,1]
        out[:,3]= intOut[:,2]
        out[:,2]= out[:,0]*intOut[:,3]
        msg= 0
    else:
        raise NotImplementedError("requested integration method does not exist")
    #post-process to remove negative radii
    neg_radii= (out[:,0] < 0.)
    out[neg_radii,0]= -out[neg_radii,0]
    out[neg_radii,3]+= m.pi
    _parse_warnmessage(msg)
    return (out,msg)
示例#27
0
 def _evaluate(self,*args,**kwargs):
     """
     NAME:
        _evaluate
     PURPOSE:
        evaluate the actions (jr,lz,jz)
     INPUT:
        Either:
           a) R,vR,vT,z,vz
           b) Orbit instance: initial condition used if that's it, orbit(t)
              if there is a time given as well
         c= True/False; overrides the object's c= keyword to use C or not
        scipy.integrate.quadrature keywords
     OUTPUT:
        (jr,lz,jz)
     HISTORY:
        2012-11-27 - Written - Bovy (IAS)
     """
     if ((self._c and not ('c' in kwargs and not kwargs['c']))\
             or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5: #R,vR.vT, z, vz
             R,vR,vT, z, vz= args
         elif len(args) == 6: #R,vR.vT, z, vz, phi
             R,vR,vT, z, vz, phi= args
         else:
             self._parse_eval_args(*args)
             R= self._eval_R
             vR= self._eval_vR
             vT= self._eval_vT
             z= self._eval_z
             vz= self._eval_vz
         if isinstance(R,float):
             R= nu.array([R])
             vR= nu.array([vR])
             vT= nu.array([vT])
             z= nu.array([z])
             vz= nu.array([vz])
         Lz= R*vT
         if self._useu0:
             #First calculate u0
             if 'u0' in kwargs:
                 u0= nu.asarray(kwargs['u0'])
             else:
                 E= nu.array([_evaluatePotentials(self._pot,R[ii],z[ii])
                              +vR[ii]**2./2.+vz[ii]**2./2.+vT[ii]**2./2. for ii in range(len(R))])
                 u0= actionAngleStaeckel_c.actionAngleStaeckel_calcu0(E,Lz,
                                                                      self._pot,
                                                                      self._delta)[0]
             kwargs.pop('u0',None)
         else:
             u0= None
         jr, jz, err= actionAngleStaeckel_c.actionAngleStaeckel_c(\
             self._pot,self._delta,R,vR,vT,z,vz,u0=u0)
         if err == 0:
             return (jr,Lz,jz)
         else: #pragma: no cover
             raise RuntimeError("C-code for calculation actions failed; try with c=False")
     else:
         if 'c' in kwargs and kwargs['c'] and not self._c: #pragma: no cover
             warnings.warn("C module not used because potential does not have a C implementation",galpyWarning)
         kwargs.pop('c',None)
         if (len(args) == 5 or len(args) == 6) \
                 and isinstance(args[0],nu.ndarray):
             ojr= nu.zeros((len(args[0])))
             olz= nu.zeros((len(args[0])))
             ojz= nu.zeros((len(args[0])))
             for ii in range(len(args[0])):
                 if len(args) == 5:
                     targs= (args[0][ii],args[1][ii],args[2][ii],
                             args[3][ii],args[4][ii])
                 elif len(args) == 6:
                     targs= (args[0][ii],args[1][ii],args[2][ii],
                             args[3][ii],args[4][ii],args[5][ii])
                 tjr,tlz,tjz= self(*targs,**copy.copy(kwargs))
                 ojr[ii]= tjr
                 ojz[ii]= tjz
                 olz[ii]= tlz
             return (ojr,olz,ojz)
         else:
             #Set up the actionAngleStaeckelSingle object
             aASingle= actionAngleStaeckelSingle(*args,pot=self._pot,
                                                  delta=self._delta)
             return (aASingle.JR(**copy.copy(kwargs)),
                     aASingle._R*aASingle._vT,
                     aASingle.Jz(**copy.copy(kwargs)))
示例#28
0
 def actionsFreqsAngles(self, *args, **kwargs):
     """
     NAME:
        actionsFreqsAngles
     PURPOSE:
        evaluate the actions, frequencies, and angles 
        (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez)
     INPUT:
        Either:
           a) R,vR,vT,z,vz,phi (MUST HAVE PHI)
           b) Orbit instance: initial condition used if that's it, orbit(t)
              if there is a time given as well
        scipy.integrate.quadrature keywords
     OUTPUT:
         (jr,lz,jz,Omegar,Omegaphi,Omegaz,angler,anglephi,anglez)
     HISTORY:
        2013-08-28 - Written - Bovy (IAS)
     """
     if ((self._c and not ('c' in kwargs and not kwargs['c']))\
             or (ext_loaded and (('c' in kwargs and kwargs['c'])))) \
             and _check_c(self._pot):
         if len(args) == 5:  #R,vR.vT, z, vz pragma: no cover
             raise IOError("Must specify phi")
         elif len(args) == 6:  #R,vR.vT, z, vz, phi
             R, vR, vT, z, vz, phi = args
         else:
             meta = actionAngle(*args)
             R = meta._R
             vR = meta._vR
             vT = meta._vT
             z = meta._z
             vz = meta._vz
             phi = meta._phi
         if isinstance(R, float):
             R = nu.array([R])
             vR = nu.array([vR])
             vT = nu.array([vT])
             z = nu.array([z])
             vz = nu.array([vz])
             phi = nu.array([phi])
         Lz = R * vT
         if self._useu0:
             #First calculate u0
             if 'u0' in kwargs:
                 u0 = nu.asarray(kwargs['u0'])
             else:
                 E = nu.array([
                     evaluatePotentials(R[ii], z[ii], self._pot) +
                     vR[ii]**2. / 2. + vz[ii]**2. / 2. + vT[ii]**2. / 2.
                     for ii in range(len(R))
                 ])
                 u0 = actionAngleStaeckel_c.actionAngleStaeckel_calcu0(
                     E, Lz, self._pot, self._delta)[0]
             kwargs.pop('u0', None)
         else:
             u0 = None
         jr, jz, Omegar, Omegaphi, Omegaz, angler, anglephi,anglez, err= actionAngleStaeckel_c.actionAngleFreqAngleStaeckel_c(\
             self._pot,self._delta,R,vR,vT,z,vz,phi,u0=u0)
         # Adjustements for close-to-circular orbits
         indx = nu.isnan(Omegar) * (jr < 10.**-3.) + nu.isnan(Omegaz) * (
             jz < 10.**-3.
         )  #Close-to-circular and close-to-the-plane orbits
         if nu.sum(indx) > 0:
             Omegar[indx] = [epifreq(self._pot, r) for r in R[indx]]
             Omegaphi[indx] = [omegac(self._pot, r) for r in R[indx]]
             Omegaz[indx] = [verticalfreq(self._pot, r) for r in R[indx]]
         if err == 0:
             return (jr, Lz, jz, Omegar, Omegaphi, Omegaz, angler, anglephi,
                     anglez)
         else:
             raise RuntimeError(
                 "C-code for calculation actions failed; try with c=False"
             )  #pragma: no cover
     else:  #pragma: no cover
         if 'c' in kwargs and kwargs['c'] and not self._c:  #pragma: no cover
             warnings.warn(
                 "C module not used because potential does not have a C implementation",
                 galpyWarning)
         raise NotImplementedError(
             "actionsFreqs with c=False not implemented")
示例#29
0
def _integrateOrbit_dxdv(vxvv, dxdv, pot, t, method, rectIn, rectOut):
    """
    NAME:
       _integrateOrbit_dxdv
    PURPOSE:
       integrate an orbit and area of phase space in a Phi(R) potential 
       in the (R,phi)-plane
    INPUT:
       vxvv - array with the initial conditions stacked like
              [R,vR,vT,phi]; vR outward!
       dxdv - difference to integrate [dR,dvR,dvT,dphi]
       pot - Potential instance
       t - list of times at which to output (0 has to be in this!)
       method - 'odeint' or 'leapfrog'
       rectIn= (False) if True, input dxdv is in rectangular coordinates
       rectOut= (False) if True, output dxdv (that in orbit_dxdv) is in rectangular coordinates
    OUTPUT:
       [:,8] array of [R,vR,vT,phi,dR,dvR,dvT,dphi] at each t
       error message from integrator
    HISTORY:
       2010-10-17 - Written - Bovy (IAS)
    """
    #First check that the potential has C
    if '_c' in method:
        allHasC = _check_c(pot) and _check_c(pot, dxdv=True)
        if not allHasC and not 'leapfrog' in method and not 'symplec' in method:
            method = 'odeint'
            warnings.warn(
                "Using odeint because not all used potential have adequate C implementations to integrate phase-space volumes",
                galpyWarning)
    #go to the rectangular frame
    this_vxvv = nu.array([
        vxvv[0] * nu.cos(vxvv[3]), vxvv[0] * nu.sin(vxvv[3]),
        vxvv[1] * nu.cos(vxvv[3]) - vxvv[2] * nu.sin(vxvv[3]),
        vxvv[2] * nu.cos(vxvv[3]) + vxvv[1] * nu.sin(vxvv[3])
    ])
    if not rectIn:
        this_dxdv = nu.array([
            nu.cos(vxvv[3]) * dxdv[0] - vxvv[0] * nu.sin(vxvv[3]) * dxdv[3],
            nu.sin(vxvv[3]) * dxdv[0] + vxvv[0] * nu.cos(vxvv[3]) * dxdv[3],
            -(vxvv[1] * nu.sin(vxvv[3]) + vxvv[2] * nu.cos(vxvv[3])) * dxdv[3]
            + nu.cos(vxvv[3]) * dxdv[1] - nu.sin(vxvv[3]) * dxdv[2],
            (vxvv[1] * nu.cos(vxvv[3]) - vxvv[2] * nu.sin(vxvv[3])) * dxdv[3] +
            nu.sin(vxvv[3]) * dxdv[1] + nu.cos(vxvv[3]) * dxdv[2]
        ])
    else:
        this_dxdv = dxdv
    if 'leapfrog' in method.lower() or 'symplec' in method.lower():
        raise TypeError(
            'Symplectic integration for phase-space volume is not possible')
    elif method.lower() == 'rk4_c' or method.lower() == 'rk6_c' \
            or method.lower() == 'dopr54_c':
        warnings.warn("Using C implementation to integrate orbits",
                      galpyWarningVerbose)
        #integrate
        tmp_out, msg = integratePlanarOrbit_dxdv_c(pot, this_vxvv, this_dxdv,
                                                   t, method)
    elif method.lower() == 'odeint':
        init = [
            this_vxvv[0], this_vxvv[1], this_vxvv[2], this_vxvv[3],
            this_dxdv[0], this_dxdv[1], this_dxdv[2], this_dxdv[3]
        ]
        #integrate
        tmp_out = integrate.odeint(_EOM_dxdv,
                                   init,
                                   t,
                                   args=(pot, ),
                                   rtol=10.**-8.)  #,mxstep=100000000)
        msg = 0
    else:
        raise NotImplementedError(
            "requested integration method does not exist")
    #go back to the cylindrical frame
    R = nu.sqrt(tmp_out[:, 0]**2. + tmp_out[:, 1]**2.)
    phi = nu.arccos(tmp_out[:, 0] / R)
    phi[(tmp_out[:, 1] < 0.)] = 2. * nu.pi - phi[(tmp_out[:, 1] < 0.)]
    vR = tmp_out[:, 2] * nu.cos(phi) + tmp_out[:, 3] * nu.sin(phi)
    vT = tmp_out[:, 3] * nu.cos(phi) - tmp_out[:, 2] * nu.sin(phi)
    cp = nu.cos(phi)
    sp = nu.sin(phi)
    dR = cp * tmp_out[:, 4] + sp * tmp_out[:, 5]
    dphi = (cp * tmp_out[:, 5] - sp * tmp_out[:, 4]) / R
    dvR = cp * tmp_out[:, 6] + sp * tmp_out[:, 7] + vT * dphi
    dvT = cp * tmp_out[:, 7] - sp * tmp_out[:, 6] - vR * dphi
    out = nu.zeros((len(t), 8))
    out[:, 0] = R
    out[:, 1] = vR
    out[:, 2] = vT
    out[:, 3] = phi
    if rectOut:
        out[:, 4:] = tmp_out[:, 4:]
    else:
        out[:, 4] = dR
        out[:, 7] = dphi
        out[:, 5] = dvR
        out[:, 6] = dvT
    _parse_warnmessage(msg)
    return (out, msg)
示例#30
0
def _integrateRZOrbit(vxvv, pot, t, method, dt):
    """
    NAME:
       _integrateRZOrbit
    PURPOSE:
       integrate an orbit in a Phi(R,z) potential in the (R,z) plane
    INPUT:
       vxvv - array with the initial conditions stacked like
              [R,vR,vT,z,vz]; vR outward!
       pot - Potential instance
       t - list of times at which to output (0 has to be in this!)
       method - 'odeint' or 'leapfrog'
       dt - if set, force the integrator to use this basic stepsize; must be an integer divisor of output stepsize
    OUTPUT:
       [:,5] array of [R,vR,vT,z,vz] at each t
    HISTORY:
       2010-04-16 - Written - Bovy (NYU)
    """
    #First check that the potential has C
    if '_c' in method:
        if not ext_loaded or not _check_c(pot):
            if ('leapfrog' in method or 'symplec' in method):
                method = 'leapfrog'
            else:
                method = 'odeint'
            if not ext_loaded:  # pragma: no cover
                warnings.warn(
                    "Cannot use C integration because C extension not loaded (using %s instead)"
                    % (method), galpyWarning)
            else:
                warnings.warn(
                    "Cannot use C integration because some of the potentials are not implemented in C (using %s instead)"
                    % (method), galpyWarning)
    if method.lower() == 'leapfrog' \
            or method.lower() == 'leapfrog_c' or method.lower() == 'rk4_c' \
            or method.lower() == 'rk6_c' or method.lower() == 'symplec4_c' \
            or method.lower() == 'symplec6_c' or method.lower() == 'dopr54_c':
        #We hack this by upgrading to a FullOrbit
        this_vxvv = nu.zeros(len(vxvv) + 1)
        this_vxvv[0:len(vxvv)] = vxvv
        tmp_out = _integrateFullOrbit(this_vxvv, pot, t, method, dt)
        #tmp_out is (nt,6)
        out = tmp_out[:, 0:5]
    elif method.lower() == 'odeint':
        l = vxvv[0] * vxvv[2]
        l2 = l**2.
        init = [vxvv[0], vxvv[1], vxvv[3], vxvv[4]]
        intOut = integrate.odeint(_RZEOM,
                                  init,
                                  t,
                                  args=(pot, l2),
                                  rtol=10.**-8.)  #,mxstep=100000000)
        out = nu.zeros((len(t), 5))
        out[:, 0] = intOut[:, 0]
        out[:, 1] = intOut[:, 1]
        out[:, 3] = intOut[:, 2]
        out[:, 4] = intOut[:, 3]
        out[:, 2] = l / out[:, 0]
    #post-process to remove negative radii
    neg_radii = (out[:, 0] < 0.)
    out[neg_radii, 0] = -out[neg_radii, 0]
    return out