def mass_inside(R, clusrx, clusry, clusrz, density, cellsrx, cellsry, cellsrz, npatch, size, nmax): """ Computes the mass inside a radius R sphere centered on (clusrx, clusry, clusrz), from the density field. Note that user can either supply: - Comoving density and comoving size (most common) - Physical density and physical size Args: R: radius of the considered sphere clusrx, clusry, clusrz: comoving coordinates of the center of the sphere density: density field, already cleaned from refinements and overlaps (but not masked!) cellsrx, cellsry, cellsrz: position fields npatch: number of patches in each level, starting in l=0 size: comoving size of the simulation box nmax: cells at base level Returns: Field containing the mask as described. """ levels = tools.create_vector_levels(npatch) cells_volume = (size / nmax / 2**levels)**3 if np.isnan(R): R = 0 mask = mask_sphere(R, clusrx, clusry, clusrz, cellsrx, cellsry, cellsrz) cellmasses = [d * m * cv for d, m, cv in zip(density, mask, cells_volume)] mass = sum([cm.sum() for cm in cellmasses]) return mass
def compute_position_fields(patchnx, patchny, patchnz, patchrx, patchry, patchrz, npatch, size, nmax, ncores=1): """ Returns 3 fields (as usually defined) containing the x, y and z position for each of our cells centres. Args: patchnx, patchny, patchnz: x-extension of each patch (in level l cells) (and Y and Z) patchrx, patchry, patchrz: physical position of the center of each patch first ¡l-1! cell (and Y and Z) npatch: number of patches in each level, starting in l=0 size: comoving size of the simulation box nmax: cells at base level ncores: Returns: 3 fields as described above """ levels = tools.create_vector_levels(npatch) if ncores == 1 or ncores == 0 or ncores is None: cellsrx = [] cellsry = [] cellsrz = [] for ipatch in range(npatch.sum() + 1): patches = compute_position_field_onepatch( (patchnx[ipatch], patchny[ipatch], patchnz[ipatch], patchrx[ipatch], patchry[ipatch], patchrz[ipatch], levels[ipatch], size, nmax)) cellsrx.append(patches[0]) cellsry.append(patches[1]) cellsrz.append(patches[2]) else: with Pool(ncores) as p: positions = p.map( compute_position_field_onepatch, [(patchnx[ipatch], patchny[ipatch], patchnz[ipatch], patchrx[ipatch], patchry[ipatch], patchrz[ipatch], levels[ipatch], size, nmax) for ipatch in range(len(patchnx))]) cellsrx = [p[0] for p in positions] cellsry = [p[1] for p in positions] cellsrz = [p[2] for p in positions] return cellsrx, cellsry, cellsrz
def load_grids(it, path='', digits=5): """ This function creates a list of dictionaries containing the information requiered for yt's load_amr_grids to build the grid structure of a simulations performed by MASCLET. Args: it: iteration number (int) path: path of the grids file in the system (str) digits: number of digits the filename is written with (int) Returns: grid_data: list of dictionaries, each containing the information about one refinement patch (left_edge, right_edge, level and dimensions [number of cells]) bbox: bounds of the simulation box in physical coordinates (typically Mpc or kpc) """ nmax, nmay, nmaz, nlevels, namrx, namry, namrz, size = parameters.read_parameters(load_npalev=False) irr, t, nl, mass_dmpart, zeta, npatch, npart, patchnx, patchny, patchnz, patchx, patchy, patchz, pare = \ read_masclet.read_grids(it, path=path, read_patchposition=False, digits=digits) # l=0 (whole box) grid_data = [dict(left_edge=[-size / 2, -size / 2, -size / 2], right_edge=[size / 2, size / 2, size / 2], level=0, dimensions=[nmax, nmay, nmaz])] levels = tools.create_vector_levels(npatch) left = np.array([tools.find_absolute_real_position(i, size, nmax, npatch, patchx, patchy, patchz, pare) for i in range(1, levels.size)]) left = np.vstack([[-size / 2, -size / 2, -size / 2], left]) right = left + np.array([patchnx / 2 ** levels, patchny / 2 ** levels, patchnz / 2 ** levels]).transpose()[:, :] \ * size / nmax for i in range(1, levels.size): grid_data.append(dict(left_edge=left[i, :].tolist(), right_edge=right[i, :].tolist(), level=levels[i], dimensions=[patchnx[i], patchny[i], patchnz[i]])) bbox = np.array([[-size / 2, size / 2], [-size / 2, size / 2], [-size / 2, size / 2]]) return grid_data, bbox
def several_radial_profiles_vw(fields, clusrx, clusry, clusrz, rmin, rmax, nbins, logbins, cellsrx, cellsry, cellsrz, cr0amr, solapst, npatch, size, nmax, up_to_level=1000, verbose=False): """ Computes a (volume-weighted) radial profile of the quantity given in the "field" argument, taking center in (clusrx, clusry, clusrz). Args: fields: set of fields (already cleaned) whose profile wants to be got clusrx, clusry, clusrz: comoving coordinates of the center for the profile rmin: starting radius of the profile rmax: final radius of the profile nbins: number of points for the profile logbins: if False, radial shells are spaced linearly. If True, they're spaced logarithmically. Not that, if logbins = True, rmin cannot be 0. cellsrx, cellsry, cellsrz: position fields cr0amr: field containing the refinements of the grid (1: not refined; 0: refined) solapst: field containing the overlaps (1: keep; 0: not keep) npatch: number of patches in each level, starting in l=0 size: comoving size of the simulation box nmax: cells at base level up_to_level: maximum AMR level to be considered for the profile verbose: if True, prints the patch being opened at a time Returns: Two lists. One of them contains the center of each radial cell. The other contains the value of the field averaged across all the cells of the shell. """ # getting the bins try: assert (rmax > rmin) except AssertionError: print('You would like to input rmax > rmin...') return if logbins: try: assert (rmin > 0) except AssertionError: print('Cannot use rmin=0 with logarithmic binning...') return bin_bounds = np.logspace(np.log10(rmin), np.log10(rmax), nbins + 1) else: bin_bounds = np.linspace(rmin, rmax, nbins + 1) bin_centers = (bin_bounds[1:] + bin_bounds[:-1]) / 2 # finding the volume-weighted mean levels = tools.create_vector_levels(npatch) cell_volume = (size / nmax / 2**levels)**3 fields_vw = [[f * cv for f, cv in zip(field, cell_volume)] for field in fields] if rmin > 0: cells_outer = mask_sphere(rmin, clusrx, clusry, clusrz, cellsrx, cellsry, cellsrz) else: cells_outer = [ np.zeros(patch.shape, dtype='bool') for patch in fields[0] ] profiles = [] for r_out in bin_bounds[1:]: if verbose: print('Working at outer radius {} Mpc'.format(r_out)) cells_inner = cells_outer cells_outer = mask_sphere(r_out, clusrx, clusry, clusrz, cellsrx, cellsry, cellsrz) shell_mask = [ inner ^ outer for inner, outer in zip(cells_inner, cells_outer) ] shell_mask = tools.clean_field(shell_mask, cr0amr, solapst, npatch, up_to_level=up_to_level) sum_vw = sum([(sm * cv).sum() for sm, cv in zip(shell_mask, cell_volume)]) profile_thisr = [ (sum([(fvw * sm).sum() for fvw, sm in zip(field_vw, shell_mask)]) / sum_vw) for field_vw in fields_vw ] profiles.append(profile_thisr) profiles = np.asarray(profiles) profiles_split = tuple([profiles[:, i] for i in range(profiles.shape[1])]) return bin_centers, profiles_split