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
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
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)
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
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
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]
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
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
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)
# * 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
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
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)