def test_radial(self): dx = 0.25 rad = 10 mesh = mesh_builder_xyz( np.c_[0.01, 0.01, 0.01], [dx, dx, dx], depth_core=0, padding_distance=[[0, 20], [0, 20], [0, 20]], mesh_type="TREE", ) radCell = int(np.ceil(rad / dx)) mesh = refine_tree_xyz( mesh, np.c_[0, 0, 0], octree_levels=[radCell], method="radial", finalize=True, ) # Volume of sphere vol = 4.0 * np.pi / 3.0 * rad**3.0 residual = (np.abs(vol - mesh.vol[mesh._cell_levels_by_indexes( range(mesh.nC)) == mesh.max_level].sum()) / vol * 100) self.assertTrue(residual < 3)
def test_surface(self): dx = 0.1 dl = 20 # Define triangle xyz = np.r_[np.c_[-dl / 2, -dl / 2, 0], np.c_[dl / 2, -dl / 2, 0], np.c_[dl / 2, dl / 2, 0], ] mesh = mesh_builder_xyz( np.c_[0.01, 0.01, 0.01], [dx, dx, dx], depth_core=0, padding_distance=[[0, 20], [0, 20], [0, 20]], mesh_type="TREE", ) mesh = refine_tree_xyz(mesh, xyz, octree_levels=[1], method="surface", finalize=True) # Volume of triangle vol = dl * dl * dx / 2 residual = ( np.abs(vol - mesh.cell_volumes[mesh._cell_levels_by_indexes( range(mesh.nC)) == mesh.max_level].sum() / 2) / vol * 100) self.assertLess(residual, 5)
def test_radial(self): dx = 0.25 rad = 10 mesh = mesh_builder_xyz( np.c_[0.01, 0.01, 0.01], [dx, dx, dx], depth_core=0, padding_distance=[[0, 20], [0, 20], [0, 20]], mesh_type="TREE", ) radCell = int(np.ceil(rad / dx)) mesh = refine_tree_xyz( mesh, np.c_[0, 0, 0], octree_levels=[radCell], method="radial", finalize=True, ) cell_levels = mesh.cell_levels_by_index(np.arange(mesh.n_cells)) vol = 4.0 * np.pi / 3.0 * (rad + dx)**3.0 vol_mesh = mesh.cell_volumes[cell_levels == mesh.max_level].sum() self.assertLess(np.abs(vol - vol_mesh) / vol, 0.05) levels, cells_per_level = np.unique(cell_levels, return_counts=True) self.assertEqual(mesh.n_cells, 311858) np.testing.assert_array_equal(levels, [3, 4, 5, 6, 7]) np.testing.assert_array_equal(cells_per_level, [232, 1176, 2671, 9435, 298344])
def test_box(self): dx = 0.25 dl = 10 # Create a box 2*dl in width X, Y, Z = np.meshgrid(np.c_[-dl, dl], np.c_[-dl, dl], np.c_[-dl, dl]) xyz = np.c_[np.ravel(X), np.ravel(Y), np.ravel(Z)] mesh = mesh_builder_xyz( np.c_[0.01, 0.01, 0.01], [dx, dx, dx], depth_core=0, padding_distance=[[0, 20], [0, 20], [0, 20]], mesh_type="TREE", ) mesh = refine_tree_xyz(mesh, xyz, octree_levels=[0, 1], method="box", finalize=True) cell_levels = mesh.cell_levels_by_index(np.arange(mesh.n_cells)) vol = ( 2 * (dl + 2 * dx))**3 # 2*dx is cell size at second to highest level vol_mesh = np.sum(mesh.cell_volumes[cell_levels == mesh.max_level - 1]) self.assertLess((vol - vol_mesh) / vol, 0.05) levels, cells_per_level = np.unique(cell_levels, return_counts=True) self.assertEqual(mesh.n_cells, 80221) np.testing.assert_array_equal(levels, [3, 4, 5, 6]) np.testing.assert_array_equal(cells_per_level, [80, 1762, 4291, 74088])
def test_box(self): dx = 0.25 dl = 10 # Create a box 2*dl in width X, Y, Z = np.meshgrid(np.c_[-dl, dl], np.c_[-dl, dl], np.c_[-dl, dl]) xyz = np.c_[np.ravel(X), np.ravel(Y), np.ravel(Z)] mesh = mesh_builder_xyz( np.c_[0.01, 0.01, 0.01], [dx, dx, dx], depth_core=0, padding_distance=[[0, 20], [0, 20], [0, 20]], mesh_type="TREE", ) mesh = refine_tree_xyz(mesh, xyz, octree_levels=[1], method="box", finalize=True) # Volume of box vol = (2 * dl)**3 residual = (np.abs(vol - mesh.vol[mesh._cell_levels_by_indexes( range(mesh.nC)) == mesh.max_level].sum()) / vol * 100) self.assertTrue(residual < 0.5)
def test_Tile(self): """ Test for TileMap """ rxLocs = np.random.randn(3, 3) * 20 h = [5, 5, 5] padDist = np.ones((3, 2)) * 100 local_meshes = [] for ii in range(rxLocs.shape[0]): local_mesh = mesh_builder_xyz(rxLocs, h, padding_distance=padDist, mesh_type="tree") local_mesh = refine_tree_xyz( local_mesh, rxLocs[ii, :].reshape((1, -1)), method="radial", octree_levels=[1], finalize=True, ) local_meshes.append(local_mesh) mesh = mesh_builder_xyz(rxLocs, h, padding_distance=padDist, mesh_type="tree") # This garantees that the local meshes are always coarser or equal for local_mesh in local_meshes: mesh.insert_cells( local_mesh.gridCC, local_mesh.cell_levels_by_index(np.arange(local_mesh.nC)), finalize=False, ) mesh.finalize() # Define an active cells from topo activeCells = utils.surface2ind_topo(mesh, rxLocs) model = np.random.randn(int(activeCells.sum())) total_mass = (model * mesh.vol[activeCells]).sum() for local_mesh in local_meshes: tile_map = maps.TileMap( mesh, activeCells, local_mesh, ) local_mass = ((tile_map * model) * local_mesh.vol[tile_map.local_active]).sum() self.assertTrue((local_mass - total_mass) / total_mass < 1e-8)
def create_octree_mesh(domain, cellwidth, points, method='surface'): """Creates an octree mesh and refines at specified points. Parameters ---------- domain : tuple ((xmin, xmax),(ymin, ymax),(zmin, zmax)) coordinates of the domain cellwidth : int width of smallest cell in the mesh points : np.ndarray array of points that will be refined in the mesh method : string the discretize method that will be used for refinement. Available are 'surface', 'radial' and 'box' Returns ------- discretize.mesh a mesh where the points are refined """ # domain dimensions x_length = np.abs(domain[0][0] - domain[0][1]) y_length = np.abs(domain[1][0] - domain[1][1]) z_length = np.abs(domain[2][0] - domain[2][1]) # number of cells needed in each dimension nbx = 2**int(np.ceil(np.log(x_length / cellwidth) / np.log(2.0))) nby = 2**int(np.ceil(np.log(y_length / cellwidth) / np.log(2.0))) nbz = 2**int(np.ceil(np.log(z_length / cellwidth) / np.log(2.0))) # define base mesh hx = cellwidth * np.ones(nbx) hy = cellwidth * np.ones(nby) hz = cellwidth * np.ones(nbz) mesh = TreeMesh([hx, hy, hz], origin=[domain[0][0], domain[1][0], domain[2][0]]) # refine mesh around the given surface points mesh = refine_tree_xyz(mesh, points, octree_levels=[1, 1, 1], method=method, max_distance=1, finalize=False) return mesh
def refine_at_locations(mesh, locations): """Refines a mesh at the given locations. Parameters ---------- mesh : discretize.mesh a not yet finalized discretize mesh locations : np.ndarray an array with coordinates of points to refine the mesh Returns ------- discretize.mesh a mesh where the new points are also refined """ mesh = refine_tree_xyz(mesh, locations, octree_levels=[1, 1], method="radial", finalize=False) return mesh
for local_index in local_indices: receivers = gravity.receivers.Point(rxLoc[local_index, :]) srcField = gravity.sources.SourceField([receivers]) local_survey = gravity.survey.Survey(srcField) # Create a local mesh that covers all points, but refined on the local survey local_mesh = mesh_builder_xyz(topo, h, padding_distance=padDist, depth_core=100, mesh_type="tree") local_mesh = refine_tree_xyz( local_mesh, local_survey.receiver_locations, method="surface", octree_levels=octree_levels, finalize=True, ) local_surveys.append(local_survey) local_meshes.append(local_mesh) ############################################################################### # Global Mesh # ------------ # # Create a global mesh survey for simulation # #
dh = 5 # minimum cell width (base mesh cell width) nbc = 64 # number of base mesh cells in x # Define base mesh (domain and finest discretization) h = dh * np.ones(nbc) mesh = TreeMesh([h, h]) # Define corner points for rectangular box xp, yp = np.meshgrid([120.0, 240.0], [80.0, 160.0]) xy = np.c_[mkvc(xp), mkvc(yp)] # mkvc creates vectors # Discretize to finest cell size within rectangular box mesh = refine_tree_xyz(mesh, xy, octree_levels=[2, 2], method="box", finalize=False) mesh.finalize() # Must finalize tree mesh before use mesh.plotGrid(show_it=True) ############################################### # Intermediate Example and Plotting # --------------------------------- # # The widths of the base mesh cells do not need to be the same in x and y. # However the number of base mesh cells in x and y each needs to be a power of 2. # # Here we show topography-based mesh refinement and refinement about a
def fdem_forward_simulation(detector, target, collection): """ Get FDEM simulation data using SimPEG. Parameters ---------- detector : class Detector target : class Target collention : class Collection Returns ------- receiver_locations : numpy.ndarray, shape(N * 3) All acquisition locations of the detector. Each row represents an acquisition location and the three columns represent x, y and z axis locations of an acquisition location. mag_data : numpy.ndarray, shape(N*3) All secondary fields of acquisition locations. mesh : SimPEG mesh mapped_model : numpy.ndarray References ---------- https://docs.simpeg.xyz/content/tutorials/01-models_mapping/plot_1_tensor_models.html#sphx-glr-content-tutorials-01-models-mapping-plot-1-tensor-models-py http://discretize.simpeg.xyz/en/master/tutorials/mesh_generation/4_tree_mesh.html#sphx-glr-tutorials-mesh-generation-4-tree-mesh-py https://docs.simpeg.xyz/content/tutorials/07-fdem/plot_fwd_2_fem_cyl.html#sphx-glr-content-tutorials-07-fdem-plot-fwd-2-fem-cyl-py https://docs.simpeg.xyz/content/examples/05-fdem/plot_inv_fdem_loop_loop_2Dinversion.html#sphx-glr-content-examples-05-fdem-plot-inv-fdem-loop-loop-2dinversion-py """ # Frequencies being predicted frequencies = [detector.frequency] # Conductivity in S/m (or resistivity in Ohm m) background_conductivity = 1e-6 air_conductivity = 1e-8 # Permeability in H/m background_permeability = mu_0 air_permeability = mu_0 """Survey""" # Defining transmitter locations acquisition_spacing = collection.spacing acq_area_xmin, acq_area_xmax = collection.x_min, collection.x_max acq_area_ymin, acq_area_ymax = collection.y_min, collection.y_max Nx = int((acq_area_xmax - acq_area_xmin) / acquisition_spacing + 1) Ny = int((acq_area_ymax - acq_area_ymin) / acquisition_spacing + 1) xtx, ytx, ztx = np.meshgrid(np.linspace(acq_area_xmin, acq_area_xmax, Nx), np.linspace(acq_area_ymin, acq_area_ymax, Ny), [collection.height]) source_locations = np.c_[mkvc(xtx), mkvc(ytx), mkvc(ztx)] ntx = np.size(xtx) # Define receiver locations xrx, yrx, zrx = np.meshgrid(np.linspace(acq_area_xmin, acq_area_xmax, Nx), np.linspace(acq_area_ymin, acq_area_ymax, Ny), [collection.height]) receiver_locations = np.c_[mkvc(xrx), mkvc(yrx), mkvc(zrx)] # Create empty list to store sources source_list = [] # Each unique location and frequency defines a new transmitter for ii in range(len(frequencies)): for jj in range(ntx): # Define receivers of different type at each location bxr_receiver = fdem.receivers.PointMagneticFluxDensitySecondary( receiver_locations[jj, :], "x", "real") bxi_receiver = fdem.receivers.PointMagneticFluxDensitySecondary( receiver_locations[jj, :], "x", "imag") byr_receiver = fdem.receivers.PointMagneticFluxDensitySecondary( receiver_locations[jj, :], "y", "real") byi_receiver = fdem.receivers.PointMagneticFluxDensitySecondary( receiver_locations[jj, :], "y", "imag") bzr_receiver = fdem.receivers.PointMagneticFluxDensitySecondary( receiver_locations[jj, :], "z", "real") bzi_receiver = fdem.receivers.PointMagneticFluxDensitySecondary( receiver_locations[jj, :], "z", "imag") receivers_list = [ bxr_receiver, bxi_receiver, byr_receiver, byi_receiver, bzr_receiver, bzi_receiver ] # Must define the transmitter properties and associated receivers source_list.append( fdem.sources.MagDipole(receivers_list, frequencies[ii], source_locations[jj], orientation="z", moment=detector.get_mag_moment())) survey = fdem.Survey(source_list) '''Mesh''' dh = 0.1 # base cell width dom_width = 20.0 # domain width # num. base cells nbc = 2**int(np.round(np.log(dom_width / dh) / np.log(2.0))) # Define the base mesh h = [(dh, nbc)] mesh = TreeMesh([h, h, h], x0="CCC") # Mesh refinement near transmitters and receivers mesh = refine_tree_xyz(mesh, receiver_locations, octree_levels=[2, 4], method="radial", finalize=False) # Refine core mesh region xp, yp, zp = np.meshgrid([-1.5, 1.5], [-1.5, 1.5], [-6, -4]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] mesh = refine_tree_xyz(mesh, xyz, octree_levels=[0, 6], method="box", finalize=False) mesh.finalize() '''Maps''' # Find cells that are active in the forward modeling (cells below surface) ind_active = mesh.gridCC[:, 2] < 0 # Define mapping from model to active cells active_sigma_map = maps.InjectActiveCells(mesh, ind_active, air_conductivity) active_mu_map = maps.InjectActiveCells(mesh, ind_active, air_permeability) # Define model. Models in SimPEG are vector arrays N = int(ind_active.sum()) model = np.kron(np.ones((N, 1)), np.c_[background_conductivity, background_permeability]) ind_cylinder = getIndicesCylinder( [target.position[0], target.position[1], target.position[2]], target.radius, target.length, [target.pitch, target.roll], mesh.gridCC) ind_cylinder = ind_cylinder[ind_active] model[ind_cylinder, :] = np.c_[target.conductivity, target.permeability] # Create model vector and wires model = mkvc(model) wire_map = maps.Wires(("sigma", N), ("mu", N)) # Use combo maps to map from model to mesh sigma_map = active_sigma_map * wire_map.sigma mu_map = active_mu_map * wire_map.mu '''Simulation''' simulation = fdem.simulation.Simulation3DMagneticFluxDensity( mesh, survey=survey, sigmaMap=sigma_map, muMap=mu_map, Solver=Solver) '''Predict''' # Compute predicted data for a your model. dpred = simulation.dpred(model) dpred = dpred * 1e9 # Data are organized by frequency, transmitter location, then by receiver. # We had nFreq transmitters and each transmitter had 2 receivers (real and # imaginary component). So first we will pick out the real and imaginary # data bx_real = dpred[0:len(dpred):6] bx_imag = dpred[1:len(dpred):6] bx_total = np.sqrt(np.square(bx_real) + np.square(bx_imag)) by_real = dpred[2:len(dpred):6] by_imag = dpred[3:len(dpred):6] by_total = np.sqrt(np.square(by_real) + np.square(by_imag)) bz_real = dpred[4:len(dpred):6] bz_imag = dpred[5:len(dpred):6] bz_total = np.sqrt(np.square(bz_real) + np.square(bz_imag)) mag_data = np.c_[mkvc(bx_total), mkvc(by_total), mkvc(bz_total)] return receiver_locations, mag_data, mesh, sigma_map * model
def set_mesh( self, topo=None, dx=None, dy=None, dz=None, corezlength=None, npad_x=None, npad_y=None, npad_z=None, pad_rate_x=None, pad_rate_y=None, pad_rate_z=None, ncell_per_dipole=None, mesh_type="TensorMesh", dimension=2, method="nearest", ): """ Set up a mesh for a given DC survey """ # Update properties if npad_x is None: npad_x = self.npad_x self.npad_x = npad_x if npad_z is None: npad_z = self.npad_z self.npad_z = npad_z if pad_rate_x is None: pad_rate_x = self.pad_rate_x self.pad_rate_x = pad_rate_x if pad_rate_z is None: pad_rate_z = self.pad_rate_z self.pad_rate_z = pad_rate_z if ncell_per_dipole is None: ncell_per_dipole = self.ncell_per_dipole self.ncell_per_dipole = ncell_per_dipole # 2D or 3D mesh if dimension not in [2, 3]: raise NotImplementedError( "Set mesh has not been implemented for a 1D system") if dimension == 2: z_ind = 1 else: z_ind = 2 a = abs(np.diff(np.sort(self.electrode_locations[:, 0]))).min() lineLength = abs(self.electrode_locations[:, 0].max() - self.electrode_locations[:, 0].min()) dx_ideal = a / ncell_per_dipole if dx is None: dx = dx_ideal print("dx is set to {} m (samllest electrode spacing ({}) / {})". format(dx, a, ncell_per_dipole)) if dz is None: dz = dx * 0.5 print("dz ({} m) is set to dx ({} m) / {}".format(dz, dx, 2)) if dimension == 3: if dy is None: print("dy is set equal to dx") dy = dx self.dy = dy if npad_y is None: npad_y = self.npad_y self.npad_y = npad_y if pad_rate_y is None: pad_rate_y = self.pad_rate_y self.pad_rate_y = pad_rate_y x0 = self.electrode_locations[:, 0].min() if topo is None: # For 2D mesh if dimension == 2: # sort by x row_idx = np.lexsort((self.electrode_locations[:, 0], )) # For 3D mesh else: # sort by x, then by y row_idx = np.lexsort( (self.electrode_locations[:, 1], self.electrode_locations[:, 0])) locs = self.electrode_locations[row_idx, :] else: # For 2D mesh if dimension == 2: mask = np.isin(self.electrode_locations[:, 0], topo[:, 0]) if np.any(mask): warnings.warn( "Because the x coordinates of some topo and electrodes are the same," " we excluded electrodes with the same coordinates.", RuntimeWarning, ) locs_tmp = np.vstack( (topo, self.electrode_locations[~mask, :])) row_idx = np.lexsort((locs_tmp[:, 0], )) else: dtype = [("x", np.float64), ("y", np.float64)] mask = np.isin( self.electrode_locations[:, [0, 1]].copy().view(dtype), topo[:, [0, 1]].copy().view(dtype), ).flatten() if np.any(mask): warnings.warn( "Because the x and y coordinates of some topo and electrodes are the same," " we excluded electrodes with the same coordinates.", RuntimeWarning, ) locs_tmp = np.vstack( (topo, self.electrode_locations[~mask, :])) row_idx = np.lexsort((locs_tmp[:, 1], locs_tmp[:, 0])) locs = locs_tmp[row_idx, :] if dx > dx_ideal: # warnings.warn( # "Input dx ({}) is greater than expected \n We recommend using {:0.1e} m cells, that is, {} cells per {0.1e} m dipole length".format(dx, dx_ideal, ncell_per_dipole, a) # ) pass # Set mesh properties to class instance self.dx = dx self.dz = dz zmax = locs[:, z_ind].max() zmin = locs[:, z_ind].min() # 3 cells each for buffer corexlength = lineLength + dx * 6 if corezlength is None: dz_topo = locs[:, 1].max() - locs[:, 1].min() corezlength = self.grids[:, z_ind].max() + dz_topo self.corezlength = corezlength if mesh_type == "TensorMesh": ncx = np.round(corexlength / dx) ncz = np.round(corezlength / dz) hx = [(dx, npad_x, -pad_rate_x), (dx, ncx), (dx, npad_x, pad_rate_x)] hz = [(dz, npad_z, -pad_rate_z), (dz, ncz)] x0_mesh = -( (dx * pad_rate_x**(np.arange(npad_x) + 1)).sum() + dx * 3 - x0) z0_mesh = (-( (dz * pad_rate_z**(np.arange(npad_z) + 1)).sum() + dz * ncz) + zmax) # For 2D mesh if dimension == 2: h = [hx, hz] x0_for_mesh = [x0_mesh, z0_mesh] self.xyzlim = np.vstack( (np.r_[x0, x0 + lineLength], np.r_[zmax - corezlength, zmax])) fill_value = "extrapolate" # For 3D mesh else: ylocs = np.unique(self.electrode_locations[:, 1]) ymin, ymax = ylocs.min(), ylocs.max() # 3 cells each for buffer in y-direction coreylength = ymax - ymin + dy * 6 ncy = np.round(coreylength / dy) hy = [(dy, npad_y, -pad_rate_y), (dy, ncy), (dy, npad_y, pad_rate_y)] y0 = ylocs.min() - dy / 2.0 y0_mesh = -((dy * pad_rate_y**(np.arange(npad_y) + 1)).sum() + dy * 3 - y0) h = [hx, hy, hz] x0_for_mesh = [x0_mesh, y0_mesh, z0_mesh] self.xyzlim = np.vstack(( np.r_[x0, x0 + lineLength], np.r_[ymin - dy * 3, ymax + dy * 3], np.r_[zmax - corezlength, zmax], )) mesh = TensorMesh(h, x0=x0_for_mesh) elif mesh_type == "TREE": # Quadtree mesh if dimension == 2: pad_length_x = np.sum(meshTensor([(dx, npad_x, pad_rate_x)])) pad_length_z = np.sum(meshTensor([(dz, npad_z, pad_rate_z)])) dom_width_x = lineLength + 2 * pad_length_x # domain width x dom_width_z = corezlength + pad_length_z # domain width z nbcx = 2**int(np.ceil(np.log(dom_width_x / dx) / np.log(2.0))) # num. base cells x nbcz = 2**int(np.ceil(np.log(dom_width_z / dz) / np.log(2.0))) # num. base cells z length = 0.0 dz_tmp = dz octree_levels = [] while length < corezlength: length += 5 * dz_tmp octree_levels.append(5) dz_tmp *= 2 # Define the base mesh hx = [(dx, nbcx)] hz = [(dz, nbcz)] mesh_width = np.sum(meshTensor(hx)) mesh_height = np.sum(meshTensor(hz)) array_midpoint = 0.5 * (self.electrode_locations[:, 0].min() + self.electrode_locations[:, 0].max()) mesh = TreeMesh( [hx, hz], x0=[array_midpoint - mesh_width / 2, zmax - mesh_height]) # mesh = TreeMesh([hx, hz], x0='CN') # Mesh refinement based on topography mesh = refine_tree_xyz( mesh, self.electrode_locations, octree_levels=octree_levels, method="radial", finalize=False, ) mesh.finalize() self.xyzlim = np.vstack(( np.r_[self.electrode_locations[:, 0].min(), self.electrode_locations[:, 0].max(), ], np.r_[zmax - corezlength, zmax], )) # Octree mesh elif dimension == 3: raise NotImplementedError( "set_mesh has not implemented 3D TreeMesh (yet)") else: raise NotImplementedError( "set_mesh currently generates TensorMesh or TreeMesh") actind = surface2ind_topo(mesh, locs, method=method, fill_value=np.nan) return mesh, actind
def dpred(self): target = self.survey.source.target collection = self.survey.source.collection '''Mesh''' # Conductivity in S/m (or resistivity in Ohm m) background_conductivity = 1e-6 air_conductivity = 1e-8 # Permeability in H/m background_permeability = mu_0 air_permeability = mu_0 dh = 0.1 # base cell width dom_width = 20.0 # domain width # num. base cells nbc = 2**int(np.round(np.log(dom_width / dh) / np.log(2.0))) # Define the base mesh h = [(dh, nbc)] mesh = TreeMesh([h, h, h], x0="CCC") # Mesh refinement near transmitters and receivers mesh = refine_tree_xyz(mesh, collection.receiver_location, octree_levels=[2, 4], method="radial", finalize=False) # Refine core mesh region xp, yp, zp = np.meshgrid([-1.5, 1.5], [-1.5, 1.5], [-6, -4]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] mesh = refine_tree_xyz(mesh, xyz, octree_levels=[0, 6], method="box", finalize=False) mesh.finalize() '''Maps''' # Find cells that are active in the forward modeling (cells below surface) ind_active = mesh.gridCC[:, 2] < 0 # Define mapping from model to active cells active_sigma_map = maps.InjectActiveCells(mesh, ind_active, air_conductivity) active_mu_map = maps.InjectActiveCells(mesh, ind_active, air_permeability) # Define model. Models in SimPEG are vector arrays N = int(ind_active.sum()) model = np.kron( np.ones((N, 1)), np.c_[background_conductivity, background_permeability]) ind_cylinder = self.getIndicesCylinder( [target.position[0], target.position[1], target.position[2]], target.radius, target.length, [target.pitch, target.roll], mesh.gridCC) ind_cylinder = ind_cylinder[ind_active] model[ind_cylinder, :] = np.c_[target.conductivity, target.permeability] # Create model vector and wires model = mkvc(model) wire_map = maps.Wires(("sigma", N), ("mu", N)) # Use combo maps to map from model to mesh sigma_map = active_sigma_map * wire_map.sigma mu_map = active_mu_map * wire_map.mu '''Simulation''' simulation = fdem.simulation.Simulation3DMagneticFluxDensity( mesh, survey=self.survey.survey, sigmaMap=sigma_map, muMap=mu_map, Solver=Solver) '''Predict''' # Compute predicted data for your model. dpred = simulation.dpred(model) dpred = dpred * 1e9 # Data are organized by frequency, transmitter location, then by receiver. # We had nFreq transmitters and each transmitter had 2 receivers (real and # imaginary component). So first we will pick out the real and imaginary # data bx_real = dpred[0:len(dpred):6] bx_imag = dpred[1:len(dpred):6] bx_total = np.sqrt(np.square(bx_real) + np.square(bx_imag)) by_real = dpred[2:len(dpred):6] by_imag = dpred[3:len(dpred):6] by_total = np.sqrt(np.square(by_real) + np.square(by_imag)) bz_real = dpred[4:len(dpred):6] bz_imag = dpred[5:len(dpred):6] bz_total = np.sqrt(np.square(bz_real) + np.square(bz_imag)) mag_data = np.c_[mkvc(bx_total), mkvc(by_total), mkvc(bz_total)] if collection.SNR is not None: mag_data = self.mag_data_add_noise(mag_data, collection.SNR) data = np.c_[collection.receiver_location, mag_data] # data = (data, ) return data # 只保留磁场强度数据,删除后面的两个参数
dh = 5 # minimum cell width (base mesh cell width) nbc = 64 # number of base mesh cells in x # Define base mesh (domain and finest discretization) h = dh * np.ones(nbc) mesh = TreeMesh([h, h]) # Define corner points for rectangular box xp, yp = np.meshgrid([120., 240.], [80., 160.]) xy = np.c_[mkvc(xp), mkvc(yp)] # mkvc creates vectors # Discretize to finest cell size within rectangular box mesh = refine_tree_xyz(mesh, xy, octree_levels=[2, 2], method='box', finalize=False) mesh.finalize() # Must finalize tree mesh before use mesh.plotGrid(show_it=True) ############################################### # Intermediate Example and Plotting # --------------------------------- # # The widths of the base mesh cells do not need to be the same in x and y. # However the number of base mesh cells in x and y each needs to be a power of 2. # # Here we show topography-based mesh refinement and refinement about a
# - The skin depth is ~500*np.sqrt(rho/f) # # dh = 25.0 # base cell width dom_width = 3000.0 # domain width nbc = 2**int(np.round(np.log(dom_width / dh) / np.log(2.0))) # num. base cells # Define the base mesh h = [(dh, nbc)] mesh = TreeMesh([h, h, h], x0="CCC") # Mesh refinement based on topography mesh = refine_tree_xyz(mesh, xyz_topo, octree_levels=[0, 0, 0, 1], method="surface", finalize=False) # Mesh refinement near transmitters and receivers mesh = refine_tree_xyz(mesh, receiver_locations, octree_levels=[2, 4], method="radial", finalize=False) # Refine core mesh region xp, yp, zp = np.meshgrid([-250.0, 250.0], [-250.0, 250.0], [-250.0, 0.0]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] mesh = refine_tree_xyz(mesh, xyz,
def setUp(self): # We will assume a vertical inducing field H0 = (50000.0, 90.0, 0.0) # The magnetization is set along a different direction (induced + remanence) M = np.array([45.0, 90.0]) # Block with an effective susceptibility chi_e = 0.05 # Create grid of points for topography # Lets create a simple Gaussian topo and set the active cells [xx, yy] = np.meshgrid(np.linspace(-200, 200, 50), np.linspace(-200, 200, 50)) b = 100 A = 50 zz = A * np.exp(-0.5 * ((xx / b)**2.0 + (yy / b)**2.0)) topo = np.c_[mkvc(xx), mkvc(yy), mkvc(zz)] # Create an array of observation points xr = np.linspace(-100.0, 100.0, 20) yr = np.linspace(-100.0, 100.0, 20) X, Y = np.meshgrid(xr, yr) Z = A * np.exp(-0.5 * ((X / b)**2.0 + (Y / b)**2.0)) + 10 # Create a MAGsurvey rxLoc = np.c_[mkvc(X.T), mkvc(Y.T), mkvc(Z.T)] rxList = magnetics.receivers.Point(rxLoc) srcField = magnetics.sources.SourceField(receiver_list=[rxList], parameters=H0) survey = magnetics.survey.Survey(srcField) ############################################################################### # Inversion Mesh # Create a mesh h = [5, 5, 5] padDist = np.ones((3, 2)) * 100 mesh = mesh_builder_xyz(rxLoc, h, padding_distance=padDist, depth_core=100, mesh_type="tree") mesh = refine_tree_xyz(mesh, topo, method="surface", octree_levels=[4, 4], finalize=True) # Define an active cells from topo actv = utils.surface2ind_topo(mesh, topo) nC = int(actv.sum()) # Convert the inclination declination to vector in Cartesian M_xyz = utils.mat_utils.dip_azimuth2cartesian( np.ones(nC) * M[0], np.ones(nC) * M[1]) # Get the indicies of the magnetized block ind = utils.model_builder.getIndicesBlock( np.r_[-20, -20, -10], np.r_[20, 20, 25], mesh.gridCC, )[0] # Assign magnetization value, inducing field strength will # be applied in by the :class:`SimPEG.PF.Magnetics` problem model = np.zeros(mesh.nC) model[ind] = chi_e # Remove air cells model = model[actv] # Creat reduced identity map idenMap = maps.IdentityMap(nP=nC) # Create the forward model operator simulation = magnetics.Simulation3DIntegral( survey=survey, mesh=mesh, chiMap=idenMap, actInd=actv, store_sensitivities="forward_only", ) simulation.M = M_xyz # Compute some data and add some random noise synthetic_data = simulation.dpred(model) # Split the data in components nD = rxLoc.shape[0] std = 5 # nT synthetic_data += np.random.randn(nD) * std wd = np.ones(nD) * std # Assigne data and uncertainties to the survey data_object = data.Data(survey, dobs=synthetic_data, noise_floor=wd) ###################################################################### # Equivalent Source # Get the active cells for equivalent source is the top only surf = utils.model_utils.surface_layer_index(mesh, topo) nC = np.count_nonzero(surf) # Number of active cells mstart = np.ones(nC) * 1e-4 # Create active map to go from reduce set to full surfMap = maps.InjectActiveCells(mesh, surf, np.nan) # Create identity map idenMap = maps.IdentityMap(nP=nC) # Create static map simulation = magnetics.simulation.Simulation3DIntegral( mesh=mesh, survey=survey, chiMap=idenMap, actInd=surf, store_sensitivities="ram", ) simulation.model = mstart # Create a regularization function, in this case l2l2 reg = regularization.Sparse(mesh, indActive=surf, mapping=maps.IdentityMap(nP=nC), alpha_z=0) reg.mref = np.zeros(nC) # Specify how the optimization will proceed, set susceptibility bounds to inf opt = optimization.ProjectedGNCG( maxIter=10, lower=-np.inf, upper=np.inf, maxIterLS=5, maxIterCG=5, tolCG=1e-3, ) # Define misfit function (obs-calc) dmis = data_misfit.L2DataMisfit(simulation=simulation, data=data_object) # Create the default L2 inverse problem from the above objects invProb = inverse_problem.BaseInvProblem(dmis, reg, opt) # Specify how the initial beta is found betaest = directives.BetaEstimate_ByEig(beta0_ratio=2) # Target misfit to stop the inversion, # try to fit as much as possible of the signal, we don't want to lose anything IRLS = directives.Update_IRLS(f_min_change=1e-3, minGNiter=1, beta_tol=1e-1, max_irls_iterations=5) update_Jacobi = directives.UpdatePreconditioner() # Put all the parts together inv = inversion.BaseInversion( invProb, directiveList=[betaest, IRLS, update_Jacobi]) # Run the equivalent source inversion print("Solving for Equivalent Source") mrec = inv.run(mstart) ######################################################## # Forward Amplitude Data # ---------------------- # # Now that we have an equialent source layer, we can forward model alh three # components of the field and add them up: :math:`|B| = \sqrt{( Bx^2 + Bx^2 + Bx^2 )}` # rxList = magnetics.receivers.Point(rxLoc, components=["bx", "by", "bz"]) srcField = magnetics.sources.SourceField(receiver_list=[rxList], parameters=H0) surveyAmp = magnetics.survey.Survey(srcField) simulation = magnetics.simulation.Simulation3DIntegral( mesh=mesh, survey=surveyAmp, chiMap=idenMap, actInd=surf, is_amplitude_data=True, store_sensitivities="forward_only", ) bAmp = simulation.fields(mrec) ###################################################################### # Amplitude Inversion # ------------------- # # Now that we have amplitude data, we can invert for an effective # susceptibility. This is a non-linear inversion. # # Create active map to go from reduce space to full actvMap = maps.InjectActiveCells(mesh, actv, -100) nC = int(actv.sum()) # Create identity map idenMap = maps.IdentityMap(nP=nC) mstart = np.ones(nC) * 1e-4 # Create the forward model operator simulation = magnetics.simulation.Simulation3DIntegral( survey=surveyAmp, mesh=mesh, chiMap=idenMap, actInd=actv, is_amplitude_data=True, ) data_obj = data.Data(survey, dobs=bAmp, noise_floor=wd) # Create a sparse regularization reg = regularization.Sparse(mesh, indActive=actv, mapping=idenMap) reg.norms = np.c_[1, 0, 0, 0] reg.mref = np.zeros(nC) # Data misfit function dmis = data_misfit.L2DataMisfit(simulation=simulation, data=data_obj) # Add directives to the inversion opt = optimization.ProjectedGNCG(maxIter=10, lower=0.0, upper=1.0, maxIterLS=5, maxIterCG=5, tolCG=1e-3) invProb = inverse_problem.BaseInvProblem(dmis, reg, opt) # Here is the list of directives betaest = directives.BetaEstimate_ByEig(beta0_ratio=1) # Specify the sparse norms IRLS = directives.Update_IRLS( max_irls_iterations=5, f_min_change=1e-3, minGNiter=1, coolingRate=1, beta_search=False, ) # Special directive specific to the mag amplitude problem. The sensitivity # weights are update between each iteration. update_SensWeight = directives.UpdateSensitivityWeights() update_Jacobi = directives.UpdatePreconditioner() # Put all together self.inv = inversion.BaseInversion( invProb, directiveList=[update_SensWeight, betaest, IRLS, update_Jacobi]) self.mstart = mstart self.model = model self.sim = simulation
# # Refine surface topography #[xx, yy] = np.meshgrid(M.vectorNx, M.vectorNy) #[xx, yy,zz] = np.meshgrid([-5000,5000], [-5000,5000],[-100,100]) #zz = 0.*(xx**2 + yy**2) - 1000. ##zz = np.zeros([300,300]) #pts = np.c_[mkvc(xx), mkvc(yy), mkvc(zz)] #M = refine_tree_xyz( # M, pts, octree_levels=[1, 1], method='surface', finalize=False # ) # Refine box xp, yp, zp = np.meshgrid([-600., 600.], [-1000., 1000.], [300., -4000.]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] M = refine_tree_xyz(M, xyz, octree_levels=[1, 0], method='box', finalize=False) ## Refine surface no alvo #xp, yp, zp = np.meshgrid([-5000., 5000.], [-5000., 5000.], [-1000., -2000.]) #xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] # #M = refine_tree_xyz( # M, xyz, octree_levels=[1,0], method='surface', finalize=False) #Refine rest of the grid def refine(cell): if np.sqrt(((np.r_[cell.center] - 0.5)**2).sum()) < 0.4: return 1 return 1
# Compute number of base mesh cells required in x and y nbcx = 2**int(np.round(np.log(x_length / dx) / np.log(2.))) nbcy = 2**int(np.round(np.log(y_length / dy) / np.log(2.))) # Define the base mesh hx = [(dx, nbcx)] hy = [(dy, nbcy)] M = TreeMesh([hx, hy], x0='CC') # Refine mesh near points xx = np.linspace(-10000, 10000, 3000) yy = 400 * np.sin((2 * xx * np.pi) / 1000) pts = np.c_[mkvc(xx), mkvc(yy)] M = refine_tree_xyz(M, pts, octree_levels=[2, 2], method='radial', finalize=False) M.finalize() print("\n the mesh has {} cells".format(M)) ccMesh = M.gridCC print('indices:', np.size(ccMesh)) # We can apply the plotGrid method and output to a specified axes object fig = plt.figure(figsize=(6, 6)) ax = fig.add_subplot(111) M.plotGrid(ax=ax) ax.set_xbound(M.x0[0], M.x0[0] + np.sum(M.hx)) ax.set_ybound(M.x0[1], M.x0[1] + np.sum(M.hy)) ax.set_title('QuadTree Mesh')
hz = [0000] # definir fronteira das camadas n_camadas = len(hz) #========================================= #Criando mais uma área de dricretização #========================================= for i in range(0, n_camadas, 1): xp, yp, zp = np.meshgrid([-(nbcx * dhx) / 32, (nbcx * dhx) / 32], [-(nbcy * dhy) / 32, (nbcy * dhy) / 32], [hz[i] - 1, hz[i] + 1]) # print(hz[i]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] # mkvc creates vectors M = refine_tree_xyz(M, xyz, octree_levels=[2, 2, 4], method='radial', finalize=False) #Define corner points for disc xp, yp, zp = np.meshgrid([-(nbcx * dhx) / 32, (nbcx * dhx) / 64], [-(nbcy * dhy) / 64, (nbcy * dhy) / 32], [-150, -350]) # xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] # mkvc creates vectors # #Discretize to finest cell size within rectangular box M = refine_tree_xyz(M, xyz, octree_levels=[3, 3, 3], method='radial', finalize=False)
# Compute number of base mesh cells required in x and y nbcx = 2**int(np.round(np.log(x_length / dx) / np.log(2.0))) nbcy = 2**int(np.round(np.log(y_length / dy) / np.log(2.0))) nbcz = 2**int(np.round(np.log(z_length / dz) / np.log(2.0))) # Define the base mesh hx = [(dx, nbcx)] hy = [(dy, nbcy)] hz = [(dz, nbcz)] mesh = TreeMesh([hx, hy, hz], x0="CCN") # Refine based on surface topography mesh = refine_tree_xyz(mesh, xyz_topo, octree_levels=[2, 2], method="surface", finalize=False) # Refine box base on region of interest xp, yp, zp = np.meshgrid([-100.0, 100.0], [-100.0, 100.0], [-80.0, 0.0]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] mesh = refine_tree_xyz(mesh, xyz, octree_levels=[2, 2], method="box", finalize=False) mesh.finalize()
def setUp(self): np.random.seed(0) H0 = (50000.0, 90.0, 0.0) # The magnetization is set along a different # direction (induced + remanence) M = np.array([45.0, 90.0]) # Create grid of points for topography # Lets create a simple Gaussian topo # and set the active cells [xx, yy] = np.meshgrid(np.linspace(-200, 200, 50), np.linspace(-200, 200, 50)) b = 100 A = 50 zz = A * np.exp(-0.5 * ((xx / b)**2.0 + (yy / b)**2.0)) # We would usually load a topofile topo = np.c_[utils.mkvc(xx), utils.mkvc(yy), utils.mkvc(zz)] # Create and array of observation points xr = np.linspace(-100.0, 100.0, 20) yr = np.linspace(-100.0, 100.0, 20) X, Y = np.meshgrid(xr, yr) Z = A * np.exp(-0.5 * ((X / b)**2.0 + (Y / b)**2.0)) + 5 # Create a MAGsurvey xyzLoc = np.c_[utils.mkvc(X.T), utils.mkvc(Y.T), utils.mkvc(Z.T)] rxLoc = mag.Point(xyzLoc) srcField = mag.SourceField([rxLoc], parameters=H0) survey = mag.Survey(srcField) # Create a mesh h = [5, 5, 5] padDist = np.ones((3, 2)) * 100 mesh = mesh_builder_xyz(xyzLoc, h, padding_distance=padDist, depth_core=100, mesh_type="tree") mesh = refine_tree_xyz(mesh, topo, method="surface", octree_levels=[4, 4], finalize=True) self.mesh = mesh # Define an active cells from topo actv = utils.surface2ind_topo(mesh, topo) nC = int(actv.sum()) model = np.zeros((mesh.nC, 3)) # Convert the inclination declination to vector in Cartesian M_xyz = utils.mat_utils.dip_azimuth2cartesian(M[0], M[1]) # Get the indicies of the magnetized block ind = utils.model_builder.getIndicesBlock( np.r_[-20, -20, -10], np.r_[20, 20, 25], mesh.gridCC, )[0] # Assign magnetization values model[ind, :] = np.kron(np.ones((ind.shape[0], 1)), M_xyz * 0.05) # Remove air cells self.model = model[actv, :] # Create active map to go from reduce set to full self.actvMap = maps.InjectActiveCells(mesh, actv, np.nan) # Creat reduced identity map idenMap = maps.IdentityMap(nP=nC * 3) # Create the forward model operator sim = mag.Simulation3DIntegral( self.mesh, survey=survey, model_type="vector", chiMap=idenMap, actInd=actv, store_sensitivities="disk", ) self.sim = sim # Compute some data and add some random noise data = sim.make_synthetic_data(utils.mkvc(self.model), relative_error=0.0, noise_floor=5.0, add_noise=True) # This Mapping connects the regularizations for the three-component # vector model wires = maps.Wires(("p", nC), ("s", nC), ("t", nC)) # Create three regularization for the different components # of magnetization reg_p = regularization.Sparse(mesh, indActive=actv, mapping=wires.p) reg_p.mref = np.zeros(3 * nC) reg_s = regularization.Sparse(mesh, indActive=actv, mapping=wires.s) reg_s.mref = np.zeros(3 * nC) reg_t = regularization.Sparse(mesh, indActive=actv, mapping=wires.t) reg_t.mref = np.zeros(3 * nC) reg = reg_p + reg_s + reg_t reg.mref = np.zeros(3 * nC) # Data misfit function dmis = data_misfit.L2DataMisfit(simulation=sim, data=data) # dmis.W = 1./survey.std # Add directives to the inversion opt = optimization.ProjectedGNCG(maxIter=10, lower=-10, upper=10.0, maxIterLS=5, maxIterCG=5, tolCG=1e-4) invProb = inverse_problem.BaseInvProblem(dmis, reg, opt) # A list of directive to control the inverson betaest = directives.BetaEstimate_ByEig(beta0_ratio=1e1) # Here is where the norms are applied # Use pick a treshold parameter empirically based on the distribution of # model parameters IRLS = directives.Update_IRLS(f_min_change=1e-3, max_irls_iterations=0, beta_tol=5e-1) # Pre-conditioner update_Jacobi = directives.UpdatePreconditioner() sensitivity_weights = directives.UpdateSensitivityWeights( everyIter=False) inv = inversion.BaseInversion( invProb, directiveList=[sensitivity_weights, IRLS, update_Jacobi, betaest]) # Run the inversion m0 = np.ones(3 * nC) * 1e-4 # Starting model mrec_MVIC = inv.run(m0) sim.chiMap = maps.SphericalSystem(nP=nC * 3) self.mstart = sim.chiMap.inverse(mrec_MVIC) dmis.simulation.model = self.mstart beta = invProb.beta # Create a block diagonal regularization wires = maps.Wires(("amp", nC), ("theta", nC), ("phi", nC)) # Create a Combo Regularization # Regularize the amplitude of the vectors reg_a = regularization.Sparse(mesh, indActive=actv, mapping=wires.amp) reg_a.norms = np.c_[0.0, 0.0, 0.0, 0.0] # Sparse on the model and its gradients reg_a.mref = np.zeros(3 * nC) # Regularize the vertical angle of the vectors reg_t = regularization.Sparse(mesh, indActive=actv, mapping=wires.theta) reg_t.alpha_s = 0.0 # No reference angle reg_t.space = "spherical" reg_t.norms = np.c_[2.0, 0.0, 0.0, 0.0] # Only norm on gradients used # Regularize the horizontal angle of the vectors reg_p = regularization.Sparse(mesh, indActive=actv, mapping=wires.phi) reg_p.alpha_s = 0.0 # No reference angle reg_p.space = "spherical" reg_p.norms = np.c_[2.0, 0.0, 0.0, 0.0] # Only norm on gradients used reg = reg_a + reg_t + reg_p reg.mref = np.zeros(3 * nC) Lbound = np.kron(np.asarray([0, -np.inf, -np.inf]), np.ones(nC)) Ubound = np.kron(np.asarray([10, np.inf, np.inf]), np.ones(nC)) # Add directives to the inversion opt = optimization.ProjectedGNCG( maxIter=5, lower=Lbound, upper=Ubound, maxIterLS=5, maxIterCG=5, tolCG=1e-3, stepOffBoundsFact=1e-3, ) opt.approxHinv = None invProb = inverse_problem.BaseInvProblem(dmis, reg, opt, beta=beta) # Here is where the norms are applied IRLS = directives.Update_IRLS( f_min_change=1e-4, max_irls_iterations=5, minGNiter=1, beta_tol=0.5, coolingRate=1, coolEps_q=True, sphericalDomain=True, ) # Special directive specific to the mag amplitude problem. The sensitivity # weights are update between each iteration. ProjSpherical = directives.ProjectSphericalBounds() sensitivity_weights = directives.UpdateSensitivityWeights() update_Jacobi = directives.UpdatePreconditioner() self.inv = inversion.BaseInversion( invProb, directiveList=[ ProjSpherical, IRLS, sensitivity_weights, update_Jacobi ], )
# Define the base mesh hx = [(dx, nbcx)] hy = [(dy, nbcy)] hz = [(dz, nbcz)] M = simpeg.Mesh.TreeMesh([hx, hy, hz], x0='CCC') # Refine surface topography [xx, yy] = np.meshgrid(M.vectorNx, M.vectorNy) [xx, yy,zz] = np.meshgrid([-4000,4000], [-1000,1000],[-100,100]) zz = 0.*(xx**2 + yy**2) - 0. #zz = np.zeros([300,300]) pts = np.c_[mkvc(xx), mkvc(yy), mkvc(zz)] M = refine_tree_xyz( M, pts, octree_levels=[2, 2], method='surface', finalize=False ) # Refine box xp, yp, zp = np.meshgrid([-600., 600.], [-6500., 6500.], [200., -2600.]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] M = refine_tree_xyz( M, xyz, octree_levels=[1,1], method='box', finalize=False) # #Refine rest of the grid # def refine(cell): # if np.sqrt(((np.r_[cell.center]-0.5)**2).sum()) < 4000: # return 1 # return 1
# The refinement process is repeated twice to allow for a finer level around # the survey locations. # # Create a mesh h = [5, 5, 5] padDist = np.ones((3, 2)) * 100 mesh = mesh_builder_xyz(xyzLoc, h, padding_distance=padDist, depth_core=100, mesh_type="tree") mesh = refine_tree_xyz(mesh, topo, method="surface", octree_levels=[4, 4], finalize=True) # Define an active cells from topo actv = utils.surface2ind_topo(mesh, topo) nC = int(actv.sum()) ########################################################################### # A simple function to plot vectors in TreeMesh # # Should eventually end up on discretize # def plotVectorSectionsOctree(
def test_active_from_xyz(self): # Create 3D topo [xx, yy] = np.meshgrid(np.linspace(-200, 200, 50), np.linspace(-200, 200, 50)) b = 50 A = 50 zz = A * np.exp(-0.5 * ((xx / b)**2.0 + (yy / b)**2.0)) h = [5.0, 5.0, 5.0] # Test 1D Mesh topo1D = zz[25, :].ravel() mesh1D = discretize.TensorMesh([np.ones(10) * 20], x0="C") indtopoCC = active_from_xyz(mesh1D, topo1D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh1D, topo1D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 3) self.assertEqual(indtopoN.sum(), 2) # Test 2D Tensor mesh topo2D = np.c_[xx[25, :].ravel(), zz[25, :].ravel()] mesh_tensor = discretize.TensorMesh([[(h[0], 24)], [(h[1], 20)]], x0="CC") indtopoCC = active_from_xyz(mesh_tensor, topo2D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_tensor, topo2D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 434) self.assertEqual(indtopoN.sum(), 412) # test 2D Curvilinear mesh nodes_x = mesh_tensor.gridN[:, 0].reshape(mesh_tensor.vnN, order="F") nodes_y = mesh_tensor.gridN[:, 1].reshape(mesh_tensor.vnN, order="F") mesh_curvi = discretize.CurvilinearMesh([nodes_x, nodes_y]) indtopoCC = active_from_xyz(mesh_curvi, topo2D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_curvi, topo2D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 434) self.assertEqual(indtopoN.sum(), 412) # Test 2D Tree mesh mesh_tree = mesh_builder_xyz(topo2D, h[:2], mesh_type="TREE") mesh_tree = refine_tree_xyz( mesh_tree, topo2D, method="surface", octree_levels=[1], octree_levels_padding=None, finalize=True, ) indtopoCC = active_from_xyz(mesh_tree, topo2D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_tree, topo2D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 167) self.assertEqual(indtopoN.sum(), 119) # Test 3D Tensor meshes topo3D = np.c_[xx.ravel(), yy.ravel(), zz.ravel()] mesh_tensor = discretize.TensorMesh( [[(h[0], 24)], [(h[1], 20)], [(h[2], 30)]], x0="CCC") indtopoCC = active_from_xyz(mesh_tensor, topo3D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_tensor, topo3D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 10496) self.assertEqual(indtopoN.sum(), 10084) # test 3D Curvilinear mesh nodes_x = mesh_tensor.gridN[:, 0].reshape(mesh_tensor.vnN, order="F") nodes_y = mesh_tensor.gridN[:, 1].reshape(mesh_tensor.vnN, order="F") nodes_z = mesh_tensor.gridN[:, 2].reshape(mesh_tensor.vnN, order="F") mesh_curvi = discretize.CurvilinearMesh([nodes_x, nodes_y, nodes_z]) indtopoCC = active_from_xyz(mesh_curvi, topo3D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_curvi, topo3D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 10496) self.assertEqual(indtopoN.sum(), 10084) # Test 3D Tree mesh mesh_tree = mesh_builder_xyz(topo3D, h, mesh_type="TREE") mesh_tree = refine_tree_xyz( mesh_tree, topo3D, method="surface", octree_levels=[1], octree_levels_padding=None, finalize=True, ) indtopoCC = active_from_xyz(mesh_tree, topo3D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_tree, topo3D, grid_reference="N", method="nearest") self.assertIn(indtopoCC.sum(), [6292, 6299]) self.assertIn(indtopoN.sum(), [4632, 4639]) # Test 3D CYL Mesh ncr = 10 # number of mesh cells in r ncz = 15 # number of mesh cells in z dr = 15 # cell width r dz = 10 # cell width z npad_r = 4 # number of padding cells in r npad_z = 4 # number of padding cells in z exp_r = 1.25 # expansion rate of padding cells in r exp_z = 1.25 # expansion rate of padding cells in z hr = [(dr, ncr), (dr, npad_r, exp_r)] hz = [(dz, npad_z, -exp_z), (dz, ncz), (dz, npad_z, exp_z)] # A value of 1 is used to define the discretization in phi for this case. mesh_cyl = discretize.CylMesh([hr, 1, hz], x0="00C") indtopoCC = active_from_xyz(mesh_cyl, topo3D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_cyl, topo3D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 183) self.assertEqual(indtopoN.sum(), 171) htheta = meshTensor([(1.0, 4)]) htheta = htheta * 2 * np.pi / htheta.sum() mesh_cyl2 = discretize.CylMesh([hr, htheta, hz], x0="00C") with self.assertRaises(NotImplementedError): indtopoCC = active_from_xyz(mesh_cyl2, topo3D, grid_reference="CC", method="nearest")
# Define base mesh (domain and finest discretization) hx = dhx * np.ones(nbcx) hy = dhy * np.ones(nbcy) #hz = dhz*np.ones(nbcz) M = Mesh.TreeMesh([hx, hy]) M.x0 = np.r_[-(nbcx * dhx) / 2, -nbcy * dhy + 15000] #definir a camada xp, yp = np.meshgrid([-(nbcx * dhx) / 2, (nbcx * dhx) / 2], [1., -1.]) #layer xy = np.c_[mkvc(xp), mkvc(yp)] # mkvc creates vectors # Discretize to finest cell size within rectangular box M = refine_tree_xyz(M, xy, octree_levels=[1, 1], method='box', finalize=False) # Define objeto xp, yp = np.meshgrid([-(nbcx * dhx) / 32, (nbcx * dhx) / 32], [-10150, -10650.]) #goal xy = np.c_[mkvc(xp), mkvc(yp)] # mkvc creates vectors # Discretize to finest cell size within rectangular box M = refine_tree_xyz(M, xy, octree_levels=[4, 4], finalize=False, method='radial') #========================================= #Criando mais uma área de dricretização
# dh = 10.0 # base cell width dom_width_x = 2400.0 # domain width x dom_width_z = 1200.0 # domain width z nbcx = 2 ** int(np.round(np.log(dom_width_x / dh) / np.log(2.0))) # num. base cells x nbcz = 2 ** int(np.round(np.log(dom_width_z / dh) / np.log(2.0))) # num. base cells z # Define the base mesh hx = [(dh, nbcx)] hz = [(dh, nbcz)] mesh = TreeMesh([hx, hz], x0="CN") # Mesh refinement based on topography mesh = refine_tree_xyz( mesh, topo_xyz[:, [0, 2]], octree_levels=[1], method="surface", finalize=False ) # Mesh refinement near transmitters and receivers electrode_locations = np.r_[ survey.locations_a, survey.locations_b, survey.locations_m, survey.locations_n ] unique_locations = np.unique(electrode_locations, axis=0) mesh = refine_tree_xyz( mesh, unique_locations, octree_levels=[2, 4], method="radial", finalize=False ) # Refine core mesh region xp, zp = np.meshgrid([-800.0, 800.0], [-800.0, 0.0])
def run(plotIt=True): nFreq = 13 freqs = np.logspace(2, -2, nFreq) # x and y grid parameters dh = 10 # minimum cell width (base mesh cell width) dhx = dh dhy = dh dhz = 1.5 #Dimensao eixo vertical( base 2) nbcx = 2**12 # number of base mesh cells in x nbcy = 2**12 nbcz = 2**15 # Define base mesh (domain and finest discretization) hx = dhx * np.ones(nbcx) hy = dhy * np.ones(nbcy) hz = dhz * np.ones(nbcz) M = Mesh.TreeMesh([hx, hy, hz]) #M.x0 = np.r_[-(nbcx*dhx)/2,-(nbcy*dhy)/2,-(nbcz*dhz)/2] M.x0 = np.r_[-(nbcx * dhx) / 2, -(nbcy * dhy) / 2, -nbcz * dhz + 15000] hz = [0] # definir fronteira das camadas n_camadas = len(hz) #========================================= #Criando mais uma área(layer) de dricretização #========================================= for i in range(0, n_camadas, 1): xp, yp, zp = np.meshgrid([-(nbcx * dhx) / 1, (nbcx * dhx) / 1], [-(nbcy * dhy) / 1, (nbcy * dhy) / 1], [hz[i] - 1, hz[i] + 1]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] # mkvc creates vectors M = refine_tree_xyz(M, xyz, octree_levels=[0, 0, 1], method='radial', finalize=False) #========================================= #Criando um objeto(target) #========================================= xp, yp, zp = np.meshgrid([-(nbcx * dhx) / 32, (nbcx * dhx) / 32], [-(nbcy * dhy) / 32, (nbcy * dhy) / 32], [-150, -350]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] #refino M = refine_tree_xyz(M, xyz, octree_levels=[1, 1, 1], method='box', finalize=False) # M.finalize() print("\n the mesh has {} cells".format(M)) ccMesh = M.gridCC print('indices:', np.size(ccMesh)) ## ## ## ## conds = [1e-2, 1] sig = simpeg.Utils.ModelBuilder.defineBlock(M.gridCC, [-20000, -20000, -350], [20000, 20000, -150], conds) sig[M.gridCC[:, 2] > 0] = 1e-8 sigBG = np.zeros(M.nC) + conds[1] sigBG[M.gridCC[:, 2] > 0] = 1e-8 # # A boolean array specifying which cells lie on the boundary bInd = M.cellBoundaryInd ## Cell volumes v = M.vol fig = plt.figure() ax = fig.add_subplot(111) collect_obj, = M.plotSlice(np.log10(sig), normal='x', ax=ax, grid=True) plt.colorbar(collect_obj) ax.set_title('slice')
nbcy = 2**int(np.round(np.log(dom_width_y / dh) / np.log(2.0))) # num. base cells y nbcz = 2**int(np.round(np.log(dom_width_z / dh) / np.log(2.0))) # num. base cells z # Define the base mesh hx = [(dh, nbcx)] hy = [(dh, nbcy)] hz = [(dh, nbcz)] mesh = TreeMesh([hx, hy, hz], x0="CCN") # Mesh refinement based on topography k = np.sqrt(np.sum(topo_xyz[:, 0:2]**2, axis=1)) < 1200 mesh = refine_tree_xyz(mesh, topo_xyz[k, :], octree_levels=[0, 6, 8], method="surface", finalize=False) # Mesh refinement near sources and receivers. electrode_locations = np.r_[dc_data.survey.locations_a, dc_data.survey.locations_b, dc_data.survey.locations_m, dc_data.survey.locations_n, ] unique_locations = np.unique(electrode_locations, axis=0) mesh = refine_tree_xyz(mesh, unique_locations, octree_levels=[4, 6, 4], method="radial", finalize=False)
def test_active_from_xyz(self): # Create 3D topo [xx, yy] = np.meshgrid(np.linspace(-200, 200, 50), np.linspace(-200, 200, 50)) b = 50 A = 50 zz = A * np.exp(-0.5 * ((xx / b) ** 2. + (yy / b) ** 2.)) h = [5., 5., 5.] # Test 1D Mesh topo1D = zz[25, :].ravel() mesh1D = discretize.TensorMesh( [np.ones(10) * 20], x0='C' ) indtopoCC = active_from_xyz(mesh1D, topo1D, grid_reference='CC', method='nearest') indtopoN = active_from_xyz(mesh1D, topo1D, grid_reference='N', method='nearest') self.assertEqual(indtopoCC.sum(), 3) self.assertEqual(indtopoN.sum(), 2) # Test 2D Tensor mesh topo2D = np.c_[xx[25, :].ravel(), zz[25, :].ravel()] mesh_tensor = discretize.TensorMesh([ [(h[0], 24)], [(h[1], 20)] ], x0='CC') indtopoCC = active_from_xyz(mesh_tensor, topo2D, grid_reference='CC', method='nearest') indtopoN = active_from_xyz(mesh_tensor, topo2D, grid_reference='N', method='nearest') self.assertEqual(indtopoCC.sum(), 434) self.assertEqual(indtopoN.sum(), 412) # Test 2D Tree mesh mesh_tree = mesh_builder_xyz(topo2D, h[:2], mesh_type='TREE') mesh_tree = refine_tree_xyz( mesh_tree, topo2D, method="surface", octree_levels=[1], octree_levels_padding=None, finalize=True ) indtopoCC = active_from_xyz(mesh_tree, topo2D, grid_reference='CC', method='nearest') indtopoN = active_from_xyz(mesh_tree, topo2D, grid_reference='N', method='nearest') self.assertEqual(indtopoCC.sum(), 167) self.assertEqual(indtopoN.sum(), 119) # Test 3D Tensor meshes topo3D = np.c_[xx.ravel(), yy.ravel(), zz.ravel()] mesh_tensor = discretize.TensorMesh([ [(h[0], 24)], [(h[1], 20)], [(h[2], 30)] ], x0='CCC') indtopoCC = active_from_xyz(mesh_tensor, topo3D, grid_reference='CC', method='nearest') indtopoN = active_from_xyz(mesh_tensor, topo3D, grid_reference='N', method='nearest') self.assertEqual(indtopoCC.sum(), 10496) self.assertEqual(indtopoN.sum(), 10084) # Test 3D Tree mesh mesh_tree = mesh_builder_xyz(topo3D, h, mesh_type='TREE') mesh_tree = refine_tree_xyz( mesh_tree, topo3D, method="surface", octree_levels=[1], octree_levels_padding=None, finalize=True ) indtopoCC = active_from_xyz(mesh_tree, topo3D, grid_reference='CC', method='nearest') indtopoN = active_from_xyz(mesh_tree, topo3D, grid_reference='N', method='nearest') self.assertEqual(indtopoCC.sum(), 6299) self.assertEqual(indtopoN.sum(), 4639) # Test 3D CYL Mesh ncr = 10 # number of mesh cells in r ncz = 15 # number of mesh cells in z dr = 15 # cell width r dz = 10 # cell width z npad_r = 4 # number of padding cells in r npad_z = 4 # number of padding cells in z exp_r = 1.25 # expansion rate of padding cells in r exp_z = 1.25 # expansion rate of padding cells in z hr = [(dr, ncr), (dr, npad_r, exp_r)] hz = [(dz, npad_z, -exp_z), (dz, ncz), (dz, npad_z, exp_z)] # A value of 1 is used to define the discretization in phi for this case. mesh_cyl = discretize.CylMesh([hr, 1, hz], x0='00C') indtopoCC = active_from_xyz(mesh_cyl, topo3D, grid_reference='CC', method='nearest') indtopoN = active_from_xyz(mesh_cyl, topo3D, grid_reference='N', method='nearest') self.assertEqual(indtopoCC.sum(), 183) self.assertEqual(indtopoN.sum(), 171) htheta = meshTensor([(1., 4)]) htheta = htheta * 2*np.pi / htheta.sum() mesh_cyl2 = discretize.CylMesh([hr, htheta, hz], x0='00C') with self.assertRaises(NotImplementedError): indtopoCC = active_from_xyz(mesh_cyl2, topo3D, grid_reference='CC', method='nearest') def gridIt(h): return [np.cumsum(np.r_[0, x]) for x in h] X, Y = ndgrid(gridIt([[5.]*24, [5.]*20]), vector=False) mesh_curvi = discretize.CurvilinearMesh([X, Y]) with self.assertRaises(TypeError): indTopoCC = active_from_xyz(mesh_curvi, topo3D, grid_reference='CC', method='nearest')