Ejemplo n.º 1
0
def enzo_m_gen(fname, field_add):

    reg, ds1 = enzo_grid_generate(fname, field_add)

    amr = AMRGrid.from_yt(
        ds1, quantity_mapping={'density': ('gas', 'dust_density')})
    '''
    levels = ds.index.max_level
    
    amr = AMRGrid()
    for ilevel in range(levels):
        level = amr.add_level()
        
    for igrid in ds.index.select_grids(ilevel):
        print igrid
        grid = level.add_grid()
        grid.xmin,grid.xmax = igrid.LeftEdge[0].in_units('cm'),igrid.RightEdge[0].in_units('cm')
        grid.ymin,grid.ymax = igrid.LeftEdge[1].in_units('cm'),igrid.RightEdge[1].in_units('cm')
        grid.zmin,grid.zmax = igrid.LeftEdge[2].in_units('cm'),igrid.RightEdge[2].in_units('cm')
        grid.quantities["density"] = np.transpose(np.array(igrid[("gas","metal_density")].in_units('g/cm**3')*cfg.par.dusttometals_ratio))
        grid.nx,grid.ny,grid.nz = igrid[("gas","metal_density")].shape
    '''

    m = Model()

    m.set_amr_grid(amr)

    #CMB DISABLED -- UNCOMMENT THIS TO FIX THIS.  The main issue is
    #that I'm not sure what shape to give to the np.repeat
    #array of energy_density_absorbed; I think it needs to be the ARM Grid shape but i'm not quite sure if it needs to be an AMRGrid()
    #energy_density_absorbed=energy_density_absorbed_by_CMB()
    #energy_density_absorbed =np.repeat(energy_density_absorbed.value,reg.index.num_grids)#amr['density'].shape)

    d = SphericalDust(cfg.par.dustdir + cfg.par.dustfile)
    if cfg.par.SUBLIMATION == True:
        d.set_sublimation_temperature(
            'fast', temperature=cfg.par.SUBLIMATION_TEMPERATURE)

    m.add_density_grid(amr["density"], d)
    #uncomment when we're ready to put CMB in (and comment out previous line)
    #m.add_density_grid(amr['density'],d,specific_energy=energy_density_absorbed)
    #m.set_specific_energy_type('additional')

    center = ds1.arr([cfg.model.x_cent, cfg.model.y_cent, cfg.model.z_cent],
                     'code_length')
    [xcent, ycent, zcent
     ] = center.in_units('cm')  #boost needs to be in cm since that's what the

    boost = np.array([xcent, ycent, zcent])

    dx = ds1.domain_width[0].in_units('cm')
    dy = ds1.domain_width[1].in_units('cm')
    dz = ds1.domain_width[2].in_units('cm')

    return m, xcent, ycent, zcent, dx, dy, dz, reg, ds1, boost
Ejemplo n.º 2
0
def enzo_m_gen(fname, field_add):

    reg, ds1 = enzo_grid_generate(fname, field_add)

    amr = yt_dataset_to_amr_grid_xyz(
        ds1, quantity_mapping={'density': ('gas', 'dust_density')})

    m = Model()

    #save in the m__dict__ that we're in an amr geometry
    m.__dict__['grid_type'] = 'amr'

    m.set_amr_grid(amr)

    #CMB DISABLED -- UNCOMMENT THIS TO FIX THIS.  The main issue is
    #that I'm not sure what shape to give to the np.repeat
    #array of energy_density_absorbed; I think it needs to be the ARM Grid shape but i'm not quite sure if it needs to be an AMRGrid()
    #energy_density_absorbed=energy_density_absorbed_by_CMB()
    #energy_density_absorbed =np.repeat(energy_density_absorbed.value,reg.index.num_grids)#amr['density'].shape)

    d = SphericalDust(cfg.par.dustdir + cfg.par.dustfile)
    if cfg.par.SUBLIMATION == True:
        d.set_sublimation_temperature(
            'fast', temperature=cfg.par.SUBLIMATION_TEMPERATURE)

    m.add_density_grid(amr["density"], d)
    #uncomment when we're ready to put CMB in (and comment out previous line)
    #m.add_density_grid(amr['density'],d,specific_energy=energy_density_absorbed)
    #m.set_specific_energy_type('additional')

    center = ds1.arr([cfg.model.x_cent, cfg.model.y_cent, cfg.model.z_cent],
                     'code_length')
    [xcent, ycent, zcent
     ] = center.in_units('cm')  #boost needs to be in cm since that's what the

    boost = np.array([xcent, ycent, zcent])

    dx = ds1.domain_width[0].in_units('cm')
    dy = ds1.domain_width[1].in_units('cm')
    dz = ds1.domain_width[2].in_units('cm')

    return m, xcent, ycent, zcent, dx, dy, dz, reg, ds1, boost
