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 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_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_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_errors(self): dx = 0.25 rad = 10 self.assertRaises( ValueError, 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="cyl", ) 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)) self.assertRaises( NotImplementedError, refine_tree_xyz, mesh, np.c_[0, 0, 0], octree_levels=[radCell], method="other", finalize=True, ) self.assertRaises( ValueError, refine_tree_xyz, mesh, np.c_[0, 0, 0], octree_levels=[radCell], octree_levels_padding=[], method="surface", finalize=True, )
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")
octree_levels = [8, 4] # Create tiles local_indices = [rxLoc[:, 0] <= 0, rxLoc[:, 0] > 0] local_surveys = [] local_meshes = [] 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
# Here, we create a TreeMesh with base cell size of 5 m. We created a small # utility function to center the mesh around points and to figure out the # outermost dimension for adequate padding distance. # The second stage allows us to refine the mesh around points or surfaces # (point assumed to follow some horizontal trend) # 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 #
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 ], )
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
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')