def actionAngleTorus_Freqs_c(pot,jr,jphi,jz, tol=0.003): """ NAME: actionAngleTorus_Freqs_c PURPOSE: compute frequencies on a single torus INPUT: pot - Potential object or list thereof jr - radial action (scalar) jphi - azimuthal action (scalar) jz - vertical action (scalar) tol= (0.003) goal for |dJ|/|J| along the torus OUTPUT: (Omegar,Omegaphi,Omegaz,flag) HISTORY: 2015-08-05/07 - Written - Bovy (UofT) """ #Parse the potential npot, pot_type, pot_args= _parse_pot(pot,potfortorus=True) #Set up result Omegar= numpy.empty(1) Omegaphi= numpy.empty(1) Omegaz= numpy.empty(1) flag= ctypes.c_int(0) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') actionAngleTorus_FreqsFunc= _lib.actionAngleTorus_Freqs actionAngleTorus_FreqsFunc.argtypes=\ [ctypes.c_double, ctypes.c_double, ctypes.c_double, 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), ctypes.POINTER(ctypes.c_int)] #Array requirements 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']) #Run the C code actionAngleTorus_FreqsFunc(ctypes.c_double(jr), ctypes.c_double(jphi), ctypes.c_double(jz), ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(tol), Omegar,Omegaphi,Omegaz, ctypes.byref(flag)) return (Omegar[0],Omegaphi[0],Omegaz[0],flag.value)
def actionAngleStaeckel_calcu0(E,Lz,pot,delta): """ NAME: actionAngleStaeckel_calcu0 PURPOSE: Use C to calculate u0 in the Staeckel approximation INPUT: E, Lz - energy and angular momentum pot - Potential or list of such instances delta - focal length of prolate spheroidal coordinates OUTPUT: (u0,err) u0 : array, shape (len(E)) err - non-zero if error occured HISTORY: 2012-12-03 - Written - Bovy (IAS) """ #Parse the potential npot, pot_type, pot_args= _parse_pot(pot,potforactions=True) #Set up result arrays u0= numpy.empty(len(E)) err= ctypes.c_int(0) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') actionAngleStaeckel_actionsFunc= _lib.calcu0 actionAngleStaeckel_actionsFunc.argtypes= [ctypes.c_int, 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), ctypes.POINTER(ctypes.c_int)] #Array requirements, first store old order f_cont= [E.flags['F_CONTIGUOUS'], Lz.flags['F_CONTIGUOUS']] E= numpy.require(E,dtype=numpy.float64,requirements=['C','W']) Lz= numpy.require(Lz,dtype=numpy.float64,requirements=['C','W']) u0= numpy.require(u0,dtype=numpy.float64,requirements=['C','W']) #Run the C code actionAngleStaeckel_actionsFunc(len(E), E, Lz, ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(delta), u0, ctypes.byref(err)) #Reset input arrays if f_cont[0]: E= numpy.asfortranarray(E) if f_cont[1]: Lz= numpy.asfortranarray(Lz) return (u0,err.value)
def calc_potential_c(pot, R, z, rforce=False, zforce=False): """ NAME: calc_potential_c PURPOSE: Use C to calculate the potential on a grid INPUT: pot - Potential or list of such instances R - grid in R z - grid in z rforce=, zforce= if either of these is True, calculate the radial or vertical force instead OUTPUT: potential on the grid (2D array) HISTORY: 2013-01-24 - Written - Bovy (IAS) 2013-01-29 - Added forces - Bovy (IAS) """ from galpy.orbit_src.integrateFullOrbit import _parse_pot #here bc otherwise there is an infinite loop #Parse the potential npot, pot_type, pot_args = _parse_pot(pot) #Set up result arrays out = numpy.empty((len(R), len(z))) err = ctypes.c_int(0) #Set up the C code ndarrayFlags = ('C_CONTIGUOUS', 'WRITEABLE') if rforce: interppotential_calc_potentialFunc = _lib.calc_rforce elif zforce: interppotential_calc_potentialFunc = _lib.calc_zforce else: interppotential_calc_potentialFunc = _lib.calc_potential interppotential_calc_potentialFunc.argtypes = [ ctypes.c_int, ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.c_int, ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.c_int, ndpointer(dtype=numpy.int32, 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'], z.flags['F_CONTIGUOUS']] R = numpy.require(R, dtype=numpy.float64, requirements=['C', 'W']) z = numpy.require(z, dtype=numpy.float64, requirements=['C', 'W']) out = numpy.require(out, dtype=numpy.float64, requirements=['C', 'W']) #Run the C code interppotential_calc_potentialFunc(len(R), R, len(z), z, ctypes.c_int(npot), pot_type, pot_args, out, ctypes.byref(err)) #Reset input arrays if f_cont[0]: R = numpy.asfortranarray(R) if f_cont[1]: z = numpy.asfortranarray(z) return (out, err.value)
def eval_force_c(pot, R, z, zforce=False): """ NAME: eval_force_c PURPOSE: Use C to evaluate the interpolated potential's forces INPUT: pot - Potential or list of such instances R - array z - array zforce= if True, return the vertical force, otherwise return the radial force OUTPUT: force evaluated R and z HISTORY: 2013-01-29 - Written - Bovy (IAS) """ from galpy.orbit_src.integrateFullOrbit import _parse_pot # here bc otherwise there is an infinite loop # Parse the potential npot, pot_type, pot_args = _parse_pot(pot) # Set up result arrays out = numpy.empty((len(R))) err = ctypes.c_int(0) # Set up the C code ndarrayFlags = ("C_CONTIGUOUS", "WRITEABLE") if zforce: interppotential_calc_forceFunc = _lib.eval_zforce else: interppotential_calc_forceFunc = _lib.eval_rforce interppotential_calc_forceFunc.argtypes = [ ctypes.c_int, 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), ndpointer(dtype=numpy.float64, flags=ndarrayFlags), ctypes.POINTER(ctypes.c_int), ] # Array requirements, first store old order f_cont = [R.flags["F_CONTIGUOUS"], z.flags["F_CONTIGUOUS"]] R = numpy.require(R, dtype=numpy.float64, requirements=["C", "W"]) z = numpy.require(z, dtype=numpy.float64, requirements=["C", "W"]) out = numpy.require(out, dtype=numpy.float64, requirements=["C", "W"]) # Run the C code interppotential_calc_forceFunc(len(R), R, z, ctypes.c_int(npot), pot_type, pot_args, out, ctypes.byref(err)) # Reset input arrays if f_cont[0]: R = numpy.asfortranarray(R) if f_cont[1]: z = numpy.asfortranarray(z) return (out, err.value)
def eval_potential_c(pot,R,z): """ NAME: eval_potential_c PURPOSE: Use C to evaluate the interpolated potential INPUT: pot - Potential or list of such instances R - array z - array OUTPUT: potential evaluated R and z HISTORY: 2013-01-24 - Written - Bovy (IAS) """ from galpy.orbit_src.integrateFullOrbit import _parse_pot #here bc otherwise there is an infinite loop #Parse the potential npot, pot_type, pot_args= _parse_pot(pot,potforactions=True) #Set up result arrays out= numpy.empty((len(R))) err= ctypes.c_int(0) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') interppotential_calc_potentialFunc= _lib.eval_potential interppotential_calc_potentialFunc.argtypes= [ctypes.c_int, 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), ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.POINTER(ctypes.c_int)] #Array requirements, first store old order f_cont= [R.flags['F_CONTIGUOUS'], z.flags['F_CONTIGUOUS']] R= numpy.require(R,dtype=numpy.float64,requirements=['C','W']) z= numpy.require(z,dtype=numpy.float64,requirements=['C','W']) out= numpy.require(out,dtype=numpy.float64,requirements=['C','W']) #Run the C code interppotential_calc_potentialFunc(len(R), R, z, ctypes.c_int(npot), pot_type, pot_args, out, ctypes.byref(err)) #Reset input arrays if f_cont[0]: R= numpy.asfortranarray(R) if f_cont[1]: z= numpy.asfortranarray(z) return (out,err.value)
def actionAngleStaeckel_calcu0(E, Lz, pot, delta): """ NAME: actionAngleStaeckel_calcu0 PURPOSE: Use C to calculate u0 in the Staeckel approximation INPUT: E, Lz - energy and angular momentum pot - Potential or list of such instances delta - focal length of prolate spheroidal coordinates OUTPUT: (u0,err) u0 : array, shape (len(E)) err - non-zero if error occured HISTORY: 2012-12-03 - Written - Bovy (IAS) """ #Parse the potential npot, pot_type, pot_args = _parse_pot(pot, potforactions=True) #Set up result arrays u0 = numpy.empty(len(E)) err = ctypes.c_int(0) #Set up the C code ndarrayFlags = ('C_CONTIGUOUS', 'WRITEABLE') actionAngleStaeckel_actionsFunc = _lib.calcu0 actionAngleStaeckel_actionsFunc.argtypes = [ ctypes.c_int, 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), ctypes.POINTER(ctypes.c_int) ] #Array requirements, first store old order f_cont = [E.flags['F_CONTIGUOUS'], Lz.flags['F_CONTIGUOUS']] E = numpy.require(E, dtype=numpy.float64, requirements=['C', 'W']) Lz = numpy.require(Lz, dtype=numpy.float64, requirements=['C', 'W']) u0 = numpy.require(u0, dtype=numpy.float64, requirements=['C', 'W']) #Run the C code actionAngleStaeckel_actionsFunc(len(E), E, Lz, ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(delta), u0, ctypes.byref(err)) #Reset input arrays if f_cont[0]: E = numpy.asfortranarray(E) if f_cont[1]: Lz = numpy.asfortranarray(Lz) return (u0, err.value)
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 calc_potential_c(pot,R,z,rforce=False,zforce=False): """ NAME: calc_potential_c PURPOSE: Use C to calculate the potential on a grid INPUT: pot - Potential or list of such instances R - grid in R z - grid in z rforce=, zforce= if either of these is True, calculate the radial or vertical force instead OUTPUT: potential on the grid (2D array) HISTORY: 2013-01-24 - Written - Bovy (IAS) 2013-01-29 - Added forces - Bovy (IAS) """ from galpy.orbit_src.integrateFullOrbit import _parse_pot #here bc otherwise there is an infinite loop #Parse the potential npot, pot_type, pot_args= _parse_pot(pot) #Set up result arrays out= numpy.empty((len(R),len(z))) err= ctypes.c_int(0) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') if rforce: interppotential_calc_potentialFunc= _lib.calc_rforce elif zforce: interppotential_calc_potentialFunc= _lib.calc_zforce else: interppotential_calc_potentialFunc= _lib.calc_potential interppotential_calc_potentialFunc.argtypes= [ctypes.c_int, ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_int, ndpointer(dtype=numpy.int32,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'], z.flags['F_CONTIGUOUS']] R= numpy.require(R,dtype=numpy.float64,requirements=['C','W']) z= numpy.require(z,dtype=numpy.float64,requirements=['C','W']) out= numpy.require(out,dtype=numpy.float64,requirements=['C','W']) #Run the C code interppotential_calc_potentialFunc(len(R), R, len(z), z, ctypes.c_int(npot), pot_type, pot_args, out, ctypes.byref(err)) #Reset input arrays if f_cont[0]: R= numpy.asfortranarray(R) if f_cont[1]: z= numpy.asfortranarray(z) return (out,err.value)
def actionAngleAdiabatic_c(pot,gamma,R,vR,vT,z,vz): """ NAME: actionAngleAdiabatic_c PURPOSE: Use C to calculate actions using the adiabatic approximation INPUT: pot - Potential or list of such instances gamma - as in Lz -> Lz+\gamma * J_z R, vR, vT, z, vz - coordinates (arrays) OUTPUT: (jr,jz,err) jr,jz : array, shape (len(R)) err - non-zero if error occured HISTORY: 2012-12-10 - Written - Bovy (IAS) """ #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)) err= ctypes.c_int(0) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') actionAngleAdiabatic_actionsFunc= _lib.actionAngleAdiabatic_actions actionAngleAdiabatic_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), 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), 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']] 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']) jr= numpy.require(jr,dtype=numpy.float64,requirements=['C','W']) jz= numpy.require(jz,dtype=numpy.float64,requirements=['C','W']) #Run the C code actionAngleAdiabatic_actionsFunc(len(R), R, vR, vT, z, vz, ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(gamma), 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) return (jr,jz,err.value)
def actionAngleTorus_hessian_c(pot,jr,jphi,jz, tol=0.003,dJ=0.001): """ NAME: actionAngleTorus_hessian_c PURPOSE: compute dO/dJ on a single torus INPUT: pot - Potential object or list thereof jr - radial action (scalar) jphi - azimuthal action (scalar) jz - vertical action (scalar) tol= (0.003) goal for |dJ|/|J| along the torus dJ= (0.001) action difference when computing derivatives (Hessian or Jacobian) OUTPUT: (dO/dJ,Omegar,Omegaphi,Omegaz,Autofit error flag) Note: dO/dJ is *not* symmetrized here HISTORY: 2016-07-15 - Written - Bovy (UofT) """ #Parse the potential npot, pot_type, pot_args= _parse_pot(pot,potfortorus=True) #Set up result dOdJT= numpy.empty(9) Omegar= numpy.empty(1) Omegaphi= numpy.empty(1) Omegaz= numpy.empty(1) flag= ctypes.c_int(0) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') actionAngleTorus_HessFunc= _lib.actionAngleTorus_hessianFreqs actionAngleTorus_HessFunc.argtypes=\ [ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_int, ndpointer(dtype=numpy.int32,flags=ndarrayFlags), ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_double, 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), ctypes.POINTER(ctypes.c_int)] #Array requirements dOdJT= numpy.require(dOdJT,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']) #Run the C code actionAngleTorus_HessFunc(ctypes.c_double(jr), ctypes.c_double(jphi), ctypes.c_double(jz), ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(tol), ctypes.c_double(dJ), dOdJT, Omegar,Omegaphi,Omegaz, ctypes.byref(flag)) return (dOdJT.reshape((3,3)).T,Omegar[0],Omegaphi[0],Omegaz[0],flag.value)
def actionAngleTorus_xvFreqs_c(pot, jr, jphi, jz, angler, anglephi, anglez, tol=0.003): """ NAME: actionAngleTorus_xvFreqs_c PURPOSE: compute configuration (x,v) and frequencies of a set of angles on a single torus INPUT: pot - Potential object or list thereof jr - radial action (scalar) jphi - azimuthal action (scalar) jz - vertical action (scalar) angler - radial angle (array [N]) anglephi - azimuthal angle (array [N]) anglez - vertical angle (array [N]) tol= (0.003) goal for |dJ|/|J| along the torus OUTPUT: (R,vR,vT,z,vz,phi,Omegar,Omegaphi,Omegaz,flag) HISTORY: 2015-08-05/07 - Written - Bovy (UofT) """ #Parse the potential npot, pot_type, pot_args = _parse_pot(pot, potfortorus=True) #Set up result arrays R = numpy.empty(len(angler)) vR = numpy.empty(len(angler)) vT = numpy.empty(len(angler)) z = numpy.empty(len(angler)) vz = numpy.empty(len(angler)) phi = numpy.empty(len(angler)) Omegar = numpy.empty(1) Omegaphi = numpy.empty(1) Omegaz = numpy.empty(1) flag = ctypes.c_int(0) #Set up the C code ndarrayFlags = ('C_CONTIGUOUS', 'WRITEABLE') actionAngleTorus_xvFreqsFunc = _lib.actionAngleTorus_xvFreqs actionAngleTorus_xvFreqsFunc.argtypes=\ [ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_int, 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), ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.POINTER(ctypes.c_int)] #Array requirements, first store old order f_cont = [ angler.flags['F_CONTIGUOUS'], anglephi.flags['F_CONTIGUOUS'], anglez.flags['F_CONTIGUOUS'] ] 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']) 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']) phi = numpy.require(phi, 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']) #Run the C code actionAngleTorus_xvFreqsFunc(ctypes.c_double(jr), ctypes.c_double(jphi), ctypes.c_double(jz), ctypes.c_int(len(angler)), angler, anglephi, anglez, ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(tol), R, vR, vT, z, vz, phi, Omegar, Omegaphi, Omegaz, ctypes.byref(flag)) #Reset input arrays if f_cont[0]: angler = numpy.asfortranarray(angler) if f_cont[1]: anglephi = numpy.asfortranarray(anglephi) if f_cont[2]: anglez = numpy.asfortranarray(anglez) return (R, vR, vT, z, vz, phi, Omegar[0], Omegaphi[0], Omegaz[0], flag.value)
def actionAngleTorus_jacobian_c(pot, jr, jphi, jz, angler, anglephi, anglez, tol=0.003, dJ=0.001): """ NAME: actionAngleTorus_jacobian_c PURPOSE: compute d(x,v)/d(J,theta) on a single torus, also compute dO/dJ and the frequencies INPUT: pot - Potential object or list thereof jr - radial action (scalar) jphi - azimuthal action (scalar) jz - vertical action (scalar) angler - radial angle (array [N]) anglephi - azimuthal angle (array [N]) anglez - vertical angle (array [N]) tol= (0.003) goal for |dJ|/|J| along the torus dJ= (0.001) action difference when computing derivatives (Hessian or Jacobian) OUTPUT: (d[R,vR,vT,z,vz,phi]/d[J,theta], Omegar,Omegaphi,Omegaz, Autofit error message) Note: dO/dJ is *not* symmetrized here HISTORY: 2016-07-19 - Written - Bovy (UofT) """ #Parse the potential npot, pot_type, pot_args = _parse_pot(pot, potfortorus=True) #Set up result R = numpy.empty(len(angler)) vR = numpy.empty(len(angler)) vT = numpy.empty(len(angler)) z = numpy.empty(len(angler)) vz = numpy.empty(len(angler)) phi = numpy.empty(len(angler)) dxvOdJaT = numpy.empty(36 * len(angler)) dOdJT = numpy.empty(9) Omegar = numpy.empty(1) Omegaphi = numpy.empty(1) Omegaz = numpy.empty(1) flag = ctypes.c_int(0) #Set up the C code ndarrayFlags = ('C_CONTIGUOUS', 'WRITEABLE') actionAngleTorus_JacFunc = _lib.actionAngleTorus_jacobianFreqs actionAngleTorus_JacFunc.argtypes=\ [ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_int, 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, 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), 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 = [ angler.flags['F_CONTIGUOUS'], anglephi.flags['F_CONTIGUOUS'], anglez.flags['F_CONTIGUOUS'] ] 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']) 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']) phi = numpy.require(phi, dtype=numpy.float64, requirements=['C', 'W']) dxvOdJaT = numpy.require(dxvOdJaT, dtype=numpy.float64, requirements=['C', 'W']) dOdJT = numpy.require(dOdJT, 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']) #Run the C code actionAngleTorus_JacFunc(ctypes.c_double(jr), ctypes.c_double(jphi), ctypes.c_double(jz), ctypes.c_int(len(angler)), angler, anglephi, anglez, ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(tol), ctypes.c_double(dJ), R, vR, vT, z, vz, phi, dxvOdJaT, dOdJT, Omegar, Omegaphi, Omegaz, ctypes.byref(flag)) #Reset input arrays if f_cont[0]: angler = numpy.asfortranarray(angler) if f_cont[1]: anglephi = numpy.asfortranarray(anglephi) if f_cont[2]: anglez = numpy.asfortranarray(anglez) dxvOdJaT = numpy.reshape(dxvOdJaT, (len(angler), 6, 6), order='C') dxvOdJa = numpy.swapaxes(dxvOdJaT, 1, 2) return (R, vR, vT, z, vz, phi, dxvOdJa, dOdJT.reshape( (3, 3)).T, Omegar[0], Omegaphi[0], Omegaz[0], flag.value)
def actionAngleTorus_hessian_c(pot, jr, jphi, jz, tol=0.003, dJ=0.001): """ NAME: actionAngleTorus_hessian_c PURPOSE: compute dO/dJ on a single torus INPUT: pot - Potential object or list thereof jr - radial action (scalar) jphi - azimuthal action (scalar) jz - vertical action (scalar) tol= (0.003) goal for |dJ|/|J| along the torus dJ= (0.001) action difference when computing derivatives (Hessian or Jacobian) OUTPUT: (dO/dJ,Omegar,Omegaphi,Omegaz,Autofit error flag) Note: dO/dJ is *not* symmetrized here HISTORY: 2016-07-15 - Written - Bovy (UofT) """ #Parse the potential npot, pot_type, pot_args = _parse_pot(pot, potfortorus=True) #Set up result dOdJT = numpy.empty(9) Omegar = numpy.empty(1) Omegaphi = numpy.empty(1) Omegaz = numpy.empty(1) flag = ctypes.c_int(0) #Set up the C code ndarrayFlags = ('C_CONTIGUOUS', 'WRITEABLE') actionAngleTorus_HessFunc = _lib.actionAngleTorus_hessianFreqs actionAngleTorus_HessFunc.argtypes=\ [ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_int, ndpointer(dtype=numpy.int32,flags=ndarrayFlags), ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.c_double, 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), ctypes.POINTER(ctypes.c_int)] #Array requirements dOdJT = numpy.require(dOdJT, 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']) #Run the C code actionAngleTorus_HessFunc(ctypes.c_double(jr), ctypes.c_double(jphi), ctypes.c_double(jz), ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(tol), ctypes.c_double(dJ), dOdJT, Omegar, Omegaphi, Omegaz, ctypes.byref(flag)) return (dOdJT.reshape( (3, 3)).T, Omegar[0], Omegaphi[0], Omegaz[0], flag.value)
def actionAngleTorus_Freqs_c(pot, jr, jphi, jz, tol=0.003): """ NAME: actionAngleTorus_Freqs_c PURPOSE: compute frequencies on a single torus INPUT: pot - Potential object or list thereof jr - radial action (scalar) jphi - azimuthal action (scalar) jz - vertical action (scalar) tol= (0.003) goal for |dJ|/|J| along the torus OUTPUT: (Omegar,Omegaphi,Omegaz,flag) HISTORY: 2015-08-05/07 - Written - Bovy (UofT) """ #Parse the potential npot, pot_type, pot_args = _parse_pot(pot, potfortorus=True) #Set up result Omegar = numpy.empty(1) Omegaphi = numpy.empty(1) Omegaz = numpy.empty(1) flag = ctypes.c_int(0) #Set up the C code ndarrayFlags = ('C_CONTIGUOUS', 'WRITEABLE') actionAngleTorus_FreqsFunc = _lib.actionAngleTorus_Freqs actionAngleTorus_FreqsFunc.argtypes=\ [ctypes.c_double, ctypes.c_double, ctypes.c_double, 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), ctypes.POINTER(ctypes.c_int)] #Array requirements 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']) #Run the C code actionAngleTorus_FreqsFunc(ctypes.c_double(jr), ctypes.c_double(jphi), ctypes.c_double(jz), ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(tol), Omegar, Omegaphi, Omegaz, ctypes.byref(flag)) return (Omegar[0], Omegaphi[0], Omegaz[0], flag.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)
def actionAngleTorus_jacobian_c(pot,jr,jphi,jz,angler,anglephi,anglez, tol=0.003,dJ=0.001): """ NAME: actionAngleTorus_jacobian_c PURPOSE: compute d(x,v)/d(J,theta) on a single torus, also compute dO/dJ and the frequencies INPUT: pot - Potential object or list thereof jr - radial action (scalar) jphi - azimuthal action (scalar) jz - vertical action (scalar) angler - radial angle (array [N]) anglephi - azimuthal angle (array [N]) anglez - vertical angle (array [N]) tol= (0.003) goal for |dJ|/|J| along the torus dJ= (0.001) action difference when computing derivatives (Hessian or Jacobian) OUTPUT: (d[R,vR,vT,z,vz,phi]/d[J,theta], Omegar,Omegaphi,Omegaz, Autofit error message) Note: dO/dJ is *not* symmetrized here HISTORY: 2016-07-19 - Written - Bovy (UofT) """ #Parse the potential npot, pot_type, pot_args= _parse_pot(pot,potfortorus=True) #Set up result R= numpy.empty(len(angler)) vR= numpy.empty(len(angler)) vT= numpy.empty(len(angler)) z= numpy.empty(len(angler)) vz= numpy.empty(len(angler)) phi= numpy.empty(len(angler)) dxvOdJaT= numpy.empty(36*len(angler)) dOdJT= numpy.empty(9) Omegar= numpy.empty(1) Omegaphi= numpy.empty(1) Omegaz= numpy.empty(1) flag= ctypes.c_int(0) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') actionAngleTorus_JacFunc= _lib.actionAngleTorus_jacobianFreqs actionAngleTorus_JacFunc.argtypes=\ [ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_int, 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, 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), 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= [angler.flags['F_CONTIGUOUS'], anglephi.flags['F_CONTIGUOUS'], anglez.flags['F_CONTIGUOUS']] 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']) 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']) phi= numpy.require(phi,dtype=numpy.float64,requirements=['C','W']) dxvOdJaT= numpy.require(dxvOdJaT, dtype=numpy.float64,requirements=['C','W']) dOdJT= numpy.require(dOdJT,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']) #Run the C code actionAngleTorus_JacFunc(ctypes.c_double(jr), ctypes.c_double(jphi), ctypes.c_double(jz), ctypes.c_int(len(angler)), angler, anglephi, anglez, ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(tol), ctypes.c_double(dJ), R,vR,vT,z,vz,phi, dxvOdJaT, dOdJT, Omegar,Omegaphi,Omegaz, ctypes.byref(flag)) #Reset input arrays if f_cont[0]: angler= numpy.asfortranarray(angler) if f_cont[1]: anglephi= numpy.asfortranarray(anglephi) if f_cont[2]: anglez= numpy.asfortranarray(anglez) dxvOdJaT= numpy.reshape(dxvOdJaT,(len(angler),6,6),order='C') dxvOdJa= numpy.swapaxes(dxvOdJaT,1,2) return (R,vR,vT,z,vz,phi, dxvOdJa, dOdJT.reshape((3,3)).T, Omegar[0],Omegaphi[0],Omegaz[0], flag.value)
def actionAngleStaeckel_c(pot,delta,R,vR,vT,z,vz,u0=None): """ 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) 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=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)) 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_double, 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']) #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, 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) return (jr,jz,err.value)
def actionAngleTorus_xvFreqs_c(pot,jr,jphi,jz, angler,anglephi,anglez, tol=0.003): """ NAME: actionAngleTorus_xvFreqs_c PURPOSE: compute configuration (x,v) and frequencies of a set of angles on a single torus INPUT: pot - Potential object or list thereof jr - radial action (scalar) jphi - azimuthal action (scalar) jz - vertical action (scalar) angler - radial angle (array [N]) anglephi - azimuthal angle (array [N]) anglez - vertical angle (array [N]) tol= (0.003) goal for |dJ|/|J| along the torus OUTPUT: (R,vR,vT,z,vz,phi,Omegar,Omegaphi,Omegaz,flag) HISTORY: 2015-08-05/07 - Written - Bovy (UofT) """ #Parse the potential npot, pot_type, pot_args= _parse_pot(pot,potfortorus=True) #Set up result arrays R= numpy.empty(len(angler)) vR= numpy.empty(len(angler)) vT= numpy.empty(len(angler)) z= numpy.empty(len(angler)) vz= numpy.empty(len(angler)) phi= numpy.empty(len(angler)) Omegar= numpy.empty(1) Omegaphi= numpy.empty(1) Omegaz= numpy.empty(1) flag= ctypes.c_int(0) #Set up the C code ndarrayFlags= ('C_CONTIGUOUS','WRITEABLE') actionAngleTorus_xvFreqsFunc= _lib.actionAngleTorus_xvFreqs actionAngleTorus_xvFreqsFunc.argtypes=\ [ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_int, 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), ndpointer(dtype=numpy.float64,flags=ndarrayFlags), ctypes.POINTER(ctypes.c_int)] #Array requirements, first store old order f_cont= [angler.flags['F_CONTIGUOUS'], anglephi.flags['F_CONTIGUOUS'], anglez.flags['F_CONTIGUOUS']] 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']) 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']) phi= numpy.require(phi,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']) #Run the C code actionAngleTorus_xvFreqsFunc(ctypes.c_double(jr), ctypes.c_double(jphi), ctypes.c_double(jz), ctypes.c_int(len(angler)), angler, anglephi, anglez, ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(tol), R,vR,vT,z,vz,phi, Omegar,Omegaphi,Omegaz, ctypes.byref(flag)) #Reset input arrays if f_cont[0]: angler= numpy.asfortranarray(angler) if f_cont[1]: anglephi= numpy.asfortranarray(anglephi) if f_cont[2]: anglez= numpy.asfortranarray(anglez) return (R,vR,vT,z,vz,phi,Omegar[0],Omegaphi[0],Omegaz[0],flag.value)
def actionAngleAdiabatic_c(pot, gamma, R, vR, vT, z, vz): """ NAME: actionAngleAdiabatic_c PURPOSE: Use C to calculate actions using the adiabatic approximation INPUT: pot - Potential or list of such instances gamma - as in Lz -> Lz+\gamma * J_z R, vR, vT, z, vz - coordinates (arrays) OUTPUT: (jr,jz,err) jr,jz : array, shape (len(R)) err - non-zero if error occured HISTORY: 2012-12-10 - Written - Bovy (IAS) """ #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)) err = ctypes.c_int(0) #Set up the C code ndarrayFlags = ('C_CONTIGUOUS', 'WRITEABLE') actionAngleAdiabatic_actionsFunc = _lib.actionAngleAdiabatic_actions actionAngleAdiabatic_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), 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), 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'] ] 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']) jr = numpy.require(jr, dtype=numpy.float64, requirements=['C', 'W']) jz = numpy.require(jz, dtype=numpy.float64, requirements=['C', 'W']) #Run the C code actionAngleAdiabatic_actionsFunc(len(R), R, vR, vT, z, vz, ctypes.c_int(npot), pot_type, pot_args, ctypes.c_double(gamma), 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) return (jr, jz, err.value)
def actionAngleFreqAngleStaeckel_c(pot,delta,R,vR,vT,z,vz,phi, u0=None,order=10): """ 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) u0= (None) if set, u0 to use order= (10) order of Gauss-Legendre integration of the relevant integrals 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=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)) 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_int, 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), 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']) 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_int(ndelta), delta, ctypes.c_int(order), 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) if f_cont[6]: delta= numpy.asfortranarray(delta) 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)