def MWRfo(ldeg, bdeg, dkpc): b = bdeg * par.degtorad l = ldeg * par.degtorad Rskpc = par.Rskpc Vs = par.Vs conversion = par.conversion Rpkpc = par.Rpkpc(ldeg, bdeg, dkpc) zkpc = dkpc * math.sin(b) be = (dkpc / Rskpc) * math.cos(b) - math.cos(l) coslam = be * (Rskpc / Rpkpc) #rforce1 = evaluateRforces(MWPotential2014, Rpkpc/Rskpc,zkpc/Rskpc)*bovy_conversion.force_in_kmsMyr(Vs,Rskpc) #rfsun = evaluateRforces(MWPotential2014, Rskpc/Rskpc,0.0/Rskpc)*bovy_conversion.force_in_kmsMyr(Vs,Rskpc) rforce1 = evaluateRforces(MWPotential2014, Rpkpc / Rskpc, zkpc / Rskpc) * ( (Vs * 1000.)**2.) / (Rskpc * par.kpctom) #m/ss rfsun = evaluateRforces(MWPotential2014, Rskpc / Rskpc, 0.0 / Rskpc) * ( (Vs * 1000.)**2.) / (Rskpc * par.kpctom) #m/ss rf0 = rforce1 * coslam + rfsun * math.cos(l) #m/ss rf = rf0 * math.cos(b) / par.c # s-1 return rf
def estimateDeltaStaeckel(R,z,pot=None): """ NAME: estimateDeltaStaeckel PURPOSE: Estimate a good value for delta using eqn. (9) in Sanders (2012) INPUT: R,z = coordinates (if these are arrays, the median estimated delta is returned, i.e., if this is an orbit) pot= Potential instance or list thereof OUTPUT: delta HISTORY: 2013-08-28 - Written - Bovy (IAS) """ if pot is None: raise IOError("pot= needs to be set to a Potential instance or list thereof") if isinstance(R,nu.ndarray): delta2= nu.array([(z[ii]**2.-R[ii]**2. #eqn. (9) has a sign error +(3.*R[ii]*evaluatezforces(R[ii],z[ii],pot) -3.*z[ii]*evaluateRforces(R[ii],z[ii],pot) +R[ii]*z[ii]*(evaluateR2derivs(R[ii],z[ii],pot) -evaluatez2derivs(R[ii],z[ii],pot)))/evaluateRzderivs(R[ii],z[ii],pot)) for ii in range(len(R))]) indx= (delta2 < 0.)*(delta2 > -10.**-10.) delta2[indx]= 0. delta2= nu.median(delta2[True-nu.isnan(delta2)]) else: delta2= (z**2.-R**2. #eqn. (9) has a sign error +(3.*R*evaluatezforces(R,z,pot) -3.*z*evaluateRforces(R,z,pot) +R*z*(evaluateR2derivs(R,z,pot) -evaluatez2derivs(R,z,pot)))/evaluateRzderivs(R,z,pot)) if delta2 < 0. and delta2 > -10.**-10.: delta2= 0. return nu.sqrt(delta2)
def accmaps(npix=200): #First setup the potential, the following are the best-fit parameters from the Sec. 5 of our paper #params= numpy.array([-1.33663190049,0.998420232634,-3.49031638164,0.31949840593,-1.63965169376]) params= numpy.array([-1.33663190049,0.998420232634,-3.0736938150237028,0.31949840593,-1.63965169376]) #this has a scale height of 360 pc try: pot= setup_potential(params) except RuntimeError: #if this set of parameters gives a nonsense potential raise #Setup grid and output Rs= numpy.linspace(0.01,20.,npix)/_REFR0 Zs= numpy.linspace(0.,20.,npix)/_REFR0 accR_dm= numpy.empty((len(Rs),len(Zs))) accZ_dm= numpy.empty((len(Rs),len(Zs))) accR_baryon= numpy.empty((len(Rs),len(Zs))) accZ_baryon= numpy.empty((len(Rs),len(Zs))) #Calculate accelerations for ii in range(len(Rs)): for jj in range(len(Zs)): accR_dm[ii,jj]= potential.evaluateRforces(Rs[ii],Zs[jj],[pot[0]]) accZ_dm[ii,jj]= potential.evaluatezforces(Rs[ii],Zs[jj],[pot[0]]) accR_baryon[ii,jj]= potential.evaluateRforces(Rs[ii],Zs[jj],pot[1:]) accZ_baryon[ii,jj]= potential.evaluatezforces(Rs[ii],Zs[jj],pot[1:]) accR_dm*= bovy_conversion.force_in_10m13kms2(_REFV0*params[1],_REFR0) accZ_dm*= bovy_conversion.force_in_10m13kms2(_REFV0*params[1],_REFR0) accR_baryon*= bovy_conversion.force_in_10m13kms2(_REFV0*params[1],_REFR0) accZ_baryon*= bovy_conversion.force_in_10m13kms2(_REFV0*params[1],_REFR0) return (accR_dm,accZ_dm,accR_baryon,accZ_baryon,Rs,Zs)
def MWBHRfo(bdeg, ldeg, dkpc): b = bdeg * par.degtorad l = ldeg * par.degtorad Rskpc = par.Rskpc Vs = par.Vs conversion = par.conversion Rpkpc = Rpkpcfunc(dkpc, b, l, Rskpc) zkpc = dkpc * math.sin(b) be = (dkpc / Rskpc) * math.cos(b) - math.cos(l) coslam = be * (Rskpc / Rpkpc) MWPotential2014.append( KeplerPotential(amp=4 * 10**6. / bovy_conversion.mass_in_msol(Vs, Rskpc))) rforce1 = evaluateRforces(MWPotential2014, Rpkpc / Rskpc, zkpc / Rskpc) * bovy_conversion.force_in_kmsMyr( Vs, Rskpc) rfsun = evaluateRforces(MWPotential2014, Rskpc / Rskpc, 0.0 / Rskpc) * bovy_conversion.force_in_kmsMyr( Vs, Rskpc) #rf = (rforce1-rfsun)*conversion*math.cos(b) # s-1 rf0 = rforce1 * coslam + rfsun * math.cos(l) rf = rf0 * conversion * math.cos(b) # s-1 return rf
def _Rforce(self,R,z,phi=0.,t=0.): if self._interpRforce and self._enable_c: if isinstance(R,float): R= numpy.array([R]) if isinstance(z,float): z= numpy.array([z]) if self._zsym: return eval_force_c(self,R,numpy.fabs(z))[0] else: return eval_force_c(self,R,z)[0] from galpy.potential import evaluateRforces if self._interpRforce: if isinstance(R,float): return self._Rforce(numpy.array([R]),numpy.array([z])) out= numpy.empty_like(R) indx= (R >= self._rgrid[0])*(R <= self._rgrid[-1]) if numpy.sum(indx) > 0: if self._zsym: if self._logR: out[indx]= self._rforceInterp.ev(numpy.log(R[indx]),numpy.fabs(z[indx])) else: out[indx]= self._rforceInterp.ev(R[indx],numpy.fabs(z[indx])) else: if self._logR: out[indx]= self._rforceInterp.ev(numpy.log(R[indx]),z[indx]) else: out[indx]= self._rforceInterp.ev(R[indx],z[indx]) if numpy.sum(True-indx) > 0: out[True-indx]= evaluateRforces(R[True-indx], z[True-indx], self._origPot) return out else: return evaluateRforces(R,z,self._origPot)
def MWBHRfo(ldeg, bdeg, dkpc): b = bdeg * par.degtorad l = ldeg * par.degtorad Rskpc = par.Rskpc Vs = par.Vs conversion = par.conversion Rpkpc = par.Rpkpc(ldeg, bdeg, dkpc) zkpc = dkpc * math.sin(b) be = (dkpc / Rskpc) * math.cos(b) - math.cos(l) coslam = be * (Rskpc / Rpkpc) MWPotential2014BH = [ MWPotential2014, KeplerPotential(amp=4 * 10**6. / bovy_conversion.mass_in_msol(par.Vs, par.Rskpc)) ] rforce1 = evaluateRforces( MWPotential2014BH, Rpkpc / Rskpc, zkpc / Rskpc) * ( (Vs * 1000.)**2.) / (Rskpc * par.kpctom) #m/ss rfsun = evaluateRforces(MWPotential2014BH, Rskpc / Rskpc, 0.0 / Rskpc) * ( (Vs * 1000.)**2.) / (Rskpc * par.kpctom) #m/ss rf0 = rforce1 * coslam + rfsun * math.cos(l) #m/ss rf = rf0 * math.cos(b) / par.c # s-1 return rf
def fdotdotSB2cal(ldeg, bdeg, dkpc, mul, mub): Rskpc = par.Rskpc Vs = par.Vs conversion = par.conversion yrts = par.yrts c = par.c kpctom = par.kpctom Rs = Rskpc * kpctom mastorad = par.mastorad normpottoSI = par.normpottoSI normForcetoSI = par.normForcetoSI normjerktoSI = par.normjerktoSI b = bdeg * par.degtorad l = ldeg * par.degtorad Rpkpc = par.Rpkpc(ldeg, bdeg, dkpc) zkpc = par.z(ldeg, bdeg, dkpc) fex_pl = excGal.Expl(ldeg, bdeg, dkpc) fex_z = excGal.Exz(ldeg, bdeg, dkpc) fex_shk = Shk.Exshk(dkpc, mul, mub) fex_tot = fex_pl + fex_z + fex_shk #mub = mu_alpha #mas/yr #mul = mu_delta muT = (mub**2. + mul**2.)**0.5 #MWPotential2014= [MWPotential2014,KeplerPotential(amp=4*10**6./bovy_conversion.mass_in_msol(par.Vs,par.Rskpc))] MWPot = MWPotential2014 appl = evaluateRforces(MWPot, Rpkpc / Rskpc, zkpc / Rskpc) * normForcetoSI aspl = evaluateRforces(MWPot, Rskpc / Rskpc, 0.0 / Rskpc) * normForcetoSI apz = evaluatezforces(MWPot, Rpkpc / Rskpc, zkpc / Rskpc) * normForcetoSI be = (dkpc / Rskpc) * math.cos(b) - math.cos(l) coslam = be * (Rskpc / Rpkpc) res1 = 2. * (mastorad / yrts) * (mub * ((math.sin(b) / c) * (appl * coslam + aspl * math.cos(l)) - (math.cos(b) / c) * apz) - mul * (math.sin(l) / c) * (appl * (Rskpc / Rpkpc) - aspl)) res2 = 2. * fex_tot * (math.cos(b) * math.cos(l) * (aspl / c) + (mastorad / yrts) * mub * (1000. * Vs / c) * math.sin(b) * math.sin(l) - (mastorad / yrts) * mul * (1000. * Vs / c) * math.cos(l)) res = res1 + res2 return res
def force_pal5(pot: PotentialType, dpal5: float, ro: float = REFR0, vo: float = REFV0) -> Tuple[float]: """Return the force at Pal5. Parameters ---------- pot: Potential, list dpal5: float ro, vo: float Return ------ force: tuple [fx, fy, fz] """ from galpy import potential from galpy.util import bovy_coords # First compute the location based on the distance l5, b5 = bovy_coords.radec_to_lb(229.018, -0.124, degree=True) X5, Y5, Z5 = bovy_coords.lbd_to_XYZ(l5, b5, dpal5, degree=True) R5, p5, Z5 = bovy_coords.XYZ_to_galcencyl(X5, Y5, Z5, Xsun=ro, Zsun=0.025) args: list = [pot, R5 / ro, Z5 / ro] kws: dict = {"phi": p5, "use_physical": True, "ro": ro, "vo": vo} return ( potential.evaluateRforces(*args, **kws), potential.evaluatezforces(*args, **kws), potential.evaluatephiforces(*args, **kws), )
def calAcc(r, v) : N = r.shape[0] a = np.zeros([N,3]) dt_min = np.ones(N)*1e5*yrs dr = r dx = r[:,0] dy = r[:,1] dz = r[:,2] dv = v dr_gp = np.sqrt(dx*dx + dy*dy)/(r0*kpc) # galpy units dz_gp = dz/(r0*kpc) drNorm = np.linalg.norm(dr, axis = 1) acc = None if useNFW : m, rho, sigma = NFWmass( drNorm) acc = -G*m/(drNorm*drNorm)[:,np.newaxis]*dr/drNorm[:,np.newaxis] elif useHernquist: m, rho, sigma = hernquistmass( drNorm) acc = -G*m/(drNorm*drNorm)[:,np.newaxis]*dr/drNorm[:,np.newaxis] else : acc = np.zeros([dr_gp.size,3]) conv = 1e-13*1e5 for i, x_gp, y_gp, r_gp, z_gp in zip(range(dr_gp.size), dx/(r0*kpc), dy/(r0*kpc), dr_gp, dz_gp) : a = gp.evaluateRforces(MWpot,r_gp,z_gp)*bovy_conversion.force_in_10m13kms2(v0,r0)*conv acc[i,0] = a*x_gp/r_gp acc[i,1] = a*y_gp/r_gp acc[i,2] = gp.evaluatezforces(MWpot,r_gp,z_gp)*bovy_conversion.force_in_10m13kms2(v0,r0)*conv dt_rmin = np.min(drNorm/np.linalg.norm(dv, axis=1)) dt_amin = np.min(np.linalg.norm(dv,axis=1)/np.maximum(np.linalg.norm(acc,axis=1), TINY)) dt_min = min(dt_rmin, dt_amin) if(args.use_DF) : acc = acc + accDF( r, v) return acc, dt_min
def get_gravity_at_point(self, eps, x, y, z): R = np.sqrt(x.value_in(units.kpc)**2. + y.value_in(units.kpc)**2.) zed = z.value_in(units.kpc) phi = np.arctan2(y.value_in(units.kpc), x.value_in(units.kpc)) Rforce = potential.evaluateRforces(self.pot, R / self.ro, zed / self.ro, phi=phi, t=self.tgalpy) phiforce = potential.evaluatephiforces( self.pot, R / self.ro, zed / self.ro, phi=phi, t=self.tgalpy) / (R / self.ro) zforce = potential.evaluatezforces(self.pot, R / self.ro, zed / self.ro, phi=phi, t=self.tgalpy) ax = (Rforce * np.cos(phi) - phiforce * np.sin(phi)) * bovy_conversion.force_in_kmsMyr( ro=self.ro, vo=self.vo) | units.kms * units.myr**-1 ay = (Rforce * np.sin(phi) + phiforce * np.cos(phi)) * bovy_conversion.force_in_kmsMyr( ro=self.ro, vo=self.vo) | units.kms * units.myr**-1 az = zforce * bovy_conversion.force_in_kmsMyr( ro=self.ro, vo=self.vo) | units.kms * units.myr**-1 return ax, ay, az
def MWBHRfo(ldeg, sigl, bdeg, sigb, dkpc, sigd): b = bdeg * par.degtorad l = ldeg * par.degtorad Rskpc = par.Rskpc Vs = par.Vs conversion = par.conversion Rpkpc = par.Rpkpc(ldeg, sigl, bdeg, sigb, dkpc, sigd) zkpc = dkpc * math.sin(b) be = (dkpc / Rskpc) * math.cos(b) - math.cos(l) coslam = be * (Rskpc / Rpkpc) ''' bp= PowerSphericalPotentialwCutoff(alpha=1.8,rc=1.9/8.,normalize=0.05) mp= MiyamotoNagaiPotential(a=3./8.,b=0.28/8.,normalize=.6) np= NFWPotential(a=16./8.,normalize=.35) kp = KeplerPotential(amp=4*10**6./bovy_conversion.mass_in_msol(par.Vs,par.Rskpc)) MWBH = [bp,mp,np,kp] rforce1 = evaluateRforces(MWBH, Rpkpc/Rskpc,zkpc/Rskpc)*bovy_conversion.force_in_kmsMyr(Vs,Rskpc) rfsun = evaluateRforces(MWBH, Rskpc/Rskpc,0.0/Rskpc)*bovy_conversion.force_in_kmsMyr(Vs,Rskpc) ''' #MWPotential2014.append(KeplerPotential(amp=4*10**6./bovy_conversion.mass_in_msol(Vs,Rskpc))) #rforce1 = evaluateRforces(MWPotential2014, Rpkpc/Rskpc,zkpc/Rskpc)*bovy_conversion.force_in_kmsMyr(Vs,Rskpc) #rfsun = evaluateRforces(MWPotential2014, Rskpc/Rskpc,0.0/Rskpc)*bovy_conversion.force_in_kmsMyr(Vs,Rskpc) MWPotential2014wBH = [ MWPotential2014, KeplerPotential(amp=4 * 10**6. / bovy_conversion.mass_in_msol(par.Vs, par.Rskpc)) ] rforce1 = evaluateRforces(MWPotential2014wBH, Rpkpc / Rskpc, zkpc / Rskpc) * bovy_conversion.force_in_kmsMyr( Vs, Rskpc) rfsun = evaluateRforces(MWPotential2014wBH, Rskpc / Rskpc, 0.0 / Rskpc) * bovy_conversion.force_in_kmsMyr( Vs, Rskpc) #rf = (rforce1-rfsun)*conversion*math.cos(b) # s-1 rf0 = rforce1 * coslam + rfsun * math.cos(l) rf = rf0 * conversion * math.cos(b) # s-1 return rf
def _Rforce(self, R, z, phi=0.0, t=0.0): from galpy.potential import evaluateRforces if self._interpRforce: out = numpy.empty_like(R) indx = (R >= self._rgrid[0]) * (R <= self._rgrid[-1]) * (z <= self._zgrid[-1]) * (z >= self._zgrid[0]) if numpy.sum(indx) > 0: if self._enable_c: out[indx] = eval_force_c(self, R[indx], z[indx])[0] / self._amp else: if self._logR: out[indx] = self._rforceInterp.ev(numpy.log(R[indx]), z[indx]) else: out[indx] = self._rforceInterp.ev(R[indx], z[indx]) if numpy.sum(True - indx) > 0: out[True - indx] = evaluateRforces(R[True - indx], z[True - indx], self._origPot) return out else: return evaluateRforces(R, z, self._origPot)
def test_vcirc(): #test the circular velocity of the KuzminKutuzovStaeckelPotential #using parameters from Batsleer & Dejonghe 1994, fig. 1-3 #and their formula eq. (10) #_____model parameters______ #surface ratios of disk and halo: ac_Ds = [50. ,50. ,50. ,50. ,50. ,50. ,40. ,40. ,40. ] ac_Hs = [1.005,1.005,1.005,1.01,1.01,1.01 ,1.02,1.02,1.02 ] #disk contribution to total mass: ks = [0.05 ,0.06 ,0.07 ,0.07,0.1 ,0.125,0.1 ,0.12,0.125] #focal distance: Delta = 1. for ii in range(9): ac_D = ac_Ds[ii] ac_H = ac_Hs[ii] k = ks[ii] #_____setup potential_____ #first try, not normalized: V_D = KuzminKutuzovStaeckelPotential(amp= k ,ac=ac_D,Delta=Delta,normalize=False) V_H = KuzminKutuzovStaeckelPotential(amp=(1.-k),ac=ac_H,Delta=Delta,normalize=False) pot = [V_D,V_H] #normalization according to Batsleer & Dejonghe 1994: V00 = evaluatePotentials(pot,0.,0.) #second try, normalized: V_D = KuzminKutuzovStaeckelPotential(amp= k / (-V00),ac=ac_D,Delta=Delta,normalize=False) V_H = KuzminKutuzovStaeckelPotential(amp=(1.-k) / (-V00),ac=ac_H,Delta=Delta,normalize=False) pot = [V_D,V_H] #_____calculate rotation curve_____ Rs = numpy.linspace(0.,20.,100) z = 0. vcirc_calc = numpy.sqrt(-Rs * evaluateRforces(pot,Rs,z)) #_____vcirc by Batsleer & Dejonghe eq. (10) (with proper Jacobian)_____ def vc2w(R): g_D = Delta**2 / (1.-ac_D**2) a_D = g_D - Delta**2 g_H = Delta**2 / (1.-ac_H**2) a_H = g_H - Delta**2 l = R**2 - a_D q = a_H - a_D termD = numpy.sqrt(l )*(numpy.sqrt(l ) + numpy.sqrt(-g_D ))**2 termH = numpy.sqrt(l-q)*(numpy.sqrt(l-q) + numpy.sqrt(-g_D-q))**2 return R**2 * (k / termD + (1.-k) / termH) vcirc_formula = numpy.sqrt(vc2w(Rs)/(-V00)) assert numpy.all(numpy.fabs(vcirc_calc - vcirc_formula) < 10**-8.), \ 'Calculated circular velocity for KuzminKutuzovStaeckelPotential '+ \ 'does not agree with eq. (10) (corrected by proper Jacobian) '+ \ 'by Batsleer & Dejonghe (1994)' return None
def _Rforce(self,R,z,phi=0.,t=0.): from galpy.potential import evaluateRforces if self._interpRforce: out= numpy.empty_like(R) indx= (R >= self._rgrid[0])*(R <= self._rgrid[-1])\ *(z <= self._zgrid[-1])*(z >= self._zgrid[0]) if numpy.sum(indx) > 0: if self._enable_c: out[indx]= eval_force_c(self,R[indx],z[indx])[0]/self._amp else: if self._logR: out[indx]= self._rforceInterp.ev(numpy.log(R[indx]),z[indx]) else: out[indx]= self._rforceInterp.ev(R[indx],z[indx]) if numpy.sum(True^indx) > 0: out[True^indx]= evaluateRforces(self._origPot, R[True^indx], z[True^indx]) return out else: return evaluateRforces(self._origPot,R,z)
def force_pal5(pot,dpal5,ro,vo): """Return the force at Pal5""" # First compute the location based on the distance l5, b5= bovy_coords.radec_to_lb(229.018,-0.124,degree=True) X5,Y5,Z5= bovy_coords.lbd_to_XYZ(l5,b5,dpal5,degree=True) R5,p5,Z5= bovy_coords.XYZ_to_galcencyl(X5,Y5,Z5,Xsun=ro,Zsun=0.025) return (potential.evaluateRforces(pot,R5/ro,Z5/ro,phi=p5, use_physical=True,ro=ro,vo=vo), potential.evaluatezforces(pot,R5/ro,Z5/ro,phi=p5, use_physical=True,ro=ro,vo=vo), potential.evaluatephiforces(pot,R5/ro,Z5/ro,phi=p5, use_physical=True,ro=ro,vo=vo))
def force_gd1(pot,ro,vo): """Return the force at GD-1""" # Just use R=12.5 kpc, Z= 6.675 kpc, phi=0 R1= 12.5 Z1= 6.675 p1= 0. return (potential.evaluateRforces(pot,R1/ro,Z1/ro,phi=p1, use_physical=True,ro=ro,vo=vo), potential.evaluatezforces(pot,R1/ro,Z1/ro,phi=p1, use_physical=True,ro=ro,vo=vo), potential.evaluatephiforces(pot,R1/ro,Z1/ro,phi=p1, use_physical=True,ro=ro,vo=vo))
def obj(x,data,bp,dp,hp): #x=[fd,fh,vc,rs,hdisk] if x[0] > 1. or x[0] < 0.: return numpy.finfo(numpy.dtype(numpy.float64)).max if x[1] > 1. or x[1] < 0.: return numpy.finfo(numpy.dtype(numpy.float64)).max if (1.-x[0]-x[1]) > 1. or (1.-x[0]-x[1]) < 0.: return numpy.finfo(numpy.dtype(numpy.float64)).max if x[2] < 0. or x[3] < 0. or x[4] < 0.: return numpy.finfo(numpy.dtype(numpy.float64)).max if x[2] > 2. or x[3] > 10. or x[4] > 2.: return numpy.finfo(numpy.dtype(numpy.float64)).max if False: #Renormalize potentials, intially normalized to 1./3. each bp= copy.deepcopy(bp) dp= copy.deepcopy(dp) hp= copy.deepcopy(hp) bp._amp*= (1.-x[0]-x[1])**2.*9. dp._amp*= x[0]**2.*9. hp._amp*= x[1]**2.*9. #Re-define disk scale length and halo scale length if _dexp: dp._hr= x[4] else: dp._a= x[4] hp._a= x[3] else: #Set-up bp= HernquistPotential(a=0.6/_REFR0,normalize=1.-x[0]-x[1]) if _dexp: dp= DoubleExponentialDiskPotential(normalize=x[0], hr=x[4], hz=0.3/_REFR0) else: dp= MiyamotoNagaiPotential(normalize=x[0], a=x[4], b=0.3/_REFR0) hp= NFWPotential(normalize=x[1], a=x[3]) #Re-normalize data vcircdata= copy.copy(data) vcircdata[:,1]/= x[2] vcircdata[:,2]/= x[2] #Vcirc chi2 vcmodel= numpy.zeros(vcircdata.shape[0]) for ii in range(vcircdata.shape[0]): vcmodel[ii]= numpy.sqrt(vcircdata[ii,0]\ *numpy.fabs(evaluateRforces(vcircdata[ii,0], 0.,[bp,dp,hp]))) #print vcircdata[:,0], vcmodel chi2= numpy.sum((vcircdata[:,1]-vcmodel)**2./vcircdata[:,2]**2.) #Add scale length measurement chi2+= (x[4]-_diskscale)**2./_diskscaleerr**2. #Add dark matter density at the Solar radius #print hp.dens(1.,0.),_rhodm*x[2]**2. #chi2+= (hp.dens(1.,0.)-_rhodm*x[2]**2.)**2./_rhodmerr**2./x[2]**4. return chi2
def estimateDeltaStaeckel(R, z, pot=None): """ NAME: estimateDeltaStaeckel PURPOSE: Estimate a good value for delta using eqn. (9) in Sanders (2012) INPUT: R,z = coordinates (if these are arrays, the median estimated delta is returned, i.e., if this is an orbit) pot= Potential instance or list thereof OUTPUT: delta HISTORY: 2013-08-28 - Written - Bovy (IAS) """ if pot is None: #pragma: no cover raise IOError( "pot= needs to be set to a Potential instance or list thereof") if isinstance(R, nu.ndarray): delta2 = nu.array([ ( z[ii]**2. - R[ii]**2. #eqn. (9) has a sign error + (3. * R[ii] * evaluatezforces(R[ii], z[ii], pot) - 3. * z[ii] * evaluateRforces(R[ii], z[ii], pot) + R[ii] * z[ii] * (evaluateR2derivs(R[ii], z[ii], pot) - evaluatez2derivs(R[ii], z[ii], pot))) / evaluateRzderivs(R[ii], z[ii], pot)) for ii in range(len(R)) ]) indx = (delta2 < 0.) * (delta2 > -10.**-10.) delta2[indx] = 0. delta2 = nu.median(delta2[True - nu.isnan(delta2)]) else: delta2 = ( z**2. - R**2. #eqn. (9) has a sign error + (3. * R * evaluatezforces(R, z, pot) - 3. * z * evaluateRforces(R, z, pot) + R * z * (evaluateR2derivs(R, z, pot) - evaluatez2derivs(R, z, pot))) / evaluateRzderivs(R, z, pot)) if delta2 < 0. and delta2 > -10.**-10.: delta2 = 0. return nu.sqrt(delta2)
def accHernquistfix(x,y,z): x = x/kpctocm y = y/kpctocm z = z/kpctocm r = np.sqrt( x**2 + y**2) pot = HernquistPotential(2.e12*u.M_sun , 30e3*u.pc) az = evaluatezforces(pot,r*u.kpc , z*u.kpc) ar = evaluateRforces(pot,r*u.kpc , z*u.kpc) az = -az*1.e5/(1.e6*3.15e7) ar = ar*1.e5/(1.e6*3.15e7) ax = -ar*x/r ay = -ar*y/r return ax,ay,az
def MWRfo(ldeg, sigl, bdeg, sigb, dkpc, sigd): b = bdeg * par.degtorad l = ldeg * par.degtorad Rskpc = par.Rskpc Vs = par.Vs conversion = par.conversion Rpkpc = par.Rpkpc(ldeg, sigl, bdeg, sigb, dkpc, sigd) zkpc = dkpc * math.sin(b) be = (dkpc / Rskpc) * math.cos(b) - math.cos(l) coslam = be * (Rskpc / Rpkpc) rforce1 = evaluateRforces(MWPotential2014, Rpkpc / Rskpc, zkpc / Rskpc) * bovy_conversion.force_in_kmsMyr( Vs, Rskpc) rfsun = evaluateRforces(MWPotential2014, Rskpc / Rskpc, 0.0 / Rskpc) * bovy_conversion.force_in_kmsMyr( Vs, Rskpc) rf0 = rforce1 * coslam + rfsun * math.cos(l) rf = rf0 * conversion * math.cos(b) # s-1 return rf
def rv(x, y, z): conv = bovy_conversion.force_in_pcMyr2(220., 8) * u.pc / ( u.Myr**2) ##Unit conversion x *= u.kpc y *= u.kpc z *= u.kpc ##Sun's location sx = 8 * u.kpc sy = 0 * u.kpc sz = 4 * u.kpc sun_ar = evaluateRforces(poten, sx, sz, phi=0 * u.deg) * conv sun_az = evaluatezforces(poten, sx, sz, phi=0 * u.deg) * conv sun_acc = Vector(sun_ar, 0 * conv, sun_az) star_ar = evaluateRforces(poten, np.sqrt(x**2 + y**2), z, phi=0 * u.deg) * conv star_az = evaluatezforces(poten, np.sqrt(x**2 + y**2), z, phi=0 * u.deg) * conv star_acc = Vector(star_ar, 0 * conv, star_az) heliocentric_acc = Vector(star_acc.x - sun_acc.x, star_acc.y - sun_acc.y, star_acc.z - sun_acc.z) r = Vector(sx - x, sy - y, sz - z) acc = r.project(heliocentric_acc) delta_v = (acc.mag * 10 * u.yr).to(u.cm / u.s) return delta_v, r
def _getForces(folder): loc = "SCFAnalysis/Orbits/{0}".format(folder) Acos = nu.load(loc + "/Acos.npy") a_nfw = 200./8 orbits_pos =nu.load(TIMEORBITS.format(loc, TIME,0.004,1*units.Myr)) scf = potential.SCFPotential(Acos=Acos, a=a_nfw, normalize=.35) ps= potential.PowerSphericalPotentialwCutoff(alpha=1.8,rc=1.9/8.,normalize=0.05) mn= potential.MiyamotoNagaiPotential(a=3./8.,b=0.28/8.,normalize=.6) MWPotential= [ps,mn,scf] x,y,z = orbits_pos[-1,1:4] R, phi, z = rect_to_cyl(x,y,z) print "(R,z,phi) = ({0}, {1}, {2})".format(R,z,phi) Rforce = potential.evaluateRforces(MWPotential, R,z,phi) zforce = potential.evaluatezforces(MWPotential, R,z,phi) phiforce = potential.evaluatephiforces(MWPotential, R,z,phi) return Rforce, zforce, phiforce
def FRStaeckel(u,v,pot,delta): """ NAME: FRStaeckel PURPOSE: return the radial force INPUT: u - confocal u v - confocal v pot - potential delta - focus OUTPUT: FR(u,v) HISTORY: 2012-11-30 - Written - Bovy (IAS) """ R,z= bovy_coords.uv_to_Rz(u,v,delta=delta) return evaluateRforces(R,z,pot)
def FRStaeckel(u, v, pot, delta): #pragma: no cover because unused """ NAME: FRStaeckel PURPOSE: return the radial force INPUT: u - confocal u v - confocal v pot - potential delta - focus OUTPUT: FR(u,v) HISTORY: 2012-11-30 - Written - Bovy (IAS) """ R, z = bovy_coords.uv_to_Rz(u, v, delta=delta) return evaluateRforces(R, z, pot)
def accMWpot(x,y,z,alpha=1.8, rc=1.9, a=3., b=0.28): x = x/kpctocm y = y/kpctocm z = z/kpctocm r = np.sqrt( x**2 + y**2) bp= gp.PowerSphericalPotentialwCutoff(alpha=1.8,rc=1.9/8.,normalize=0.05) mp= gp.MiyamotoNagaiPotential(a=a/8.,b=b/8.,normalize=.6) nfw= gp.NFWPotential(a=16/8.,normalize=.35) #print(help(MWPotential2014)) #pot = [bp,mp,nfw] pot = MWPotential2014 az = evaluatezforces(pot,r*u.kpc , z*u.kpc)*bovy_conversion.force_in_kmsMyr(Vlsr/1e5,8.122) ar = evaluateRforces(pot,r*u.kpc , z*u.kpc)*bovy_conversion.force_in_kmsMyr(Vlsr/1e5,8.122) ar = ar*1.e5/(1.e6*3.15e7) az = -az*1.e5/(1.e6*3.15e7) ax = -ar*x/r ay = -ar*y/r return ax,ay,az
def calAcc(r, v): N = r.shape[0] a = np.zeros([N, 3]) dt_min = np.ones(N) * 1e5 * yrs dr = r dx = r[:, 0] dy = r[:, 1] dz = r[:, 2] dv = v dr_gp = np.sqrt(dx * dx + dy * dy) / (r0 * kpc) # galpy units dz_gp = dz / (r0 * kpc) drNorm = np.linalg.norm(dr, axis=1) acc = None if useNFW: m, rho, sigma = NFWmass(drNorm) acc = -G * m / (drNorm * drNorm)[:, np.newaxis] * dr / drNorm[:, np.newaxis] elif useHernquist: m, rho, sigma = hernquistmass(drNorm) acc = -G * m / (drNorm * drNorm)[:, np.newaxis] * dr / drNorm[:, np.newaxis] else: acc = np.zeros([dr_gp.size, 3]) conv = 1e-13 * 1e5 for i, x_gp, y_gp, r_gp, z_gp in zip(range(dr_gp.size), dx / (r0 * kpc), dy / (r0 * kpc), dr_gp, dz_gp): a = gp.evaluateRforces(MWpot, r_gp, z_gp) * bovy_conversion.force_in_10m13kms2( v0, r0) * conv acc[i, 0] = a * x_gp / r_gp acc[i, 1] = a * y_gp / r_gp acc[i, 2] = gp.evaluatezforces( MWpot, r_gp, z_gp) * bovy_conversion.force_in_10m13kms2( v0, r0) * conv dt_rmin = np.min(drNorm / np.linalg.norm(dv, axis=1)) dt_amin = np.min( np.linalg.norm(dv, axis=1) / np.maximum(np.linalg.norm(acc, axis=1), TINY)) dt_min = min(dt_rmin, dt_amin) if (args.use_DF): acc = acc + accDF(r, v) return acc, dt_min
def force_gd1(pot, ro, vo): """Return the force at GD-1. Parameters ---------- pot: Potential ro, vo: float Return ------ force: tuple [fx, fy, fz] """ # Just use R=12.5 kpc, Z= 6.675 kpc, phi=0 R1 = 12.5 Z1 = 6.675 p1 = 0.0 return ( potential.evaluateRforces(pot, R1 / ro, Z1 / ro, phi=p1, use_physical=True, ro=ro, vo=vo), potential.evaluatezforces(pot, R1 / ro, Z1 / ro, phi=p1, use_physical=True, ro=ro, vo=vo), potential.evaluatephiforces(pot, R1 / ro, Z1 / ro, phi=p1, use_physical=True, ro=ro, vo=vo), )
def calAcc(r, v) : N = r.shape[0] dr = r dx = r[:,0] dy = r[:,1] dz = r[:,2] dv = v dr_gp = np.sqrt(dx*dx + dy*dy)/(r0*kpc) # galpy units dz_gp = dz/(r0*kpc) drNorm = np.linalg.norm(dr, axis = 1) acc = None if useNFW : m, rho, sigma = NFWmass( drNorm) acc = -G*m/(drNorm*drNorm)[:,np.newaxis]*dr/drNorm[:,np.newaxis] elif useHernquist: m, rho, sigma = hernquistmass( drNorm) acc = (-G*m/(drNorm*drNorm*drNorm))[:,np.newaxis]*dr#[:,np.newaxis]*dr else : acc = np.zeros([dr_gp.size,3]) conv = 1e-13*1e5 for i, x_gp, y_gp, r_gp, z_gp in zip(range(dr_gp.size), dx/(r0*kpc), dy/(r0*kpc), dr_gp, dz_gp) : a = gp.evaluateRforces(MWpot,r_gp,z_gp)*bovy_conversion.force_in_10m13kms2(v0,r0)*conv acc[i,0] = a*x_gp/r_gp acc[i,1] = a*y_gp/r_gp acc[i,2] = gp.evaluatezforces(MWpot,r_gp,z_gp)*bovy_conversion.force_in_10m13kms2(v0,r0)*conv dt_rmin = np.min(drNorm/np.linalg.norm(dv, axis=1)) dt_amin = np.min(np.linalg.norm(dv,axis=1)/np.maximum(np.linalg.norm(acc,axis=1), TINY)) dt_min = min(dt_rmin, dt_amin) if(useDF) : acc[:Nsat,:] = acc[:Nsat,:] + accDF( r[:Nsat,:], v[:Nsat,:]) if(useTestParticles and Nsat < N and runSat) : # include accelerations from other satellites for test particles for i in range(Nsat) : rsat = r[i] dr = r[Nsat:,:] - rsat[np.newaxis,:] drNorm = np.linalg.norm( dr, axis=1) m, rho, sigma = hernquistmass( drNorm, m0=msat[i], vc200=vc200sat[i], r200=r200sat[i], c0=c0sat[i]) acc[Nsat:,:] = acc[Nsat:,:] - (G*m/(drNorm*drNorm*drNorm))[:,np.newaxis]*dr return acc, dt_min
def del_E(coord, custom_potential=None): """ NAME: del_E PURPOSE: Given (m,6) array for a list of the position and velocity of stars in Cartesian coordinate, return the gradient vectors of energy in Cartesian form, in the corresponding row order. Assumes input and out put are in natrual unit. INPUT: coord = array([[x, y, z, vx, vy, vz], ...]) where each row represents the coordinate of a star OUTPUT: del_E = gradient in Cartesian coordinate where each row represents the gradient of a star HISTORY: 2018-07-10 - Written - Samuel Wong 2018-07-24 - Changed to an array of points - Samuel Wong """ if custom_potential == None: potential = MWPotential2014 else: potential = custom_potential x, y, z, vx, vy, vz = coord.T R, vR, vT, z, vz, phi = rect_to_cyl(x, y, z, vx, vy, vz).T # get the force of the potential in cylindrical form F_phi = evaluatephiforces(potential, R, z, phi) / R F_R = evaluateRforces(potential, R, z, phi) F_z = evaluatezforces(potential, R, z, phi) # return the gradient in Cartesian coordinate gradient = [ F_phi * np.sin(phi) - F_R * np.cos(phi), -F_R * np.sin(phi) - F_phi * np.cos(phi), -F_z, vx, vy, vz ] return np.array(gradient).T
def _a_integrand(T,y,b,w,pot,compt): t = T/(1-T*T) X = b+w*t+y*numpy.array([0,1,0]) r = numpy.sqrt(numpy.sum(X**2)) return (1+T*T)/(1-T*T)**2*evaluateRforces(r,0.,pot)*X[compt]/r
def fdotdotSB1cal(ldeg, bdeg, dkpc, mul, mub, vrad): Rskpc = par.Rskpc Vs = par.Vs conversion = par.conversion yrts = par.yrts c = par.c kpctom = par.kpctom Rs = Rskpc * kpctom mastorad = par.mastorad normpottoSI = par.normpottoSI normForcetoSI = par.normForcetoSI normjerktoSI = par.normjerktoSI b = bdeg * par.degtorad l = ldeg * par.degtorad Rpkpc = par.Rpkpc(ldeg, bdeg, dkpc) zkpc = par.z(ldeg, bdeg, dkpc) fex_pl = excGal.Expl(ldeg, bdeg, dkpc) fex_z = excGal.Exz(ldeg, bdeg, dkpc) fex_shk = Shk.Exshk(dkpc, mul, mub) fex_tot = fex_pl + fex_z + fex_shk #mub = mu_alpha #mas/yr #mul = mu_delta muT = (mub**2. + mul**2.)**0.5 #MWPotential2014= [MWPotential2014,KeplerPotential(amp=4*10**6./bovy_conversion.mass_in_msol(par.Vs,par.Rskpc))] MWPot = MWPotential2014 appl = -evaluateRforces(MWPot, Rpkpc / Rskpc, zkpc / Rskpc) * normForcetoSI aspl = -evaluateRforces(MWPot, Rskpc / Rskpc, 0.0 / Rskpc) * normForcetoSI apz = evaluatezforces(MWPot, Rpkpc / Rskpc, zkpc / Rskpc) * normForcetoSI be = (dkpc / Rskpc) * math.cos(b) - math.cos(l) coslam = be * (Rskpc / Rpkpc) coslpluslam = math.cos(l) * coslam - (Rskpc * math.sin(l) / Rpkpc) * math.sin(l) aTl1 = -(appl * (Rskpc * math.sin(l) / Rpkpc) - aspl * math.sin(l)) aTb1 = appl * coslam * math.sin(b) + apz * math.cos(b) + aspl * math.cos( l) * math.sin(b) aTnet1 = (aTl1**2. + aTb1**2.)**(0.5) alphaV1 = math.atan2(mub, mul) / par.degtorad alphaA1 = math.atan2(aTb1, aTl1) / par.degtorad if alphaV1 < 0.: alphaV = 360. + alphaV1 else: alphaV = alphaV1 if alphaA1 < 0.: alphaA = 360. + alphaA1 else: alphaA = alphaA1 alpha = abs(alphaA - alphaV) aT1 = 2. * appl * aspl * coslpluslam aT2 = (c * (fex_pl + fex_z))**2. aTsq = appl**2. + aspl**2. + aT1 + apz**2. - aT2 #if aTsq < 0.0: aT = (appl**2. + aspl**2. + aT1 + apz**2. - aT2)**0.5 zdot = (1000.0 * vrad) * math.sin(b) + (mastorad / yrts) * mub * ( dkpc * kpctom) * math.cos(b) Rpdot = (1. / (Rpkpc * kpctom)) * ( ((dkpc * kpctom) * (math.cos(b)**2.) - Rs * math.cos(b) * math.cos(l)) * (1000.0 * vrad) + (Rs * (dkpc * kpctom) * math.sin(b) * math.cos(l) - ((dkpc * kpctom)**2.) * math.cos(b) * math.sin(b)) * ((mastorad / yrts) * mub) + Rs * (dkpc * kpctom) * math.sin(l) * ((mastorad / yrts) * mul)) phiR2 = normjerktoSI * evaluateR2derivs(MWPot, Rpkpc / Rskpc, zkpc / Rskpc) phiz2 = normjerktoSI * evaluatez2derivs(MWPot, Rpkpc / Rskpc, zkpc / Rskpc) phiRz = normjerktoSI * evaluateRzderivs(MWPot, Rpkpc / Rskpc, zkpc / Rskpc) phiR2sun = normjerktoSI * evaluateR2derivs(MWPot, Rskpc / Rskpc, 0.0 / Rskpc) phiRzsun = normjerktoSI * evaluateRzderivs(MWPot, Rskpc / Rskpc, 0.0 / Rskpc) aspldot = phiR2sun * Rpdot + phiRzsun * zdot appldot = phiR2 * Rpdot + phiRz * zdot if b > 0: apzdot = phiRz * Rpdot + phiz2 * zdot else: apzdot = -(phiRz * Rpdot + phiz2 * zdot) #if coslam != 0.0 and Rpkpc != 0.0 and math.cos(b) != 0.0: lamdot = (1. / coslam) * ((Rs * math.cos(l) * ((mastorad / yrts) * mul)) / ((Rpkpc * kpctom) * math.cos(b)) - (Rs * math.sin(l) / ((Rpkpc * kpctom)**2.)) * Rpdot) ardot1 = math.sin(b) * (appl * coslam + aspl * math.cos(l)) * ( (mastorad / yrts) * mub) ardot2 = math.cos(b) * (appldot * coslam + aspldot * math.cos(l)) ardot3 = apzdot * math.sin(abs(b)) ardot4 = appl * math.cos(b) * (Rskpc * math.sin(l) / Rpkpc) * lamdot ardot5 = aspl * math.sin(l) * ((mastorad / yrts) * mul) ardot6 = abs(apz) * math.cos(b) * ((mastorad / yrts) * mub) * (b / abs(b)) ardot = ardot1 - ardot2 - ardot3 + ardot4 + ardot5 - ardot6 jerkt = (1. / c) * (ardot - aT * ((mastorad / yrts) * muT) * math.cos(alpha)) return jerkt
def test_vcirc(): #test the circular velocity of the KuzminKutuzovStaeckelPotential #using parameters from Batsleer & Dejonghe 1994, fig. 1-3 #and their formula eq. (10) #_____model parameters______ #surface ratios of disk and halo: ac_Ds = [50., 50., 50., 50., 50., 50., 40., 40., 40.] ac_Hs = [1.005, 1.005, 1.005, 1.01, 1.01, 1.01, 1.02, 1.02, 1.02] #disk contribution to total mass: ks = [0.05, 0.06, 0.07, 0.07, 0.1, 0.125, 0.1, 0.12, 0.125] #focal distance: Delta = 1. for ii in range(9): ac_D = ac_Ds[ii] ac_H = ac_Hs[ii] k = ks[ii] #_____setup potential_____ #first try, not normalized: V_D = KuzminKutuzovStaeckelPotential(amp=k, ac=ac_D, Delta=Delta, normalize=False) V_H = KuzminKutuzovStaeckelPotential(amp=(1. - k), ac=ac_H, Delta=Delta, normalize=False) pot = [V_D, V_H] #normalization according to Batsleer & Dejonghe 1994: V00 = evaluatePotentials(pot, 0., 0.) #second try, normalized: V_D = KuzminKutuzovStaeckelPotential(amp=k / (-V00), ac=ac_D, Delta=Delta, normalize=False) V_H = KuzminKutuzovStaeckelPotential(amp=(1. - k) / (-V00), ac=ac_H, Delta=Delta, normalize=False) pot = [V_D, V_H] #_____calculate rotation curve_____ Rs = numpy.linspace(0., 20., 100) z = 0. vcirc_calc = numpy.sqrt(-Rs * evaluateRforces(pot, Rs, z)) #_____vcirc by Batsleer & Dejonghe eq. (10) (with proper Jacobian)_____ def vc2w(R): g_D = Delta**2 / (1. - ac_D**2) a_D = g_D - Delta**2 g_H = Delta**2 / (1. - ac_H**2) a_H = g_H - Delta**2 l = R**2 - a_D q = a_H - a_D termD = numpy.sqrt(l) * (numpy.sqrt(l) + numpy.sqrt(-g_D))**2 termH = numpy.sqrt(l - q) * (numpy.sqrt(l - q) + numpy.sqrt(-g_D - q))**2 return R**2 * (k / termD + (1. - k) / termH) vcirc_formula = numpy.sqrt(vc2w(Rs) / (-V00)) assert numpy.all(numpy.fabs(vcirc_calc - vcirc_formula) < 10**-8.), \ 'Calculated circular velocity for KuzminKutuzovStaeckelPotential '+ \ 'does not agree with eq. (10) (corrected by proper Jacobian) '+ \ 'by Batsleer & Dejonghe (1994)' return None
def plhalo_from_dlnvcdlnr(dlnvcdlnr,diskpot,bulgepot,fh): """Calculate the halo's shape corresponding to this rotation curve derivative""" #First calculate the derivatives dvc^2/dR of disk and bulge dvcdr_disk= -potential.evaluateRforces(1.,0.,diskpot)+potential.evaluateR2derivs(1.,0.,diskpot) dvcdr_bulge= -potential.evaluateRforces(1.,0.,bulgepot)+potential.evaluateR2derivs(1.,0.,bulgepot) return 2.-(2.*dlnvcdlnr-dvcdr_disk-dvcdr_bulge)/fh
def plotForceField(savefig: Optional[str] = None): """Plot MW Force Field. Parameters ---------- savefic: str, optional """ p_b15_pal5gd1_voro = fit(fitc=True, c=None, addpal5=True, addgd1=True, fitvoro=True, mc16=True) # Set up potential p_b15 = p_b15_pal5gd1_voro[0] ro, vo = REFR0, REFV0 pot = setup_potential(p_b15, p_b15_pal5gd1_voro[0][-1], False, False, ro, vo) # Compute force field Rs = np.linspace(0.01, 20.0, 51) zs = np.linspace(-20.0, 20.0, 151) mRs, mzs = np.meshgrid(Rs, zs, indexing="ij") forces = np.zeros((len(Rs), len(zs), 2)) potvals = np.zeros((len(Rs), len(zs))) for ii in tqdm(range(len(Rs))): for jj in tqdm(range(len(zs))): forces[ii, jj, 0] = potential.evaluateRforces( pot, mRs[ii, jj] / ro, mzs[ii, jj] / ro, use_physical=True, ro=ro, vo=vo, ) forces[ii, jj, 1] = potential.evaluatezforces( pot, mRs[ii, jj] / ro, mzs[ii, jj] / ro, use_physical=True, ro=ro, vo=vo, ) potvals[ii, jj] = potential.evaluatePotentials( pot, mRs[ii, jj] / ro, mzs[ii, jj] / ro, use_physical=True, ro=ro, vo=vo, ) fig = plt.figure(figsize=(8, 16)) skip = 10 # Make sure to keep zs symmetric!! scale = 35.0 # Don't plot these # forces[(mRs < 5.)*(np.fabs(mzs) < 4.)]= np.nan forces[(mRs < 2.0) * (np.fabs(mzs) < 5.0)] = np.nan bovy_plot.bovy_dens2d( potvals.T, origin="lower", cmap="viridis", xrange=[Rs[0], Rs[-1]], yrange=[zs[0], zs[-1]], xlabel=r"$R\,(\mathrm{kpc})$", ylabel=r"$Z\,(\mathrm{kpc})$", contours=True, aspect=1.0, ) plt.quiver( mRs[1::skip, 5:-1:skip], mzs[1::skip, 5:-1:skip], forces[1::skip, 5:-1:skip, 0], forces[1::skip, 5:-1:skip, 1], scale=scale, ) # Add a few lines pointing to the GC for angle in tqdm(np.linspace(0.0, np.pi / 2.0, 8)): plt.plot((0.0, 100.0 * np.cos(angle)), (0.0, 100.0 * np.sin(angle)), "k:") plt.plot((0.0, 100.0 * np.cos(angle)), (0.0, -100.0 * np.sin(angle)), "k:") # Add measurements # Pal 5 plt.quiver((8.0, ), (16.0, ), (-0.8, ), (-1.82, ), color="w", zorder=10, scale=scale) # GD-1 plt.quiver( (12.5, ), (6.675, ), (-2.51, ), (-1.47, ), color="w", zorder=10, scale=scale, ) # Disk + flat APOGEE rotation curve: # Use Bovy & Tremaine (2012) method for translating F_R in the plane to F_R # at 1.1 kpc: dFr/dz = dFz / dR diskrs = np.linspace(5.5, 8.5, 3) diskfzs = (-67.0 * np.exp(-(diskrs - 8.0) / 2.7) / bovy_conversion.force_in_2piGmsolpc2(220.0, 8.0) * bovy_conversion.force_in_kmsMyr(220.0, 8.0)) diskfrs = (-(218.0**2.0 / diskrs) * bovy_conversion._kmsInPcMyr / 1000.0 - 1.1 * diskfzs / 2.7) plt.quiver( diskrs, 1.1 * np.ones_like(diskrs), diskfrs, diskfzs, color="w", zorder=10, scale=scale, ) # Labels bovy_plot.bovy_text(5.8, 16.0, r"$\mathbf{Pal\ 5}$", color="w", size=17.0) bovy_plot.bovy_text(12.5, 7.0, r"$\mathbf{GD-1}$", color="w", size=17.0) bovy_plot.bovy_text(8.65, 0.5, r"$\mathbf{disk\ stars}$", color="w", size=17.0) if savefig is not None: fig.savefig(savefig) return fig
def __init__(self, RZPot=None,rgrid=(numpy.log(0.01),numpy.log(20.),101), zgrid=(0.,1.,101),logR=True, interpPot=False,interpRforce=False,interpzforce=False, interpDens=False, interpvcirc=False, interpdvcircdr=False, interpepifreq=False,interpverticalfreq=False, ro=None,vo=None, use_c=False,enable_c=False,zsym=True, numcores=None): """ NAME: __init__ PURPOSE: Initialize an interpRZPotential instance INPUT: RZPot - RZPotential to be interpolated rgrid - R grid to be given to linspace as in rs= linspace(*rgrid) zgrid - z grid to be given to linspace as in zs= linspace(*zgrid) logR - if True, rgrid is in the log of R so logrs= linspace(*rgrid) interpPot, interpRforce, interpzforce, interpDens,interpvcirc, interpepifreq, interpverticalfreq, interpdvcircdr= if True, interpolate these functions use_c= use C to speed up the calculation of the grid enable_c= enable use of C for interpolations zsym= if True (default), the potential is assumed to be symmetric around z=0 (so you can use, e.g., zgrid=(0.,1.,101)). numcores= if set to an integer, use this many cores (only used for vcirc, dvcircdR, epifreq, and verticalfreq; NOT NECESSARILY FASTER, TIME TO MAKE SURE) ro=, vo= distance and velocity scales for translation into internal units (default from configuration file) OUTPUT: instance HISTORY: 2010-07-21 - Written - Bovy (NYU) 2013-01-24 - Started with new implementation - Bovy (IAS) """ if isinstance(RZPot,interpRZPotential): from galpy.potential import PotentialError raise PotentialError('Cannot setup interpRZPotential with another interpRZPotential') # Propagate ro and vo roSet= True voSet= True if ro is None: if isinstance(RZPot,list): ro= RZPot[0]._ro roSet= RZPot[0]._roSet else: ro= RZPot._ro roSet= RZPot._roSet if vo is None: if isinstance(RZPot,list): vo= RZPot[0]._vo voSet= RZPot[0]._voSet else: vo= RZPot._vo voSet= RZPot._voSet Potential.__init__(self,amp=1.,ro=ro,vo=vo) # Turn off physical if it hadn't been on if not roSet: self._roSet= False if not voSet: self._voSet= False self._origPot= RZPot self._rgrid= numpy.linspace(*rgrid) self._logR= logR if self._logR: self._rgrid= numpy.exp(self._rgrid) self._logrgrid= numpy.log(self._rgrid) self._zgrid= numpy.linspace(*zgrid) self._interpPot= interpPot self._interpRforce= interpRforce self._interpzforce= interpzforce self._interpDens= interpDens self._interpvcirc= interpvcirc self._interpdvcircdr= interpdvcircdr self._interpepifreq= interpepifreq self._interpverticalfreq= interpverticalfreq self._enable_c= enable_c*ext_loaded self.hasC= self._enable_c self._zsym= zsym if interpPot: if use_c*ext_loaded: self._potGrid, err= calc_potential_c(self._origPot,self._rgrid,self._zgrid) else: from galpy.potential import evaluatePotentials potGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): potGrid[ii,jj]= evaluatePotentials(self._origPot,self._rgrid[ii],self._zgrid[jj]) self._potGrid= potGrid if self._logR: self._potInterp= interpolate.RectBivariateSpline(self._logrgrid, self._zgrid, self._potGrid, kx=3,ky=3,s=0.) else: self._potInterp= interpolate.RectBivariateSpline(self._rgrid, self._zgrid, self._potGrid, kx=3,ky=3,s=0.) if enable_c*ext_loaded: self._potGrid_splinecoeffs= calc_2dsplinecoeffs_c(self._potGrid) if interpRforce: if use_c*ext_loaded: self._rforceGrid, err= calc_potential_c(self._origPot,self._rgrid,self._zgrid,rforce=True) else: from galpy.potential import evaluateRforces rforceGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): rforceGrid[ii,jj]= evaluateRforces(self._origPot,self._rgrid[ii],self._zgrid[jj]) self._rforceGrid= rforceGrid if self._logR: self._rforceInterp= interpolate.RectBivariateSpline(self._logrgrid, self._zgrid, self._rforceGrid, kx=3,ky=3,s=0.) else: self._rforceInterp= interpolate.RectBivariateSpline(self._rgrid, self._zgrid, self._rforceGrid, kx=3,ky=3,s=0.) if enable_c*ext_loaded: self._rforceGrid_splinecoeffs= calc_2dsplinecoeffs_c(self._rforceGrid) if interpzforce: if use_c*ext_loaded: self._zforceGrid, err= calc_potential_c(self._origPot,self._rgrid,self._zgrid,zforce=True) else: from galpy.potential import evaluatezforces zforceGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): zforceGrid[ii,jj]= evaluatezforces(self._origPot,self._rgrid[ii],self._zgrid[jj]) self._zforceGrid= zforceGrid if self._logR: self._zforceInterp= interpolate.RectBivariateSpline(self._logrgrid, self._zgrid, self._zforceGrid, kx=3,ky=3,s=0.) else: self._zforceInterp= interpolate.RectBivariateSpline(self._rgrid, self._zgrid, self._zforceGrid, kx=3,ky=3,s=0.) if enable_c*ext_loaded: self._zforceGrid_splinecoeffs= calc_2dsplinecoeffs_c(self._zforceGrid) if interpDens: from galpy.potential import evaluateDensities densGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): densGrid[ii,jj]= evaluateDensities(self._origPot,self._rgrid[ii],self._zgrid[jj]) self._densGrid= densGrid if self._logR: self._densInterp= interpolate.RectBivariateSpline(self._logrgrid, self._zgrid, numpy.log(self._densGrid+10.**-10.), kx=3,ky=3,s=0.) else: self._densInterp= interpolate.RectBivariateSpline(self._rgrid, self._zgrid, numpy.log(self._densGrid+10.**-10.), kx=3,ky=3,s=0.) if interpvcirc: from galpy.potential import vcirc if not numcores is None: self._vcircGrid= multi.parallel_map((lambda x: vcirc(self._origPot,self._rgrid[x])), list(range(len(self._rgrid))),numcores=numcores) else: self._vcircGrid= numpy.array([vcirc(self._origPot,r) for r in self._rgrid]) if self._logR: self._vcircInterp= interpolate.InterpolatedUnivariateSpline(self._logrgrid,self._vcircGrid,k=3) else: self._vcircInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid,self._vcircGrid,k=3) if interpdvcircdr: from galpy.potential import dvcircdR if not numcores is None: self._dvcircdrGrid= multi.parallel_map((lambda x: dvcircdR(self._origPot,self._rgrid[x])), list(range(len(self._rgrid))),numcores=numcores) else: self._dvcircdrGrid= numpy.array([dvcircdR(self._origPot,r) for r in self._rgrid]) if self._logR: self._dvcircdrInterp= interpolate.InterpolatedUnivariateSpline(self._logrgrid,self._dvcircdrGrid,k=3) else: self._dvcircdrInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid,self._dvcircdrGrid,k=3) if interpepifreq: from galpy.potential import epifreq if not numcores is None: self._epifreqGrid= numpy.array(multi.parallel_map((lambda x: epifreq(self._origPot,self._rgrid[x])), list(range(len(self._rgrid))),numcores=numcores)) else: self._epifreqGrid= numpy.array([epifreq(self._origPot,r) for r in self._rgrid]) indx= True^numpy.isnan(self._epifreqGrid) if numpy.sum(indx) < 4: if self._logR: self._epifreqInterp= interpolate.InterpolatedUnivariateSpline(self._logrgrid[indx],self._epifreqGrid[indx],k=1) else: self._epifreqInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid[indx],self._epifreqGrid[indx],k=1) else: if self._logR: self._epifreqInterp= interpolate.InterpolatedUnivariateSpline(self._logrgrid[indx],self._epifreqGrid[indx],k=3) else: self._epifreqInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid[indx],self._epifreqGrid[indx],k=3) if interpverticalfreq: from galpy.potential import verticalfreq if not numcores is None: self._verticalfreqGrid= multi.parallel_map((lambda x: verticalfreq(self._origPot,self._rgrid[x])), list(range(len(self._rgrid))),numcores=numcores) else: self._verticalfreqGrid= numpy.array([verticalfreq(self._origPot,r) for r in self._rgrid]) if self._logR: self._verticalfreqInterp= interpolate.InterpolatedUnivariateSpline(self._logrgrid,self._verticalfreqGrid,k=3) else: self._verticalfreqInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid,self._verticalfreqGrid,k=3) return None
def __init__(self, RZPot=None,rgrid=(0.01,2.,101),zgrid=(0.,0.2,101),logR=False, interpPot=False,interpRforce=False,interpzforce=False, interpDens=False, interpvcirc=False, interpdvcircdr=False, interpepifreq=False,interpverticalfreq=False, use_c=False,enable_c=False,zsym=True, numcores=None): """ NAME: __init__ PURPOSE: Initialize an interpRZPotential instance INPUT: RZPot - RZPotential to be interpolated rgrid - R grid to be given to linspace zgrid - z grid to be given to linspace logR - if True, rgrid is in the log of R interpPot, interpRfoce, interpzforce, interpDens,interpvcirc, interpeopifreq, interpverticalfreq, interpdvcircdr= if True, interpolate these functions use_c= use C to speed up the calculation enable_c= enable use of C for interpolations zsym= if True (default), the potential is assumed to be symmetric around z=0 (so you can use, e.g., zgrid=(0.,1.,101)). numcores= if set to an integer, use this many cores (only used for vcirc, dvcircdR, epifreq, and verticalfreq; NOT NECESSARILY FASTER, TIME TO MAKE SURE) OUTPUT: instance HISTORY: 2010-07-21 - Written - Bovy (NYU) 2013-01-24 - Started with new implementation - Bovy (IAS) """ Potential.__init__(self,amp=1.) self.hasC= True self._origPot= RZPot self._rgrid= numpy.linspace(*rgrid) self._logR= logR if self._logR: self._rgrid= numpy.exp(self._rgrid) self._logrgrid= numpy.log(self._rgrid) self._zgrid= numpy.linspace(*zgrid) self._interpPot= interpPot self._interpRforce= interpRforce self._interpzforce= interpzforce self._interpDens= interpDens self._interpvcirc= interpvcirc self._interpdvcircdr= interpdvcircdr self._interpepifreq= interpepifreq self._interpverticalfreq= interpverticalfreq self._enable_c= enable_c*ext_loaded self._zsym= zsym if interpPot: if use_c*ext_loaded: self._potGrid, err= calc_potential_c(self._origPot,self._rgrid,self._zgrid) else: from galpy.potential import evaluatePotentials potGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): potGrid[ii,jj]= evaluatePotentials(self._rgrid[ii],self._zgrid[jj],self._origPot) self._potGrid= potGrid if self._logR: self._potInterp= interpolate.RectBivariateSpline(self._logrgrid, self._zgrid, self._potGrid, kx=3,ky=3,s=0.) else: self._potInterp= interpolate.RectBivariateSpline(self._rgrid, self._zgrid, self._potGrid, kx=3,ky=3,s=0.) if enable_c*ext_loaded: self._potGrid_splinecoeffs= calc_2dsplinecoeffs_c(self._potGrid) if interpRforce: if use_c*ext_loaded: self._rforceGrid, err= calc_potential_c(self._origPot,self._rgrid,self._zgrid,rforce=True) else: from galpy.potential import evaluateRforces rforceGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): rforceGrid[ii,jj]= evaluateRforces(self._rgrid[ii],self._zgrid[jj],self._origPot) self._rforceGrid= rforceGrid if self._logR: self._rforceInterp= interpolate.RectBivariateSpline(self._logrgrid, self._zgrid, self._rforceGrid, kx=3,ky=3,s=0.) else: self._rforceInterp= interpolate.RectBivariateSpline(self._rgrid, self._zgrid, self._rforceGrid, kx=3,ky=3,s=0.) if enable_c*ext_loaded: self._rforceGrid_splinecoeffs= calc_2dsplinecoeffs_c(self._rforceGrid) if interpzforce: if use_c*ext_loaded: self._zforceGrid, err= calc_potential_c(self._origPot,self._rgrid,self._zgrid,zforce=True) else: from galpy.potential import evaluatezforces zforceGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): zforceGrid[ii,jj]= evaluatezforces(self._rgrid[ii],self._zgrid[jj],self._origPot) self._zforceGrid= zforceGrid if self._logR: self._zforceInterp= interpolate.RectBivariateSpline(self._logrgrid, self._zgrid, self._zforceGrid, kx=3,ky=3,s=0.) else: self._zforceInterp= interpolate.RectBivariateSpline(self._rgrid, self._zgrid, self._zforceGrid, kx=3,ky=3,s=0.) if enable_c*ext_loaded: self._zforceGrid_splinecoeffs= calc_2dsplinecoeffs_c(self._zforceGrid) if interpDens: if False: raise NotImplementedError("Using C to calculate an interpolation grid for the density is not supported currently") self._densGrid, err= calc_dens_c(self._origPot,self._rgrid,self._zgrid) else: from galpy.potential import evaluateDensities densGrid= numpy.zeros((len(self._rgrid),len(self._zgrid))) for ii in range(len(self._rgrid)): for jj in range(len(self._zgrid)): densGrid[ii,jj]= evaluateDensities(self._rgrid[ii],self._zgrid[jj],self._origPot) self._densGrid= densGrid if self._logR: self._densInterp= interpolate.RectBivariateSpline(self._logrgrid, self._zgrid, numpy.log(self._densGrid+10.**-10.), kx=3,ky=3,s=0.) else: self._densInterp= interpolate.RectBivariateSpline(self._rgrid, self._zgrid, numpy.log(self._densGrid+10.**-10.), kx=3,ky=3,s=0.) if False: self._densGrid_splinecoeffs= calc_2dsplinecoeffs_c(self._densGrid) if interpvcirc: from galpy.potential import vcirc if not numcores is None: self._vcircGrid= multi.parallel_map((lambda x: vcirc(self._origPot,self._rgrid[x])), range(len(self._rgrid)),numcores=numcores) else: self._vcircGrid= numpy.array([vcirc(self._origPot,r) for r in self._rgrid]) if self._logR: self._vcircInterp= interpolate.InterpolatedUnivariateSpline(self._logrgrid,self._vcircGrid,k=3) else: self._vcircInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid,self._vcircGrid,k=3) if interpdvcircdr: from galpy.potential import dvcircdR if not numcores is None: self._dvcircdrGrid= multi.parallel_map((lambda x: dvcircdR(self._origPot,self._rgrid[x])), range(len(self._rgrid)),numcores=numcores) else: self._dvcircdrGrid= numpy.array([dvcircdR(self._origPot,r) for r in self._rgrid]) if self._logR: self._dvcircdrInterp= interpolate.InterpolatedUnivariateSpline(self._logrgrid,self._dvcircdrGrid,k=3) else: self._dvcircdrInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid,self._dvcircdrGrid,k=3) if interpepifreq: from galpy.potential import epifreq if not numcores is None: self._epifreqGrid= multi.parallel_map((lambda x: epifreq(self._origPot,self._rgrid[x])), range(len(self._rgrid)),numcores=numcores) else: self._epifreqGrid= numpy.array([epifreq(self._origPot,r) for r in self._rgrid]) indx= True-numpy.isnan(self._epifreqGrid) if numpy.sum(indx) < 4: if self._logR: self._epifreqInterp= interpolate.InterpolatedUnivariateSpline(self._logrgrid[indx],self._epifreqGrid[indx],k=1) else: self._epifreqInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid[indx],self._epifreqGrid[indx],k=1) else: if self._logR: self._epifreqInterp= interpolate.InterpolatedUnivariateSpline(self._logrgrid[indx],self._epifreqGrid[indx],k=3) else: self._epifreqInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid[indx],self._epifreqGrid[indx],k=3) if interpverticalfreq: from galpy.potential import verticalfreq if not numcores is None: self._verticalfreqGrid= multi.parallel_map((lambda x: verticalfreq(self._origPot,self._rgrid[x])), range(len(self._rgrid)),numcores=numcores) else: self._verticalfreqGrid= numpy.array([verticalfreq(self._origPot,r) for r in self._rgrid]) if self._logR: self._verticalfreqInterp= interpolate.InterpolatedUnivariateSpline(self._logrgrid,self._verticalfreqGrid,k=3) else: self._verticalfreqInterp= interpolate.InterpolatedUnivariateSpline(self._rgrid,self._verticalfreqGrid,k=3) return None
def my_f_cylr(self, r, ang, *args, **kwargs): """Return the force in cylindical R direction at (r, theta)""" z, r_cyl = self.spherical_to_cylindrical(r, ang) return evaluateRforces(self.func, r_cyl / self.R0, z / self.R0) * self.force_to_kpckms2
def fdotdotSB3calBH(ldeg, bdeg, dkpc, mul, mub, vrad): Rskpc = par.Rskpc Vs = par.Vs conversion = par.conversion yrts = par.yrts c = par.c kpctom = par.kpctom Rs = Rskpc * kpctom mastorad = par.mastorad normpottoSI = par.normpottoSI normForcetoSI = par.normForcetoSI normjerktoSI = par.normjerktoSI b = bdeg * par.degtorad l = ldeg * par.degtorad Rpkpc = par.Rpkpc(ldeg, bdeg, dkpc) zkpc = par.z(ldeg, bdeg, dkpc) fex_pl = excGalBH.Expl(ldeg, bdeg, dkpc) fex_z = excGalBH.Exz(ldeg, bdeg, dkpc) fex_shk = Shk.Exshk(dkpc, mul, mub) fex_tot = fex_pl + fex_z + fex_shk #mub = mu_alpha #mas/yr #mul = mu_delta muT = (mub**2. + mul**2.)**0.5 #MWPotential2014= [MWPotential2014,KeplerPotential(amp=4*10**6./bovy_conversion.mass_in_msol(par.Vs,par.Rskpc))] MWPot = [ MWPotential2014, KeplerPotential(amp=4 * 10**6. / bovy_conversion.mass_in_msol(par.Vs, par.Rskpc)) ] appl = evaluateRforces(MWPot, Rpkpc / Rskpc, zkpc / Rskpc) * normForcetoSI aspl = evaluateRforces(MWPot, Rskpc / Rskpc, 0.0 / Rskpc) * normForcetoSI apz = evaluatezforces(MWPot, Rpkpc / Rskpc, zkpc / Rskpc) * normForcetoSI be = (dkpc / Rskpc) * math.cos(b) - math.cos(l) coslam = be * (Rskpc / Rpkpc) coslpluslam = math.cos(l) * coslam - (Rskpc * math.sin(l) / Rpkpc) * math.sin(l) aTl1 = -(appl * (Rskpc * math.sin(l) / Rpkpc) - aspl * math.sin(l)) aTb1 = appl * coslam * math.sin(b) - apz * math.cos(b) + aspl * math.cos( l) * math.sin(b) aTnet1 = (aTl1**2. + aTb1**2.)**(0.5) alphaV1 = math.atan2(mub, mul) / par.degtorad alphaA1 = math.atan2(aTb1, aTl1) / par.degtorad if alphaV1 < 0.: alphaV = 360. + alphaV1 else: alphaV = alphaV1 if alphaA1 < 0.: alphaA = 360. + alphaA1 else: alphaA = alphaA1 alpha = abs(alphaA - alphaV) aT1 = 2. * appl * aspl * coslpluslam aT2 = (c * (fex_pl + fex_z))**2. aTsq = appl**2. + aspl**2. + aT1 + apz**2. - aT2 #if aTsq < 0.0: aT = (appl**2. + aspl**2. + aT1 + apz**2. - aT2)**0.5 yrts = par.yrts c = par.c mastorad = par.mastorad #tsbvrad = (1./c)*(3.*(1000.0*vrad)*(((mastorad/yrts)*muT)**2.)) tsbt = (1. / c) * (aT * ((mastorad / yrts) * muT) * math.cos(alpha) - 3. * (1000.0 * vrad) * (((mastorad / yrts) * muT)**2.)) return tsbt
def impulse_deltav_general_orbitintegration(v,x,b,w,x0,v0,pot,tmax,galpot, tmaxfac=10.,nsamp=1000, integrate_method='symplec4_c'): """ NAME: impulse_deltav_general_orbitintegration PURPOSE: calculate the delta velocity to due an encounter with a general spherical potential NOT in the impulse approximation by integrating each particle in the underlying galactic potential; allows for arbitrary velocity vectors and arbitrary shaped streams. INPUT: v - velocity of the stream (nstar,3) x - position along the stream (nstar,3) b - impact parameter w - velocity of the subhalo (3) x0 - position of closest approach (3) v0 - velocity of stream at closest approach (3) pot - Potential object or list thereof (should be spherical) tmax - maximum integration time galpot - galpy Potential object or list thereof nsamp(1000) - number of forward integration points integrate_method= ('symplec4_c') orbit integrator to use (see Orbit.integrate) OUTPUT: deltav (nstar,3) HISTORY: 2015-08-17 - SANDERS """ if len(v.shape) == 1: v= numpy.reshape(v,(1,3)) if len(x.shape) == 1: x= numpy.reshape(x,(1,3)) nstar,ndim=numpy.shape(v) b0 = numpy.cross(w,v0) b0 *= b/numpy.sqrt(numpy.sum(b0**2)) times = numpy.linspace(0.,tmax,nsamp) xres = numpy.zeros(shape=(len(x),nsamp*2-1,3)) R, phi, z= bovy_coords.rect_to_cyl(x[:,0],x[:,1],x[:,2]) vR, vp, vz= bovy_coords.rect_to_cyl_vec(v[:,0],v[:,1],v[:,2], R,phi,z,cyl=True) for i in range(nstar): o = Orbit([R[i],vR[i],vp[i],z[i],vz[i],phi[i]]) o.integrate(times,galpot,method=integrate_method) xres[i,nsamp:,0]=o.x(times)[1:] xres[i,nsamp:,1]=o.y(times)[1:] xres[i,nsamp:,2]=o.z(times)[1:] oreverse = o.flip() oreverse.integrate(times,galpot,method=integrate_method) xres[i,:nsamp,0]=oreverse.x(times)[::-1] xres[i,:nsamp,1]=oreverse.y(times)[::-1] xres[i,:nsamp,2]=oreverse.z(times)[::-1] times = numpy.concatenate((-times[::-1],times[1:])) nsamp = len(times) X = b0+xres-x0-numpy.outer(times,w) r = numpy.sqrt(numpy.sum(X**2,axis=-1)) acc = (numpy.reshape(evaluateRforces(r.flatten(),0.,pot),(nstar,nsamp))/r)[:,:,numpy.newaxis]*X return integrate.simps(acc,x=times,axis=1)
def spiral_arms_potential(FR_frac=1., t_on=-5., tgrow=2, tstream=5., axi_pot=MWPotential2014, cos=True, N=2, pat_speed=24.5, pitch_angle=9.9, r_ref=8., Rs=7., phi0=26., H=0.3): phi0 = np.radians(phi0) omega = pat_speed * (ro / vo) alpha = numpy.radians(pitch_angle) r_ref /= ro Rs /= ro H /= ro # percentage of the radial force to set the amplitude of the spiral FR_frac = FR_frac * 0.01 if cos: Cs = [8. / (3. * numpy.pi), 0.5, 8. / (15. * numpy.pi)] else: Cs = [1] #compute max radial force for amp=1 pp = np.linspace(0., 2. * np.pi, 1000) FR_nonaxi = [] spiral_pot_amp1 = SpiralArmsPotential(amp=1., N=N, omega=omega, alpha=alpha, phi_ref=phi0, r_ref=r_ref, H=H, Rs=Rs, Cs=Cs) turn_physical_off(spiral_pot_amp1) for ii in range(len(pp)): FR_nonaxi.append( potential.evaluateRforces(spiral_pot_amp1, R=8. / ro, z=0., phi=pp[ii], t=0.)) interp_FR_nonaxi = interpolate.InterpolatedUnivariateSpline(pp, FR_nonaxi) #fmin, because radial force is negative max_phi = optimize.fmin(interp_FR_nonaxi, 0., disp=0) max_FR_nonaxi = interp_FR_nonaxi(max_phi)[0] #compute the radial force due to the axisymmetric potential FR_axi = potential.evaluateRforces(axi_pot, R=8. / ro, z=0., t=0.) #compute the correct amplitude amp = numpy.abs(FR_frac * FR_axi / max_FR_nonaxi) #setup spiral potential with correct amplitude spiralpot = SpiralArmsPotential(amp=amp, N=N, omega=omega, alpha=alpha, phi_ref=phi0, r_ref=r_ref, H=H, Rs=Rs, Cs=Cs) #grow the spirals Tspiral = 2. * np.pi / np.abs(omega) #bar period in galpy units. t_on = t_on / bovy_conversion.time_in_Gyr(vo, ro) tsteady = tgrow * Tspiral tform = t_on - tsteady #- because past is negative #if t_on >= t_pal5_age, then Pal 5 sees the spirals always on if np.abs(t_on) * bovy_conversion.time_in_Gyr(vo, ro) >= tstream: print('not growing spiral') MWspiralpot = axi_pot + [spiralpot] turn_physical_off(MWspiralpot) return (MWspiralpot) elif np.abs(tform) * bovy_conversion.time_in_Gyr(vo, ro) >= tstream: print("tform > age of stream") elif np.abs(tform) * bovy_conversion.time_in_Gyr(vo, ro) < tstream: print('growing spiral') spiralpot_grow = DehnenWrap(amp=1., pot=spiralpot, tform=tform, tsteady=tsteady) turn_physical_off(spiralpot_grow) MWspiralpot = axi_pot + [spiralpot_grow] return MWspiralpot
def fdotdotexcwBHcal(ldeg, bdeg, dkpc, mul, mub, Rpkpc, zkpc, f, fdotobs, vrad, fex_pl, fex_z, fex_shk): Rskpc = par.Rskpc Vs = par.Vs conversion = par.conversion yrts = par.yrts c = par.c kpctom = par.kpctom Rs = Rskpc * kpctom mastorad = par.mastorad normpottoSI = par.normpottoSI normForcetoSI = par.normForcetoSI normjerktoSI = par.normjerktoSI b = bdeg * par.degtorad l = ldeg * par.degtorad fex_tot = fex_pl + fex_z + fex_shk #mub = mu_alpha #mas/yr #mul = mu_delta muT = (mub**2. + mul**2.)**0.5 #MWPotential2014= [MWPotential2014,KeplerPotential(amp=4*10**6./bovy_conversion.mass_in_msol(par.Vs,par.Rskpc))] MWPot = [ MWPotential2014, KeplerPotential(amp=4 * 10**6. / bovy_conversion.mass_in_msol(par.Vs, par.Rskpc)) ] appl = evaluateRforces(MWPot, Rpkpc / Rskpc, zkpc / Rskpc) * normForcetoSI aspl = evaluateRforces(MWPot, Rskpc / Rskpc, 0.0 / Rskpc) * normForcetoSI apz = evaluatezforces(MWPot, Rpkpc / Rskpc, zkpc / Rskpc) * normForcetoSI be = (dkpc / Rskpc) * math.cos(b) - math.cos(l) coslam = be * (Rskpc / Rpkpc) coslpluslam = math.cos(l) * coslam - (Rskpc * math.sin(l) / Rpkpc) * math.sin(l) aTl1 = -(appl * (Rskpc * math.sin(l) / Rpkpc) - aspl * math.sin(l)) aTb1 = appl * coslam * math.sin(b) - apz * math.cos(b) + aspl * math.cos( l) * math.sin(b) aTnet1 = (aTl1**2. + aTb1**2.)**(0.5) alphaV1 = math.atan2(mub, mul) / par.degtorad alphaA1 = math.atan2(aTb1, aTl1) / par.degtorad if alphaV1 < 0.: alphaV = 360. + alphaV1 else: alphaV = alphaV1 if alphaA1 < 0.: alphaA = 360. + alphaA1 else: alphaA = alphaA1 alpha = abs(alphaA - alphaV) aT1 = 2. * appl * aspl * coslpluslam aT2 = (c * (fex_pl + fex_z))**2. aTsq = appl**2. + aspl**2. + aT1 + apz**2. - aT2 #if aTsq < 0.0: aT = (appl**2. + aspl**2. + aT1 + apz**2. - aT2)**0.5 Combterm = fdotdotSB1cal( ldeg, bdeg, dkpc, mul, mub, Rpkpc, zkpc, vrad, coslam, alpha, appl, apz, aspl, aT, MWPot) + fdotdotSB2cal( ldeg, bdeg, dkpc, mul, mub, Rpkpc, zkpc, fex_pl, fex_z, fex_shk, appl, apz, aspl) + fdotdotSB3cal(vrad, aT, muT, alpha) fddotfex = -Combterm + fdotdotSB4cal(f, fdotobs, fex_pl, fex_z, fex_shk) #fdotint = fdotobs-fs*fex_tot #fddotint = fddotobs-fs*fddotfex return fddotfex
def sample(self, n, returndt=False, integrate=True, xy=False, lb=False): """ NAME: sample PURPOSE: sample from the DF INPUT: n - number of points to return returndt= (False) if True, also return the time since the star was stripped integrate= (True) if True, integrate the orbits to the present time, if False, return positions at stripping (probably want to combine with returndt=True then to make sense of them!) xy= (False) if True, return Galactocentric rectangular coordinates lb= (False) if True, return Galactic l,b,d,vlos,pmll,pmbb coordinates OUTPUT: (R,vR,vT,z,vz,phi) of points on the stream in 6,N array HISTORY: 2018-07-31 - Written - Bovy (IAS) """ if xy or lb: raise NotImplementedError( "xy=True and lb=True options currently not implemented") # First sample times dt = numpy.random.uniform(size=n) * self._tdisrupt # Build all rotation matrices rot, rot_inv = self._setup_rot(dt) # Compute progenitor position in the instantaneous frame xyzpt = numpy.einsum( 'ijk,ik->ij', rot, numpy.array([ self._progenitor.x(-dt), self._progenitor.y(-dt), self._progenitor.z(-dt) ]).T) vxyzpt = numpy.einsum( 'ijk,ik->ij', rot, numpy.array([ self._progenitor.vx(-dt), self._progenitor.vy(-dt), self._progenitor.vz(-dt) ]).T) Rpt, phipt, Zpt = bovy_coords.rect_to_cyl(xyzpt[:, 0], xyzpt[:, 1], xyzpt[:, 2]) vRpt, vTpt, vZpt = bovy_coords.rect_to_cyl_vec(vxyzpt[:, 0], vxyzpt[:, 1], vxyzpt[:, 2], Rpt, phipt, Zpt, cyl=True) # Sample positions and velocities in the instantaneous frame k = self._meankvec + numpy.random.normal( size=n)[:, numpy.newaxis] * self._sigkvec try: rtides = rtide(self._rtpot, Rpt, Zpt, phi=phipt, t=-dt, M=self._progenitor_mass, use_physical=False) vcs = numpy.sqrt(-Rpt * evaluateRforces( self._rtpot, Rpt, Zpt, phi=phipt, t=-dt, use_physical=False)) except (ValueError, TypeError): rtides = numpy.array([ rtide(self._rtpot, Rpt[ii], Zpt[ii], phi=phipt[ii], t=-dt[ii], M=self._progenitor_mass, use_physical=False) for ii in range(len(Rpt)) ]) vcs = numpy.array([ numpy.sqrt(-Rpt[ii] * evaluateRforces(self._rtpot, Rpt[ii], Zpt[ii], phi=phipt[ii], t=-dt[ii], use_physical=False)) for ii in range(len(Rpt)) ]) rtides_as_frac = rtides / Rpt RpZst = numpy.array([ Rpt + k[:, 0] * rtides, phipt + k[:, 5] * rtides_as_frac, k[:, 3] * rtides_as_frac ]).T vRTZst = numpy.array([ vRpt * (1. + k[:, 1]), vTpt + k[:, 2] * vcs * rtides_as_frac, k[:, 4] * vcs * rtides_as_frac ]).T # Now rotate these back to the galactocentric frame xst, yst, zst = bovy_coords.cyl_to_rect(RpZst[:, 0], RpZst[:, 1], RpZst[:, 2]) vxst, vyst, vzst = bovy_coords.cyl_to_rect_vec(vRTZst[:, 0], vRTZst[:, 1], vRTZst[:, 2], RpZst[:, 1]) xyzs = numpy.einsum('ijk,ik->ij', rot_inv, numpy.array([xst, yst, zst]).T) vxyzs = numpy.einsum('ijk,ik->ij', rot_inv, numpy.array([vxst, vyst, vzst]).T) Rs, phis, Zs = bovy_coords.rect_to_cyl(xyzs[:, 0], xyzs[:, 1], xyzs[:, 2]) vRs, vTs, vZs = bovy_coords.rect_to_cyl_vec(vxyzs[:, 0], vxyzs[:, 1], vxyzs[:, 2], Rs, phis, Zs, cyl=True) out = numpy.empty((6, n)) if integrate: # Now integrate the orbits for ii in range(n): o = Orbit( [Rs[ii], vRs[ii], vTs[ii], Zs[ii], vZs[ii], phis[ii]]) o.integrate(numpy.linspace(-dt[ii], 0., 10001), self._pot) o = o(0.) out[:, ii] = [o.R(), o.vR(), o.vT(), o.z(), o.vz(), o.phi()] else: out[0] = Rs out[1] = vRs out[2] = vTs out[3] = Zs out[4] = vZs out[5] = phis if returndt: return (out, dt) else: return out