Example #1
0
def test_monotonic_incomplete_bridge():
    # Test the monotonic bridge where not all the particles are shared
    f1 = pynbody.new(dm=10)
    f2 = pynbody.new(dm=9)
    f1['iord'] = np.arange(0, 10)
    f2['iord'] = np.array([0, 1, 2, 4, 5 ,6, 7, 8, 9])
    b = pynbody.bridge.OrderBridge(f1, f2, monotonic=False)

    assert (b(f1[:5])['iord'] == np.array([0, 1, 2, 4])).all()
Example #2
0
def test_order_bridge():
    f1 = pynbody.new(dm=1000)
    f2 = pynbody.new(dm=3000)
    f1['iord'] = np.arange(5, 2005, 2, dtype=int)
    f2['iord'] = np.arange(3000, dtype=int)

    b = pynbody.bridge.OrderBridge(f1, f2)

    h1 = f1[:50:2]
    assert b(h1).ancestor is f2
    assert (b(h1)['iord'] == h1['iord']).all
Example #3
0
def test_family_morphing():
    f1 = pynbody.new(dm=5, gas=5)
    f2 = pynbody.new(dm=10)

    # set dm and gas iords separately as it's possible the new command initialises them out of order
    f1.dm['iord'] = np.arange(0,5)
    f1.gas['iord'] = np.arange(5,10)
    f2['iord'] = np.array([0,2,4,6,8,1,3,5,7,9])

    b = pynbody.bridge.OrderBridge(f1,f2,monotonic=False,allow_family_change=True)

    assert (b(f2).dm['iord']==np.array([0,2,4,1,3])).all()
    assert (b(f2).gas['iord'] == np.array([6, 8, 5, 7, 9])).all()
Example #4
0
def setup():
    global f, h
    f = pynbody.new(dm=1000, star=500, gas=500, order='gas,dm,star')
    f['pos'] = np.random.normal(scale=1.0, size=f['pos'].shape)
    f['vel'] = np.random.normal(scale=1.0, size=f['vel'].shape)
    f['mass'] = np.random.uniform(1.0, 10.0, size=f['mass'].shape)
    f.gas['rho'] = np.ones(500, dtype=float)
Example #5
0
def test_interpsnapshotKeplerPotential_normalize_units():
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 4.
    s['eps']= 0.
    s['pos'].units= 'kpc'
    s['vel'].units= 'km s**-1'
    sp= potential.InterpSnapshotRZPotential(s,
                                          rgrid=(0.01,3.,201),
                                          zgrid=(0.,0.2,201),
                                          logR=False,
                                          interpPot=True,
                                          zsym=True)
    #Currently unnormalized
    assert numpy.fabs(sp.Rforce(1.,0.)+4.) < 10.**-7., "InterpSnapShotPotential that is assumed to be unnormalized doesn't behave as expected"
    # Normalize
    sp.normalize(R0=1.)
    assert numpy.fabs(sp.Rforce(1.,0.)+1.) < 10.**-7., "InterpSnapShotPotential that is assumed to be normalized doesn't behave as expected"
    # De normalize
    sp.denormalize()
    assert numpy.fabs(sp.Rforce(1.,0.)+4.) < 10.**-7., "InterpSnapShotPotential that is assumed to be normalized doesn't behave as expected"
    # Also test when R0 =/= 1
    sp.normalize(R0=2.)
    assert numpy.fabs(sp.Rforce(1.,0.)+1.) < 10.**-7., "InterpSnapShotPotential that is assumed to be normalized doesn't behave as expected"
    # De normalize
    sp.denormalize()
    assert numpy.fabs(sp.Rforce(1.,0.)+4.) < 10.**-7., "InterpSnapShotPotential that is assumed to be normalized doesn't behave as expected"
    return None
Example #6
0
def test_interpsnapshotKeplerPotential_eval():
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 1.
    s['eps']= 0.
    sp= potential.InterpSnapshotRZPotential(s,
                                            rgrid=(0.01,2.,201),
                                            zgrid=(0.,0.2,201),
                                            logR=False,
                                            interpPot=True,
                                            zsym=True,
                                            numcores=1)
    kp= potential.KeplerPotential(amp=1.) #should be the same
    #This just tests on the grid
    rs= numpy.linspace(0.01,2.,21)
    zs= numpy.linspace(-0.2,0.2,41)
    for r in rs:
        for z in zs:
            assert numpy.fabs((sp(r,z)-kp(r,z))/kp(r,z)) < 10.**-10., 'RZPot interpolation w/ InterpSnapShotPotential of KeplerPotential fails at (R,z) = (%g,%g)' % (r,z)
    #This tests within the grid
    rs= numpy.linspace(0.01,2.,10)
    zs= numpy.linspace(-0.2,0.2,20)
    for r in rs:
        for z in zs:
            assert numpy.fabs((sp(r,z)-kp(r,z))/kp(r,z)) < 10.**-5., 'RZPot interpolation w/ InterpSnapShotPotential of KeplerPotential fails at (R,z) = (%g,%g) by %g' % (r,z,numpy.fabs((sp(r,z)-kp(r,z))/kp(r,z)))           
    #Test all at the same time to use vector evaluation
    mr,mz= numpy.meshgrid(rs,zs)
    mr= mr.flatten()
    mz= mz.flatten()
    assert numpy.all(numpy.fabs((sp(mr,mz)-kp(mr,mz))/kp(mr,mz)) < 10.**-5.), 'RZPot interpolation w/ interpRZPotential fails for vector input'
    return None
Example #7
0
def test_float_kd():
    f = pynbody.load("testdata/test_g2_snap")
    del f.properties['boxsize']

    assert f.dm['mass'].dtype==f.dm['pos'].dtype==np.float32
    assert f.dm['smooth'].dtype==np.float32

    # make double copy
    g = pynbody.new(len(f.dm))
    g.dm['pos']=f.dm['pos']
    g.dm['mass']=f.dm['mass']

    assert g.dm['mass'].dtype==g.dm['pos'].dtype==g.dm['smooth'].dtype==np.float64

    # check smoothing lengths agree (they have been calculated differently
    # using floating/double routines)

    npt.assert_allclose(f.dm['smooth'],g.dm['smooth'],rtol=1e-4)
    npt.assert_allclose(f.dm['rho'],g.dm['rho'],rtol=1e-4)

    # check all combinations of float/double smoothing
    double_ar = np.ones(len(f.dm),dtype=np.float64)
    float_ar = np.ones(len(f.dm),dtype=np.float32)

    double_double = g.dm.kdtree.sph_mean(double_ar,32)
    double_float = g.dm.kdtree.sph_mean(float_ar,32)
    float_double = f.dm.kdtree.sph_mean(double_ar,32)
    float_float = f.dm.kdtree.sph_mean(float_ar,32)

    # take double-double as 'gold standard' (though of course if any of these
    # fail it could also be a problem with the double-double case)

    npt.assert_allclose(double_double,double_float,rtol=1e-4)
    npt.assert_allclose(double_double,float_double,rtol=1e-4)
    npt.assert_allclose(double_double,float_float,rtol=1e-4)
Example #8
0
def test_interpsnapshotKeplerPotential_eval_naz():
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 1.
    s['eps']= 0.
    sp= potential.InterpSnapshotRZPotential(s,
                                            rgrid=(0.01,2.,51),
                                            zgrid=(0.,0.2,51),
                                            logR=False,
                                            interpPot=True,
                                            zsym=True,
                                            numcores=1)
    spaz= potential.InterpSnapshotRZPotential(s,
                                              rgrid=(0.01,2.,51),
                                              zgrid=(0.,0.2,51),
                                              logR=False,
                                              interpPot=True,
                                              zsym=True,
                                              numcores=1,nazimuths=12)
    #This just tests on the grid
    rs= numpy.linspace(0.01,2.,21)
    zs= numpy.linspace(-0.2,0.2,41)
    for r in rs:
        for z in zs:
            assert numpy.fabs((sp(r,z)-spaz(r,z))/sp(r,z)) < 10.**-10., 'RZPot interpolation w/ InterpSnapShotPotential of KeplerPotential with different nazimuths fails at (R,z) = (%g,%g)' % (r,z)
    #This tests within the grid, with vector evaluation
    rs= numpy.linspace(0.01,2.,10)
    zs= numpy.linspace(-0.2,0.2,20)
    mr,mz= numpy.meshgrid(rs,zs)
    mr= mr.flatten()
    mz= mz.flatten()
    assert numpy.all(numpy.fabs((sp(mr,mz)-spaz(mr,mz))/sp(mr,mz)) < 10.**-5.), 'RZPot interpolation w/ interpRZPotential with different nazimimuths fails for vector input'
    return None
Example #9
0
def test_interpsnapshotKeplerPotential_z2deriv():
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 2.
    s['eps']= 0.
    sp= potential.InterpSnapshotRZPotential(s,
                                            rgrid=(0.01,2.,101),
                                            zgrid=(0.,0.2,101),
                                            logR=False,
                                            interpPot=True,
                                            interpverticalfreq=True,
                                            zsym=True)
    kp= potential.KeplerPotential(amp=2.) #should be the same
    #This just tests on the grid
    rs= numpy.linspace(0.01,2.,21)[1:]
    zs= numpy.linspace(-0.2,0.2,41)
    for r in rs:
        for z in zs:
            assert numpy.fabs((sp.z2deriv(r,z)-kp.z2deriv(r,z))/kp.z2deriv(r,z)) < 10.**-4., 'RZPot interpolation of z2deriv w/ InterpSnapShotPotential of KeplerPotential fails at (R,z) = (%g,%g) by %g' % (r,z,numpy.fabs((sp.z2deriv(r,z)-kp.z2deriv(r,z))/kp.z2deriv(r,z)))
    #This tests within the grid
    rs= numpy.linspace(0.01,2.,10)[1:]
    zs= numpy.linspace(-0.2,0.2,20)
    for r in rs:
        for z in zs:
            assert numpy.fabs((sp.z2deriv(r,z)-kp.z2deriv(r,z))/kp.z2deriv(r,z)) < 2.*10.**-4., 'RZPot interpolation of z2deriv w/ InterpSnapShotPotential of KeplerPotential fails at (R,z) = (%g,%g) by %g' % (r,z,numpy.fabs((sp.z2deriv(r,z)-kp.z2deriv(r,z))/kp.z2deriv(r,z)))
    return None
Example #10
0
def test_interpsnapshotKeplerpotential_Rzderiv():
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 2.
    s['eps']= 0.
    sp= potential.InterpSnapshotRZPotential(s,
                                            rgrid=(0.01,2.,101),
                                            zgrid=(0.,0.2,101),
                                            logR=False,
                                            interpPot=True,
                                            interpepifreq=True,
                                            interpverticalfreq=True,
                                            zsym=True)
    kp= potential.KeplerPotential(amp=2.) #should be the same
    #This just tests on the grid
    rs= numpy.linspace(0.01,2.,21)[1:]
    zs= numpy.linspace(-0.2,0.2,41)
    zs= zs[zs != 0.]# avoid zero
    # Test, but give small |z| a less constraining 
    for r in rs:
        for z in zs:
            assert numpy.fabs((sp.Rzderiv(r,z)-kp.Rzderiv(r,z))/kp.Rzderiv(r,z)) < 10.**-4.*(1.+19.*(numpy.fabs(z) < 0.05)), 'RZPot interpolation of Rzderiv w/ InterpSnapShotPotential of KeplerPotential fails at (R,z) = (%g,%g) by %g; value is %g' % (r,z,numpy.fabs((sp.Rzderiv(r,z)-kp.Rzderiv(r,z))/kp.Rzderiv(r,z)),kp.Rzderiv(r,z))
    #This tests within the grid
    rs= numpy.linspace(0.01,2.,10)[1:]
    zs= numpy.linspace(-0.2,0.2,20)
    for r in rs:
        for z in zs:
            assert numpy.fabs((sp.Rzderiv(r,z)-kp.Rzderiv(r,z))/kp.Rzderiv(r,z)) < 10.**-4.*(1.+19.*(numpy.fabs(z) < 0.05)), 'RZPot interpolation of Rzderiv w/ InterpSnapShotPotential of KeplerPotential fails at (R,z) = (%g,%g) by %g' % (r,z,numpy.fabs((sp.Rzderiv(r,z)-kp.Rzderiv(r,z))/kp.Rzderiv(r,z)))
    return None