Ejemplo n.º 3
0
def active_dust_add(ds,m,grid_of_sizes,nsizes,dustdens,specific_energy,refined=[False]):
        #first, save the grid_of_sizes to the ds.paramteters so we can carry it around
        ds.parameters['reg_grid_of_sizes'] = grid_of_sizes #named 'reg_grid_of_sizes' 


        #for empty cells, use the median size distribution
        for isize in range(nsizes):
                wzero = np.where(grid_of_sizes[:,isize] == 0)[0]
                wnonzero = np.where(grid_of_sizes[:,isize] != 0)[0]
                
                grid_of_sizes[wzero,isize] = np.median(grid_of_sizes[wnonzero,isize])
                
                print(len(wzero)/len(wnonzero))



        #now load the mapping between grain bin and filename for the lookup table
        data = np.load(cfg.par.pd_source_dir+'active_dust/dust_files/binned_dust_sizes.npz')
        grain_size_left_edge_array = data['grain_size_left_edge_array']
        grain_size_right_edge_array  = data['grain_size_right_edge_array']
        dust_filenames = data['outfile_filenames']

        nbins = len(grain_size_left_edge_array)




        #find which sizes in the hydro simulation correspond to the
        #pre-binned extinction law sizes from dust_file_writer.py

        dust_file_to_grain_size_mapping_idx = []
        x=np.linspace(cfg.par.otf_extinction_log_min_size,cfg.par.otf_extinction_log_max_size,nsizes)
        for i in range(nbins):
                dust_file_to_grain_size_mapping_idx.append(find_nearest(x,grain_size_left_edge_array[i]))


        #set up the frac array that is nbins big.  this is the
        #fractional contribution of each dust file bin which is based
        #on the total number of grains in the grid in that bin.

        #frac =np.zeros([dustdens.shape[0],nbins])

        dsf_grid = np.zeros([dustdens.shape[0],nbins])
        frac_grid = np.zeros([dustdens.shape[0],nbins])
        debug_nearest_extinction_curve = np.zeros([nbins])

        if cfg.par.OTF_EXTINCTION_MRN_FORCE == True:
                grid_sum = np.zeros(nbins)

                #how DNSF was set up.  not needed other than for testing
                x=np.linspace(-4,0,41)
                #load an example dust size function for testing against
                dsf = np.loadtxt(cfg.par.pd_source_dir+'active_dust/mrn_dn.txt')#DNSF_example.txt')

                #nbins = len(grain_size_left_edge_array)


                for i in range(nbins):
                        #find the index bounds in x that we want to interpolate between
                        idx0 = find_nearest(x,grain_size_left_edge_array[i])
                        if x[idx0] > grain_size_left_edge_array[i]: idx0 -= 1
                        idx1 = idx0+1
                
                        dsf_interp = np.interp(grain_size_left_edge_array[i],[x[idx0],x[idx1]],[dsf[idx0],dsf[idx1]])
                
                        #this sets the fraction of each bin size we need (for the
                        #entire grid!)
                        dsf_grid[:,i] = dsf_interp
                        grid_sum[i] = np.sum(dsf_grid[:,i])
                        debug_nearest_extinction_curve[i] = dsf_interp


                #set up the frac array that is nbins big.  this is the
                #fractional contribution of each dust file bin which is based
                #on the total number of grains in the grid in that bin.
                frac = grid_sum/np.sum(grid_sum)

                #now we need to set the localized extinction law. we do
                #this by comparing, fractionally, a given cell's number of
                #grains in that bin to the maximum number of grains that
                #the grid has in that bin.
                
                for i in range(nbins):
                        frac_grid[:,i] = dsf_grid[:,i]/np.max(dsf_grid[:,i])*frac[i]
            
                '''
                import matplotlib.pyplot as plt
                fig = plt.figure()
                ax = fig.add_subplot(111)
                ax.plot(x,dsf,label='dsf')
                ax.plot(grain_size_left_edge_array,frac_grid[0,:],label='frac_grid')
                ax.plot(grain_size_left_edge_array,grid_sum,label='grid_sum')
                ax.plot(grain_size_left_edge_array,debug_nearest_extinction_curve,label='d_n_e_c')
                ax.set_yscale('log')
                plt.legend()
                fig.savefig('junk.png',dpi=300)
                
                import pdb
                pdb.set_trace()
                '''

                #------------------------    
        
        else:


                grid_sum = np.zeros(nbins)


                #this sets the fraction of each bin size we need (for the
                #entire grid!)
                for i in range(nbins):
                        grid_sum[i] = np.sum(grid_of_sizes[:,dust_file_to_grain_size_mapping_idx[i]])


                #set up the frac array that is nbins big.  this is the
                #fractional contribution of each dust file bin which is based
                #on the total number of grains in the grid in that bin.
                frac = grid_sum/np.sum(grid_sum)

            
                #now we need to set the localized extinction law. we do
                #this by comparing, fractionally, a given cell's number of
                #grains in that bin to the maximum number of grains that
                #the grid has in that bin.
                
                #this block tests if we're in an octree or not (i.e., we
                #could be in a voronoi mesh, in which case refined doesn't
                #mean anything).  this is necessary since for an octree we
                #don't want to worry about the Trues
                if np.sum(refined) > 0:
                        wFalse = np.where(np.asarray(refined) == 0)[0]
                
                        for i in range(nbins):
                                frac_grid[wFalse,i] = grid_of_sizes[:,dust_file_to_grain_size_mapping_idx[i]]/np.max(grid_of_sizes[:,dust_file_to_grain_size_mapping_idx[i]])*frac[i]
                else:
                        #we take the fractioal grain size distribution
                        #from each size bin, and multiply it by the
                        #cells in each grid (weighted by the ratio of
                        #the logarithm of the actual number of grains
                        #in that bin in that cell to the log of the
                        #cell with the most grains in that bin).
                        for i in range(nbins):
                                frac_grid[:,i] = np.log10(grid_of_sizes[:,dust_file_to_grain_size_mapping_idx[i]])/np.max(np.log10(grid_of_sizes[:,dust_file_to_grain_size_mapping_idx[i]]))*frac[i]


                #now add the dust grids to hyperion
                for bin in range(nbins):
                        file = dust_filenames[bin]
                        d = SphericalDust(cfg.par.pd_source_dir+'active_dust/'+file)
                        m.add_density_grid(dustdens*frac_grid[:,bin],d,specific_energy=specific_energy)
                        #m.add_density_grid(dustdens*frac[bin],d,specific_energy=specific_energy)

        

        #finally, save the grid_of_sizes and grain sizes to the ds.paramteters so we can carry it around
        ds.parameters['reg_grid_of_sizes'] = grid_of_sizes #named 'reg_grid_of_sizes'
        ds.parameters['grain_sizes_in_micron '] = 10.**(x)
