def Er(self,R,z,vR,vz,E,Lz,sinh2u0,u0): """ NAME: Er PURPOSE: calculate the 'radial energy' INPUT: R, z, vR, vz - coordinates E - energy Lz - angular momentum sinh2u0, u0 - sinh^2 and u0 OUTPUT: Er HISTORY: 2012-11-29 - Written - Bovy (IAS) """ u,v= bovy_coords.Rz_to_uv(R,z,self._delta) pu= (vR*numpy.cosh(u)*numpy.sin(v) +vz*numpy.sinh(u)*numpy.cos(v)) #no delta, bc we will divide it out out= (pu**2./2.+Lz**2./2./self._delta**2.*(1./numpy.sinh(u)**2.-1./sinh2u0) -E*(numpy.sinh(u)**2.-sinh2u0) +(numpy.sinh(u)**2.+1.)*actionAngleStaeckel.potentialStaeckel(u,numpy.pi/2.,self._pot,self._delta) -(sinh2u0+1.)*actionAngleStaeckel.potentialStaeckel(u0,numpy.pi/2.,self._pot,self._delta)) # +(numpy.sinh(u)**2.+numpy.sin(v)**2.)*actionAngleStaeckel.potentialStaeckel(u,v,self._pot,self._delta) # -(sinh2u0+numpy.sin(v)**2.)*actionAngleStaeckel.potentialStaeckel(u0,v,self._pot,self._delta)) return out
def __init__(self, *args, **kwargs): """ NAME: __init__ PURPOSE: initialize an actionAngleStaeckelSingle object 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 pot= potential or list of potentials OUTPUT: HISTORY: 2012-11-27 - Written - Bovy (IAS) """ actionAngle.__init__(self, *args, **kwargs) if not 'pot' in kwargs: #pragma: no cover raise IOError("Must specify pot= for actionAngleStaeckelSingle") self._pot = kwargs['pot'] if not 'delta' in kwargs: #pragma: no cover raise IOError("Must specify delta= for actionAngleStaeckel") self._delta = kwargs['delta'] #Pre-calculate everything self._ux, self._vx = bovy_coords.Rz_to_uv(self._R, self._z, delta=self._delta) self._sinvx = nu.sin(self._vx) self._cosvx = nu.cos(self._vx) self._coshux = nu.cosh(self._ux) self._sinhux = nu.sinh(self._ux) self._pux = self._delta * (self._vR * self._coshux * self._sinvx + self._vz * self._sinhux * self._cosvx) self._pvx = self._delta * (self._vR * self._sinhux * self._cosvx - self._vz * self._coshux * self._sinvx) EL = self.calcEL() self._E = EL[0] self._Lz = EL[1] #Determine umin and umax self._u0 = kwargs.pop( 'u0', self._ux) #u0 as defined by Binney does not matter for a #single action evaluation, so we don't determine it here self._sinhu0 = nu.sinh(self._u0) self._potu0v0 = potentialStaeckel(self._u0, self._vx, self._pot, self._delta) self._I3U= self._E*self._sinhux**2.-self._pux**2./2./self._delta**2.\ -self._Lz**2./2./self._delta**2./self._sinhux**2. self._potupi2 = potentialStaeckel(self._ux, nu.pi / 2., self._pot, self._delta) dV = (self._coshux**2. * self._potupi2 - (self._sinhux**2. + self._sinvx**2.) * potentialStaeckel(self._ux, self._vx, self._pot, self._delta)) self._I3V= -self._E*self._sinvx**2.+self._pvx**2./2./self._delta**2.\ +self._Lz**2./2./self._delta**2./self._sinvx**2.\ -dV self.calcUminUmax() self.calcVmin() return None
def actionAngleStaeckel_c(pot, delta, R, vR, vT, z, vz, u0=None, order=10): """ NAME: actionAngleStaeckel_c PURPOSE: Use C to calculate actions using the Staeckel approximation INPUT: pot - Potential or list of such instances delta - focal length of prolate spheroidal coordinates R, vR, vT, z, vz - coordinates (arrays) u0= (None) if set, u0 to use order= (10) order of Gauss-Legendre integration of the relevant integrals OUTPUT: (jr,jz,err) jr,jz : array, shape (len(R)) err - non-zero if error occured HISTORY: 2012-12-01 - Written - Bovy (IAS) """ if u0 is None: u0, dummy = bovy_coords.Rz_to_uv(R, z, delta=numpy.atleast_1d(delta)) #Parse the potential npot, pot_type, pot_args = _parse_pot(pot, potforactions=True) #Parse delta delta = numpy.atleast_1d(delta) ndelta = len(delta) #Set up result arrays jr = numpy.empty(len(R)) jz = numpy.empty(len(R)) err = ctypes.c_int(0) #Set up the C code ndarrayFlags = ('C_CONTIGUOUS', 'WRITEABLE') actionAngleStaeckel_actionsFunc = _lib.actionAngleStaeckel_actions actionAngleStaeckel_actionsFunc.argtypes = [ ctypes.c_int, ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.c_int, ndpointer(dtype=numpy.int32, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.c_int, ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.c_int, ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.POINTER(ctypes.c_int) ] #Array requirements, first store old order f_cont = [ R.flags['F_CONTIGUOUS'], vR.flags['F_CONTIGUOUS'], vT.flags['F_CONTIGUOUS'], z.flags['F_CONTIGUOUS'], vz.flags['F_CONTIGUOUS'], u0.flags['F_CONTIGUOUS'], delta.flags['F_CONTIGUOUS'] ] R = numpy.require(R, dtype=numpy.float64, requirements=['C', 'W']) vR = numpy.require(vR, dtype=numpy.float64, requirements=['C', 'W']) vT = numpy.require(vT, dtype=numpy.float64, requirements=['C', 'W']) z = numpy.require(z, dtype=numpy.float64, requirements=['C', 'W']) vz = numpy.require(vz, dtype=numpy.float64, requirements=['C', 'W']) u0 = numpy.require(u0, dtype=numpy.float64, requirements=['C', 'W']) delta = numpy.require(delta, dtype=numpy.float64, requirements=['C', 'W']) jr = numpy.require(jr, dtype=numpy.float64, requirements=['C', 'W']) jz = numpy.require(jz, dtype=numpy.float64, requirements=['C', 'W']) #Run the C code actionAngleStaeckel_actionsFunc(len(R), R, vR, vT, z, vz, u0, ctypes.c_int(npot), pot_type, pot_args, ctypes.c_int(ndelta), delta, ctypes.c_int(order), jr, jz, ctypes.byref(err)) #Reset input arrays if f_cont[0]: R = numpy.asfortranarray(R) if f_cont[1]: vR = numpy.asfortranarray(vR) if f_cont[2]: vT = numpy.asfortranarray(vT) if f_cont[3]: z = numpy.asfortranarray(z) if f_cont[4]: vz = numpy.asfortranarray(vz) if f_cont[5]: u0 = numpy.asfortranarray(u0) if f_cont[6]: delta = numpy.asfortranarray(delta) return (jr, jz, err.value)
def actionAngleUminUmaxVminStaeckel_c(pot, delta, R, vR, vT, z, vz, u0=None): """ NAME: actionAngleUminUmaxVminStaeckel_c PURPOSE: Use C to calculate umin, umax, and vmin using the Staeckel approximation INPUT: pot - Potential or list of such instances delta - focal length of prolate spheroidal coordinates R, vR, vT, z, vz - coordinates (arrays) OUTPUT: (umin,umax,vmin,err) umin,umax,vmin : array, shape (len(R)) err - non-zero if error occured HISTORY: 2017-12-12 - Written - Bovy (UofT) """ if u0 is None: u0, dummy = bovy_coords.Rz_to_uv(R, z, delta=numpy.atleast_1d(delta)) #Parse the potential from galpy.orbit.integrateFullOrbit import _parse_pot npot, pot_type, pot_args = _parse_pot(pot, potforactions=True) #Parse delta delta = numpy.atleast_1d(delta) ndelta = len(delta) #Set up result arrays umin = numpy.empty(len(R)) umax = numpy.empty(len(R)) vmin = numpy.empty(len(R)) err = ctypes.c_int(0) #Set up the C code ndarrayFlags = ('C_CONTIGUOUS', 'WRITEABLE') actionAngleStaeckel_actionsFunc = _lib.actionAngleStaeckel_uminUmaxVmin actionAngleStaeckel_actionsFunc.argtypes = [ ctypes.c_int, ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.c_int, ndpointer(dtype=numpy.int32, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.c_int, ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.POINTER(ctypes.c_int) ] #Array requirements, first store old order f_cont = [ R.flags['F_CONTIGUOUS'], vR.flags['F_CONTIGUOUS'], vT.flags['F_CONTIGUOUS'], z.flags['F_CONTIGUOUS'], vz.flags['F_CONTIGUOUS'], u0.flags['F_CONTIGUOUS'], delta.flags['F_CONTIGUOUS'] ] R = numpy.require(R, dtype=numpy.float64, requirements=['C', 'W']) vR = numpy.require(vR, dtype=numpy.float64, requirements=['C', 'W']) vT = numpy.require(vT, dtype=numpy.float64, requirements=['C', 'W']) z = numpy.require(z, dtype=numpy.float64, requirements=['C', 'W']) vz = numpy.require(vz, dtype=numpy.float64, requirements=['C', 'W']) u0 = numpy.require(u0, dtype=numpy.float64, requirements=['C', 'W']) delta = numpy.require(delta, dtype=numpy.float64, requirements=['C', 'W']) umin = numpy.require(umin, dtype=numpy.float64, requirements=['C', 'W']) umax = numpy.require(umax, dtype=numpy.float64, requirements=['C', 'W']) vmin = numpy.require(vmin, dtype=numpy.float64, requirements=['C', 'W']) #Run the C code actionAngleStaeckel_actionsFunc(len(R), R, vR, vT, z, vz, u0, ctypes.c_int(npot), pot_type, pot_args, ctypes.c_int(ndelta), delta, umin, umax, vmin, ctypes.byref(err)) #Reset input arrays if f_cont[0]: R = numpy.asfortranarray(R) if f_cont[1]: vR = numpy.asfortranarray(vR) if f_cont[2]: vT = numpy.asfortranarray(vT) if f_cont[3]: z = numpy.asfortranarray(z) if f_cont[4]: vz = numpy.asfortranarray(vz) if f_cont[5]: u0 = numpy.asfortranarray(u0) if f_cont[6]: delta = numpy.asfortranarray(delta) return (umin, umax, vmin, err.value)
def actionAngleFreqAngleStaeckel_c(pot, delta, R, vR, vT, z, vz, phi, u0=None): """ NAME: actionAngleFreqAngleStaeckel_c PURPOSE: Use C to calculate actions, frequencies, and angles using the Staeckel approximation INPUT: pot - Potential or list of such instances delta - focal length of prolate spheroidal coordinates R, vR, vT, z, vz, phi - coordinates (arrays) OUTPUT: (jr,jz,Omegar,Omegaphi,Omegaz,Angler,Anglephi,Anglez,err) jr,jz,Omegar,Omegaphi,Omegaz,Angler,Anglephi,Anglez : array, shape (len(R)) err - non-zero if error occured HISTORY: 2013-08-27 - Written - Bovy (IAS) """ if u0 is None: u0, dummy = bovy_coords.Rz_to_uv(R, z, delta=delta) #Parse the potential npot, pot_type, pot_args = _parse_pot(pot, potforactions=True) #Set up result arrays jr = numpy.empty(len(R)) jz = numpy.empty(len(R)) Omegar = numpy.empty(len(R)) Omegaphi = numpy.empty(len(R)) Omegaz = numpy.empty(len(R)) Angler = numpy.empty(len(R)) Anglephi = numpy.empty(len(R)) Anglez = numpy.empty(len(R)) err = ctypes.c_int(0) #Set up the C code ndarrayFlags = ('C_CONTIGUOUS', 'WRITEABLE') actionAngleStaeckel_actionsFunc = _lib.actionAngleStaeckel_actionsFreqsAngles actionAngleStaeckel_actionsFunc.argtypes = [ ctypes.c_int, ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.c_int, ndpointer(dtype=numpy.int32, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.c_double, ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.POINTER(ctypes.c_int) ] #Array requirements, first store old order f_cont = [ R.flags['F_CONTIGUOUS'], vR.flags['F_CONTIGUOUS'], vT.flags['F_CONTIGUOUS'], z.flags['F_CONTIGUOUS'], vz.flags['F_CONTIGUOUS'], u0.flags['F_CONTIGUOUS'] ] R = numpy.require(R, dtype=numpy.float64, requirements=['C', 'W']) vR = numpy.require(vR, dtype=numpy.float64, requirements=['C', 'W']) vT = numpy.require(vT, dtype=numpy.float64, requirements=['C', 'W']) z = numpy.require(z, dtype=numpy.float64, requirements=['C', 'W']) vz = numpy.require(vz, dtype=numpy.float64, requirements=['C', 'W']) u0 = numpy.require(u0, dtype=numpy.float64, requirements=['C', 'W']) jr = numpy.require(jr, dtype=numpy.float64, requirements=['C', 'W']) jz = numpy.require(jz, dtype=numpy.float64, requirements=['C', 'W']) Omegar = numpy.require(Omegar, dtype=numpy.float64, requirements=['C', 'W']) Omegaphi = numpy.require(Omegaphi, dtype=numpy.float64, requirements=['C', 'W']) Omegaz = numpy.require(Omegaz, dtype=numpy.float64, requirements=['C', 'W']) Angler = numpy.require(Angler, dtype=numpy.float64, requirements=['C', 'W']) Anglephi = numpy.require(Anglephi, dtype=numpy.float64, requirements=['C', 'W']) Anglez = numpy.require(Anglez, dtype=numpy.float64, requirements=['C', 'W']) #Run the C code actionAngleStaeckel_actionsFunc(len(R), R, vR, vT, z, vz, u0, ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(delta), jr, jz, Omegar, Omegaphi, Omegaz, Angler, Anglephi, Anglez, ctypes.byref(err)) #Reset input arrays if f_cont[0]: R = numpy.asfortranarray(R) if f_cont[1]: vR = numpy.asfortranarray(vR) if f_cont[2]: vT = numpy.asfortranarray(vT) if f_cont[3]: z = numpy.asfortranarray(z) if f_cont[4]: vz = numpy.asfortranarray(vz) if f_cont[5]: u0 = numpy.asfortranarray(u0) badAngle = Anglephi != 9999.99 Anglephi[badAngle] = (Anglephi[badAngle] + phi[badAngle] % (2. * numpy.pi)) % (2. * numpy.pi) Anglephi[Anglephi < 0.] += 2. * numpy.pi return (jr, jz, Omegar, Omegaphi, Omegaz, Angler, Anglephi, Anglez, err.value)