Example #11
0
 def __init__(self, **kwargs):
     self.__kwargs = kwargs
     self.__profile = kwargs.get('profile', density_profiles.alphabetagamma)
     self.__drhodr = kwargs.get('drhodr', density_profiles.dalphabetagammadr)
     self.__d2rhodr2 = kwargs.get('d2rhodr2', density_profiles.d2alphabetagammadr2)
     self.__pars = kwargs.get('pars', {'alpha': 1., 'beta': 3., 'gamma': 1.,
         'c': 10., 'factor': 0.1})
     if self.__profile == density_profiles.alphabetagamma and self.__pars['beta'] <= 3.:
         if 'factor' not in self.__pars.keys(): self.__pars['factor'] = 0.1
     self.__m_vir = kwargs.get('m_vir', '1e12 Msol')
     self.__m_vir = units.Unit(self.__m_vir)
     self.__h = kwargs.get('h', 0.7)
     self.__overden = kwargs.get('overden', 200.)
     self.__r_vir = tools.calc_r_vir(self.__m_vir, self.__h, self.__overden)
     self.__r_s = self.__r_vir/self.__pars['c']
     self.__n_particles = int(kwargs.get('n_particles', 1e5))
     self.__logxmax_rho = np.log10(self.__pars['c']) + 2.
     # Make sure to sample well inside the gravitational softening
     self.__logxmin_rho = self.__logxmax_rho - .5*np.log10(self.__n_particles) - 3.
     self.__logxmin_dist_func = kwargs.get('logxmin_dist_func', -3.)
     self.__logxmax_dist_func = kwargs.get('logxmax_dist_func', 14.)
     self.__n_sample_rho = int(kwargs.get('n_sample_rho', 1e4))
     self.__n_sample_dist_func = int(kwargs.get('n_sample_dist_func', 1e2))
     self.__n_sample_dist_func_rho = int(kwargs.get('n_sample_dist_func_rho', 1e4))
     self.__random_seed = kwargs.get('random_seed', 4)
     if 'prng' in kwargs.keys():
         self.__prng = kwargs['prng']
     else:
         self.__prng = np.random.RandomState(self.__random_seed)
     self.__spline_order = kwargs.get('spline_order', 3)
     self.__progress_bar = kwargs.get('progress_bar', False)
     self.__no_bulk_vel = kwargs.get('no_bulk_vel', True)
     self.__x_rho = np.logspace(self.__logxmin_rho, self.__logxmax_rho, self.__n_sample_rho)
     self.__f_bary = kwargs.get('f_bary', 0.1)
     self.__mu = kwargs.get('mu', 1.3)
     self.__spin_parameter = kwargs.get('spin_parameter', 0.04)
     self.__rot_balanced = kwargs.get('rot_balanced', False)
     # Different gas profiles are not yet implemented or successfully tested
     self.__gas_profile = self.__profile
     self.__gas_pars = self.__pars
     #self.__gas_profile = kwargs.get('gas_profile', density_profiles.alphabetagamma)
     #self.__gas_pars = kwargs.get('gas_pars', {'alpha': 1., 'beta': 3., 'gamma': 1.,
     #   'c': 10., 'factor': 0.1})
     self.__r_s_gas = self.__r_vir/self.__gas_pars['c']
     #self.__vel_prof = kwargs.get('vel_prof', None)
     self.__vel_pars = kwargs.get('vel_pars', {'rs_v': array.SimArray(1., 'kpc'),
         'c': self.__pars['c'], 'prefac': 1., 'factor': 1.})
     self.__n_gas_particles = int(kwargs.get('n_gas_particles', self.__n_particles))
     self.__ang_mom_prof = kwargs.get('ang_mom_prof', am_profiles.bullock_prof)
     self.__ang_mom_pars = kwargs.get('ang_mom_pars', {'mu': self.__mu})
     self.__fname = kwargs.get('fname', 'halo.out')
     # Careful here: as of now, only the output as tipsy files has been successfully tested
     self.__type = {'gadget': gadget.GadgetSnap,
                     'grafic': grafic.GrafICSnap,
                     'nchilada': nchilada.NchiladaSnap,
                     'ramses': ramses.RamsesSnap,
                     'tipsy': tipsy.TipsySnap}[kwargs.get('type', 'tipsy')]
     self.sim = new(dm=self.__n_particles, gas=self.__n_gas_particles)
     self.sim.physical_units()
Example #12
0
def test_family_filter():
    f = pynbody.new(dm=100,gas=100)
    f_dm = f.dm
    f_dm_filter = f[pynbody.filt.FamilyFilter(pynbody.family.dm)]
    f_gas = f.gas
    f_gas_filter = f[pynbody.filt.FamilyFilter(pynbody.family.gas)]
    assert (f_dm.get_index_list(f) == f_dm_filter.get_index_list(f)).all()
    assert (f_gas.get_index_list(f) == f_gas_filter.get_index_list(f)).all()
Example #13
0
def test_one_family_promotion():
    fx = pynbody.new(dm=10)
    fx.dm['bla'] = np.arange(10)
    # should have been made as a full-simulation array

    assert 'bla' in fx.keys()
    fx['bla']
    del fx
Example #14
0
def setup():
    global f
    f = pynbody.new(1000)
    f['pos'] = np.random.normal(scale=1.0, size=f['pos'].shape)
    f['vel'] = np.random.normal(scale=1.0, size=f['vel'].shape)
    f['mass'] = np.random.uniform(1.0, 10.0, size=f['mass'].shape)
    f['pos'].units = 'kpc'
    f['vel'].units = 'km s^-1'
    f['mass'].units = 'Msol'
Example #15
0
def test_pickle() :
    import pickle
    f = pynbody.new(10)
    f['blob']=np.arange(10)
    s = f[[3,6,7]]
    assert (s['blob']==[3,6,7]).all(), "Preliminary check to testing pickle failed!"

    reloaded = pickle.loads(pickle.dumps(s['blob']))
    assert (reloaded==[3,6,7]).all(), "Unpickled array had incorrect contents"
Example #16
0
def setup():
    global f, original

    f = pynbody.new(dm=1000)
    f['pos'] = np.random.normal(scale=1.0, size=f['pos'].shape)
    f['vel'] = np.random.normal(scale=1.0, size=f['vel'].shape)
    f['mass'] = np.random.uniform(1.0, 10.0, size=f['mass'].shape)

    original = copy.deepcopy(f)
Example #17
0
def test_aform_saturation():
    """Test that NaN is returned when tform cannot be calculated from aform"""
    ipoints = pynbody.analysis.cosmology._interp_points
    f = pynbody.new(ipoints + 1)
    f['aform'] = np.linspace(0.0,1.1,ipoints+1)-0.05
    tf = f['tform'][::100]
    assert tf[0]!=tf[0] # nan outside range
    assert tf[-1]!=tf[-1] # nan outside range
    assert (tf[1:-1]==tf[1:-1]).all() # no nans inside range
Example #18
0
def init_snapshot(IC):
    """
    Initialize a snapshot for the IC object.  Requires that positions have
    been created.  Also sets:
     * pos
     * metals
     * temp
     * mass
     * star eps
    
    Parameters
    ----------
    IC : ICobj
    
    Returns
    -------
    snapshot : SimSnap
    """
    # Get required settings from IC
    settings = IC.settings
    # particle positions
    r = IC.pos.r
    xyz = IC.pos.xyz
    nParticles = IC.pos.nParticles
    m_star = settings.physical.M
    m_disk = IC.sigma.m_disk
    m_disk = match_units(m_disk, m_star)[0]
    m_particles = m_disk / float(nParticles)
    metals = settings.snapshot.metals
    # re-scale the particles (allows making of lo-mass disk)
    m_particles *= settings.snapshot.mScale
    
    # Handle units
    units = setup_units(m_star, r)
    
    if xyz.units != r.units:
        
        xyz.convert_units(units['x'])
    
    # Initialize arrays
    snapshot = pynbody.new(star=1,gas=nParticles)
    snapshot['vel'].units = units['v']
    snapshot['eps'] = SimArray(0.01, units['x'])
    snapshot['rho'] = 0.
    snapshot['metals'] = metals
    # Assign array values
    snapshot.gas['pos'] = xyz
    snapshot.gas['temp'] = IC.T(r)
    snapshot.gas['mass'] = m_particles
    
    snapshot.star['pos'] = 0.
    snapshot.star['mass'] = m_star
    # Estimate the star's softening length as the closest particle distance/2
    snapshot.star['eps'] = r.min()/2.
    
    return snapshot
Example #19
0
def test_potential_profile_fp32():
    f = pynbody.new(100)
    coords = np.random.normal(size=(100,3))
    del f['pos']
    del f['mass']
    f['pos'] = np.array(coords,dtype=np.float32)
    f['eps'] = np.ones(100,dtype=np.float32)
    f['mass'] = np.ones(100,dtype=np.float32)
    p = pynbody.analysis.profile.Profile(f, nbins=50)
    p['pot']
Example #20
0
def test_gravity_float():
    f = pynbody.new(100)
    np.random.seed(0)
    coords = np.random.normal(size=(100,3))
    del f['pos']
    del f['mass']
    f['pos'] = np.array(coords,dtype=np.float32)
    f['eps'] = np.ones(100,dtype=np.float32)
    f['mass'] = np.ones(100,dtype=np.float32)
    pynbody.gravity.calc.all_direct(f)
Example #21
0
def test_family_array_null_slice():
    """Regression test for issue where getting a family array for an IndexedSubSnap containing no members of that family
    - would erroneously return the entire family array"""

    test = pynbody.new(dm=10, star=10, order='dm,star')
    test.star['TestFamilyArray'] = 1.0
    assert len(test[[1,3,5,7]].star)==0 # this always succeeded
    assert len(test[[1,3,5,7]].star['mass'])==0 # this always succeeded
    assert len(test[1:9:2].star['TestFamilyArray'])==0 # this always succeeded
    assert len(test[[1, 3, 5, 11,13]].star['TestFamilyArray']) == 2  # this always succeeded
    assert len(test[[1,3,5,7]].star['TestFamilyArray'])==0 # this would fail
Example #22
0
def test_a_to_t():
    """Test scalefactor -> time conversion for accuracy. See also issue #479"""
    f = pynbody.new() # for default cosmology
    ipoints = pynbody.analysis.cosmology._interp_points
    interp_a = np.linspace(0.005, 1.0, ipoints+1) # enough values to force interpolation rather than direct calculation
    interp_z = 1./interp_a - 1.
    interp_t = pynbody.analysis.cosmology.age(f, z=interp_z)
    direct_aform = interp_a[::100]
    z = 1./direct_aform-1.
    direct_tform = pynbody.analysis.cosmology.age(f,z)
    npt.assert_almost_equal(direct_tform, interp_t[::100], decimal=4)
Example #23
0
def test_snapshotKeplerPotential_hash():
    # Test that hashing the previous grid works
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 1.
    s['eps']= 0.
    sp= potential.SnapshotRZPotential(s)
    kp= potential.KeplerPotential(amp=1.) #should be the same
    assert numpy.fabs(sp(1.,0.)-kp(1.,0.)) < 10.**-8., 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    assert numpy.fabs(sp(1.,0.)-kp(1.,0.)) < 10.**-8., 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    return None
Example #24
0
def test_write() :
    f2 = pynbody.new(dm=10,star=10,gas=20)
    f2.dm['test_array']=np.ones(10)
    f2['x']=np.arange(0,40)
    f2['vx']=np.arange(40,80)
    f2.write(fmt=pynbody.tipsy.TipsySnap, filename="testdata/test_out.tipsy")
    
    f3 = pynbody.load("testdata/test_out.tipsy")
    assert all(f3['x']==f2['x'])
    assert all(f3['vx']==f3['vx'])
    assert all(f3.dm['test_array']==f2.dm['test_array'])
Example #25
0
def test_snapshotKeplerPotential_zforce_naz():
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 1.
    s['eps']= 0.
    sp= potential.SnapshotRZPotential(s,num_threads=1)
    spaz= potential.SnapshotRZPotential(s,num_threads=1,nazimuths=12)
    assert numpy.fabs(sp.zforce(1.,0.)-spaz.zforce(1.,0.)) < 10.**-8., 'SnapshotRZPotential with single unit mass for naz=4 does not agree with naz=12'
    assert numpy.fabs(sp.zforce(0.5,0.)-spaz.zforce(0.5,0.)) < 10.**-8., 'SnapshotRZPotential with single unit mass for naz=4 does not agree with naz=12'
    assert numpy.fabs(sp.zforce(1.,0.5)-spaz.zforce(1.,0.5)) < 10.**-8., 'SnapshotRZPotential with single unit mass for naz=4 does not agree with naz=12'
    assert numpy.fabs(sp.zforce(1.,-0.5)-spaz.zforce(1.,-0.5)) < 10.**-8., 'SnapshotRZPotential with single unit mass for naz=4 does not agree with naz=12'
    return None
Example #26
0
def test_snapshotKeplerPotential_zforce_array():
    # Test evaluating the snapshotPotential with array input
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 1.
    s['eps']= 0.
    sp= potential.SnapshotRZPotential(s)
    kp= potential.KeplerPotential(amp=1.) #should be the same
    rs= numpy.ones(3)*0.5+0.5
    zs= (numpy.zeros(3)-1.)/2.
    assert numpy.all(numpy.fabs(sp.zforce(rs,zs)-kp.zforce(rs,zs)) < 10.**-8.), 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    return None
Example #27
0
def test_snapshotKeplerPotential_grid():
    # Test that evaluating on a grid works
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 2.
    s['eps']= 0.
    sp= potential.SnapshotRZPotential(s)
    kp= potential.KeplerPotential(amp=2.) #should be the same
    rs= numpy.arange(3)+1
    zs= 0.1
    assert numpy.all(numpy.fabs(sp(rs,zs)-kp(rs,zs)) < 10.**-8.), 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    return None
Example #28
0
def test_ndim_issue_399():
    f = pynbody.new(10)
    f_sub = f[[1,2,3,6]]
    f['blob'] = np.arange(10)
    assert f['blob'].ndim==1
    assert f_sub['blob'].ndim==1

    f['blob_3d'] = np.zeros((10,3))
    assert f['blob_3d'].ndim==2
    assert f['blob_3d'].shape==(10,3)
    assert f_sub['blob_3d'].ndim==2
    assert f_sub['blob_3d'].shape==(4,3)
