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) # Finalize the mesh mesh.finalize() ####################################################### # Project Electrodes to Discretized Topography # -------------------------------------------- # # It is important that electrodes are not modeled as being in the air. Even if the # electrodes are properly located along surface topography, they may lie above # the discretized topography. This step is carried out to ensure all electrodes # lie on the discretized surface. # # Find cells that lie below surface topography ind_active = surface2ind_topo(mesh, topo_xyz) # Extract survey from data object
# 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 # set of points. We also show some aspect of customizing plots. We use the # keyword argument *octree_levels* to define the rate of cell width increase # relative to our surface and the set of discrete points about which we are # refining.
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 # 只保留磁场强度数据,删除后面的两个参数
# 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')
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