def _write_attrib(obj_list, k, v, hd): #print('obj_list: ',dir(obj_list)) #print('k: ',k) #print('v: ', v) unit = False if isinstance(v, YTQuantity): data = [getattr(i, k).d for i in obj_list] unit = True elif isinstance(v, YTArray): if np.shape(v)[0] == 3: data = np.vstack([getattr(i, k).d for i in obj_list]) else: data = [getattr(i, k).d for i in obj_list] unit = True elif isinstance(v, np.ndarray) and np.shape(v)[0] == 3 and 'list' not in k: try: data = np.vstack([getattr(i, k) for i in obj_list]) except: mylog.warning('Saver unable to stack: %s %s %s', k, v, np.shape(v)) return elif isinstance(v, (int, float, bool, np.number)): data = [getattr(i, k) for i in obj_list] else: return _write_dataset(k, data, hd) if unit: hd[k].attrs.create('unit', str(v.units).encode('utf8'))
def set_field(self, name, value): """ Set a field with name *name* to value *value*, which is a YTArray. The array will be checked to make sure that it has the appropriate size. """ if not isinstance(value, YTArray): raise TypeError("value needs to be a YTArray") if len(value) == self.num_elements: if name in self.fields: mylog.warning("Overwriting field %s." % name) self.fields[name] = value else: raise ValueError("The length of the array needs to be %d elements!" % self.num_elements)
def setup_fluid_fields(self): setup_magnetic_field_aliases(self, "amrvac", [f"mag{ax}" for ax in "xyz"]) self._setup_velocity_fields() # gas velocities self._setup_dust_fields() # dust derived fields (including velocities) # fields with nested dependencies are defined thereafter # by increasing level of complexity us = self.ds.unit_system def _kinetic_energy_density(field, data): # devnote : have a look at issue 1301 return 0.5 * data["gas", "density"] * data["gas", "velocity_magnitude"]**2 self.add_field( ("gas", "kinetic_energy_density"), function=_kinetic_energy_density, units=us["density"] * us["velocity"]**2, dimensions=dimensions.density * dimensions.velocity**2, sampling_type="cell", ) # magnetic energy density if ("amrvac", "b1") in self.field_list: def _magnetic_energy_density(field, data): emag = 0.5 * data["gas", "magnetic_1"]**2 for idim in "23": if not ("amrvac", f"b{idim}") in self.field_list: break emag += 0.5 * data["gas", f"magnetic_{idim}"]**2 # in AMRVAC the magnetic field is defined in units where mu0 = 1, # such that # Emag = 0.5*B**2 instead of Emag = 0.5*B**2 / mu0 # To correctly transform the dimensionality from gauss**2 -> rho*v**2, # we have to take mu0 into account. If we divide here, units when adding # the field should be us["density"]*us["velocity"]**2. # If not, they should be us["magnetic_field"]**2 and division should # happen elsewhere. emag /= 4 * np.pi # divided by mu0 = 4pi in cgs, # yt handles 'mks' and 'code' unit systems internally. return emag self.add_field( ("gas", "magnetic_energy_density"), function=_magnetic_energy_density, units=us["density"] * us["velocity"]**2, dimensions=dimensions.density * dimensions.velocity**2, sampling_type="cell", ) # Adding the thermal pressure field. # In AMRVAC we have multiple physics possibilities: # - if HD/MHD + energy equation P = (gamma-1)*(e - ekin (- emag)) for (M)HD # - if HD/MHD but solve_internal_e is true in parfile, P = (gamma-1)*e for both # - if (m)hd_energy is false in parfile (isothermal), P = c_adiab * rho**gamma def _full_thermal_pressure_HD(field, data): # energy density and pressure are actually expressed in the same unit pthermal = (data.ds.gamma - 1) * (data["gas", "energy_density"] - data["gas", "kinetic_energy_density"]) return pthermal def _full_thermal_pressure_MHD(field, data): pthermal = ( _full_thermal_pressure_HD(field, data) - (data.ds.gamma - 1) * data["gas", "magnetic_energy_density"]) return pthermal def _polytropic_thermal_pressure(field, data): return (data.ds.gamma - 1) * data["gas", "energy_density"] def _adiabatic_thermal_pressure(field, data): return data.ds._c_adiab * data["gas", "density"]**data.ds.gamma pressure_recipe = None if ("amrvac", "e") in self.field_list: if self.ds._e_is_internal: pressure_recipe = _polytropic_thermal_pressure mylog.info("Using polytropic EoS for thermal pressure.") elif ("amrvac", "b1") in self.field_list: pressure_recipe = _full_thermal_pressure_MHD mylog.info("Using full MHD energy for thermal pressure.") else: pressure_recipe = _full_thermal_pressure_HD mylog.info("Using full HD energy for thermal pressure.") elif self.ds._c_adiab is not None: pressure_recipe = _adiabatic_thermal_pressure mylog.info( "Using adiabatic EoS for thermal pressure (isothermal).") mylog.warning("If you used usr_set_pthermal you should " "redefine the thermal_pressure field.") if pressure_recipe is not None: self.add_field( ("gas", "thermal_pressure"), function=pressure_recipe, units=us["density"] * us["velocity"]**2, dimensions=dimensions.density * dimensions.velocity**2, sampling_type="cell", ) # sound speed and temperature depend on thermal pressure def _sound_speed(field, data): return np.sqrt(data.ds.gamma * data["gas", "thermal_pressure"] / data["gas", "density"]) self.add_field( ("gas", "sound_speed"), function=_sound_speed, units=us["velocity"], dimensions=dimensions.velocity, sampling_type="cell", ) else: mylog.warning( "e not found and no parfile passed, can not set thermal_pressure." )
def save(obj, filename='test.hdf5'): """Function to save a CAESAR file to disk. Parameters ---------- obj : :class:`main.CAESAR` Main caesar object to save. filename : str, optional Filename of the output file. Examples -------- >>> obj.save('output.hdf5') """ from yt.funcs import mylog if os.path.isfile(filename): mylog.warning('%s already present, overwriting!' % filename) os.remove(filename) mylog.info('Writing %s' % filename) outfile = h5py.File(filename, 'w') outfile.attrs.create('caesar', 315) unit_registry = obj.yt_dataset.unit_registry.to_json() outfile.attrs.create('unit_registry_json', unit_registry.encode('utf8')) serialize_global_attribs(obj, outfile) obj.simulation._serialize(obj, outfile) if hasattr(obj, 'halos') and obj.nhalos > 0: hd = outfile.create_group('halo_data') hdd = hd.create_group('lists') hddd = hd.create_group('dicts') # gather index_lists = ['dmlist'] if 'gas' in obj.data_manager.ptypes: index_lists.append('glist') if 'star' in obj.data_manager.ptypes: index_lists.extend(['slist', 'galaxy_index_list']) if 'dm2' in obj.data_manager.ptypes: index_lists.append('dm2list') if 'dm3' in obj.data_manager.ptypes: index_lists.append('dm3list') if obj.data_manager.blackholes: index_lists.append('bhlist') if obj.data_manager.dust: index_lists.append('dlist') #write for vals in index_lists: serialize_list(obj.halos, vals, hdd) serialize_attributes(obj.halos, hd, hddd) if hasattr(obj, 'galaxies') and obj.ngalaxies > 0: hd = outfile.create_group('galaxy_data') hdd = hd.create_group('lists') hddd = hd.create_group('dicts') # gather index_lists = ['glist', 'slist', 'cloud_index_list'] if obj.data_manager.blackholes: index_lists.append('bhlist') if obj.data_manager.dust: index_lists.append('dlist') # write for vals in index_lists: serialize_list(obj.galaxies, vals, hdd) serialize_attributes(obj.galaxies, hd, hddd) if hasattr(obj, 'clouds') and obj.nclouds > 0: hd = outfile.create_group('cloud_data') hdd = hd.create_group('lists') hddd = hd.create_group('dicts') # gather index_lists = ['glist'] # write for vals in index_lists: serialize_list(obj.clouds, vals, hdd) serialize_attributes(obj.clouds, hd, hddd) if hasattr(obj, 'global_particle_lists'): hd = outfile.create_group('global_lists') # gather global_index_lists = [ 'halo_dmlist', 'halo_glist', 'halo_slist', 'galaxy_glist', 'galaxy_slist', 'cloud_glist' ] if obj.data_manager.blackholes: global_index_lists.extend(['halo_bhlist', 'galaxy_bhlist']) if obj.data_manager.dust: global_index_lists.extend(['halo_dlist', 'galaxy_dlist']) # write for vals in global_index_lists: check_and_write_dataset(obj.global_particle_lists, vals, hd) outfile.close()
def setup_fluid_fields(self): def _v1(field, data): return data["gas", "moment_1"] / data["gas", "density"] def _v2(field, data): return data["gas", "moment_2"] / data["gas", "density"] def _v3(field, data): return data["gas", "moment_3"] / data["gas", "density"] us = self.ds.unit_system aliases = direction_aliases[self.ds.geometry] for idir, alias, func in zip("123", aliases, (_v1, _v2, _v3)): if not ("amrvac", "m%s" % idir) in self.field_list: break self.add_field(("gas", "velocity_%s" % alias), function=func, units=us['velocity'], dimensions=dimensions.velocity, sampling_type="cell") self.alias(("gas", "velocity_%s" % idir), ("gas", "velocity_%s" % alias), units=us["velocity"]) self.alias(("gas", "moment_%s" % alias), ("gas", "moment_%s" % idir), units=us["density"] * us["velocity"]) setup_magnetic_field_aliases(self, "amrvac", ["mag%s" % ax for ax in "xyz"]) # fields with nested dependencies are defined thereafter by increasing level of complexity # kinetic pressure is given by 0.5 * rho * v**2 def _kinetic_energy_density(field, data): # devnote : have a look at issue 1301 return 0.5 * data['gas', 'density'] * data['gas', 'velocity_magnitude']**2 self.add_field(("gas", "kinetic_energy_density"), function=_kinetic_energy_density, units=us["density"] * us["velocity"]**2, dimensions=dimensions.density * dimensions.velocity**2, sampling_type="cell") # magnetic energy density if ('amrvac', 'b1') in self.field_list: def _magnetic_energy_density(field, data): emag = 0.5 * data['gas', 'magnetic_1']**2 for idim in '23': if not ('amrvac', 'b%s' % idim) in self.field_list: break emag += 0.5 * data['gas', 'magnetic_%s' % idim]**2 # important note: in AMRVAC the magnetic field is defined in units where mu0 = 1, such that # Emag = 0.5*B**2 instead of Emag = 0.5*B**2 / mu0 # To correctly transform the dimensionality from gauss**2 -> rho*v**2, we have to take mu0 into account. # If we divide here, units when adding the field should be us["density"]*us["velocity"]**2 # If not, they should be us["magnetic_field"]**2 and division should happen elsewhere. emag /= 4 * np.pi # divided by mu0 = 4pi in cgs, yt handles 'mks' and 'code' unit systems internally. return emag self.add_field( ('gas', 'magnetic_energy_density'), function=_magnetic_energy_density, units=us["density"] * us["velocity"]**2, dimensions=dimensions.density * dimensions.velocity**2, sampling_type='cell') # Adding the thermal pressure field. # In AMRVAC we have multiple physics possibilities: # - if HD/MHD + energy equation, pressure is (gamma-1)*(e - ekin (- emag)) for (M)HD # - if HD/MHD but solve_internal_e is true in parfile, pressure is (gamma-1)*e for both # - if (m)hd_energy is false in parfile (isothermal), pressure is c_adiab * rho**gamma def _full_thermal_pressure_HD(field, data): # important note : energy density and pressure are actually expressed in the same unit pthermal = (data.ds.gamma - 1) * (data['gas', 'energy_density'] - data['gas', 'kinetic_energy_density']) return pthermal def _full_thermal_pressure_MHD(field, data): pthermal = _full_thermal_pressure_HD(field, data) \ - (data.ds.gamma - 1) * data["gas", "magnetic_energy_density"] return pthermal def _polytropic_thermal_pressure(field, data): return (data.ds.gamma - 1) * data['gas', 'energy_density'] def _adiabatic_thermal_pressure(field, data): return data.ds._c_adiab * data["gas", "density"]**data.ds.gamma pressure_recipe = None if ("amrvac", "e") in self.field_list: if self.ds._e_is_internal: pressure_recipe = _polytropic_thermal_pressure mylog.info('Using polytropic EoS for thermal pressure.') elif ('amrvac', 'b1') in self.field_list: pressure_recipe = _full_thermal_pressure_MHD mylog.info('Using full MHD energy for thermal pressure.') else: pressure_recipe = _full_thermal_pressure_HD mylog.info('Using full HD energy for thermal pressure.') elif self.ds._c_adiab is not None: pressure_recipe = _adiabatic_thermal_pressure mylog.info( 'Using adiabatic EoS for thermal pressure (isothermal).') mylog.warning( 'If you used usr_set_pthermal you should redefine the thermal_pressure field.' ) if pressure_recipe is not None: self.add_field( ('gas', 'thermal_pressure'), function=pressure_recipe, units=us['density'] * us['velocity']**2, dimensions=dimensions.density * dimensions.velocity**2, sampling_type='cell') # sound speed and temperature depend on thermal pressure def _sound_speed(field, data): return np.sqrt(data.ds.gamma * data["gas", "thermal_pressure"] / data["gas", "density"]) self.add_field(("gas", "sound_speed"), function=_sound_speed, units=us["velocity"], dimensions=dimensions.velocity, sampling_type="cell") else: mylog.warning( "e not found and no parfile passed, can not set thermal_pressure." )