Example #29
0
def test_snapshotKeplerPotential_eval():
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 1.
    s['eps']= 0.
    sp= potential.SnapshotRZPotential(s,num_threads=1)
    kp= potential.KeplerPotential(amp=1.) #should be the same
    assert numpy.fabs(sp(1.,0.)-kp(1.,0.)) < 10.**-8., 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    assert numpy.fabs(sp(0.5,0.)-kp(0.5,0.)) < 10.**-8., 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    assert numpy.fabs(sp(1.,0.5)-kp(1.,0.5)) < 10.**-8., 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    assert numpy.fabs(sp(1.,-0.5)-kp(1.,-0.5)) < 10.**-8., 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    return None
Example #30
0
def test_nonmonotonic_transfer_matrix():
    # test the case where a non-monotonic bridge between two simulations is queries for particle transfer
    f1 = pynbody.new(dm=10)
    f2 = pynbody.new(dm=10)
    f1['iord'] = np.arange(0,10)
    f2['iord'] = np.array([0,2,4,6,8,1,3,5,7,9],dtype=np.int32)


    # 100% of mass in group 1 transfers to group 1
    # 80% of mass in group 0 transfers to group 0
    # 20% of mass in group 0 transfers to group 1

    f1['grp'] = np.array([0,0,0,0,0,1,1,1,1,1],dtype=np.int32)
    f2['grp'] = np.array([0,0,0,0,1,1,1,1,1,1],dtype=np.int32)[f2['iord']]

    b = pynbody.bridge.OrderBridge(f1,f2,monotonic=False)

    h1 = pynbody.halo.GrpCatalogue(f1)
    h2 = pynbody.halo.GrpCatalogue(f2)

    xfer = b.catalog_transfer_matrix(0,1,h1,h2)

    assert (xfer==[[4,1],[0,5]]).all()
Example #31
0
def get_final_density(input_linear_field, output_resolution=None, time=0.025):
    """Starting from a linear field, generate the equivalent non-linear field under the
    Zeldovich approximation at the specified time. If the output resolution is not
    specified, it is chosen to match in the input resolution. Output is both returned
    as a numpy array and displayed in a matplotlib window."""
    assert input_linear_field.shape[0] == input_linear_field.shape[1]
    N = len(input_linear_field)
    if not output_resolution:
        output_resolution = N
    x, y = get_evolved_particle_positions(input_linear_field, time)
    f = pynbody.new(len(x))
    f['x'] = x - N / 2
    f['y'] = y - N / 2
    f['mass'] = 1.0
    f['mass'].units = "kg"
    f['x'].units = "cm"
    return pynbody.plot.sph.image(f,
                                  width=N,
                                  resolution=output_resolution,
                                  units="kg cm^-2")
def test_snapshotKeplerPotential_eval():
    # Set up a snapshot with just one unit mass at the origin
    s = pynbody.new(star=1)
    s['mass'] = 1.
    s['eps'] = 0.
    sp = potential.SnapshotRZPotential(s, num_threads=1)
    kp = potential.KeplerPotential(amp=1.)  #should be the same
    assert numpy.fabs(
        sp(1., 0.) - kp(1., 0.)
    ) < 10.**-8., 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    assert numpy.fabs(
        sp(0.5, 0.) - kp(0.5, 0.)
    ) < 10.**-8., 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    assert numpy.fabs(
        sp(1., 0.5) - kp(1., 0.5)
    ) < 10.**-8., 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    assert numpy.fabs(
        sp(1., -0.5) - kp(1., -0.5)
    ) < 10.**-8., 'SnapshotRZPotential with single unit mass does not correspond to KeplerPotential'
    return None
Example #33
0
def test_interpsnapshotKeplerPotential_logR_eval():
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 1.
    s['eps']= 0.
    sp= potential.InterpSnapshotRZPotential(s,
                                          rgrid=(numpy.log(0.01),numpy.log(20.),
                                                 251),
                                          logR=True,
                                          zgrid=(0.,0.2,201),
                                          interpPot=True,
                                          zsym=True)
    kp= potential.KeplerPotential(amp=1.) #should be the same
    rs= numpy.linspace(0.02,16.,20)
    zs= numpy.linspace(-0.15,0.15,40)
    mr,mz= numpy.meshgrid(rs,zs)
    mr= mr.flatten()
    mz= mz.flatten()
    assert numpy.all(numpy.fabs((sp(mr,mz)-kp(mr,mz))/kp(mr,mz)) < 10.**-5.), 'RZPot interpolation w/ interpRZPotential fails for vector input, w/ logR at (R,z) = (%f,%f) by %g' % (mr[numpy.argmax(numpy.fabs((sp(mr,mz)-kp(mr,mz))/kp(mr,mz)))],mz[numpy.argmax(numpy.fabs((sp(mr,mz)-kp(mr,mz))/kp(mr,mz)))],numpy.amax(numpy.fabs((sp(mr,mz)-kp(mr,mz))/kp(mr,mz))))
    return None
def test_snapshotKeplerPotential_zforce_naz():
    # Set up a snapshot with just one unit mass at the origin
    s = pynbody.new(star=1)
    s['mass'] = 1.
    s['eps'] = 0.
    sp = potential.SnapshotRZPotential(s, num_threads=1)
    spaz = potential.SnapshotRZPotential(s, num_threads=1, nazimuths=12)
    assert numpy.fabs(
        sp.zforce(1., 0.) - spaz.zforce(1., 0.)
    ) < 10.**-8., 'SnapshotRZPotential with single unit mass for naz=4 does not agree with naz=12'
    assert numpy.fabs(
        sp.zforce(0.5, 0.) - spaz.zforce(0.5, 0.)
    ) < 10.**-8., 'SnapshotRZPotential with single unit mass for naz=4 does not agree with naz=12'
    assert numpy.fabs(
        sp.zforce(1., 0.5) - spaz.zforce(1., 0.5)
    ) < 10.**-8., 'SnapshotRZPotential with single unit mass for naz=4 does not agree with naz=12'
    assert numpy.fabs(
        sp.zforce(1., -0.5) - spaz.zforce(1., -0.5)
    ) < 10.**-8., 'SnapshotRZPotential with single unit mass for naz=4 does not agree with naz=12'
    return None
Example #35
0
def test_interpsnapshotKeplerPotential_noc_eval():
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 1.
    s['eps']= 0.
    sp= potential.InterpSnapshotRZPotential(s,
                                          rgrid=(0.01,2.,201),
                                          zgrid=(0.,0.2,201),
                                          logR=False,
                                          interpPot=True,
                                          zsym=True,
                                          enable_c=False)
    kp= potential.KeplerPotential(amp=1.) #should be the same
    #Test all at the same time to use vector evaluation
    rs= numpy.linspace(0.01,2.,10)
    zs= numpy.linspace(-0.2,0.2,20)
    mr,mz= numpy.meshgrid(rs,zs)
    mr= mr.flatten()
    mz= mz.flatten()
    assert numpy.all(numpy.fabs((sp(mr,mz)-kp(mr,mz))/kp(mr,mz)) < 10.**-5.), 'RZPot interpolation w/ interpRZPotential fails for vector input, without enable_c'
    return None
Example #36
0
def test_write():
    f2 = pynbody.new(gas=20, star=11, dm=9, order='gas,dm,star')
    f2.dm['test_array'] = np.ones(9)
    f2['x'] = np.arange(0, 40)
    f2['vx'] = np.arange(40, 80)
    f2.properties['a'] = 0.5
    f2.properties['time'] = 12.0
    f2.write(fmt=pynbody.tipsy.TipsySnap, filename="testdata/test_out.tipsy")

    f3 = pynbody.load("testdata/test_out.tipsy")
    assert all(f3['x'] == f2['x'])
    assert all(f3['vx'] == f3['vx'])
    assert all(f3.dm['test_array'] == f2.dm['test_array'])
    assert f3.properties['a'] == 0.5

    # this looks strange, but it's because the .param file in the testdata folder implies a cosmological tipsy snap
    # whereas we have just written the snapshot asserting it is non-cosmological
    f2.write(fmt=pynbody.tipsy.TipsySnap,
             filename="testdata/test_out.tipsy",
             cosmological=False)
    f3 = pynbody.load("testdata/test_out.tipsy")
    assert f3.properties['a'] == 12
def test_interpsnapshotKeplerPotential_eval_naz():
    # Set up a snapshot with just one unit mass at the origin
    s = pynbody.new(star=1)
    s['mass'] = 1.
    s['eps'] = 0.
    sp = potential.InterpSnapshotRZPotential(s,
                                             rgrid=(0.01, 2., 51),
                                             zgrid=(0., 0.2, 51),
                                             logR=False,
                                             interpPot=True,
                                             zsym=True,
                                             numcores=1)
    spaz = potential.InterpSnapshotRZPotential(s,
                                               rgrid=(0.01, 2., 51),
                                               zgrid=(0., 0.2, 51),
                                               logR=False,
                                               interpPot=True,
                                               zsym=True,
                                               numcores=1,
                                               nazimuths=12)
    #This just tests on the grid
    rs = numpy.linspace(0.01, 2., 21)
    zs = numpy.linspace(-0.2, 0.2, 41)
    for r in rs:
        for z in zs:
            assert numpy.fabs(
                (sp(r, z) - spaz(r, z)) / sp(r, z)
            ) < 10.**-10., 'RZPot interpolation w/ InterpSnapShotPotential of KeplerPotential with different nazimuths fails at (R,z) = (%g,%g)' % (
                r, z)
    #This tests within the grid, with vector evaluation
    rs = numpy.linspace(0.01, 2., 10)
    zs = numpy.linspace(-0.2, 0.2, 20)
    mr, mz = numpy.meshgrid(rs, zs)
    mr = mr.flatten()
    mz = mz.flatten()
    assert numpy.all(
        numpy.fabs((sp(mr, mz) - spaz(mr, mz)) / sp(mr, mz)) < 10.**-5.
    ), 'RZPot interpolation w/ interpRZPotential with different nazimimuths fails for vector input'
    return None
def test_interpsnapshotKeplerPotential_eval():
    # Set up a snapshot with just one unit mass at the origin
    s = pynbody.new(star=1)
    s['mass'] = 1.
    s['eps'] = 0.
    sp = potential.InterpSnapshotRZPotential(s,
                                             rgrid=(0.01, 2., 201),
                                             zgrid=(0., 0.2, 201),
                                             logR=False,
                                             interpPot=True,
                                             zsym=True,
                                             numcores=1)
    kp = potential.KeplerPotential(amp=1.)  #should be the same
    #This just tests on the grid
    rs = numpy.linspace(0.01, 2., 21)
    zs = numpy.linspace(-0.2, 0.2, 41)
    for r in rs:
        for z in zs:
            assert numpy.fabs(
                (sp(r, z) - kp(r, z)) / kp(r, z)
            ) < 10.**-10., 'RZPot interpolation w/ InterpSnapShotPotential of KeplerPotential fails at (R,z) = (%g,%g)' % (
                r, z)
    #This tests within the grid
    rs = numpy.linspace(0.01, 2., 10)
    zs = numpy.linspace(-0.2, 0.2, 20)
    for r in rs:
        for z in zs:
            assert numpy.fabs(
                (sp(r, z) - kp(r, z)) / kp(r, z)
            ) < 10.**-5., 'RZPot interpolation w/ InterpSnapShotPotential of KeplerPotential fails at (R,z) = (%g,%g) by %g' % (
                r, z, numpy.fabs((sp(r, z) - kp(r, z)) / kp(r, z)))
    #Test all at the same time to use vector evaluation
    mr, mz = numpy.meshgrid(rs, zs)
    mr = mr.flatten()
    mz = mz.flatten()
    assert numpy.all(
        numpy.fabs((sp(mr, mz) - kp(mr, mz)) / kp(mr, mz)) < 10.**-5.
    ), 'RZPot interpolation w/ interpRZPotential fails for vector input'
    return None
Example #39
0
def test_interpsnapshotKeplerPotential_verticalfreq():
    # Set up a snapshot with just one unit mass at the origin
    s= pynbody.new(star=1)
    s['mass']= 2.
    s['eps']= 0.
    sp= potential.InterpSnapshotRZPotential(s,
                                            rgrid=(0.01,2.,101),
                                            zgrid=(0.,0.2,101),
                                            logR=False,
                                            interpPot=True,
                                            interpverticalfreq=True,
                                            zsym=True)
    kp= potential.KeplerPotential(normalize=2.) #should be the same
    #This just tests on the grid
    rs= numpy.linspace(0.01,2.,21)[1:]
    for r in rs:
        assert numpy.fabs((sp.verticalfreq(r)-kp.verticalfreq(r))/kp.verticalfreq(r)) < 10.**-4., 'RZPot interpolation of verticalfreq w/ InterpSnapShotPotential of KeplerPotential fails at R = %g by %g' % (r,numpy.fabs((sp.verticalfreq(r)-kp.verticalfreq(r))/kp.verticalfreq(r)))
    #This tests within the grid
    rs= numpy.linspace(0.01,2.,10)[1:]
    for r in rs:
        assert numpy.fabs((sp.verticalfreq(r)-kp.verticalfreq(r))/kp.verticalfreq(r)) < 10.**-4., 'RZPot interpolation of verticalfreq w/ InterpSnapShotPotential of KeplerPotential fails at R = %g by %g' % (r,numpy.fabs((sp.verticalfreq(r)-kp.verticalfreq(r))/kp.verticalfreq(r)))
    return None