Ejemplo n.º 4
0
def arepo_m_gen(fname, field_add):

    reg, ds, dustdens = arepo_vornoi_grid_generate(fname, field_add)

    xcent = ds.quan(cfg.model.x_cent, 'code_length').to('cm')  #proper cm
    ycent = ds.quan(cfg.model.y_cent, 'code_length').to('cm')
    zcent = ds.quan(cfg.model.z_cent, 'code_length').to('cm')

    boost = np.array([xcent, ycent, zcent])
    print('[arepo_tributary/vornoi_m_gen]:  boost = ', boost)

    #========================================================================
    #Initialize Hyperion Model
    #========================================================================

    m = Model()

    #because we boost the stars to a [0,0,0] coordinate center, we
    #want to make sure our vornoi tesslation is created in the same manner.

    particle_x = reg["gascoordinates"][:, 0].to('cm')
    particle_y = reg["gascoordinates"][:, 1].to('cm')
    particle_z = reg["gascoordinates"][:, 2].to('cm')

    #just for the sake of symmetry, pass on a dx,dy,dz since it can be
    #used optionally downstream in other functions.
    dx = 2. * ds.quan(cfg.par.zoom_box_len, 'kpc').to('cm')
    dy = 2. * ds.quan(cfg.par.zoom_box_len, 'kpc').to('cm')
    dz = 2. * ds.quan(cfg.par.zoom_box_len, 'kpc').to('cm')

    print('[arepo_tributary] boost = ', boost)
    print('[arepo_tributary] xmin (pc)= ', (xcent - dx / 2.).to('pc'))
    print('[arepo_tributary] xmax (pc)= ', (xcent + dx / 2.).to('pc'))
    print('[arepo_tributary] ymin (pc)= ', (ycent - dy / 2.).to('pc'))
    print('[arepo_tributary] ymax (pc)= ', (ycent + dy / 2.).to('pc'))
    print('[arepo_tributary] zmin (pc)= ', (zcent - dz / 2.).to('pc'))
    print('[arepo_tributary] zmax (pc)= ', (zcent + dz / 2.).to('pc'))

    x_pos_boost = (particle_x - xcent).to('cm')
    y_pos_boost = (particle_y - ycent).to('cm')
    z_pos_boost = (particle_z - zcent).to('cm')

    m.set_voronoi_grid(x_pos_boost.value, y_pos_boost.value, z_pos_boost.value)

    #get CMB:

    energy_density_absorbed = energy_density_absorbed_by_CMB()
    specific_energy = np.repeat(energy_density_absorbed.value, dustdens.shape)

    if cfg.par.PAH == True:

        # load PAH fractions for usg, vsg, and big (grain sizes)
        frac = cfg.par.PAH_frac

        # Normalize to 1
        total = np.sum(list(frac.values()))
        frac = {k: v / total for k, v in frac.items()}

        for size in frac.keys():
            d = SphericalDust(cfg.par.dustdir + '%s.hdf5' % size)
            if cfg.par.SUBLIMATION == True:
                d.set_sublimation_temperature(
                    'fast', temperature=cfg.par.SUBLIMATION_TEMPERATURE)
            #m.add_density_grid(dustdens * frac[size], cfg.par.dustdir+'%s.hdf5' % size)
            m.add_density_grid(dustdens * frac[size],
                               d,
                               specific_energy=specific_energy)
        m.set_enforce_energy_range(cfg.par.enforce_energy_range)
    else:
        d = SphericalDust(cfg.par.dustdir + cfg.par.dustfile)
        if cfg.par.SUBLIMATION == True:
            d.set_sublimation_temperature(
                'fast', temperature=cfg.par.SUBLIMATION_TEMPERATURE)
        m.add_density_grid(dustdens, d, specific_energy=specific_energy)
        #m.add_density_grid(dustdens,cfg.par.dustdir+cfg.par.dustfile)
    m.set_specific_energy_type('additional')

    return m, xcent, ycent, zcent, dx.value, dy.value, dz.value, reg, ds, boost
Ejemplo n.º 5
0
def sph_m_gen(fname,field_add):
    
    refined,dustdens,fc1,fw1,pf,ad = yt_octree_generate(fname,field_add)
    xmin = (fc1[:,0]-fw1[:,0]/2.).convert_to_units('cm') #in proper cm 
    xmax = (fc1[:,0]+fw1[:,0]/2.).convert_to_units('cm')
    ymin = (fc1[:,1]-fw1[:,1]/2.).convert_to_units('cm')
    ymax = (fc1[:,1]+fw1[:,1]/2.).convert_to_units('cm')
    zmin = (fc1[:,2]-fw1[:,2]/2.).convert_to_units('cm')
    zmax = (fc1[:,2]+fw1[:,2]/2.).convert_to_units('cm')
    

    #dx,dy,dz are the edges of the parent grid
    dx = (np.max(xmax)-np.min(xmin)).value
    dy = (np.max(ymax)-np.min(ymin)).value
    dz = (np.max(zmax)-np.min(zmin)).value


    xcent = np.mean([np.min(xmin),np.max(xmax)]) #kpc
    ycent = np.mean([np.min(ymin),np.max(ymax)])
    zcent = np.mean([np.min(zmin),np.max(zmax)])
    
    boost = np.array([xcent,ycent,zcent])
    print ('[pd_front end] boost = ',boost)

    
    #Tom Robitaille's conversion from z-first ordering (yt's default) to
    #x-first ordering (the script should work both ways)

    refined_array = np.array(refined)
    refined_array = np.squeeze(refined_array)
    
    order = find_order(refined_array)
    refined_reordered = []
    dustdens_reordered = np.zeros(len(order))
    
    
    
    for i in range(len(order)): 
        refined_reordered.append(refined[order[i]])
        dustdens_reordered[i] = dustdens[order[i]]


    refined = refined_reordered
    dustdens=dustdens_reordered

    #hyperion octree stats
    max_level = hos.hyperion_octree_stats(refined)


    pto.test_octree(refined,max_level)

    dump_cell_info(refined,fc1,fw1,xmin,xmax,ymin,ymax,zmin,zmax)
    np.save('refined.npy',refined)
    np.save('density.npy',dustdens)
    

    #========================================================================
    #Initialize Hyperion Model
    #========================================================================

    m = Model()
    
    if cfg.par.FORCE_RANDOM_SEED == True: m.set_seed(cfg.par.seed)

    print ('Setting Octree Grid with Parameters: ')



    #m.set_octree_grid(xcent,ycent,zcent,
    #                  dx,dy,dz,refined)
    m.set_octree_grid(0,0,0,dx/2,dy/2,dz/2,refined)    


    #get CMB:
    
    energy_density_absorbed=energy_density_absorbed_by_CMB()
    specific_energy = np.repeat(energy_density_absorbed.value,dustdens.shape)

    if cfg.par.PAH == True:
        
        # load PAH fractions for usg, vsg, and big (grain sizes)
        frac = cfg.par.PAH_frac

        # Normalize to 1
        total = np.sum(list(frac.values()))
        frac = {k: v / total for k, v in frac.items()}

        for size in frac.keys():
            d = SphericalDust(cfg.par.dustdir+'%s.hdf5'%size)
            if cfg.par.SUBLIMATION == True:
                d.set_sublimation_temperature('fast',temperature=cfg.par.SUBLIMATION_TEMPERATURE)
            #m.add_density_grid(dustdens * frac[size], cfg.par.dustdir+'%s.hdf5' % size)
            m.add_density_grid(dustdens*frac[size],d,specific_energy=specific_energy)
        m.set_enforce_energy_range(cfg.par.enforce_energy_range)
    else:
        d = SphericalDust(cfg.par.dustdir+cfg.par.dustfile)
        if cfg.par.SUBLIMATION == True:
            d.set_sublimation_temperature('fast',temperature=cfg.par.SUBLIMATION_TEMPERATURE)
        m.add_density_grid(dustdens,d,specific_energy=specific_energy)
        #m.add_density_grid(dustdens,cfg.par.dustdir+cfg.par.dustfile)  
    m.set_specific_energy_type('additional')








    return m,xcent,ycent,zcent,dx,dy,dz,pf,boost
