def setup_gas_particle_fields(self, ptype): super(GizmoFieldInfo, self).setup_gas_particle_fields(ptype) def _h_density(field, data): x_H = 1.0 - data[(ptype, "He_metallicity")] - \ data[(ptype, "metallicity")] return x_H * data[(ptype, "density")] * \ data[(ptype, "NeutralHydrogenAbundance")] self.add_field((ptype, "H_density"), function=_h_density, particle_type=True, units=self.ds.unit_system["density"]) add_species_field_by_density(self, ptype, "H", particle_type=True) for suffix in ["density", "fraction", "mass", "number_density"]: self.alias((ptype, "H_p0_%s" % suffix), (ptype, "H_%s" % suffix)) def _h_p1_density(field, data): x_H = 1.0 - data[(ptype, "He_metallicity")] - \ data[(ptype, "metallicity")] return x_H * data[(ptype, "density")] * \ (1.0 - data[(ptype, "NeutralHydrogenAbundance")]) self.add_field((ptype, "H_p1_density"), function=_h_p1_density, particle_type=True, units=self.ds.unit_system["density"]) add_species_field_by_density(self, ptype, "H_p1", particle_type=True) def _nuclei_mass_density_field(field, data): species = field.name[1][:field.name[1].find("_")] return data[ptype, "density"] * \ data[ptype, "%s_metallicity" % species] num_neighbors = 64 for species in ['H', 'H_p0', 'H_p1']: for suf in ["_density", "_number_density"]: field = "%s%s" % (species, suf) fn = add_volume_weighted_smoothed_field( ptype, "particle_position", "particle_mass", "smoothing_length", "density", field, self, num_neighbors) self.alias(("gas", field), fn[0]) for species in self.nuclei_names: self.add_field((ptype, "%s_nuclei_mass_density" % species), function=_nuclei_mass_density_field, particle_type=True, units=self.ds.unit_system["density"]) for suf in ["_nuclei_mass_density", "_metallicity"]: field = "%s%s" % (species, suf) fn = add_volume_weighted_smoothed_field( ptype, "particle_position", "particle_mass", "smoothing_length", "density", field, self, num_neighbors) self.alias(("gas", field), fn[0])
def setup_gas_particle_fields(self, ptype): if (ptype, "ElectronAbundance") in self.ds.field_list: def _temperature(field, data): # Assume cosmic abundances x_H = 0.76 gamma = 5.0/3.0 a_e = data[ptype, 'ElectronAbundance'] mu = 4.0 / (3.0 * x_H + 1.0 + 4.0 * x_H * a_e) ret = data[ptype, "InternalEnergy"]*(gamma-1)*mu*mp/kb return ret.in_units('K') else: def _temperature(field, data): # Assume cosmic abundances x_H = 0.76 gamma = 5.0/3.0 # Assume zero ionization mu = 4.0 / (3.0 * x_H + 1.0) ret = data[ptype, "InternalEnergy"]*(gamma-1)*mu*mp/kb return ret.in_units('K') self.add_field( (ptype, "Temperature"), function=_temperature, particle_type=True, units="K") # For now, we hardcode num_neighbors. We should make this configurable # in the future. num_neighbors = 64 fn = add_volume_weighted_smoothed_field( ptype, "particle_position", "particle_mass", "smoothing_length", "density", "Temperature", self, num_neighbors) # Alias ("gas", "temperature") to the new smoothed Temperature field self.alias(("gas", "temperature"), fn[0])
def setup_gas_particle_fields(self, ptype): if (ptype, "ElectronAbundance") in self.ds.field_list: def _temperature(field, data): # Assume cosmic abundances x_H = 0.76 gamma = 5.0 / 3.0 a_e = data[ptype, 'ElectronAbundance'] mu = 4.0 / (3.0 * x_H + 1.0 + 4.0 * x_H * a_e) ret = data[ptype, "InternalEnergy"] * (gamma - 1) * mu * mp / kb return ret.in_units(self.ds.unit_system["temperature"]) else: def _temperature(field, data): # Assume cosmic abundances x_H = 0.76 gamma = 5.0 / 3.0 if data.has_field_parameter("mean_molecular_weight"): mu = data.get_field_parameter("mean_molecular_weight") else: # Assume zero ionization #mu = 4.0 / (3.0 * x_H + 1.0) # Assume full ionization mu = 4.0 / (5.0 * x_H + 3.0) ret = data[ptype, "InternalEnergy"] * (gamma - 1) * mu * mp / kb return ret.in_units(self.ds.unit_system["temperature"]) self.add_field((ptype, "Temperature"), sampling_type="particle", function=_temperature, units=self.ds.unit_system["temperature"]) self.alias((ptype, 'temperature'), (ptype, 'Temperature')) # For now, we hardcode num_neighbors. We should make this configurable # in the future. num_neighbors = 64 fn = add_volume_weighted_smoothed_field(ptype, "particle_position", "particle_mass", "smoothing_length", "density", "Temperature", self, num_neighbors) # Alias ("gas", "temperature") to the new smoothed Temperature field self.alias(("gas", "temperature"), fn[0])
def load_data(ray_start, ray_direction, low_res=True): if low_res: # Import some FIRE2 data fname = '/mnt/raid-project/murray/lakhlani/FIRE2_core/'+\ 'm12c_res56000/output/snapshot_600.hdf5' ds = yt.load(fname) # The center of the Halo was recovered in another notebook center_Halo = [25277.66673046, 34505.21241664, 32868.48520185] sp = ds.sphere(center_Halo, (20, "kpc")) # Put the earth about 8kpc from the # center where the box units are in kpc/h z_axis = np.array([0.90088129, -0.07389156, -0.42772998]) x_axis = yt.ortho_find(z_axis)[1] y_axis = yt.ortho_find(z_axis)[2] ray_start_conv = x_axis*ray_start[0]+y_axis*ray_start[1]+\ z_axis*ray_start[2] ray_direction_conv = x_axis*ray_direction[0]+y_axis*ray_direction[1]+\ z_axis*ray_direction[2] # Adds the field to the data set ds.add_field(('PartType0', '_ElectronDensity'), function=_ElectronDensity, sampling_type='particle', units='1/cm**3') # smooths a particle field into a continuous field fn = add_volume_weighted_smoothed_field("PartType0", "particle_position", "particle_mass", "smoothing_length", "density", "_ElectronDensity", ds.field_info) # Labels the new field ds.field_info.alias(('gas', '_ElectronDensity'), fn[0]) ds.derived_field_list.append(('gas', '_ElectronDensity')) return ds, center_Halo, sp, ray_direction_conv, ray_start_conv
def gadget_field_add(fname, bounding_box=None, ds=None, add_smoothed_quantities=True): def _starmetals_00(field, data): el_dict = { 'He': '01', 'C': '02', 'N': '03', 'O': '04', 'Ne': '05', 'Mg': '06', 'Si': '07', 'S': '08', 'Ca': '09', 'Fe': '10' } el_str = field.name[1] if '_' in el_str: el_name = field.name[1][field.name[1].find('_') + 1:] el_num = el_dict[el_name] else: el_num = '00' return data[('PartType4', 'Metallicity_' + el_num)] def _starmetals(field, data): return data[('PartType4', 'Metallicity')] def _starcoordinates(field, data): return data[('PartType4', 'Coordinates')] def _starformationtime(field, data): return data[('PartType4', 'StellarFormationTime')] def _starmasses(field, data): return data[("PartType4", "Masses")] def _diskstarcoordinates(field, data): return data[('PartType2', 'Coordinates')] def _diskstarmasses(field, data): return data[("PartType2", "Masses")] def _bulgestarcoordinates(field, data): return data[('PartType3', 'Coordinates')] def _bulgestarmasses(field, data): return data[("PartType3", "Masses")] def _gasdensity(field, data): return data[('PartType0', 'Density')] def _gasmetals_00(field, data): return data[('PartType0', 'Metallicity_00')] def _gasmetals(field, data): return data[('PartType0', 'Metallicity')] def _gascoordinates(field, data): return data[('PartType0', 'Coordinates')] def _gasmasses(field, data): return data[('PartType0', 'Masses')] def _gasfh2(field, data): try: return data[('PartType0', 'FractionH2')] except: return data[('PartType0', 'metallicity')] * 0. def _gassfr(field, data): return data[('PartType0', 'StarFormationRate')] def _gassmootheddensity(field, data): if yt.__version__ == '4.0.dev0': return data.ds.parameters['octree'][('PartType0', 'density')] else: return data[("deposit", "PartType0_smoothed_density")] def _gassmoothedmetals(field, data): if yt.__version__ == '4.0.dev0': return data.ds.parameters['octree'][('PartType0', 'metallicity')] else: return data[("deposit", "PartType0_smoothed_metallicity")] def _gassmoothedmasses(field, data): if yt.__version__ == '4.0.dev0': return data.ds.parameters['octree'][('PartType0', 'Masses')] else: return data[('deposit', 'PartType0_mass')] def _metaldens_00(field, data): return (data["PartType0", "Density"] * data["PartType0", "Metallicity_00"]) def _metaldens(field, data): return (data["PartType0", "Density"] * data["PartType0", "Metallicity"]) def _metalmass_00(field, data): return (data["PartType0", "Masses"] * (data["PartType0", "Metallicity_00"].value)) def _metalmass(field, data): return (data["PartType0", "Masses"] * (data["PartType0", "Metallicity"].value)) def _metalsmoothedmasses(field, data): if yt.__version__ == '4.0.dev0': return (data.ds.parameters['octree'][('PartType0', 'Masses')] * data.ds.parameters['octree'][('PartType0', 'metallicity')]) else: return (data[('deposit', 'PartType0_smoothed_metalmass')].value) def _dustmass_manual(field, data): return (data.ds.arr(data[("PartType0", "Dust_Masses")].value, 'code_mass')) def _dustmass_dtm(field, data): return (data["PartType0", "metalmass"] * cfg.par.dusttometals_ratio) def _li_ml_dustmass(field, data): return (data.ds.arr(data.ds.parameters['li_ml_dustmass'].value, 'code_mass')) def _dustsmoothedmasses(field, data): if yt.__version__ == '4.0.dev0': return (data.ds.parameters['octree'][('PartType0', 'Dust_Masses')]) else: return (data.ds.arr( data[("deposit", "PartType0_sum_Dust_Masses")].value, 'code_mass')) def _li_ml_dustsmoothedmasses(field, data): if yt.__version__ == '4.0.dev0': return (data.ds.parameters['octree'][('PartType0', 'li_ml_dustmass')]) else: return (data.ds.arr( data[("deposit", "PartType0_sum_li_ml_dustmass")].value, 'code_mass')) def _stellarages(field, data): ad = data.ds.all_data() if data.ds.cosmological_simulation == False: simtime = data.ds.current_time.in_units('Gyr') simtime = simtime.value age = simtime - data.ds.arr( ad[('PartType4', 'StellarFormationTime')], 'Gyr').value # make the minimum age 1 million years age[np.where(age < 1.e-3)[0]] = 1.e-3 print('\n--------------') print( '[gadget2pd: ] Idealized Galaxy Simulation Assumed: Simulation time is (Gyr): ', simtime) print('--------------\n') else: yt_cosmo = yt.utilities.cosmology.Cosmology( hubble_constant=data.ds.hubble_constant, omega_matter=data.ds.omega_matter, omega_lambda=data.ds.omega_lambda) simtime = yt_cosmo.t_from_z(ds.current_redshift).in_units( 'Gyr').value # Current age of the universe scalefactor = data[('PartType4', 'StellarFormationTime')].value formation_z = (1. / scalefactor) - 1. formation_time = yt_cosmo.t_from_z(formation_z).in_units( 'Gyr').value age = simtime - formation_time # Minimum age is set to 1 Myr (FSPS doesn't work properly for ages below 1 Myr) age[np.where(age < 1.e-3)[0]] = 1.e-3 print('\n--------------') print( '[gadget2pd: ] Cosmological Galaxy Simulation Assumed: Current age of Universe is (Gyr): ', simtime) print('--------------\n') age = data.ds.arr(age, 'Gyr') return age def _starsmoothedmasses(field, data): return data[('deposit', 'PartType4_mass')] def _bhluminosity(field, data): ad = data.ds.all_data() mdot = ad[("PartType5", "BH_Mdot")] # give it a unit since usually these are dimensionless in yt mdot = data.ds.arr(mdot, "code_mass/code_time") c = yt.utilities.physical_constants.speed_of_light_cgs bhluminosity = (cfg.par.BH_eta * mdot * c**2.).in_units("erg/s") print("[front_ends/gadget2pd:] Generating the black hole luminosity") if cfg.par.BH_var: return bhluminosity * cfg.par.bhlfrac else: return bhluminosity def _bhcoordinates(field, data): return data["PartType5", "Coordinates"] def _bhsed_nu(field, data): bhluminosity = data["bhluminosity"] log_lum_lsun = np.log10(bhluminosity[0].in_units("Lsun")) nu, bhlum = agn_spectrum(log_lum_lsun) # the last 4 numbers aren't part of the SED nu = nu[0:-4] nu = 10.**nu nu = yt.YTArray(nu, "Hz") return nu def _bhsed_sed(field, data): bhluminosity = data["bhluminosity"] nholes = len(bhluminosity) # get len of nu just for the 0th hole so we know how long the vector is log_lum_lsun = np.log10(bhluminosity[0].in_units("Lsun")) nu, l_band_vec = agn_spectrum(log_lum_lsun) nu = nu[0:-4] n_nu = len(nu) bh_sed = np.zeros([nholes, n_nu]) for i in range(nholes): log_lum_lsun = np.log10(bhluminosity[i].in_units("Lsun")) nu, l_band_vec = agn_spectrum(log_lum_lsun) l_band_vec = 10.**l_band_vec l_band_vec = l_band_vec[0:-4] for l in range(len(l_band_vec)): l_band_vec[l] = data.ds.quan(l_band_vec[l], "erg/s") bh_sed[i, :] = l_band_vec bh_sed = yt.YTArray(bh_sed, "erg/s") return bh_sed # load the ds (but only if this is our first passthrough and we pass in fname) if fname != None: if yt.__version__ == '4.0.dev0': ds = yt.load(fname) ds.index ad = ds.all_data() else: ds = yt.load(fname, bounding_box=bounding_box, over_refine_factor=cfg.par.oref, n_ref=cfg.par.n_ref) ds.index ad = ds.all_data() #if we're in the 4.x branch of yt, load up the octree for smoothing if yt.__version__ == '4.0.dev0': left = np.array([pos[0] for pos in bounding_box]) right = np.array([pos[1] for pos in bounding_box]) #octree = ds.octree(left, right, over_refine_factor=cfg.par.oref, n_ref=cfg.par.n_ref, force_build=True) octree = ds.octree(left, right, n_ref=cfg.par.n_ref) ds.parameters['octree'] = octree # for the metal fields have a few options since gadget can have different nomenclatures ad = ds.all_data() if ('PartType4', 'Metallicity_00') in ds.derived_field_list: try: ds.add_field(('starmetals'), function=_starmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('starmetals_He'), function=_starmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('starmetals_C'), function=_starmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('starmetals_N'), function=_starmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('starmetals_O'), function=_starmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('starmetals_Ne'), function=_starmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('starmetals_Mg'), function=_starmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('starmetals_Si'), function=_starmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('starmetals_S'), function=_starmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('starmetals_Ca'), function=_starmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('starmetals_Fe'), function=_starmetals_00, units="code_metallicity", particle_type=True) except: ds.add_field(('starmetals'), function=_starmetals_00, units="code_metallicity", particle_type=True) else: ds.add_field(('starmetals'), function=_starmetals, units="code_metallicity", particle_type=True) if ('PartType0', 'Metallicity_00') in ds.derived_field_list: ds.add_field(('gasmetals'), function=_gasmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('metaldens'), function=_metaldens_00, units="g/cm**3", particle_type=True) # we add this as part type 0 (a non-general name) as it gets # smoothed immediately and that's all we end up using downstream ds.add_field(('PartType0', 'metalmass'), function=_metalmass_00, units="g", particle_type=True) else: ds.add_field(('gasmetals'), function=_gasmetals, units="code_metallicity", particle_type=True) ds.add_field(('metaldens'), function=_metaldens, units="g/cm**3", particle_type=True) ds.add_field(('PartType0', 'metalmass'), function=_metalmass, units="g", particle_type=True) metalmass_fn = add_volume_weighted_smoothed_field("PartType0", "Coordinates", "Masses", "SmoothingLength", "Density", "metalmass", ds.field_info) if add_smoothed_quantities == True: ds.add_field(('metalsmoothedmasses'), function=_metalsmoothedmasses, units='code_metallicity', particle_type=True) # get the dust mass if cfg.par.dust_grid_type == 'dtm': ds.add_field(('dustmass'), function=_dustmass_dtm, units='code_mass', particle_type=True) if cfg.par.dust_grid_type == 'manual': #if ('PartType0', 'Dust_Masses') in ds.derived_field_list: ds.add_field(('dustmass'), function=_dustmass_manual, units='code_mass', particle_type=True) ds.add_deposited_particle_field(("PartType0", "Dust_Masses"), "sum") if add_smoothed_quantities == True: ds.add_field(('dustsmoothedmasses'), function=_dustsmoothedmasses, units='code_mass', particle_type=True) #if we have the Li, Narayanan & Dave 2019 Extreme Randomized Trees #dust model in place, create a field for these so that #dust_grid_gen can use these dust masses if cfg.par.dust_grid_type == 'li_ml': #get the dust to gas ratio ad = ds.all_data() li_ml_dgr = dgr_ert(ad["PartType0", "Metallicity_00"], ad["PartType0", "StarFormationRate"], ad["PartType0", "Masses"]) li_ml_dustmass = ((10.**li_ml_dgr) * ad["PartType0", "Masses"]).in_units('code_mass') #this is an icky way to pass this to the function for ds.add_field in the next line. but such is life. ds.parameters['li_ml_dustmass'] = li_ml_dustmass ds.add_field(('PartType0', 'li_ml_dustmass'), function=_li_ml_dustmass, units='code_mass', particle_type=True) ds.add_deposited_particle_field(("PartType0", "li_ml_dustmass"), "sum") if add_smoothed_quantities == True: ds.add_field(("li_ml_dustsmoothedmasses"), function=_li_ml_dustsmoothedmasses, units='code_mass', particle_type=True) ds.add_field(('starmasses'), function=_starmasses, units='g', particle_type=True) ds.add_field(('starcoordinates'), function=_starcoordinates, units='cm', particle_type=True) ds.add_field(('starformationtime'), function=_starformationtime, units='dimensionless', particle_type=True) ds.add_field(('stellarages'), function=_stellarages, units='Gyr', particle_type=True) if ('PartType2', 'Masses') in ds.derived_field_list: ds.add_field(('diskstarmasses'), function=_diskstarmasses, units='g', particle_type=True) ds.add_field(('diskstarcoordinates'), function=_diskstarcoordinates, units='cm', particle_type=True) if ('PartType3', 'Masses') in ds.derived_field_list: ds.add_field(('bulgestarmasses'), function=_bulgestarmasses, units='g', particle_type=True) ds.add_field(('bulgestarcoordinates'), function=_bulgestarcoordinates, units='cm', particle_type=True) if add_smoothed_quantities == True: ds.add_field(('starsmoothedmasses'), function=_starsmoothedmasses, units='g', particle_type=True) ds.add_field(('gasdensity'), function=_gasdensity, units='g/cm**3', particle_type=True) # Gas Coordinates need to be in Comoving/h as they'll get converted later. ds.add_field(('gascoordinates'), function=_gascoordinates, units='cm', particle_type=True) if add_smoothed_quantities == True: ds.add_field(('gassmootheddensity'), function=_gassmootheddensity, units='g/cm**3', particle_type=True) ds.add_field(('gassmoothedmetals'), function=_gassmoothedmetals, units='code_metallicity', particle_type=True) ds.add_field(('gassmoothedmasses'), function=_gassmoothedmasses, units='g', particle_type=True) ds.add_field(('gasmasses'), function=_gasmasses, units='g', particle_type=True) ds.add_field(('gasfh2'), function=_gasfh2, units='dimensionless', particle_type=True) ds.add_field(('gassfr'), function=_gassfr, units='g/s', particle_type=True) if cfg.par.BH_SED == True: if ('PartType5', 'BH_Mass') in ds.derived_field_list: nholes = len(ds.all_data()[('PartType5', 'BH_Mass')]) print("The number of black holes is:", nholes) if nholes > 0: if cfg.par.BH_model == 'Nenkova': from powderday.agn_models.nenkova import Nenkova2008 agn_spectrum = Nenkova2008( *cfg.par.nenkova_params).agn_spectrum else: from powderday.agn_models.hopkins import agn_spectrum if cfg.par.BH_var: from powderday.agn_models.hickox import vary_bhluminosity cfg.par.bhlfrac = vary_bhluminosity(nholes) ds.add_field(("bhluminosity"), function=_bhluminosity, units='erg/s', particle_type=True) ds.add_field(("bhcoordinates"), function=_bhcoordinates, units="cm", particle_type=True) ds.add_field(("bhnu"), function=_bhsed_nu, units='Hz', particle_type=True) ds.add_field(("bhsed"), function=_bhsed_sed, units="erg/s", particle_type=True) else: print('No black holes found (length of BH_Mass field is 0)') return ds
def setup_particle_fields(self, ptype): """ additional particle fields derived from those in snapshot. we also need to add the smoothed fields here b/c setup_fluid_fields is called before setup_particle_fields. """ smoothed_suffixes = ("_number_density", "_density", "_mass") # we add particle element fields for stars and gas #----------------------------------------------------- if ptype in self._add_elements: # this adds the particle element fields # X_density, X_mass, and X_number_density # where X is an item of self._elements. # X_fraction are defined in snapshot #----------------------------------------------- for s in self._elements: add_species_field_by_fraction(self, ptype, s, particle_type=True) # this needs to be called after the call to # add_species_field_by_fraction for some reason ... # not sure why yet. #------------------------------------------------------- if ptype == 'PartType0': ftype = 'gas' elif ptype == 'PartType1': ftype = 'dm' elif ptype == 'PartType2': ftype = 'PartType2' elif ptype == 'PartType3': ftype = 'PartType3' elif ptype == 'PartType4': ftype = 'star' elif ptype == 'PartType5': ftype = 'BH' elif ptype == 'all': ftype = 'all' super(OWLSFieldInfo, self).setup_particle_fields(ptype, num_neighbors=self._num_neighbors, ftype=ftype) # and now we add the smoothed versions for PartType0 #----------------------------------------------------- if ptype == 'PartType0': # we only add ion fields for gas. this takes some # time as the ion abundances have to be interpolated # from cloudy tables (optically thin) #----------------------------------------------------- # this defines the ion density on particles # X_density for all items in self._ions #----------------------------------------------- self.setup_gas_ion_density_particle_fields(ptype) # this adds the rest of the ion particle fields # X_fraction, X_mass, X_number_density #----------------------------------------------- for ion in self._ions: # construct yt name for ion #--------------------------------------------------- if ion[0:2].isalpha(): symbol = ion[0:2].capitalize() roman = int(ion[2:]) else: symbol = ion[0:1].capitalize() roman = int(ion[1:]) if (ptype, symbol + "_fraction") not in self.field_aliases: continue pstr = "_p" + str(roman - 1) yt_ion = symbol + pstr # add particle field #--------------------------------------------------- add_species_field_by_density(self, ptype, yt_ion, particle_type=True) # add smoothed ion fields #----------------------------------------------- for ion in self._ions: # construct yt name for ion #--------------------------------------------------- if ion[0:2].isalpha(): symbol = ion[0:2].capitalize() roman = int(ion[2:]) else: symbol = ion[0:1].capitalize() roman = int(ion[1:]) if (ptype, symbol + "_fraction") not in self.field_aliases: continue pstr = "_p" + str(roman - 1) yt_ion = symbol + pstr loaded = [] for sfx in smoothed_suffixes: fname = yt_ion + sfx fn = add_volume_weighted_smoothed_field( ptype, "particle_position", "particle_mass", "smoothing_length", "density", fname, self, self._num_neighbors) loaded += fn self.alias(("gas", fname), fn[0]) self._show_field_errors += loaded self.find_dependencies(loaded)
def gadget_field_add(fname, bounding_box=None, ds=None, starages=False): def _starcoordinates(field, data): return data[('PartType4', 'Coordinates')] def _starformationtime(field, data): return data[('PartType4', 'StellarFormationTime')] def _starmasses(field, data): return data[("PartType4", "Masses")] def _starmetals_00_romeel(field, data): ad = ds.all_data() metals = np.zeros(len(ad[("PartType4", "Metallicity_00")])) for i in range(0, 4): metals += ad[("PartType4", "Metallicity_0%s" % i)] #the metallicity in romeel/benopp simulations needs to be #multiplied by a metallicity factor of 0.0189/0.0147 as #stolen from bobby thompson's pygadgetreader metals *= 0.0189 / 0.0147 return data.ds.arr(metals, 'code_metallicity') def _diskstarcoordinates(field, data): return data[('PartType2', 'Coordinates')] def _diskstarmasses(field, data): return data[("PartType2", "Masses")] def _bulgestarcoordinates(field, data): return data[('PartType3', 'Coordinates')] def _bulgestarmasses(field, data): return data[("PartType3", "Masses")] def _gasdensity(field, data): return data[('PartType0', 'Density')] def _gasmetals_00_romeel(field, data): ad = ds.all_data() metals = np.zeros(len(ad[("PartType0", "Metallicity_00")])) for i in range(0, 4): metals += ad[("PartType0", "Metallicity_0%s" % i)] #the metallicity in romeel/benopp simulations needs to be #multiplied by a metallicity factor of 0.0189/0.0147 as #stolen from bobby thompson's pygadgetreader metals *= 0.0189 / 0.0147 return data.ds.arr(metals, 'code_metallicity') def _gascoordinates(field, data): return data[('PartType0', 'Coordinates')] def _gassmootheddensity(field, data): return data[("deposit", "PartType0_smoothed_density")] def _gassmoothedmetals(field, data): return data[('deposit', 'PartType0_smoothed_gasmetals')] def _gassmoothedmasses(field, data): return data[('deposit', 'PartType0_mass')] def _metaldens_00_romeel(field, data): return (data["PartType0", "Density"] * data["gasmetals"].value) def _metalmass_00_romeel(field, data): return (data["PartType0", "Masses"] * (data["gasmetals"].value)) def _metalsmoothedmasses(field, data): return (data[('deposit', 'PartType0_smoothed_metalmass')].value) def _stellarages(field, data): ad = data.ds.all_data() if data.ds.cosmological_simulation == False: #we assume that the romeel stellar ages are the same as #normal gadget for idealized simulations, but in yr. but #this could be totally wrong. simtime = data.ds.current_time.in_units('yr') simtime = simtime.value age = simtime - ad[( "starformationtime" )].value #yr (assumes that ad["starformationtime"] is in Myr for benopp/romeel Gadget) #make the minimum age 1 million years age[np.where(age < 1.e6)[0]] = 1.e6 print('\n--------------') print( '[SED_gen/star_list_gen: ] Idealized Galaxy Simulation Assumed: Simulation time is (Gyr): ', simtime) print('--------------\n') else: simtime = data.ds.current_time.in_units('Gyr') simtime = simtime.value age = ad["starformationtime"].value #yr #make the minimum age 1 million years if len(np.where(age < 1.e6)[0]) > 0: age[np.where(age < 1.e6)[0]] = 1.e6 print('\n--------------') print( '[SED_gen/star_list_gen: ] Cosmological Galaxy Simulation Assumed: Current age of Universe is (Assuming Planck13 Cosmology) is (Gyr): ', simtime) print('--------------\n') age = data.ds.arr(age, 'yr') age = age.in_units('Gyr') return age #load the ds if fname != None: ds = yt.load(fname, bounding_box=bounding_box, over_refine_factor=cfg.par.oref, n_ref=cfg.par.n_ref) ds.index ds.add_field(('gasmetals'), function=_gasmetals_00_romeel, units="code_metallicity", particle_type=True) ds.add_field(('starmetals'), function=_starmetals_00_romeel, units="code_metallicity", particle_type=True) ds.add_field(('metaldens'), function=_metaldens_00_romeel, units="g/cm**3", particle_type=True) ds.add_field(('PartType0', 'metalmass'), function=_metalmass_00_romeel, units="g", particle_type=True) #this is exactly the same as 'gasmetals' but in 'parttype0' #notation so we can project it with #add_volume_weighted_smoothed_field ds.add_field((('PartType0', 'gasmetals')), function=_gasmetals_00_romeel, units="code_metallicity", particle_type=True) metalmass_fn = add_volume_weighted_smoothed_field("PartType0", "Coordinates", "Masses", "SmoothingLength", "Density", "metalmass", ds.field_info) metallicity_smoothed_fn = add_volume_weighted_smoothed_field( "PartType0", "Coordinates", "Masses", "SmoothingLength", "Density", "gasmetals", ds.field_info) ds.add_field(('metalsmoothedmasses'), function=_metalsmoothedmasses, units='code_metallicity', particle_type=True) ds.add_field(('starmasses'), function=_starmasses, units='g', particle_type=True) ds.add_field(('starcoordinates'), function=_starcoordinates, units='cm', particle_type=True) ds.add_field(('starformationtime'), function=_starformationtime, units='dimensionless', particle_type=True) if ('PartType2', 'Masses') in ds.derived_field_list: ds.add_field(('diskstarmasses'), function=_diskstarmasses, units='g', particle_type=True) ds.add_field(('diskstarcoordinates'), function=_diskstarcoordinates, units='cm', particle_type=True) if ('PartType3', 'Masses') in ds.derived_field_list: ds.add_field(('bulgestarmasses'), function=_bulgestarmasses, units='g', particle_type=True) ds.add_field(('bulgestarcoordinates'), function=_bulgestarcoordinates, units='cm', particle_type=True) ds.add_field(('gasdensity'), function=_gasdensity, units='g/cm**3', particle_type=True) #Gas Coordinates need to be in Comoving/h as they'll get converted later. ds.add_field(('gascoordinates'), function=_gascoordinates, units='cm', particle_type=True) ds.add_field(('gassmootheddensity'), function=_gassmootheddensity, units='g/cm**3', particle_type=True) ds.add_field(('gassmoothedmetals'), function=_gassmoothedmetals, units='code_metallicity', particle_type=True) ds.add_field(('gassmoothedmasses'), function=_gassmoothedmasses, units='g', particle_type=True) if starages == True: ds.add_field(('stellarages'), function=_stellarages, units='Gyr', particle_type=True) return ds
def gadget_field_add(fname, bounding_box=None, ds=None, starages=False): def _starcoordinates(field, data): return data[('PartType4', 'Coordinates')] def _starformationtime(field, data): return data[('PartType4', 'StellarFormationTime')] def _starmasses(field, data): return data[("PartType4", "Masses")] def _starmetals_00_CS(field, data): ad = ds.all_data() starmass = ad[("PartType4", "Masses")].value metals = np.zeros(len(ad[("PartType4", "Metallicity_00")])) for i in range(1, 6): metals += ad[("PartType4", "Metallicity_0%s" % i)] #we avoid 6 because this is the hydrogen mass for i in range(7, 10): metals += ad[("PartType4", "Metallicity_0%s" % i)] for i in (10, 11): metals += ad[("PartType4", "Metallicity_%s" % i)] #the CS metals are actually masses in code units, so to get #metallicity, divide by particle gas mass in code units metals /= starmass return data.ds.arr(metals, 'code_metallicity') def _diskstarcoordinates(field, data): return data[('PartType2', 'Coordinates')] def _diskstarmasses(field, data): return data[("PartType2", "Masses")] def _bulgestarcoordinates(field, data): return data[('PartType3', 'Coordinates')] def _bulgestarmasses(field, data): return data[("PartType3", "Masses")] def _gasdensity(field, data): return data[('PartType0', 'Density')] def _gasmetals_00_CS(field, data): ad = ds.all_data() gasmass = ad[("PartType0", "Masses")].value metals = np.zeros(len(ad[("PartType0", "Metallicity_00")])) for i in range(1, 6): metals += ad[("PartType0", "Metallicity_0%s" % i)] #we avoid 6 because this is the hydrogen mass for i in range(7, 10): metals += ad[("PartType0", "Metallicity_0%s" % i)] for i in (10, 11): metals += ad[("PartType0", "Metallicity_%s" % i)] #the CS metals are actually masses in code units, so to get #metallicity, divide by particle gas mass in code units metals /= gasmass return data.ds.arr(metals, 'code_metallicity') def _gasmasses(field, data): return data[('PartType0', 'Masses')] def _gasfh2(field, data): try: return data[('PartType0', 'FractionH2')] except: return np.zeros(len(data[('PartType0', 'Masses')])) def _gassfr(field, data): return data[('PartType0', 'StarFormationRate')] def _gascoordinates(field, data): return data[('PartType0', 'Coordinates')] def _gassmootheddensity(field, data): return data[("deposit", "PartType0_smoothed_density")] def _gassmoothedmetals(field, data): return data[('deposit', 'PartType0_smoothed_gasmetals')] def _gassmoothedmasses(field, data): return data[('deposit', 'PartType0_mass')] def _metaldens_00_CS(field, data): return (data["PartType0", "Density"] * data["gasmetals"].value) def _metalmass_00_CS(field, data): return (data["PartType0", "Masses"] * (data["gasmetals"].value)) def _metalsmoothedmasses(field, data): return (data[('deposit', 'PartType0_smoothed_metalmass')].value) def _stellarages(field, data): ad = data.ds.all_data() if data.ds.cosmological_simulation == False: simtime = data.ds.current_time.in_units('Gyr') simtime = simtime.value age = simtime - ad[( "starformationtime" )].value #Gyr (assumes that ad["starformationtime"] is in Gyr for Gadget) #make the minimum age 1 million years age[np.where(age < 1.e-3)[0]] = 1.e-3 print('\n--------------') print( '[SED_gen/star_list_gen: ] Idealized Galaxy Simulation Assumed: Simulation time is (Gyr): ', simtime) print('--------------\n') else: simtime = Planck13.age(data.ds.current_redshift).to( u.Gyr).value #what is the age of the Universe right now? scalefactor = ad[("starformationtime")].value formation_z = (1. / scalefactor) - 1. formation_time = redshift_vectorized(formation_z) #drop the Gyr unit formation_time = np.asarray( [formation_time[i].value for i in range(len(formation_time))]) age = simtime - formation_time #make the minimum age 1 million years age[np.where(age < 1.e-3)[0]] = 1.e-3 print('\n--------------') print( '[SED_gen/star_list_gen: ] Cosmological Galaxy Simulation Assumed: Current age of Universe is (Assuming Planck13 Cosmology) is (Gyr): ', simtime) print('--------------\n') age = data.ds.arr(age, 'Gyr') return age def _starsmoothedmasses(field, data): return data[('deposit', 'PartType4_mass')] def _bhluminosity(field, data): ad = data.ds.all_data() mdot = ad[("PartType5", "BH_Mdot")] #give it a unit since usually these are dimensionless in yt mdot = data.ds.arr(mdot, "code_mass/code_time") c = yt.utilities.physical_constants.speed_of_light_cgs bhluminosity = (cfg.par.BH_eta * mdot * c**2.).in_units("erg/s") return bhluminosity def _bhcoordinates(field, data): return data["PartType5", "Coordinates"] def _bhsed_nu(field, data): bhluminosity = data["bhluminosity"] log_lum_lsun = np.log10(bhluminosity[0].in_units("Lsun")) nu, bhlum = agn_spectrum(log_lum_lsun) #the last 4 numbers aren't part of the SED nu = nu[0:-4] nu = 10.**nu nu = yt.YTArray(nu, "Hz") return nu def _bhsed_sed(field, data): bhluminosity = data["bhluminosity"] nholes = len(bhluminosity) #get len of nu just for the 0th hole so we know how long the vector is log_lum_lsun = np.log10(bhluminosity[0].in_units("Lsun")) nu, l_band_vec = agn_spectrum(log_lum_lsun) nu = nu[0:-4] n_nu = len(nu) bh_sed = np.zeros([nholes, n_nu]) for i in range(nholes): log_lum_lsun = np.log10(bhluminosity[i].in_units("Lsun")) nu, l_band_vec = agn_spectrum(log_lum_lsun) l_band_vec = 10.**l_band_vec l_band_vec = l_band_vec[0:-4] for l in range(len(l_band_vec)): l_band_vec[l] = data.ds.quan(l_band_vec[l], "erg/s") bh_sed[i, :] = l_band_vec bh_sed = yt.YTArray(bh_sed, "erg/s") return bh_sed #load the ds if fname != None: ds = yt.load(fname, bounding_box=bounding_box, over_refine_factor=cfg.par.oref, n_ref=cfg.par.n_ref) ds.index #------------------ #Munich Group Gadget Metallicity Fields based on Cecila Scannapieco's Metallicity Implementation #------------------ ds.add_field(('gasmetals'), function=_gasmetals_00_CS, units="code_metallicity", particle_type=True) ds.add_field(('starmetals'), function=_starmetals_00_CS, units="code_metallicity", particle_type=True) ds.add_field(('metaldens'), function=_metaldens_00_CS, units="g/cm**3", particle_type=True) ds.add_field(('PartType0', 'metalmass'), function=_metalmass_00_CS, units="g", particle_type=True) #this is exactly the same as 'gasmetals' but in 'parttype0' #notation so we can project it with #add_volume_weighted_smoothed_field ds.add_field((('PartType0', 'gasmetals')), function=_gasmetals_00_CS, units="code_metallicity", particle_type=True) metalmass_fn = add_volume_weighted_smoothed_field("PartType0", "Coordinates", "Masses", "SmoothingLength", "Density", "metalmass", ds.field_info) metallicity_smoothed_fn = add_volume_weighted_smoothed_field( "PartType0", "Coordinates", "Masses", "SmoothingLength", "Density", "gasmetals", ds.field_info) ds.add_field(('metalsmoothedmasses'), function=_metalsmoothedmasses, units='code_metallicity', particle_type=True) ds.add_field(('starmasses'), function=_starmasses, units='g', particle_type=True) ds.add_field(('starcoordinates'), function=_starcoordinates, units='cm', particle_type=True) ds.add_field(('starformationtime'), function=_starformationtime, units='dimensionless', particle_type=True) ds.add_field(('starsmoothedmasses'), function=_starsmoothedmasses, units='g', particle_type=True) if ('PartType2', 'Masses') in ds.derived_field_list: ds.add_field(('diskstarmasses'), function=_diskstarmasses, units='g', particle_type=True) ds.add_field(('diskstarcoordinates'), function=_diskstarcoordinates, units='cm', particle_type=True) if ('PartType3', 'Masses') in ds.derived_field_list: ds.add_field(('bulgestarmasses'), function=_bulgestarmasses, units='g', particle_type=True) ds.add_field(('bulgestarcoordinates'), function=_bulgestarcoordinates, units='cm', particle_type=True) ds.add_field(('gasdensity'), function=_gasdensity, units='g/cm**3', particle_type=True) #Gas Coordinates need to be in Comoving/h as they'll get converted later. ds.add_field(('gascoordinates'), function=_gascoordinates, units='cm', particle_type=True) ds.add_field(('gassmootheddensity'), function=_gassmootheddensity, units='g/cm**3', particle_type=True) ds.add_field(('gassmoothedmetals'), function=_gassmoothedmetals, units='code_metallicity', particle_type=True) ds.add_field(('gassmoothedmasses'), function=_gassmoothedmasses, units='g', particle_type=True) ds.add_field(('gasmasses'), function=_gasmasses, units='g', particle_type=True) ds.add_field(('gasfh2'), function=_gasfh2, units='dimensionless', particle_type=True) ds.add_field(('gassfr'), function=_gassfr, units='g/s', particle_type=True) if cfg.par.BH_SED == True: try: if len(ds.all_data()[('PartType5', 'BH_Mass')]) > 0: if cfg.par.BH_model == 'Nenkova': from agn_models.nenkova import Nenkova2008 try: model = Nenkova2008(cfg.par.nenkova_params) except: model = Nenkova2008 agn_spectrum = model.agn_spectrum else: from agn_models.hopkins import agn_spectrum ds.add_field(("bhluminosity"), function=_bhluminosity, units='erg/s', particle_type=True) ds.add_field(("bhcoordinates"), function=_bhcoordinates, units="cm", particle_type=True) ds.add_field(("bhnu"), function=_bhsed_nu, units='Hz', particle_type=True) ds.add_field(("bhsed"), function=_bhsed_sed, units="erg/s", particle_type=True) else: print('No black holes found (length of BH_Mass field is 0)') except: print('Unable to find field "BH_Mass" in snapshot. Skipping.') if starages == True: ds.add_field(('stellarages'), function=_stellarages, units='Gyr', particle_type=True) return ds
pf.h fig = plt.figure() grid = AxesGrid(fig, (0.01, 0.07, 0.45, 0.91), nrows_ncols=(3, 1), axes_pad=0.02, add_all=True, share_all=True, label_mode="1", cbar_mode="single", cbar_location="right", cbar_size="1.5%", cbar_pad="0%") fn = add_volume_weighted_smoothed_field("Gas", "Coordinates", "particle_mass", "SmoothingLength", "density", "density", pf.field_info) pf.field_info.alias(("gas", "density"), fn[0]) # Let's find the center to keep the galaxy at the center of all the images. v, center = pf.h.find_max(("gas", "density")) # The following makes a 1x3 column of a field along all 3 axes with a horizontal colorbar at the bottom #fig, axes, colorbars = get_multi_plot( 1, 3, colorbar='horizontal', bw = 4) for ax in range(3): p = ProjectionPlot(pf, ax, ("gas", "density"), center=center, weight_field=None) p.set_zlim(("gas", "density"), 1e-6, 1e-1)
density = data['PartType0', 'Density'] Z = data['PartType0', 'metallicity'] return density * Z # Add it to the dataset. ds.add_field(('PartType0', 'metal_density'), function=_metal_density, units="g/cm**3", particle_type=True) # Add the corresponding smoothed field to the dataset. from yt.fields.particle_fields import add_volume_weighted_smoothed_field add_volume_weighted_smoothed_field('PartType0', 'Coordinates', 'Masses', 'SmoothingLength', 'Density', 'metal_density', ds.field_info) # Define the region where the disk galaxy is. (See the Gadget notebook for # details. Here I make the box a little larger than needed to eliminate the # margin effect.) center = ds.arr([31996, 31474, 28970], "code_length") box_size = ds.quan(250, "code_length") left_edge = center - box_size / 2 * 1.1 right_edge = center + box_size / 2 * 1.1 box = ds.box(left_edge=left_edge, right_edge=right_edge) # And make a projection plot! yt.ProjectionPlot(ds, 'z', ('deposit', 'PartType0_smoothed_metal_density'), center=center,
pf.h fig = plt.figure() grid = AxesGrid(fig, (0.01,0.07,0.45,0.91), nrows_ncols = (3, 1), axes_pad = 0.02, add_all = True, share_all = True, label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "1.5%", cbar_pad = "0%") fn = add_volume_weighted_smoothed_field("Gas", "Coordinates", "particle_mass", "SmoothingLength", "density", "density", pf.field_info) pf.field_info.alias(("gas", "density"), fn[0]) # Let's find the center to keep the galaxy at the center of all the images. v, center = pf.h.find_max(("gas", "density")) # The following makes a 1x3 column of a field along all 3 axes with a horizontal colorbar at the bottom #fig, axes, colorbars = get_multi_plot( 1, 3, colorbar='horizontal', bw = 4) for ax in range(3): p = ProjectionPlot(pf, ax, ("gas", "density"), center = center, weight_field = None) p.set_zlim(("gas", "density"), 1e-6, 1e-1) plot = p.plots[("gas", "density")] plot.figure = fig plot.axes = grid[ax].axes
cblabel = r'${\rm T \;[K]}$' px_frb = px.data_source.to_frb((newboxsize, "kpc"), 128) px_dens = np.array(px_frb[ ('gas', 'temperature')]) cbcolor = 'hot' if (wanted == 'Bfield'): def _Benergydensityfun(field, data): Bf = data['PartType0', 'MagneticField'].in_cgs() print 'Bf.shape', Bf.shape Bdensity = (Bf[:,0]*Bf[:,0]+Bf[:,1]*Bf[:,1]+Bf[:,2]*Bf[:,2])/8./np.pi return Bdensity ds.add_field(('PartType0', 'Benergydensity'), function=_Benergydensityfun, units="erg/cm**3", particle_type=True, display_name="Benergydensity") add_volume_weighted_smoothed_field('PartType0', 'Coordinates', 'Masses', 'SmoothingLength', 'Density', 'Benergydensity', ds.field_info) ad2= ds.region(center=center, left_edge=left_edge, right_edge=right_edge) if mode == 'projected': px = yt.ProjectionPlot(ds, projectionaxis, ('deposit', 'PartType0_smoothed_Benergydensity'), center=center, width=new_box_size, north_vector=north_vector) if mode == 'Slice': if rotface==1: px = yt.OffAxisSlicePlot(ds, projectionaxis, ('deposit', 'PartType0_smoothed_Benergydensity'),\ center=center, width=new_box_size, north_vector=north_vector) else: px = yt.SlicePlot(ds, projectionaxis, ('deposit', 'PartType0_smoothed_Benergydensity'), center=center, width=new_box_size) px_frb = px.data_source.to_frb((newboxsize, "kpc"), 128) px_dens = np.array(px_frb[('deposit', 'PartType0_smoothed_Benergydensity')]) cbcolor = 'RdPu' cblabel = r'${\rm B\;energy\;[ erg/cm^3}]$'
def gadget_field_add(fname, bounding_box=None, ds=None, starages=False): def _starmetals_00(field, data): return data[('PartType4', 'Metallicity_00')] def _starmetals(field, data): return data[('PartType4', 'Metallicity')] def _starcoordinates(field, data): return data[('PartType4', 'Coordinates')] def _starformationtime(field, data): return data[('PartType4', 'StellarFormationTime')] def _starmasses(field, data): return data[("PartType4", "Masses")] def _diskstarcoordinates(field, data): return data[('PartType2', 'Coordinates')] def _diskstarmasses(field, data): return data[("PartType2", "Masses")] def _bulgestarcoordinates(field, data): return data[('PartType3', 'Coordinates')] def _bulgestarmasses(field, data): return data[("PartType3", "Masses")] def _gasdensity(field, data): return data[('PartType0', 'Density')] def _gasmetals_00(field, data): return data[('PartType0', 'Metallicity_00')] def _gasmetals(field, data): return data[('PartType0', 'Metallicity')] def _gascoordinates(field, data): return data[('PartType0', 'Coordinates')] def _gasmasses(field, data): return data[('PartType0', 'Masses')] def _gasfh2(field, data): try: return data[('PartType0', 'FractionH2')] except: return data[('PartType0', 'Masses')] * 0. def _gassfr(field, data): return data[('PartType0', 'StarFormationRate')] def _gassmootheddensity(field, data): return data[("deposit", "PartType0_smoothed_density")] def _gassmoothedmetals(field, data): return data[("deposit", "PartType0_smoothed_metallicity")] def _gassmoothedmasses(field, data): return data[('deposit', 'PartType0_mass')] def _metaldens_00(field, data): return (data["PartType0", "Density"] * data["PartType0", "Metallicity_00"]) def _metaldens(field, data): return (data["PartType0", "Density"] * data["PartType0", "Metallicity"]) def _metalmass_00(field, data): return (data["PartType0", "Masses"] * (data["PartType0", "Metallicity_00"].value)) def _metalmass(field, data): return (data["PartType0", "Masses"] * (data["PartType0", "Metallicity"].value)) def _metalsmoothedmasses(field, data): return (data[('deposit', 'PartType0_smoothed_metalmass')].value) def _dustmass(field, data): return (data.ds.arr(data[("PartType0", "Dust_Masses")].value, 'code_mass')) def _dustsmoothedmasses(field, data): return (data.ds.arr( data[("deposit", "PartType0_sum_Dust_Masses")].value, 'code_mass')) def _stellarages(field, data): ad = data.ds.all_data() if data.ds.cosmological_simulation == False: simtime = data.ds.current_time.in_units('Gyr') simtime = simtime.value # Gyr (assumes that ad["starformationtime"] is in Gyr for Gadget) age = simtime - ad[("starformationtime")].value # make the minimum age 1 million years age[np.where(age < 1.e-3)[0]] = 1.e-3 print('\n--------------') print( '[SED_gen/star_list_gen: ] Idealized Galaxy Simulation Assumed: Simulation time is (Gyr): ', simtime) print('--------------\n') else: yt_cosmo = yt.utilities.cosmology.Cosmology( hubble_constant=data.ds.hubble_constant, omega_matter=data.ds.omega_matter, omega_lambda=data.ds.omega_lambda) simtime = yt_cosmo.t_from_z(ds.current_redshift).in_units( 'Gyr').value # Current age of the universe scalefactor = ad[("starformationtime")].value formation_z = (1. / scalefactor) - 1. formation_time = yt_cosmo.t_from_z(formation_z).in_units( 'Gyr').value age = simtime - formation_time # Minimum age is set to 1 Myr (FSPS doesn't work properly for ages below 1 Myr) age[np.where(age < 1.e-3)[0]] = 1.e-3 print('\n--------------') print( '[SED_gen/star_list_gen: ] Cosmological Galaxy Simulation Assumed: Current age of Universe is (Gyr): ', simtime) print('--------------\n') age = data.ds.arr(age, 'Gyr') return age def _starsmoothedmasses(field, data): return data[('deposit', 'PartType4_mass')] def _bhluminosity(field, data): ad = data.ds.all_data() mdot = ad[("PartType5", "BH_Mdot")] # give it a unit since usually these are dimensionless in yt mdot = data.ds.arr(mdot, "code_mass/code_time") c = yt.utilities.physical_constants.speed_of_light_cgs bhluminosity = (cfg.par.BH_eta * mdot * c**2.).in_units("erg/s") if cfg.par.BH_var: return bhluminosity * cfg.par.bhlfrac else: return bhluminosity def _bhcoordinates(field, data): return data["PartType5", "Coordinates"] def _bhsed_nu(field, data): bhluminosity = data["bhluminosity"] log_lum_lsun = np.log10(bhluminosity[0].in_units("Lsun")) nu, bhlum = agn_spectrum(log_lum_lsun) # the last 4 numbers aren't part of the SED nu = nu[0:-4] nu = 10.**nu nu = yt.YTArray(nu, "Hz") return nu def _bhsed_sed(field, data): bhluminosity = data["bhluminosity"] nholes = len(bhluminosity) # get len of nu just for the 0th hole so we know how long the vector is log_lum_lsun = np.log10(bhluminosity[0].in_units("Lsun")) nu, l_band_vec = agn_spectrum(log_lum_lsun) nu = nu[0:-4] n_nu = len(nu) bh_sed = np.zeros([nholes, n_nu]) for i in range(nholes): log_lum_lsun = np.log10(bhluminosity[i].in_units("Lsun")) nu, l_band_vec = agn_spectrum(log_lum_lsun) l_band_vec = 10.**l_band_vec l_band_vec = l_band_vec[0:-4] for l in range(len(l_band_vec)): l_band_vec[l] = data.ds.quan(l_band_vec[l], "erg/s") bh_sed[i, :] = l_band_vec bh_sed = yt.YTArray(bh_sed, "erg/s") return bh_sed # load the ds if fname != None: ds = yt.load(fname, bounding_box=bounding_box, over_refine_factor=cfg.par.oref, n_ref=cfg.par.n_ref) ds.index ad = ds.all_data() # for the metal fields have a few options since gadget can have different nomenclatures if ('PartType4', 'Metallicity_00') in ds.derived_field_list: ds.add_field(('starmetals'), function=_starmetals_00, units="code_metallicity", particle_type=True) else: ds.add_field(('starmetals'), function=_starmetals, units="code_metallicity", particle_type=True) if ('PartType0', 'Metallicity_00') in ds.derived_field_list: ds.add_field(('gasmetals'), function=_gasmetals_00, units="code_metallicity", particle_type=True) ds.add_field(('metaldens'), function=_metaldens_00, units="g/cm**3", particle_type=True) # we add this as part type 0 (a non-general name) as it gets # smoothed immediately and that's all we end up using downstream ds.add_field(('PartType0', 'metalmass'), function=_metalmass_00, units="g", particle_type=True) else: ds.add_field(('gasmetals'), function=_gasmetals, units="code_metallicity", particle_type=True) ds.add_field(('metaldens'), function=_metaldens, units="g/cm**3", particle_type=True) ds.add_field(('PartType0', 'metalmass'), function=_metalmass, units="g", particle_type=True) metalmass_fn = add_volume_weighted_smoothed_field("PartType0", "Coordinates", "Masses", "SmoothingLength", "Density", "metalmass", ds.field_info) ds.add_field(('metalsmoothedmasses'), function=_metalsmoothedmasses, units='code_metallicity', particle_type=True) # get the dust mass if ('PartType0', 'Dust_Masses') in ds.derived_field_list: ds.add_field(('dustmass'), function=_dustmass, units='code_mass', particle_type=True) ds.add_deposited_particle_field(("PartType0", "Dust_Masses"), "sum") ds.add_field(('dustsmoothedmasses'), function=_dustsmoothedmasses, units='code_mass', particle_type=True) ds.add_field(('starmasses'), function=_starmasses, units='g', particle_type=True) ds.add_field(('starcoordinates'), function=_starcoordinates, units='cm', particle_type=True) ds.add_field(('starformationtime'), function=_starformationtime, units='dimensionless', particle_type=True) if ('PartType2', 'Masses') in ds.derived_field_list: ds.add_field(('diskstarmasses'), function=_diskstarmasses, units='g', particle_type=True) ds.add_field(('diskstarcoordinates'), function=_diskstarcoordinates, units='cm', particle_type=True) if ('PartType3', 'Masses') in ds.derived_field_list: ds.add_field(('bulgestarmasses'), function=_bulgestarmasses, units='g', particle_type=True) ds.add_field(('bulgestarcoordinates'), function=_bulgestarcoordinates, units='cm', particle_type=True) ds.add_field(('starsmoothedmasses'), function=_starsmoothedmasses, units='g', particle_type=True) ds.add_field(('gasdensity'), function=_gasdensity, units='g/cm**3', particle_type=True) # Gas Coordinates need to be in Comoving/h as they'll get converted later. ds.add_field(('gascoordinates'), function=_gascoordinates, units='cm', particle_type=True) ds.add_field(('gassmootheddensity'), function=_gassmootheddensity, units='g/cm**3', particle_type=True) ds.add_field(('gassmoothedmetals'), function=_gassmoothedmetals, units='code_metallicity', particle_type=True) ds.add_field(('gassmoothedmasses'), function=_gassmoothedmasses, units='g', particle_type=True) ds.add_field(('gasmasses'), function=_gasmasses, units='g', particle_type=True) ds.add_field(('gasfh2'), function=_gasfh2, units='dimensionless', particle_type=True) ds.add_field(('gassfr'), function=_gassfr, units='g/s', particle_type=True) if cfg.par.BH_SED == True: try: nholes = len(ds.all_data()[('PartType5', 'BH_Mass')]) if nholes > 0: if cfg.par.BH_model == 'Nenkova': from powderday.agn_models.nenkova import Nenkova2008 try: model = Nenkova2008(cfg.par.nenkova_params) except: model = Nenkova2008 agn_spectrum = model.agn_spectrum else: from powderday.agn_models.hopkins import agn_spectrum if cfg.par.BH_var: from powderday.agn_models.hickox import vary_bhluminosity cfg.par.bhlfrac = vary_bhluminosity(nholes) ds.add_field(("bhluminosity"), function=_bhluminosity, units='erg/s', particle_type=True) ds.add_field(("bhcoordinates"), function=_bhcoordinates, units="cm", particle_type=True) ds.add_field(("bhnu"), function=_bhsed_nu, units='Hz', particle_type=True) ds.add_field(("bhsed"), function=_bhsed_sed, units="erg/s", particle_type=True) else: print('No black holes found (length of BH_Mass field is 0)') except: print('Unable to find field "BH_Mass" in snapshot. Skipping.') if starages == True: ds.add_field(('stellarages'), function=_stellarages, units='Gyr', particle_type=True) return ds
def setup_particle_fields(self, ptype): """ additional particle fields derived from those in snapshot. we also need to add the smoothed fields here b/c setup_fluid_fields is called before setup_particle_fields. """ smoothed_suffixes = ("_number_density", "_density", "_mass") # we add particle element fields for stars and gas #----------------------------------------------------- if ptype in self._add_elements: # this adds the particle element fields # X_density, X_mass, and X_number_density # where X is an item of self._elements. # X_fraction are defined in snapshot #----------------------------------------------- for s in self._elements: add_species_field_by_fraction(self, ptype, s, particle_type=True) # this needs to be called after the call to # add_species_field_by_fraction for some reason ... # not sure why yet. #------------------------------------------------------- if ptype == 'PartType0': ftype='gas' elif ptype == 'PartType1': ftype='dm' elif ptype == 'PartType2': ftype='PartType2' elif ptype == 'PartType3': ftype='PartType3' elif ptype == 'PartType4': ftype='star' elif ptype == 'PartType5': ftype='BH' elif ptype == 'all': ftype='all' super(OWLSFieldInfo,self).setup_particle_fields( ptype, num_neighbors=self._num_neighbors, ftype=ftype) # and now we add the smoothed versions for PartType0 #----------------------------------------------------- if ptype == 'PartType0': # we only add ion fields for gas. this takes some # time as the ion abundances have to be interpolated # from cloudy tables (optically thin) #----------------------------------------------------- # this defines the ion density on particles # X_density for all items in self._ions #----------------------------------------------- self.setup_gas_ion_density_particle_fields( ptype ) # this adds the rest of the ion particle fields # X_fraction, X_mass, X_number_density #----------------------------------------------- for ion in self._ions: # construct yt name for ion #--------------------------------------------------- if ion[0:2].isalpha(): symbol = ion[0:2].capitalize() roman = int(ion[2:]) else: symbol = ion[0:1].capitalize() roman = int(ion[1:]) pstr = "_p" + str(roman-1) yt_ion = symbol + pstr # add particle field #--------------------------------------------------- add_species_field_by_density(self, ptype, yt_ion, particle_type=True) # add smoothed ion fields #----------------------------------------------- for ion in self._ions: # construct yt name for ion #--------------------------------------------------- if ion[0:2].isalpha(): symbol = ion[0:2].capitalize() roman = int(ion[2:]) else: symbol = ion[0:1].capitalize() roman = int(ion[1:]) pstr = "_p" + str(roman-1) yt_ion = symbol + pstr loaded = [] for sfx in smoothed_suffixes: fname = yt_ion + sfx fn = add_volume_weighted_smoothed_field( ptype, "particle_position", "particle_mass", "smoothing_length", "density", fname, self, self._num_neighbors) loaded += fn self.alias(("gas", fname), fn[0]) self._show_field_errors += loaded self.find_dependencies(loaded)