def setUp(self): dh = 1.0 nx = 16 ny = 16 nz = 16 hx = [(dh, nx)] hy = [(dh, ny)] hz = [(dh, nz)] mesh = TreeMesh([hx, hy, hz], "CNN") mesh.insert_cells([5, 5, 5], [4]) # reg actv = np.ones(len(mesh), dtype=bool) # maps wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC)) cross_grad = regularization.CrossGradient(mesh, wire_map=wires, indActive=actv) self.mesh = mesh self.cross_grad = cross_grad
def setUp(self): dh = 1.0 nx = 16 ny = 16 nz = 16 hx = [(dh, nx)] hy = [(dh, ny)] hz = [(dh, nz)] mesh = TreeMesh([hx, hy, hz], "CNN") mesh.insert_cells([5, 5, 5], [4]) # reg actv = np.ones(len(mesh), dtype=bool) # maps wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC)) jtv = regularization.JointTotalVariation(mesh, wire_map=wires, indActive=actv) self.mesh = mesh self.jtv = jtv self.x0 = np.random.rand(len(mesh) * 2)
def baseline_octree_mesh(N, delta): """ Set up a basic regular Cartesian octree mesh as a default; this can then be refined once we specify model features or voxelizations, so it is NOT currently finalized :param N: length of one edge of a cubical volume in cells :param delta: length of one edge of a mesh cube :return: TreeMesh instance """ h = delta * np.ones(N) mesh = TreeMesh([h, h, h], x0="CCC") mesh.refine(3, finalize=False) return mesh
def make_example_mesh(): # Base mesh parameters dh = 5.0 # base cell size nbc = 32 # total width of mesh in terms of number of base mesh cells h = dh * np.ones(nbc) mesh = TreeMesh([h, h, h], x0="CCC") # Refine to largest possible cell size mesh.refine(3, finalize=False) return mesh
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
# # Defining domain side and minimum cell size dh = 25.0 # base cell width dom_width_x = 6000.0 # domain width x dom_width_y = 6000.0 # domain width y dom_width_z = 4000.0 # domain width z nbcx = 2 ** int(np.round(np.log(dom_width_x / dh) / np.log(2.0))) # num. base cells x 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_survey.locations_a, dc_survey.locations_b, dc_survey.locations_m, dc_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 )
import matplotlib.pyplot as plt from matplotlib.patches import Rectangle from SimPEG.Utils import mkvc, modelutils, PlotUtils, plot2Ddata import pyvista ############################################################################### # Load the Data # +++++++++++++ # # Load the mesh and data from the previous example grav_data = pyvista.read(gdc19.get_gravity_path('grav_obs.vtk')) xyz = grav_data.points survey = pyvista.PolyData(xyz) mesh = TreeMesh.readUBC(gdc19.get_gravity_path('mesh.msh')) actv = mesh.readModelUBC(gdc19.get_gravity_path('actv.mod')) ############################################################################### # Tile the Problem # ++++++++++++++++ rxLoc = xyz tiles, binCount, labels = modelutils.tileSurveyPoints(rxLoc, 14) # Grab the smallest bin and generate a temporary mesh indMin = np.argmin(binCount) X1, Y1 = tiles[0][:, 0], tiles[0][:, 1] X2, Y2 = tiles[1][:, 0], tiles[1][:, 1] nTiles = X1.shape[0]
# ------------------ # # Here, we create the OcTree mesh that will be used to predict both DC # resistivity and IP data. # 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
# Here, we create the Tree mesh that will be used to predict both DC # resistivity and IP data. # 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,
dz = 5 # minimum cell width (base mesh cell width) in z x_length = 240.0 # domain width in x y_length = 240.0 # domain width in y z_length = 120.0 # domain width in y # 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],
dh = 40.0 # base cell width dom_width_x = 10000.0 # domain width x dom_width_y = 10000.0 # domain width y dom_width_z = 2000.0 # domain width z nbcx = 2**int(np.round(np.log(dom_width_x / dh) / np.log(2.0))) # num. base cells x 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 mesh = refine_tree_xyz(mesh, xyz_topo, octree_levels=[0, 0, 1], method="surface", finalize=False) # Mesh refinement near sources and receivers. First we need to obtain the # set of unique electrode locations. electrode_locations = np.r_[survey.locations_a, survey.locations_b, survey.locations_m, survey.locations_n] unique_locations = np.unique(electrode_locations, axis=0)
# Here, we create the OcTree mesh that will be used to predict both DC # resistivity and IP data. # dh = 4 # base cell width dom_width_x = 3200.0 # domain width x dom_width_z = 2400.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=[0, 0, 4, 4], method="surface", finalize=False, ) # Mesh refinement near transmitters and receivers. First we need to obtain the # set of unique electrode locations. electrode_locations = np.c_[dc_survey.locations_a, dc_survey.locations_b, dc_survey.locations_m, dc_survey.locations_n, ]
# We chose to design a coarser mesh to decrease the run time. # When designing a mesh to solve practical frequency domain problems: # # - Your smallest cell size should be 10%-20% the size of your smallest skin depth # - The thickness of your padding needs to be 2-3 times biggest than your largest skin depth # - 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)
# Here, we create the Tree mesh that will be used to predict both DC # resistivity and IP data. # 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_[dc_survey.locations_a, dc_survey.locations_b, dc_survey.locations_m, dc_survey.locations_n, ] unique_locations = np.unique(electrode_locations, axis=0) mesh = refine_tree_xyz(mesh,
# We chose to design a coarser mesh to decrease the run time. # When designing a mesh to solve practical frequency domain problems: # # - Your smallest cell size should be 10%-20% the size of your smallest skin depth # - The thickness of your padding needs to be 2-3 times biggest than your largest skin depth # - 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, topo_xyz, 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)
# We chose to design a coarser mesh to decrease the run time. # When designing a mesh to solve practical time domain problems: # # - Your smallest cell size should be 10%-20% the size of your smallest diffusion distance # - The thickness of your padding needs to be 2-3 times biggest than your largest diffusion distance # - The diffusion distance is ~1260*np.sqrt(rho*t) # # dh = 25.0 # base cell width dom_width = 1600.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, topo_xyz, 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)
# sphinx_gallery_thumbnail_number = 4 dx = 10 # minimum cell width (base mesh cell width) in x dy = 10 # minimum cell width (base mesh cell width) in y x_length = 40000. # domain width in x y_length = 40000. # domain width in y # 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=['C', -15000]) # definir camada xx = M.vectorNx yy = np.zeros(nbcx + 1) #vetor linha(poderia ser uma função ou pontos) pts = np.c_[matutils.mkvc(xx), matutils.mkvc(yy)] M = meshutils.refine_tree_xyz(M, pts, octree_levels=[1, 1], method='box', finalize=False) #definir um ponto(xc,yc) a ser refinado. Raio_length = 500 xc = -5000 yc = 2200
# ---------------- # # Here, we create the Tree mesh that will be used to invert both DC # resistivity and IP data. # dh = 4 # base cell width dom_width_x = 3200.0 # domain width x dom_width_z = 2400.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=[0, 0, 4, 4], method="surface", finalize=False, ) # Mesh refinement near transmitters and receivers. First we need to obtain the # set of unique electrode locations. electrode_locations = np.c_[ dc_data.survey.locations_a, dc_data.survey.locations_b,
plt.close('all') dx = 50 # minimum cell width (base mesh cell width) in x dy = 50 # minimum cell width (base mesh cell width) in y x_length = 30000. # domain width in x y_length = 30000. # domain width in y # 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))
def setUp(self): mesh = TreeMesh([32, 32]) mesh.refine_box([0.2, 0.2], [0.5, 0.8], 5) self.mesh = mesh
dz = 50 # tamanho minimo da celula em z x_length = 5000 # tamanho do dominio em x y_length = 5000 # tamanho do dominio em y z_length = 50000 # tamanho do dominio em z # 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.))) nbcz = 2**int(np.round(np.log(z_length / dz) / np.log(2.))) # Define the base mesh hx = [(dx, nbcx)] hy = [(dy, nbcy)] hz = [(dz, nbcz)] M = TreeMesh([hx, hy, hz], x0='CCC') # # 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)]
# Create Tree Mesh # ------------------ # # Here, we create the Tree mesh that will be used invert the DC data # dh = 4 # base cell width dom_width_x = 3200.0 # domain width x dom_width_z = 2400.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=[0, 0, 4, 4], method="surface", finalize=False, ) # Mesh refinement near transmitters and receivers. First we need to obtain the # set of unique electrode locations. electrode_locations = np.c_[ dc_data.survey.locations_a, dc_data.survey.locations_b,
############################################### # Basic Example # ------------- # # Here we demonstrate the basic two step process for creating a 2D tree mesh # (QuadTree mesh). The region of highest discretization if defined within a # rectangular box. We use the keyword argument *octree_levels* to define the # rate of cell width increase outside the box. # 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)
fig.show() ######################################################### # Tree Mesh Divergence # -------------------- # # For a tree mesh, there needs to be special attention taken for the hanging # faces to achieve second order convergence for the divergence operator. # Although the divergence cannot be constructed through Kronecker product # operations, the initial steps are exactly the same for calculating the # stencil, volumes, and areas. This yields a divergence defined for every # cell in the mesh using all faces. There is, however, redundant information # when hanging faces are included. # mesh = TreeMesh([[(1, 16)], [(1, 16)]], levels=4) mesh.insert_cells(np.array([5.0, 5.0]), np.array([3])) mesh.number() fig = plt.figure(figsize=(10, 10)) ax1 = fig.add_subplot(211) mesh.plotGrid(centers=True, nodes=False, ax=ax1) ax1.axis("off") ax1.set_title("Simple QuadTree Mesh") ax1.set_xlim([-1, 17]) ax1.set_ylim([-1, 17]) for ii, loc in zip(range(mesh.nC), mesh.gridCC): ax1.text(loc[0] + 0.2, loc[1], "{0:d}".format(ii), color="r")
# Create Tree Mesh # ------------------ # # Here, we create the Tree mesh that will be used to predict DC data. # dh = 4 # base cell width dom_width_x = 3200.0 # domain width x dom_width_z = 2400.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=[0, 0, 4, 4], method="surface", finalize=False, ) # Mesh refinement near transmitters and receivers. First we need to obtain the # set of unique electrode locations. electrode_locations = np.c_[ survey.locations_a, survey.locations_b, survey.locations_m, survey.locations_n, ]
# Here, we create the Tree mesh that will be used to predict both DC # resistivity and IP data. # 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, xyz_topo[:, [0, 2]], octree_levels=[1], method="surface", finalize=False) # Mesh refinement near transmitters and receivers. First we need to obtain the # set of unique electrode locations. electrode_locations = np.c_[survey.locations_a, survey.locations_b, survey.locations_m, survey.locations_n] unique_locations = np.unique(np.reshape(electrode_locations, (4 * survey.nD, 2)),
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 plotVectorSectionsOctree( mesh, m, normal="X", ind=0, vmin=None, vmax=None, scale=1.0, vec="k", axs=None, actvMap=None, fill=True, ): """ Plot section through a 3D tensor model """ # plot recovered model normalInd = {"X": 0, "Y": 1, "Z": 2}[normal] antiNormalInd = {"X": [1, 2], "Y": [0, 2], "Z": [0, 1]}[normal] h2d = (mesh.h[antiNormalInd[0]], mesh.h[antiNormalInd[1]]) x2d = (mesh.x0[antiNormalInd[0]], mesh.x0[antiNormalInd[1]]) #: Size of the sliced dimension szSliceDim = len(mesh.h[normalInd]) if ind is None: ind = int(szSliceDim // 2) cc_tensor = [None, None, None] for i in range(3): cc_tensor[i] = np.cumsum(np.r_[mesh.x0[i], mesh.h[i]]) cc_tensor[i] = (cc_tensor[i][1:] + cc_tensor[i][:-1]) * 0.5 slice_loc = cc_tensor[normalInd][ind] # Create a temporary TreeMesh with the slice through temp_mesh = TreeMesh(h2d, x2d) level_diff = mesh.max_level - temp_mesh.max_level XS = [None, None, None] XS[antiNormalInd[0]], XS[antiNormalInd[1]] = np.meshgrid( cc_tensor[antiNormalInd[0]], cc_tensor[antiNormalInd[1]]) XS[normalInd] = np.ones_like(XS[antiNormalInd[0]]) * slice_loc loc_grid = np.c_[XS[0].reshape(-1), XS[1].reshape(-1), XS[2].reshape(-1)] inds = np.unique(mesh._get_containing_cell_indexes(loc_grid)) grid2d = mesh.gridCC[inds][:, antiNormalInd] levels = mesh._cell_levels_by_indexes(inds) - level_diff temp_mesh.insert_cells(grid2d, levels) tm_gridboost = np.empty((temp_mesh.nC, 3)) tm_gridboost[:, antiNormalInd] = temp_mesh.gridCC tm_gridboost[:, normalInd] = slice_loc # Interpolate values to mesh.gridCC if not 'CC' mx = actvMap * m[:, 0] my = actvMap * m[:, 1] mz = actvMap * m[:, 2] m = np.c_[mx, my, mz] # Interpolate values from mesh.gridCC to grid2d ind_3d_to_2d = mesh._get_containing_cell_indexes(tm_gridboost) v2d = m[ind_3d_to_2d, :] amp = np.sum(v2d**2.0, axis=1)**0.5 if axs is None: axs = plt.subplot(111) if fill: temp_mesh.plotImage(amp, ax=axs, clim=[vmin, vmax], grid=True) axs.quiver( temp_mesh.gridCC[:, 0], temp_mesh.gridCC[:, 1], v2d[:, antiNormalInd[0]], v2d[:, antiNormalInd[1]], pivot="mid", scale_units="inches", scale=scale, linewidths=(1, ), edgecolors=(vec), headaxislength=0.1, headwidth=10, headlength=30, )
dh = 25.0 # base cell width dom_width_x = 6000.0 # domain width x dom_width_y = 6000.0 # domain width y dom_width_z = 4000.0 # domain width z nbcx = 2**int(np.round(np.log(dom_width_x / dh) / np.log(2.0))) # num. base cells x 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)
dz = 5 # minimum cell width (base mesh cell width) in z x_length = 240.0 # domain width in x y_length = 240.0 # domain width in y z_length = 120.0 # domain width in y # 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 based 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],