def test_sigmalos_wlog_zerobeta(): from galpy.potential import LogarithmicHaloPotential lp= LogarithmicHaloPotential(normalize=1.,q=1.) rs= numpy.linspace(0.5,2.,3) assert numpy.all(numpy.fabs(numpy.array([jeans.sigmalos(lp,r) for r in rs])-1./numpy.sqrt(2.)) < 1e-8), 'Radial sigma_los computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential and beta=0' # Also with pre-computed sigmar rs= numpy.linspace(0.5,2.,11) # beta = 0 --> sigma = vc/sqrt(2) assert numpy.all(numpy.fabs(numpy.array([jeans.sigmalos(lp,r,sigma_r=1./numpy.sqrt(2.)) for r in rs])-1./numpy.sqrt(2.)) < 1e-8), 'Radial sigma_los computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential and beta=0' # Also with pre-computed, callable sigmar rs= numpy.linspace(0.5,2.,11) # beta = 0 --> sigma = vc/sqrt(2) assert numpy.all(numpy.fabs(numpy.array([jeans.sigmalos(lp,r,sigma_r=lambda x: 1./numpy.sqrt(2.)) for r in rs])-1./numpy.sqrt(2.)) < 1e-8), 'Radial sigma_los computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential and beta=0' # Also with pre-computed, callable sigmar and dens given rs= numpy.linspace(0.5,2.,11) # beta = 0 --> sigma = vc/sqrt(2) assert numpy.all(numpy.fabs(numpy.array([jeans.sigmalos(lp,r,dens=lambda x: x**-2,sigma_r=lambda x: 1./numpy.sqrt(2.)) for r in rs])-1./numpy.sqrt(2.)) < 1e-8), 'Radial sigma_los computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential and beta=0' # Also with pre-computed, callable sigmar and dens,surfdens given as func rs= numpy.linspace(0.5,2.,11) # beta = 0 --> sigma = vc/sqrt(2) assert numpy.all(numpy.fabs(numpy.array([jeans.sigmalos(lp,r,dens=lambda x: lp.dens(x,0.),surfdens=lambda x: lp.surfdens(x,numpy.inf),sigma_r=lambda x: 1./numpy.sqrt(2.)) for r in rs])-1./numpy.sqrt(2.)) < 1e-8), 'Radial sigma_los computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential and beta=0' # Also with pre-computed, callable sigmar and dens,surfdens given (value) rs= numpy.linspace(0.5,2.,11) # beta = 0 --> sigma = vc/sqrt(2) assert numpy.all(numpy.fabs(numpy.array([jeans.sigmalos(lp,r,dens=lambda x: lp.dens(x,0.),surfdens=lp.surfdens(r,numpy.inf),sigma_r=lambda x: 1./numpy.sqrt(2.)) for r in rs])-1./numpy.sqrt(2.)) < 1e-8), 'Radial sigma_los computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential and beta=0' # Also with pre-computed sigmar and callable beta rs= numpy.linspace(0.5,2.,11) # beta = 0 --> sigma = vc/sqrt(2) assert numpy.all(numpy.fabs(numpy.array([jeans.sigmalos(lp,r,sigma_r=1./numpy.sqrt(2.),beta=lambda x: 0.) for r in rs])-1./numpy.sqrt(2.)) < 1e-8), 'Radial sigma_los computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential and beta=0' return None
def test_TimeInterpPotential(): #Just to check that the code above has run properly from galpy.potential import LogarithmicHaloPotential, \ MiyamotoNagaiPotential lp= LogarithmicHaloPotential(normalize=1.) mp= MiyamotoNagaiPotential(normalize=1.) tip= TimeInterpPotential(lp,mp) assert numpy.fabs(tip.Rforce(1.,0.1,t=10.)-lp.Rforce(1.,0.1)) < 10.**-8., 'TimeInterPotential does not work as expected' assert numpy.fabs(tip.Rforce(1.,0.1,t=200.)-mp.Rforce(1.,0.1)) < 10.**-8., 'TimeInterPotential does not work as expected' return None
def test_mildnonaxi_meanvt_grid_tlist_onet(): # Test that for a close to axisymmetric potential, the mean vt is close to that of the initial DF, for a list consisting of a single time idf = dehnendf(beta=0.) pot = [ LogarithmicHaloPotential(normalize=1.), SteadyLogSpiralPotential(A=-0.005, omegas=0.2) ] #very mild non-axi edf = evolveddiskdf(idf, pot=pot, to=-10.) mvt, grid = edf.meanvT(0.9, t=[0.], phi=0.2, integrate_method='rk6_c', grid=True, returnGrid=True, gridpoints=_GRIDPOINTS) assert numpy.fabs( mvt - idf.meanvT(0.9) ) < 0.005, 'meanvT of evolveddiskdf for axisymmetric potential is not equal to that of the initial dehnendf' mvt = edf.meanvT( 0.9, t=[0.], phi=0.2, integrate_method='rk6_c', grid=grid, gridpoints=_GRIDPOINTS, ) assert numpy.fabs( mvt - idf.meanvT(0.9) ) < 0.005, 'meanvT of evolveddiskdf for axisymmetric potential is not equal to that of the initial dehnendf when calculated with pre-computed grid' global _maxi_meanvt _maxi_meanvt = mvt return None
def test_elliptical_cold_oortABCK_position2(): # Test that the Oort functions A, B, C, and K for the elliptical disk behaves as analytically expected idf= dehnendf(beta=0.,profileParams=(1./3.,1.,0.0125)) cp= 0.05 pot= [LogarithmicHaloPotential(normalize=1.), EllipticalDiskPotential(cp=cp,sp=0.,p=0.,tform=-150.,tsteady=125.)] edf= evolveddiskdf(idf,pot=pot,to=-150.) #Should be 0.5/0.9+cp/2 oorta, grid, gridr, gridp= edf.oortA(0.9,phi=0., integrate_method='rk6_c',grid=True, nsigma=7., derivRGrid=True,derivphiGrid=True, returnGrids=True, gridpoints=51, derivGridpoints=51) assert numpy.fabs(oorta-cp/2.-0.5/0.9) < 10.**-2.2, 'Cold elliptical disk does not agree with analytical calculation for oortA' #Should be -cp/2-0.5/0.9 oortb= edf.oortB(0.9,phi=0., integrate_method='rk6_c',grid=grid,nsigma=7., derivRGrid=gridr,derivphiGrid=gridp) assert numpy.fabs(oortb+cp/2.+0.5/0.9) < 10.**-2.2, 'Cold elliptical disk does not agree with analytical calculation for oortB' #Should be 0 oortc= edf.oortC(0.9,phi=0., integrate_method='rk6_c',grid=grid,nsigma=7., derivRGrid=gridr,derivphiGrid=gridp) assert numpy.fabs(oortc) < 10.**-3., 'Cold elliptical disk does not agree with analytical calculation for oortC' #Should be 0 oortk= edf.oortK(0.9,phi=0., integrate_method='rk6_c',grid=grid,nsigma=7., derivRGrid=gridr,derivphiGrid=gridp) assert numpy.fabs(oortk) < 10.**-3., 'Cold elliptical disk does not agree with analytical calculation for oortK' return None
def test_elliptical_cold_vt(): # Test that the rotational velocity for the elliptical disk behaves as analytically expected idf = dehnendf(beta=0., profileParams=(1. / 3., 1., 0.0125)) cp = 0.05 pot = [ LogarithmicHaloPotential(normalize=1.), EllipticalDiskPotential(cp=cp, sp=0., p=0., tform=-150., tsteady=125.) ] edf = evolveddiskdf(idf, pot=pot, to=-150.) #Should be 1. mvt, grid = edf.meanvT(0.9, phi=-numpy.pi / 4., integrate_method='rk6_c', grid=True, returnGrid=True, gridpoints=_GRIDPOINTS) assert numpy.fabs( mvt - 1. ) < 10.**-3., 'Cold elliptical disk does not agree with analytical calculation for vt' #Should be 1.-cp mvt, grid = edf.meanvT(0.9, phi=0., integrate_method='rk6_c', grid=True, nsigma=7., returnGrid=True, gridpoints=_GRIDPOINTS) assert numpy.fabs( mvt - 1. + cp ) < 10.**-3., 'Cold elliptical disk does not agree with analytical calculation for vt' return None
def test_elliptical_cold_vertexdev(): # Test that the vertex deviations for the elliptical disk behaves as analytically expected idf = dehnendf(beta=0., profileParams=(1. / 3., 1., 0.0125)) cp = 0.05 pot = [ LogarithmicHaloPotential(normalize=1.), EllipticalDiskPotential(cp=cp, sp=0., p=0., tform=-150., tsteady=125.) ] edf = evolveddiskdf(idf, pot=pot, to=-150.) #Should be -2cp in radians vdev, grid = edf.vertexdev(0.9, phi=-numpy.pi / 4., integrate_method='rk6_c', grid=True, nsigma=7., returnGrid=True, gridpoints=_GRIDPOINTS) assert numpy.fabs( vdev + 2. * cp ) < 10.**-3., 'Cold elliptical disk does not agree with analytical calculation for vertexdev' #Should be 0 vdev, grid = edf.vertexdev(0.9, phi=0., integrate_method='rk6_c', grid=True, nsigma=7., returnGrid=True, gridpoints=_GRIDPOINTS) assert numpy.fabs( vdev ) < 10.**-2. / 180. * numpy.pi, 'Cold elliptical disk does not agree with analytical calculation for vertexdev' return None
def test_mildnonaxi_meanvr_grid_tlist(): # Test that for a close to axisymmetric potential, the mean vr is close to zero idf = dehnendf(beta=0.) pot = [ LogarithmicHaloPotential(normalize=1.), SteadyLogSpiralPotential(A=-0.005, omegas=0.2) ] #very mild non-axi edf = evolveddiskdf(idf, pot=pot, to=-10.) mvr, grid = edf.meanvR(0.9, t=[0., -2.5, -5., -7.5, -10.], phi=0.2, integrate_method='rk6_c', grid=True, returnGrid=True, gridpoints=_GRIDPOINTS) assert numpy.all( numpy.fabs(mvr) < 0.003 ), 'meanvR of evolveddiskdf for axisymmetric potential is not equal to zero for list of times' mvr = edf.meanvR(0.9, t=[0., -2.5, -5., -7.5, -10.], phi=0.2, integrate_method='rk6_c', grid=grid) assert numpy.all( numpy.fabs(mvr) < 0.003 ), 'meanvR of evolveddiskdf for axisymmetric potential is not equal to zero when calculated with pre-computed grid for list of times' return None
def test_mildnonaxi_meanvt_hierarchgrid(): # Test that for a close to axisymmetric potential, the mean vt is close to that of the initial DF idf= dehnendf(beta=0.) pot= [LogarithmicHaloPotential(normalize=1.), SteadyLogSpiralPotential(A=-0.005,omegas=0.2)] #very mild non-axi edf= evolveddiskdf(idf,pot=pot,to=-10.) mvt, grid= edf.meanvT(0.9,phi=0.2,integrate_method='rk6_c', grid=True,hierarchgrid=True, returnGrid=True,gridpoints=_GRIDPOINTS) assert numpy.fabs(mvt-idf.meanvT(0.9)) < 0.005, 'meanvT of evolveddiskdf for axisymmetric potential is not equal to that of the initial dehnendf when using hierarchgrid' mvt= edf.meanvT(0.9,phi=0.2,integrate_method='rk6_c',grid=grid, gridpoints=_GRIDPOINTS) assert numpy.fabs(mvt-idf.meanvT(0.9)) < 0.005, 'meanvT of evolveddiskdf for axisymmetric potential is not equal to that of the initial dehnendf when calculated with pre-computed grid when using hierarchgrid' #Also test that the hierarchgrid is properly returned smass, ngrid= edf.vmomentsurfacemass(0.9,0,0,phi=0.2, integrate_method='rk6_c', grid=grid,gridpoints=_GRIDPOINTS, returnGrid=True) assert ngrid == grid, 'hierarchical grid returned by vmomentsurfacemass w/ grid input is not the same as the input' nsmass= edf.vmomentsurfacemass(0.9,0,0,phi=0.2, integrate_method='rk6_c', grid=True,hierarchgrid=True, gridpoints=_GRIDPOINTS) assert numpy.fabs(smass-nsmass) < 0.001, 'surfacemass computed w/ and w/o returnGrid are not the same' return None
def test_mildnonaxi_meanvt_grid_rmEstimates(): # Test vmomentsurfacemass w/o having the _estimateX functions in the intial DF class fakeDehnen(dehnendf): #class that removes the _estimate functions def __init__(self, *args, **kwargs): dehnendf.__init__(self, *args, **kwargs) _estimatemeanvR = property() _estimatemeanvT = property() _estimateSigmaR2 = property() _estimateSigmaT2 = property() idf = fakeDehnen(beta=0.) pot = [ LogarithmicHaloPotential(normalize=1.), SteadyLogSpiralPotential(A=-0.005, omegas=0.2) ] #very mild non-axi edf = evolveddiskdf(idf, pot=pot, to=-10.) mvt, grid = edf.meanvT(0.9, phi=0.2, integrate_method='rk6_c', grid=True, returnGrid=True, gridpoints=_GRIDPOINTS) assert numpy.fabs( mvt - idf.meanvT(0.9) ) < 0.005, 'meanvT of evolveddiskdf for axisymmetric potential is not equal to that of the initial dehnendf' return None
def test_plot_hierarchgrid(): idf = dehnendf(beta=0.) pot = [ LogarithmicHaloPotential(normalize=1.), SteadyLogSpiralPotential(A=-0.005, omegas=0.2) ] #very mild non-axi edf = evolveddiskdf(idf, pot=pot, to=-10.) mvr, grid = edf.meanvR(0.9, phi=0.2, integrate_method='rk6_c', grid=True, hierarchgrid=True, returnGrid=True, gridpoints=_GRIDPOINTS) grid.plot() #w/ list of tiems mvr, grid = edf.meanvR(0.9, t=[0., -2.5, -5., -7.5, -10.], phi=0.2, integrate_method='rk6_c', grid=True, hierarchgrid=True, returnGrid=True, gridpoints=_GRIDPOINTS) grid.plot(1) return None
def test_mildnonaxi_meanvt_hierarchgrid_tlist(): # Test that for a close to axisymmetric potential, the mean vt is close to that of the initial DF idf = dehnendf(beta=0.) pot = [ LogarithmicHaloPotential(normalize=1.), SteadyLogSpiralPotential(A=-0.005, omegas=0.2) ] #very mild non-axi edf = evolveddiskdf(idf, pot=pot, to=-10.) mvt, grid = edf.meanvT(0.9, t=[0., -2.5, -5., -7.5, -10.], phi=0.2, integrate_method='rk6_c', grid=True, hierarchgrid=True, returnGrid=True, gridpoints=_GRIDPOINTS) assert numpy.all( numpy.fabs(mvt - idf.meanvT(0.9)) < 0.005 ), 'meanvT of evolveddiskdf for axisymmetric potential is not equal to that of the initial dehnendf when using hierarchgrid and tlist' mvt = edf.meanvT(0.9, t=[0., -2.5, -5., -7.5, -10.], phi=0.2, integrate_method='rk6_c', grid=grid, gridpoints=_GRIDPOINTS) assert numpy.all( numpy.fabs(mvt - idf.meanvT(0.9)) < 0.005 ), 'meanvT of evolveddiskdf for axisymmetric potential is not equal to that of the initial dehnendf when calculated with pre-computed grid when using hierarchgrid and tlist' return None
def test_call_marginalizevperp(): from galpy.orbit import Orbit idf = dehnendf(beta=0.) pot = [ LogarithmicHaloPotential(normalize=1.), EllipticalDiskPotential(twophio=0.001) ] #very mild non-axi edf = evolveddiskdf(idf, pot=pot[0], to=-10.) #one with just one potential #l=0 R, phi, vR = 0.8, 0., 0.4 vts = numpy.linspace(0., 1.5, 51) pvts = numpy.array( [edf(Orbit([R, vR, vt, phi]), integrate_method='rk6_c') for vt in vts]) assert numpy.fabs(numpy.sum(pvts)*(vts[1]-vts[0])\ -edf(Orbit([R,vR,0.,phi]),marginalizeVperp=True,integrate_method='rk6_c')) < 10.**-3.5, 'evolveddiskdf call w/ marginalizeVperp does not work' #l=270 edf = evolveddiskdf(idf, pot=pot, to=-10.) R, phi, vT = numpy.sin(numpy.pi / 6.), -numpy.pi / 3., 0.7 #l=30 degree vrs = numpy.linspace(-1., 1., 101) pvrs = numpy.array( [edf(Orbit([R, vr, vT, phi]), integrate_method='rk6_c') for vr in vrs]) assert numpy.fabs(numpy.log(numpy.sum(pvrs)*(vrs[1]-vrs[0]))\ -edf(Orbit([R,0.,vT,phi]), marginalizeVperp=True, integrate_method='rk6_c',log=True, nsigma=4)) < 10.**-2.5, 'evolveddiskdf call w/ marginalizeVperp does not work' return None
def test_call_marginalizevlos(): from galpy.orbit import Orbit idf = dehnendf(beta=0.) pot = [ LogarithmicHaloPotential(normalize=1.), EllipticalDiskPotential(twophio=0.001) ] #very mild non-axi edf = evolveddiskdf(idf, pot=pot[0], to=-10.) #one with just one potential #l=0 R, phi, vT = 0.8, 0., 0.7 vrs = numpy.linspace(-1., 1., 101) pvrs = numpy.array( [edf(Orbit([R, vr, vT, phi]), integrate_method='rk6_c') for vr in vrs]) assert numpy.fabs(numpy.log(numpy.sum(pvrs)*(vrs[1]-vrs[0]))\ -edf(Orbit([R,0.,vT,phi]),marginalizeVlos=True,integrate_method='rk6_c',log=True)) < 10.**-4., 'diskdf call w/ marginalizeVlos does not work' #l=270, this DF has some issues, but it suffices to test the mechanics of the code edf = evolveddiskdf(idf, pot=pot, to=-10.) R, phi, vR = numpy.sin(numpy.pi / 6.), -numpy.pi / 3., 0.4 #l=30 degree vts = numpy.linspace(0.3, 1.5, 101) pvts = numpy.array( [edf(Orbit([R, vR, vt, phi]), integrate_method='rk6_c') for vt in vts]) assert numpy.fabs(numpy.sum(pvts)*(vts[1]-vts[0])\ -edf(Orbit([R,vR,0.,phi]), marginalizeVlos=True, integrate_method='rk6_c', nsigma=4)) < 10.**-3.5, 'diskdf call w/ marginalizeVlos does not work' return None
def test_sigmar_wlog_constbeta_diffdens_powerlaw(): from galpy.potential import LogarithmicHaloPotential lp = LogarithmicHaloPotential(normalize=1., q=1.) rs = numpy.linspace(0.001, 5., 101) # general beta and r^-gamma --> sigma = vc/sqrt(gamma-2beta) gamma, beta = 1., 0. assert numpy.all( numpy.fabs( numpy.array([ jeans.sigmar(lp, r, beta=beta, dens=lambda r: r**-gamma) for r in rs ]) - 1. / numpy.sqrt(gamma - 2. * beta)) < 1e-10 ), 'Radial sigma computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential, beta=0, and power-law density r^-1' gamma, beta = 3., 0.5 assert numpy.all( numpy.fabs( numpy.array([ jeans.sigmar(lp, r, beta=beta, dens=lambda r: r**-gamma) for r in rs ]) - 1. / numpy.sqrt(gamma - 2. * beta)) < 1e-10 ), 'Radial sigma computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential, beta=0.5, and power-law density r^-3' gamma, beta = 0., -0.5 assert numpy.all( numpy.fabs( numpy.array([ jeans.sigmar(lp, r, beta=beta, dens=lambda r: r**-gamma) for r in rs ]) - 1. / numpy.sqrt(gamma - 2. * beta)) < 1e-10 ), 'Radial sigma computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential, beta=-0.5, and power-law density r^0' return None
def test_sigmar_wlog_linbeta(): # for log halo, dens ~ r^-gamma, and beta = -b x r --> # sigmar = vc sqrt( scipy.special.gamma(-gamma)*scipy.special.gammaincc(-gamma,2*b*r)/[(2*b*r)**-gamma*exp(-2*b*r)] from scipy import special from galpy.potential import LogarithmicHaloPotential lp = LogarithmicHaloPotential(normalize=1., q=1.) rs = numpy.linspace(0.001, 5., 101) gamma, b = -0.1, 3. assert numpy.all( numpy.fabs( numpy.array([ jeans.sigmar( lp, r, beta=lambda x: -b * x, dens=lambda x: x**-gamma) - numpy.sqrt( special.gamma(-gamma) * special.gammaincc(-gamma, 2 * b * r) / ((2 * b * r)**-gamma * numpy.exp(-2. * b * r))) for r in rs ])) < 1e-10 ), 'Radial sigma computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential, beta= -b*r, and dens ~ r^-gamma' gamma, b = -0.5, 4. assert numpy.all( numpy.fabs( numpy.array([ jeans.sigmar( lp, r, beta=lambda x: -b * x, dens=lambda x: x**-gamma) - numpy.sqrt( special.gamma(-gamma) * special.gammaincc(-gamma, 2 * b * r) / ((2 * b * r)**-gamma * numpy.exp(-2. * b * r))) for r in rs ])) < 1e-10 ), 'Radial sigma computed w/ spherical Jeans equation incorrect for LogarithmicHaloPotential, beta= -b*r, and dens ~ r^-gamma' return None
def test_impulse_deltav_plummerstream_curved_subhalo_perpendicular(): from galpy.util import conversion from galpy.potential import LogarithmicHaloPotential from galpy.df import impulse_deltav_plummer_curvedstream, \ impulse_deltav_plummerstream_curvedstream R0, V0= 8., 220. lp= LogarithmicHaloPotential(normalize=1.,q=0.9) tol= -5. GM= 10.**-2./conversion.mass_in_1010msol(V0,R0) rs= 0.625/R0 dt= 0.01*rs/(numpy.pi/4.) kick= impulse_deltav_plummer_curvedstream(\ numpy.array([[.5,0.1,0.2]]), numpy.array([[1.2,0.,0.]]), rs, numpy.array([0.1,numpy.pi/4.,0.1]), numpy.array([1.2,0.,0.]), numpy.array([.5,0.1,0.2]), GM,rs) stream_kick= impulse_deltav_plummerstream_curvedstream(\ numpy.array([[.5,0.1,0.2]]), numpy.array([[1.2,0.,0.]]), numpy.array([0.]), rs, numpy.array([0.1,numpy.pi/4.,0.1]), numpy.array([1.2,0.,0.]), numpy.array([.5,0.1,0.2]), lambda t: GM/dt,rs,lp,-dt/2.,dt/2.) # Should be equal assert numpy.all(numpy.fabs((kick-stream_kick)/kick) < 10.**tol), 'Curved, short Plummer-stream kick does not agree with curved Plummer-sphere kick by %g' % (numpy.amax(numpy.fabs((kick-stream_kick)/kick))) return None
def test_mildnonaxi_meanvr_grid(): # Test that for a close to axisymmetric potential, the mean vr is close to zero idf= dehnendf(beta=0.) pot= [LogarithmicHaloPotential(normalize=1.), SteadyLogSpiralPotential(A=-0.005,omegas=0.2)] #very mild non-axi edf= evolveddiskdf(idf,pot=pot,to=-10.) mvr, grid= edf.meanvR(0.9,phi=0.2,integrate_method='rk6_c',grid=True, returnGrid=True,gridpoints=_GRIDPOINTS) assert numpy.fabs(mvr) < 0.001, 'meanvR of evolveddiskdf for axisymmetric potential is not equal to zero' mvr= edf.meanvR(0.9,phi=0.2,integrate_method='rk6_c',grid=grid) assert numpy.fabs(mvr) < 0.001, 'meanvR of evolveddiskdf for axisymmetric potential is not equal to zero when calculated with pre-computed grid' #Pre-compute surfmass and use it, first test that grid is properly returned when given smass, ngrid= edf.vmomentsurfacemass(0.9,0,0,phi=0.2, integrate_method='rk6_c', grid=grid,gridpoints=_GRIDPOINTS, returnGrid=True) assert ngrid == grid, 'grid returned by vmomentsurfacemass w/ grid input is not the same as the input' #Pre-compute surfmass and use it nsmass= edf.vmomentsurfacemass(0.9,0,0,phi=0.2, integrate_method='rk6_c', grid=True,gridpoints=_GRIDPOINTS) assert numpy.fabs(smass-nsmass) < 0.001, 'surfacemass computed w/ and w/o returnGrid are not the same' mvr= edf.meanvR(0.9,phi=0.2,integrate_method='rk6_c',grid=grid, surfacemass=smass) assert numpy.fabs(mvr) < 0.001, 'meanvR of evolveddiskdf for axisymmetric potential is not equal to zero when calculated with pre-computed grid and surfacemass' global _maxi_meanvr _maxi_meanvr= mvr global _maxi_surfacemass _maxi_surfacemass= smass return None
def test_mildnonaxi_oortK_grid(): # Test that for a close to axisymmetric potential, the oortK is close to zero idf = dehnendf(beta=0.) pot = [ LogarithmicHaloPotential(normalize=1.), EllipticalDiskPotential(twophio=0.001) ] #very mild non-axi edf = evolveddiskdf(idf, pot=pot, to=-10.) ok, grid, dgridR, dgridphi=\ edf.oortK(0.9,phi=0.2,integrate_method='rk6_c', grid=True,derivRGrid=True,derivphiGrid=True, returnGrids=True, gridpoints=_GRIDPOINTS,derivGridpoints=_GRIDPOINTS) assert numpy.fabs( ok ) < 0.005, 'oortK of evolveddiskdf for axisymmetric potential is not equal to that of initial DF' ok = edf.oortK(0.9, phi=0.2, integrate_method='rk6_c', grid=grid, derivRGrid=dgridR, derivphiGrid=dgridphi, gridpoints=_GRIDPOINTS, derivGridpoints=_GRIDPOINTS) assert numpy.fabs( ok ) < 0.005, 'oortK of evolveddiskdf for axisymmetric potential is not equal to that of initial DF when calculated with pre-computed grid' return None
def test_actionAngleTorus_interppot_freqs(): from galpy.actionAngle import actionAngleTorus from galpy.potential import LogarithmicHaloPotential, interpRZPotential lp = LogarithmicHaloPotential(normalize=1.) ip = interpRZPotential(RZPot=lp, interpPot=True, interpDens=True, interpRforce=True, interpzforce=True, enable_c=True) aAT = actionAngleTorus(pot=lp) aATi = actionAngleTorus(pot=ip) jr, jphi, jz = 0.05, 1.1, 0.02 om = aAT.Freqs(jr, jphi, jz) omi = aATi.Freqs(jr, jphi, jz) assert numpy.fabs( (om[0] - omi[0]) / om[0] ) < 0.2, 'Radial frequency computed using the torus machine does not agree between potential and interpolated potential' assert numpy.fabs( (om[1] - omi[1]) / om[1] ) < 0.2, 'Azimuthal frequency computed using the torus machine does not agree between potential and interpolated potential' assert numpy.fabs( (om[2] - omi[2]) / om[2] ) < 0.8, 'Vertical frequency computed using the torus machine does not agree between potential and interpolated potential' return None
def test_mildnonaxi_oortA_grid_tlist(): # Test that for a close to axisymmetric potential, the oortA is close to the value of the initial DF idf = dehnendf(beta=0.) pot = [ LogarithmicHaloPotential(normalize=1.), EllipticalDiskPotential(twophio=0.001) ] #very mild non-axi edf = evolveddiskdf(idf, pot=pot, to=-10.) oa, grid, dgridR, dgridphi=\ edf.oortA(0.9,t=[0.,-2.5,-5.,-7.5,-10.], phi=0.2,integrate_method='rk6_c', grid=True,derivRGrid=True,derivphiGrid=True, returnGrids=True, gridpoints=_GRIDPOINTS,derivGridpoints=_GRIDPOINTS) ioa = idf.oortA(0.9) assert numpy.all( numpy.fabs(oa - ioa) < 0.005 ), 'oortA of evolveddiskdf for axisymmetric potential is not equal to that of initial DF' oa = edf.oortA(0.9, t=[0., -2.5, -5., -7.5, -10.], phi=0.2, integrate_method='rk6_c', grid=grid, derivRGrid=dgridR, derivphiGrid=dgridphi, gridpoints=_GRIDPOINTS, derivGridpoints=_GRIDPOINTS) assert numpy.all( numpy.fabs(oa - ioa) < 0.005 ), 'oortA of evolveddiskdf for axisymmetric potential is not equal to that of initial DF when calculated with pre-computed grid' return None
def test_trailingwleadingimpact_error(): #Imports from galpy.df import streamgapdf from galpy.orbit import Orbit from galpy.potential import LogarithmicHaloPotential from galpy.actionAngle import actionAngleIsochroneApprox from galpy.util import conversion #for unit conversions lp = LogarithmicHaloPotential(normalize=1., q=0.9) aAI = actionAngleIsochroneApprox(pot=lp, b=0.8) prog_unp_peri = Orbit([ 2.6556151742081835, 0.2183747276300308, 0.67876510797240575, -2.0143395648974671, -0.3273737682604374, 0.24218273922966019 ]) V0, R0 = 220., 8. sigv = 0.365 * (10. / 2.)**(1. / 3.) # km/s with pytest.raises(ValueError) as excinfo: dum= streamgapdf(sigv/V0,progenitor=prog_unp_peri,pot=lp,aA=aAI, leading=False,nTrackChunks=26, nTrackIterations=1, sigMeanOffset=4.5, tdisrupt=10.88\ /conversion.time_in_Gyr(V0,R0), Vnorm=V0,Rnorm=R0, impactb=0., subhalovel=numpy.array([6.82200571,132.7700529, 149.4174464])/V0, timpact=0.88/conversion.time_in_Gyr(V0,R0), impact_angle=2.34, GM=10.**-2.\ /conversion.mass_in_1010msol(V0,R0), rs=0.625/R0) return None
def test_actionAngleTorus_AutoFitWarning(): from galpy.potential import LogarithmicHaloPotential from galpy.actionAngle import actionAngleTorus lp= LogarithmicHaloPotential(normalize=1.,q=0.9) aAT= actionAngleTorus(pot=lp,tol=10.**-8.) # These should give warnings jr, jp, jz= 0.27209033, 1.80253892, 0.6078445 ar, ap, az= numpy.array([1.95732492]), numpy.array([6.16753224]), \ numpy.array([4.08233059]) #Turn warnings into errors to test for them import warnings with warnings.catch_warnings(record=True) as w: if PY2: reset_warning_registry('galpy') warnings.simplefilter("always",galpyWarning) aAT(jr,jp,jz,ar,ap,az) # Should raise warning bc of Autofit, might raise others raisedWarning= False for wa in w: raisedWarning= (str(wa.message) == "actionAngleTorus' AutoFit exited with non-zero return status -3: Fit failed the goal by more than 2") if raisedWarning: break assert raisedWarning, "actionAngleTorus with flattened LogarithmicHaloPotential and a particular orbit should have thrown a warning, but didn't" with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always",galpyWarning) aAT.xvFreqs(jr,jp,jz,ar,ap,az) # Should raise warning bc of Autofit, might raise others raisedWarning= False for wa in w: raisedWarning= (str(wa.message) == "actionAngleTorus' AutoFit exited with non-zero return status -3: Fit failed the goal by more than 2") if raisedWarning: break assert raisedWarning, "actionAngleTorus with flattened LogarithmicHaloPotential and a particular orbit should have thrown a warning, but didn't" with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always",galpyWarning) aAT.Freqs(jr,jp,jz) # Should raise warning bc of Autofit, might raise others raisedWarning= False for wa in w: raisedWarning= (str(wa.message) == "actionAngleTorus' AutoFit exited with non-zero return status -3: Fit failed the goal by more than 2") if raisedWarning: break assert raisedWarning, "actionAngleTorus with flattened LogarithmicHaloPotential and a particular orbit should have thrown a warning, but didn't" with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always",galpyWarning) aAT.hessianFreqs(jr,jp,jz) # Should raise warning bc of Autofit, might raise others raisedWarning= False for wa in w: raisedWarning= (str(wa.message) == "actionAngleTorus' AutoFit exited with non-zero return status -3: Fit failed the goal by more than 2") if raisedWarning: break assert raisedWarning, "actionAngleTorus with flattened LogarithmicHaloPotential and a particular orbit should have thrown a warning, but didn't" with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always",galpyWarning) aAT.xvJacobianFreqs(jr,jp,jz,ar,ap,az) # Should raise warning bc of Autofit, might raise others raisedWarning= False for wa in w: raisedWarning= (str(wa.message) == "actionAngleTorus' AutoFit exited with non-zero return status -3: Fit failed the goal by more than 2") if raisedWarning: break assert raisedWarning, "actionAngleTorus with flattened LogarithmicHaloPotential and a particular orbit should have thrown a warning, but didn't" return None
def test_mildnonaxi_meanvr_direct(): # Test that for an axisymmetric potential, the mean vr is close to zero # We do this for an axisymmetric potential, bc otherwise it takes too long idf= dehnendf(beta=0.) pot= [LogarithmicHaloPotential(normalize=1.)] edf= evolveddiskdf(idf,pot=pot,to=-10.) mvr= edf.meanvR(0.9,phi=0.2,integrate_method='rk6_c',grid=False) assert numpy.fabs(mvr) < 0.001, 'meanvR of evolveddiskdf for axisymmetric potential is not equal to zero when calculated directly' return None
def test_mildnonaxi_meanvt_direct(): # Test that for a close to axisymmetric potential, the mean vt is close to that of the initial DF # We do this for an axisymmetric potential, bc otherwise it takes too long idf= dehnendf(beta=0.) pot= [LogarithmicHaloPotential(normalize=1.)] edf= evolveddiskdf(idf,pot=pot,to=-10.) mvt= edf.meanvT(0.9,phi=0.2,integrate_method='rk6_c',grid=False) assert numpy.fabs(mvt-idf.meanvT(0.9)) < 0.001, 'meanvT of evolveddiskdf for axisymmetric potential is not equal to that of the initial dehnendf when using direct integration' return None
def test_mildnonaxi_sigmat2_direct(): # Test that for an axisymmetric potential, the sigmaT2 is close to the value of the initial DF # We do this for an axisymmetric potential, bc otherwise it takes too long idf= dehnendf(beta=0.) pot= [LogarithmicHaloPotential(normalize=1.)] edf= evolveddiskdf(idf,pot=pot,to=-10.) st2= edf.sigmaT2(0.9,phi=0.2,integrate_method='rk6_c',grid=False) ist2= idf.sigmaT2(0.9) assert numpy.fabs(numpy.log(st2)-numpy.log(ist2)) < 0.025, 'sigmat2 of evolveddiskdf for axisymmetric potential is not equal to that of initial DF when calculated directly' return None
def setup_gd1model(leading=True, timpact=None, hernquist=True, age=9., singleImpact=False, length_factor=1., **kwargs): lp = LogarithmicHaloPotential(normalize=1., q=0.9) aAI = actionAngleIsochroneApprox(pot=lp, b=0.8) obs = Orbit([ 1.56148083, 0.35081535, -1.15481504, 0.88719443, -0.47713334, 0.12019596 ]) sigv = 0.365 / 2. * (9. / age) #km/s, /2 bc tdis x2, adjust for diff. age if timpact is None: sdf = streamdf(sigv / 220., progenitor=obs, pot=lp, aA=aAI, leading=leading, nTrackChunks=11, tdisrupt=age / bovy_conversion.time_in_Gyr(V0, R0), Vnorm=V0, Rnorm=R0) elif singleImpact: sdf = streamgapdf(sigv / 220., progenitor=obs, pot=lp, aA=aAI, leading=leading, nTrackChunks=11, tdisrupt=age / bovy_conversion.time_in_Gyr(V0, R0), Vnorm=V0, Rnorm=R0, timpact=timpact, spline_order=3, hernquist=hernquist, **kwargs) else: sdf = streampepperdf(sigv / 220., progenitor=obs, pot=lp, aA=aAI, leading=leading, nTrackChunks=101, tdisrupt=age / bovy_conversion.time_in_Gyr(V0, R0), Vnorm=V0, Rnorm=R0, timpact=timpact, spline_order=1, hernquist=hernquist, length_factor=length_factor) sdf.turn_physical_off() return sdf
def test_mildnonaxi_meanvt_direct_tlist(): # Shouldn't work idf= dehnendf(beta=0.) pot= [LogarithmicHaloPotential(normalize=1.)] edf= evolveddiskdf(idf,pot=pot,to=-10.) try: edf.meanvT(0.9,t=[0.,-2.5,-5.,-7.5,-10.], phi=0.2,integrate_method='rk6_c',grid=False) except IOError: pass else: raise AssertionError('direct evolveddiskdf calculation of meanvT w/ list of times did not raise IOError') return None
def test_mildnonaxi_vertexdev_direct(): # Test that for an axisymmetric potential, the vertex deviation is close zero # We do this for an axisymmetric potential, bc otherwise it takes too long idf = dehnendf(beta=0.) pot = [LogarithmicHaloPotential(normalize=1.)] edf = evolveddiskdf(idf, pot=pot, to=-10.) vdev = edf.vertexdev(0.9, phi=0.2, integrate_method='rk6_c', grid=False) assert numpy.fabs( vdev ) < 0.01 / 180. * numpy.pi, 'vertexdev of evolveddiskdf for axisymmetric potential is not equal to zero when calculated directly' return None
def test_call_special(): from galpy.orbit import Orbit idf= dehnendf(beta=0.) pot= [LogarithmicHaloPotential(normalize=1.), EllipticalDiskPotential(twophio=0.001)] #very mild non-axi edf= evolveddiskdf(idf,pot=pot,to=-10.) o= Orbit([0.9,0.1,1.1,2.]) #call w/ and w/o explicit t assert numpy.fabs(numpy.log(edf(o,0.))-numpy.log(edf(o))) < 10.**-10., 'edf.__call__ w/ explicit t=0. and w/o t do not give the same answer' #call must get Orbit, otherwise error try: edf(0.9,0.1,1.1,2.) except IOError: pass else: raise AssertionError('edf.__call__ w/o Orbit input did not raise IOError') #Call w/ list, but just to assert numpy.fabs(numpy.log(edf(o,[-10.]))-numpy.log(idf(o))) < 10.**-10., 'edf.__call__ w/ tlist set to [to] did not return initial DF' #Call w/ just to assert numpy.fabs(numpy.log(edf(o,-10.))-numpy.log(idf(o))) < 10.**-10., 'edf.__call__ w/ tlist set to [to] did not return initial DF' #also w/ log assert numpy.fabs(edf(o,[-10.],log=True)-numpy.log(idf(o))) < 10.**-10., 'edf.__call__ w/ tlist set to [to] did not return initial DF (log)' assert numpy.fabs(edf(o,-10.,log=True)-numpy.log(idf(o))) < 10.**-10., 'edf.__call__ w/ tlist set to [to] did not return initial DF (log)' # Tests w/ odeint: tlist codeint= edf(o,[0.,-2.5,-5.,-7.5,-10.],integrate_method='odeint',log=True) crk6c= edf(o,[0.,-2.5,-5.,-7.5,-10.],integrate_method='rk6_c',log=True) assert numpy.all(numpy.fabs(codeint-crk6c) < 10.**-4.), 'edf.__call__ w/ odeint and tlist does not give the same result as w/ rk6_c' # Crazy orbit w/ tlist crk6c= edf(Orbit([3.,1.,-1.,2.]),[0.],integrate_method='odeint',log=True) assert crk6c < -20., 'crazy orbit does not have DF equal to zero' # deriv w/ odeint codeint= edf(o,[0.,-2.5,-5.,-7.5,-10.],integrate_method='odeint', deriv='R') crk6c= edf(o,[0.,-2.5,-5.,-7.5,-10.],integrate_method='rk6_c',deriv='R') assert numpy.all(numpy.fabs(codeint-crk6c) < 10.**-4.), 'edf.__call__ w/ odeint and tlist does not give the same result as w/ rk6_c (deriv=R)' # deriv w/ len(tlist)=1 crk6c= edf(o,[0.],integrate_method='rk6_c',deriv='R') crk6c2= edf(o,0.,integrate_method='rk6_c',deriv='R') assert numpy.all(numpy.fabs(crk6c-crk6c2) < 10.**-4.), 'edf.__call__ w/ tlist consisting of one time and just a scalar time do not agree' #Call w/ just to and deriv assert numpy.fabs(edf(o,-10.,deriv='R')-idf(o)*idf._dlnfdR(o._orb.vxvv[0],o._orb.vxvv[1],o._orb.vxvv[2])) < 10.**-10., 'edf.__call__ w/ to did not return initial DF (deriv=R)' assert numpy.fabs(edf(o,-10.,deriv='phi')) < 10.**-10., 'edf.__call__ w/ to did not return initial DF (deriv=phi)' # Call w/ just one t and odeint codeint= edf(o,0,integrate_method='odeint',log=True) crk6c= edf(o,0.,integrate_method='rk6_c',log=True) assert numpy.fabs(codeint-crk6c) < 10.**-4., 'edf.__call__ w/ odeint and tlist does not give the same result as w/ rk6_c' # Call w/ just one t and fallback to odeint # turn off C edf._pot[0].hasC= False edf._pot[0].hasC_dxdv= False codeint= edf(o,0,integrate_method='dopr54_c',log=True) assert numpy.fabs(codeint-crk6c) < 10.**-4., 'edf.__call__ w/ odeint and tlist does not give the same result as w/ rk6_c' # Call w/ just one t and fallback to leaprog cleapfrog= edf(o,0,integrate_method='leapfrog_c',log=True) assert numpy.fabs(cleapfrog-crk6c) < 10.**-4., 'edf.__call__ w/ odeint and tlist does not give the same result as w/ rk6_c'
def test_setup_diffsetups(): #Test the different ways to setup a qdf object #Test errors try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., aA=aAS,cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/o pot set did not raise exception") try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/o aA set did not raise exception") from galpy.potential import LogarithmicHaloPotential try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=LogarithmicHaloPotential(), aA=aAS,cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/ aA potential different from pot= did not raise exception") #qdf setup with an actionAngleIsochrone instance (issue #190) from galpy.potential import IsochronePotential from galpy.actionAngle import actionAngleIsochrone ip= IsochronePotential(normalize=1.,b=2.) try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=ip, aA=actionAngleIsochrone(ip=ip),cutcounter=True) except: raise raise AssertionError('quasi-isothermaldf setup w/ an actionAngleIsochrone instance failed') #qdf setup with an actionAngleIsochrone instance should raise error if potentials are not the same ip= IsochronePotential(normalize=1.,b=2.) try: qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=ip, aA=actionAngleIsochrone(ip=IsochronePotential(normalize=1.,b=2.5)), cutcounter=True) except IOError: pass else: raise AssertionError("qdf setup w/ aA potential different from pot= did not raise exception") #precompute qdf= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True, _precomputerg=True) qdfnpc= quasiisothermaldf(1./4.,0.2,0.1,1.,1., pot=MWPotential,aA=aAS,cutcounter=True, _precomputerg=False) assert numpy.fabs(qdf.rg(1.1)-qdfnpc.rg(1.1)) < 10.**-5., 'rg calculated from qdf instance w/ precomputerg set is not the same as that computed from an instance w/o it set'
def test_mildnonaxi_vertexdev_grid(): # Test that for a close to axisymmetric potential, the vertex deviation is close to zero idf= dehnendf(beta=0.) pot= [LogarithmicHaloPotential(normalize=1.), SteadyLogSpiralPotential(A=-0.005,omegas=0.2)] #very mild non-axi edf= evolveddiskdf(idf,pot=pot,to=-10.) vdev, grid= edf.vertexdev(0.9,phi=0.2,integrate_method='rk6_c',grid=True, returnGrid=True,gridpoints=_GRIDPOINTS) assert numpy.fabs(vdev) < 2., 'vertexdev of evolveddiskdf for axisymmetric potential is not close to zero' #2 is pretty big, but the weak spiral creates that vdev= edf.vertexdev(0.9,phi=0.2,integrate_method='rk6_c',grid=grid, gridpoints=_GRIDPOINTS) assert numpy.fabs(vdev) < 2., 'vertexdev of evolveddiskdf for axisymmetric potential is not equal zero when calculated with pre-computed grid' vdev= edf.vertexdev(0.9,phi=0.2,integrate_method='rk6_c',grid=grid, sigmaR2=_maxi_sigmar2,sigmaT2=_maxi_sigmat2, sigmaRT=_maxi_sigmart,gridpoints=_GRIDPOINTS) assert numpy.fabs(vdev) < 2., 'sigmart of evolveddiskdf for axisymmetric potential is not equal to zero when calculated with pre-computed sigmaR2,sigmaT2,sigmaRT' return None