def volume(self): """The abstract volume associated with this VolumeSource This object does the heavy lifting to access data in an efficient manner using a KDTree """ if self._volume is None: mylog.info("Creating volume") volume = AMRKDTree(self.data_source.ds, data_source=self.data_source) self._volume = volume return self._volume
def __init__( self, ds, positions, xfield="velocity_x", yfield="velocity_x", zfield="velocity_x", volume=None, dx=None, length=None, direction=1, get_magnitude=False, ): ParallelAnalysisInterface.__init__(self) self.ds = ds self.start_positions = sanitize_length(positions, ds) self.N = self.start_positions.shape[0] # I need a data object to resolve the field names to field tuples # via _determine_fields() ad = self.ds.all_data() self.xfield = ad._determine_fields(xfield)[0] self.yfield = ad._determine_fields(yfield)[0] self.zfield = ad._determine_fields(zfield)[0] self.get_magnitude = get_magnitude self.direction = np.sign(direction) if volume is None: volume = AMRKDTree(self.ds) volume.set_fields([self.xfield, self.yfield, self.zfield], [False, False, False], False) volume.join_parallel_trees() self.volume = volume if dx is None: dx = self.ds.index.get_smallest_dx() self.dx = sanitize_length(dx, ds) if length is None: length = np.max(self.ds.domain_right_edge - self.ds.domain_left_edge) self.length = sanitize_length(length, ds) self.steps = int(self.length / self.dx) + 1 # Fix up the dx. self.dx = 1.0 * self.length / self.steps self.streamlines = np.zeros((self.N, self.steps, 3), dtype="float64") self.magnitudes = None if self.get_magnitude: self.magnitudes = np.zeros((self.N, self.steps), dtype="float64")
def __init__(self, ds, positions, xfield='velocity_x', yfield='velocity_x', zfield='velocity_x', volume=None, dx=None, length=None, direction=1, get_magnitude=False): ParallelAnalysisInterface.__init__(self) self.ds = ds self.start_positions = np.array(positions) self.N = self.start_positions.shape[0] self.xfield = xfield self.yfield = yfield self.zfield = zfield self.get_magnitude = get_magnitude self.direction = np.sign(direction) if volume is None: volume = AMRKDTree(self.ds) volume.set_fields([self.xfield, self.yfield, self.zfield], [False, False, False], False) volume.join_parallel_trees() self.volume = volume if dx is None: dx = self.ds.index.get_smallest_dx() self.dx = dx if length is None: length = np.max(self.ds.domain_right_edge - self.ds.domain_left_edge) self.length = length self.steps = int(length / dx) + 1 # Fix up the dx. self.dx = 1.0 * self.length / self.steps self.streamlines = np.zeros((self.N, self.steps, 3), dtype='float64') self.magnitudes = None if self.get_magnitude: self.magnitudes = np.zeros((self.N, self.steps), dtype='float64')
def test_amr_kdtree_coverage(): return #TESTDISABLED domain_dims = (32, 32, 32) data = np.zeros(domain_dims) + 0.25 fo = [ ic.CoredSphere(0.05, 0.3, [0.7, 0.4, 0.75], {"density": (0.25, 100.0)}) ] rc = [fm.flagging_method_registry["overdensity"](8.0)] ug = load_uniform_grid({"density": data}, domain_dims, 1.0) ds = refine_amr(ug, rc, fo, 5) kd = AMRKDTree(ds) volume = kd.count_volume() yield assert_equal, volume, \ np.prod(ds.domain_right_edge - ds.domain_left_edge) cells = kd.count_cells() true_cells = ds.all_data().quantities['TotalQuantity']('Ones')[0] yield assert_equal, cells, true_cells # This largely reproduces the AMRKDTree.tree.check_tree() functionality tree_ok = True for node in kd.tree.trunk.depth_traverse(): if node.grid is None: continue grid = ds.index.grids[node.grid - kd._id_offset] dds = grid.dds gle = grid.LeftEdge nle = node.get_left_edge() nre = node.get_right_edge() li = np.rint((nle - gle) / dds).astype('int32') ri = np.rint((nre - gle) / dds).astype('int32') dims = (ri - li).astype('int32') tree_ok *= np.all(grid.LeftEdge <= nle) tree_ok *= np.all(grid.RightEdge >= nre) tree_ok *= np.all(dims > 0) yield assert_equal, True, tree_ok
# Using AMRKDTree Homogenized Volumes to examine large datasets # at lower resolution. # In this example we will show how to use the AMRKDTree to take a simulation # with 8 levels of refinement and only use levels 0-3 to render the dataset. # We begin by loading up yt, and importing the AMRKDTree import numpy as np import yt from yt.utilities.amr_kdtree.api import AMRKDTree # Load up a dataset and define the kdtree ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030') kd = AMRKDTree(ds) # Print out specifics of KD Tree print("Total volume of all bricks = %i" % kd.count_volume()) print("Total number of cells = %i" % kd.count_cells()) # Define a camera and take an volume rendering. tf = yt.ColorTransferFunction((-30, -22)) cam = ds.camera([0.5, 0.5, 0.5], [0.2, 0.3, 0.4], 0.10, 256, tf, volume=kd) tf.add_layers(4, 0.01, col_bounds=[-27.5, -25.5], colormap='RdBu_r') cam.snapshot("v1.png", clip_ratio=6.0) # This rendering is okay, but lets say I'd like to improve it, and I don't want # to spend the time rendering the high resolution data. What we can do is # generate a low resolution version of the AMRKDTree and pass that in to the # camera. We do this by specifying a maximum refinement level of 6.
from yt.utilities.amr_kdtree.api import AMRKDTree # Load up a dataset and define the kdtree ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030') im, sc = yt.volume_render(ds, 'density', fname='v0.png') sc.camera.set_width(ds.arr(100, 'kpc')) render_source = sc.get_source(0) kd = render_source.volume # Print out specifics of KD Tree print("Total volume of all bricks = %i" % kd.count_volume()) print("Total number of cells = %i" % kd.count_cells()) new_source = ds.all_data() new_source.max_level = 3 kd_low_res = AMRKDTree(ds, data_source=new_source) print(kd_low_res.count_volume()) print(kd_low_res.count_cells()) # Now we pass this in as the volume to our camera, and render the snapshot # again. render_source.set_volume(kd_low_res) render_source.set_field('density') sc.render() sc.save("v1.png", sigma_clip=6.0) # This operation was substantiall faster. Now lets modify the low resolution # rendering until we find something we like. tf = render_source.transfer_function
def surfacePressureEnergy(clump): steps = np.array([[-1, -1, -1], [-1, -1, 0], [-1, -1, 1], [-1, 0, -1], [-1, 0, 0], [-1, 0, 1], [-1, 1, -1], [-1, 1, 0], [-1, 1, 1], [0, -1, -1], [0, -1, 0], [0, -1, 1], [0, 0, -1], [0, 0, 1], [0, 1, -1], [0, 1, 0], [0, 1, 1], [1, -1, -1], [1, -1, 0], [1, -1, 1], [1, 0, -1], [1, 0, 0], [1, 0, 1], [1, 1, -1], [1, 1, 0], [1, 1, 1]]) mag = np.sqrt((steps**2).sum(axis=1)) mag = np.array([mag, mag, mag]).T.astype(float) normals = -steps / mag neighborsTrue = np.ones([3, 3, 3], bool) neighborsTrue[1, 1, 1] = False ds = clump.data.ds amrTree = clump.data.tiles cm = clump.quantities.center_of_mass() LE = clump.data.tiles.data_source.base_object.left_edge RE = clump.data.tiles.data_source.base_object.right_edge newLE = LE - (RE - LE) / 10 newRE = RE + (RE - LE) / 10 biggerBox = ds.box(newLE, newRE) amrTree = AMRKDTree(ds, data_source=biggerBox) surfPressureTerm = 0 grid_mask_dict = dict((g, m) for g, m in clump.data.blocks) pad = 2 # dictionary to keep track of surface cells that have been # visited and the corresponding grid they were visited from. allSurfCells = {'cell': [], 'grid': []} for grid, clumpMask in clump.data.blocks: print(grid) # Get surface cells using masks surfMask = np.zeros(np.array(clumpMask.shape) + 2 * pad, dtype=bool) L = surfMask.shape[0] - pad W = surfMask.shape[1] - pad H = surfMask.shape[2] - pad surfMask[2:L, 2:W, 2:H] = clumpMask padClumpMask = surfMask.copy() for i in [-1, 0, 1]: for j in [-1, 0, 1]: for k in [-1, 0, 1]: surfMask[pad + i:L + i, pad + j:W + j, pad + k:H + k] |= clumpMask surfMask = np.logical_xor(surfMask, padClumpMask) surfCells_fromPad = np.argwhere(surfMask) surfCells = surfCells_fromPad - np.array([pad, pad, pad]) surfInGrid = np.all((surfCells >= 0) * (surfCells < clumpMask.shape), axis=1) surfOutGrid = np.logical_not(surfInGrid) # *** Think about looping over surfInGrid surfOutGrid separately *** # for cell in surfCells: surfNormals = [] cell = np.array(cell) center_dds = grid.dds # get physical position of surface cell position = grid.LeftEdge + (np.array(cell) + 0.5) * grid.dds new_position = periodic_position(position, ds) r = position - cm # get cooresponding grid that surface cell lives in as well as its # indicies relatvie to that grid. trueGrid = ds.index.grids[ amrTree.locate_brick(new_position).grid \ - grid._id_offset] trueCell = ((new_position - trueGrid.LeftEdge) / trueGrid.dds).v trueCell = tuple(trueCell.astype(int)) # if surface cell has already been visited in a different grid loop, # then we have already accounted for the surface pressure from that cell # and we can skip it. skip = False for g, c in zip(allSurfCells['grid'], allSurfCells['cell']): if (not (np.array(c) - np.array(trueCell)).sum()) and grid.id != g: skip = True break if skip: continue allSurfCells['cell'].append(trueCell) allSurfCells['grid'].append(grid.id) #print("\tgrid, trueGrid", grid, trueGrid) #print("\tcell, trueCell", cell, trueCell) # if trueCell is part of the clump in trueGrid it is not actually # a surface cell and we can skip it. Also if trueGrid is not in # grid_mask_dict, that means trueCell is not in this clump and is # a true surface cells possiblyInClump = False try: trueClumpMask = grid_mask_dict[trueGrid] possiblyInClump = True except: pass trueCellInClump = False if possiblyInClump: #print("\ttrue cell", trueCell, " in clump?") trueCellMask = np.zeros_like(trueClumpMask) trueCellMask[trueCell] = True trueCellInClump = np.logical_and(trueCellMask, trueClumpMask).any() if trueCellInClump: # not a true surface cell, continue to next one #print("\t\tYES. Next surface cell") continue #print("\t\tNO. True surface cell") # if we made it here we have a true surface cell. We know need # the pressure and the surface normals of all the cells in the # clump it is touching. pressure = trueGrid['pressure'][trueCell] dS = grid.dds[0] * grid.dds[0] # find grid and cell indicies of neighboring cells # which may be in separate grids cell = np.array(cell) center_dds = grid.dds grids = np.empty(26, dtype='object') neigborCells = np.empty([26, 3], dtype='int64') offs = 0.5 * (center_dds + amrTree.sdx) new_neigborCells = cell + steps # index mask for cells this in grid in_grid = np.all( (new_neigborCells >=0) * \ (new_neigborCells < grid.ActiveDimensions), axis=1 ) # index mask for cells in a neighboring grid not_in_grid = np.logical_not(in_grid) # physical positions of neighboring cells (assumes a periodic box) new_positions = position + steps * offs new_positions = [periodic_position(p, ds) for p in new_positions] grids[in_grid] = grid neigborCells[in_grid] = new_neigborCells[in_grid] # neigboring cell indicies of cells that are in other grids get_them = np.argwhere(not_in_grid).ravel() if not_in_grid.any(): # get grids containing cells outside current grids grids[get_them] = \ [ds.index.grids[amrTree.locate_brick(new_positions[i]).grid - \ grid._id_offset] for i in get_them ] # get cell location indicies in grids outside current grid neigborCells[not_in_grid] = \ [ (new_positions[i] - grids[i].LeftEdge)/grids[i].dds \ for i in get_them ] neigborCells = [tuple(_cs) for _cs in neigborCells] # find which neigbor cells are in the clump. We only care about # neighbor cells that are within the clump becaause we need to # know the normal vectors for those ones. #print("\t\tFind neigbor cells within clump") for nGrid, nCell, norm in zip(grids, neigborCells, normals): nCell = tuple(nCell) #print("\t\tnCell, nGrid", nCell, nGrid) try: nClumpMask = grid_mask_dict[nGrid] except: # if nGrid is not in dict of grids for this clump, # then nCell cannot be in this clump continue # is nCell in nClump? nCellMask = np.zeros_like(nClumpMask) nCellMask[nCell] = True inClump = np.logical_and(nCellMask, nClumpMask).any() if inClump: #print("\t\t\tIN clump") surfNormals.append(norm) #else: #print("\t\t\tNOT in clump") surfNormals = np.array(surfNormals) rs = ds.arr(np.empty_like(surfNormals), r.units) rs[:] = r # surface pressure term = Integrate{ p r dot dS } r_dot_dS = (rs * surfNormals).sum(axis=1) * dS surfPressureTerm += (pressure * r_dot_dS).sum() #print(surfPressureTerm.to('erg')) return surfPressureTerm