Source code for yt.utilities.flagging_methods

import numpy as np  # For modern purposes

from yt.utilities.lib.misc_utilities import grow_flagging_field

flagging_method_registry = {}


[docs] class RegisteredFlaggingMethod(type): def __init__(cls, name, b, d): type.__init__(cls, name, b, d)
[docs] class FlaggingMethod: _skip_add = False def __init_subclass__(cls, *args, **kwargs): super().__init_subclass__(*args, **kwargs) if hasattr(cls, "_type_name") and not cls._skip_add: flagging_method_registry[cls._type_name] = cls
[docs] class OverDensity(FlaggingMethod): _type_name = "overdensity" def __init__(self, over_density): self.over_density = over_density def __call__(self, grid): rho = grid[("gas", "density")] / (grid.ds.refine_by**grid.Level) return rho > self.over_density
[docs] class FlaggingGrid: def __init__(self, grid, methods): self.grid = grid flagged = np.zeros(grid.ActiveDimensions, dtype="bool") for method in methods: flagged |= method(self.grid) self.flagged = grow_flagging_field(flagged) self.subgrids = [] self.left_index = grid.get_global_startindex() self.dimensions = grid.ActiveDimensions.copy()
[docs] def find_subgrids(self): if not np.any(self.flagged): return [] psg = ProtoSubgrid(self.flagged, self.left_index, self.dimensions) sgl = [psg] index = 0 while index < len(sgl): psg = sgl[index] psg.shrink() if psg.dimensions.prod() == 0: sgl[index] = None continue while not psg.acceptable: new_psgs = [] for dim in np.argsort(psg.dimensions)[::-1]: new_psgs = psg.find_by_zero_signature(dim) if len(new_psgs) > 1: break if len(new_psgs) <= 1: new_psgs = psg.find_by_second_derivative() psg = new_psgs[0] sgl[index] = psg sgl.extend(new_psgs[1:]) psg.shrink() index += 1 return sgl
# Much or most of this is directly translated from Enzo
[docs] class ProtoSubgrid: def __init__(self, flagged_base, left_index, dimensions, offset=(0, 0, 0)): self.left_index = left_index.copy() self.dimensions = dimensions.copy() self.flagged = flagged_base[ offset[0] : offset[0] + dimensions[0], offset[1] : offset[1] + dimensions[1], offset[2] : offset[2] + dimensions[2], ] self.compute_signatures()
[docs] def compute_signatures(self): self.sigs = [] for dim in range(3): d1 = (dim + 1) % 3 d2 = int(dim == 0) self.sigs.append(self.flagged.sum(axis=d1).sum(axis=d2))
@property def acceptable(self): return float(self.flagged.sum()) / self.flagged.size > 0.2
[docs] def shrink(self): new_ind = [] for dim in range(3): sig = self.sigs[dim] new_start = 0 while sig[new_start] == 0: new_start += 1 new_end = sig.size while sig[new_end - 1] == 0: new_end -= 1 self.dimensions[dim] = new_end - new_start self.left_index[dim] += new_start new_ind.append((new_start, new_end)) self.flagged = self.flagged[ new_ind[0][0] : new_ind[0][1], new_ind[1][0] : new_ind[1][1], new_ind[2][0] : new_ind[2][1], ] self.compute_signatures()
[docs] def find_by_zero_signature(self, dim): sig = self.sigs[dim] grid_ends = np.zeros((sig.size, 2), dtype="int64") ng = 0 i = 0 while i < sig.size: if sig[i] != 0: grid_ends[ng, 0] = i while i < sig.size and sig[i] != 0: i += 1 grid_ends[ng, 1] = i - 1 ng += 1 i += 1 new_grids = [] for si, ei in grid_ends[:ng, :]: li = self.left_index.copy() dims = self.dimensions.copy() li[dim] += si dims[dim] = ei - si offset = [0, 0, 0] offset[dim] = si new_grids.append(ProtoSubgrid(self.flagged, li, dims, offset)) return new_grids
[docs] def find_by_second_derivative(self): max_strength = 0 max_axis = -1 for dim in range(3): sig = self.sigs[dim] sd = sig[:-2] - 2.0 * sig[1:-1] + sig[2:] center = int((self.flagged.shape[dim] - 1) / 2) strength = zero_strength = zero_cross = 0 for i in range(1, sig.size - 2): # Note that sd is offset by one if sd[i - 1] * sd[i] < 0: strength = np.abs(sd[i - 1] - sd[i]) # TODO this differs from what I could find in ENZO # there's |center - i| < |center - zero_cross| instead # additionally zero_cross is undefined in first pass if strength > zero_strength or ( strength == zero_strength and np.abs(center - i) < np.abs(zero_cross - i) ): zero_strength = strength zero_cross = i if zero_strength > max_strength: max_axis = dim dims = self.dimensions.copy() li = self.left_index.copy() dims[max_axis] = zero_cross psg1 = ProtoSubgrid(self.flagged, li, dims) li[max_axis] += zero_cross dims[max_axis] = self.dimensions[max_axis] - zero_cross offset = np.zeros(3) offset[max_axis] = zero_cross psg2 = ProtoSubgrid(self.flagged, li, dims, offset) return [psg1, psg2]
def __str__(self): return f"LI: ({self.left_index}) DIMS: ({self.dimensions})"