Ejemplo n.º 6
0
def extract_extinction_map(SO_cm, SO, dust):
    '''
    Extracting extinction map from radiative transfer calculation.
    
    Parameters
    ----------
    
    SO_cm : SyntheticImage 
        FluxCompensator object of cm observation
    
    SO : SyntheticImage 
        FluxCompensator object of synthetic observation where fieldstars should be added to.
    
    dust : str
        Path and name of dust file.
    
    
    Returns
    -------
    
    A_v : numpy.ndarray
        Optical extinction map.
    
    '''

    # S0_cm needs to be at 1cm
    w0 = SO_cm.wav[0]
    if w0 > 10000. or w0 < 9999.:
        raise Exception('WARNING: Dust extinction image is not at 1cm.')

    # check if resolution is the same
    if SO.resolution['rad'] != SO_cm.resolution['rad']:
        raise Exception(
            'WARNING: Extinction image at 1cm and image from pipeline do not have the same resolution.'
        )

    # check if units are correct
    if SO_cm.units != 'ergs/cm^2/s/Hz':
        raise Exception('WARNING: Units of SO_cm need to be ergs/cm^2/s/Hz.')

    if isinstance(dust, str):
        # load dust properties from hyperion
        from hyperion.dust import SphericalDust
        d = SphericalDust(dust)
        kappa = d.optical_properties.kappa
        chi = d.optical_properties.chi
        wav = d.optical_properties.wav

    else:
        # load dust_kappa, dust_chi & dust_wav
        # from tuple dust={kappa, chi, wav}
        kappa = dust['kappa']
        chi = dust['chi']
        wav = dust['wav']

        if wav[0] < wav[1]:
            kappa = kappa[::-1]
            chi = chi[::-1]
            wav = wav[::-1]

    # extrapolate kappa at 1cm and chi at all wavelengths of SO
    kappa_cm = np.interp(w0, wav[::-1], kappa[::-1])  # cm^2/g
    chi_wav = np.interp(SO.wav, wav[::-1], chi[::-1])  # cm^2/g

    # constants in cgs
    T = 10.
    pi = 3.141592653589793
    h = 6.626068e-27
    k = 1.3806503e-16
    c = 29979245800.0

    # Plank function and Jnu at 1cm with T=10K
    nu = c / (w0 * 1e-4)
    Bnu = 2 * h * nu**3 / c**2 * (np.exp(h * nu / k / T) - 1)**(-1)
    Jnu = Bnu * kappa_cm

    # surface density * chi = tau
    # surface density = surface brightnes / Jnu
    sr = SO_cm.resolution['rad']**2
    tau = SO_cm.val / Jnu / sr * chi_wav

    # extinction at 1 cm
    A_lam = 1.086 * tau

    # convert to A_v
    print 'CAUTION: Extinction law from Kim et al. is used.'
    wav_ext, k_lam = np.loadtxt(ROOT +
                                '../database/extinction/extinction_law.txt',
                                unpack=True)
    k_v = np.interp(0.550, wav_ext, k_lam)
    k = np.interp(1., wav_ext, k_lam)
    A_v = A_lam * (k_v / k)

    return A_v[:, :, 0]
Ejemplo n.º 7
0
def enzo_m_gen(fname,field_add):
    

    
    #add the fields in pd format
    pf = field_add(fname)
    ad = pf.all_data()
   
 

    #cutout
    center = pf.arr([cfg.model.x_cent,cfg.model.y_cent,cfg.model.z_cent],'code_length')
    
    box_len = pf.quan(cfg.par.zoom_box_len,'kpc').in_units('code_length')
   
    min_region = [center[0]-box_len,center[1]-box_len,center[2]-box_len]
    max_region = [center[0]+box_len,center[1]+box_len,center[2]+box_len]
    region = pf.region(center,min_region,max_region)
  
    pf = region.ds
  
    proj_plots(pf)
    #def. dust density
    def _dust_density(field, data):
        return data[('gas', 'metal_density')].in_units("g/cm**3")*cfg.par.dusttometals_ratio
    
    pf.add_field(('gas', 'dust_density'), function=_dust_density, units = 'g/cm**3')
       
    amr = AMRGrid.from_yt(pf, quantity_mapping={'density':('gas','dust_density')})
    


    '''
    levels = pf.index.max_level
    
    amr = AMRGrid()
    for ilevel in range(levels):
        level = amr.add_level()
        
    for igrid in pf.index.select_grids(ilevel):
        print igrid
        grid = level.add_grid()
        grid.xmin,grid.xmax = igrid.LeftEdge[0].in_units('cm'),igrid.RightEdge[0].in_units('cm')
        grid.ymin,grid.ymax = igrid.LeftEdge[1].in_units('cm'),igrid.RightEdge[1].in_units('cm')
        grid.zmin,grid.zmax = igrid.LeftEdge[2].in_units('cm'),igrid.RightEdge[2].in_units('cm')
        grid.quantities["density"] = np.transpose(np.array(igrid[("gas","metal_density")].in_units('g/cm**3')*cfg.par.dusttometals_ratio))
        grid.nx,grid.ny,grid.nz = igrid[("gas","metal_density")].shape
    '''


    m = Model()

    m.set_amr_grid(amr)

    energy_density_absorbed=energy_density_absorbed_by_CMB()
    energy_density_absorbed = np.repeat(energy_density_absorbed.value,amr['density'].shape)


    d = SphericalDust(cfg.par.dustdir+cfg.par.dustfile)
    if cfg.par.SUBLIMATION == True:
        d.set_sublimation_temperature('fast',temperature=cfg.par.SUBLIMATION_TEMPERATURE)
    m.add_density_grid(amr['density'],d,specific_energy=energy_density_absorbed)
    m.set_specific_energy_type('additional')
 #m.add_density_grid(amr['density'], cfg.par.dustdir+cfg.par.dustfile)
    

    #define the random things needed for parsing out the output args
    #center = pf.domain_center
    [xcent,ycent,zcent] = center
   
    boost = np.array([xcent,ycent,zcent])
    dx = pf.domain_width.in_units('cm')
    dy = pf.domain_width.in_units('cm')
    dz = pf.domain_width.in_units('cm')
    
    
    return m,xcent,ycent,zcent,dx,dy,dz,pf,boost

       
