def make_McMillan2017(ro=8.21, vo=233.1): ''' make_McMillan2017: Make the McMillan 2017 potential using SCF basis expansion: No arguments, but could change ro, vo if desired. ro is from the Gravity Collaboration (2018). vo is from Eilers (2018) and Schonrich (2010) Args: None ''' #dicts used in DiskSCFPotential sigmadict = [{'type':'exp','h':Rd_HI,'amp':Sigma0_HI, 'Rhole':Rm_HI}, {'type':'exp','h':Rd_H2,'amp':Sigma0_H2, 'Rhole':Rm_H2}, {'type':'exp','h':Rd_thin,'amp':Sigma0_thin, 'Rhole':0.}, {'type':'exp','h':Rd_thick,'amp':Sigma0_thick, 'Rhole':0.}] hzdict = [{'type':'sech2', 'h':zd_HI}, {'type':'sech2', 'h':zd_H2}, {'type':'exp', 'h':0.3/ro}, {'type':'exp', 'h':0.9/ro}] McMillan_bulge=\ mySCFPotential(Acos=potential.scf_compute_coeffs_axi(bulge_dens,20,10,a=0.1)[0], a=0.1,ro=ro,vo=vo) McMillan_disk = myDiskSCFPotential(dens=lambda R,z: gas_stellar_dens(R,z), Sigma=sigmadict, hz=hzdict, a=2.5, N=30, L=30,ro=ro,vo=vo) McMillan_halo = potential.NFWPotential(amp = rho0_halo*(4*np.pi*rh**3), a = rh,ro=ro,vo=vo) McMillan2017 = [McMillan_disk,McMillan_halo,McMillan_bulge] return McMillan2017
def test_nemo_NFWPotential(): np = potential.NFWPotential(normalize=1., a=3.) tmax = 3. vo, ro = 200., 7. o = Orbit([1., 0.5, 1.3, 0.3, 0.1, 0.4], ro=ro, vo=vo) run_orbitIntegration_comparison(o, np, tmax, vo, ro) return None
def setup_potential_kuepper(Mhalo: float, a: float) -> List[Potential]: """Set up Kuepper et al. (2015) Potential. Parameters ---------- Mhalo: float mass / 10^12 Msun a: float scale length / kpc, Returns ------- potential : list HernquistPotential + MiyamotoNagaiPotential + NFWPotential """ pot: List[Potential] = [ potential.HernquistPotential(amp=3.4e10 * u.Msun, a=0.7 * u.kpc), potential.MiyamotoNagaiPotential(amp=1e11 * u.Msun, a=6.5 * u.kpc, b=0.26 * u.kpc), potential.NFWPotential(amp=Mhalo * 1e12 * u.Msun, a=a * u.kpc), ] return pot
def test_staeckel_fudge_delta(): import galpy.potential as galpy_pot from galpy.actionAngle import estimateDeltaStaeckel ro = 8.1 * u.kpc vo = 229 * u.km / u.s paired_potentials = [] # Miyamoto-Nagai potential = gp.MiyamotoNagaiPotential(m=6e10 * u.Msun, a=3 * u.kpc, b=0.3 * u.kpc, units=galactic) amp = (G * potential.parameters['m']).to_value(vo**2 * ro) a = potential.parameters['a'].to_value(ro) b = potential.parameters['b'].to_value(ro) galpy_potential = galpy_pot.MiyamotoNagaiPotential(amp=amp, a=a, b=b, ro=ro, vo=vo) paired_potentials.append((potential, galpy_potential)) # Hernquist potential = gp.HernquistPotential(m=6e10 * u.Msun, c=0.3 * u.kpc, units=galactic) amp = (G * potential.parameters['m']).to_value(vo**2 * ro) a = potential.parameters['c'].to_value(ro) galpy_potential = galpy_pot.HernquistPotential(amp=amp, a=a, ro=ro, vo=vo) paired_potentials.append((potential, galpy_potential)) # NFW potential = gp.NFWPotential(m=6e11 * u.Msun, r_s=15.6 * u.kpc, units=galactic) amp = (G * potential.parameters['m']).to_value(vo**2 * ro) a = potential.parameters['r_s'].to_value(ro) galpy_potential = galpy_pot.NFWPotential(amp=amp, a=a, ro=ro, vo=vo) paired_potentials.append((potential, galpy_potential)) # TEST: N = 1024 rnd = np.random.default_rng(42) w = PhaseSpacePosition(pos=rnd.uniform(-10, 10, size=(3, N)) * u.kpc, vel=rnd.uniform(-100, 100, size=(3, N)) * u.km / u.s) R = w.cylindrical.rho.to_value(ro) z = w.z.to_value(ro) for p, galpy_p in paired_potentials: galpy_deltas = estimateDeltaStaeckel(galpy_p, R, z, no_median=True) gala_deltas = get_staeckel_fudge_delta(p, w).value print(p, np.allclose(gala_deltas, galpy_deltas)) assert np.allclose(gala_deltas, galpy_deltas, atol=1e-6)
def setup_class(cls): """Setup fixtures for testing.""" super().setup_class() cls.representation_type = None # Whatevs. Need to prevent Cartesian. # TODO!! actual potential that properly evaluates cls.original_potential = gpot.NFWPotential(amp=2e12 * u.solMass) cls.klass = cls.obj cls.inst = cls.klass(grid=cls.points, original_potential=cls.original_potential, observable=cls.observable, representation_type=cls.representation_type, **cls.kwargs)
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 rho_NFW(R, z=0, phi=0.): nfw = potential.NFWPotential() return nfw.dens(R, z, phi)
def test_phiforceMatches_nfw(): nfw = potential.NFWPotential() Acos, Asin = potential.scf_compute_coeffs_spherical(rho_NFW, 10) scf = SCFPotential(amp=1, Acos=Acos, Asin=Asin) assertmsg = "Comparing the azimuth force of NFW Potential with SCF fails at R={0}, Z={1}, phi={2}" compareFunctions(nfw.phiforce, scf.phiforce, assertmsg)
def test_zforceMatches_nfw(): nfw = potential.NFWPotential() Acos, Asin = potential.scf_compute_coeffs_spherical(rho_NFW, 50, a=50) scf = SCFPotential(amp=1, Acos=Acos, Asin=Asin, a=50) assertmsg = "Comparing the vertical force of NFW Potential with SCF fails at R={0}, Z={1}, phi={2}" compareFunctions(nfw.zforce, scf.zforce, assertmsg, eps=1e-3)
def test_potentialMatches_nfw(): nfw = potential.NFWPotential() Acos, Asin = potential.scf_compute_coeffs_spherical(rho_NFW, 50, a=50) scf = SCFPotential(amp=1, Acos=Acos, Asin=Asin, a=50) assertmsg = "Comparing nfw with SCF fails at R={0}, Z={1}, phi={2}" compareFunctions(nfw, scf, assertmsg, eps=1e-4)
def test_dynamfric_c(): import copy from galpy.orbit import Orbit from galpy.potential.Potential import _check_c from galpy.potential.mwpotentials import McMillan17 #Basic parameters for the test times = numpy.linspace(0., -100., 1001) #~3 Gyr at the Solar circle integrator = 'dop853_c' py_integrator = 'dop853' #Define all of the potentials (by hand, because need reasonable setup) MWPotential3021 = copy.deepcopy(potential.MWPotential2014) MWPotential3021[2] *= 1.5 # Increase mass by 50% pots= [potential.LogarithmicHaloPotential(normalize=1), potential.LogarithmicHaloPotential(normalize=1.3, q=0.9,b=0.7), #nonaxi potential.NFWPotential(normalize=1.,a=1.5), potential.MiyamotoNagaiPotential(normalize=.02,a=10.,b=10.), potential.MiyamotoNagaiPotential(normalize=.6,a=0.,b=3.), # special case potential.PowerSphericalPotential(alpha=2.3,normalize=2.), potential.DehnenSphericalPotential(normalize=4.,alpha=1.2), potential.DehnenCoreSphericalPotential(normalize=4.), potential.HernquistPotential(normalize=1.,a=3.5), potential.JaffePotential(normalize=1.,a=20.5), potential.DoubleExponentialDiskPotential(normalize=0.2, hr=3.,hz=0.6), potential.FlattenedPowerPotential(normalize=3.), potential.FlattenedPowerPotential(normalize=3.,alpha=0), #special case potential.IsochronePotential(normalize=2.), potential.PowerSphericalPotentialwCutoff(normalize=0.3,rc=10.), potential.PlummerPotential(normalize=.6,b=3.), potential.PseudoIsothermalPotential(normalize=.1,a=3.), potential.BurkertPotential(normalize=.2,a=2.5), potential.TriaxialHernquistPotential(normalize=1.,a=3.5, b=0.8,c=0.9), potential.TriaxialNFWPotential(normalize=1.,a=1.5,b=0.8,c=0.9), potential.TriaxialJaffePotential(normalize=1.,a=20.5,b=0.8,c=1.4), potential.PerfectEllipsoidPotential(normalize=.3,a=3.,b=0.7,c=1.5), potential.PerfectEllipsoidPotential(normalize=.3,a=3.,b=0.7,c=1.5, pa=3.,zvec=[0.,1.,0.]), #rotated potential.HomogeneousSpherePotential(normalize=0.02,R=82./8), # make sure to go to dens = 0 part, potential.interpSphericalPotential(\ rforce=potential.HomogeneousSpherePotential(normalize=0.02, R=82./8.), rgrid=numpy.linspace(0.,82./8.,201)), potential.TriaxialGaussianPotential(normalize=.03,sigma=4.,b=0.8,c=1.5,pa=3.,zvec=[1.,0.,0.]), potential.SCFPotential(Acos=numpy.array([[[1.]]]), # same as Hernquist normalize=1.,a=3.5), potential.SCFPotential(Acos=numpy.array([[[1.,0.],[.3,0.]]]), # nonaxi Asin=numpy.array([[[0.,0.],[1e-1,0.]]]), normalize=1.,a=3.5), MWPotential3021, McMillan17 # SCF + DiskSCF ] #tolerances in log10 tol = {} tol['default'] = -7. # Following are a little more difficult tol['DoubleExponentialDiskPotential'] = -4.5 tol['TriaxialHernquistPotential'] = -6. tol['TriaxialNFWPotential'] = -6. tol['TriaxialJaffePotential'] = -6. tol['MWPotential3021'] = -6. tol['HomogeneousSpherePotential'] = -6. tol['interpSphericalPotential'] = -6. # == HomogeneousSpherePotential tol['McMillan17'] = -6. for p in pots: if not _check_c(p, dens=True): continue # dynamfric not in C! pname = type(p).__name__ if pname == 'list': if isinstance(p[0],potential.PowerSphericalPotentialwCutoff) \ and len(p) > 1 \ and isinstance(p[1],potential.MiyamotoNagaiPotential) \ and len(p) > 2 \ and isinstance(p[2],potential.NFWPotential): pname = 'MWPotential3021' # Must be! else: pname = 'McMillan17' #print(pname) if pname in list(tol.keys()): ttol = tol[pname] else: ttol = tol['default'] # Setup orbit, ~ LMC o = Orbit([ 5.13200034, 1.08033051, 0.23323391, -3.48068653, 0.94950884, -1.54626091 ]) # Setup dynamical friction object if pname == 'McMillan17': cdf= potential.ChandrasekharDynamicalFrictionForce(\ GMs=0.5553870441722593,rhm=5./8.,dens=p,maxr=500./8,nr=101) ttimes = numpy.linspace(0., -30., 1001) #~1 Gyr at the Solar circle else: cdf= potential.ChandrasekharDynamicalFrictionForce(\ GMs=0.5553870441722593,rhm=5./8.,dens=p,maxr=500./8,nr=201) ttimes = times # Integrate in C o.integrate(ttimes, p + cdf, method=integrator) # Integrate in Python op = o() op.integrate(ttimes, p + cdf, method=py_integrator) # Compare r (most important) assert numpy.amax(numpy.fabs(o.r(ttimes)-op.r(ttimes))) < 10**ttol, \ 'Dynamical friction in C does not agree with dynamical friction in Python for potential {}'.format(pname) return None
McMillan_halo = potential.NFWPotential(amp = rho0_halo*(4*np.pi*rh**3), a = rh,ro=ro,vo=vo) McMillan2017 = [McMillan_disk,McMillan_halo,McMillan_bulge] return McMillan2017 #def # Make the potential so it's just an attribute. #dicts used in DiskSCFPotential sigmadict = [{'type':'exp','h':Rd_HI,'amp':Sigma0_HI, 'Rhole':Rm_HI}, {'type':'exp','h':Rd_H2,'amp':Sigma0_H2, 'Rhole':Rm_H2}, {'type':'exp','h':Rd_thin,'amp':Sigma0_thin, 'Rhole':0.}, {'type':'exp','h':Rd_thick,'amp':Sigma0_thick, 'Rhole':0.}] hzdict = [{'type':'sech2', 'h':zd_HI}, {'type':'sech2', 'h':zd_H2}, {'type':'exp', 'h':0.3/ro}, {'type':'exp', 'h':0.9/ro}] McMillan_bulge=\ mySCFPotential(Acos=potential.scf_compute_coeffs_axi(bulge_dens,20,10,a=0.1)[0], a=0.1,ro=ro,vo=vo) McMillan_disk = myDiskSCFPotential(dens=lambda R,z: gas_stellar_dens(R,z), Sigma=sigmadict, hz=hzdict, a=2.5, N=30, L=30,ro=ro,vo=vo) McMillan_halo = potential.NFWPotential(amp = rho0_halo*(4*np.pi*rh**3), a = rh,ro=ro,vo=vo) McMillan2017 = [McMillan_disk,McMillan_halo,McMillan_bulge] # ----------------------------------------------------------------------------
import numpy as np import matplotlib.pyplot as plt import nbodypy as npy from galpy import potential from galpy.potential import MWPotential2014 import os r0 = 8. v0 = 220. #for i in range(0,16): for i in range(11, 12): wdir = './nfw%i/' % i pot = potential.NFWPotential(a=2., normalize=0.35, ro=r0, vo=v0) if os.path.isfile(wdir + 'norbit.npy'): wfile = open(wdir + 'rldata.dat', 'w') print(i, wdir) for j in range(0, 13): nsnap = j cluster = npy.load_cluster('nbodypy', units0='realkpc', origin0='galaxy', nsnap=nsnap, wdir=wdir, oname='norbit.npy') cluster.rlimiting(pot=pot, nrad=50) bcluster = npy.sub_cluster(cluster, rmax=cluster.rl) if bcluster.ntot == 0: