def test_haverkamp_k_m(self): mesh = discretize.TensorMesh([5]) expmap = maps.IdentityMap(nP=mesh.nC) wires2 = maps.Wires(("one", mesh.nC), ("two", mesh.nC)) wires3 = maps.Wires(("one", mesh.nC), ("two", mesh.nC), ("three", mesh.nC)) opts = [ ("Ks", dict(KsMap=expmap), 1), ("A", dict(AMap=expmap), 1), ("gamma", dict(gammaMap=expmap), 1), ("Ks-A", dict(KsMap=expmap * wires2.one, AMap=expmap * wires2.two), 2), ( "Ks-gamma", dict(KsMap=expmap * wires2.one, gammaMap=expmap * wires2.two), 2, ), ( "A-gamma", dict(AMap=expmap * wires2.one, gammaMap=expmap * wires2.two), 2, ), ( "Ks-A-gamma", dict( KsMap=expmap * wires3.one, AMap=expmap * wires3.two, gammaMap=expmap * wires3.three, ), 3, ), ] u = np.random.randn(mesh.nC) for name, opt, nM in opts: np.random.seed(2) hav = richards.empirical.Haverkamp_k(mesh, **opt) def fun(m): hav.model = m return hav(u), hav.derivM(u) print("Haverkamp_k test m deriv: ", name) passed = checkDerivative(fun, np.random.randn(mesh.nC * nM), plotIt=False) self.assertTrue(passed, True)
def test_Maps(self): nP = 10 m = np.random.rand(2 * nP) wires = maps.Wires(("sigma", nP), ("mu", nP)) objfct1 = objective_function.L2ObjectiveFunction(mapping=wires.sigma) objfct2 = objective_function.L2ObjectiveFunction(mapping=wires.mu) objfct3 = objfct1 + objfct2 objfct4 = objective_function.L2ObjectiveFunction(nP=nP) self.assertTrue(objfct1.nP == 2 * nP) self.assertTrue(objfct2.nP == 2 * nP) self.assertTrue(objfct3.nP == 2 * nP) # print(objfct1.nP, objfct4.nP, objfct4.W.shape, objfct1.W.shape, m[:nP].shape) self.assertTrue(objfct1(m) == objfct4(m[:nP])) self.assertTrue(objfct2(m) == objfct4(m[nP:])) self.assertTrue(objfct3(m) == objfct1(m) + objfct2(m)) objfct1.test() objfct2.test() objfct3.test()
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 = 12 ny = 12 nz = 12 hx = [(dh, nx)] hy = [(dh, ny)] hz = [(dh, nz)] mesh = TensorMesh([hx, hy, hz], "CNN") # reg actv = np.ones(len(mesh), dtype=bool) # maps wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC)) cros_grad = regularization.CrossGradient( mesh, wire_map=wires, indActive=actv, ) self.mesh = mesh self.cross_grad = cros_grad
def setUp(self): dh = 1.0 nx = 12 ny = 12 nz = 12 hx = [(dh, nx)] hy = [(dh, ny)] hz = [(dh, nz)] mesh = TensorMesh([hx, hy, hz], "CNN") # 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 spectral_ip_mappings( mesh, indActive=None, inactive_eta=1e-4, inactive_tau=1e-4, inactive_c=1e-4, is_log_eta=True, is_log_tau=True, is_log_c=True, ): """ Generates Mappings for Spectral Induced Polarization Simulation. Three parameters are required to be input: Chargeability (eta), Time constant (tau), and Frequency dependency (c). If there is no topography (indActive is None), model (m) can be either set to m = np.r_[log(eta), log(tau), log(c)] or m = np.r_[eta, tau, c] When indActive is not None, m is m = np.r_[log(eta[indAcitve]), log(tau[indAcitve]), log(c[indAcitve])] or m = np.r_[eta[indAcitve], tau[indAcitve], c[indAcitve]] or TODO: Illustrate input and output variables """ if indActive is None: indActive = np.ones(mesh.nC, dtype=bool) actmap_eta = maps.InjectActiveCells( mesh, indActive=indActive, valInactive=inactive_eta ) actmap_tau = maps.InjectActiveCells( mesh, indActive=indActive, valInactive=inactive_tau ) actmap_c = maps.InjectActiveCells(mesh, indActive=indActive, valInactive=inactive_c) wires = maps.Wires( ("eta", indActive.sum()), ("tau", indActive.sum()), ("c", indActive.sum()) ) if is_log_eta: eta_map = actmap_eta * maps.ExpMap(nP=actmap_eta.nP) * wires.eta else: eta_map = actmap_eta * wires.eta if is_log_tau: tau_map = actmap_tau * maps.ExpMap(nP=actmap_tau.nP) * wires.tau else: tau_map = actmap_tau * wires.tau if is_log_c: c_map = actmap_c * maps.ExpMap(nP=actmap_c.nP) * wires.c else: c_map = actmap_c * wires.c return eta_map, tau_map, c_map, wires
def test_basic(self): mesh = discretize.TensorMesh([10, 10, 10]) wires = maps.Wires(("sigma", mesh.nCz), ("mu_casing", 1),) model = np.arange(mesh.nCz + 1) assert isinstance(wires.sigma, maps.Projection) assert wires.nP == mesh.nCz + 1 named_model = wires * model named_model.sigma == model[: mesh.nCz] assert named_model.mu_casing == 10
def model_soundings(h0, h1, rho0, rho1, rho2): hz = np.r_[h0, h1] rho = np.r_[rho0, rho1, rho2] srcList_w = [] srcList_s = [] AB2 = np.arange(4, 89, 3) + 0.5 for i, a in enumerate(AB2): a_loc = -a b_loc = a m_loc_wen = -a + (a * 2) // 3 n_loc_wen = -m_loc_wen m_loc_sch = -1.5 n_loc_sch = 1.5 rx_w = DC.Rx.Dipole(np.r_[m_loc_wen, 0, 0], np.r_[n_loc_wen, 0, 0]) rx_s = DC.Rx.Dipole(np.r_[m_loc_sch, 0, 0], np.r_[n_loc_sch, 0, 0]) locA = np.r_[a_loc, 0, 0] locB = np.r_[b_loc, 0, 0] src = DC.Src.Dipole([rx_w], locA, locB) srcList_w.append(src) src = DC.Src.Dipole([rx_s], locA, locB) srcList_s.append(src) m = np.r_[rho, hz] wires = maps.Wires(('rho', rho.size), ('t', rho.size - 1)) mapping_rho = maps.IdentityMap(nP=rho.size) * wires.rho mapping_t = maps.IdentityMap(nP=hz.size) * wires.t survey = DC.Survey(srcList_w) simulation = DC.Simulation1DLayers(rhoMap=mapping_rho, thicknessesMap=mapping_t, survey=survey, data_type='apparent_resistivity') data_w = simulation.make_synthetic_data(m) survey = DC.Survey(srcList_s) simulation = DC.Simulation1DLayers(rhoMap=mapping_rho, thicknessesMap=mapping_t, survey=survey, data_type='apparent_resistivity') data_s = simulation.make_synthetic_data(m) return data_w, data_s
def test_mappings_and_cell_weights(self): mesh = discretize.TensorMesh([8, 7, 6]) m = np.random.rand(2 * mesh.nC) v = np.random.rand(2 * mesh.nC) cell_weights = np.random.rand(mesh.nC) wires = maps.Wires(("sigma", mesh.nC), ("mu", mesh.nC)) reg = regularization.SimpleSmall(mesh, mapping=wires.sigma, cell_weights=cell_weights) objfct = objective_function.L2ObjectiveFunction(W=utils.sdiag( np.sqrt(cell_weights)), mapping=wires.sigma) self.assertTrue(reg(m) == objfct(m)) self.assertTrue(np.all(reg.deriv(m) == objfct.deriv(m))) self.assertTrue(np.all(reg.deriv2(m, v=v) == objfct.deriv2(m, v=v)))
def test_mappings(self): mesh = discretize.TensorMesh([8, 7, 6]) m = np.random.rand(2 * mesh.nC) wires = maps.Wires(("sigma", mesh.nC), ("mu", mesh.nC)) for regType in ["Tikhonov", "Sparse", "Simple"]: reg1 = getattr(regularization, regType)(mesh, mapping=wires.sigma) reg2 = getattr(regularization, regType)(mesh, mapping=wires.mu) reg3 = reg1 + reg2 self.assertTrue(reg1.nP == 2 * mesh.nC) self.assertTrue(reg2.nP == 2 * mesh.nC) self.assertTrue(reg3.nP == 2 * mesh.nC) print(reg3(m), reg1(m), reg2(m)) self.assertTrue(reg3(m) == reg1(m) + reg2(m)) reg1.test(eps=TOL) reg2.test(eps=TOL) reg3.test(eps=TOL)
def setUp(self): dh = 1.0 nx = 12 ny = 12 hx = [(dh, nx)] hy = [(dh, ny)] mesh = TensorMesh([hx, hy], "CN") # reg actv = np.ones(len(mesh), dtype=bool) # maps wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC)) corr = regularization.LinearCorrespondence( mesh, wire_map=wires, indActive=actv, ) self.mesh = mesh self.corr = corr
def setUp(self): dh = 1.0 nx = 16 ny = 16 hx = [(dh, nx)] hy = [(dh, ny)] mesh = TreeMesh([hx, hy], "CN") mesh.insert_cells([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 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", )
def setUp(self): cs = 25.0 hx = [(cs, 0, -1.3), (cs, 21), (cs, 0, 1.3)] hy = [(cs, 0, -1.3), (cs, 21), (cs, 0, 1.3)] hz = [(cs, 0, -1.3), (cs, 20)] mesh = discretize.TensorMesh([hx, hy, hz], x0="CCN") blkind0 = utils.model_builder.getIndicesSphere( np.r_[-100.0, -100.0, -200.0], 75.0, mesh.gridCC) blkind1 = utils.model_builder.getIndicesSphere( np.r_[100.0, 100.0, -200.0], 75.0, mesh.gridCC) sigma = np.ones(mesh.nC) * 1e-2 eta = np.zeros(mesh.nC) tau = np.ones_like(sigma) * 1.0 eta[blkind0] = 0.1 eta[blkind1] = 0.1 tau[blkind0] = 0.1 tau[blkind1] = 0.01 x = mesh.vectorCCx[(mesh.vectorCCx > -155.0) & (mesh.vectorCCx < 155.0)] y = mesh.vectorCCy[(mesh.vectorCCy > -155.0) & (mesh.vectorCCy < 155.0)] Aloc = np.r_[-200.0, 0.0, 0.0] Bloc = np.r_[200.0, 0.0, 0.0] M = utils.ndgrid(x - 25.0, y, np.r_[0.0]) N = utils.ndgrid(x + 25.0, y, np.r_[0.0]) times = np.arange(10) * 1e-3 + 1e-3 rx = sip.receivers.Dipole(M, N, times) print(rx.nD) print(rx.locations) src = sip.sources.Dipole([rx], Aloc, Bloc) survey = sip.Survey([src]) print(f"Survey ND = {survey.nD}") print(f"Survey ND = {src.nD}") wires = maps.Wires(("eta", mesh.nC), ("taui", mesh.nC)) problem = sip.Simulation3DCellCentered( mesh, survey=survey, rho=1.0 / sigma, etaMap=wires.eta, tauiMap=wires.taui, storeJ=False, ) problem.solver = Solver mSynth = np.r_[eta, 1.0 / tau] problem.model = mSynth dobs = problem.make_synthetic_data(mSynth, add_noise=True) # Now set up the problem to do some minimization dmis = data_misfit.L2DataMisfit(data=dobs, simulation=problem) reg = regularization.Tikhonov(mesh) opt = optimization.InexactGaussNewton(maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6) invProb = inverse_problem.BaseInvProblem(dmis, reg, opt, beta=1e4) inv = inversion.BaseInversion(invProb) self.inv = inv self.reg = reg self.p = problem self.mesh = mesh self.m0 = mSynth self.survey = survey self.dmis = dmis self.dobs = dobs
def setup_maps(self, mesh, k_fun, theta_fun): wires = maps.Wires(("Ks", mesh.nC), ("A", mesh.nC), ("theta_s", mesh.nC)) k_fun.KsMap = maps.ExpMap(nP=mesh.nC) * wires.Ks k_fun.AMap = wires.A theta_fun.theta_sMap = wires.theta_s
ind_sphere = model_builder.getIndicesSphere(np.r_[-20.0, 0.0, -15.0], 20.0, mesh.gridCC) ind_sphere = ind_sphere[ind_active] # So same size and order as model model[ind_sphere, :] = np.c_[sphere_sigma_value, sphere_mu_value] # Add a conductive and non-permeable dyke xp = np.kron(np.ones((2)), [-10.0, 10.0, 55.0, 35.0]) yp = np.kron([-1000.0, 1000.0], np.ones((4))) zp = np.kron(np.ones((2)), [-120.0, -120.0, 45.0, 45.0]) xyz_pts = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] ind_polygon = model_builder.PolygonInd(mesh, xyz_pts) ind_polygon = ind_polygon[ind_active] # So same size and order as model model[ind_polygon, 0] = dyke_sigma_value # Create model vector and wires model = mkvc(model) wire_map = maps.Wires(("log_sigma", N), ("mu", N)) # Use combo maps to map from model to mesh sigma_map = active_map * maps.ExpMap() * wire_map.log_sigma mu_map = active_map * wire_map.mu # Plot fig = plt.figure(figsize=(5, 5)) ax = fig.add_subplot(111) ind_slice = int(mesh.hy.size / 2) mesh.plotSlice(sigma_map * model, normal="Y", ax=ax, ind=ind_slice, grid=True) ax.set_title("Model slice at y = {} m".format(mesh.x0[1] + np.sum(mesh.hy[0:ind_slice]))) plt.show()
def setUp(self): cs = 25.0 hx = [(cs, 0, -1.3), (cs, 21), (cs, 0, 1.3)] hy = [(cs, 0, -1.3), (cs, 21), (cs, 0, 1.3)] hz = [(cs, 0, -1.3), (cs, 20), (cs, 0, 1.3)] mesh = discretize.TensorMesh([hx, hy, hz], x0="CCC") blkind0 = utils.model_builder.getIndicesSphere( np.r_[-100.0, -100.0, -200.0], 75.0, mesh.gridCC) blkind1 = utils.model_builder.getIndicesSphere( np.r_[100.0, 100.0, -200.0], 75.0, mesh.gridCC) sigma = np.ones(mesh.nC) * 1e-2 airind = mesh.gridCC[:, 2] > 0.0 sigma[airind] = 1e-8 eta = np.zeros(mesh.nC) tau = np.ones_like(sigma) * 1.0 c = np.ones_like(sigma) * 0.5 eta[blkind0] = 0.1 eta[blkind1] = 0.1 tau[blkind0] = 0.1 tau[blkind1] = 0.01 actmapeta = maps.InjectActiveCells(mesh, ~airind, 0.0) actmaptau = maps.InjectActiveCells(mesh, ~airind, 1.0) actmapc = maps.InjectActiveCells(mesh, ~airind, 1.0) x = mesh.vectorCCx[(mesh.vectorCCx > -155.0) & (mesh.vectorCCx < 155.0)] y = mesh.vectorCCy[(mesh.vectorCCy > -155.0) & (mesh.vectorCCy < 155.0)] Aloc = np.r_[-200.0, 0.0, 0.0] Bloc = np.r_[200.0, 0.0, 0.0] M = utils.ndgrid(x - 25.0, y, np.r_[0.0]) N = utils.ndgrid(x + 25.0, y, np.r_[0.0]) times = np.arange(10) * 1e-3 + 1e-3 rx = sip.receivers.Dipole(M, N, times) src = sip.sources.Dipole([rx], Aloc, Bloc) survey = sip.Survey([src]) wires = maps.Wires(("eta", actmapeta.nP), ("taui", actmaptau.nP), ("c", actmapc.nP)) problem = sip.Simulation3DNodal( mesh, survey=survey, sigma=sigma, etaMap=actmapeta * wires.eta, tauiMap=actmaptau * wires.taui, cMap=actmapc * wires.c, actinds=~airind, storeJ=False, verbose=False, ) problem.solver = Solver mSynth = np.r_[eta[~airind], 1.0 / tau[~airind], c[~airind]] dobs = problem.make_synthetic_data(mSynth, add_noise=True) # Now set up the problem to do some minimization dmis = data_misfit.L2DataMisfit(data=dobs, simulation=problem) reg_eta = regularization.Sparse(mesh, mapping=wires.eta, indActive=~airind) reg_taui = regularization.Sparse(mesh, mapping=wires.taui, indActive=~airind) reg_c = regularization.Sparse(mesh, mapping=wires.c, indActive=~airind) reg = reg_eta + reg_taui + reg_c opt = optimization.InexactGaussNewton(maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6) invProb = inverse_problem.BaseInvProblem(dmis, reg, opt, beta=1e4) inv = inversion.BaseInversion(invProb) self.inv = inv self.reg = reg self.p = problem self.mesh = mesh self.m0 = mSynth self.survey = survey self.dmis = dmis self.dobs = dobs
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 # 只保留磁场强度数据,删除后面的两个参数
# --------- # # We can now attempt the inverse calculations. We put great care # into designing an inversion methology that would yield a geologically # reasonable solution for the non-induced problem. # The inversion is done in two stages. First we compute a smooth # solution using a Cartesian coordinate system, then a sparse # inversion in the Spherical domain. # # Create sensitivity weights from our linear forward operator rxLoc = survey.source_field.receiver_list[0].locations # This Mapping connects the regularizations for the three-component # vector model wires = maps.Wires(("p", nC), ("s", nC), ("t", nC)) m0 = np.ones(3 * nC) * 1e-4 # Starting model # Create three regularizations 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
resistivities = np.r_[1e3, 1e3, 1e3] layer_thicknesses = np.r_[50.0, 50.0] # Define a mesh for plotting and regularization. mesh = TensorMesh([(np.r_[layer_thicknesses, layer_thicknesses[-1]])], "0") print(mesh) # Define model. We are inverting for the layer resistivities and layer thicknesses. # Since the bottom layer extends to infinity, it is not a model parameter for # which we need to invert. For a 3 layer model, there is a total of 5 parameters. # For stability, our model is the log-resistivity and log-thickness. starting_model = np.r_[np.log(resistivities), np.log(layer_thicknesses)] # Since the model contains two different properties for each layer, we use # wire maps to distinguish the properties. wire_map = maps.Wires(("rho", mesh.nC), ("t", mesh.nC - 1)) resistivity_map = maps.ExpMap(nP=mesh.nC) * wire_map.rho layer_map = maps.ExpMap(nP=mesh.nC - 1) * wire_map.t ####################################################################### # Define the Physics # ------------------ # # Here we define the physics of the problem. The data consists of apparent # resistivity values. This is defined here. # simulation = dc.simulation_1d.Simulation1DLayers( survey=survey, rhoMap=resistivity_map, thicknessesMap=layer_map,
mesh=mesh, n_components=3, covariance_type="full", tol=1e-8, reg_covar=1e-3, max_iter=1000, n_init=100, init_params="kmeans", random_state=None, warm_start=False, verbose=0, verbose_interval=10, ) clfnomapping = clfnomapping.fit(model2d) wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC)) relatrive_error = 0.01 noise_floor = 0.0 prob1 = simulation.LinearSimulation(mesh, G=G, model_map=wires.m1) survey1 = prob1.make_synthetic_data(m, relative_error=relatrive_error, noise_floor=noise_floor, add_noise=True) prob2 = simulation.LinearSimulation(mesh, G=G, model_map=wires.m2) survey2 = prob2.make_synthetic_data(m, relative_error=relatrive_error, noise_floor=noise_floor, add_noise=True)
# # Define density contrast values for each unit in g/cc. background_dens, background_susc = 1e-6, 1e-6 # Find the indicies of the active cells in forward model (ones below surface) ind_active = surface2ind_topo(mesh, xyz_topo) # Define mapping from model to active cells nC = int(ind_active.sum()) model_map = maps.IdentityMap( nP=nC) # model consists of a value for each active cell # Create Wires Map that maps from stacked models to individual model components # m1 refers to density model, m2 refers to susceptibility wires = maps.Wires(("density", nC), ("susceptibility", nC)) # Define and plot starting model starting_model = np.r_[background_dens * np.ones(nC), background_susc * np.ones(nC)] ############################################## # Define the Physics # ------------------ # # Here, we define the physics of the gravity and magnetic problems by using the simulation # class. # simulation_grav = gravity.simulation.Simulation3DIntegral(survey=survey_grav, mesh=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
def setupProblem( mesh, muMod, sigmaMod, prbtype="ElectricField", invertMui=False, sigmaInInversion=False, freq=1.0, ): rxcomp = ["real", "imag"] loc = utils.ndgrid([mesh.vectorCCx, np.r_[0.0], mesh.vectorCCz]) if prbtype in ["ElectricField", "MagneticFluxDensity"]: rxfields_y = ["ElectricField", "CurrentDensity"] rxfields_xz = ["MagneticFluxDensity", "MagneticField"] elif prbtype in ["MagneticField", "CurrentDensity"]: rxfields_y = ["MagneticFluxDensity", "MagneticField"] rxfields_xz = ["ElectricField", "CurrentDensity"] receiver_list_edge = [ getattr(fdem.receivers, "Point{f}".format(f=f))(loc, component=comp, orientation=orient) for f in rxfields_y for comp in rxcomp for orient in ["y"] ] receiver_list_face = [ getattr(fdem.receivers, "Point{f}".format(f=f))(loc, component=comp, orientation=orient) for f in rxfields_xz for comp in rxcomp for orient in ["x", "z"] ] receiver_list = receiver_list_edge + receiver_list_face src_loc = np.r_[0.0, 0.0, 0.0] if prbtype in ["ElectricField", "MagneticFluxDensity"]: src = fdem.sources.MagDipole(receiver_list=receiver_list, location=src_loc, frequency=freq) elif prbtype in ["MagneticField", "CurrentDensity"]: ind = utils.closestPoints(mesh, src_loc, "Fz") + mesh.vnF[0] vec = np.zeros(mesh.nF) vec[ind] = 1.0 src = fdem.sources.RawVec_e(receiver_list=receiver_list, frequency=freq, s_e=vec) survey = fdem.Survey([src]) if sigmaInInversion: wires = maps.Wires(("mu", mesh.nC), ("sigma", mesh.nC)) muMap = maps.MuRelative(mesh) * wires.mu sigmaMap = maps.ExpMap(mesh) * wires.sigma if invertMui: muiMap = maps.ReciprocalMap(mesh) * muMap prob = getattr(fdem, "Simulation3D{}".format(prbtype))(mesh, muiMap=muiMap, sigmaMap=sigmaMap) # m0 = np.hstack([1./muMod, sigmaMod]) else: prob = getattr(fdem, "Simulation3D{}".format(prbtype))(mesh, muMap=muMap, sigmaMap=sigmaMap) m0 = np.hstack([muMod, sigmaMod]) else: muMap = maps.MuRelative(mesh) if invertMui: muiMap = maps.ReciprocalMap(mesh) * muMap prob = getattr(fdem, "Simulation3D{}".format(prbtype))(mesh, sigma=sigmaMod, muiMap=muiMap) # m0 = 1./muMod else: prob = getattr(fdem, "Simulation3D{}".format(prbtype))(mesh, sigma=sigmaMod, muMap=muMap) m0 = muMod prob.survey = survey return m0, prob, survey
# Load Topo topo_file = io_utils.download( "https://storage.googleapis.com/simpeg/pgi_tutorial_assets/CDED_Lake_warp.xyz" ) topo = np.genfromtxt(topo_file, skip_header=1) # find the active cells actv = utils.surface2ind_topo(mesh, topo, gridLoc="CC") # Create active map to go from reduce set to full ndv = np.nan actvMap = maps.InjectActiveCells(mesh, actv, ndv) nactv = int(actv.sum()) # Create simulations and data misfits # Wires mapping wires = maps.Wires(("den", actvMap.nP), ("sus", actvMap.nP)) gravmap = actvMap * wires.den magmap = actvMap * wires.sus idenMap = maps.IdentityMap(nP=nactv) # Grav problem simulation_grav = pf.gravity.simulation.Simulation3DIntegral( survey=data_grav.survey, mesh=mesh, rhoMap=wires.den, actInd=actv, ) dmis_grav = data_misfit.L2DataMisfit(data=data_grav, simulation=simulation_grav) # Mag problem simulation_mag = pf.magnetics.simulation.Simulation3DIntegral( survey=data_mag.survey,
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 ], )