Example #40
0
def test_dimensionful_comparison():
    # check that dimensionful units compare correctly
    # see issue 130
    a1 = SA(np.ones(2), 'kpc')
    a2 = SA(np.ones(2) * 2, 'pc')
    assert (a2 < a1).all()
    assert not (a2 > a1).any()
    a2 = SA(np.ones(2) * 1000, 'pc')
    assert (a1 == a2).all()
    assert (a2 <= a2).all()

    a2 = SA(np.ones(2), 'Msol')
    try:
        a2 < a1
        assert False, "Comparison should have failed - incompatible units"
    except pynbody.units.UnitsException:
        pass

    a2 = SA(np.ones(2))
    try:
        a2 < a1
        assert False, "Comparison should have failed - incompatible units"
    except pynbody.units.UnitsException:
        pass

    assert (a1 < pynbody.units.Unit("0.5 Mpc")).all()
    assert (a1 > pynbody.units.Unit("400 pc")).all()

    # now check with subarrays

    x = pynbody.new(10)
    x['a'] = SA(np.ones(10), 'kpc')
    x['b'] = SA(2 * np.ones(10), 'pc')

    y = x[[1, 2, 5]]

    assert (y['b'] < y['a']).all()
    assert not (y['b'] > y['a']).any()
def test_interpsnapshotKeplerPotential_normalize_units():
    # Set up a snapshot with just one unit mass at the origin
    s = pynbody.new(star=1)
    s['mass'] = 4.
    s['eps'] = 0.
    s['pos'].units = 'kpc'
    s['vel'].units = 'km s**-1'
    sp = potential.InterpSnapshotRZPotential(s,
                                             rgrid=(0.01, 3., 201),
                                             zgrid=(0., 0.2, 201),
                                             logR=False,
                                             interpPot=True,
                                             zsym=True)
    #Currently unnormalized
    assert numpy.fabs(
        sp.Rforce(1., 0.) + 4.
    ) < 10.**-7., "InterpSnapShotPotential that is assumed to be unnormalized doesn't behave as expected"
    # Normalize
    sp.normalize(R0=1.)
    assert numpy.fabs(
        sp.Rforce(1., 0.) + 1.
    ) < 10.**-7., "InterpSnapShotPotential that is assumed to be normalized doesn't behave as expected"
    # De normalize
    sp.denormalize()
    assert numpy.fabs(
        sp.Rforce(1., 0.) + 4.
    ) < 10.**-7., "InterpSnapShotPotential that is assumed to be normalized doesn't behave as expected"
    # Also test when R0 =/= 1
    sp.normalize(R0=2.)
    assert numpy.fabs(
        sp.Rforce(1., 0.) + 1.
    ) < 10.**-7., "InterpSnapShotPotential that is assumed to be normalized doesn't behave as expected"
    # De normalize
    sp.denormalize()
    assert numpy.fabs(
        sp.Rforce(1., 0.) + 4.
    ) < 10.**-7., "InterpSnapShotPotential that is assumed to be normalized doesn't behave as expected"
    return None
Example #42
0
def test_sim_propagation():
    f = pynbody.new(10)
    f['blob'] = 0

    # check arrays remember their simulation
    assert f['blob'].sim is f
    assert f[::2]['blob'].sim is f

    assert f[[1, 2, 5]]['blob'].sim.ancestor is f
    assert f[[1, 2, 5]]['blob'].sim is not f

    # if we do anything that constructs a literal SimArray, the simulation
    # reference jumps up to be the main snapshot since we can't keep track
    # of what SubSnap it came from in generality
    assert pynbody.array.SimArray(f[[1, 2, 5]]['blob']).sim is f
    assert (f[[1, 2, 5]]['blob']).sum().sim is f

    # the reference should be weak: check
    X = f['blob']
    assert X.sim is f
    del f
    gc.collect()
    assert X.sim is None
def test_interpsnapshotKeplerPotential_z2deriv():
    # Set up a snapshot with just one unit mass at the origin
    s = pynbody.new(star=1)
    s['mass'] = 2.
    s['eps'] = 0.
    sp = potential.InterpSnapshotRZPotential(s,
                                             rgrid=(0.01, 2., 101),
                                             zgrid=(0., 0.2, 101),
                                             logR=False,
                                             interpPot=True,
                                             interpverticalfreq=True,
                                             zsym=True)
    kp = potential.KeplerPotential(amp=2.)  #should be the same
    #This just tests on the grid
    rs = numpy.linspace(0.01, 2., 21)[1:]
    zs = numpy.linspace(-0.2, 0.2, 41)
    for r in rs:
        for z in zs:
            assert numpy.fabs(
                (sp.z2deriv(r, z) - kp.z2deriv(r, z)) / kp.z2deriv(r, z)
            ) < 10.**-4., 'RZPot interpolation of z2deriv w/ InterpSnapShotPotential of KeplerPotential fails at (R,z) = (%g,%g) by %g' % (
                r, z,
                numpy.fabs(
                    (sp.z2deriv(r, z) - kp.z2deriv(r, z)) / kp.z2deriv(r, z)))
    #This tests within the grid
    rs = numpy.linspace(0.01, 2., 10)[1:]
    zs = numpy.linspace(-0.2, 0.2, 20)
    for r in rs:
        for z in zs:
            assert numpy.fabs(
                (sp.z2deriv(r, z) - kp.z2deriv(r, z)) / kp.z2deriv(r, z)
            ) < 2. * 10.**-4., 'RZPot interpolation of z2deriv w/ InterpSnapShotPotential of KeplerPotential fails at (R,z) = (%g,%g) by %g' % (
                r, z,
                numpy.fabs(
                    (sp.z2deriv(r, z) - kp.z2deriv(r, z)) / kp.z2deriv(r, z)))
    return None
Example #44
0
def test_float_kd():
    f = pynbody.load("testdata/test_g2_snap")
    del f.properties['boxsize']

    assert f.dm['mass'].dtype == f.dm['pos'].dtype == np.float32
    assert f.dm['smooth'].dtype == np.float32

    # make double copy
    g = pynbody.new(len(f.dm))
    g.dm['pos'] = f.dm['pos']
    g.dm['mass'] = f.dm['mass']

    assert g.dm['mass'].dtype == g.dm['pos'].dtype == g.dm[
        'smooth'].dtype == np.float64

    # check smoothing lengths agree (they have been calculated differently
    # using floating/double routines)

    npt.assert_allclose(f.dm['smooth'], g.dm['smooth'], rtol=1e-4)
    npt.assert_allclose(f.dm['rho'], g.dm['rho'], rtol=1e-4)

    # check all combinations of float/double smoothing
    double_ar = np.ones(len(f.dm), dtype=np.float64)
    float_ar = np.ones(len(f.dm), dtype=np.float32)

    double_double = g.dm.kdtree.sph_mean(double_ar, 32)
    double_float = g.dm.kdtree.sph_mean(float_ar, 32)
    float_double = f.dm.kdtree.sph_mean(double_ar, 32)
    float_float = f.dm.kdtree.sph_mean(float_ar, 32)

    # take double-double as 'gold standard' (though of course if any of these
    # fail it could also be a problem with the double-double case)

    npt.assert_allclose(double_double, double_float, rtol=1e-4)
    npt.assert_allclose(double_double, float_double, rtol=1e-4)
    npt.assert_allclose(double_double, float_float, rtol=1e-4)
Example #45
0
def test_family_array_sim():
    """Test that the simulation of a family array is a family slice"""

    test = pynbody.new(dm=10, star=10)
    test.dm._create_array('mass')
    assert test.dm['mass'].sim == test.dm
Example #46
0
def wave1d(rho0=1., dustFrac0=0.5, drho=1e-4, v0=1e-4, gamma=5./3, cs=1., 
            ngas=100, L=1., tStop=5e-4, nSmooth=5, nPeriods=1):
    r"""
    Generate a 1D dusty-gas wave as in Price & Laibe 2015.
    I've only gotten this to work with the M4Kernel and nSmooth = 4 or 5.
    Other kernels or nSmooth create noisy garbage
    
    Default params are stored in 'wave_defaults.param' and can be overridden
    in 'user_wave_defaults.param'
    
    This applies perturbations like:
        
        .. math::
            \rho(z) &= \rho_0 (1 + \delta\rho\sin{(2 \pi N z/L)}) \\
            v(z) &= v_0 \sin{(2 \pi N z/L)} \\
            P(z) &= P_0 + c_s v_0 \rho_0 \sin{(2 \pi N z/L)} 
                [1 + (\delta\rho/2) \sin{(2 \pi N z/L)}]
        
    Which makes a wave moving to the right at the speed of sound :math:`c_s`.
    The pressure perturbation is derived from the density and velocity 
    perturbations using the momentum equation and assuming sinewaves travelling
    to the right at cs
    
    Parameters
    ----------
    All parameters listed are in code units!
    
    rho0: float
        Base total density. :math:`\rho_0`
    dustFrac: float
        Dust fraction of the gas.
    drho: float
        Fractional amplitude of density perturbation
    v0: float
        Velocity perturbation amplitude
    gamma: float
        Adiabatic index
    cs: float
        Sound speed
    ngas: int
        Number of particles
    L: float
        Length of the periodic box
    tStop: float
        Stopping time of the dust
    nSmooth: int
        Number of neighbors for smoothing
    nPeriods: float or int
        Number of wave periods to fit in the box
    
    Returns
    -------
    snapshot: pynbody SimSnap
        ICs for the simulation.  they will also be saved to disk
    param: dict
        Runtime params.  Also saved to a .param file
    paramname: str
        Path to the saved param file
    """
    args = locals()
    nDim = 1
    pickle.dump(args, open(argname, 'w'), 2)
    print 'Saved args to:', argname
    
    param = testdust.utils.loadDefaultParam(defaultParam1D, userDefaults1D)
    
    # -------------------------------------------
    # Parse input param file
    # -------------------------------------------
    # Get units
    units = diskpy.pychanga.units_from_param(param)
    # filenames
    fname = param['achInFile']
    outparam = param['achOutName'] + '.param'
    molecularWeight = param['dMeanMolWeight']
    
    # -------------------------------------------
    # Set-up
    # -------------------------------------------
    mass = rho0/(L * float(ngas))
    # Give everything units
    v0 = SimArray(v0, units['v_unit'])
    cs = SimArray(cs, units['v_unit'])
    rho0 = SimArray(rho0, units['rho_unit'])
    L = SimArray(L, units['l_unit'])
    mass = SimArray(mass, units['m_unit'])
    tStop = SimArray(tStop, units['t_unit'])
    molecularWeight = SimArray(molecularWeight, 'm_p')
    # Initialize snapshot
    snap = pynbody.new(gas=ngas)
    # Initialize arrays
    for key in ('temp', 'rho', 'dustFrac', 'pos', 'mass'):
        
        snap[key] = 0.
    
    k = 2 * np.pi * nPeriods/L
    # -------------------------------------------
    # Positions and mass
    # -------------------------------------------
    z = wavePos(ngas, drho, L, nPeriods)
    snap['z'] = z
    snap['mass'] = mass
    # -------------------------------------------
    # Temperature
    # -------------------------------------------
    P0 = rho0 * (cs**2)/gamma
    P = P0 + cs * v0 * rho0 * np.sin(k * z) * (1 + 0.5 * drho * np.sin(k * z))
    rho = rho0 * (1 + drho * np.sin(k * z))
    T = molecularWeight * P/(kB * (1-dustFrac0) * rho)
    T.convert_units('K')
    print 'Temp:', T
    snap['temp'] = T
    # -------------------------------------------
    # Velocity profile
    # -------------------------------------------
    vz = v0 * np.sin(2*np.pi*snap['z']*nPeriods/L)
    v = SimArray(np.zeros([ngas, 3]), vz.units)
    v[:,2] = vz
    snap['vel'] = v
    # -------------------------------------------
    # Dust stuff
    # -------------------------------------------
    # Dust mass
    grainDensity = rho0*cs*tStop*np.sqrt(8/np.pi/gamma)/units['l_unit']
    grainDensity.convert_units(units['rho_unit'])
    param['dDustSize'] = 1.
    param['dDustGrainDensity'] = float(grainDensity)
    # Define dust fraction
    snap['dustFrac'] = dustFrac0 * np.ones(ngas)
    # Estimate density and eps
    snap['rho'] 
    snap['eps'] = 100 * L/ngas**(nDim/3.)
    
    # -------------------------------------------
    # Write out
    # -------------------------------------------
    testdust.utils.setupParamBounds(param, [float(L)])
    param['nSmooth'] = nSmooth
    param['dConstGamma'] = gamma
    # Write out snapshot and paramfile
    snap.write(fmt=pynbody.tipsy.TipsySnap, filename=fname, double_pos=True, \
    double_vel=True)
    print 'Saved snapshot to:', fname
    diskpy.utils.configsave(param, outparam, 'param')
    print 'Saved .param to:', outparam
    
    return snap, param, outparam
Example #47
0
def test_reject_unsuitable_rockstar_files():
    fwrong = pynbody.new(dm=2097152)
    fwrong.properties['z'] = 0
    with pytest.raises(RuntimeError):
        hwrong = fwrong.halos()
import pynbody
import numpy as np
from pynbody.array import SimArray

