def setUp(self): # Define inducing field and sphere parameters H0 = (50000.0, 60.0, 250.0) # H0 = (50000., 90., 0.) self.b0 = mag.analytics.IDTtoxyz(-H0[1], H0[2], H0[0]) self.rad = 2.0 self.chi = 0.01 # Define a mesh cs = 0.2 hxind = [(cs, 21)] hyind = [(cs, 21)] hzind = [(cs, 21)] mesh = discretize.TensorMesh([hxind, hyind, hzind], "CCC") # Get cells inside the sphere sph_ind = getIndicesSphere([0.0, 0.0, 0.0], self.rad, mesh.gridCC) # Adjust susceptibility for volume difference Vratio = (4.0 / 3.0 * np.pi * self.rad**3.0) / (np.sum(sph_ind) * cs**3.0) model = np.ones(mesh.nC) * self.chi * Vratio self.model = model[sph_ind] # Creat reduced identity map for Linear Pproblem idenMap = maps.IdentityMap(nP=int(sum(sph_ind))) # Create plane of observations xr = np.linspace(-20, 20, nx) yr = np.linspace(-20, 20, ny) self.xr = xr self.yr = yr X, Y = np.meshgrid(xr, yr) components = ["bx", "by", "bz", "tmi"] # Move obs plane 2 radius away from sphere Z = np.ones((xr.size, yr.size)) * 2.0 * self.rad self.locXyz = np.c_[utils.mkvc(X), utils.mkvc(Y), utils.mkvc(Z)] rxLoc = mag.Point(self.locXyz, components=components) srcField = mag.SourceField([rxLoc], parameters=H0) self.survey = mag.Survey(srcField) self.sim = mag.Simulation3DIntegral( mesh, survey=self.survey, chiMap=idenMap, actInd=sph_ind, store_sensitivities="forward_only", )
def setUp(self): Inc = 45.0 Dec = 45.0 Btot = 51000 H0 = (Btot, Inc, Dec) self.b0 = mag.analytics.IDTtoxyz(-Inc, Dec, Btot) cs = 25.0 hxind = [(cs, 5, -1.3), (cs / 2.0, 41), (cs, 5, 1.3)] hyind = [(cs, 5, -1.3), (cs / 2.0, 41), (cs, 5, 1.3)] hzind = [(cs, 5, -1.3), (cs / 2.0, 40), (cs, 5, 1.3)] M = discretize.TensorMesh([hxind, hyind, hzind], "CCC") chibkg = 0.0 self.chiblk = 0.01 chi = np.ones(M.nC) * chibkg self.rad = 100 self.sphere_center = [0.0, 0.0, 0.0] sph_ind = getIndicesSphere(self.sphere_center, self.rad, M.gridCC) chi[sph_ind] = self.chiblk xr = np.linspace(-300, 300, 41) yr = np.linspace(-300, 300, 41) X, Y = np.meshgrid(xr, yr) Z = np.ones((xr.size, yr.size)) * 150 components = ["bx", "by", "bz"] self.xr = xr self.yr = yr self.rxLoc = np.c_[utils.mkvc(X), utils.mkvc(Y), utils.mkvc(Z)] receivers = mag.Point(self.rxLoc, components=components) srcField = mag.SourceField([receivers], parameters=H0) self.survey = mag.Survey(srcField) self.sim = mag.simulation.Simulation3DDifferential( M, survey=self.survey, muMap=maps.ChiMap(M), solver=Pardiso, ) self.M = M self.chi = chi
def setUp(self): mesh = discretize.TensorMesh([4, 4, 4]) # Magnetic inducing field parameter (A,I,D) B = [50000, 90, 0] # Create a MAGsurvey rx = mag.Point(np.vstack([[0.25, 0.25, 0.25], [-0.25, -0.25, 0.25]])) srcField = mag.SourceField([rx], parameters=(B[0], B[1], B[2])) survey = mag.Survey(srcField) # Create the forward model operator sim = mag.Simulation3DIntegral(mesh, survey=survey, chiMap=maps.IdentityMap(mesh)) # Compute forward model some data m = np.random.rand(mesh.nC) data = sim.make_synthetic_data(m, add_noise=True) reg = regularization.Sparse(mesh) reg.mref = np.zeros(mesh.nC) reg.norms = np.c_[0, 1, 1, 1] reg.eps_p, reg.eps_q = 1e-3, 1e-3 # Data misfit function dmis = data_misfit.L2DataMisfit(data) dmis.W = 1.0 / data.relative_error # Add directives to the inversion opt = optimization.ProjectedGNCG(maxIter=2, lower=-10.0, upper=10.0, maxIterCG=2) invProb = inverse_problem.BaseInvProblem(dmis, reg, opt) self.mesh = mesh self.invProb = invProb self.sim = sim
def setUp(self): np.random.seed(0) # First we need to define the direction of the inducing field # As a simple case, we pick a vertical inducing field of magnitude # 50,000nT. # From old convention, field orientation is given as an # azimuth from North (positive clockwise) # and dip from the horizontal (positive downward). H0 = (50000.0, 90.0, 0.0) # Create a mesh h = [5, 5, 5] padDist = np.ones((3, 2)) * 100 nCpad = [2, 4, 2] # Create grid of points for topography # Lets create a simple Gaussian topo and set the active cells [xx, yy] = np.meshgrid(np.linspace(-200.0, 200.0, 50), np.linspace(-200.0, 200.0, 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) # self.mesh.finalize() self.mesh = meshutils.mesh_builder_xyz( xyzLoc, h, padding_distance=padDist, mesh_type="TREE", ) self.mesh = meshutils.refine_tree_xyz( self.mesh, topo, method="surface", octree_levels=nCpad, octree_levels_padding=nCpad, finalize=True, ) # Define an active cells from topo actv = utils.surface2ind_topo(self.mesh, topo) nC = int(actv.sum()) # We can now create a susceptibility model and generate data # Lets start with a simple block in half-space self.model = utils.model_builder.addBlock( self.mesh.gridCC, np.zeros(self.mesh.nC), np.r_[-20, -20, -15], np.r_[20, 20, 20], 0.05, )[actv] # Create active map to go from reduce set to full self.actvMap = maps.InjectActiveCells(self.mesh, actv, np.nan) # Creat reduced identity map idenMap = maps.IdentityMap(nP=nC) # Create the forward model operator sim = mag.Simulation3DIntegral( self.mesh, survey=survey, chiMap=idenMap, actInd=actv, store_sensitivities="ram", ) self.sim = sim data = sim.make_synthetic_data(self.model, relative_error=0.0, noise_floor=1.0, add_noise=True) # Create a regularization reg = regularization.Sparse(self.mesh, indActive=actv, mapping=idenMap) reg.norms = np.c_[0, 0, 0, 0] reg.mref = np.zeros(nC) # Data misfit function dmis = data_misfit.L2DataMisfit(simulation=sim, data=data) # Add directives to the inversion opt = optimization.ProjectedGNCG( maxIter=10, lower=0.0, upper=10.0, maxIterLS=5, maxIterCG=5, tolCG=1e-4, stepOffBoundsFact=1e-4, ) invProb = inverse_problem.BaseInvProblem(dmis, reg, opt, beta=1e6) # 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=20, beta_tol=1e-1, beta_search=False) update_Jacobi = directives.UpdatePreconditioner() sensitivity_weights = directives.UpdateSensitivityWeights() self.inv = inversion.BaseInversion( invProb, directiveList=[IRLS, sensitivity_weights, update_Jacobi])
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): np.random.seed(0) # Define the inducing field parameter H0 = (50000, 90, 0) # Create a mesh dx = 5.0 hxind = [(dx, 5, -1.3), (dx, 5), (dx, 5, 1.3)] hyind = [(dx, 5, -1.3), (dx, 5), (dx, 5, 1.3)] hzind = [(dx, 5, -1.3), (dx, 6)] self.mesh = discretize.TensorMesh([hxind, hyind, hzind], "CCC") # Get index of the center midx = int(self.mesh.nCx / 2) midy = int(self.mesh.nCy / 2) # Lets create a simple Gaussian topo and set the active cells [xx, yy] = np.meshgrid(self.mesh.vectorNx, self.mesh.vectorNy) zz = -np.exp((xx**2 + yy**2) / 75**2) + self.mesh.vectorNz[-1] # Go from topo to actv cells topo = np.c_[utils.mkvc(xx), utils.mkvc(yy), utils.mkvc(zz)] actv = utils.surface2ind_topo(self.mesh, topo, "N") actv = np.where(actv)[0] # Create active map to go from reduce space to full self.actvMap = maps.InjectActiveCells(self.mesh, actv, -100) nC = len(actv) # Create and array of observation points xr = np.linspace(-20.0, 20.0, 20) yr = np.linspace(-20.0, 20.0, 20) X, Y = np.meshgrid(xr, yr) # Move the observation points 5m above the topo Z = -np.exp((X**2 + Y**2) / 75**2) + self.mesh.vectorNz[-1] + 5.0 # Create a MAGsurvey rxLoc = np.c_[utils.mkvc(X.T), utils.mkvc(Y.T), utils.mkvc(Z.T)] rxLoc = mag.Point(rxLoc) srcField = mag.SourceField([rxLoc], parameters=H0) survey = mag.Survey(srcField) # We can now create a susceptibility model and generate data # Here a simple block in half-space model = np.zeros((self.mesh.nCx, self.mesh.nCy, self.mesh.nCz)) model[(midx - 2):(midx + 2), (midy - 2):(midy + 2), -6:-2] = 0.02 model = utils.mkvc(model) self.model = model[actv] # Create active map to go from reduce set to full self.actvMap = maps.InjectActiveCells(self.mesh, actv, -100) # Creat reduced identity map idenMap = maps.IdentityMap(nP=nC) # Create the forward model operator sim = mag.Simulation3DIntegral( self.mesh, survey=survey, chiMap=idenMap, actInd=actv, store_sensitivities="disk", ) self.sim = sim # Compute linear forward operator and compute some data data = sim.make_synthetic_data(self.model, relative_error=0.0, noise_floor=1.0, add_noise=True) # Create a regularization reg = regularization.Sparse(self.mesh, indActive=actv, mapping=idenMap) reg.norms = np.c_[0, 0, 0, 0] reg.gradientType = "component" # reg.eps_p, reg.eps_q = 1e-3, 1e-3 # Data misfit function dmis = data_misfit.L2DataMisfit(simulation=sim, data=data) # dmis.W = 1/wd # Add directives to the inversion opt = optimization.ProjectedGNCG(maxIter=100, lower=0.0, upper=1.0, maxIterLS=20, maxIterCG=10, tolCG=1e-3) invProb = inverse_problem.BaseInvProblem(dmis, reg, opt) betaest = directives.BetaEstimate_ByEig() # Here is where the norms are applied IRLS = directives.Update_IRLS(f_min_change=1e-4, minGNiter=1) update_Jacobi = directives.UpdatePreconditioner() sensitivity_weights = directives.UpdateSensitivityWeights( everyIter=False) self.inv = inversion.BaseInversion( invProb, directiveList=[IRLS, sensitivity_weights, betaest, update_Jacobi])
def run(plotIt=True): H0 = (50000.0, 90.0, 0.0) # Create a mesh dx = 5.0 hxind = [(dx, 5, -1.3), (dx, 10), (dx, 5, 1.3)] hyind = [(dx, 5, -1.3), (dx, 10), (dx, 5, 1.3)] hzind = [(dx, 5, -1.3), (dx, 10)] mesh = discretize.TensorMesh([hxind, hyind, hzind], "CCC") # Lets create a simple Gaussian topo and set the active cells [xx, yy] = np.meshgrid(mesh.vectorNx, mesh.vectorNy) zz = -np.exp((xx ** 2 + yy ** 2) / 75 ** 2) + mesh.vectorNz[-1] # We would usually load a topofile topo = np.c_[utils.mkvc(xx), utils.mkvc(yy), utils.mkvc(zz)] # Go from topo to array of indices of active cells actv = utils.surface2ind_topo(mesh, topo, "N") actv = np.where(actv)[0] # Create and array of observation points xr = np.linspace(-20.0, 20.0, 20) yr = np.linspace(-20.0, 20.0, 20) X, Y = np.meshgrid(xr, yr) # Move the observation points 5m above the topo Z = -np.exp((X ** 2 + Y ** 2) / 75 ** 2) + mesh.vectorNz[-1] + 5.0 # Create a MAGsurvey rxLoc = np.c_[utils.mkvc(X.T), utils.mkvc(Y.T), utils.mkvc(Z.T)] rxLoc = magnetics.Point(rxLoc) srcField = magnetics.SourceField([rxLoc], parameters=H0) survey = magnetics.Survey(srcField) # We can now create a susceptibility model and generate data model = np.zeros(mesh.nC) # Change values in half the domain model[mesh.gridCC[:, 0] < 0] = 0.01 # Add a block in half-space model = utils.model_builder.addBlock( mesh.gridCC, model, np.r_[-10, -10, 20], np.r_[10, 10, 40], 0.05 ) model = utils.mkvc(model) model = model[actv] # Create active map to go from reduce set to full actvMap = maps.InjectActiveCells(mesh, actv, np.nan) # Create reduced identity map idenMap = maps.IdentityMap(nP=len(actv)) # Create the forward model operator prob = magnetics.Simulation3DIntegral( mesh, survey=survey, chiMap=idenMap, actInd=actv, store_sensitivities="forward_only", ) # Compute linear forward operator and compute some data data = prob.make_synthetic_data( model, relative_error=0.0, noise_floor=1, add_noise=True ) # Create a homogenous maps for the two domains domains = [mesh.gridCC[actv, 0] < 0, mesh.gridCC[actv, 0] >= 0] homogMap = maps.SurjectUnits(domains) # Create a wire map for a second model space, voxel based wires = maps.Wires(("h**o", len(domains)), ("hetero", len(actv))) # Create Sum map sumMap = maps.SumMap([homogMap * wires.h**o, wires.hetero]) # Create the forward model operator prob = magnetics.Simulation3DIntegral( mesh, survey=survey, chiMap=sumMap, actInd=actv, store_sensitivities="ram" ) # Make depth weighting wr = np.zeros(sumMap.shape[1]) print(prob.nC) # print(prob.M.shape) # why does this reset nC G = prob.G # Take the cell number out of the scaling. # Want to keep high sens for large volumes scale = utils.sdiag( np.r_[utils.mkvc(1.0 / homogMap.P.sum(axis=0)), np.ones_like(actv)] ) for ii in range(survey.nD): wr += ( (prob.G[ii, :] * prob.chiMap.deriv(np.ones(sumMap.shape[1]) * 1e-4) * scale) / data.standard_deviation[ii] ) ** 2.0 # Scale the model spaces independently wr[wires.h**o.index] /= np.max((wires.h**o * wr)) wr[wires.hetero.index] /= np.max(wires.hetero * wr) wr = wr ** 0.5 ## Create a regularization # For the homogeneous model regMesh = discretize.TensorMesh([len(domains)]) reg_m1 = regularization.Sparse(regMesh, mapping=wires.h**o) reg_m1.cell_weights = wires.h**o * wr reg_m1.norms = np.c_[0, 2, 2, 2] reg_m1.mref = np.zeros(sumMap.shape[1]) # Regularization for the voxel model reg_m2 = regularization.Sparse(mesh, indActive=actv, mapping=wires.hetero) reg_m2.cell_weights = wires.hetero * wr reg_m2.norms = np.c_[0, 1, 1, 1] reg_m2.mref = np.zeros(sumMap.shape[1]) reg = reg_m1 + reg_m2 # Data misfit function dmis = data_misfit.L2DataMisfit(simulation=prob, data=data) # Add directives to the inversion opt = optimization.ProjectedGNCG( maxIter=100, lower=0.0, upper=1.0, maxIterLS=20, maxIterCG=10, tolCG=1e-3, tolG=1e-3, eps=1e-6, ) invProb = inverse_problem.BaseInvProblem(dmis, reg, opt) betaest = directives.BetaEstimate_ByEig() # Here is where the norms are applied # Use pick a threshold parameter empirically based on the distribution of # model parameters IRLS = directives.Update_IRLS(f_min_change=1e-3, minGNiter=1) update_Jacobi = directives.UpdatePreconditioner() inv = inversion.BaseInversion(invProb, directiveList=[IRLS, betaest, update_Jacobi]) # Run the inversion m0 = np.ones(sumMap.shape[1]) * 1e-4 # Starting model prob.model = m0 mrecSum = inv.run(m0) if plotIt: mesh.plot_3d_slicer( actvMap * model, aspect="equal", zslice=30, pcolorOpts={"cmap": "inferno_r"}, transparent="slider", ) mesh.plot_3d_slicer( actvMap * sumMap * mrecSum, aspect="equal", zslice=30, pcolorOpts={"cmap": "inferno_r"}, transparent="slider", )