Ejemplo n.º 8
0
def arepo_m_gen(fname, field_add):

    reg, ds, dustdens = arepo_vornoi_grid_generate(fname, field_add)

    xcent = ds.quan(cfg.model.x_cent, 'code_length').to('cm')  #proper cm
    ycent = ds.quan(cfg.model.y_cent, 'code_length').to('cm')
    zcent = ds.quan(cfg.model.z_cent, 'code_length').to('cm')

    boost = np.array([xcent, ycent, zcent])
    print('[arepo_tributary/vornoi_m_gen]:  boost = ', boost)

    #========================================================================
    #Initialize Hyperion Model
    #========================================================================

    m = Model()

    #because we boost the stars to a [0,0,0] coordinate center, we
    #want to make sure our vornoi tesslation is created in the same manner.

    particle_x = reg["gas", "coordinates"][:, 0].to('cm')
    particle_y = reg["gas", "coordinates"][:, 1].to('cm')
    particle_z = reg["gas", "coordinates"][:, 2].to('cm')

    #just for the sake of symmetry, pass on a dx,dy,dz since it can be
    #used optionally downstream in other functions.
    dx = 2. * ds.quan(cfg.par.zoom_box_len, 'kpc').to('cm')
    dy = 2. * ds.quan(cfg.par.zoom_box_len, 'kpc').to('cm')
    dz = 2. * ds.quan(cfg.par.zoom_box_len, 'kpc').to('cm')

    print('[arepo_tributary] boost = ', boost)
    print('[arepo_tributary] xmin (pc)= ', (xcent - dx / 2.).to('pc'))
    print('[arepo_tributary] xmax (pc)= ', (xcent + dx / 2.).to('pc'))
    print('[arepo_tributary] ymin (pc)= ', (ycent - dy / 2.).to('pc'))
    print('[arepo_tributary] ymax (pc)= ', (ycent + dy / 2.).to('pc'))
    print('[arepo_tributary] zmin (pc)= ', (zcent - dz / 2.).to('pc'))
    print('[arepo_tributary] zmax (pc)= ', (zcent + dz / 2.).to('pc'))

    x_pos_boost = (particle_x - xcent).to('cm')
    y_pos_boost = (particle_y - ycent).to('cm')
    z_pos_boost = (particle_z - zcent).to('cm')

    m.set_voronoi_grid(x_pos_boost.value, y_pos_boost.value, z_pos_boost.value)

    #get CMB:

    energy_density_absorbed = energy_density_absorbed_by_CMB()
    specific_energy = np.repeat(energy_density_absorbed.value, dustdens.shape)

    if cfg.par.otf_extinction == False:

        if cfg.par.PAH == True:

            # load PAH fractions for usg, vsg, and big (grain sizes)
            frac = cfg.par.PAH_frac

            # Normalize to 1
            total = np.sum(list(frac.values()))
            frac = {k: v / total for k, v in frac.items()}

            for size in frac.keys():
                d = SphericalDust(cfg.par.dustdir + '%s.hdf5' % size)
                if cfg.par.SUBLIMATION == True:
                    d.set_sublimation_temperature(
                        'fast', temperature=cfg.par.SUBLIMATION_TEMPERATURE)
                    #m.add_density_grid(dustdens * frac[size], cfg.par.dustdir+'%s.hdf5' % size)
                m.add_density_grid(dustdens * frac[size],
                                   d,
                                   specific_energy=specific_energy)
            m.set_enforce_energy_range(cfg.par.enforce_energy_range)
        else:
            d = SphericalDust(cfg.par.dustdir + cfg.par.dustfile)
            if cfg.par.SUBLIMATION == True:
                d.set_sublimation_temperature(
                    'fast', temperature=cfg.par.SUBLIMATION_TEMPERATURE)
            m.add_density_grid(dustdens, d, specific_energy=specific_energy)
        #m.add_density_grid(dustdens,cfg.par.dustdir+cfg.par.dustfile)

    else:  #instead of using a constant extinction law across the
        #entire galaxy, we'll compute it on a cell-by-cell bassis by
        #using information about the grain size distribution from
        #the simulation itself.

        ad = ds.all_data()
        nsizes = reg['PartType0', 'NumGrains'].shape[1]
        try:
            assert (np.sum(ad['PartType0', 'NumGrains']) > 0)
        except AssertionError:
            raise AssertionError(
                "[arepo_tributary:] There are no dust grains in this simulation.  This can sometimes happen in an early snapshot of a simulation where the dust has not yet had time to form."
            )
        grid_of_sizes = reg['PartType0', 'NumGrains']
        active_dust_add(ds, m, grid_of_sizes, nsizes, dustdens,
                        specific_energy)

    m.set_specific_energy_type('additional')

    return m, xcent, ycent, zcent, dx.value, dy.value, dz.value, reg, ds, boost