if __name__ == '__main__':

    f = pynbody.new(star=8)

    mass_prefactor = 1e4

    f['pos'] = SimArray(np.array([
        [-2,  2, 2], [-2,  2, -2],
        [-2, -2, 2], [-2, -2, -2],
        [ 2, -2, 2], [ 2, -2, -2],
        [ 2,  2, 2], [ 2,  2, -2]]
        )*0.8, units='kpc')

    f['vel'] = SimArray(np.array([[0, 0, -60],[0,0,80]]*4), units='km s**-1')

    f['mass'] = SimArray([1e-10]*8, units='1e10 Msol') * mass_prefactor
    # f.properties['time'] = 14 * pynbody.units.Unit('s kpc km**-1')

    # the 1 minus part is because in the output time is set to 1 in internal units , so that the age is 1 minus the tform.
    f['tform'] = 1 * pynbody.units.Unit('s kpc km**-1') - SimArray([1,1]*2+[1,4]*2, units='Gyr')
    print(f['tform'])
    f['feh'] = SimArray([-1.22,-1.22]+[0.29, -1.22]*2 + [-1.22, -1.22])

    f.properties['boxsize'] = 1000 * pynbody.units.kpc
    print(f.properties)

    pynbody.config['sph']['smooth-particles'] = 1
Example #49
0
def snapshot_gen(ICobj):
    """
    Generates a tipsy snapshot from the initial conditions object ICobj.
    
    Returns snapshot, param
    
        snapshot: tipsy snapshot
        param: dictionary containing info for a .param file
    Note: Code has been edited (dflemin3) such that now it returns a snapshot for a circumbinary disk
    where initial conditions generated assuming star at origin of mass M.  After gas initialized, replaced
    star at origin with binary system who's center of mass lies at the origin and who's mass m1 +m2 = M
    """
    
    print 'Generating snapshot...'
    # Constants
    G = SimArray(1.0,'G')
    # ------------------------------------
    # Load in things from ICobj
    # ------------------------------------
    print 'Accessing data from ICs'
    settings = ICobj.settings
    
    # snapshot file name
    snapshotName = settings.filenames.snapshotName
    paramName = settings.filenames.paramName   
 
    # particle positions
    r = ICobj.pos.r
    xyz = ICobj.pos.xyz
    
    # Number of particles
    nParticles = ICobj.pos.nParticles
    
    # molecular mass
    m = settings.physical.m
    
    # star mass
    m_star = settings.physical.M.copy()
    
    # disk mass
    m_disk = ICobj.sigma.m_disk.copy()
    m_disk = match_units(m_disk, m_star)[0]
    
    # mass of the gas particles
    m_particles = m_disk / float(nParticles)
    
    # re-scale the particles (allows making of low-mass disk)
    m_particles *= settings.snapshot.mScale
    
    # -------------------------------------------------
    # Assign output
    # -------------------------------------------------
    print 'Assigning data to snapshot'
    # Get units all set up
    m_unit = m_star.units
    pos_unit = r.units
    
    if xyz.units != r.units:
        
        xyz.convert_units(pos_unit)
        
    # time units are sqrt(L^3/GM)
    t_unit = np.sqrt((pos_unit**3)*np.power((G*m_unit), -1)).units
    # velocity units are L/t
    v_unit = (pos_unit/t_unit).ratio('km s**-1')
    # Make it a unit, save value for future conversion
    v_unit_vel = v_unit
    #Ensure v_unit_vel is the same as what I assume it is.
    assert(np.fabs(AddBinary.VEL_UNIT-v_unit_vel)<AddBinary.SMALL),"VEL_UNIT not equal to ChaNGa unit! Why??"			
	
    v_unit = pynbody.units.Unit('{0} km s**-1'.format(v_unit))
    
    # Other settings
    metals = settings.snapshot.metals
    star_metals = metals
    
    # Generate snapshot
    # Note that empty pos, vel, and mass arrays are created in the snapshot
    snapshot = pynbody.new(star=1,gas=nParticles)
    snapshot['vel'].units = v_unit
    snapshot['eps'] = 0.01*SimArray(np.ones(nParticles+1, dtype=np.float32), pos_unit)
    snapshot['metals'] = SimArray(np.zeros(nParticles+1, dtype=np.float32))
    snapshot['rho'] = SimArray(np.zeros(nParticles+1, dtype=np.float32))
    
    snapshot.gas['pos'] = xyz
    snapshot.gas['temp'] = ICobj.T(r)
    snapshot.gas['mass'] = m_particles
    snapshot.gas['metals'] = metals
    
    snapshot.star['pos'] = SimArray([[ 0.,  0.,  0.]],pos_unit)
    snapshot.star['vel'] = SimArray([[ 0.,  0.,  0.]], v_unit)
    snapshot.star['mass'] = m_star
    snapshot.star['metals'] = SimArray(star_metals)
    # Estimate the star's softening length as the closest particle distance
    #snapshot.star['eps'] = r.min()
    
    # Make param file
    param = make_param(snapshot, snapshotName)
    param['dMeanMolWeight'] = m
       
    gc.collect()
    
    # CALCULATE VELOCITY USING calc_velocity.py.  This also estimates the 
    # gravitational softening length eps
    print 'Calculating circular velocity'
    preset = settings.changa_run.preset
    max_particles = global_settings['misc']['max_particles']
    calc_velocity.v_xy(snapshot, param, changa_preset=preset, max_particles=max_particles)
    
    gc.collect()
  
	# -------------------------------------------------
    # Estimate time step for changa to use
    # -------------------------------------------------
    # Save param file
    configsave(param, paramName, 'param')
    # Save snapshot
    snapshot.write(filename=snapshotName, fmt=pynbody.tipsy.TipsySnap)
    # est dDelta
    dDelta = ICgen_utils.est_time_step(paramName, preset)
    param['dDelta'] = dDelta
 
	# -------------------------------------------------
    # Create director file
    # -------------------------------------------------
    # largest radius to plot
    r_director = float(0.9 * r.max())
    # Maximum surface density
    sigma_min = float(ICobj.sigma(r_director))
    # surface density at largest radius
    sigma_max = float(ICobj.sigma.input_dict['sigma'].max())
    # Create director dict
    director = make_director(sigma_min, sigma_max, r_director, filename=param['achOutName'])
    ## Save .director file
    #configsave(director, directorName, 'director')

    #Now that velocities and everything are all initialized for gas particles, create new snapshot to return in which
    #single star particle is replaced by 2, same units as above
    snapshotBinary = pynbody.new(star=2,gas=nParticles)
    snapshotBinary['eps'] = 0.01*SimArray(np.ones(nParticles+2, dtype=np.float32), pos_unit)
    snapshotBinary['metals'] = SimArray(np.zeros(nParticles+2, dtype=np.float32))
    snapshotBinary['vel'].units = v_unit
    snapshotBinary['pos'].units = pos_unit
    snapshotBinary['mass'].units = snapshot['mass'].units
    snapshotBinary['rho'] = SimArray(np.zeros(nParticles+2, dtype=np.float32))

    #Assign gas particles with calculated/given values from above
    snapshotBinary.gas['pos'] = snapshot.gas['pos']
    snapshotBinary.gas['vel'] = snapshot.gas['vel']
    snapshotBinary.gas['temp'] = snapshot.gas['temp']
    snapshotBinary.gas['rho'] = snapshot.gas['rho']
    snapshotBinary.gas['eps'] = snapshot.gas['eps']
    snapshotBinary.gas['mass'] = snapshot.gas['mass']
    snapshotBinary.gas['metals'] = snapshot.gas['metals']

    #Load Binary system obj to initialize system
    binsys = ICobj.settings.physical.binsys
    
    x1,x2,v1,v2 = binsys.generateICs()

    #Put velocity in sim units
    #!!! Note: v_unit_vel will always be 29.785598165 km/s when m_unit = Msol and r_unit = 1 AU in kpc!!!
    #conv = v_unit_vel #km/s in sim units
    #v1 /= conv
    #v2 /= conv

    #Assign position, velocity assuming CCW orbit

    snapshotBinary.star[0]['pos'] = SimArray(x1,pos_unit)
    snapshotBinary.star[0]['vel'] = SimArray(v1,v_unit)
    snapshotBinary.star[1]['pos'] = SimArray(x2,pos_unit)
    snapshotBinary.star[1]['vel'] = SimArray(v2,v_unit)

    #Set stellar masses
    #Set Mass units
    #Create simArray for mass, convert units to simulation mass units
    priMass = SimArray(binsys.m1,m_unit)
    secMass = SimArray(binsys.m2,m_unit)

    snapshotBinary.star[0]['mass'] = priMass
    snapshotBinary.star[1]['mass'] = secMass
    snapshotBinary.star['metals'] = SimArray(star_metals)

    #Estimate stars' softening length as fraction of distance to COM
    d = np.sqrt(AddBinary.dotProduct(x1-x2,x1-x2))

    snapshotBinary.star[0]['eps'] = SimArray(math.fabs(d)/4.0,pos_unit)
    snapshotBinary.star[1]['eps'] = SimArray(math.fabs(d)/4.0,pos_unit)
 
    print 'Wrapping up'
    # Now set the star particle's tform to a negative number.  This allows
    # UW ChaNGa treat it as a sink particle.
    snapshotBinary.star['tform'] = -1.0
    
    #Set Sink Radius to be mass-weighted average of Roche lobes of two stars
    r1 = AddBinary.calcRocheLobe(binsys.m1/binsys.m2,binsys.a) 
    r2 = AddBinary.calcRocheLobe(binsys.m2/binsys.m1,binsys.a)
    p = strip_units(binsys.m1/(binsys.m1 + binsys.m2))

    r_sink = (r1*p) + (r2*(1.0-p))
    param['dSinkBoundOrbitRadius'] = r_sink
    param['dSinkRadius'] = r_sink
    param['dSinkMassMin'] = 0.9 * strip_units(secMass)
    param['bDoSinks'] = 1
    
    return snapshotBinary, param, director
    
        
Example #50
0
def dOmSqdr(r):
    m = simpson(
        starpot, r, 0, 100
    )  #derivative of omega squared I think? thesis is not entirely clear about this
    return G * (starpot(r) / r**3 - 3 * m / r**4)


#
# How these functions should be used in the end
#
starList = genPartList(10.5, 2000, 1000, expDist, expDistVel)
dmList = genPartList(84.0, 18000, 1000, expDist, expDistVel)
#
#
noahSim = pyn.new(star=len(starList[0]),
                  dm=len(dmList[0]))  #,dm=len(dmList[0]))
