def test_mass_in_msol(): #Test the scaling, should be velocity^2 x position vofid, rofid = 200., 8. assert numpy.fabs(4. * bovy_conversion.mass_in_msol(vofid, rofid) / bovy_conversion.mass_in_msol(2. * vofid, rofid) - 1.) < 10.**-10., 'mass_in_msol did not work as expected' assert numpy.fabs(2. * bovy_conversion.mass_in_msol(vofid, rofid) / bovy_conversion.mass_in_msol(vofid, 2 * rofid) - 1.) < 10.**-10., 'mass_in_msol did not work as expected' return None
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 test_ChandrasekharDynamicalFrictionForce_varLambda(): # Test that dynamical friction with variable Lambda for small r ranges # gives ~ the same result as using a constant Lambda that is the mean of # the variable lambda # Also tests that giving an axisymmetric list of potentials for the # density works from galpy.util import bovy_conversion from galpy.orbit import Orbit ro, vo = 8., 220. # Parameters GMs = 10.**9. / bovy_conversion.mass_in_msol(vo, ro) r_init = 3. dt = 2. / bovy_conversion.time_in_Gyr(vo, ro) # Compute evolution with variable ln Lambda cdf= potential.ChandrasekharDynamicalFrictionForce(\ GMs=GMs,rhm=0.125, dens=potential.MWPotential2014,sigmar=lambda r: 1./numpy.sqrt(2.)) o = Orbit([r_init, 0., 1., 0., 0., 0.]) ts = numpy.linspace(0., dt, 1001) o.integrate(ts, [potential.MWPotential2014, cdf], method='odeint') lnLs = numpy.array([ cdf.lnLambda(r, v) for (r, v) in zip( o.r(ts), numpy.sqrt(o.vx(ts)**2. + o.vy(ts)**2. + o.vz(ts)**2.)) ]) cdfc= potential.ChandrasekharDynamicalFrictionForce(\ GMs=GMs,rhm=0.125,const_lnLambda=numpy.mean(lnLs), dens=potential.MWPotential2014,sigmar=lambda r: 1./numpy.sqrt(2.)) oc = o() oc.integrate(ts, [potential.MWPotential2014, cdfc], method='odeint') assert numpy.fabs( oc.r(ts[-1]) - o.r(ts[-1]) ) < 0.05, 'ChandrasekharDynamicalFrictionForce with variable lnLambda for a short radial range is not close to the calculation using a constant lnLambda' return None
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 test_ChandrasekharDynamicalFrictionForce_constLambda(): # Test that the ChandrasekharDynamicalFrictionForce with constant Lambda # agrees with analytical solutions for circular orbits: # assuming that a mass remains on a circular orbit in an isothermal halo # with velocity dispersion sigma and for constant Lambda: # r_final^2 - r_initial^2 = -0.604 ln(Lambda) GM/sigma t # (e.g., B&T08, p. 648) from galpy.util import bovy_conversion from galpy.orbit import Orbit ro, vo = 8., 220. # Parameters GMs = 10.**9. / bovy_conversion.mass_in_msol(vo, ro) const_lnLambda = 7. r_init = 2. dt = 2. / bovy_conversion.time_in_Gyr(vo, ro) # Compute lp = potential.LogarithmicHaloPotential(normalize=1., q=1.) cdfc= potential.ChandrasekharDynamicalFrictionForce(\ GMs=GMs,const_lnLambda=const_lnLambda, dens=lp) # don't provide sigmar, so it gets computed using galpy.df.jeans o = Orbit([r_init, 0., 1., 0., 0., 0.]) ts = numpy.linspace(0., dt, 1001) o.integrate(ts, [lp, cdfc], method='odeint') r_pred = numpy.sqrt(o.r()**2. - 0.604 * const_lnLambda * GMs * numpy.sqrt(2.) * dt) assert numpy.fabs( r_pred - o.r(ts[-1]) ) < 0.01, 'ChandrasekharDynamicalFrictionForce with constant lnLambda for circular orbits does not agree with analytical prediction' return None
def MWBHZfo(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) ''' 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] zf1 = evaluatezforces(MWBH, Rpkpc/Rskpc,zkpc/Rskpc)*bovy_conversion.force_in_kmsMyr(Vs,Rskpc) ''' MWPotential2014wBH = [ MWPotential2014, KeplerPotential(amp=4 * 10**6. / bovy_conversion.mass_in_msol(par.Vs, par.Rskpc)) ] zf1 = evaluatezforces(MWPotential2014wBH, Rpkpc / Rskpc, zkpc / Rskpc) * bovy_conversion.force_in_kmsMyr(Vs, Rskpc) Excz = zf1 * conversion * math.sin(b) #s-1 return Excz
def __init__(self,progenitor_mass,progenitor=None,pot=None, tdisrupt=None,leading=True, meankvec=[2.,0.,0.3,0.,0.,0.], sigkvec=[0.4,0.,0.4,0.5,0.5,0.], ro=None,vo=None): """ NAME: __init__ PURPOSE: Initialize a stream spray DF model of a tidal stream INPUT: progenitor_mass - mass of the progenitor (can be Quantity) tdisrupt= (5 Gyr) time since start of disruption (can be Quantity) leading= (True) if True, model the leading part of the stream if False, model the trailing part progenitor= progenitor orbit as Orbit instance (will be re-integrated, so don't bother integrating the orbit before) meankvec= (Fardal+2015-ish defaults) sigkvec= (Fardal+2015-ish defaults) OUTPUT: Instance HISTORY: 2018-07-31 - Written - Bovy (UofT) """ df.__init__(self,ro=ro,vo=vo) if _APY_LOADED and isinstance(progenitor_mass,units.Quantity): progenitor_mass= progenitor_mass.to(units.Msun).value\ /bovy_conversion.mass_in_msol(self._vo,self._ro) self._progenitor_mass= progenitor_mass if tdisrupt is None: self._tdisrupt= 5./bovy_conversion.time_in_Gyr(self._vo,self._ro) else: if _APY_LOADED and isinstance(tdisrupt,units.Quantity): tdisrupt= tdisrupt.to(units.Gyr).value\ /bovy_conversion.time_in_Gyr(self._vo,self._ro) self._tdisrupt= tdisrupt if pot is None: #pragma: no cover raise IOError("pot= must be set") self._pot= flatten_potential(pot) self._progenitor= progenitor() self._progenitor_times= numpy.linspace(0.,-self._tdisrupt,10001) self._progenitor.integrate(self._progenitor_times,self._pot) self._meankvec= numpy.array(meankvec) self._sigkvec= numpy.array(sigkvec) if leading: self._meankvec*= -1. return None
def powerlaw_wcutoff(massrange,cutoff): accept= False while not accept: prop= (10.**-(massrange[0]/2.)+(10.**-(massrange[1]/2.)\ -10.**(-massrange[0]/2.))\ *numpy.random.uniform())**-2. if numpy.random.uniform() < numpy.exp(-10.**cutoff/prop): accept= True return prop/bovy_conversion.mass_in_msol(V0,R0)
def powerlaw_wcutoff(massrange, cutoff): accept = False while not accept: prop= (10.**-(massrange[0]/2.)+(10.**-(massrange[1]/2.)\ -10.**(-massrange[0]/2.))\ *numpy.random.uniform())**-2. if numpy.random.uniform() < numpy.exp(-10.**cutoff / prop): accept = True return prop / bovy_conversion.mass_in_msol(V0, R0)
def GMs(self,gms): if _APY_LOADED and isinstance(gms,units.Quantity): try: gms= gms.to(units.Msun).value\ /bovy_conversion.mass_in_msol(self._vo,self._ro) except units.UnitConversionError: # Try G x mass try: gms= gms.to(units.pc*units.km**2/units.s**2)\ .value\ /bovy_conversion.mass_in_msol(self._vo,self._ro)\ /bovy_conversion._G except units.UnitConversionError: raise units.UnitConversionError('GMs for %s should have units of mass or G x mass' % (type(self).__name__)) self._amp*= gms/self._ms self._ms= gms # Reset the hash self._force_hash= None return None
def jacobiRadius(m, r, z): galMass = 0. for massElement in MWPotential2014: galMass += massElement.mass(r, z=z) * bovy_conversion.mass_in_msol(220., 8.) #MSun galactocentricDistance = np.sqrt(r**2. + z**2.) return galactocentricDistance * (m / galMass)**(1/3.)
def to_galpy(cluster, do_key_params=False, ro=8.0, vo=220.0): """ Convert stellar positions/velocities, centre of mass, and orbital position and velocity to galpy units Parameters ---------- cluster : class StarCluster do_key_params : bool call key_params to calculate key parameters after unit change (default: False) ro : float galpy radius scaling parameter vo : float galpy velocity scaling parameter Returns ------- None History: ------- 2018 - Written - Webb (UofT) """ if cluster.units != "kpckms" and cluster.units != "galpy": cluster.to_kpckms(do_key_params=False) if cluster.units == "kpckms": cluster.m = cluster.m / bovy_conversion.mass_in_msol(ro=ro, vo=vo) cluster.x /= ro cluster.y /= ro cluster.z /= ro cluster.vx /= vo cluster.vy /= vo cluster.vz /= vo cluster.xc /= ro cluster.yc /= ro cluster.zc /= ro cluster.vxc /= vo cluster.vyc /= vo cluster.vzc /= vo cluster.xgc /= ro cluster.ygc /= ro cluster.zgc /= ro cluster.vxgc /= vo cluster.vygc /= vo cluster.vzgc /= vo cluster.units = "galpy" cluster.rv3d() if do_key_params: cluster.key_params()
def MWBHZfo(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) MWPotential2014BH= [MWPotential2014,KeplerPotential(amp=4*10**6./bovy_conversion.mass_in_msol(par.Vs,par.Rskpc))] zf1 = evaluatezforces(MWPotential2014BH, Rpkpc/Rskpc,zkpc/Rskpc)*((Vs*1000.)**2.)/(Rskpc*par.kpctom) #m/ss Excz = zf1*math.sin(b)/par.c #s-1 return Excz;
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 test_ChandrasekharDynamicalFrictionForce_pickling(): # Test that ChandrasekharDynamicalFrictionForce objects can/cannot be # pickled as expected import pickle from galpy.util import bovy_conversion ro, vo = 8., 220. # Parameters GMs = 10.**9. / bovy_conversion.mass_in_msol(vo, ro) # sigmar internally computed, should be able to be pickled # Compute evolution with variable ln Lambda cdf= potential.ChandrasekharDynamicalFrictionForce(\ GMs=GMs,rhm=0.125, dens=potential.MWPotential2014, minr=0.5,maxr=2.) pickled = pickle.dumps(cdf) cdfu = pickle.loads(pickled) # Test a few values assert numpy.fabs(cdf.Rforce(1.,0.2,v=[1.,1.,0.])\ -cdfu.Rforce(1.,0.2,v=[1.,1.,0.])) < 1e-10, 'Pickling of ChandrasekharDynamicalFrictionForce object does not work as expected' assert numpy.fabs(cdf.zforce(2.,-0.2,v=[1.,1.,0.])\ -cdfu.zforce(2.,-0.2,v=[1.,1.,0.])) < 1e-10, 'Pickling of ChandrasekharDynamicalFrictionForce object does not work as expected' # Not providing dens = Logarithmic should also work cdf= potential.ChandrasekharDynamicalFrictionForce(\ GMs=GMs,rhm=0.125, minr=0.5,maxr=2.) pickled = pickle.dumps(cdf) cdfu = pickle.loads(pickled) # Test a few values assert numpy.fabs(cdf.Rforce(1.,0.2,v=[1.,1.,0.])\ -cdfu.Rforce(1.,0.2,v=[1.,1.,0.])) < 1e-10, 'Pickling of ChandrasekharDynamicalFrictionForce object does not work as expected' assert numpy.fabs(cdf.zforce(2.,-0.2,v=[1.,1.,0.])\ -cdfu.zforce(2.,-0.2,v=[1.,1.,0.])) < 1e-10, 'Pickling of ChandrasekharDynamicalFrictionForce object does not work as expected' # Providing sigmar as a lambda function gives AttributeError sigmar = lambda r: 1. / r cdf= potential.ChandrasekharDynamicalFrictionForce(\ GMs=GMs,rhm=0.125, dens=potential.MWPotential2014,sigmar=sigmar, minr=0.5,maxr=2.) if PY3: with pytest.raises(AttributeError) as excinfo: pickled = pickle.dumps(cdf) else: with pytest.raises(pickle.PicklingError) as excinfo: pickled = pickle.dumps(cdf) return None
def sample_galpy_potential(pot,n,rmin,rmax,ro=8.,vo=220.,coordinates='cartesian'): ran=np.random.rand(n) rad=np.linspace(rmin,rmax,n) try: menc=pot.mass(rad/ro,z=0,t=0,forceint=False) except: vc= potential.vcirc(pot,rad/ro,phi=0,t=0.,ro=ro,vo=vo,use_physical=False) menc=vc**2.*(rad/ro) menc*=bovy_conversion.mass_in_msol(ro=ro,vo=vo) r=np.interp(ran, menc/menc[-1], rad) phi=2.0*np.pi*np.random.rand(n) theta=np.arccos(1.0-2.0*np.random.rand(n)) x=r*np.sin(theta)*np.cos(phi) y=r*np.sin(theta)*np.sin(phi) z=r*np.cos(theta) sigma_v_1d=vo*potential.vcirc(pot,rad/ro,phi=0,t=0.,ro=ro,vo=vo,use_physical=False)/np.sqrt(3.) vx=np.random.normal(0.,sigma_v_1d,n) vy=np.random.normal(0.,sigma_v_1d,n) vz=np.random.normal(0.,sigma_v_1d,n) if coordinates=='spherical': vr = (vx * np.sin(theta) * np.cos(phi) + vy * np.sin(theta) * np.sin(phi) + vz * np.cos(theta) ) vtheta = ( vx * np.cos(theta) * np.cos(phi) + vy * np.cos(theta) * np.sin(phi) - vz * np.sin(theta) ) vphi = vx * -np.sin(phi) + vy * np.cos(phi) x,y,z=r,phi,theta vx,vy,vz=vr,vphi,vtheta elif coordinates=='cylindrical': x,y,z=bovy_coords.rect_to_cyl(x,y,z) vx,vy,vz=bovy_coords.rect_to_cyl_vec(vx,vy,vz,x,y,z,True) return x,y,z,vx,vy,vz
def VpratioMWBH(Rpkpc): #MWPotential2014.append(KeplerPotential(amp=4*10**6./bovy_conversion.mass_in_msol(par.Vs,par.Rskpc))) #a = vcirc(MWPotential2014,Rpkpc/par.Rskpc) ''' 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] a = vcirc(MWBH,Rpkpc/par.Rskpc) ''' MWPotential2014wBH = [ MWPotential2014, KeplerPotential(amp=4 * 10**6. / bovy_conversion.mass_in_msol(par.Vs, par.Rskpc)) ] a = vcirc(MWPotential2014wBH, Rpkpc / par.Rskpc) return a
def MWBHZfo(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) MWPotential2014.append( KeplerPotential(amp=4 * 10**6. / bovy_conversion.mass_in_msol(Vs, Rskpc))) zf1 = evaluatezforces(MWPotential2014, Rpkpc / Rskpc, zkpc / Rskpc) * bovy_conversion.force_in_kmsMyr(Vs, Rskpc) Excz = zf1 * conversion * math.sin(b) #s-1 return Excz
def test_ChandrasekharDynamicalFrictionForce_evaloutsideminrmaxr(): # Test that dynamical friction returns the expected force when evaluating # outside of the [minr,maxr] range over which sigmar is interpolated: # 0 at r < minr # using sigmar(r) for r > maxr from galpy.util import bovy_conversion ro, vo = 8., 220. # Parameters GMs = 10.**9. / bovy_conversion.mass_in_msol(vo, ro) # Compute evolution with variable ln Lambda sigmar = lambda r: 1. / r cdf= potential.ChandrasekharDynamicalFrictionForce(\ GMs=GMs,rhm=0.125, dens=potential.MWPotential2014,sigmar=sigmar, minr=0.5,maxr=2.) # cdf 2 for checking r > maxr of cdf cdf2= potential.ChandrasekharDynamicalFrictionForce(\ GMs=GMs,rhm=0.125, dens=potential.MWPotential2014,sigmar=sigmar, minr=0.5,maxr=4.) v = [0.1, 0., 0.] # r < minr assert numpy.fabs( cdf.Rforce(0.1, 0., v=v) ) < 1e-16, 'potential.ChandrasekharDynamicalFrictionForce at r < minr not equal to zero' assert numpy.fabs( cdf.zforce(0.1, 0., v=v) ) < 1e-16, 'potential.ChandrasekharDynamicalFrictionForce at r < minr not equal to zero' # r > maxr assert numpy.fabs( cdf.Rforce(3., 0., v=v) - cdf2.Rforce(3., 0., v=v) ) < 1e-10, 'potential.ChandrasekharDynamicalFrictionForce at r > maxr not as expected' assert numpy.fabs( cdf.zforce(3., 0., v=v) - cdf2.zforce(3., 0., v=v) ) < 1e-10, 'potential.ChandrasekharDynamicalFrictionForce at r > maxr not as expected' return None
def pal5_abc(sdf_pepper, options): """ """ # Setup apar grid bins = np.linspace(options.ximin, options.ximax, options.nxi) if options.recompute: # Load density and omega from file outsamp = options.outsamp if not options.batch is None: outsamp = outsamp.replace('.dat', '.%i.dat' % options.batch) sampdata = np.genfromtxt(outsamp, delimiter=',', skip_header=1) nd = 0 else: # Setup saving if os.path.exists(options.outsamp): # First read the file to check apar print('does ' + options.outsamp + ' exist?', os.path.exists(options.outsamp)) bins_file = np.genfromtxt(options.outsamp, delimiter=',', max_rows=1) print(np.amax(np.fabs(bins_file - bins))) assert np.amax( np.fabs(bins_file - bins) ) < 10.**-5., 'bins according to options does not correspond to bins already in outsamp' csvsamp = open(options.outsamp, 'a') sampwriter = csv.writer(csvsamp, delimiter=',') else: csvsamp = open(options.outsamp, 'w') sampwriter = csv.writer(csvsamp, delimiter=',') # First write bins sampwriter.writerow([b for b in bins]) csvsamp.flush() # Setup sampling massrange = simulate_streampepper.parse_mass(options.mass) rs = simulate_streampepper.rs sample_GM= lambda: (10.**((-0.5)*massrange[0])\ +(10.**((-0.5)*massrange[1])\ -10.**((-0.5)*massrange[0]))\ *np.random.uniform())**(1./(-0.5))\ /bovy_conversion.mass_in_msol(V0,R0) sample_rs = lambda x: rs(x * bovy_conversion.mass_in_1010msol(V0, R0) * 10.**10., plummer=options.plummer) rate_range = np.arange(massrange[0] + 0.5, massrange[1] + 0.5, 1) cdmrate= np.sum([simulate_streampepper.\ dNencdm(sdf_pepper,10.**r,Xrs=options.Xrs, plummer=options.plummer, rsfac=options.rsfac) for r in rate_range]) print("Using an overall CDM rate of %f" % cdmrate) # Load Pal 5 data to compare to if options.mockfilename is None: power_data, data_err, data_ppyr, data_ppyi=\ process_pal5_densdata(options) else: power_data, data_err, data_ppyr, data_ppyi, data_py_err=\ process_mock_densdata(options) # Run ABC while True: if not options.recompute: # Simulate a rate l10rate = (np.random.uniform() * (options.ratemax - options.ratemin) + options.ratemin) #### fix to CDM for testing if options.fixcdmrate: print('warning: using only CDM rate') l10rate = 0. rate = 10.**l10rate * cdmrate print(l10rate, rate) # Simulate sdf_pepper.simulate(rate=rate, sample_GM=sample_GM, sample_rs=sample_rs, Xrs=options.Xrs) # Compute density along stream try: samp, binn = np.histogram(get_star_dx(sdf_pepper, n=options.nsamples, returnxi=True), bins=bins) except: continue write_samp = [l10rate] write_samp.extend(list(samp)) sampwriter.writerow(write_samp) csvsamp.flush() else: if nd >= len(densdata): break l10rate = densdata[nd, 0] dens = densdata[nd, 1:] omega = omegadata[nd, 1:] nd += 1 # Convert density to observed density xixi = (bins[1:] + bins[:-1]) / 2. dens = samp # Add errors (Rao-Blackwellize...) for ee in range(options.nerrsim): tdens = dens + np.random.poisson(options.nbg, size=len(dens)) tdens = np.maximum(tdens - options.nbg, np.zeros_like(tdens)) pp = Polynomial.fit(xixi, tdens, deg=options.polydeg, w=1. / np.sqrt(tdens + 1.)) tdens = tdens / pp(xixi) # Compute power spectrum tcsd = signal.csd(tdens, tdens, fs=1. / (xixi[1] - xixi[0]), scaling='spectrum', nperseg=len(xixi))[1].real power = np.sqrt(tcsd * (xixi[-1] - xixi[0])) # Compute bispectrum Bspec, Bpx = bispectrum.bispectrum(np.vstack((tdens, tdens)).T, nfft=len(tdens), wind=7, nsamp=1, overlap=0) ppyr = np.fabs(Bspec[len(Bspec) // 2 + _BISPECIND, len(Bspec) // 2:].real) ppyi = np.fabs(Bspec[len(Bspec) // 2 + _BISPECIND, len(Bspec) // 2:].imag) yield ( l10rate, power, ppyr, ppyi, #np.fabs(power[1]-power_data[1]), #np.fabs(power[2]-power_data[2]), #np.fabs(power[3]-power_data[3]), #np.fabs(np.log(np.mean(tdens[7:17])\ # /np.mean(tdens[107:117]))), #np.fabs(ppyr-data_ppyr)[_BISPECIND], #np.fabs(ppyi-data_ppyi)[_BISPECIND], ee)
def run_simulations(sdf_pepper,sdf_smooth,options): # Setup apar grid apar= numpy.arange(options.amin,options.amax,options.dapar) # Check whether the output files already exist and if so, get the amin, amax, da from them if os.path.exists(options.outdens): # First read the file to check apar apar_file= numpy.genfromtxt(options.outdens,delimiter=',',max_rows=1) print numpy.amax(numpy.fabs(apar_file-apar)) assert numpy.amax(numpy.fabs(apar_file-apar)) < 10.**-5., 'apar according to options does not correspond to apar already in outdens' apar_file= numpy.genfromtxt(options.outomega,delimiter=',',max_rows=1) print numpy.amax(numpy.fabs(apar_file-apar)) assert numpy.amax(numpy.fabs(apar_file-apar)) < 10.**-5., 'apar according to options does not correspond to apar already in outomega' csvdens= open(options.outdens,'a') csvomega= open(options.outomega,'a') denswriter= csv.writer(csvdens,delimiter=',') omegawriter= csv.writer(csvomega,delimiter=',') else: csvdens= open(options.outdens,'w') csvomega= open(options.outomega,'w') denswriter= csv.writer(csvdens,delimiter=',') omegawriter= csv.writer(csvomega,delimiter=',') # First write apar and the smooth calculations denswriter.writerow([a for a in apar]) omegawriter.writerow([a for a in apar]) if sdf_smooth is None and options.stream.lower() == 'gd1like': sdf_smooth= gd1_util.setup_gd1model(age=options.age) elif sdf_smooth is None and options.stream.lower() == 'pal5like': sdf_smooth= pal5_util.setup_pal5model(age=options.age) dens_unp= [sdf_smooth._density_par(a) for a in apar] denswriter.writerow(dens_unp) omega_unp= [sdf_smooth.meanOmega(a,oned=True) for a in apar] omegawriter.writerow(omega_unp) csvdens.flush() csvomega.flush() # Parse mass massrange= parse_mass(options.mass) if len(massrange) == 1: sample_GM= lambda: 10.**(massrange[0]-10.)\ /bovy_conversion.mass_in_1010msol(V0,R0) rate= options.timescdm*dNencdm(sdf_pepper, 10.**massrange[0],Xrs=options.Xrs, plummer=options.plummer, rsfac=options.rsfac, sigma=options.sigma) elif len(massrange) == 2: # Sample from power-law if not options.cutoff is None: sample_GM= lambda: powerlaw_wcutoff(massrange,options.cutoff) elif numpy.fabs(options.massexp+1.5) < 10.**-6.: sample_GM= lambda: 10.**(massrange[0]\ +(massrange[1]-massrange[0])\ *numpy.random.uniform())\ /bovy_conversion.mass_in_msol(V0,R0) else: sample_GM= lambda: (10.**((options.massexp+1.5)*massrange[0])\ +(10.**((options.massexp+1.5)*massrange[1])\ -10.**((options.massexp+1.5)*massrange[0]))\ *numpy.random.uniform())**(1./(options.massexp+1.5))\ /bovy_conversion.mass_in_msol(V0,R0) rate_range= numpy.arange(massrange[0]+0.5,massrange[1]+0.5,1) rate= options.timescdm\ *numpy.sum([dNencdm(sdf_pepper,10.**r,Xrs=options.Xrs, plummer=options.plummer,rsfac=options.rsfac, sigma=options.sigma) for r in rate_range]) if not options.cutoff is None: rate*= integrate.quad(lambda x: x**-1.5\ *numpy.exp(-10.**options.cutoff/x), 10.**massrange[0],10.**massrange[1])[0]\ /integrate.quad(lambda x: x**-1.5, 10.**massrange[0], 10.**massrange[1])[0] print "Using an overall rate of %f" % rate sample_rs= lambda x: rs(x*bovy_conversion.mass_in_1010msol(V0,R0)*10.**10., plummer=options.plummer,rsfac=options.rsfac) # Simulate start= time.time() ns= 0 while True: if options.nsamples is None and time.time() >= (start+options.dt*60.): break elif not options.nsamples is None and ns > options.nsamples: break ns+= 1 sdf_pepper.simulate(rate=rate,sample_GM=sample_GM,sample_rs=sample_rs, Xrs=options.Xrs,sigma=options.sigma/V0) # Compute density and meanOmega and save try: densOmega= numpy.array([sdf_pepper._densityAndOmega_par_approx(a) for a in apar]).T except IndexError: # no hit dens_unp= [sdf_smooth._density_par(a) for a in apar] omega_unp= [sdf_smooth.meanOmega(a,oned=True) for a in apar] denswriter.writerow(dens_unp) omegawriter.writerow(omega_unp) else: denswriter.writerow(list(densOmega[0])) omegawriter.writerow(list(densOmega[1])) csvdens.flush() csvomega.flush() csvdens.close() csvomega.close() return None
def _sample_galpy_potential(pot, n, rmin, rmax, ro=8., vo=220., coordinates='cartesian'): """Generate positions and velocities from galpy potentail Parameters ---------- pot : class galpy potential N : int number of stars in the cluster (default: 1000) rmin : float minimum stellar radius (default: 0.01) rmax : float maximnum stellar radius (default: 100.) ro : float galpy distance scaling parameter vo : float galpy velocity scaling parameter coordinates : str coordinate system to return (default: cartesian) Returns ------- x,y,z,vx,vy,vz : float positions and velocities of generated points History ------- 2020 - Written - Webb (UofT) """ ran = np.random.rand(n) rad = np.linspace(rmin, rmax, n) try: menc = pot.mass(rad / ro, z=0, t=0, forceint=False) except: vc = potential.vcirc(pot, rad / ro, phi=0, t=0., ro=ro, vo=vo, use_physical=False) menc = vc**2. * (rad / ro) menc *= bovy_conversion.mass_in_msol(ro=ro, vo=vo) r = np.interp(ran, menc / menc[-1], rad) phi = 2.0 * np.pi * np.random.rand(n) theta = np.arccos(1.0 - 2.0 * np.random.rand(n)) x = r * np.sin(theta) * np.cos(phi) y = r * np.sin(theta) * np.sin(phi) z = r * np.cos(theta) sigma_v_1d = vo * potential.vcirc( pot, rad / ro, phi=0, t=0., ro=ro, vo=vo, use_physical=False) / np.sqrt(3.) vx = np.random.normal(0., sigma_v_1d, n) vy = np.random.normal(0., sigma_v_1d, n) vz = np.random.normal(0., sigma_v_1d, n) if coordinates == 'spherical': vr = (vx * np.sin(theta) * np.cos(phi) + vy * np.sin(theta) * np.sin(phi) + vz * np.cos(theta)) vtheta = (vx * np.cos(theta) * np.cos(phi) + vy * np.cos(theta) * np.sin(phi) - vz * np.sin(theta)) vphi = vx * -np.sin(phi) + vy * np.cos(phi) x, y, z = r, phi, theta vx, vy, vz = vr, vphi, vtheta elif coordinates == 'cylindrical': x, y, z = bovy_coords.rect_to_cyl(x, y, z) vx, vy, vz = bovy_coords.rect_to_cyl_vec(vx, vy, vz, x, y, z, True) return x, y, z, vx, vy, vz
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 compute_impact_parameters_GC(timp,a,xs,ys,zs,pot=MWPotential2014,npart=64,sampling_low_file='',bmax=0.5,td=9.): ''' timp : timpacts a,xs,ys,zs : list of array, each array decribes the stream at that time, no of arrays = timpacts sampling_low : low timpact object on to which the impacts from high timpact case will be set bmax: fixed max impact parameter ''' if pot != MWPotential2014 : chain_ind=int(pot) prog,pot,sigv,tvo=set_prog_potential(chain_ind) t_age= np.linspace(0.,td,1001)/bovy_conversion.time_in_Gyr(tvo,_REFR0) bovy_convert_mass=bovy_conversion.mass_in_msol(tvo,_REFR0) else : #integrate their orbits td Gyr back, t_age= np.linspace(0.,td,1001)/bovy_conversion.time_in_Gyr(_REFV0,_REFR0) bovy_convert_mass=bovy_conversion.mass_in_msol(_REFV0,_REFR0) #load the GMCs #M,rs,coord=add_MCs(pot=pot,Mmin=Mmin,rand_rotate=rand_rotate,Rmax=Rmax,Rmin=Rmin) M,rs,coord=add_GCs() orbits=[] N=len(M) for ii in range(N): orbits.append(Orbit(coord[ii],radec=True,ro=8.,vo=220.,solarmotion=[-11.1,24.,7.25]).flip()) # flip flips the velocities for backwards integration orbits[ii].integrate(t_age,pot) min_sep_matrix=np.empty([N,len(timp)]) apar_matrix=np.empty([N,len(timp)]) #compute min_sep of each MC for kk in range(len(timp)): for jj in range(N) : x_mc=orbits[jj].x(timp[kk]) y_mc=orbits[jj].y(timp[kk]) z_mc=orbits[jj].z(timp[kk]) min_sep,apar_min=compute_min_separation(x_mc,y_mc,z_mc,a[kk],xs[kk],ys[kk],zs[kk]) min_sep_matrix[jj,kk]=min_sep apar_matrix[jj,kk]=apar_min impactb=[] impact_angle=[] vx_mc=[] vy_mc=[] vz_mc=[] tmin=[] rs_mc=[] M_mc=[] impactMC_ind=[] #just to get timpacts with open(sampling_low_file,'rb') as savefile: sdf_pepper_low= pickle.load(savefile,encoding='latin1') timpact_low=sdf_pepper_low._timpact c=0 for ii in range(len(orbits)): bmax=bmax/_REFR0 if min(min_sep_matrix[ii]) <= bmax : c+=1 min_timpact_ind=np.argmin(min_sep_matrix[ii]) impactMC_ind.append(ii) t_high=timp[min_timpact_ind] #round t_high to the nearest timpact in the low timpact sampling t_low=timpact_low[np.argmin(np.abs(timpact_low-t_high))] tmin.append(t_low) impactb.append(min_sep_matrix[ii,min_timpact_ind]) impact_angle.append(apar_matrix[ii,min_timpact_ind]) # _sigMeanSign = -/+ = trail/lead rs_mc.append(rs[ii]/_REFR0) M_mc.append(M[ii]/bovy_convert_mass) #flip velocities vx_mc.append(-orbits[ii].vx(t_high)) vy_mc.append(-orbits[ii].vy(t_high)) vz_mc.append(-orbits[ii].vz(t_high)) #combine vx,vy,vz to v v_mc=np.c_[vx_mc,vy_mc,vz_mc] print ("The stream had %i impacts"%c) M_mc=np.array(M_mc) rs_mc=np.array(rs_mc) v_mc=np.array(v_mc) impactb=np.array(impactb) impact_angle=np.array(impact_angle) tmin=np.array(tmin) return (impactMC_ind,M_mc,rs_mc,v_mc,impactb,impact_angle,tmin)
def test_mass_in_msol(): #Test the scaling, should be velocity^2 x position vofid, rofid= 200., 8. assert numpy.fabs(4.*bovy_conversion.mass_in_msol(vofid,rofid)/bovy_conversion.mass_in_msol(2.*vofid,rofid)-1.) < 10.**-10., 'mass_in_msol did not work as expected' assert numpy.fabs(2.*bovy_conversion.mass_in_msol(vofid,rofid)/bovy_conversion.mass_in_msol(vofid,2*rofid)-1.) < 10.**-10., 'mass_in_msol did not work as expected' return None
def __init__(self, amp=1., ro=None, vo=None, amp_units=None): """ NAME: __init__ PURPOSE: Initialize Force INPUT: amp - amplitude to be applied when evaluating the potential and its forces ro - physical distance scale (in kpc or as Quantity) vo - physical velocity scale (in km/s or as Quantity) amp_units - ('mass', 'velocity2', 'density') type of units that amp should have if it has units OUTPUT: HISTORY: 2018-03-18 - Written to generalize Potential to force that may or may not be conservative - Bovy (UofT) """ self._amp = amp # Parse ro and vo if ro is None: self._ro = config.__config__.getfloat('normalization', 'ro') self._roSet = False else: if _APY_LOADED and isinstance(ro, units.Quantity): ro = ro.to(units.kpc).value self._ro = ro self._roSet = True if vo is None: self._vo = config.__config__.getfloat('normalization', 'vo') self._voSet = False else: if _APY_LOADED and isinstance(vo, units.Quantity): vo = vo.to(units.km / units.s).value self._vo = vo self._voSet = True # Parse amp if it has units if _APY_LOADED and isinstance(self._amp, units.Quantity): # Try a bunch of possible units unitFound = False # velocity^2 try: self._amp= self._amp.to(units.km**2/units.s**2).value\ /self._vo**2. except units.UnitConversionError: pass else: unitFound = True if not amp_units == 'velocity2': raise units.UnitConversionError( 'amp= parameter of %s should have units of %s, but has units of velocity2 instead' % (type(self).__name__, amp_units)) if not unitFound: # mass try: self._amp= self._amp.to(units.Msun).value\ /bovy_conversion.mass_in_msol(self._vo,self._ro) except units.UnitConversionError: pass else: unitFound = True if not amp_units == 'mass': raise units.UnitConversionError( 'amp= parameter of %s should have units of %s, but has units of mass instead' % (type(self).__name__, amp_units)) if not unitFound: # G x mass try: self._amp= self._amp.to(units.pc*units.km**2/units.s**2)\ .value\ /bovy_conversion.mass_in_msol(self._vo,self._ro)\ /bovy_conversion._G except units.UnitConversionError: pass else: unitFound = True if not amp_units == 'mass': raise units.UnitConversionError( 'amp= parameter of %s should have units of %s, but has units of G x mass instead' % (type(self).__name__, amp_units)) if not unitFound: # density try: self._amp= self._amp.to(units.Msun/units.pc**3).value\ /bovy_conversion.dens_in_msolpc3(self._vo,self._ro) except units.UnitConversionError: pass else: unitFound = True if not amp_units == 'density': raise units.UnitConversionError( 'amp= parameter of %s should have units of %s, but has units of density instead' % (type(self).__name__, amp_units)) if not unitFound: # G x density try: self._amp= self._amp.to(units.km**2/units.s**2\ /units.pc**2).value\ /bovy_conversion.dens_in_msolpc3(self._vo,self._ro)\ /bovy_conversion._G except units.UnitConversionError: pass else: unitFound = True if not amp_units == 'density': raise units.UnitConversionError( 'amp= parameter of %s should have units of %s, but has units of G x density instead' % (type(self).__name__, amp_units)) if not unitFound: # surface density try: self._amp= self._amp.to(units.Msun/units.pc**2).value\ /bovy_conversion.surfdens_in_msolpc2(self._vo,self._ro) except units.UnitConversionError: pass else: unitFound = True if not amp_units == 'surfacedensity': raise units.UnitConversionError( 'amp= parameter of %s should have units of %s, but has units of surface density instead' % (type(self).__name__, amp_units)) if not unitFound: # G x surface density try: self._amp= self._amp.to(units.km**2/units.s**2\ /units.pc).value\ /bovy_conversion.surfdens_in_msolpc2(self._vo,self._ro)\ /bovy_conversion._G except units.UnitConversionError: pass else: unitFound = True if not amp_units == 'surfacedensity': raise units.UnitConversionError( 'amp= parameter of %s should have units of %s, but has units of G x surface density instead' % (type(self).__name__, amp_units)) if not unitFound: raise units.UnitConversionError( 'amp= parameter of %s should have units of %s; given units are not understood' % (type(self).__name__, amp_units)) else: # When amplitude is given with units, turn on physical output self._roSet = True self._voSet = True return None
def pal5_abc(sdf_pepper, sdf_smooth, options): """ """ # Setup apar grid apar = numpy.arange(options.amin, options.amax, options.dapar) dens_unp = numpy.array([sdf_smooth._density_par(a) for a in apar]) if options.recompute: # Load density and omega from file outdens = options.outdens outomega = options.outomega if not options.batch is None: outdens = outdens.replace(".dat", ".%i.dat" % options.batch) if not options.batch is None: outomega = outomega.replace(".dat", ".%i.dat" % options.batch) densdata = numpy.genfromtxt(outdens, delimiter=",", skip_header=1) omegadata = numpy.genfromtxt(outomega, delimiter=",", skip_header=1) nd = 0 else: # Setup saving of the densities and mean Omegas denswriter, omegawriter, csvdens, csvomega = setup_densOmegaWriter(apar, options) # Setup sampling massrange = simulate_streampepper.parse_mass(options.mass) rs = simulate_streampepper.rs sample_GM = lambda: ( 10.0 ** ((-0.5) * massrange[0]) + (10.0 ** ((-0.5) * massrange[1]) - 10.0 ** ((-0.5) * massrange[0])) * numpy.random.uniform() ) ** (1.0 / (-0.5)) / bovy_conversion.mass_in_msol(V0, R0) sample_rs = lambda x: rs(x * bovy_conversion.mass_in_1010msol(V0, R0) * 10.0 ** 10.0, plummer=options.plummer) rate_range = numpy.arange(massrange[0] + 0.5, massrange[1] + 0.5, 1) cdmrate = numpy.sum( [ simulate_streampepper.dNencdm( sdf_pepper, 10.0 ** r, Xrs=options.Xrs, plummer=options.plummer, rsfac=options.rsfac ) for r in rate_range ] ) print "Using an overall CDM rate of %f" % cdmrate # Load Pal 5 data to compare to if options.mockfilename is None: power_data, data_err, data_ppyr, data_ppyi = process_pal5_densdata(options) else: power_data, data_err, data_ppyr, data_ppyi = process_mock_densdata(options) # Run ABC while True: if not options.recompute: # Simulate a rate l10rate = numpy.random.uniform() * (options.ratemax - options.ratemin) + options.ratemin rate = 10.0 ** l10rate * cdmrate print l10rate, rate # Simulate sdf_pepper.simulate(rate=rate, sample_GM=sample_GM, sample_rs=sample_rs, Xrs=options.Xrs) # Compute density and meanOmega and save try: densOmega = numpy.array([sdf_pepper._densityAndOmega_par_approx(a) for a in apar]).T except IndexError: # no hit dens = numpy.array([sdf_smooth._density_par(a) for a in apar]) omega = numpy.array([sdf_smooth.meanOmega(a, oned=True) for a in apar]) else: dens = densOmega[0] omega = densOmega[1] write_dens = [l10rate] write_omega = [l10rate] write_dens.extend(list(dens)) write_omega.extend(list(omega)) denswriter.writerow(write_dens) omegawriter.writerow(write_omega) csvdens.flush() csvomega.flush() else: if nd >= len(densdata): break l10rate = densdata[nd, 0] dens = densdata[nd, 1:] omega = omegadata[nd, 1:] nd += 1 # Convert density to observed density xixi, dens = convert_dens_to_obs( sdf_pepper, apar, dens, omega, dens_unp, minxi=options.minxi, maxxi=options.maxxi ) # Add errors (Rao-Blackwellize...) for ee in range(options.nerrsim): tdens = dens + numpy.random.normal(size=len(xixi)) * data_err # Compute power spectrum tcsd = signal.csd(tdens, tdens, fs=1.0 / (xixi[1] - xixi[0]), scaling="spectrum", nperseg=len(xixi))[1].real power = numpy.sqrt(tcsd * (xixi[-1] - xixi[0])) # Compute bispectrum Bspec, Bpx = bispectrum.bispectrum( numpy.vstack((tdens, tdens)).T, nfft=len(tdens), wind=7, nsamp=1, overlap=0 ) ppyr = numpy.fabs(Bspec[len(Bspec) // 2 + _BISPECIND, len(Bspec) // 2 :].real) ppyi = numpy.fabs(Bspec[len(Bspec) // 2 + _BISPECIND, len(Bspec) // 2 :].imag) yield ( l10rate, numpy.fabs(power[1] - power_data[1]), numpy.fabs(power[2] - power_data[2]), numpy.fabs(power[3] - power_data[3]), numpy.fabs(numpy.log(numpy.mean(tdens[7:17]) / numpy.mean(tdens[107:117]))), numpy.fabs(ppyr - data_ppyr)[_BISPECIND], numpy.fabs(ppyi - data_ppyi)[_BISPECIND], ee, )
def __init__(self,amp=1.,ro=None,vo=None,amp_units=None): """ NAME: __init__ PURPOSE: Initialize Force INPUT: amp - amplitude to be applied when evaluating the potential and its forces ro - physical distance scale (in kpc or as Quantity) vo - physical velocity scale (in km/s or as Quantity) amp_units - ('mass', 'velocity2', 'density') type of units that amp should have if it has units OUTPUT: HISTORY: 2018-03-18 - Written to generalize Potential to force that may or may not be conservative - Bovy (UofT) """ self._amp= amp # Parse ro and vo if ro is None: self._ro= config.__config__.getfloat('normalization','ro') self._roSet= False else: if _APY_LOADED and isinstance(ro,units.Quantity): ro= ro.to(units.kpc).value self._ro= ro self._roSet= True if vo is None: self._vo= config.__config__.getfloat('normalization','vo') self._voSet= False else: if _APY_LOADED and isinstance(vo,units.Quantity): vo= vo.to(units.km/units.s).value self._vo= vo self._voSet= True # Parse amp if it has units if _APY_LOADED and isinstance(self._amp,units.Quantity): # Try a bunch of possible units unitFound= False # velocity^2 try: self._amp= self._amp.to(units.km**2/units.s**2).value\ /self._vo**2. except units.UnitConversionError: pass else: unitFound= True if not amp_units == 'velocity2': raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of velocity2 instead' % (type(self).__name__,amp_units)) if not unitFound: # mass try: self._amp= self._amp.to(units.Msun).value\ /bovy_conversion.mass_in_msol(self._vo,self._ro) except units.UnitConversionError: pass else: unitFound= True if not amp_units == 'mass': raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of mass instead' % (type(self).__name__,amp_units)) if not unitFound: # G x mass try: self._amp= self._amp.to(units.pc*units.km**2/units.s**2)\ .value\ /bovy_conversion.mass_in_msol(self._vo,self._ro)\ /bovy_conversion._G except units.UnitConversionError: pass else: unitFound= True if not amp_units == 'mass': raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of G x mass instead' % (type(self).__name__,amp_units)) if not unitFound: # density try: self._amp= self._amp.to(units.Msun/units.pc**3).value\ /bovy_conversion.dens_in_msolpc3(self._vo,self._ro) except units.UnitConversionError: pass else: unitFound= True if not amp_units == 'density': raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of density instead' % (type(self).__name__,amp_units)) if not unitFound: # G x density try: self._amp= self._amp.to(units.km**2/units.s**2\ /units.pc**2).value\ /bovy_conversion.dens_in_msolpc3(self._vo,self._ro)\ /bovy_conversion._G except units.UnitConversionError: pass else: unitFound= True if not amp_units == 'density': raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of G x density instead' % (type(self).__name__,amp_units)) if not unitFound: # surface density try: self._amp= self._amp.to(units.Msun/units.pc**2).value\ /bovy_conversion.surfdens_in_msolpc2(self._vo,self._ro) except units.UnitConversionError: pass else: unitFound= True if not amp_units == 'surfacedensity': raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of surface density instead' % (type(self).__name__,amp_units)) if not unitFound: # G x surface density try: self._amp= self._amp.to(units.km**2/units.s**2\ /units.pc).value\ /bovy_conversion.surfdens_in_msolpc2(self._vo,self._ro)\ /bovy_conversion._G except units.UnitConversionError: pass else: unitFound= True if not amp_units == 'surfacedensity': raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of G x surface density instead' % (type(self).__name__,amp_units)) if not unitFound: raise units.UnitConversionError('amp= parameter of %s should have units of %s; given units are not understood' % (type(self).__name__,amp_units)) else: # When amplitude is given with units, turn on physical output self._roSet= True self._voSet= True return None
def run_simulations(sdf_pepper, sdf_smooth, options): # Setup apar grid apar = numpy.arange(options.amin, options.amax, options.dapar) # Check whether the output files already exist and if so, get the amin, amax, da from them if os.path.exists(options.outdens): # First read the file to check apar apar_file = numpy.genfromtxt(options.outdens, delimiter=',', max_rows=1) print(numpy.amax(numpy.fabs(apar_file - apar))) assert numpy.amax( numpy.fabs(apar_file - apar) ) < 10.**-5., 'apar according to options does not correspond to apar already in outdens' apar_file = numpy.genfromtxt(options.outomega, delimiter=',', max_rows=1) print(numpy.amax(numpy.fabs(apar_file - apar))) assert numpy.amax( numpy.fabs(apar_file - apar) ) < 10.**-5., 'apar according to options does not correspond to apar already in outomega' csvdens = open(options.outdens, 'a') csvomega = open(options.outomega, 'a') denswriter = csv.writer(csvdens, delimiter=',') omegawriter = csv.writer(csvomega, delimiter=',') else: csvdens = open(options.outdens, 'w') csvomega = open(options.outomega, 'w') denswriter = csv.writer(csvdens, delimiter=',') omegawriter = csv.writer(csvomega, delimiter=',') # First write apar and the smooth calculations denswriter.writerow([a for a in apar]) omegawriter.writerow([a for a in apar]) if sdf_smooth is None and options.stream.lower() == 'gd1like': sdf_smooth = gd1_util.setup_gd1model(age=options.age) elif sdf_smooth is None and options.stream.lower() == 'pal5like': sdf_smooth = pal5_util.setup_pal5model(age=options.age) dens_unp = [sdf_smooth._density_par(a) for a in apar] denswriter.writerow(dens_unp) omega_unp = [sdf_smooth.meanOmega(a, oned=True) for a in apar] omegawriter.writerow(omega_unp) csvdens.flush() csvomega.flush() # Parse mass massrange = parse_mass(options.mass) if len(massrange) == 1: sample_GM= lambda: 10.**(massrange[0]-10.)\ /bovy_conversion.mass_in_1010msol(V0,R0) rate = options.timescdm * dNencdm(sdf_pepper, 10.**massrange[0], Xrs=options.Xrs, plummer=options.plummer, rsfac=options.rsfac, sigma=options.sigma) elif len(massrange) == 2: # Sample from power-law if not options.cutoff is None: sample_GM = lambda: powerlaw_wcutoff(massrange, options.cutoff) elif numpy.fabs(options.massexp + 1.5) < 10.**-6.: sample_GM= lambda: 10.**(massrange[0]\ +(massrange[1]-massrange[0])\ *numpy.random.uniform())\ /bovy_conversion.mass_in_msol(V0,R0) else: sample_GM= lambda: (10.**((options.massexp+1.5)*massrange[0])\ +(10.**((options.massexp+1.5)*massrange[1])\ -10.**((options.massexp+1.5)*massrange[0]))\ *numpy.random.uniform())**(1./(options.massexp+1.5))\ /bovy_conversion.mass_in_msol(V0,R0) rate_range = numpy.arange(massrange[0] + 0.5, massrange[1] + 0.5, 1) rate= options.timescdm\ *numpy.sum([dNencdm(sdf_pepper,10.**r,Xrs=options.Xrs, plummer=options.plummer,rsfac=options.rsfac, sigma=options.sigma) for r in rate_range]) if not options.cutoff is None: rate*= integrate.quad(lambda x: x**-1.5\ *numpy.exp(-10.**options.cutoff/x), 10.**massrange[0],10.**massrange[1])[0]\ /integrate.quad(lambda x: x**-1.5, 10.**massrange[0], 10.**massrange[1])[0] print("Using an overall rate of %f" % rate) sample_rs = lambda x: rs(x * bovy_conversion.mass_in_1010msol(V0, R0) * 10. **10., plummer=options.plummer, rsfac=options.rsfac) # Simulate start = time.time() ns = 0 while True: if options.nsamples is None and time.time() >= (start + options.dt * 60.): break elif not options.nsamples is None and ns > options.nsamples: break ns += 1 sdf_pepper.simulate(rate=rate, sample_GM=sample_GM, sample_rs=sample_rs, Xrs=options.Xrs, sigma=options.sigma / V0) # Compute density and meanOmega and save try: densOmega = numpy.array( [sdf_pepper._densityAndOmega_par_approx(a) for a in apar]).T except IndexError: # no hit dens_unp = [sdf_smooth._density_par(a) for a in apar] omega_unp = [sdf_smooth.meanOmega(a, oned=True) for a in apar] denswriter.writerow(dens_unp) omegawriter.writerow(omega_unp) else: denswriter.writerow(list(densOmega[0])) omegawriter.writerow(list(densOmega[1])) csvdens.flush() csvomega.flush() csvdens.close() csvomega.close() return None
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
ax = axs[i, j] print('') print('') print(row['Name']) x, y, z = row['X'] - 8., row['Y'], row['Z'] print(x, y, z) galMass = 0. #bulge, bar, disk for massElement in MWPotential2014: galMass += massElement.mass(np.sqrt(x**2. + y**2.), z=z) * bovy_conversion.mass_in_msol( 220., 8.) gcDist = np.sqrt(x**2. + y**2. + z**2.) jacobiRadius = 3. * gcDist * (gcMasses[row['ID']] / galMass)**(1 / 3.) print('enclosed mass: %.02e' % (galMass)) print('gcDist: %.03f kpc' % (gcDist)) print('jacobiRadius: %.03f pc' % (jacobiRadius * 1000.)) if row['Name'] == 'omega Cen': ax.annotate(r'$\omega$ Cen', xy=(0.6, 0.8), xycoords='axes fraction', fontsize=16) else: ax.annotate(row['Name'],
def pal5_abc(sdf_pepper, sdf_smooth, options): """ """ # Setup apar grid apar = numpy.arange(options.amin, options.amax, options.dapar) dens_unp = numpy.array([sdf_smooth._density_par(a) for a in apar]) if options.recompute: # Load density and omega from file outdens = options.outdens outomega = options.outomega if not options.batch is None: outdens = outdens.replace('.dat', '.%i.dat' % options.batch) if not options.batch is None: outomega = outomega.replace('.dat', '.%i.dat' % options.batch) densdata = numpy.genfromtxt(outdens, delimiter=',', skip_header=1) omegadata = numpy.genfromtxt(outomega, delimiter=',', skip_header=1) nd = 0 else: # Setup saving of the densities and mean Omegas denswriter, omegawriter, csvdens, csvomega=\ setup_densOmegaWriter(apar,options) # Setup sampling massrange = simulate_streampepper.parse_mass(options.mass) rs = simulate_streampepper.rs sample_GM= lambda: (10.**((-0.5)*massrange[0])\ +(10.**((-0.5)*massrange[1])\ -10.**((-0.5)*massrange[0]))\ *numpy.random.uniform())**(1./(-0.5))\ /bovy_conversion.mass_in_msol(V0,R0) sample_rs = lambda x: rs(x * bovy_conversion.mass_in_1010msol(V0, R0) * 10.**10., plummer=options.plummer) rate_range = numpy.arange(massrange[0] + 0.5, massrange[1] + 0.5, 1) cdmrate= numpy.sum([simulate_streampepper.\ dNencdm(sdf_pepper,10.**r,Xrs=options.Xrs, plummer=options.plummer, rsfac=options.rsfac) for r in rate_range]) print "Using an overall CDM rate of %f" % cdmrate # Load Pal 5 data to compare to if options.mockfilename is None: power_data, data_err, data_ppyr, data_ppyi=\ process_pal5_densdata(options) else: power_data, data_err, data_ppyr, data_ppyi=\ process_mock_densdata(options) # Run ABC while True: if not options.recompute: # Simulate a rate l10rate = (numpy.random.uniform() * (options.ratemax - options.ratemin) + options.ratemin) rate = 10.**l10rate * cdmrate print l10rate, rate # Simulate sdf_pepper.simulate(rate=rate, sample_GM=sample_GM, sample_rs=sample_rs, Xrs=options.Xrs) # Compute density and meanOmega and save try: densOmega= numpy.array([\ sdf_pepper._densityAndOmega_par_approx(a) for a in apar]).T except IndexError: # no hit dens = numpy.array([sdf_smooth._density_par(a) for a in apar]) omega = numpy.array( [sdf_smooth.meanOmega(a, oned=True) for a in apar]) else: dens = densOmega[0] omega = densOmega[1] write_dens = [l10rate] write_omega = [l10rate] write_dens.extend(list(dens)) write_omega.extend(list(omega)) denswriter.writerow(write_dens) omegawriter.writerow(write_omega) csvdens.flush() csvomega.flush() else: if nd >= len(densdata): break l10rate = densdata[nd, 0] dens = densdata[nd, 1:] omega = omegadata[nd, 1:] nd += 1 # Convert density to observed density xixi, dens = convert_dens_to_obs(sdf_pepper, apar, dens, omega, dens_unp, minxi=options.minxi, maxxi=options.maxxi) # Add errors (Rao-Blackwellize...) for ee in range(options.nerrsim): tdens = dens + numpy.random.normal(size=len(xixi)) * data_err # Compute power spectrum tcsd = signal.csd(tdens, tdens, fs=1. / (xixi[1] - xixi[0]), scaling='spectrum', nperseg=len(xixi))[1].real power = numpy.sqrt(tcsd * (xixi[-1] - xixi[0])) # Compute bispectrum Bspec, Bpx = bispectrum.bispectrum(numpy.vstack((tdens, tdens)).T, nfft=len(tdens), wind=7, nsamp=1, overlap=0) ppyr = numpy.fabs(Bspec[len(Bspec) // 2 + _BISPECIND, len(Bspec) // 2:].real) ppyi = numpy.fabs(Bspec[len(Bspec) // 2 + _BISPECIND, len(Bspec) // 2:].imag) yield (l10rate, numpy.fabs(power[1]-power_data[1]), numpy.fabs(power[2]-power_data[2]), numpy.fabs(power[3]-power_data[3]), numpy.fabs(numpy.log(numpy.mean(tdens[7:17])\ /numpy.mean(tdens[107:117]))), numpy.fabs(ppyr-data_ppyr)[_BISPECIND], numpy.fabs(ppyi-data_ppyi)[_BISPECIND], ee)
#sdf_smooth= pal5_util.setup_pal5model(age=9.) #sdf_pepper= pal5_util.setup_pal5model(singleImpact=True) # # if 0: sdf_pepper_t = pal5_util.setup_pal5model(timpact=[1.]) sdf_pepper_l = pal5_util.setup_pal5model(timpact=[1.], leading=True) massrange = [7., 9.] massexp = -2. sp = sdf_pepper_l sample_GM= lambda: (10.**((massexp+1.5)*massrange[0])\ +(10.**((massexp+1.5)*massrange[1])\ -10.**((massexp+1.5)*massrange[0]))\ *numpy.random.uniform())**(1./(massexp+1.5))\ /bovy_conversion.mass_in_msol(V0,R0) rate_range = numpy.arange(massrange[0] + 0.5, massrange[1] + 0.5, 1) rate = numpy.sum([ dNencdm(sp, 10.**r, Xrs=3., plummer=False, rsfac=1., sigma=120.) for r in rate_range ]) for i in np.arange(10): sample_GM = lambda: powerlaw_wcutoff(massrange, 7.) rate_range = numpy.arange(massrange[0] + 0.5, massrange[1] + 0.5, 1) rate = 3 * numpy.sum([ dNencdm(sp, 10.**r, Xrs=3., plummer=False, rsfac=1., sigma=120.) for r in rate_range ]) sample_rs = lambda x: rs(x * bovy_conversion.mass_in_1010msol(V0, R0) * 10. **10.,
def simulate_subhalos_vary_amp_slope_mwdm(sdf_pepper, m_wdm, mf_slope=-1.9, c0kpc=2.02 * 10**(-13), r=20., Xrs=5., sigma=120. / 220.): ''' Sample amp and slope such that dN/dM = amp*M^slope and simulate subhalo impacts ''' Mbin_edge = [5., 6., 7., 8., 9.] Nbins = len(Mbin_edge) - 1 #compute number of subhalos in each mass bin nden_bin = np.empty(Nbins) rate_bin = np.empty(Nbins) for ll in range(Nbins): nden_bin[ll] = nsub_wdm(Mbin_edge[ll], Mbin_edge[ll + 1], m_wdm=m_wdm, r=r, c0kpc=c0kpc, mf_slope=mf_slope) Mmid = 10**(0.5 * (Mbin_edge[ll] + Mbin_edge[ll + 1])) rate_bin[ll] = sdf_pepper.subhalo_encounters(sigma=sigma, nsubhalo=nden_bin[ll], bmax=Xrs * rs(Mmid, plummer=True)) rate = np.sum(rate_bin) Nimpact = numpy.random.poisson(rate) norm = 1. / quad(lambda M: fac(M, m_wdm) * ( (M)**(mf_slope + 0.5)), 10**(Mbin_edge[0]), 10**(Mbin_edge[Nbins]))[0] def cdf(M): return quad(lambda M: norm * fac(M, m_wdm) * (M)**(mf_slope + 0.5), 10**Mbin_edge[0], M)[0] MM = numpy.linspace(Mbin_edge[0], Mbin_edge[Nbins], 10000) cdfl = [cdf(i) for i in 10**MM] icdf = interpolate.InterpolatedUnivariateSpline(cdfl, 10**MM, k=1) timpact_sub = numpy.array(sdf_pepper._uniq_timpact)[numpy.random.choice( len(sdf_pepper._uniq_timpact), size=Nimpact, p=sdf_pepper._ptimpact)] # Sample angles from the part of the stream that existed then impact_angle_sub = numpy.array([ sdf_pepper._icdf_stream_len[ti](numpy.random.uniform()) for ti in timpact_sub ]) sample_GM = lambda: icdf(numpy.random.uniform() ) / bovy_conversion.mass_in_msol(vo, ro) GM_sub = numpy.array([sample_GM() for a in impact_angle_sub]) rs_sub = numpy.array( [rs(gm * bovy_conversion.mass_in_msol(vo, ro)) for gm in GM_sub]) # impact b impactb_sub = (2. * numpy.random.uniform(size=len(impact_angle_sub)) - 1.) * Xrs * rs_sub # velocity subhalovel_sub = numpy.empty((len(impact_angle_sub), 3)) for ii in range(len(timpact_sub)): subhalovel_sub[ii] = sdf_pepper._draw_impact_velocities( timpact_sub[ii], sigma, impact_angle_sub[ii], n=1)[0] # Flip angle sign if necessary #if not sdf_pepper._gap_leading: impact_angles*= -1. #angles not flipped, flip them after including angles from GMC and GC impacts return impact_angle_sub, impactb_sub, subhalovel_sub, timpact_sub, GM_sub, rs_sub
def compute_impact_parameters_GMC(timp, a, xs, ys, zs, pot=MWPotential2014, npart=64, sampling_low_file='', imp_fac=5., Mmin=10**6., rand_rotate=False): ''' timp : timpacts a,xs,ys,zs : list of array, each array decribes the stream at that time, no of arrays = timpacts sampling_low : low timpact object on to which the impacts from high timpact case will be set imp_fac: X where bmax= X.r_s Mmin min mass above which all GMCs will be considered for impact rand_rotate : give the GMCs an ol' shaka shaka along phi ''' if pot != MWPotential2014: chain_ind = int(pot) prog, pot, sigv, tvo = set_prog_potential(chain_ind) t_age = np.linspace(0., 5., 1001) / bovy_conversion.time_in_Gyr( tvo, _REFR0) bovy_convert_mass = bovy_conversion.mass_in_msol(tvo, _REFR0) else: #integrate their orbits 5 Gyr back, t_age = np.linspace(0., 5., 1001) / bovy_conversion.time_in_Gyr( _REFV0, _REFR0) bovy_convert_mass = bovy_conversion.mass_in_msol(_REFV0, _REFR0) #load the GMCs M, rs, coord = add_MCs(pot=pot, Mmin=Mmin, rand_rotate=rand_rotate) orbits = [] N = len(M) for ii in range(N): orbits.append(Orbit(coord[ii]).flip() ) # flip flips the velocities for backwards integration orbits[ii].integrate(t_age, pot) min_sep_matrix = np.empty([N, len(timp)]) apar_matrix = np.empty([N, len(timp)]) #compute min_sep of each MC for kk in range(len(timp)): for jj in range(N): x_mc = orbits[jj].x(timp[kk]) y_mc = orbits[jj].y(timp[kk]) z_mc = orbits[jj].z(timp[kk]) min_sep, apar_min = compute_min_separation(x_mc, y_mc, z_mc, a[kk], xs[kk], ys[kk], zs[kk]) min_sep_matrix[jj, kk] = min_sep apar_matrix[jj, kk] = apar_min impactb = [] impact_angle = [] vx_mc = [] vy_mc = [] vz_mc = [] tmin = [] rs_mc = [] M_mc = [] impactMC_ind = [] if npart > 1: #just to get timpacts with open(sampling_low_file, 'rb') as savefile: sdf_pepper_low = pickle.load(savefile, encoding='latin1') timpact_low = sdf_pepper_low._timpact c = 0 for ii in range(len(orbits)): bmax = imp_fac * rs[ii] / _REFR0 if min(min_sep_matrix[ii]) <= bmax: c += 1 min_timpact_ind = np.argmin(min_sep_matrix[ii]) impactMC_ind.append(ii) t_high = timp[min_timpact_ind] #round t_high to the nearest timpact in the low timpact sampling t_low = timpact_low[np.argmin(np.abs(timpact_low - t_high))] tmin.append(t_low) impactb.append(min_sep_matrix[ii, min_timpact_ind]) impact_angle.append(apar_matrix[ ii, min_timpact_ind]) # _sigMeanSign = -/+ = trail/lead rs_mc.append(rs[ii] / _REFR0) M_mc.append(M[ii] / bovy_convert_mass) #flip velocities vx_mc.append(-orbits[ii].vx(t_high)) vy_mc.append(-orbits[ii].vy(t_high)) vz_mc.append(-orbits[ii].vz(t_high)) #combine vx,vy,vz to v v_mc = np.c_[vx_mc, vy_mc, vz_mc] print("The stream had %i impacts" % c) else: c = 0 for ii in range(len(orbits)): bmax = imp_fac * rs[ii] / _REFR0 if min(min_sep_matrix[ii]) <= bmax: c += 1 min_timpact_ind = np.argmin(min_sep_matrix[ii]) impactMC_ind.append(ii) t_imp_min = timp[min_timpact_ind] tmin.append(t_imp_min) impactb.append(min_sep_matrix[ii, min_timpact_ind]) impact_angle.append(apar_matrix[ ii, min_timpact_ind]) # _sigMeanSign = -/+ = trail/lead rs_mc.append(rs[ii] / _REFR0) M_mc.append(M[ii] / bovy_conversion.mass_in_msol(_REFV0, _REFR0)) #flip velocities vx_mc.append(-orbits[ii].vx(t_imp_min)) vy_mc.append(-orbits[ii].vy(t_imp_min)) vz_mc.append(-orbits[ii].vz(t_imp_min)) #combine vx,vy,vz to v v_mc = np.c_[vx_mc, vy_mc, vz_mc] print("The stream had %i impacts" % c) return (impactMC_ind, M_mc, rs_mc, v_mc, impactb, impact_angle, tmin)
def create_frames(options,args): # First reload the model with open('gd1pepper%isampling.pkl' % options.nsnap,'rb') as savefile: sdf_pepper_leading= pickle.load(savefile) with open('gd1pepper%isampling_trailing.pkl' % options.nsnap,'rb') as savefile: sdf_pepper_trailing= pickle.load(savefile) # Output times timpacts= sdf_pepper_leading._uniq_timpact # Sample unperturbed aAt numpy.random.seed(1) Oml,anglel,dtl= super(streampepperdf,sdf_pepper_leading)._sample_aAt(\ options.nparticles) Omt,anglet,dtt= super(streampepperdf,sdf_pepper_trailing)._sample_aAt(\ options.nparticles) # Setup progenitor prog= sdf_pepper_leading._progenitor().flip() prog.integrate(numpy.linspace(0.,9./bovy_conversion.time_in_Gyr(V0,R0), 10001),sdf_pepper_leading._pot) prog.flip() # Setup impacts if options.single: # Hit the leading arm and the trailing arm 1 Gyr later m= options.singlemimpact/bovy_conversion.mass_in_1010msol(V0,R0)/1000. t= timpacts[\ numpy.argmin(\ numpy.fabs(\ numpy.array(timpacts)\ -options.singletimpact\ /bovy_conversion.time_in_Gyr(V0,R0)))] sdf_pepper_leading.set_impacts(\ impactb=[0.5*simulate_streampepper.rs(options.singlemimpact*10.**7.)], subhalovel=numpy.array([[-25.,155.,30.]])/V0, impact_angle=[0.2], timpact=[t], GM=[m],rs=[simulate_streampepper.rs(options.singlemimpact*10.**7.)]) # Trailing m= options.singlemimpact/bovy_conversion.mass_in_1010msol(V0,R0)/1000. t= timpacts[\ numpy.argmin(\ numpy.fabs(\ numpy.array(timpacts)\ -(options.singletimpact+1.)\ /bovy_conversion.time_in_Gyr(V0,R0)))] sdf_pepper_trailing.set_impacts(\ impactb=[1.*simulate_streampepper.rs(options.singlemimpact*10.**7.)], subhalovel=numpy.array([[-25.,155.,30.]])/V0, impact_angle=[-0.3], timpact=[t], GM=[m],rs=[simulate_streampepper.rs(options.singlemimpact*10.**7.)]) elif options.pepper: # Sampling functions massrange=[options.Mmin,options.Mmax] plummer= False Xrs= 5. nsubhalo= simulate_streampepper.nsubhalo rs= simulate_streampepper.rs dNencdm= simulate_streampepper.dNencdm sample_GM= lambda: (10.**((-0.5)*massrange[0])\ +(10.**((-0.5)*massrange[1])\ -10.**((-0.5)*massrange[0]))\ *numpy.random.uniform())**(1./(-0.5))\ /bovy_conversion.mass_in_msol(V0,R0) rate_range= numpy.arange(massrange[0]+0.5,massrange[1]+0.5,1) rate= numpy.sum([dNencdm(sdf_pepper_leading,10.**r,Xrs=Xrs, plummer=plummer) for r in rate_range]) rate= options.timescdm*rate sample_rs= lambda x: rs(x*bovy_conversion.mass_in_1010msol(V0,R0)*10.**10., plummer=plummer) # Pepper both sdf_pepper_leading.simulate(rate=rate,sample_GM=sample_GM, sample_rs=sample_rs,Xrs=Xrs) print numpy.amax(sdf_pepper_leading._GM)*bovy_conversion.mass_in_1010msol(V0,R0) sdf_pepper_trailing.simulate(rate=rate,sample_GM=sample_GM, sample_rs=sample_rs,Xrs=Xrs) print numpy.amax(sdf_pepper_trailing._GM)*bovy_conversion.mass_in_1010msol(V0,R0) else: # Hit both with zero sdf_pepper_leading.set_impacts(\ impactb=[0.], subhalovel=numpy.array([[-25.,155.,30.]])/V0, impact_angle=[0.2], timpact=[timpacts[0]], GM=[0.],rs=[1.]) sdf_pepper_trailing.set_impacts(\ impactb=[0.], subhalovel=numpy.array([[-25.,155.,30.]])/V0, impact_angle=[-0.2], timpact=[timpacts[0]], GM=[0.],rs=[1.]) # Now make all frames dum= multi.parallel_map( (lambda x: _plot_one_frame(x,options,prog,timpacts, sdf_pepper_leading,sdf_pepper_trailing, Oml,Omt,anglel,anglet,dtl,dtt)), range(len(timpacts)), numcores=numpy.amin([len(timpacts),30])) return None