def _populate_grid_objects(self): mask = np.empty(self.grids.size, dtype="int32") for g in self.grids: g._prepare_grid() g._setup_dx() for gi, g in enumerate(self.grids): g.Children = self._get_grid_children(g) for g1 in g.Children: g1.Parent.append(g) get_box_grids_level( self.grid_left_edge[gi, :], self.grid_right_edge[gi, :], self.grid_levels[gi], self.grid_left_edge, self.grid_right_edge, self.grid_levels, mask, ) m = mask.astype("bool") m[gi] = False siblings = self.grids[gi:][m[gi:]] if len(siblings) > 0: g.OverlappingSiblings = siblings.tolist() self.max_level = self.grid_levels.max()
def _reconstruct_parent_child(self): mask = np.empty(len(self.grids), dtype='int32') mylog.debug("First pass; identifying child grids") for i, grid in enumerate(self.grids): get_box_grids_level(self.grid_left_edge[i, :], self.grid_right_edge[i, :], self.grid_levels[i] + 1, self.grid_left_edge, self.grid_right_edge, self.grid_levels, mask) ids = np.where(mask.astype("bool")) # where is a tuple grid._children_ids = ids[0] + grid._id_offset mylog.debug("Second pass; identifying parents") for i, grid in enumerate(self.grids): # Second pass for child in grid.Children: child._parent_id.append(i + grid._id_offset)
def _reconstruct_parent_child(self): mask = np.empty(len(self.grids), dtype='int32') mylog.debug("First pass; identifying child grids") for i, grid in enumerate(self.grids): get_box_grids_level(self.grid_left_edge[i,:], self.grid_right_edge[i,:], self.grid_levels[i] + 1, self.grid_left_edge, self.grid_right_edge, self.grid_levels, mask) grid.Children = [g for g in self.grids[mask.astype("bool")] if g.Level == grid.Level + 1] mylog.debug("Second pass; identifying parents") for i, grid in enumerate(self.grids): # Second pass for child in grid.Children: child.Parent.append(grid)
def _reconstruct_parent_child(self): mask = np.empty(len(self.grids), dtype='int32') mylog.debug("First pass; identifying child grids") for i, grid in enumerate(self.grids): get_box_grids_level(self.grid_left_edge[i,:], self.grid_right_edge[i,:], self.grid_levels[i] + 1, self.grid_left_edge, self.grid_right_edge, self.grid_levels, mask) ids = np.where(mask.astype("bool")) # where is a tuple grid._children_ids = ids[0] + grid._id_offset mylog.debug("Second pass; identifying parents") for i, grid in enumerate(self.grids): # Second pass for child in grid.Children: child._parent_id.append(i + grid._id_offset)
def _reconstruct_parent_child(self): mask = np.empty(len(self.grids), dtype="int32") mylog.debug("First pass; identifying child grids") for i, grid in enumerate(self.grids): get_box_grids_level( self.grid_left_edge[i, :], self.grid_right_edge[i, :], self.grid_levels[i] + 1, self.grid_left_edge, self.grid_right_edge, self.grid_levels, mask, ) # ids = np.where(mask.astype("bool")) # where is a tuple # mask[ids] = True grid.Children = [g for g in self.grids[mask.astype("bool")] if g.Level == grid.Level + 1] mylog.debug("Second pass; identifying parents") for i, grid in enumerate(self.grids): # Second pass for child in grid.Children: child.Parent.append(grid)
def _populate_grid_objects(self): mask = np.empty(self.grids.size, dtype='int32') for gi, g in enumerate(self.grids): g._prepare_grid() g._setup_dx() for gi, g in enumerate(self.grids): g.Children = self._get_grid_children(g) for g1 in g.Children: g1.Parent.append(g) get_box_grids_level(self.grid_left_edge[gi, :], self.grid_right_edge[gi, :], self.grid_levels[gi], self.grid_left_edge, self.grid_right_edge, self.grid_levels, mask) m = mask.astype("bool") m[gi] = False siblings = self.grids[gi:][m[gi:]] if len(siblings) > 0: g.OverlappingSiblings = siblings.tolist() self.max_level = self.grid_levels.max()
def _reconstruct_parent_child(self): mask = np.empty(len(self.grids), dtype="int32") mylog.debug("First pass; identifying child grids") for i, grid in enumerate(self.grids): get_box_grids_level( self.grid_left_edge[i, :], self.grid_right_edge[i, :], self.grid_levels[i] + 1, self.grid_left_edge, self.grid_right_edge, self.grid_levels, mask, ) ids = np.where(mask.astype("bool")) grid._children_ids = ids[0] # where is a tuple mylog.debug("Second pass; identifying parents") self.stream_handler.parent_ids = ( np.zeros(self.stream_handler.num_grids, "int64") - 1) for i, grid in enumerate(self.grids): # Second pass for child in grid.Children: child._parent_id = i # _id_offset = 0 self.stream_handler.parent_ids[child.id] = i
def load_amr_grids( grid_data, domain_dimensions, bbox=None, sim_time=0.0, length_unit=None, mass_unit=None, time_unit=None, velocity_unit=None, magnetic_unit=None, periodicity=(True, True, True), geometry="cartesian", refine_by=2, unit_system="cgs", ): r"""Load a set of grids of data into yt as a :class:`~yt.frontends.stream.data_structures.StreamHandler`. This should allow a sequence of grids of varying resolution of data to be loaded directly into yt and analyzed as would any others. This comes with several caveats: * Units will be incorrect unless the unit system is explicitly specified. * Some functions may behave oddly, and parallelism will be disappointing or non-existent in most cases. * Particles may be difficult to integrate. * No consistency checks are performed on the index Parameters ---------- grid_data : list of dicts This is a list of dicts. Each dict must have entries "left_edge", "right_edge", "dimensions", "level", and then any remaining entries are assumed to be fields. Field entries must map to an NDArray. The grid_data may also include a particle count. If no particle count is supplied, the dataset is understood to contain no particles. The grid_data will be modified in place and can't be assumed to be static. domain_dimensions : array_like This is the domain dimensions of the grid length_unit : string or float Unit to use for lengths. Defaults to unitless. If set to be a string, the bbox dimensions are assumed to be in the corresponding units. If set to a float, the value is a assumed to be the conversion from bbox dimensions to centimeters. mass_unit : string or float Unit to use for masses. Defaults to unitless. time_unit : string or float Unit to use for times. Defaults to unitless. velocity_unit : string or float Unit to use for velocities. Defaults to unitless. magnetic_unit : string or float Unit to use for magnetic fields. Defaults to unitless. bbox : array_like (xdim:zdim, LE:RE), optional Size of computational domain in units specified by length_unit. Defaults to a cubic unit-length domain. sim_time : float, optional The simulation time in seconds periodicity : tuple of booleans Determines whether the data will be treated as periodic along each axis geometry : string or tuple "cartesian", "cylindrical", "polar", "spherical", "geographic" or "spectral_cube". Optionally, a tuple can be provided to specify the axis ordering -- for instance, to specify that the axis ordering should be z, x, y, this would be: ("cartesian", ("z", "x", "y")). The same can be done for other coordinates, for instance: ("spherical", ("theta", "phi", "r")). refine_by : integer or list/array of integers. Specifies the refinement ratio between levels. Defaults to 2. This can be an array, in which case it specifies for each dimension. For instance, this can be used to say that some datasets have refinement of 1 in one dimension, indicating that they span the full range in that dimension. Examples -------- >>> grid_data = [ ... dict(left_edge = [0.0, 0.0, 0.0], ... right_edge = [1.0, 1.0, 1.], ... level = 0, ... dimensions = [32, 32, 32], ... number_of_particles = 0), ... dict(left_edge = [0.25, 0.25, 0.25], ... right_edge = [0.75, 0.75, 0.75], ... level = 1, ... dimensions = [32, 32, 32], ... number_of_particles = 0) ... ] ... >>> for g in grid_data: ... g["density"] = (np.random.random(g["dimensions"])*2**g["level"], "g/cm**3") ... >>> ds = load_amr_grids(grid_data, [32, 32, 32], length_unit=1.0) """ from yt.frontends.stream.data_structures import ( StreamDataset, StreamDictFieldHandler, StreamHandler, ) from yt.frontends.stream.definitions import process_data, set_particle_types domain_dimensions = np.array(domain_dimensions) ngrids = len(grid_data) if bbox is None: bbox = np.array([[0.0, 1.0], [0.0, 1.0], [0.0, 1.0]], "float64") domain_left_edge = np.array(bbox[:, 0], "float64") domain_right_edge = np.array(bbox[:, 1], "float64") grid_levels = np.zeros((ngrids, 1), dtype="int32") grid_left_edges = np.zeros((ngrids, 3), dtype="float64") grid_right_edges = np.zeros((ngrids, 3), dtype="float64") grid_dimensions = np.zeros((ngrids, 3), dtype="int32") number_of_particles = np.zeros((ngrids, 1), dtype="int64") parent_ids = np.zeros(ngrids, dtype="int64") - 1 sfh = StreamDictFieldHandler() for i, g in enumerate(grid_data): grid_left_edges[i, :] = g.pop("left_edge") grid_right_edges[i, :] = g.pop("right_edge") grid_dimensions[i, :] = g.pop("dimensions") grid_levels[i, :] = g.pop("level") # If someone included this throw it away--old API if "number_of_particles" in g: issue_deprecation_warning( "It is no longer necessary to include " "the number of particles in the data " "dict. The number of particles is " "determined from the sizes of the " "particle fields.", since="4.0.0", removal="4.1.0", ) g.pop("number_of_particles") field_units, data, n_particles = process_data( g, grid_dims=tuple(grid_dimensions[i, :]) ) number_of_particles[i, :] = n_particles sfh[i] = data # We now reconstruct our parent ids, so that our particle assignment can # proceed. mask = np.empty(ngrids, dtype="int32") for gi in range(ngrids): get_box_grids_level( grid_left_edges[gi, :], grid_right_edges[gi, :], grid_levels[gi] + 1, grid_left_edges, grid_right_edges, grid_levels, mask, ) ids = np.where(mask.astype("bool")) for ci in ids: parent_ids[ci] = gi # Check if the grid structure is properly aligned (bug #1295) for lvl in range(grid_levels.min() + 1, grid_levels.max() + 1): idx = grid_levels.flatten() == lvl dims = domain_dimensions * refine_by ** (lvl - 1) for iax, ax in enumerate("xyz"): cell_edges = np.linspace( domain_left_edge[iax], domain_right_edge[iax], dims[iax], endpoint=False ) if set(grid_left_edges[idx, iax]) - set(cell_edges): raise YTIllDefinedAMR(lvl, ax) if length_unit is None: length_unit = "code_length" if mass_unit is None: mass_unit = "code_mass" if time_unit is None: time_unit = "code_time" if velocity_unit is None: velocity_unit = "code_velocity" if magnetic_unit is None: magnetic_unit = "code_magnetic" particle_types = {} for grid in sfh.values(): particle_types.update(set_particle_types(grid)) handler = StreamHandler( grid_left_edges, grid_right_edges, grid_dimensions, grid_levels, parent_ids, number_of_particles, np.zeros(ngrids).reshape((ngrids, 1)), sfh, field_units, (length_unit, mass_unit, time_unit, velocity_unit, magnetic_unit), particle_types=particle_types, periodicity=periodicity, ) handler.name = "AMRGridData" handler.domain_left_edge = domain_left_edge handler.domain_right_edge = domain_right_edge handler.refine_by = refine_by if np.all(domain_dimensions[1:] == 1): dimensionality = 1 elif domain_dimensions[2] == 1: dimensionality = 2 else: dimensionality = 3 handler.dimensionality = dimensionality handler.domain_dimensions = domain_dimensions handler.simulation_time = sim_time handler.cosmology_simulation = 0 sds = StreamDataset(handler, geometry=geometry, unit_system=unit_system) return sds