#
noahSim['pos'].units = 'kpc'  #maybe there's something off with the units?
noahSim['vel'].units = 'km s^-1'
noahSim['mass'].units = 'Msol'
#
sl2 = np.asarray(
    starList[2]
)  #translating from one file format to another: functions will take np arrays, but not lists
dl2 = np.asarray(starList[2])  #
#
# Setting position, velocity, softening length, mass, and potential for stars
#
noahSim.star['pos'] = starList[0]
noahSim.star['vel'] = starList[1]
noahSim.star['eps'] = .075
Example #51
0
def snapshot_gen(ICobj):
    """
    Generates a tipsy snapshot from the initial conditions object ICobj.
    
    Returns snapshot, param
    
        snapshot: tipsy snapshot
        param: dictionary containing info for a .param file
    Note: Code has been edited (dflemin3) such that now it returns a snapshot for a circumbinary disk
    where initial conditions generated assuming star at origin of mass M.  After gas initialized, replaced
    star at origin with binary system who's center of mass lies at the origin and who's mass m1 +m2 = M
    """

    print 'Generating snapshot...'
    # Constants
    G = SimArray(1.0, 'G')
    # ------------------------------------
    # Load in things from ICobj
    # ------------------------------------
    print 'Accessing data from ICs'
    settings = ICobj.settings

    # snapshot file name
    snapshotName = settings.filenames.snapshotName
    paramName = settings.filenames.paramName

    #Load user supplied snapshot (assumed to be in cwd)
    path = "/astro/store/scratch/tmp/dflemin3/nbodyshare/9au-Q1.05-129K/"
    snapshot = pynbody.load(path + snapshotName)

    # particle positions
    r = snapshot.gas['r']
    xyz = snapshot.gas['pos']

    # Number of particles
    nParticles = len(snapshot.gas)

    # molecular mass
    m = settings.physical.m

    #Pull star mass from user-supplied snapshot
    ICobj.settings.physical.M = snapshot.star[
        'mass']  #Total stellar mass in solar masses
    m_star = ICobj.settings.physical.M

    # disk mass
    m_disk = np.sum(snapshot.gas['mass'])
    m_disk = isaac.match_units(m_disk, m_star)[0]

    # mass of the gas particles
    m_particles = m_disk / float(nParticles)

    # re-scale the particles (allows making of low-mass disk)
    m_particles *= settings.snapshot.mScale

    # -------------------------------------------------
    # Assign output
    # -------------------------------------------------
    print 'Assigning data to snapshot'
    # Get units all set up
    m_unit = m_star.units
    pos_unit = r.units

    if xyz.units != r.units:

        xyz.convert_units(pos_unit)

    # time units are sqrt(L^3/GM)
    t_unit = np.sqrt((pos_unit**3) * np.power((G * m_unit), -1)).units
    # velocity units are L/t
    v_unit = (pos_unit / t_unit).ratio('km s**-1')
    # Make it a unit, save value for future conversion
    v_unit_vel = v_unit
    #Ensure v_unit_vel is the same as what I assume it is.
    assert (np.fabs(AddBinary.VEL_UNIT - v_unit_vel) <
            AddBinary.SMALL), "VEL_UNIT not equal to ChaNGa unit! Why??"

    v_unit = pynbody.units.Unit('{0} km s**-1'.format(v_unit))

    # Other settings
    metals = settings.snapshot.metals
    star_metals = metals

    # Estimate the star's softening length as the closest particle distance
    eps = r.min()

    # Make param file
    param = isaac.make_param(snapshot, snapshotName)
    param['dMeanMolWeight'] = m

    gc.collect()

    # CALCULATE VELOCITY USING calc_velocity.py.  This also estimates the
    # gravitational softening length eps

    preset = settings.changa_run.preset

    # -------------------------------------------------
    # Estimate time step for changa to use
    # -------------------------------------------------
    # Save param file
    isaac.configsave(param, paramName, 'param')
    # Save snapshot
    snapshot.write(filename=snapshotName, fmt=pynbody.tipsy.TipsySnap)
    # est dDelta
    dDelta = ICgen_utils.est_time_step(paramName, preset)
    param['dDelta'] = dDelta

    # -------------------------------------------------
    # Create director file
    # -------------------------------------------------
    # largest radius to plot
    r_director = float(0.9 * r.max())
    # Maximum surface density
    sigma_min = float(ICobj.sigma(r_director))
    # surface density at largest radius
    sigma_max = float(ICobj.sigma.input_dict['sigma'].max())
    # Create director dict
    director = isaac.make_director(sigma_min,
                                   sigma_max,
                                   r_director,
                                   filename=param['achOutName'])
    ## Save .director file
    #isaac.configsave(director, directorName, 'director')
    """
    Now that the gas disk is initializes around the primary (M=m1), add in the
    second star as specified by the user.
    """

    #Now that velocities and everything are all initialized for gas particles, create new snapshot to return in which
    #single star particle is replaced by 2, same units as above
    snapshotBinary = pynbody.new(star=2, gas=nParticles)
    snapshotBinary['eps'] = 0.01 * SimArray(
        np.ones(nParticles + 2, dtype=np.float32), pos_unit)
    snapshotBinary['metals'] = SimArray(
        np.zeros(nParticles + 2, dtype=np.float32))
    snapshotBinary['vel'].units = v_unit
    snapshotBinary['pos'].units = pos_unit
    snapshotBinary['mass'].units = snapshot['mass'].units
    snapshotBinary['rho'] = SimArray(np.zeros(nParticles + 2,
                                              dtype=np.float32))

    #Assign gas particles with calculated/given values from above
    snapshotBinary.gas['pos'] = snapshot.gas['pos']
    snapshotBinary.gas['vel'] = snapshot.gas['vel']
    snapshotBinary.gas['temp'] = snapshot.gas['temp']
    snapshotBinary.gas['rho'] = snapshot.gas['rho']
    snapshotBinary.gas['eps'] = snapshot.gas['eps']
    snapshotBinary.gas['mass'] = snapshot.gas['mass']
    snapshotBinary.gas['metals'] = snapshot.gas['metals']

    #Load Binary system obj to initialize system
    binsys = ICobj.settings.physical.binsys
    m_disk = isaac.strip_units(np.sum(snapshotBinary.gas['mass']))
    binsys.m1 = isaac.strip_units(m_star)
    binsys.m1 = binsys.m1 + m_disk
    #Recompute cartesian coords considering primary as m1+m_disk
    binsys.computeCartesian()

    x1, x2, v1, v2 = binsys.generateICs()

    #Assign position, velocity assuming CCW orbit
    snapshotBinary.star[0]['pos'] = SimArray(x1, pos_unit)
    snapshotBinary.star[0]['vel'] = SimArray(v1, v_unit)
    snapshotBinary.star[1]['pos'] = SimArray(x2, pos_unit)
    snapshotBinary.star[1]['vel'] = SimArray(v2, v_unit)
    """
    We have the binary positions about their center of mass, (0,0,0), so 
    shift the position, velocity of the gas disk to be around the primary.
    """
    snapshotBinary.gas['pos'] += snapshotBinary.star[0]['pos']
    snapshotBinary.gas['vel'] += snapshotBinary.star[0]['vel']

    #Set stellar masses: Create simArray for mass, convert units to simulation mass units
    snapshotBinary.star[0]['mass'] = SimArray(binsys.m1 - m_disk, m_unit)
    snapshotBinary.star[1]['mass'] = SimArray(binsys.m2, m_unit)
    snapshotBinary.star['metals'] = SimArray(star_metals)

    print 'Wrapping up'
    # Now set the star particle's tform to a negative number.  This allows
    # UW ChaNGa treat it as a sink particle.
    snapshotBinary.star['tform'] = -1.0

    #Set sink radius, stellar smoothing length as fraction of distance
    #from primary to inner edge of the disk
    r_sink = eps
    snapshotBinary.star[0]['eps'] = SimArray(r_sink / 2.0, pos_unit)
    snapshotBinary.star[1]['eps'] = SimArray(r_sink / 2.0, pos_unit)
    param['dSinkBoundOrbitRadius'] = r_sink
    param['dSinkRadius'] = r_sink
    param['dSinkMassMin'] = 0.9 * binsys.m2
    param['bDoSinks'] = 1

    return snapshotBinary, param, director
Example #52
0
def test_kd_issue_88():
    # number of particles less than number of smoothing neighbours
    f = pynbody.new(gas=16)
    f['pos'] = np.random.uniform(size=(16, 3))
    with pytest.raises(ValueError):
        f["smooth"]
Example #53
0
 def __init__(self, **kwargs):
     self.__kwargs = kwargs
     self.__profile = kwargs.get('profile', density_profiles.alphabetagamma)
     self.__drhodr = kwargs.get('drhodr',
                                density_profiles.dalphabetagammadr)
     self.__d2rhodr2 = kwargs.get('d2rhodr2',
                                  density_profiles.d2alphabetagammadr2)
     self.__pars = kwargs.get('pars', {
         'alpha': 1.,
         'beta': 3.,
         'gamma': 1.,
         'c': 10.,
         'factor': 0.1
     })
     if self.__profile == density_profiles.alphabetagamma and self.__pars[
             'beta'] <= 3.:
         if 'factor' not in self.__pars.keys(): self.__pars['factor'] = 0.1
     self.__m_vir = kwargs.get('m_vir', '1e12 Msol')
     self.__m_vir = units.Unit(self.__m_vir)
     self.__h = kwargs.get('h', 0.7)
     self.__overden = kwargs.get('overden', 200.)
     self.__r_vir = tools.calc_r_vir(self.__m_vir, self.__h, self.__overden)
     self.__r_s = self.__r_vir / self.__pars['c']
     self.__n_particles = int(kwargs.get('n_particles', 1e5))
     self.__logxmax_rho = np.log10(self.__pars['c']) + 2.
     # Make sure to sample well inside the gravitational softening
     self.__logxmin_rho = self.__logxmax_rho - .5 * np.log10(
         self.__n_particles) - 3.
     self.__logxmin_dist_func = kwargs.get('logxmin_dist_func', -3.)
     self.__logxmax_dist_func = kwargs.get('logxmax_dist_func', 14.)
     self.__n_sample_rho = int(kwargs.get('n_sample_rho', 1e4))
     self.__n_sample_dist_func = int(kwargs.get('n_sample_dist_func', 1e2))
     self.__n_sample_dist_func_rho = int(
         kwargs.get('n_sample_dist_func_rho', 1e4))
     self.__random_seed = kwargs.get('random_seed', 4)
     if 'prng' in kwargs.keys():
         self.__prng = kwargs['prng']
     else:
         self.__prng = np.random.RandomState(self.__random_seed)
     self.__spline_order = kwargs.get('spline_order', 3)
     self.__progress_bar = kwargs.get('progress_bar', False)
     self.__no_bulk_vel = kwargs.get('no_bulk_vel', True)
     self.__x_rho = np.logspace(self.__logxmin_rho, self.__logxmax_rho,
                                self.__n_sample_rho)
     self.__f_bary = kwargs.get('f_bary', 0.1)
     self.__mu = kwargs.get('mu', 1.3)
     self.__spin_parameter = kwargs.get('spin_parameter', 0.04)
     self.__rot_balanced = kwargs.get('rot_balanced', False)
     # Different gas profiles are not yet implemented or successfully tested
     self.__gas_profile = self.__profile
     self.__gas_pars = self.__pars
     #self.__gas_profile = kwargs.get('gas_profile', density_profiles.alphabetagamma)
     #self.__gas_pars = kwargs.get('gas_pars', {'alpha': 1., 'beta': 3., 'gamma': 1.,
     #   'c': 10., 'factor': 0.1})
     self.__r_s_gas = self.__r_vir / self.__gas_pars['c']
     #self.__vel_prof = kwargs.get('vel_prof', None)
     self.__vel_pars = kwargs.get(
         'vel_pars', {
             'rs_v': array.SimArray(1., 'kpc'),
             'c': self.__pars['c'],
             'prefac': 1.,
             'factor': 1.
         })
     self.__n_gas_particles = int(
         kwargs.get('n_gas_particles', self.__n_particles))
     self.__ang_mom_prof = kwargs.get('ang_mom_prof',
                                      am_profiles.bullock_prof)
     self.__ang_mom_pars = kwargs.get('ang_mom_pars', {'mu': self.__mu})
     self.__fname = kwargs.get('fname', 'halo.out')
     # Careful here: as of now, only the output as tipsy files has been successfully tested
     self.__type = {
         'gadget': gadget.GadgetSnap,
         'grafic': grafic.GrafICSnap,
         'nchilada': nchilada.NchiladaSnap,
         'ramses': ramses.RamsesSnap,
         'tipsy': tipsy.TipsySnap
     }[kwargs.get('type', 'tipsy')]
     self.sim = new(dm=self.__n_particles, gas=self.__n_gas_particles)
     self.sim.physical_units()
Example #54
0
def makeICs(simdir='difftest',
            cs=1.,
            boxSize=1.,
            criticalRadius=0.25,
            dustFrac0=0.1,
            tStop=0.1,
            rho=1.,
            nSmooth=32,
            dustFracMin=0.,
            inputSnap=None,
            dDeltaFactor=1,
            boxRes=[50, 58, 60]):
    r"""
    Generates ICs for the dustydiffusion test of Price & Laibe 2015.
    
    The ICs are in a periodic cube, centered on the origin, with uniform 
    density and a dust fraction decaying from the origin.  The dust fraction
    profile is set as:
        
    .. math::
        
        \epsilon(r, 0) = \epsilon_0 (1 - (r/r_c)^2)
        
    ICs will be saved to simdir
    
    Parameters
    ----------
    simdir : str
        Directory to save ICs in
    cs : float
        Sound speed (code units)
    boxSize : float
        Size of the periodic cube (code units)
    criticalRadius : float
        :math:`r_c` in the equation above
    dustFrac0 : float
        :math:`\epsilon_0` in the equation above
    tStop : float
        Dust stopping time (code units)
    rho : float
        total density (code units)
    nSmooth : int
        Number of neighbors for smoothing operations
    dustFracMin : float
        Minimum dust fraction
    inputSnap : SimSnap
        (optional) The positions for the simulation can be taken from another
        simulation if one is supplied.
    dDeltaFactor : float
        Factor by which to scale time step.  This will keep outputs at the 
        same simulation time (ie will scale iOutInterval, etc...).  This can 
        be useful e.g. to test multistepping
    boxRes : array-like
        Resolution of the box (number of grid points) along each axis
        
    Returns
    -------
    ICs : SimSnap
        Generated ICs
    param : dict
        params used
    simdir : str
        Directory the ICs are saved in
    paramname : str
        Path to the saved .param file
        
    """
    runParams = locals()
    # -----------------------------------------------
    # Load stuff
    # -----------------------------------------------
    if inputSnap is not None:
        # Load inputSnap file
        if isinstance(inputSnap, str):
            inputSnap = pynbody.load(inputSnap)
        else:
            inputSnap = inputSnap
        ngas = len(inputSnap)
    else:
        # Create grid ICs
        boxRes = np.asarray(boxRes).astype(int)
        ngas = np.product(boxRes)
    # Parse param file
    param = testdust.utils.loadDefaultParam(defaultParam, userDefaults)
    # Get units
    units = diskpy.pychanga.units_from_param(param)
    grainSize = param['dDustSize']
    # filenames
    fname = param['achInFile']
    outparam = param['achOutName'] + '.param'
    molecularWeight = param['dMeanMolWeight']

    # -----------------------------------------------
    # set up simulation directory
    # -----------------------------------------------
    if not os.path.exists(simdir):

        os.mkdir(simdir)

    fRunParams = os.path.join(simdir, runParamsName)
    fname = os.path.join(simdir, fname)

    # -----------------------------------------------

    snap = pynbody.new(gas=ngas)

    # Give everything units
    cs = SimArray(cs, units['v_unit'])
    rho = SimArray(rho, units['rho_unit'])
    boxSize = SimArray(boxSize, units['l_unit'])
    criticalRadius = SimArray(criticalRadius, units['l_unit'])
    tStop = SimArray(tStop, units['t_unit'])
    molecularWeight = SimArray(molecularWeight, 'm_p')
    grainSize = SimArray(grainSize, units['l_unit'])
    # Save/update run parameters
    runParams['criticalRadius'] = criticalRadius
    runParams['cs'] = cs
    runParams['tStop'] = tStop
    pickle.dump(runParams, open(fRunParams, 'w'))
    print "Run parameters saved to:", fRunParams

    # Isothermal temperature
    T = (cs**2) * molecularWeight / kB
    T.convert_units('K')
    snap['temp'] = T * np.ones(ngas)

    # Mass
    m = (rho * boxSize**3) / ngas
    m.convert_units(units['m_unit'])
    snap['mass'] = m

    # Grain density
    grainDensity = rho * cs * tStop * np.sqrt(8 / np.pi) / grainSize
    grainDensity.convert_units(units['rho_unit'])
    param['dDustGrainDensity'] = float(grainDensity)

    # Setup positions
    if inputSnap is not None:
        pos = inputSnap['pos'].view(float, np.ndarray)
        snap['pos'] = boxSize * pos
        Lfloat = float(boxSize)
        param['dPeriod'] = Lfloat
    else:
        boxShape = boxSize * np.ones(3)
        pos = periodicGrid(boxRes, boxShape)
        snap['pos'] = pos
        Lfloat = float(boxSize)
        param['dPeriod'] = Lfloat

    # Define dust fraction
    snap['dustFrac'] = dustFrac0 * (1 - (snap['r'] / criticalRadius)**2)
    snap['dustFrac'][snap['dustFrac'] < dustFracMin] = dustFracMin

    # Estimate a useable softening length.  Make it big so that it does not
    # constrain the timestepping.  Gravitational forces should be off, so this
    # is okay
    snap['rho']
    snap['eps'] = 100 * snap['smooth'].mean()

    # Save out
    snap.write(fmt=pynbody.tipsy.TipsySnap, filename=fname)
    # Set up the param file
    param['nSmooth'] = nSmooth
    scaleTimeStep(param, dDeltaFactor)
    outparamfull = os.path.join(simdir, outparam)
    diskpy.utils.configsave(param, outparamfull, 'param')

    print 'ICs saved to ' + fname
    return snap, param, simdir, outparam