Ejemplo n.º 9
0
def setup_model(parfile, output, imaging=True):

    # Read in model parameters
    par = read_parfile(parfile, nested=True)

    # Find all dust files
    dust_files = {}
    for par_name in par:
        if 'dust' in par[par_name]:
            dust_file = par[par_name]['dust']
            dust_files[dust_file] = SphericalDust(dust_file)

    # Find dimensionality of problem:
    if 'disk' in par:
        ndim = 2
        optimize = False
    elif 'cavity' in par:
        ndim = 2
        optimize = False
    elif 'envelope' in par and 'rc' in par['envelope']:
        ndim = 2
        optimize = False
    else:
        ndim = 1
        optimize = True

    # Set up model
    m = AnalyticalYSOModel(output)

    if not 'star' in par:
        raise Exception("Cannot compute a model without a central source")

    # Set radius and luminosity
    m.star.radius = par['star']['radius'] * rsun
    m.star.luminosity = 4. * pi * (par['star']['radius'] * rsun) ** 2. \
                        * sigma * par['star']['temperature'] ** 4.

    # Interpolate and set spectrum
    nu, fnu = interp_atmos(par['star']['temperature'])
    m.star.spectrum = (nu, fnu)

    subtract_from_ambient = []

    if 'disk' in par:

        # Add the flared disk component
        disk = m.add_flared_disk()

        # Basic parameters
        disk.mass = par['disk']['mass'] * msun
        disk.rmax = par['disk']['rmax'] * au
        disk.p = par['disk']['p']
        disk.beta = par['disk']['beta']
        disk.h_0 = par['disk']['h100'] * au
        disk.r_0 = 100. * au

        # Set inner and outer walls to be spherical
        disk.cylindrical_inner_rim = False
        disk.cylindrical_outer_rim = False

        # Set dust
        disk.dust = dust_files[par['disk']['dust']]

        # Inner radius
        if 'rmin' in par['disk']:
            disk.rmin = par['disk']['rmin'] * OptThinRadius(TSUB)
        else:
            disk.rmin = OptThinRadius(TSUB)

        # Settling
        if 'eta' in par['disk']:
            raise Exception("Dust settling not implemented")

        # Accretion luminosity
        if 'lacc' in par['disk']:
            raise Exception("Accretion luminosity not implemented")
            # m.setup_magnetospheric_accretion(par['disk']['lacc'] * lsun,
            #                                  par['disk']['rtrunc'],
            #                                  par['star']['fspot'], disk)

        subtract_from_ambient.append(disk)

    if 'envelope' in par:

        if 'rc' in par['envelope']:  # Ulrich envelope

            envelope = m.add_ulrich_envelope()
            envelope.rho_0 = par['envelope']['rho_0']
            envelope.rc = par['envelope']['rc'] * au

        elif 'power' in par['envelope']:  # Power-law envelope

            envelope = m.add_power_law_envelope()
            envelope.power = par['envelope']['power']
            envelope.rho_0 = par['envelope']['rho_0']
            envelope.r_0 = 1000. * au

        # Set dust
        envelope.dust = dust_files[par['envelope']['dust']]

        # Inner radius
        if 'rmin' in par['envelope']:
            envelope.rmin = par['envelope']['rmin'] * OptThinRadius(TSUB)
        else:
            envelope.rmin = OptThinRadius(TSUB)

        subtract_from_ambient.append(envelope)

    if 'cavity' in par:

        if not 'envelope' in par:
            raise Exception("Can't have a bipolar cavity without an envelope")

        # Add the bipolar cavity component
        cavity = envelope.add_bipolar_cavity()

        # Basic parameters
        cavity.power = par['cavity']['power']
        cavity.r_0 = 10000 * au
        cavity.theta_0 = par['cavity']['theta_0']
        cavity.rho_0 = par['cavity']['rho_0']
        cavity.rho_exp = 0.

        # Very important is that the cavity density should not be *larger* than
        # the envelope density.
        cavity.cap_to_envelope_density = True

        # Set dust
        cavity.dust = dust_files[par['cavity']['dust']]

        subtract_from_ambient.append(cavity)

    if 'ambient' in par:

        # Add the ambient medium contribution
        ambient = m.add_ambient_medium(subtract=subtract_from_ambient)

        # Set the density, temperature, and dust properties
        ambient.rho = par['ambient']['density']
        ambient.temperature = par['ambient']['temperature']
        ambient.dust = dust_files[par['ambient']['dust']]

        # If there is an envelope, set the outer radius to where the
        # optically thin temperature would transition to the ambient medium
        # temperature
        if 'envelope' in par:

            # Find radius where the optically thin temperature drops to the
            # ambient temperature. We can do this only if we've already set
            # up all the sources of emission beforehand (which we have)
            rmax_temp = OptThinRadius(ambient.temperature).evaluate(m.star, envelope.dust)

            # Find radius where the envelope density drops to the ambient density
            rmax_dens = envelope.outermost_radius(ambient.rho)

            # If disk radius is larger than this, use that instead
            if 'disk' in par:
                if disk.rmax > rmax_dens:
                    rmax_dens = disk.rmax

            # Pick the largest
            if rmax_temp < rmax_dens:
                print("Setting envelope outer radius to that where rho(r) = rho_amb")
                envelope.rmax = rmax_dens
            else:
                print("Setting envelope outer radius to that where T_thin(r) = T_amb")
                envelope.rmax = OptThinRadius(ambient.temperature)

            ambient.rmax = envelope.rmax

        else:

            if 'disk' in par:

                # Find radius where the optically thin temperature drops to the
                # ambient temperature. We can do this only if we've already set
                # up all the sources of emission beforehand (which we have)
                rmax_temp = OptThinRadius(ambient.temperature).evaluate(m.star, ambient.dust)

                # Find outer disk radius
                rmax_dens = disk.rmax

                # Pick the largest
                if rmax_temp < rmax_dens:
                    print("Setting ambient outer radius to outer disk radius")
                    ambient.rmax = rmax_dens
                else:
                    print("Setting ambient outer radius to that where T_thin(r) = T_amb")
                    ambient.rmax = OptThinRadius(ambient.temperature)

            else:

                ambient.rmax = OptThinRadius(ambient.temperature)

        # The inner radius for the ambient medium should be the largest of
        # the inner radii for the disk and envelope
        if 'envelope' in par and 'rmin' in par['envelope']:
            if 'disk' in par and 'rmin' in par['disk']:
                ambient.rmin = max(par['disk']['rmin'], \
                                   par['envelope']['rmin']) \
                               * OptThinRadius(TSUB)
            else:
                ambient.rmin = par['envelope']['rmin'] * OptThinRadius(TSUB)
        elif 'disk' in par and 'rmin' in par['disk']:
            ambient.rmin = par['disk']['rmin'] * OptThinRadius(TSUB)
        else:
            ambient.rmin = OptThinRadius(TSUB)

        # The ambient medium needs to go out to sqrt(2.) times the envelope
        # radius to make sure the slab is full (don't need to do sqrt(3)
        # because we only need a cylinder along line of sight)
        ambient.rmax *= np.sqrt(2.)

        # Make sure that the temperature in the model is always at least
        # the ambient temperature
        m.set_minimum_temperature(ambient.temperature)

    else:

        # Make sure that the temperature in the model is always at least
        # the CMB temperature
        m.set_minimum_temperature(2.725)

        if 'envelope' in par:
            raise Exception("Can't have an envelope without an ambient medium")

    # Use raytracing to improve s/n of thermal/source emission
    m.set_raytracing(True)

    # Use the modified random walk
    m.set_mrw(True, gamma=2.)

    # Use the partial diffusion approximation
    m.set_pda(True)

    # Improve s/n of scattering by forcing the first interaction
    m.set_forced_first_scattering(True)

    # Set up grid.
    if ndim == 1:
        m.set_spherical_polar_grid_auto(400, 1, 1)
    else:
        m.set_spherical_polar_grid_auto(400, 300, 1)

    # Find the range of radii spanned by the grid
    rmin, rmax = m.radial_range()

    # Set up SEDs
    image = m.add_peeled_images(sed=True, image=False)
    image.set_wavelength_range(200, 0.01, 5000.)

    if 'ambient' in par:
        image.set_aperture_range(20, rmin, rmax / np.sqrt(2.))
    else:
        image.set_aperture_range(20, rmin, rmax)

    image.set_output_bytes(8)
    image.set_track_origin(True)
    image.set_uncertainties(True)
    image.set_stokes(True)

    if ndim == 1:

        # Viewing angle does not matter
        image.set_viewing_angles([45.], [45.])

    else:

        # Use stratified random sampling to ensure that all models
        # contain a viewing angle in each bin, but also ensure we have a
        # continuum of viewing angles over all models
        xi = np.random.uniform(0., 90./float(NVIEW), NVIEW)
        theta = xi + np.linspace(0., 90. * (1. - 1./float(NVIEW)), NVIEW)
        image.set_viewing_angles(theta, np.repeat(45., NVIEW))

    if 'ambient' in par:  # take a slab to avoid spherical geometrical effects
        w = ambient.rmax / np.sqrt(2.)
        image.set_depth(-w, w)
    else:  # don't need to take a slab, as no ambient material or envelope
        image.set_depth(-np.inf, np.inf)

    # Set number of photons

    if imaging:
        n_imaging=1e6
        n_raytracing_sources=10000
        n_raytracing_dust=1e6
    else:
        n_imaging=0
        n_raytracing_sources=0
        n_raytracing_dust=0

    if ndim == 1:
        m.set_n_photons(initial=100, imaging=n_imaging,
                        raytracing_sources=n_raytracing_sources,
                        raytracing_dust=n_raytracing_dust)
    else:
        m.set_n_photons(initial=1000000, imaging=n_imaging,
                        raytracing_sources=n_raytracing_sources,
                        raytracing_dust=n_raytracing_dust)

    # Set physical array output to 32-bit
    m.set_output_bytes(4)

    # Set maximum of 10^8 interactions per photon
    m.set_max_interactions(1e8)

    # Only request certain arrays to be output
    m.conf.output.output_density = 'none'
    m.conf.output.output_specific_energy = 'last'
    m.conf.output.output_n_photons = 'none'
    m.conf.output.output_density_diff = 'last'

    # Set number of temperature iterations and convergence criterion
    m.set_n_initial_iterations(10)
    m.set_convergence(True, percentile=99.0, absolute=2.0, relative=1.1)

    # Don't copy the full input into the output files
    m.set_copy_input(False)

    # Check whether the model is very optically thick

    mf = m.to_model()

    if 'envelope' in par:

        from hyperion.model.helpers import tau_to_radius
        surface = tau_to_radius(mf, tau=1., wav=5e3)
        rtau = np.min(surface)

        if rtau > rmin and optimize:
            log.warn("tau_5mm > 1 for all (theta,phi) values - truncating "
                     "inner envelope from {0:.3f}au to {1:.3f}au".format(mf.grid.r_wall[1] / au, rtau / au))
            for item in mf.grid['density']:
                item.array[mf.grid.gr < rtau] = 0.

    # Write out file
    mf.write(copy=False, absolute_paths=False,
             physics_dtype=np.float32, wall_dtype=float)
