def test_freq_in_kmskpc(): #Test the scaling, as 1/time, should scale as velocity/position vofid, rofid = 200., 8. assert numpy.fabs(2. * bovy_conversion.freq_in_kmskpc(vofid, rofid) / bovy_conversion.freq_in_kmskpc(2. * vofid, rofid) - 1. ) < 10.**-10., 'freq_in_kmskpc did not work as expected' assert numpy.fabs(.5 * bovy_conversion.freq_in_kmskpc(vofid, rofid) / bovy_conversion.freq_in_kmskpc(vofid, 2 * rofid) - 1. ) < 10.**-10., 'freq_in_kmskpc did not work as expected' return None
def custom_sample_aAt(sdf,n): """Custom time and frequency sampling based on Jason's investigations of Denis' simulations""" # Sample pericenter vs. continuous w= 0.28 atperi= numpy.random.binomial(1,1.-w,size=n) # Setup output dO1s= numpy.zeros(n) dt= numpy.zeros(n) # First go through the pericenter ones: # find all of the pericenter passages up to tdisrupt nperi= sdf._tdisrupt/sdf._progenitor_Omega[0]+2 tps= sdf._progenitor_angle[0]/sdf._progenitor_Omega[0]\ +numpy.arange(nperi)*2.*numpy.pi/sdf._progenitor_Omega[0] tps= tps[tps < sdf._tdisrupt] # Sample these with a linearly-increasing probability dt[atperi==1]= tps[numpy.random.choice(len(tps), size=numpy.sum(atperi), p=tps/numpy.sum(tps))] # Generate frequencies from the broad Gaussian dO1s[atperi==1]= numpy.random.normal(size=numpy.sum(atperi))\ *0.049+0.306 # Next do the continuous part dt[atperi==0]= (numpy.random.uniform(size=n-numpy.sum(atperi)))**(1./2.)\ *sdf._tdisrupt dO1s[atperi==0]= numpy.random.normal(size=n-numpy.sum(atperi))\ *0.023+0.243 # Put everything together and rotate etc. dO1s/= bovy_conversion.freq_in_kmskpc(sdf._vo,sdf._ro) dO1s= numpy.array(dO1s)*sdf._sigMeanSign dO2s= numpy.random.normal(size=n)*numpy.sqrt(sdf._sortedSigOEig[1]) dO3s= numpy.random.normal(size=n)*numpy.sqrt(sdf._sortedSigOEig[0]) #Rotate into dOs in R,phi,z coordinates dO= numpy.vstack((dO3s,dO2s,dO1s)) dO= numpy.dot(sdf._sigomatrixEig[1][:,sdf._sigomatrixEigsortIndx], dO) Om= dO+numpy.tile(sdf._progenitor_Omega.T,(n,1)).T #Also generate angles da= numpy.random.normal(size=(3,n))*sdf._sigangle #Integrate the orbits relative to the progenitor da+= dO*numpy.tile(dt,(3,1)) angle= da+numpy.tile(sdf._progenitor_angle.T,(n,1)).T return (Om,angle,dt)
def custom_sample_aAt(sdf, n): """Custom time and frequency sampling based on Jason's investigations of Denis' simulations""" # Sample pericenter vs. continuous w = 0.28 atperi = numpy.random.binomial(1, 1. - w, size=n) # Setup output dO1s = numpy.zeros(n) dt = numpy.zeros(n) # First go through the pericenter ones: # find all of the pericenter passages up to tdisrupt nperi = sdf._tdisrupt / sdf._progenitor_Omega[0] + 2 tps= sdf._progenitor_angle[0]/sdf._progenitor_Omega[0]\ +numpy.arange(nperi)*2.*numpy.pi/sdf._progenitor_Omega[0] tps = tps[tps < sdf._tdisrupt] # Sample these with a linearly-increasing probability dt[atperi == 1] = tps[numpy.random.choice(len(tps), size=numpy.sum(atperi), p=tps / numpy.sum(tps))] # Generate frequencies from the broad Gaussian dO1s[atperi==1]= numpy.random.normal(size=numpy.sum(atperi))\ *0.049+0.306 # Next do the continuous part dt[atperi==0]= (numpy.random.uniform(size=n-numpy.sum(atperi)))**(1./2.)\ *sdf._tdisrupt dO1s[atperi==0]= numpy.random.normal(size=n-numpy.sum(atperi))\ *0.023+0.243 # Put everything together and rotate etc. dO1s /= bovy_conversion.freq_in_kmskpc(sdf._vo, sdf._ro) dO1s = numpy.array(dO1s) * sdf._sigMeanSign dO2s = numpy.random.normal(size=n) * numpy.sqrt(sdf._sortedSigOEig[1]) dO3s = numpy.random.normal(size=n) * numpy.sqrt(sdf._sortedSigOEig[0]) #Rotate into dOs in R,phi,z coordinates dO = numpy.vstack((dO3s, dO2s, dO1s)) dO = numpy.dot(sdf._sigomatrixEig[1][:, sdf._sigomatrixEigsortIndx], dO) Om = dO + numpy.tile(sdf._progenitor_Omega.T, (n, 1)).T #Also generate angles da = numpy.random.normal(size=(3, n)) * sdf._sigangle #Integrate the orbits relative to the progenitor da += dO * numpy.tile(dt, (3, 1)) angle = da + numpy.tile(sdf._progenitor_angle.T, (n, 1)).T return (Om, angle, dt)
def __init__(self,amp=1.,pot=None,omega=1.,pa=0.,ro=None,vo=None): """ NAME: __init__ PURPOSE: initialize a SolidBodyRotationWrapper Potential INPUT: amp - amplitude to be applied to the potential (default: 1.) pot - Potential instance or list thereof; this potential is made to rotate around the z axis by the wrapper omega= (1.) the pattern speed (can be a Quantity) pa= (0.) the position angle (can be a Quantity) OUTPUT: (none) HISTORY: 2017-08-22 - Started - Bovy (UofT) """ WrapperPotential.__init__(self,amp=amp,pot=pot,ro=ro,vo=vo) if _APY_LOADED and isinstance(omega,units.Quantity): omega= omega.to(units.km/units.s/units.kpc).value\ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) if _APY_LOADED and isinstance(pa,units.Quantity): pa= pa.to(units.rad).value self._omega= omega self._pa= pa self.hasC= True self.hasC_dxdv= True
def __init__(self,amp=1.,pot=None,omega=1.,pa=0.,ro=None,vo=None): """ NAME: __init__ PURPOSE: initialize a SolidBodyRotationWrapper Potential INPUT: amp - amplitude to be applied to the potential (default: 1.) pot - Potential instance or list thereof; this potential is made to rotate around the z axis by the wrapper omega= (1.) the pattern speed (can be a Quantity) pa= (0.) the position angle (can be a Quantity) OUTPUT: (none) HISTORY: 2017-08-22 - Started - Bovy (UofT) """ if _APY_LOADED and isinstance(omega,units.Quantity): omega= omega.to(units.km/units.s/units.kpc).value\ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) if _APY_LOADED and isinstance(pa,units.Quantity): pa= pa.to(units.rad).value self._omega= omega self._pa= pa self.hasC= True self.hasC_dxdv= True
def __init__(self, *args, **kwargs): """ NAME: __init__ PURPOSE: initialize an actionAngleHarmonic object INPUT: omega= frequencies (can be Quantity) ro= distance from vantage point to GC (kpc; can be Quantity) vo= circular velocity at ro (km/s; can be Quantity) OUTPUT: instance HISTORY: 2018-04-08 - Written - Bovy (Uoft) """ actionAngle.__init__(self, ro=kwargs.get('ro', None), vo=kwargs.get('vo', None)) if not 'omega' in kwargs: #pragma: no cover raise IOError("Must specify omega= for actionAngleHarmonic") omega = kwargs.get('omega') if _APY_LOADED and isinstance(omega, units.Quantity): omega= omega.to(units.km/units.s/units.kpc).value \ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) self._omega = omega return None
def __init__(self,amp=1.,omegas=0.65,A=-0.035, alpha=-7.,m=2,gamma=math.pi/4.,p=None, sigma=1.,to=0.,ro=None,vo=None): """ NAME: __init__ PURPOSE: initialize a transient logarithmic spiral potential localized around to INPUT: amp - amplitude to be applied to the potential (default: 1., A below) gamma - angle between sun-GC line and the line connecting the peak of the spiral pattern at the Solar radius (in rad; default=45 degree; can be Quantity) A - amplitude (alpha*potential-amplitude; default=0.035; can be Quantity) omegas= - pattern speed (default=0.65; can be Quantity) m= number of arms to= time at which the spiral peaks (can be Quantity) sigma= "spiral duration" (sigma in Gaussian amplitude; can be Quantity) Either provide: a) alpha= b) p= pitch angle (rad; can be Quantity) OUTPUT: (none) HISTORY: 2011-03-27 - Started - Bovy (NYU) """ planarPotential.__init__(self,amp=amp,ro=ro,vo=vo) if _APY_LOADED and isinstance(gamma,units.Quantity): gamma= gamma.to(units.rad).value if _APY_LOADED and isinstance(p,units.Quantity): p= p.to(units.rad).value if _APY_LOADED and isinstance(A,units.Quantity): A= A.to(units.km**2/units.s**2).value/self._vo**2. if _APY_LOADED and isinstance(omegas,units.Quantity): omegas= omegas.to(units.km/units.s/units.kpc).value\ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) if _APY_LOADED and isinstance(to,units.Quantity): to= to.to(units.Gyr).value\ /bovy_conversion.time_in_Gyr(self._vo,self._ro) if _APY_LOADED and isinstance(sigma,units.Quantity): sigma= sigma.to(units.Gyr).value\ /bovy_conversion.time_in_Gyr(self._vo,self._ro) self._omegas= omegas self._A= A self._m= m self._gamma= gamma self._to= to self._sigma2= sigma**2. if not p is None: self._alpha= self._m/math.tan(p) else: self._alpha= alpha self.hasC= True
def __init__(self,amp=1.,a=4.,b=0.,c=1.,normalize=False, pa=0.4,omegab=1.8,ro=None,vo=None): """ NAME: __init__ PURPOSE: initialize a softened-needle bar potential INPUT: amp - amplitude to be applied to the potential (default: 1); can be a Quantity with units of mass a= (4.) Bar half-length (can be Quantity) b= (1.) Triaxial softening length (can be Quantity) c= (1.) Prolate softening length (can be Quantity) pa= (0.4) The position angle of the x axis (rad or Quantity) omegab= (1.8) Pattern speed (can be Quantity) normalize - if True, normalize such that vc(1.,0.)=1., or, if given as a number, such that the force is this fraction of the force necessary to make vc(1.,0.)=1. ro=, vo= distance and velocity scales for translation into internal units (default from configuration file) OUTPUT: (none) HISTORY: 2016-11-02 - Started - Bovy (UofT) """ Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='mass') if _APY_LOADED and isinstance(a,units.Quantity): a= a.to(units.kpc).value/self._ro if _APY_LOADED and isinstance(b,units.Quantity): b= b.to(units.kpc).value/self._ro if _APY_LOADED and isinstance(c,units.Quantity): c= c.to(units.kpc).value/self._ro if _APY_LOADED and isinstance(pa,units.Quantity): pa= pa.to(units.rad).value if _APY_LOADED and isinstance(omegab,units.Quantity): omegab= omegab.to(units.km/units.s/units.kpc).value\ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) self._a= a self._b= b self._c2= c**2. self._pa= pa self._omegab= omegab self._force_hash= None self.hasC= True self.hasC_dxdv= False if normalize or \ (isinstance(normalize,(int,float)) \ and not isinstance(normalize,bool)): #pragma: no cover self.normalize(normalize) self.isNonAxi= True return None
import numpy as np import matplotlib.pylab as plt import galpy from galpy.util import bovy_conversion from nemo_funcs import tail_cut R0 = 8. V0 = 220. fact = bovy_conversion.freq_in_Gyr(220., 8.) fact2 = bovy_conversion.freq_in_kmskpc(220., 8.) #prog = np.loadtxt("/Users/anita/dyn-modeling-streams-2014/sim/test.dat", delimiter=',') #tail = np.loadtxt("/Users/anita/Desktop/Meeting_2/tail_concatenated_final.txt") tail = np.loadtxt("/home/bahmanyar/Github/AST1501/Codes/concatenated_2.0.txt") tail = tail.T #JR_p, Lz_p, Jz_p, omegaR_p, omega_phi_p, omegaz_p, thetaR_p, theta_phi_p, thetaz_p = prog[:,0], prog[:,1], prog[:,2], prog[:,3], prog[:,4], prog[:,5], prog[:,6], prog[:,7], prog[:,8] JR_t, Lz_t, Jz_t, omegaR_t, omega_phi_t, omegaz_t, thetaR_t, theta_phi_t, thetaz_t = tail[:,0], tail[:,1], tail[:,2], tail[:,3], tail[:,4], tail[:,5], tail[:,6], tail[:,7], tail[:,8] indx_t = tail_cut(tail) #indx_p = tail_cut(prog) # Tail omegaR_t, omega_phi_t, omegaz_t, = tail[indx_t,3], tail[indx_t,4], tail[indx_t,5] JR_t, Lz_t, Jz_t = tail[indx_t,0], tail[indx_t,1], tail[indx_t,2] thetaR_t, theta_phi_t, thetaz_t = tail[indx_t,6], tail[indx_t,7], tail[indx_t,8] thetaR_t = (np.pi+(thetaR_t-np.median(tail[:,6]))) % (2.*np.pi) theta_phi_t = (np.pi+(theta_phi_t-np.median(tail[:,7]))) % (2.*np.pi)
def test_freq_in_kmskpc(): #Test the scaling, as 1/time, should scale as velocity/position vofid, rofid= 200., 8. assert numpy.fabs(2.*bovy_conversion.freq_in_kmskpc(vofid,rofid)/bovy_conversion.freq_in_kmskpc(2.*vofid,rofid)-1.) < 10.**-10., 'freq_in_kmskpc did not work as expected' assert numpy.fabs(.5*bovy_conversion.freq_in_kmskpc(vofid,rofid)/bovy_conversion.freq_in_kmskpc(vofid,2*rofid)-1.) < 10.**-10., 'freq_in_kmskpc did not work as expected' return None
def __init__(self, amp=1, ro=None, vo=None, amp_units='density', N=2, alpha=0.2, r_ref=1, phi_ref=0, Rs=0.3, H=0.125, omega=0, Cs=[1]): """ NAME: __init__ PURPOSE: initialize a spiral arms potential INPUT: :amp: amplitude to be applied to the potential (default: 1); can be a Quantity with units of density. (:math:`amp = 4 \\pi G \\rho_0`) :ro: distance scales for translation into internal units (default from configuration file) :vo: velocity scales for translation into internal units (default from configuration file) :N: number of spiral arms :alpha: pitch angle of the logarithmic spiral arms in radians (can be Quantity) :r_ref: fiducial radius where :math:`\\rho = \\rho_0` (:math:`r_0` in the paper by Cox and Gomez) (can be Quantity) :phi_ref: reference angle (:math:`\\phi_p(r_0)` in the paper by Cox and Gomez) (can be Quantity) :Rs: radial scale length of the drop-off in density amplitude of the arms (can be Quantity) :H: scale height of the stellar arm perturbation (can be Quantity) :Cs: list of constants multiplying the :math:`\cos(n \\gamma)` terms :omega: rotational pattern speed of the spiral arms (can be Quantity) OUTPUT: (none) HISTORY: Started - 2017-05-12 Jack Hong (UBC) Completed - 2017-07-04 Jack Hong (UBC) """ Potential.__init__(self, amp=amp, ro=ro, vo=vo, amp_units=amp_units) if _APY_LOADED: if isinstance(alpha, units.Quantity): alpha = alpha.to(units.rad).value if isinstance(r_ref, units.Quantity): r_ref = r_ref.to(units.kpc).value / self._ro if isinstance(phi_ref, units.Quantity): phi_ref = phi_ref.to(units.rad).value if isinstance(Rs, units.Quantity): Rs = Rs.to(units.kpc).value / self._ro if isinstance(H, units.Quantity): H = H.to(units.kpc).value / self._ro if isinstance(omega, units.Quantity): omega = omega.to(units.km / units.s / units.kpc).value \ / bovy_conversion.freq_in_kmskpc(self._vo, self._ro) self._N = -N # trick to flip to left handed coordinate system; flips sign for phi and phi_ref, but also alpha. self._alpha = -alpha # we don't want sign for alpha to change, so flip alpha. (see eqn. 3 in the paper) self._sin_alpha = np.sin(-alpha) self._tan_alpha = np.tan(-alpha) self._r_ref = r_ref self._phi_ref = phi_ref self._Rs = Rs self._H = H self._Cs = np.array(Cs) self._ns = np.arange(1, len(Cs) + 1) self._omega = omega self._rho0 = 1 / (4 * np.pi) self._HNn = self._H * self._N * self._ns self.isNonAxi = True # Potential is not axisymmetric self.hasC = True # Potential has C implementation to speed up orbit integrations self.hasC_dxdv = True # Potential has C implementation of second derivatives
def __init__(self, amp=1., omegas=0.65, A=-0.035, alpha=-7., m=2, gamma=math.pi / 4., p=None, tform=None, tsteady=None, ro=None, vo=None): """ NAME: __init__ PURPOSE: initialize a logarithmic spiral potential INPUT: amp - amplitude to be applied to the potential (default: 1., A below) gamma - angle between sun-GC line and the line connecting the peak of the spiral pattern at the Solar radius (in rad; default=45 degree; or can be Quantity) A - amplitude (alpha*potential-amplitude; default=0.035; can be Quantity omegas= - pattern speed (default=0.65; can be Quantity) m= number of arms Either provide: a) alpha= b) p= pitch angle (rad; can be Quantity) tform - start of spiral growth / spiral period (default: -Infinity) tsteady - time from tform at which the spiral is fully grown / spiral period (default: 2 periods) OUTPUT: (none) HISTORY: 2011-03-27 - Started - Bovy (NYU) """ planarPotential.__init__(self, amp=amp, ro=ro, vo=vo) if _APY_LOADED and isinstance(gamma, units.Quantity): gamma = gamma.to(units.rad).value if _APY_LOADED and isinstance(p, units.Quantity): p = p.to(units.rad).value if _APY_LOADED and isinstance(A, units.Quantity): A = A.to(units.km**2 / units.s**2).value / self._vo**2. if _APY_LOADED and isinstance(omegas, units.Quantity): omegas= omegas.to(units.km/units.s/units.kpc).value\ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) self._omegas = omegas self._A = A self._m = m self._gamma = gamma if not p is None: self._alpha = self._m / math.tan(p) else: self._alpha = alpha self._ts = 2. * math.pi / self._omegas if not tform is None: self._tform = tform * self._ts else: self._tform = None if not tsteady is None: self._tsteady = self._tform + tsteady * self._ts else: if self._tform is None: self._tsteady = None else: self._tsteady = self._tform + 2. * self._ts self.hasC = True
def __init__(self,amp=1.,omegas=0.65,A=-0.035, alpha=-7.,m=2,gamma=math.pi/4.,p=None, tform=None,tsteady=None,ro=None,vo=None): """ NAME: __init__ PURPOSE: initialize a logarithmic spiral potential INPUT: amp - amplitude to be applied to the potential (default: 1., A below) gamma - angle between sun-GC line and the line connecting the peak of the spiral pattern at the Solar radius (in rad; default=45 degree; or can be Quantity) A - amplitude (alpha*potential-amplitude; default=0.035; can be Quantity omegas= - pattern speed (default=0.65; can be Quantity) m= number of arms Either provide: a) alpha= b) p= pitch angle (rad; can be Quantity) tform - start of spiral growth / spiral period (default: -Infinity) tsteady - time from tform at which the spiral is fully grown / spiral period (default: 2 periods) OUTPUT: (none) HISTORY: 2011-03-27 - Started - Bovy (NYU) """ planarPotential.__init__(self,amp=amp,ro=ro,vo=vo) if _APY_LOADED and isinstance(gamma,units.Quantity): gamma= gamma.to(units.rad).value if _APY_LOADED and isinstance(p,units.Quantity): p= p.to(units.rad).value if _APY_LOADED and isinstance(A,units.Quantity): A= A.to(units.km**2/units.s**2).value/self._vo**2. if _APY_LOADED and isinstance(omegas,units.Quantity): omegas= omegas.to(units.km/units.s/units.kpc).value\ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) self._omegas= omegas self._A= A self._m= m self._gamma= gamma if not p is None: self._alpha= self._m/math.tan(p) else: self._alpha= alpha self._ts= 2.*math.pi/self._omegas if not tform is None: self._tform= tform*self._ts else: self._tform= None if not tsteady is None: self._tsteady= self._tform+tsteady*self._ts else: if self._tform is None: self._tsteady= None else: self._tsteady= self._tform+2.*self._ts self.hasC= True
def __init__(self,amp=105/96*3.3*10**10*units.Msun,a=1.,n=2,b=0.35,c=0.2375,omegab=0.001, pa=0.,normalize=False,ro=None,vo=None): """ NAME: __init__ PURPOSE: initialize a triaxial two-power-density potential INPUT: amp - amplitude to be applied to the potential (default: 1); can be a Quantity with units of mass or Gxmass a - scale radius (can be Quantity) n - power of Ferrers density (n > 0) b - y-to-x axis ratio of the density c - z-to-x axis ratio of the density omegab - rotation speed of the bar (can be Quantity) pa= (None) If set, the position angle of the x axis (rad or Quantity) normalize - if True, normalize such that vc(1.,0.)=1., or, if given as a number, such that the force is this fraction of the force necessary to make vc(1.,0.)=1. ro=, vo= distance and velocity scales for translation into internal units (default from configuration file) OUTPUT: (none) HISTORY: 2016-06-30 - Started - Semyeong Oh """ Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='mass') if _APY_LOADED and isinstance(a,units.Quantity): a= a.to(units.kpc).value/self._ro if _APY_LOADED and isinstance(omegab,units.Quantity): omegab= omegab.to(units.km/units.s/units.kpc).value\ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) if _APY_LOADED and isinstance(pa,units.Quantity): pa= pa.to(units.rad).value self.a= a self._scale= self.a if n <= 0: raise IOError('FerrersPotential requires n > 0') self.n= n self._b= b self._c= c self._omegab= omegab self._a2= self.a*a self._b2= self._b*b self._c2= self._c*c self._force_hash= None self._pa = pa if normalize or \ (isinstance(normalize,(int,float)) \ and not isinstance(normalize,bool)): #pragma: no cover self.normalize(normalize) if np.fabs(self._b-1.) > 10.**-10.: self.isNonAxi= True return None
def __init__(self, amp=1., a=1., n=2, b=0.35, c=0.2375, omegab=0., pa=0., normalize=False, ro=None, vo=None): """ NAME: __init__ PURPOSE: initialize a Ferrers potential INPUT: amp - total mass of the ellipsoid determines the amplitude of the potential; can be a Quantity with units of mass or Gxmass a - scale radius (can be Quantity) n - power of Ferrers density (n > 0) b - y-to-x axis ratio of the density c - z-to-x axis ratio of the density omegab - rotation speed of the ellipsoid (can be Quantity) pa= (None) If set, the position angle of the x axis (rad or Quantity) normalize - if True, normalize such that vc(1.,0.)=1., or, if given as a number, such that the force is this fraction of the force necessary to make vc(1.,0.)=1. ro=, vo= distance and velocity scales for translation into internal units (default from configuration file) OUTPUT: (none) """ Potential.__init__(self, amp=amp, ro=ro, vo=vo, amp_units='mass') if _APY_LOADED and isinstance(a, units.Quantity): a = a.to(units.kpc).value / self._ro if _APY_LOADED and isinstance(omegab, units.Quantity): omegab= omegab.to(units.km/units.s/units.kpc).value\ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) if _APY_LOADED and isinstance(pa, units.Quantity): pa = pa.to(units.rad).value self.a = a self._scale = self.a if n <= 0: raise ValueError('FerrersPotential requires n > 0') self.n = n self._b = b self._c = c self._omegab = omegab self._a2 = self.a**2 self._b2 = self._b**2. self._c2 = self._c**2. self._force_hash = None self._pa = pa self._rhoc_M = gamma(n + 2.5) / gamma(n + 1) / np.pi**1.5 / a**3 / b / c if normalize or \ (isinstance(normalize,(int,float)) \ and not isinstance(normalize,bool)): #pragma: no cover self.normalize(normalize) if np.fabs(self._b - 1.) > 10.**-10.: self.isNonAxi = True return None
def __init__(self,amp=1.,a=1.,n=2,b=0.35,c=0.2375,omegab=0., pa=0.,normalize=False,ro=None,vo=None): """ NAME: __init__ PURPOSE: initialize a Ferrers potential INPUT: amp - total mass of the ellipsoid determines the amplitude of the potential; can be a Quantity with units of mass or Gxmass a - scale radius (can be Quantity) n - power of Ferrers density (n > 0) b - y-to-x axis ratio of the density c - z-to-x axis ratio of the density omegab - rotation speed of the ellipsoid (can be Quantity) pa= (None) If set, the position angle of the x axis (rad or Quantity) normalize - if True, normalize such that vc(1.,0.)=1., or, if given as a number, such that the force is this fraction of the force necessary to make vc(1.,0.)=1. ro=, vo= distance and velocity scales for translation into internal units (default from configuration file) OUTPUT: (none) """ Potential.__init__(self,amp=amp,ro=ro,vo=vo,amp_units='mass') if _APY_LOADED and isinstance(a,units.Quantity): a= a.to(units.kpc).value/self._ro if _APY_LOADED and isinstance(omegab,units.Quantity): omegab= omegab.to(units.km/units.s/units.kpc).value\ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) if _APY_LOADED and isinstance(pa,units.Quantity): pa= pa.to(units.rad).value self.a= a self._scale= self.a if n <= 0: raise ValueError('FerrersPotential requires n > 0') self.n= n self._b= b self._c= c self._omegab= omegab self._a2= self.a**2 self._b2= self._b**2. self._c2= self._c**2. self._force_hash= None self._pa = pa self._rhoc_M = gamma(n+2.5)/gamma(n+1) / np.pi**1.5/a**3/b/c if normalize or \ (isinstance(normalize,(int,float)) \ and not isinstance(normalize,bool)): #pragma: no cover self.normalize(normalize) if np.fabs(self._b-1.) > 10.**-10.: self.isNonAxi= True return None
def __init__(self,amp=1.,omegab=None,rb=None,chi=0.8, rolr=0.9,barphi=25.*_degtorad, tform=-4.,tsteady=None,beta=0., alpha=0.01,Af=None,ro=None,vo=None): """ NAME: __init__ PURPOSE: initialize a Dehnen bar potential INPUT: amp - amplitude to be applied to the potential (default: 1., see alpha or Ab below) barphi - angle between sun-GC line and the bar's major axis (in rad; default=25 degree; or can be Quantity)) tform - start of bar growth / bar period (default: -4) tsteady - time from tform at which the bar is fully grown / bar period (default: -tform/2, st the perturbation is fully grown at tform/2) Either provide: a) rolr - radius of the Outer Lindblad Resonance for a circular orbit (can be Quantity) chi - fraction R_bar / R_CR (corotation radius of bar) alpha - relative bar strength (default: 0.01) beta - power law index of rotation curve (to calculate OLR, etc.) b) omegab - rotation speed of the bar (can be Quantity) rb - bar radius (can be Quantity) Af - bar strength (can be Quantity) OUTPUT: (none) HISTORY: 2010-11-24 - Started - Bovy (NYU) 2017-06-23 - Converted to 3D following Monari et al. (2016) - Bovy (UofT/CCA) """ Potential.__init__(self,amp=amp,ro=ro,vo=vo) if _APY_LOADED and isinstance(barphi,units.Quantity): barphi= barphi.to(units.rad).value if _APY_LOADED and isinstance(rolr,units.Quantity): rolr= rolr.to(units.kpc).value/self._ro if _APY_LOADED and isinstance(rb,units.Quantity): rb= rb.to(units.kpc).value/self._ro if _APY_LOADED and isinstance(omegab,units.Quantity): omegab= omegab.to(units.km/units.s/units.kpc).value\ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) if _APY_LOADED and isinstance(Af,units.Quantity): Af= Af.to(units.km**2/units.s**2).value/self._vo**2. self.hasC= True self.hasC_dxdv= True self.isNonAxi= True self._barphi= barphi if omegab is None: self._rolr= rolr self._chi= chi self._beta= beta #Calculate omegab and rb self._omegab= 1./((self._rolr**(1.-self._beta))/(1.+numpy.sqrt((1.+self._beta)/2.))) self._rb= self._chi*self._omegab**(1./(self._beta-1.)) self._alpha= alpha self._af= self._alpha/3./self._rb**3. else: self._omegab= omegab self._rb= rb self._af= Af self._tb= 2.*numpy.pi/self._omegab self._tform= tform*self._tb if tsteady is None: self._tsteady= self._tform/2. else: self._tsteady= self._tform+tsteady*self._tb
def __init__(self, amp=1., omegas=0.65, A=-0.035, alpha=-7., m=2, gamma=math.pi / 4., p=None, sigma=1., to=0., ro=None, vo=None): """ NAME: __init__ PURPOSE: initialize a transient logarithmic spiral potential localized around to INPUT: amp - amplitude to be applied to the potential (default: 1., A below) gamma - angle between sun-GC line and the line connecting the peak of the spiral pattern at the Solar radius (in rad; default=45 degree; can be Quantity) A - amplitude (alpha*potential-amplitude; default=0.035; can be Quantity) omegas= - pattern speed (default=0.65; can be Quantity) m= number of arms to= time at which the spiral peaks (can be Quantity) sigma= "spiral duration" (sigma in Gaussian amplitude; can be Quantity) Either provide: a) alpha= b) p= pitch angle (rad; can be Quantity) OUTPUT: (none) HISTORY: 2011-03-27 - Started - Bovy (NYU) """ planarPotential.__init__(self, amp=amp, ro=ro, vo=vo) if _APY_LOADED and isinstance(gamma, units.Quantity): gamma = gamma.to(units.rad).value if _APY_LOADED and isinstance(p, units.Quantity): p = p.to(units.rad).value if _APY_LOADED and isinstance(A, units.Quantity): A = A.to(units.km**2 / units.s**2).value / self._vo**2. if _APY_LOADED and isinstance(omegas, units.Quantity): omegas= omegas.to(units.km/units.s/units.kpc).value\ /bovy_conversion.freq_in_kmskpc(self._vo,self._ro) if _APY_LOADED and isinstance(to, units.Quantity): to= to.to(units.Gyr).value\ /bovy_conversion.time_in_Gyr(self._vo,self._ro) if _APY_LOADED and isinstance(sigma, units.Quantity): sigma= sigma.to(units.Gyr).value\ /bovy_conversion.time_in_Gyr(self._vo,self._ro) self._omegas = omegas self._A = A self._m = m self._gamma = gamma self._to = to self._sigma2 = sigma**2. if not p is None: self._alpha = self._m / math.tan(p) else: self._alpha = alpha self.hasC = True