Example #55
0
def load_gadget(infile, plot_thing, centredens=False):
    f = h5py.File(infile, "r")

    header = f["/Header"]
    time = header.attrs.get("Time")
    time *= 0.9778e9  # to yr
    time /= 1.e6  # to Myr

    xyz = np.array(f["/PartType0/Coordinates"])  # kpc
    n = xyz.shape[0]
    data = pynbody.new(gas=n)
    data["xyz"] = xyz

    try:
        BH_data = f["/BH_binary"]
        Binary_pos_1 = BH_data.attrs.get("Binary_pos_1")
        Binary_pos_2 = BH_data.attrs.get("Binary_pos_2")
        if isinstance(Binary_pos_1, np.ndarray) & isinstance(
                Binary_pos_2, np.ndarray):
            data.binary_positions = [Binary_pos_1 * 1.e3, Binary_pos_2 * 1.e3]
        else:
            data.binary_positions = None
    #         verboseprint("Binary BH data loaded")
    except KeyError as e:
        data.binary_positions = None
    #         verboseprint("No Binary BH data found, skipping")

    data["m_p"] = np.array(f["/PartType0/Masses"])  # 10^10 msun
    data["m_p"] *= 1e+10  # 10^10 solar masses to solar masses
    data["h_p"] = np.array(f["/PartType0/SmoothingLength"])  # kpc

    need_to_load = set(plot_thing)
    if centredens:
        need_to_load.add("nH")
    need_to_load = preqs_config.process_preqs(need_to_load)

    if "id" in need_to_load:
        data["id_p"] = np.array(f["/PartType0/ParticleIDs"]).astype(int)

    if "age" in need_to_load:
        infile_split = infile.split("/")
        run_id = infile_split[-3]
        run_name = infile_split[-2]
        run_snapfile = infile_split[-1]
        run_isnap = int(run_snapfile[-8:-5])
        age_file = "../../data/age_{}_{}_{}.dat".format(
            run_id, run_name, run_isnap)
        data["age"] = time - np.loadtxt(age_file)

    if "pres" in need_to_load:
        data["pres"] = np.array(f["/PartType0/Pressure"])
    #         data.pres*=1.989e+33 # from internal units to dyne/cm*8*2

    if "arads" in need_to_load:
        data["arads"] = np.array(f["/PartType0/RadiativeAcceleration"])
        data["arads"] *= 3.24086617e-12  # to cm/s/s

    if "arad" in need_to_load:
        data["arad"] = np.sqrt(np.sum(data["arads"]**2, axis=1))

    if "accel" in need_to_load:
        data["accels"] = np.array(f["/PartType0/Acceleration"])
        data["accels"] *= 3.24086617e-12  # to cm/s/s
        data["accel"] = np.sqrt(np.sum(data["accels"]**2, axis=1))

    if "depth" in need_to_load:
        data["depth"] = np.array(
            f["/PartType0/AGNOpticalDepth"])  # Msun/kpc**2

    if "list" in need_to_load:
        data["list"] = np.arange(n)

    if "rand" in need_to_load:
        data["rand"] = np.random.random(n)

    if "nneigh" in need_to_load:
        data["nneigh"] = np.array(f["/PartType0/TrueNumberOfNeighbours"])

    if "temp" in need_to_load:
        data["u_p"] = np.array(f["/PartType0/InternalEnergy"])  # 1e10 erg/g
        data["u_p"] *= 1.e10  # to erg/g

        data["TK_p"] = (gamma_minus_one / boltzmann_cgs *
                        (molecular_mass * proton_mass_cgs) * data["u_p"])

    if "vels" in need_to_load:
        data["vels"] = np.array(f["/PartType0/Velocities"])  # in km/s

    # doesn't work well
    if "dt" in need_to_load:
        data["dt_p"] = np.array(f["/PartType0/TimeStep"])
        data["dt_p"] *= 0.9778e9  # to yr

    # doesn't work well
    if "heat" in need_to_load:
        data["heat"] = np.array(f["/PartType0/AGNHeat"])
        data["heat"] *= 1e10 / 3.08568e+16  # to erg/s/g

    if "nH" in need_to_load:
        data["rho_p"] = np.array(f["/PartType0/Density"])
        data["rho_p"] *= 6.77e-22  # to g/cm**3
        data["nH_p"] = data["rho_p"] / (molecular_mass * proton_mass_cgs)

    if "tau" in need_to_load:
        data["tau"] = np.array(f["/PartType0/AGNDepth"])
    if "tau_2" in need_to_load:
        data["tau_2"] = np.array(f["/PartType0/AGNDepth_2"])
    if "tau_eff" in need_to_load:
        data["tau_eff"] = np.array(f["/PartType0/AGNDepth_Effective"])

    if "AGNI" in need_to_load:
        data["AGNI"] = np.array(f["/PartType0/AGNIntensity"])
        data["AGNI"] *= (
            1.989e53 / (0.9778e9 * 3.154e7) / 3.086e21**2
        )  # convert from internal units (energy/Gyr-ish/kpc**2) to erg/s/cm**2

    if "AGNI2" in need_to_load:
        data["AGNI2"] = np.array(f["/PartType0/AGNIntensity_2"])
        data["AGNI2"] *= (
            1.989e53 / (0.9778e9 * 3.154e7) / 3.086e21**2
        )  # convert from internal units (energy/Gyr-ish/kpc**2) to erg/s/cm**2

    if "AGNIeff" in need_to_load:
        data["AGNIeff"] = np.array(f["/PartType0/AGNIntensity_Effective"])
        data["AGNIeff"] *= (
            1.989e53 / (0.9778e9 * 3.154e7) / 3.086e21**2
        )  # convert from internal units (energy/Gyr-ish/kpc**2) to erg/s/cm**2

    if "table" in need_to_load:
        verboseprint("Load dust tables")

        #         table_date="060319" # used in paper - not all intensities are there
        table_date = "130720"
        # table_res = "0.1"
        table_res = "0.0001"

        coolheat_dir = os.path.join(this_dir, "../coolheat_tab/")
        cloudy_table = gizmo_tools.cloudy_table(table_date, table_res,
                                                coolheat_dir)
        data["flux_p"] = np.array(
            f["/PartType0/AGNIntensity"])  # energy per surface area per time
        data["flux_p"] *= 1.989e+53 / 3.086e21**2 / 3.08568e+16

        table_particles = pd.DataFrame()
        table_particles["nH"] = data["nH_p"]
        table_particles["temp"] = data["TK_p"]
        table_particles["AGNIntensity"] = data["flux_p"]
        table_particles["AGNDepth"] = data["tau"]
        # TODO: correct optical depths etc for binary
        #         if "tau_eff" in data:
        #             table_particles["AGNDepth"] = data["tau_eff"]
        #         else:
        #             table_particles["AGNDepth"] = data["tau"]

        verboseprint("Calculating dust/cooling/heating properties from table")
        cloudy_table.interp(table_particles)

    if "col" in need_to_load:
        if "/PartType0/AGNColDens" in f:
            data["coldens"] = np.array(
                f["/PartType0/AGNColDens"])  # Msun/kpc**2
            data["coldens"] *= (1.989e+43 / 3.086e+21**2)  # to g/cm**2
            data["coldens"] /= (molecular_mass * proton_mass_cgs
                                )  # N in cm**(-2)
        else:
            data["coldens"] = table_particles["column_out"]

    if "tdust" in need_to_load:
        data["dustTemp"] = table_particles["dustT"]

    for line in lines[1:]:
        if line in need_to_load:
            data[line] = table_particles["line_" + line]
            if line in [
                    "12mic", "8mic", "850mic"
            ]:  # these are given in erg/cm**3/s, need to convert to erg/g/s
                data[line] /= data["nH_p"]
        if line + "m" in need_to_load:
            data[line + "m"] = table_particles[
                "line_" + line] * data["m_p"] * 1.9891e33 / 9.52140614e36 / (
                    4. * np.pi
                )  # erg/s/g to erg/s, extra factor for pc**2 to ster cm**2, output is erg/s/cm**2/ster

    if "dg" in need_to_load:
        data["dg"] = table_particles["dg"]

    if "dust" in need_to_load:
        data["dust"] = data["dg"] * data["m_p"]

    if "emit" in need_to_load:
        data["emissivity"] = 5.67e-5 * data["dustTemp"]**4. * data[
            "dg"] / np.nanmax(data["dg"])  # erg/s/cm^2

    if "opac" in need_to_load:
        data["opac"] = np.array(f["/PartType0/AGNOpacity"]
                                )  # internal units: kpc**2/1e10 solar mass
        data["opac"] *= 0.478679108  # to cm**2/g

    if ("view" in need_to_load or "vlos" in need_to_load
            or any(x in need_to_load
                   for x in ["view" + line for line in lines])
            or "dusttau" in need_to_load):
        if "view" in need_to_load:
            data["brightness"] = 5.67e-5 * data["dustTemp"]**4. * data[
                "dg"] / np.nanmax(data["dg"])  # erg/s/cm^2

        verboseprint("faking opacity")
        opacity = 65.2  # cm^2/g, somewhat arbitrary
        verboseprint("Broad IR opacity is now ", opacity, " cm^2/g")

        opacity *= 0.000208908219  # convert to pc**2/solar mass for consistency
        data["opac"] = np.full(n, opacity)
        data["opac"] *= data["dg"] / np.nanmax(
            data["dg"])  # take into account dust fraction

        if "dusttau" in need_to_load:
            data["dusttau"] = data["opac"] * data["m_p"]
        for line in lines[1:]:
            if not "view" + line in need_to_load:
                continue
            data[line + "opac"] = np.full(n, line_opacities[line])
            data[line + "brightness"] = data[line + "m"] / data[
                line +
                "opac"]  # erg/s/cm^2 - multiply by opacity to get actual emission
        #             data.__dict__[line+"brightness"]=data.__dict__[line+"m"] # erg/s, gets SPH smoothed to get erg/s/cm**2

        if "view" in need_to_load:
            # sputtered = (data.dustTemp>2.5e3) # or something, super arbitrary
            sputtered = (data["dustTemp"] > 1.e5
                         )  # or something, super arbitrary
            data["brightness"][sputtered] = 0.
            data["opac"][sputtered] = 0.
    if any(x in need_to_load for x in ("IRdustm", "IRdust", "IRdustopac",
                                       "IRdustbrightness", "viewIRdust")):
        #         data["dustTemp"] = table_particles["dustT"]
        data["IRdustbrightness"] = 5.67e-5 * data["dustTemp"]**4. * data[
            "dg"] / np.nanmax(data["dg"])
        data["IRdustopac"] = np.full(n, line_opacities["IRdust"])
        data["IRdustm"] = data["IRdustbrightness"] * data["IRdustopac"]
        data["IRdust"] = data["IRdustm"] / (data["m_p"] * 1.9891e33 /
                                            9.52140614e36 / (4. * np.pi))

    if "rad0" in need_to_load:
        data["rad0"] = np.load("rad0.npy")
        data["rad0"] = data["rad0"][data["id_p"] - 1]

    return time, data