Ejemplo n.º 10
0
    # * system size = 10x10x10 pc
    # * system coordinates (x,y,z min/max) = -5 to +5 pc
    # * slab z extent = -2 to -5 pc
    # * slab xy extend = -5 pc to 5 pc
    # * z optical depth @0.55um in slab = 0.1, 1, 20
    # * optical depth outside slab = 0

    x = np.linspace(-5 * pc, 5 * pc, 100)
    y = np.linspace(-5 * pc, 5 * pc, 100)
    z = np.hstack([np.linspace(-5 * pc, -2 * pc, 100), 5 * pc])

    m.set_cartesian_grid(x, y, z)

    # Grain Properties:

    d = SphericalDust('integrated_hg_scattering.hdf5')
    chi_v = d.optical_properties.interp_chi_wav(0.55)

    # Determine density in slab
    rho0 = tau_v / (3 * pc * chi_v)

    # Set up density grid
    density = np.ones(m.grid.shape) * rho0
    density[-1,:,:] = 0.

    m.add_density_grid(density, d)

    # Set up illuminating source:
    s = m.add_point_source()
    s.position = (0., 0., 4 * pc)
    s.temperature = 10000.0
Ejemplo n.º 11
0
def sph_m_gen(fname,field_add):

    refined,dustdens,fc1,fw1,reg,ds = yt_octree_generate(fname,field_add)
    
    if float(yt.__version__[0:3]) >= 4:
        xmin = (fc1[:,0]-fw1[:,0]/2.).to('cm') #in proper cm 
        xmax = (fc1[:,0]+fw1[:,0]/2.).to('cm')
        ymin = (fc1[:,1]-fw1[:,1]/2.).to('cm')
        ymax = (fc1[:,1]+fw1[:,1]/2.).to('cm')
        zmin = (fc1[:,2]-fw1[:,2]/2.).to('cm')
        zmax = (fc1[:,2]+fw1[:,2]/2.).to('cm')
    else:
        xmin = (fc1[:,0]-fw1[:,0]/2.).convert_to_units('cm') #in proper cm
        xmax = (fc1[:,0]+fw1[:,0]/2.).convert_to_units('cm')
        ymin = (fc1[:,1]-fw1[:,1]/2.).convert_to_units('cm')
        ymax = (fc1[:,1]+fw1[:,1]/2.).convert_to_units('cm')
        zmin = (fc1[:,2]-fw1[:,2]/2.).convert_to_units('cm')
        zmax = (fc1[:,2]+fw1[:,2]/2.).convert_to_units('cm')

    #dx,dy,dz are the edges of the parent grid
    dx = (np.max(xmax)-np.min(xmin)).value
    dy = (np.max(ymax)-np.min(ymin)).value
    dz = (np.max(zmax)-np.min(zmin)).value


    xcent = float(ds.quan(cfg.model.x_cent,"code_length").to('cm').value)
    ycent = float(ds.quan(cfg.model.y_cent,"code_length").to('cm').value)
    zcent = float(ds.quan(cfg.model.z_cent,"code_length").to('cm').value)

    boost = np.array([xcent,ycent,zcent])
    print ('[sph_tributary] boost = ',boost)
    print ('[sph_tributary] xmin (pc)= ',np.min(xmin.to('pc')))
    print ('[sph_tributary] xmax (pc)= ',np.max(xmax.to('pc')))
    print ('[sph_tributary] ymin (pc)= ',np.min(ymin.to('pc')))
    print ('[sph_tributary] ymax (pc)= ',np.max(ymax.to('pc')))
    print ('[sph_tributary] zmin (pc)= ',np.min(zmin.to('pc')))
    print ('[sph_tributary] zmax (pc)= ',np.max(zmax.to('pc')))
    #Tom Robitaille's conversion from z-first ordering (yt's default) to
    #x-first ordering (the script should work both ways)



    refined_array = np.array(refined)
    refined_array = np.squeeze(refined_array)
    
    order = find_order(refined_array)
    refined_reordered = []
    dustdens_reordered = np.zeros(len(order))
    


    
    for i in range(len(order)): 
        refined_reordered.append(refined[order[i]])
        dustdens_reordered[i] = dustdens[order[i]]


    refined = refined_reordered
    dustdens=dustdens_reordered

    #hyperion octree stats
    max_level = hos.hyperion_octree_stats(refined)


    pto.test_octree(refined,max_level)
    
    if float(yt.__version__[0:3]) >= 4:
        dump_cell_info(refined,fc1.to('cm'),fw1.to('cm'),xmin,xmax,ymin,ymax,zmin,zmax)
    else:
        dump_cell_info(refined,fc1.convert_to_units('cm'),fw1.convert_to_units('cm'),xmin,xmax,ymin,ymax,zmin,zmax)
    
    np.save('refined.npy',refined)
    np.save('density.npy',dustdens)
    

    #========================================================================
    #Initialize Hyperion Model
    #========================================================================

    m = Model()
    
    #save in the m__dict__ that we're in an oct geometry
    m.__dict__['grid_type']='oct'

    print ('Setting Octree Grid with Parameters: ')



    #m.set_octree_grid(xcent,ycent,zcent,
    #                  dx,dy,dz,refined)
    m.set_octree_grid(0,0,0,dx/2,dy/2,dz/2,refined)    

    #get CMB:
    
    energy_density_absorbed=energy_density_absorbed_by_CMB()
    specific_energy = np.repeat(energy_density_absorbed.value,dustdens.shape)


    if cfg.par.otf_extinction == False:
        
        if cfg.par.PAH == True:

            # load PAH fractions for usg, vsg, and big (grain sizes)
            frac = cfg.par.PAH_frac
            
            # Normalize to 1
            total = np.sum(list(frac.values()))
            frac = {k: v / total for k, v in frac.items()}

            for size in frac.keys():
                d = SphericalDust(cfg.par.dustdir+'%s.hdf5'%size)
                if cfg.par.SUBLIMATION == True:
                    d.set_sublimation_temperature('fast',temperature=cfg.par.SUBLIMATION_TEMPERATURE)
                #m.add_density_grid(dustdens * frac[size], cfg.par.dustdir+'%s.hdf5' % size)
                m.add_density_grid(dustdens*frac[size],d,specific_energy=specific_energy)
            m.set_enforce_energy_range(cfg.par.enforce_energy_range)
        else:
            d = SphericalDust(cfg.par.dustdir+cfg.par.dustfile)
            if cfg.par.SUBLIMATION == True:
                d.set_sublimation_temperature('fast',temperature=cfg.par.SUBLIMATION_TEMPERATURE)
            m.add_density_grid(dustdens,d,specific_energy=specific_energy)
        #m.add_density_grid(dustdens,cfg.par.dustdir+cfg.par.dustfile)  


    else: #instead of using a constant extinction law across the
          #entire galaxy, we'll compute it on a cell-by-cell basis by
          #using information about the grain size distribution from
          #the simulation itself.


        print("==============================================\n")
        print("Entering OTF Extinction Calculation\n")
        print("Note: For very high-resolution grids, this may cause memory issues due to adding ncells dust grids")
        print("==============================================\n")
        
        ad = ds.all_data()
        nsizes = ad['PartType3','Dust_Size'].shape[1]
        ncells = reg.parameters["octree_of_sizes"].shape[0]
        #ensure that the grid has particles
        for isize in range(nsizes):
            try:
                assert (np.sum(reg.parameters["octree_of_sizes"][:,isize]) > 0)
            except AssertionError:
                raise AssertionError("[sph_tributary:] The grain size distribution smoothed onto the octree has deposited no particles.  Try either increasing your box size, or decreasing n_ref in parameters_master.  Alternatively, run the simulation with otf_extinction=False")

        #define the grid of sizes that will be used in tributary_dust_add
        grid_of_sizes = reg.parameters["octree_of_sizes"]
        
        active_dust_add(ds,m,grid_of_sizes,nsizes,dustdens,specific_energy,refined)
        

    m.set_specific_energy_type('additional')

    return m,xcent,ycent,zcent,dx,dy,dz,reg,ds,boost
Ejemplo n.º 12
0
from hyperion.dust import SphericalDust
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

from astropy import units as u
from astropy import constants as constants

dustfile = '/ufrc/narayanan/desika.narayanan/pd/hyperion-dust/dust_files/d03_3.1_6.0_A.hdf5'
dust = SphericalDust(dustfile)
mw_df_nu = dust.optical_properties.nu
mw_df_chi  = dust.optical_properties.chi

mw_df_lam = (constants.c/(mw_df_nu*u.Hz)).to(u.micron)
x = 1./mw_df_lam


fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x,mw_df_chi)
ax.set_xlim([1,10])
ax.set_xlabel('x')
ax.set_ylabel(r'$\chi$')
fig.savefig('extinction.png',dpi=300)