Example #56
0
def make_binary(IC, snapshot):
    """
    Turns a snapshot for a single star into a snapshot of a binary system
    
    Parameters
    ----------
    IC : IC object
    snapshot : SimSnap
        Single star system to turn into a binary
    
    Returns
    -------
    snapshotBinary : SimSnap
        A binary version of the simulation snapshot
    """
    # Initialize snapshot
    snapshotBinary = pynbody.new(star=2, gas=len(snapshot.g))
    # Copy gas particles over
    for key in snapshot.gas.keys():
        
        snapshotBinary.gas[key] = snapshot.gas[key]
        
    # Load Binary system obj to initialize system
    starMode = IC.settings.physical.starMode.lower()
    binsys = IC.settings.physical.binsys
    
    if starMode == 'stype':
        
        # Treate the primary as a star of mass mStar + mDisk
        m_disk = strip_units(np.sum(snapshotBinary.gas['mass']))
        binsys.m1 += m_disk
        binsys.computeCartesian()
        
    x1,x2,v1,v2 = binsys.generateICs()
    
    #Assign star parameters assuming CCW orbit
    snapshotBinary.star[0]['pos'] = x1
    snapshotBinary.star[0]['vel'] = v1
    snapshotBinary.star[1]['pos'] = x2
    snapshotBinary.star[1]['vel'] = v2
    
    #Set stellar masses
    priMass = binsys.m1
    secMass = binsys.m2    
    snapshotBinary.star[0]['mass'] = priMass
    snapshotBinary.star[1]['mass'] = secMass    
    snapshotBinary.star['metals'] = snapshot.s['metals']
    
    if starMode == 'stype':
        # We have the binary positions about their center of mass, (0,0,0), so 
        # shift the position, velocity of the gas disk to be around the primary.
        snapshotBinary.gas['pos'] += snapshotBinary.star[0]['pos']
        snapshotBinary.gas['vel'] += snapshotBinary.star[0]['vel']  
        # Remove disk mass from the effective star mass
        snapshotBinary[0]['mass'] -= m_disk
        binsys.m1 -= m_disk
        # Star smoothing
        snapshotBinary.star['eps'] = snapshot.star['eps']

        
    elif starMode == 'binary':
        
        # Estimate stars' softening length as fraction of distance to COM
        d = np.sqrt(AddBinary.dotProduct(x1-x2,x1-x2))
        pos_unit = snapshotBinary['pos'].units
        snapshotBinary.star['eps'] = SimArray(abs(d)/4.0,pos_unit)
        
    return snapshotBinary
Example #57
0
def test_kd_issue_88():
    # number of particles less than number of smoothing neighbours
    f = pynbody.new(gas=16)
    f['pos'] = np.random.uniform(size=(16, 3))
    trigger_fn = lambda: f['smooth']
    nose.tools.assert_raises(ValueError, trigger_fn)
Example #58
0
    def combine(self):
        """
        Combines the two galaxies into a new TipsySnap.

        Returns
        ----------
        """
        # these x y z refer to initial condit to be added
        print("Getting initial conditions")
        x1, y1, vx1, vy1 = self._initial_conds(which_gal=self.Gal1)
        x2, y2, vx2, vy2 = self._initial_conds(which_gal=self.Gal2)

        # Mass ratio is unitless so it doesn't matter that they are in kg
        # Units specified and value taken only because later we use in_units
        # Only using simulation units to avoid namespace clutter
        x1 = (x1).to(self.dKpcUnit).value * (self.Mass1_scaled / self.m_tot_scaled)
        y1 = (y1).to(self.dKpcUnit).value * (self.Mass1_scaled / self.m_tot_scaled)
        x2 = (x2).to(self.dKpcUnit).value * (self.Mass2_scaled / self.m_tot_scaled)
        y2 = (y2).to(self.dKpcUnit).value * (self.Mass2_scaled / self.m_tot_scaled)

        vx1 = (vx1).to(self.velUnit).value * (self.Mass1_scaled / self.m_tot_scaled)
        vy1 = (vy1).to(self.velUnit).value * (self.Mass1_scaled / self.m_tot_scaled)
        vx2 = (vx2).to(self.velUnit).value * (self.Mass2_scaled / self.m_tot_scaled)
        vy2 = (vy2).to(self.velUnit).value * (self.Mass2_scaled / self.m_tot_scaled)
        print("Done")
        print("")

        lengths = {}
        for fam in self.Gal1.families():
            lengths[fam.name] = len(self.Gal1[fam])

        gal1_shifted = pynbody.new(**lengths)

        def transform(row, rmat):
            row = (rmat * np.matrix(row).transpose())
            return(row)

        for fam in self.Gal1.families():
            s1 = self.Gal1[fam]
            if self.transform is True:
                print("Tranforming " + str(fam))
                s1["pos"] = np.apply_along_axis(transform, 1, s1["pos"],
                                                (self._rmat(a=self.W1,
                                                            b=self.i1,
                                                            g=self.w1)))

                s1["vel"] = np.apply_along_axis(transform, 1, s1["vel"],
                                                (self._rmat(a=self.W1,
                                                            b=self.i1,
                                                            g=self.w1)))
                print("Done")
                print("")

            else:
                pass

            print("Shifting family " + str(fam))
            # in_units here IS needed to ensure units match when added to IC
            gal1_shifted[fam][:len(s1)]["pos"] = s1["pos"].in_units(str(self.dKpcUnit.value) + " kpc") + [x1, y1, 0]
            gal1_shifted[fam][:len(s1)]["vel"] = s1["vel"].in_units(str(self.velUnit.value) + " km s**-1") * np.sqrt(self.massScale) + [vx1, vy1, 0]
            gal1_shifted[fam][:len(s1)]["mass"] = s1["mass"].in_units(str(self.dMsolUnit.value) + " Msol") * self.massScale
            gal1_shifted[fam][:len(s1)]["rho"] = s1["rho"].in_units(str((self.dMsolUnit / (self.dKpcUnit**3)).value) + " Msol kpc**-3") * self.massScale
            gal1_shifted[fam][:len(s1)]["eps"] = s1["eps"].in_units("kpc")

            if str(fam) == 'gas':
                gal1_shifted[fam][:len(s1)]["temp"] = s1["temp"] * self.massScale
            else:
                pass

            print("Done")
            print("")

        lengths = {}
        for fam in self.Gal2.families():
            lengths[fam.name] = len(self.Gal2[fam])

        gal2_shifted = pynbody.new(**lengths)

        for fam in self.Gal2.families():
            s2 = self.Gal2[fam]
            if self.transform is True:
                print("Tranforming " + str(fam))
                s2["pos"] = np.apply_along_axis(transform, 1, s2["pos"],
                                                (self._rmat(a=self.W2,
                                                            b=self.i2,
                                                            g=self.w2)))

                s2["vel"] = np.apply_along_axis(transform, 1, s2["vel"],
                                                (self._rmat(a=self.W2,
                                                            b=self.i2,
                                                            g=self.w2)))
                print("Done")
                print("")
            else:
                pass

            print("Shifting family " + str(fam))

            gal2_shifted[fam][:len(s2)]["pos"] = s2["pos"].in_units(str(self.dKpcUnit.value) + " kpc") + [x2, y2, 0]
            gal2_shifted[fam][:len(s2)]["vel"] = s2["vel"].in_units(str(self.velUnit.value) + " km s**-1") * np.sqrt(self.massScale) + [vx2, vy2, 0]
            gal2_shifted[fam][:len(s2)]["mass"] = s2["mass"].in_units(str(self.dMsolUnit.value) + " Msol") * self.massScale
            gal2_shifted[fam][:len(s2)]["rho"] = s2["rho"].in_units(str((self.dMsolUnit / (self.dKpcUnit**3)).value) + " Msol kpc**-3") * self.massScale
            gal2_shifted[fam][:len(s2)]["eps"] = s2["eps"].in_units("kpc")

            if str(fam) == 'g':
                gal2_shifted[fam][:len(s2)]["temp"] = s2["temp"] * self.massScale
            else:
                pass

            print("Done")
            print("")

        print("Combining galaxies")
        for fam in gal1_shifted.families():
            lengths[fam.name] = len(gal1_shifted[fam]) + len(gal2_shifted[fam])

        combined = pynbody.new(**lengths)

        for fam in self.Gal1.families():
            s1 = gal1_shifted[fam]
            s2 = gal2_shifted[fam]
            for arname in "pos", "vel", "mass", "rho", "eps":
                combined[fam][:len(s1)][arname] = s1[arname]
                combined[fam][len(s1):][arname] = s2[arname]
            if str(fam) == "gas":
                # temp starts out uniform
                combined[fam][:len(s1)]["temp"] = s1["temp"][:]
                combined[fam][len(s1):]["temp"] = s1["temp"][:]
                print(combined[fam]["temp"])
            else:
                pass

        print("Done")
        print("")

        return combined
Example #59
0
def shock1d(nParticles=2 * 569,
            L=2.,
            P=(1, 1. / 8),
            rhog=(1, 1. / 8),
            dustFrac=0.5,
            gamma=5. / 3,
            inputParamName=None):
    """
    Creates SPH ICs for a 1D dusty-shock tube a la Price & Laibe 2015
    (see their dustyshock, section 4.2).
    
    Particles are in a line along the z-axis.  Note that since ChaNGa uses 
    periodic boundaries (rather than particles in a tube) the shock tube
    should be twice as long and will actually produce 2 shocks.
    
    Parameters
    ----------
    nParticles: int
        Approximate number of particles to use.  nParticles will be set in the
        end to best approximate the gas density in each region.
    L: float
        Length of the shock tube. (in code units)
    P: array-like
        Pressure in the two regions (left and right)
    rhog: array-like
        Gas density in the two regions
    dustFrac: float
        Dust fraction (between 0 and 1)
    gamma: float
        Adiabatic index
    inputParamName: str
        (optional) Override the default ChaNGa params.  This can also be
        done by changing the appropriate user default param in this directory.
    
    Returns
    -------
    ICs: SimSnap
        Pynbody snapshot of the ICs
    param: dict
        dict of the runtime params
    arguments: dict
        Arguments used when calling this function, including defaults.
    paramsavename: str
        Path the param file is saved to
    """
    # Keep track of arguments (and save at the end)
    arguments = locals()

    P = np.asarray(P)
    rhog = np.asarray(P)
    L = float(L)
    gamma = float(gamma)

    # --------------------------------------------
    # Initialize
    # --------------------------------------------
    # Load stuff
    if inputParamName is not None:
        param = diskpy.utils.configparser(inputParamName)
    else:
        param = testdust.utils.loadDefaultParam(defaultParam1d, userDefault1d)
#    param = diskpy.utils.configparser(inputParamName, 'param')
    fprefix = param['achOutName']
    savename = param['achInFile']
    molecularWeight = SimArray(param['dMeanMolWeight'], 'm_p')
    units = diskpy.pychanga.units_from_param(param)
    # Initialize quantities
    L = SimArray(L, units['l_unit'])
    P = SimArray(P, units['pres_unit'])
    rhog = SimArray(rhog, units['rho_unit'])
    rho = rhog / (1. - dustFrac)
    # Set-up number of particles to left/right of boundary
    N = np.array(np.round(nParticles * rho / rho.sum()).astype(int))
    nParticles = N.sum()
    # Initialize snapshot
    f = pynbody.new(gas=nParticles)
    # Initialize arrays
    for key in ('temp', 'rho', 'dustFrac'):
        f[key] = 0.
    # Set up left/right slices.  These select the left/right regions
    slices = [slice(0, N[0]), slice(N[0], N[0] + N[1])]

    # --------------------------------------------
    # Setup values
    # --------------------------------------------
    # Mass
    totMass = float((rho * (L / 2.)).sum())
    f['mass'] = totMass / nParticles
    # Position
    z = [0.5 * L * testdust.utils.periodicLine(n) for n in N]
    f['z'][slices[0]] = z[0] - 0.25 * L
    f['z'][slices[1]] = z[1] + 0.25 * L

    # Temperature
    T = molecularWeight * P / (rhog * kB)
    T.convert_units('K')

    # Assign arrays, looping over both sides
    for i, s in enumerate(slices):
        f['temp'][s] = T[i]
        f['rho'][s] = rho[i]
        f['dustFrac'][s] = dustFrac

    # Other
    f['eps'] = 10 * L / nParticles

    # Setup params
    testdust.utils.setupParamBounds(param, [float(L)])
    param['dConstGamma'] = gamma

    # Save
    f.write(filename=savename, fmt=pynbody.tipsy.TipsySnap)
    print 'snapshot saved to:', savename
    paramsavename = fprefix + '.param'
    diskpy.utils.configsave(param, paramsavename)
    print '.param file saved to:', paramsavename

    pickle.dump(arguments, open(argsavename, 'w'), 2)
    print 'arguments dict pickled to:', argsavename

    return f, param, arguments, paramsavename
Example #60
0
    v[nanind] = 0.0
    print 'Setting {0} particle velocities to 0 (to avoid nans)'.format(
        nanind.sum())
    # -------------------------------------------------
    # Assign output
    # -------------------------------------------------
    vel = SimArray(np.zeros([nParticles, 3]), '2.98e+01 km s**-1')
    vel[:, 0] = -np.sin(pos['theta']) * v
    vel[:, 1] = np.cos(pos['theta']) * v
    # Generate positions
    xyz = SimArray(np.zeros([nParticles, 3]), 'au')
    xyz[:, 0] = pos['x']
    xyz[:, 1] = pos['y']
    xyz[:, 2] = pos['z']
    # Generate snapshot
    snapshot = pynbody.new(star=1, gas=nParticles)
    snapshot.gas['vel'] = vel
    snapshot.gas['pos'] = xyz
    snapshot.gas['temp'] = T
    snapshot.gas['mass'] = mGas
    snapshot.gas['metals'] = metals
    snapshot.gas['eps'] = eps

    snapshot.star['pos'] = SimArray([[0., 0., 0.]], 'au')
    snapshot.star['vel'] = SimArray([[0., 0., 0.]], '2.98e+01 km s**-1')
    snapshot.star['mass'] = mStar
    snapshot.star['metals'] = SimArray([1.])
    snapshot.star['eps'] = SimArray([0.01], 'au')
    # -------------------------------------------------
    # Save Output
    # -------------------------------------------------