def setUp_TDEM(prbtype="ElectricField", rxcomp="ElectricFieldx"): cs = 5.0 ncx = 8 ncy = 8 ncz = 8 npad = 0 # hx = [(cs, ncx), (cs, npad, 1.3)] # hz = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)] mesh = discretize.TensorMesh( [ [(cs, npad, -1.3), (cs, ncx), (cs, npad, 1.3)], [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)], [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)], ], "CCC", ) # active = mesh.vectorCCz < 0.0 activeMap = maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * activeMap rxOffset = 0.0 rxlocs = np.array([[20, 20.0, 0.0]]) rxtimes = np.logspace(-4, -3, 20) rx = getattr(tdem.Rx, "Point{}".format(rxcomp[:-1]))(locations=rxlocs, times=rxtimes, orientation=rxcomp[-1]) Aloc = np.r_[-10.0, 0.0, 0.0] Bloc = np.r_[10.0, 0.0, 0.0] srcloc = np.vstack((Aloc, Bloc)) src = tdem.Src.LineCurrent([rx], location=srcloc, waveform=tdem.Src.StepOffWaveform()) survey = tdem.Survey([src]) prb = getattr(tdem, "Simulation3D{}".format(prbtype))(mesh, sigmaMap=mapping) prb.time_steps = [(1e-05, 10), (5e-05, 10), (2.5e-4, 10)] prb.solver = Solver m = np.log(1e-1) * np.ones(prb.sigmaMap.nP) + 1e-3 * np.random.randn( prb.sigmaMap.nP) prb.pair(survey) mesh = mesh return prb, m, mesh
def setUp(self): mesh = discretize.TensorMesh([30]) sigma = np.ones(mesh.nC) model = np.log(sigma) receivers = survey.BaseRx(20 * [[0.0]]) source = survey.BaseSrc([receivers]) self.sim = simulation.ExponentialSinusoidSimulation( mesh=mesh, survey=survey.BaseSurvey([source]), model_map=maps.ExpMap(mesh)) self.dobs = self.sim.dpred(model)
def test_property_mirroring(self): mesh = discretize.TensorMesh([8, 7, 6]) for regType in ["Tikhonov", "Sparse", "Simple"]: reg = getattr(regularization, regType)(mesh) print(reg.nP, mesh.nC) self.assertTrue(reg.nP == mesh.nC) # Test assignment of active indices indActive = mesh.gridCC[:, 2] < 0.6 reg.indActive = indActive self.assertTrue(reg.nP == int(indActive.sum())) [ self.assertTrue(np.all(fct.indActive == indActive)) for fct in reg.objfcts ] # test assignment of cell weights cell_weights = np.random.rand(indActive.sum()) reg.cell_weights = cell_weights [ self.assertTrue(np.all(fct.cell_weights == cell_weights)) for fct in reg.objfcts ] # test updated mappings mapping = maps.ExpMap(nP=int(indActive.sum())) reg.mapping = mapping m = np.random.rand(mapping.nP) [ self.assertTrue(np.all(fct.mapping * m == mapping * m)) for fct in reg.objfcts ] # test alphas m = np.random.rand(reg.nP) a = reg(m) [ setattr( reg, "{}".format(objfct._multiplier_pair), 0.5 * getattr(reg, "{}".format(objfct._multiplier_pair)), ) for objfct in reg.objfcts ] b = reg(m) self.assertTrue(0.5 * a == b)
def test_sum(self): M2 = discretize.TensorMesh([np.ones(10), np.ones(20)], "CC") block = maps.ParametricEllipsoid(M2) * maps.Projection( 7, np.r_[1, 2, 3, 4, 5, 6]) background = (maps.ExpMap(M2) * maps.SurjectFull(M2) * maps.Projection(7, np.r_[0])) summap0 = maps.SumMap([block, background]) summap1 = block + background m0 = np.hstack([ np.random.rand(3), np.r_[M2.x0[0], 2 * M2.hx.min()], np.r_[M2.x0[1], 4 * M2.hy.min()], ]) self.assertTrue(np.all(summap0 * m0 == summap1 * m0)) self.assertTrue(summap0.test(m0)) self.assertTrue(summap1.test(m0))
def test_vangenuchten_k_m(self): mesh = discretize.TensorMesh([50]) expmap = maps.ExpMap(nP=mesh.nC) idnmap = maps.IdentityMap(nP=mesh.nC) seeds = { "Ks": np.random.triangular(np.log(1e-7), np.log(1e-6), np.log(1e-5), mesh.nC), "I": np.random.rand(mesh.nC), "n": np.random.rand(mesh.nC) + 1, "alpha": np.random.rand(mesh.nC), } opts = [ ("Ks", dict(KsMap=expmap), 1), ("I", dict(IMap=idnmap), 1), ("n", dict(nMap=idnmap), 1), ("alpha", dict(alphaMap=idnmap), 1), ] u = np.random.randn(mesh.nC) for name, opt, nM in opts: van = richards.empirical.Vangenuchten_k(mesh, **opt) x0 = np.concatenate([seeds[n] for n in name.split("-")]) def fun(m): van.model = m return van(u), van.derivM(u) print("Vangenuchten_k test m deriv: ", name) passed = checkDerivative(fun, x0, plotIt=False) self.assertTrue(passed, True)
def setUp(self): cs = 10 nc = 20 npad = 10 mesh = discretize.CylMesh([ [(cs, nc), (cs, npad, 1.3)], np.r_[2 * np.pi], [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)], ]) mesh.x0 = np.r_[0.0, 0.0, -mesh.hz[:npad + nc].sum()] # receivers rx_x = np.linspace(10, 200, 20) rx_z = np.r_[-5] rx_locs = utils.ndgrid([rx_x, np.r_[0], rx_z]) rx_list = [ dc.receivers.BaseRx(rx_locs, projField="e", orientation="x") ] # sources src_a = np.r_[0.0, 0.0, -5.0] src_b = np.r_[55.0, 0.0, -5.0] src_list = [ dc.sources.Dipole(rx_list, locationA=src_a, locationB=src_b) ] self.mesh = mesh self.survey = dc.survey.Survey(src_list) self.sigma_map = maps.ExpMap(mesh) * maps.InjectActiveCells( mesh, mesh.gridCC[:, 2] <= 0, np.log(1e-8)) self.prob = dc.simulation.Simulation3DCellCentered( mesh=mesh, survey=self.survey, sigmaMap=self.sigma_map, Solver=Pardiso, bc_type="Dirichlet", )
def getSensitivity(survey, A, B, M, N, model): src_type, rx_type = survey.split("-") if rx_type == "Pole": rx = DC.receivers.Pole(np.r_[M, 0.0]) else: rx = DC.receivers.Dipole(np.r_[M, 0.0], np.r_[N, 0.0]) if src_type == "Pole": src = DC.sources.Pole([rx], np.r_[A, 0.0]) else: src = DC.sources.Dipole([rx], np.r_[A, 0.0], np.r_[B, 0.0]) # Model mappings expmap = maps.ExpMap(mesh) mapping = expmap survey = DC.Survey([src]) sim = DC.Simulation3DCellCentered( mesh, sigmaMap=mapping, solver=Pardiso, survey=survey ) J = sim.getJ(model)[0] return J
def test_reciprocal_no_map(self): expMap = maps.ExpMap(discretize.TensorMesh((3,))) PM = ReciprocalExample() self.assertRaises(AttributeError, getattr, PM, "sigma") PM.sigmaMap = expMap # PM = pickle.loads(pickle.dumps(PM)) PM.model = np.r_[1.0, 2.0, 3.0] assert np.all(PM.sigma == np.exp(np.r_[1.0, 2.0, 3.0])) assert np.all(PM.rho == 1.0 / np.exp(np.r_[1.0, 2.0, 3.0])) PM.rho = np.r_[1.0, 2.0, 3.0] assert PM.sigmaMap is None assert PM.sigmaDeriv == 0 assert np.all(PM.sigma == 1.0 / np.r_[1.0, 2.0, 3.0]) PM.sigmaMap = expMap assert len(PM.sigmaMap) == 1 # PM = pickle.loads(pickle.dumps(PM)) assert np.all(PM.rho == 1.0 / np.exp(np.r_[1.0, 2.0, 3.0])) assert np.all(PM.sigma == np.exp(np.r_[1.0, 2.0, 3.0])) assert isinstance(PM.sigmaDeriv.todense(), np.ndarray)
def setUp(self): cs = 10.0 ncx, ncy, ncz = 30.0, 30.0, 30.0 npad = 10.0 hx = [(cs, npad, -1.5), (cs, ncx), (cs, npad, 1.5)] hy = [(cs, npad, -1.5), (cs, ncy), (cs, npad, 1.5)] hz = [(cs, npad, -1.5), (cs, ncz), (cs, npad, 1.5)] self.mesh = discretize.TensorMesh([hx, hy, hz], "CCC") mapping = maps.ExpMap(self.mesh) self.frequency = 1.0 self.prob_e = fdem.Simulation3DElectricField(self.mesh, sigmaMap=mapping) self.prob_b = fdem.Simulation3DMagneticFluxDensity(self.mesh, sigmaMap=mapping) self.prob_h = fdem.Simulation3DMagneticField(self.mesh, sigmaMap=mapping) self.prob_j = fdem.Simulation3DCurrentDensity(self.mesh, sigmaMap=mapping) loc = np.r_[0.0, 0.0, 0.0] self.location = utils.mkvc( self.mesh.gridCC[utils.closestPoints(self.mesh, loc, "CC"), :])
from discretize import TensorMesh from SimPEG import maps, SolverLU, utils from SimPEG.utils import ExtractCoreMesh from SimPEG.electromagnetics.static import resistivity as DC from ..base import widgetify # Mesh, mapping can be globals global npad = 15 growrate = 2.0 cs = 0.5 hx = [(cs, npad, -growrate), (cs, 200), (cs, npad, growrate)] hy = [(cs, npad, -growrate), (cs, 100)] mesh = TensorMesh([hx, hy], "CN") expmap = maps.ExpMap(mesh) mapping = expmap dx = 5 xr = np.arange(-40, 41, dx) dxr = np.diff(xr) xmin = -40.0 xmax = 40.0 ymin = -40.0 ymax = 8.0 xylim = np.c_[[xmin, ymin], [xmax, ymax]] indCC, meshcore = ExtractCoreMesh(xylim, mesh) indx = ( (mesh.gridFx[:, 0] >= xmin) & (mesh.gridFx[:, 0] <= xmax) & (mesh.gridFx[:, 1] >= ymin) & (mesh.gridFx[:, 1] <= ymax)
def halfSpaceProblemAnaDiff( meshType, srctype="MagDipole", sig_half=1e-2, rxOffset=50.0, bounds=None, plotIt=False, rxType="MagneticFluxDensityz", ): if bounds is None: bounds = [1e-5, 1e-3] if meshType == "CYL": cs, ncx, ncz, npad = 5.0, 30, 10, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = discretize.CylMesh([hx, 1, hz], "00C") elif meshType == "TENSOR": cs, nc, npad = 20.0, 13, 5 hx = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] mesh = discretize.TensorMesh([hx, hy, hz], "CCC") active = mesh.vectorCCz < 0.0 actMap = maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * actMap rx = getattr(tdem.Rx, "Point{}".format(rxType[:-1]))(np.array([[rxOffset, 0.0, 0.0]]), np.logspace(-5, -4, 21), rxType[-1]) if srctype == "MagDipole": src = tdem.Src.MagDipole( [rx], waveform=tdem.Src.StepOffWaveform(), location=np.array([0.0, 0.0, 0.0]), ) elif srctype == "CircularLoop": src = tdem.Src.CircularLoop( [rx], waveform=tdem.Src.StepOffWaveform(), location=np.array([0.0, 0.0, 0.0]), radius=0.1, ) survey = tdem.Survey([src]) time_steps = [ (1e-06, 40), (5e-06, 40), (1e-05, 40), (5e-05, 40), (0.0001, 40), (0.0005, 40), ] prb = tdem.Simulation3DMagneticFluxDensity(mesh, survey=survey, time_steps=time_steps, sigmaMap=mapping) prb.solver = Solver sigma = np.ones(mesh.nCz) * 1e-8 sigma[active] = sig_half sigma = np.log(sigma[active]) if srctype == "MagDipole": bz_ana = mu_0 * analytics.hzAnalyticDipoleT(rx.locations[0][0] + 1e-3, rx.times, sig_half) elif srctype == "CircularLoop": bz_ana = mu_0 * analytics.hzAnalyticDipoleT(13, rx.times, sig_half) bz_calc = prb.dpred(sigma) ind = np.logical_and(rx.times > bounds[0], rx.times < bounds[1]) log10diff = np.linalg.norm( np.log10(np.abs(bz_calc[ind])) - np.log10(np.abs(bz_ana[ind]))) / np.linalg.norm( np.log10(np.abs(bz_ana[ind]))) print(" |bz_ana| = {ana} |bz_num| = {num} |bz_ana-bz_num| = {diff}".format( ana=np.linalg.norm(bz_ana), num=np.linalg.norm(bz_calc), diff=np.linalg.norm(bz_ana - bz_calc), )) print("Difference: {}".format(log10diff)) if plotIt is True: plt.loglog( rx.times[bz_calc > 0], bz_calc[bz_calc > 0], "r", rx.times[bz_calc < 0], -bz_calc[bz_calc < 0], "r--", ) plt.loglog(rx.times, abs(bz_ana), "b*") plt.title("sig_half = {0:e}".format(sig_half)) plt.show() return log10diff
def run(plotIt=True, saveFig=False, cleanup=True): """ Run 1D inversions for a single sounding of the RESOLVE and SkyTEM bookpurnong data :param bool plotIt: show the plots? :param bool saveFig: save the figure :param bool cleanup: remove the downloaded results """ downloads, directory = download_and_unzip_data() resolve = h5py.File(os.path.sep.join([directory, "booky_resolve.hdf5"]), "r") skytem = h5py.File(os.path.sep.join([directory, "booky_skytem.hdf5"]), "r") river_path = resolve["river_path"].value # Choose a sounding location to invert xloc, yloc = 462100.0, 6196500.0 rxind_skytem = np.argmin( abs(skytem["xy"][:, 0] - xloc) + abs(skytem["xy"][:, 1] - yloc)) rxind_resolve = np.argmin( abs(resolve["xy"][:, 0] - xloc) + abs(resolve["xy"][:, 1] - yloc)) # Plot both resolve and skytem data on 2D plane fig = plt.figure(figsize=(13, 6)) title = ["RESOLVE In-phase 400 Hz", "SkyTEM High moment 156 $\mu$s"] ax1 = plt.subplot(121) ax2 = plt.subplot(122) axs = [ax1, ax2] out_re = utils.plot2Ddata( resolve["xy"], resolve["data"][:, 0], ncontour=100, contourOpts={"cmap": "viridis"}, ax=ax1, ) vmin, vmax = out_re[0].get_clim() cb_re = plt.colorbar(out_re[0], ticks=np.linspace(vmin, vmax, 3), ax=ax1, fraction=0.046, pad=0.04) temp_skytem = skytem["data"][:, 5].copy() temp_skytem[skytem["data"][:, 5] > 7e-10] = 7e-10 out_sky = utils.plot2Ddata( skytem["xy"][:, :2], temp_skytem, ncontour=100, contourOpts={ "cmap": "viridis", "vmax": 7e-10 }, ax=ax2, ) vmin, vmax = out_sky[0].get_clim() cb_sky = plt.colorbar( out_sky[0], ticks=np.linspace(vmin, vmax * 0.99, 3), ax=ax2, format="%.1e", fraction=0.046, pad=0.04, ) cb_re.set_label("Bz (ppm)") cb_sky.set_label("dB$_z$ / dt (V/A-m$^4$)") for i, ax in enumerate(axs): xticks = [460000, 463000] yticks = [6195000, 6198000, 6201000] ax.set_xticks(xticks) ax.set_yticks(yticks) ax.plot(xloc, yloc, "wo") ax.plot(river_path[:, 0], river_path[:, 1], "k", lw=0.5) ax.set_aspect("equal") if i == 1: ax.plot(skytem["xy"][:, 0], skytem["xy"][:, 1], "k.", alpha=0.02, ms=1) ax.set_yticklabels([str(" ") for f in yticks]) else: ax.plot(resolve["xy"][:, 0], resolve["xy"][:, 1], "k.", alpha=0.02, ms=1) ax.set_yticklabels([str(f) for f in yticks]) ax.set_ylabel("Northing (m)") ax.set_xlabel("Easting (m)") ax.set_title(title[i]) ax.axis("equal") # plt.tight_layout() if saveFig is True: fig.savefig("resolve_skytem_data.png", dpi=600) # ------------------ Mesh ------------------ # # Step1: Set 2D cylindrical mesh cs, ncx, ncz, npad = 1.0, 10.0, 10.0, 20 hx = [(cs, ncx), (cs, npad, 1.3)] npad = 12 temp = np.logspace(np.log10(1.0), np.log10(12.0), 19) temp_pad = temp[-1] * 1.3**np.arange(npad) hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad] mesh = discretize.CylMesh([hx, 1, hz], "00C") active = mesh.vectorCCz < 0.0 # Step2: Set a SurjectVertical1D mapping # Note: this sets our inversion model as 1D log conductivity # below subsurface active = mesh.vectorCCz < 0.0 actMap = maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * actMap sig_half = 1e-1 sig_air = 1e-8 sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half # Initial and reference model m0 = np.log(sigma[active]) # ------------------ RESOLVE Forward Simulation ------------------ # # Step3: Invert Resolve data # Bird height from the surface b_height_resolve = resolve["src_elevation"].value src_height_resolve = b_height_resolve[rxind_resolve] # Set Rx (In-phase and Quadrature) rxOffset = 7.86 bzr = FDEM.Rx.PointMagneticFluxDensitySecondary( np.array([[rxOffset, 0.0, src_height_resolve]]), orientation="z", component="real", ) bzi = FDEM.Rx.PointMagneticFluxDensity( np.array([[rxOffset, 0.0, src_height_resolve]]), orientation="z", component="imag", ) # Set Source (In-phase and Quadrature) frequency_cp = resolve["frequency_cp"].value freqs = frequency_cp.copy() srcLoc = np.array([0.0, 0.0, src_height_resolve]) srcList = [ FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation="Z") for freq in freqs ] # Set FDEM survey (In-phase and Quadrature) survey = FDEM.Survey(srcList) prb = FDEM.Simulation3DMagneticFluxDensity(mesh, sigmaMap=mapping, Solver=Solver) prb.survey = survey # ------------------ RESOLVE Inversion ------------------ # # Primary field bp = -mu_0 / (4 * np.pi * rxOffset**3) # Observed data cpi_inds = [0, 2, 6, 8, 10] cpq_inds = [1, 3, 7, 9, 11] dobs_re = (np.c_[resolve["data"][rxind_resolve, :][cpi_inds], resolve["data"][rxind_resolve, :][cpq_inds], ].flatten() * bp * 1e-6) # Uncertainty relative = np.repeat(np.r_[np.ones(3) * 0.1, np.ones(2) * 0.15], 2) floor = 20 * abs(bp) * 1e-6 std = abs(dobs_re) * relative + floor # Data Misfit data_resolve = data.Data(dobs=dobs_re, survey=survey, standard_deviation=std) dmisfit = data_misfit.L2DataMisfit(simulation=prb, data=data_resolve) # Regularization regMesh = discretize.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = regularization.Simple(regMesh, mapping=maps.IdentityMap(regMesh)) # Optimization opt = optimization.InexactGaussNewton(maxIter=5) # statement of the inverse problem invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) # Inversion directives and parameters target = directives.TargetMisfit() # stop when we hit target misfit invProb.beta = 2.0 inv = inversion.BaseInversion(invProb, directiveList=[target]) reg.alpha_s = 1e-3 reg.alpha_x = 1.0 reg.mref = m0.copy() opt.LSshorten = 0.5 opt.remember("xc") # run the inversion mopt_re = inv.run(m0) dpred_re = invProb.dpred # ------------------ SkyTEM Forward Simulation ------------------ # # Step4: Invert SkyTEM data # Bird height from the surface b_height_skytem = skytem["src_elevation"].value src_height = b_height_skytem[rxind_skytem] srcLoc = np.array([0.0, 0.0, src_height]) # Radius of the source loop area = skytem["area"].value radius = np.sqrt(area / np.pi) rxLoc = np.array([[radius, 0.0, src_height]]) # Parameters for current waveform t0 = skytem["t0"].value times = skytem["times"].value waveform_skytem = skytem["waveform"].value offTime = t0 times_off = times - t0 # Note: we are Using theoretical VTEM waveform, # but effectively fits SkyTEM waveform peakTime = 1.0000000e-02 a = 3.0 dbdt_z = TDEM.Rx.PointMagneticFluxTimeDerivative( locations=rxLoc, times=times_off[:-3] + offTime, orientation="z") # vertical db_dt rxList = [dbdt_z] # list of receivers srcList = [ TDEM.Src.CircularLoop( rxList, loc=srcLoc, radius=radius, orientation="z", waveform=TDEM.Src.VTEMWaveform(offTime=offTime, peakTime=peakTime, a=3.0), ) ] # solve the problem at these times timeSteps = [ (peakTime / 5, 5), ((offTime - peakTime) / 5, 5), (1e-5, 5), (5e-5, 5), (1e-4, 10), (5e-4, 15), ] prob = TDEM.Simulation3DElectricField(mesh, time_steps=timeSteps, sigmaMap=mapping, Solver=Solver) survey = TDEM.Survey(srcList) prob.survey = survey src = srcList[0] rx = src.receiver_list[0] wave = [] for time in prob.times: wave.append(src.waveform.eval(time)) wave = np.hstack(wave) out = prob.dpred(m0) # plot the waveform fig = plt.figure(figsize=(5, 3)) times_off = times - t0 plt.plot(waveform_skytem[:, 0], waveform_skytem[:, 1], "k.") plt.plot(prob.times, wave, "k-", lw=2) plt.legend(("SkyTEM waveform", "Waveform (fit)"), fontsize=10) for t in rx.times: plt.plot(np.ones(2) * t, np.r_[-0.03, 0.03], "k-") plt.ylim(-0.1, 1.1) plt.grid(True) plt.xlabel("Time (s)") plt.ylabel("Normalized current") if saveFig: fig.savefig("skytem_waveform", dpi=200) # Observed data dobs_sky = skytem["data"][rxind_skytem, :-3] * area # ------------------ SkyTEM Inversion ------------------ # # Uncertainty relative = 0.12 floor = 7.5e-12 std = abs(dobs_sky) * relative + floor # Data Misfit data_sky = data.Data(dobs=-dobs_sky, survey=survey, standard_deviation=std) dmisfit = data_misfit.L2DataMisfit(simulation=prob, data=data_sky) # Regularization regMesh = discretize.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = regularization.Simple(regMesh, mapping=maps.IdentityMap(regMesh)) # Optimization opt = optimization.InexactGaussNewton(maxIter=5) # statement of the inverse problem invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) # Directives and Inversion Parameters target = directives.TargetMisfit() invProb.beta = 20.0 inv = inversion.BaseInversion(invProb, directiveList=[target]) reg.alpha_s = 1e-1 reg.alpha_x = 1.0 opt.LSshorten = 0.5 opt.remember("xc") reg.mref = mopt_re # Use RESOLVE model as a reference model # run the inversion mopt_sky = inv.run(m0) dpred_sky = invProb.dpred # Plot the figure from the paper plt.figure(figsize=(12, 8)) fs = 13 # fontsize matplotlib.rcParams["font.size"] = fs ax0 = plt.subplot2grid((2, 2), (0, 0), rowspan=2) ax1 = plt.subplot2grid((2, 2), (0, 1)) ax2 = plt.subplot2grid((2, 2), (1, 1)) # Recovered Models sigma_re = np.repeat(np.exp(mopt_re), 2, axis=0) sigma_sky = np.repeat(np.exp(mopt_sky), 2, axis=0) z = np.repeat(mesh.vectorCCz[active][1:], 2, axis=0) z = np.r_[mesh.vectorCCz[active][0], z, mesh.vectorCCz[active][-1]] ax0.semilogx(sigma_re, z, "k", lw=2, label="RESOLVE") ax0.semilogx(sigma_sky, z, "b", lw=2, label="SkyTEM") ax0.set_ylim(-50, 0) # ax0.set_xlim(5e-4, 1e2) ax0.grid(True) ax0.set_ylabel("Depth (m)") ax0.set_xlabel("Conducivity (S/m)") ax0.legend(loc=3) ax0.set_title("(a) Recovered Models") # RESOLVE Data ax1.loglog(frequency_cp, dobs_re.reshape((5, 2))[:, 0] / bp * 1e6, "k-", label="Obs (real)") ax1.loglog( frequency_cp, dobs_re.reshape((5, 2))[:, 1] / bp * 1e6, "k--", label="Obs (imag)", ) ax1.loglog( frequency_cp, dpred_re.reshape((5, 2))[:, 0] / bp * 1e6, "k+", ms=10, markeredgewidth=2.0, label="Pred (real)", ) ax1.loglog( frequency_cp, dpred_re.reshape((5, 2))[:, 1] / bp * 1e6, "ko", ms=6, markeredgecolor="k", markeredgewidth=0.5, label="Pred (imag)", ) ax1.set_title("(b) RESOLVE") ax1.set_xlabel("Frequency (Hz)") ax1.set_ylabel("Bz (ppm)") ax1.grid(True) ax1.legend(loc=3, fontsize=11) # SkyTEM data ax2.loglog(times_off[3:] * 1e6, dobs_sky / area, "b-", label="Obs") ax2.loglog( times_off[3:] * 1e6, -dpred_sky / area, "bo", ms=4, markeredgecolor="k", markeredgewidth=0.5, label="Pred", ) ax2.set_xlim(times_off.min() * 1e6 * 1.2, times_off.max() * 1e6 * 1.1) ax2.set_xlabel("Time ($\mu s$)") ax2.set_ylabel("dBz / dt (V/A-m$^4$)") ax2.set_title("(c) SkyTEM High-moment") ax2.grid(True) ax2.legend(loc=3) a3 = plt.axes([0.86, 0.33, 0.1, 0.09], facecolor=[0.8, 0.8, 0.8, 0.6]) a3.plot(prob.times * 1e6, wave, "k-") a3.plot(rx.times * 1e6, np.zeros_like(rx.times), "k|", markeredgewidth=1, markersize=12) a3.set_xlim([prob.times.min() * 1e6 * 0.75, prob.times.max() * 1e6 * 1.1]) a3.set_title("(d) Waveform", fontsize=11) a3.set_xticks([prob.times.min() * 1e6, t0 * 1e6, prob.times.max() * 1e6]) a3.set_yticks([]) # a3.set_xticklabels(['0', '2e4']) a3.set_xticklabels(["-1e4", "0", "1e4"]) plt.tight_layout() if saveFig: plt.savefig("booky1D_time_freq.png", dpi=600) if plotIt: plt.show() resolve.close() skytem.close() if cleanup: print(os.path.split(directory)[:-1]) os.remove( os.path.sep.join(directory.split()[:-1] + ["._bookpurnong_inversion"])) os.remove(downloads) shutil.rmtree(directory)
# well as the mapping from the model space to the active cells. Starting and # reference models can be a constant background value or contain a-priori # structures. Here, the starting model is the natural log of 0.01 S/m. # # Define conductivity model in S/m air_conductivity = np.log(1e-8) background_conductivity = np.log(1e-2) # Find the indecies of the active cells in forward model (ones below surface) ind_active = surface2ind_topo(mesh, xyz_topo) active_map = maps.InjectActiveCells(mesh, ind_active, np.exp(air_conductivity)) nC = int(ind_active.sum()) model_map = active_map * maps.ExpMap() # Define model starting_model = background_conductivity * np.ones(nC) ############################################## # Define the Physics # ------------------ # # Here, we define the physics of the gravity problem by using the simulation # class. # simulation = fdem.simulation.Simulation3DMagneticFluxDensity( mesh, survey=survey, sigmaMap=model_map, Solver=Solver)
def run(plotIt=True): cs, ncx, ncz, npad = 5.0, 25, 24, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = discretize.CylMesh([hx, 1, hz], "00C") active = mesh.vectorCCz < 0.0 layer = (mesh.vectorCCz < -50.0) & (mesh.vectorCCz >= -150.0) actMap = maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * actMap sig_half = 1e-3 sig_air = 1e-8 sig_layer = 1e-2 sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half sigma[layer] = sig_layer mtrue = np.log(sigma[active]) x = np.r_[30, 50, 70, 90] rxloc = np.c_[x, x * 0.0, np.zeros_like(x)] prb = TDEM.Simulation3DMagneticFluxDensity(mesh, sigmaMap=mapping, solver=Solver) prb.time_steps = [ (1e-3, 5), (1e-4, 5), (5e-5, 10), (5e-5, 5), (1e-4, 10), (5e-4, 10), ] # Use VTEM waveform out = EMutils.VTEMFun(prb.times, 0.00595, 0.006, 100) # Forming function handle for waveform using 1D linear interpolation wavefun = interp1d(prb.times, out) t0 = 0.006 waveform = TDEM.Src.RawWaveform(offTime=t0, waveFct=wavefun) rx = TDEM.Rx.PointMagneticFluxTimeDerivative( rxloc, np.logspace(-4, -2.5, 11) + t0, "z") src = TDEM.Src.CircularLoop([rx], waveform=waveform, loc=np.array([0.0, 0.0, 0.0]), radius=10.0) survey = TDEM.Survey([src]) prb.survey = survey # create observed data data = prb.make_synthetic_data(mtrue, relative_error=0.02, noise_floor=1e-11) dmisfit = data_misfit.L2DataMisfit(simulation=prb, data=data) regMesh = discretize.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = regularization.Simple(regMesh) opt = optimization.InexactGaussNewton(maxIter=5, LSshorten=0.5) invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) target = directives.TargetMisfit() # Create an inversion object beta = directives.BetaSchedule(coolingFactor=1.0, coolingRate=2.0) betaest = directives.BetaEstimate_ByEig(beta0_ratio=1e0) invProb.beta = 1e2 inv = inversion.BaseInversion(invProb, directiveList=[beta, target]) m0 = np.log(np.ones(mtrue.size) * sig_half) prb.counter = opt.counter = utils.Counter() opt.remember("xc") mopt = inv.run(m0) if plotIt: fig, ax = plt.subplots(1, 2, figsize=(10, 6)) Dobs = data.dobs.reshape((len(rx.times), len(x))) Dpred = invProb.dpred.reshape((len(rx.times), len(x))) for i in range(len(x)): ax[0].loglog(rx.times - t0, -Dobs[:, i].flatten(), "k") ax[0].loglog(rx.times - t0, -Dpred[:, i].flatten(), "k.") if i == 0: ax[0].legend(("$d^{obs}$", "$d^{pred}$"), fontsize=16) ax[0].set_xlabel("Time (s)", fontsize=14) ax[0].set_ylabel("$db_z / dt$ (nT/s)", fontsize=16) ax[0].set_xlabel("Time (s)", fontsize=14) ax[0].grid(color="k", alpha=0.5, linestyle="dashed", linewidth=0.5) plt.semilogx(sigma[active], mesh.vectorCCz[active]) plt.semilogx(np.exp(mopt), mesh.vectorCCz[active]) ax[1].set_ylim(-600, 0) ax[1].set_xlim(1e-4, 1e-1) ax[1].set_xlabel("Conductivity (S/m)", fontsize=14) ax[1].set_ylabel("Depth (m)", fontsize=14) ax[1].grid(color="k", alpha=0.5, linestyle="dashed", linewidth=0.5) plt.legend(["$\sigma_{true}$", "$\sigma_{pred}$"])
# Define the model on subsurface cells model = background_value * np.ones(ind_active.sum()) ind_dyke = (mesh.gridCC[ind_active, 0] > 20.0) & (mesh.gridCC[ind_active, 0] < 40.0) model[ind_dyke] = dyke_value ind_block = ((mesh.gridCC[ind_active, 0] > -40.0) & (mesh.gridCC[ind_active, 0] < -10.0) & (mesh.gridCC[ind_active, 1] > -30.0) & (mesh.gridCC[ind_active, 1] < 30.0) & (mesh.gridCC[ind_active, 2] > -40.0) & (mesh.gridCC[ind_active, 2] < 0.0)) model[ind_block] = block_value # Define a single mapping from model to mesh exponential_map = maps.ExpMap() reciprocal_map = maps.ReciprocalMap() model_map = active_map * reciprocal_map * exponential_map # Plot fig = plt.figure(figsize=(5, 5)) ax = fig.add_subplot(111) ind_slice = int(mesh.hy.size / 2) mesh.plotSlice(model_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() ############################################# # Models with arbitrary shapes # ----------------------------
# # Here, we create starting and/or reference models for the inversion as # well as the mapping from the model space to the active cells. Starting and # reference models can be a constant background value or contain a-priori # structures. Here, the starting model is log(1000) Ohm meters. # # Define log-resistivity values for each layer since our model is the # log-resistivity. Don't make the values 0! # Otherwise the gradient for the 1st iteration is zero and the inversion will # not converge. # Define model. A resistivity (Ohm meters) or conductivity (S/m) for each layer. starting_model = np.log(2e2 * np.ones((len(layer_thicknesses) + 1))) # Define mapping from model to active cells. model_map = maps.IdentityMap(nP=len(starting_model)) * maps.ExpMap() ####################################################################### # Define the Physics # ------------------ # # Here we define the physics of the problem using the Simulation1DLayers class. # simulation = dc.simulation_1d.Simulation1DLayers( survey=survey, rhoMap=model_map, thicknesses=layer_thicknesses, data_type="apparent_resistivity", )
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, data_type="apparent_resistivity",
def run(plotIt=True): cs, ncx, ncz, npad = 5.0, 25, 15, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = discretize.CylMesh([hx, 1, hz], "00C") active = mesh.vectorCCz < 0.0 layer = (mesh.vectorCCz < 0.0) & (mesh.vectorCCz >= -100.0) actMap = maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * actMap sig_half = 2e-3 sig_air = 1e-8 sig_layer = 1e-3 sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half sigma[layer] = sig_layer mtrue = np.log(sigma[active]) rxOffset = 1e-3 rx = time_domain.Rx.PointMagneticFluxTimeDerivative( np.array([[rxOffset, 0.0, 30]]), np.logspace(-5, -3, 31), "z" ) src = time_domain.Src.MagDipole([rx], location=np.array([0.0, 0.0, 80])) survey = time_domain.Survey([src]) time_steps = [(1e-06, 20), (1e-05, 20), (0.0001, 20)] simulation = time_domain.Simulation3DElectricField( mesh, sigmaMap=mapping, survey=survey, time_steps=time_steps ) # d_true = simulation.dpred(mtrue) # create observed data rel_err = 0.05 data = simulation.make_synthetic_data(mtrue, relative_error=rel_err) dmisfit = data_misfit.L2DataMisfit(simulation=simulation, data=data) regMesh = discretize.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = regularization.Tikhonov(regMesh, alpha_s=1e-2, alpha_x=1.0) opt = optimization.InexactGaussNewton(maxIter=5, LSshorten=0.5) invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) # Create an inversion object beta = directives.BetaSchedule(coolingFactor=5, coolingRate=2) betaest = directives.BetaEstimate_ByEig(beta0_ratio=1e0) inv = inversion.BaseInversion(invProb, directiveList=[beta, betaest]) m0 = np.log(np.ones(mtrue.size) * sig_half) simulation.counter = opt.counter = utils.Counter() opt.remember("xc") mopt = inv.run(m0) if plotIt: fig, ax = plt.subplots(1, 2, figsize=(10, 6)) ax[0].loglog(rx.times, -invProb.dpred, "b.-") ax[0].loglog(rx.times, -data.dobs, "r.-") ax[0].legend(("Noisefree", "$d^{obs}$"), fontsize=16) ax[0].set_xlabel("Time (s)", fontsize=14) ax[0].set_ylabel("$B_z$ (T)", fontsize=16) ax[0].set_xlabel("Time (s)", fontsize=14) ax[0].grid(color="k", alpha=0.5, linestyle="dashed", linewidth=0.5) plt.semilogx(sigma[active], mesh.vectorCCz[active]) plt.semilogx(np.exp(mopt), mesh.vectorCCz[active]) ax[1].set_ylim(-600, 0) ax[1].set_xlim(1e-4, 1e-2) ax[1].set_xlabel("Conductivity (S/m)", fontsize=14) ax[1].set_ylabel("Depth (m)", fontsize=14) ax[1].grid(color="k", alpha=0.5, linestyle="dashed", linewidth=0.5) plt.legend(["$\sigma_{true}$", "$\sigma_{pred}$"])
def run(runIt=False, plotIt=True, saveIt=False, saveFig=False, cleanup=True): """ Run the bookpurnong 1D stitched RESOLVE inversions. :param bool runIt: re-run the inversions? Default downloads and plots saved results :param bool plotIt: show the plots? :param bool saveIt: save the re-inverted results? :param bool saveFig: save the figure :param bool cleanup: remove the downloaded results """ # download the data downloads, directory = download_and_unzip_data() # Load resolve data resolve = h5py.File(os.path.sep.join([directory, "booky_resolve.hdf5"]), "r") river_path = resolve["river_path"][()] # River path nSounding = resolve["data"].shape[0] # the # of soundings # Bird height from surface b_height_resolve = resolve["src_elevation"][()] # fetch the frequencies we are considering cpi_inds = [0, 2, 6, 8, 10] # Indices for HCP in-phase cpq_inds = [1, 3, 7, 9, 11] # Indices for HCP quadrature frequency_cp = resolve["frequency_cp"][()] # build a mesh cs, ncx, ncz, npad = 1.0, 10.0, 10.0, 20 hx = [(cs, ncx), (cs, npad, 1.3)] npad = 12 temp = np.logspace(np.log10(1.0), np.log10(12.0), 19) temp_pad = temp[-1] * 1.3**np.arange(npad) hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad] mesh = discretize.CylMesh([hx, 1, hz], "00C") active = mesh.vectorCCz < 0.0 # survey parameters rxOffset = 7.86 # tx-rx separation bp = -mu_0 / (4 * np.pi * rxOffset**3) # primary magnetic field # re-run the inversion if runIt: # set up the mappings - we are inverting for 1D log conductivity # below the earth's surface. actMap = maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * actMap # build starting and reference model sig_half = 1e-1 sig_air = 1e-8 sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half m0 = np.log(1e-1) * np.ones(active.sum()) # starting model mref = np.log(1e-1) * np.ones(active.sum()) # reference model # initalize empty lists for storing inversion results mopt_re = [] # recovered model dpred_re = [] # predicted data dobs_re = [] # observed data # downsample the data for the inversion nskip = 40 # set up a noise model # 10% for the 3 lowest frequencies, 15% for the two highest relative = np.repeat(np.r_[np.ones(3) * 0.1, np.ones(2) * 0.15], 2) floor = abs(20 * bp * 1e-6) # floor of 20ppm # loop over the soundings and invert each for rxind in range(nSounding): # convert data from ppm to magnetic field (A/m^2) dobs = (np.c_[resolve["data"][rxind, :][cpi_inds].astype(float), resolve["data"][ rxind, :][cpq_inds].astype(float), ].flatten() * bp * 1e-6) # perform the inversion src_height = b_height_resolve[rxind].astype(float) mopt, dpred, dobs = resolve_1Dinversions( mesh, dobs, src_height, frequency_cp, m0, mref, mapping, relative=relative, floor=floor, ) # add results to our list mopt_re.append(mopt) dpred_re.append(dpred) dobs_re.append(dobs) # save results mopt_re = np.vstack(mopt_re) dpred_re = np.vstack(dpred_re) dobs_re = np.vstack(dobs_re) if saveIt: np.save("mopt_re_final", mopt_re) np.save("dobs_re_final", dobs_re) np.save("dpred_re_final", dpred_re) mopt_re = resolve["mopt"][()] dobs_re = resolve["dobs"][()] dpred_re = resolve["dpred"][()] sigma = np.exp(mopt_re) indz = -7 # depth index # so that we can visually compare with literature (eg Viezzoli, 2010) cmap = "jet" # dummy figure for colobar fig = plt.figure() out = plt.scatter(np.ones(3), np.ones(3), c=np.linspace(-2, 1, 3), cmap=cmap) plt.close(fig) # plot from the paper fs = 13 # fontsize # matplotlib.rcParams['font.size'] = fs plt.figure(figsize=(13, 7)) ax0 = plt.subplot2grid((2, 3), (0, 0), rowspan=2, colspan=2) ax1 = plt.subplot2grid((2, 3), (0, 2)) ax2 = plt.subplot2grid((2, 3), (1, 2)) # titles of plots title = [ ("(a) Recovered model, %.1f m depth") % (-mesh.vectorCCz[active][indz]), "(b) Obs (Real 400 Hz)", "(c) Pred (Real 400 Hz)", ] temp = sigma[:, indz] tree = cKDTree(list(zip(resolve["xy"][:, 0], resolve["xy"][:, 1]))) d, d_inds = tree.query(list(zip(resolve["xy"][:, 0], resolve["xy"][:, 1])), k=20) w = 1.0 / (d + 100.0)**2.0 w = utils.sdiag(1.0 / np.sum(w, axis=1)) * (w) xy = resolve["xy"] temp = (temp.flatten()[d_inds] * w).sum(axis=1) utils.plot2Ddata( xy, temp, ncontour=100, scale="log", dataloc=False, contourOpts={ "cmap": cmap, "vmin": 1e-2, "vmax": 1e1 }, ax=ax0, ) ax0.plot(resolve["xy"][:, 0], resolve["xy"][:, 1], "k.", alpha=0.02, ms=1) cb = plt.colorbar(out, ax=ax0, ticks=np.linspace(-2, 1, 4), format="$10^{%.1f}$") cb.set_ticklabels(["0.01", "0.1", "1", "10"]) cb.set_label("Conductivity (S/m)") ax0.plot(river_path[:, 0], river_path[:, 1], "k-", lw=0.5) # plot observed and predicted data freq_ind = 0 axs = [ax1, ax2] temp_dobs = dobs_re[:, freq_ind].copy() ax1.plot(river_path[:, 0], river_path[:, 1], "k-", lw=0.5) inf = temp_dobs / abs(bp) * 1e6 print(inf.min(), inf.max()) out = utils.plot2Ddata( resolve["xy"][()], temp_dobs / abs(bp) * 1e6, ncontour=100, scale="log", dataloc=False, ax=ax1, contourOpts={"cmap": "viridis"}, ) vmin, vmax = out[0].get_clim() print(vmin, vmax) cb = plt.colorbar( out[0], ticks=np.logspace(np.log10(vmin), np.log10(vmax), 3), ax=ax1, format="%.1e", fraction=0.046, pad=0.04, ) cb.set_label("Bz (ppm)") temp_dpred = dpred_re[:, freq_ind].copy() # temp_dpred[mask_:_data] = np.nan ax2.plot(river_path[:, 0], river_path[:, 1], "k-", lw=0.5) utils.plot2Ddata( resolve["xy"][()], temp_dpred / abs(bp) * 1e6, ncontour=100, scale="log", dataloc=False, contourOpts={ "vmin": vmin, "vmax": vmax, "cmap": "viridis" }, ax=ax2, ) cb = plt.colorbar( out[0], ticks=np.logspace(np.log10(vmin), np.log10(vmax), 3), ax=ax2, format="%.1e", fraction=0.046, pad=0.04, ) cb.set_label("Bz (ppm)") for i, ax in enumerate([ax0, ax1, ax2]): xticks = [460000, 463000] yticks = [6195000, 6198000, 6201000] xloc, yloc = 462100.0, 6196500.0 ax.set_xticks(xticks) ax.set_yticks(yticks) # ax.plot(xloc, yloc, 'wo') ax.plot(river_path[:, 0], river_path[:, 1], "k", lw=0.5) ax.set_aspect("equal") ax.plot(resolve["xy"][:, 0], resolve["xy"][:, 1], "k.", alpha=0.02, ms=1) ax.set_yticklabels([str(f) for f in yticks]) ax.set_ylabel("Northing (m)") ax.set_xlabel("Easting (m)") ax.set_title(title[i]) plt.tight_layout() if plotIt: plt.show() if saveFig is True: fig.savefig("obspred_resolve.png", dpi=200) resolve.close() if cleanup: os.remove(downloads) shutil.rmtree(directory)
def test_io_rhoa(self): # Setup a dipole-dipole Survey for survey_type, test_file, rhoa_file in zip( ["dipole-dipole", "pole-dipole", "dipole-pole", "pole-pole"], [ "2sph_dipole_dipole.obs", "2sph_pole_dipole.obs", "2sph_dipole_pole.obs", "2sph_pole_pole.obs", ], [ "rhoA_GIF_dd.txt", "rhoA_GIF_pd.txt", "rhoA_GIF_dp.txt", "rhoA_GIF_pp.txt", ], ): print("\n Testing {} ... ".format(survey_type)) survey = utils.gen_DCIPsurvey( self.xyz, survey_type=survey_type, dim=self.mesh.dim, a=self.survey_a, b=self.survey_b, n=self.survey_n, ) self.assertEqual(survey_type, survey.survey_type) # Setup Problem with exponential mapping expmap = maps.ExpMap(self.mesh) problem = dc.Simulation3DCellCentered( self.mesh, sigmaMap=expmap, survey=survey, bc_type="Neumann" ) problem.solver = Solver # Create synthetic data dobs = problem.make_synthetic_data(self.model, relative_error=0.0) dobs.eps = 1e-5 # Testing IO surveyfile = os.path.sep.join([self.basePath, test_file]) utils.writeUBC_DCobs( surveyfile, dobs, survey_type=survey_type, dim=3, format_type="GENERAL" ) data2 = utils.readUBC_DC3Dobs(surveyfile) self.assertTrue(np.allclose(mkvc(data2), mkvc(dobs))) if self.plotIt: import matplotlib.pyplot as plt # Test Pseudosections plotting fig, ax = plt.subplots(1, 1, figsize=(15, 3)) ax = utils.plot_pseudoSection( survey, ax, survey_type=survey_type, scale="log", clim=None, data_type="appResistivity", pcolorOpts={"cmap": "viridis"}, data_location=True, ) plt.show() # Test the utils functions electrode_separations, # source_receiver_midpoints, geometric_factor, # apparent_resistivity all at once rhoapp = utils.apparent_resistivity( dobs, survey_type=survey_type, space_type="half-space", eps=0.0 ) rhoA_GIF_file = os.path.sep.join([self.basePath, rhoa_file]) rhoA_GIF = np.loadtxt(rhoA_GIF_file) passed = np.allclose(rhoapp, rhoA_GIF) self.assertTrue(passed) print(" ... ok \n".format(survey_type))
def get_mapping(mesh): active = mesh.vectorCCz < 0.0 activeMap = maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) return maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * activeMap
def run(plotIt=True, survey_type="dipole-dipole", p=0.0, qx=2.0, qz=2.0): np.random.seed(1) # Initiate I/O class for DC IO = DC.IO() # Obtain ABMN locations xmin, xmax = 0.0, 200.0 ymin, ymax = 0.0, 0.0 zmin, zmax = 0, 0 endl = np.array([[xmin, ymin, zmin], [xmax, ymax, zmax]]) # Generate DC survey object survey = gen_DCIPsurvey(endl, survey_type=survey_type, dim=2, a=10, b=10, n=10) survey = IO.from_abmn_locations_to_survey( survey.locations_a, survey.locations_b, survey.locations_m, survey.locations_n, survey_type, data_dc_type="volt", ) # Obtain 2D TensorMesh mesh, actind = IO.set_mesh() topo, mesh1D = genTopography(mesh, -10, 0, its=100) actind = utils.surface2ind_topo(mesh, np.c_[mesh1D.vectorCCx, topo]) survey.drape_electrodes_on_topography(mesh, actind, option="top") # Build a conductivity model blk_inds_c = utils.model_builder.getIndicesSphere(np.r_[60.0, -25.0], 12.5, mesh.gridCC) blk_inds_r = utils.model_builder.getIndicesSphere(np.r_[140.0, -25.0], 12.5, mesh.gridCC) layer_inds = mesh.gridCC[:, 1] > -5.0 sigma = np.ones(mesh.nC) * 1.0 / 100.0 sigma[blk_inds_c] = 1.0 / 10.0 sigma[blk_inds_r] = 1.0 / 1000.0 sigma[~actind] = 1.0 / 1e8 rho = 1.0 / sigma # Show the true conductivity model if plotIt: fig = plt.figure(figsize=(12, 3)) ax = plt.subplot(111) temp = rho.copy() temp[~actind] = np.nan out = mesh.plotImage( temp, grid=True, ax=ax, gridOpts={"alpha": 0.2}, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ) ax.plot(survey.electrode_locations[:, 0], survey.electrode_locations[:, 1], "k.") ax.set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max()) ax.set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min()) cb = plt.colorbar(out[0]) cb.set_label("Resistivity (ohm-m)") ax.set_aspect("equal") plt.show() # Use Exponential Map: m = log(rho) actmap = maps.InjectActiveCells(mesh, indActive=actind, valInactive=np.log(1e8)) mapping = maps.ExpMap(mesh) * actmap # Generate mtrue mtrue = np.log(rho[actind]) # Generate 2.5D DC problem # "N" means potential is defined at nodes prb = DC.Simulation2DNodal(mesh, survey=survey, rhoMap=mapping, storeJ=True, Solver=Solver, verbose=True) # Make synthetic DC data with 5% Gaussian noise data = prb.make_synthetic_data(mtrue, relative_error=0.05, add_noise=True) IO.data_dc = data.dobs # Show apparent resisitivty pseudo-section if plotIt: IO.plotPseudoSection(data=data.dobs / IO.G, data_type="apparent_resistivity") # Show apparent resisitivty histogram if plotIt: fig = plt.figure() out = hist(data.dobs / IO.G, bins=20) plt.xlabel("Apparent Resisitivty ($\Omega$m)") plt.show() # Set initial model based upon histogram m0 = np.ones(actmap.nP) * np.log(100.0) # Set standard_deviation # floor eps = 10**(-3.2) # percentage relative = 0.05 dmisfit = data_misfit.L2DataMisfit(simulation=prb, data=data) uncert = abs(data.dobs) * relative + eps dmisfit.standard_deviation = uncert # Map for a regularization regmap = maps.IdentityMap(nP=int(actind.sum())) # Related to inversion reg = regularization.Sparse(mesh, indActive=actind, mapping=regmap, gradientType="components") # gradientType = 'components' reg.norms = np.c_[p, qx, qz, 0.0] IRLS = directives.Update_IRLS(max_irls_iterations=20, minGNiter=1, beta_search=False, fix_Jmatrix=True) opt = optimization.InexactGaussNewton(maxIter=40) invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) beta = directives.BetaSchedule(coolingFactor=5, coolingRate=2) betaest = directives.BetaEstimate_ByEig(beta0_ratio=1e0) target = directives.TargetMisfit() update_Jacobi = directives.UpdatePreconditioner() inv = inversion.BaseInversion(invProb, directiveList=[betaest, IRLS]) prb.counter = opt.counter = utils.Counter() opt.LSshorten = 0.5 opt.remember("xc") # Run inversion mopt = inv.run(m0) rho_est = mapping * mopt rho_est_l2 = mapping * invProb.l2model rho_est[~actind] = np.nan rho_est_l2[~actind] = np.nan rho_true = rho.copy() rho_true[~actind] = np.nan # show recovered conductivity if plotIt: vmin, vmax = rho.min(), rho.max() fig, ax = plt.subplots(3, 1, figsize=(20, 9)) out1 = mesh.plotImage( rho_true, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ax=ax[0], ) out2 = mesh.plotImage( rho_est_l2, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ax=ax[1], ) out3 = mesh.plotImage( rho_est, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ax=ax[2], ) out = [out1, out2, out3] titles = ["True", "L2", ("L%d, Lx%d, Lz%d") % (p, qx, qz)] for i in range(3): ax[i].plot(survey.electrode_locations[:, 0], survey.electrode_locations[:, 1], "kv") ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max()) ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min()) cb = plt.colorbar(out[i][0], ax=ax[i]) cb.set_label("Resistivity ($\Omega$m)") ax[i].set_xlabel("Northing (m)") ax[i].set_ylabel("Elevation (m)") ax[i].set_aspect("equal") ax[i].set_title(titles[i]) plt.tight_layout() plt.show()
def run(plotIt=True, saveFig=False): # Set up cylindrically symmeric mesh cs, ncx, ncz, npad = 10.0, 15, 25, 13 # padded cyl mesh hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = discretize.CylMesh([hx, 1, hz], "00C") # Conductivity model layerz = np.r_[-200.0, -100.0] layer = (mesh.vectorCCz >= layerz[0]) & (mesh.vectorCCz <= layerz[1]) active = mesh.vectorCCz < 0.0 sig_half = 1e-2 # Half-space conductivity sig_air = 1e-8 # Air conductivity sig_layer = 5e-2 # Layer conductivity sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half sigma[layer] = sig_layer # Mapping actMap = maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * actMap mtrue = np.log(sigma[active]) # ----- FDEM problem & survey ----- # rxlocs = utils.ndgrid([np.r_[50.0], np.r_[0], np.r_[0.0]]) bzr = FDEM.Rx.PointMagneticFluxDensitySecondary(rxlocs, "z", "real") bzi = FDEM.Rx.PointMagneticFluxDensitySecondary(rxlocs, "z", "imag") freqs = np.logspace(2, 3, 5) srcLoc = np.array([0.0, 0.0, 0.0]) print( "min skin depth = ", 500.0 / np.sqrt(freqs.max() * sig_half), "max skin depth = ", 500.0 / np.sqrt(freqs.min() * sig_half), ) print( "max x ", mesh.vectorCCx.max(), "min z ", mesh.vectorCCz.min(), "max z ", mesh.vectorCCz.max(), ) source_list = [ FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation="Z") for freq in freqs ] surveyFD = FDEM.Survey(source_list) prbFD = FDEM.Simulation3DMagneticFluxDensity( mesh, survey=surveyFD, sigmaMap=mapping, solver=Solver ) rel_err = 0.03 dataFD = prbFD.make_synthetic_data(mtrue, relative_error=rel_err, add_noise=True) dataFD.noise_floor = np.linalg.norm(dataFD.dclean) * 1e-5 # FDEM inversion np.random.seed(1) dmisfit = data_misfit.L2DataMisfit(simulation=prbFD, data=dataFD) regMesh = discretize.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = regularization.Simple(regMesh) opt = optimization.InexactGaussNewton(maxIterCG=10) invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) # Inversion Directives beta = directives.BetaSchedule(coolingFactor=4, coolingRate=3) betaest = directives.BetaEstimate_ByEig(beta0_ratio=1.0, seed=518936) target = directives.TargetMisfit() directiveList = [beta, betaest, target] inv = inversion.BaseInversion(invProb, directiveList=directiveList) m0 = np.log(np.ones(mtrue.size) * sig_half) reg.alpha_s = 5e-1 reg.alpha_x = 1.0 prbFD.counter = opt.counter = utils.Counter() opt.remember("xc") moptFD = inv.run(m0) # TDEM problem times = np.logspace(-4, np.log10(2e-3), 10) print( "min diffusion distance ", 1.28 * np.sqrt(times.min() / (sig_half * mu_0)), "max diffusion distance ", 1.28 * np.sqrt(times.max() / (sig_half * mu_0)), ) rx = TDEM.Rx.PointMagneticFluxDensity(rxlocs, times, "z") src = TDEM.Src.MagDipole( [rx], waveform=TDEM.Src.StepOffWaveform(), location=srcLoc, # same src location as FDEM problem ) surveyTD = TDEM.Survey([src]) prbTD = TDEM.Simulation3DMagneticFluxDensity( mesh, survey=surveyTD, sigmaMap=mapping, solver=Solver ) prbTD.time_steps = [(5e-5, 10), (1e-4, 10), (5e-4, 10)] rel_err = 0.03 dataTD = prbTD.make_synthetic_data(mtrue, relative_error=rel_err, add_noise=True) dataTD.noise_floor = np.linalg.norm(dataTD.dclean) * 1e-5 # TDEM inversion dmisfit = data_misfit.L2DataMisfit(simulation=prbTD, data=dataTD) regMesh = discretize.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = regularization.Simple(regMesh) opt = optimization.InexactGaussNewton(maxIterCG=10) invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) # directives beta = directives.BetaSchedule(coolingFactor=4, coolingRate=3) betaest = directives.BetaEstimate_ByEig(beta0_ratio=1.0, seed=518936) target = directives.TargetMisfit() directiveList = [beta, betaest, target] inv = inversion.BaseInversion(invProb, directiveList=directiveList) m0 = np.log(np.ones(mtrue.size) * sig_half) reg.alpha_s = 5e-1 reg.alpha_x = 1.0 prbTD.counter = opt.counter = utils.Counter() opt.remember("xc") moptTD = inv.run(m0) # Plot the results if plotIt: plt.figure(figsize=(10, 8)) ax0 = plt.subplot2grid((2, 2), (0, 0), rowspan=2) ax1 = plt.subplot2grid((2, 2), (0, 1)) ax2 = plt.subplot2grid((2, 2), (1, 1)) fs = 13 # fontsize matplotlib.rcParams["font.size"] = fs # Plot the model # z_true = np.repeat(mesh.vectorCCz[active][1:], 2, axis=0) # z_true = np.r_[mesh.vectorCCz[active][0], z_true, mesh.vectorCCz[active][-1]] activeN = mesh.vectorNz <= 0.0 + cs / 2.0 z_true = np.repeat(mesh.vectorNz[activeN][1:-1], 2, axis=0) z_true = np.r_[mesh.vectorNz[activeN][0], z_true, mesh.vectorNz[activeN][-1]] sigma_true = np.repeat(sigma[active], 2, axis=0) ax0.semilogx(sigma_true, z_true, "k-", lw=2, label="True") ax0.semilogx( np.exp(moptFD), mesh.vectorCCz[active], "bo", ms=6, markeredgecolor="k", markeredgewidth=0.5, label="FDEM", ) ax0.semilogx( np.exp(moptTD), mesh.vectorCCz[active], "r*", ms=10, markeredgecolor="k", markeredgewidth=0.5, label="TDEM", ) ax0.set_ylim(-700, 0) ax0.set_xlim(5e-3, 1e-1) ax0.set_xlabel("Conductivity (S/m)", fontsize=fs) ax0.set_ylabel("Depth (m)", fontsize=fs) ax0.grid(which="both", color="k", alpha=0.5, linestyle="-", linewidth=0.2) ax0.legend(fontsize=fs, loc=4) # plot the data misfits - negative b/c we choose positive to be in the # direction of primary ax1.plot(freqs, -dataFD.dobs[::2], "k-", lw=2, label="Obs (real)") ax1.plot(freqs, -dataFD.dobs[1::2], "k--", lw=2, label="Obs (imag)") dpredFD = prbFD.dpred(moptTD) ax1.loglog( freqs, -dpredFD[::2], "bo", ms=6, markeredgecolor="k", markeredgewidth=0.5, label="Pred (real)", ) ax1.loglog( freqs, -dpredFD[1::2], "b+", ms=10, markeredgewidth=2.0, label="Pred (imag)" ) ax2.loglog(times, dataTD.dobs, "k-", lw=2, label="Obs") ax2.loglog( times, prbTD.dpred(moptTD), "r*", ms=10, markeredgecolor="k", markeredgewidth=0.5, label="Pred", ) ax2.set_xlim(times.min() - 1e-5, times.max() + 1e-4) # Labels, gridlines, etc ax2.grid(which="both", alpha=0.5, linestyle="-", linewidth=0.2) ax1.grid(which="both", alpha=0.5, linestyle="-", linewidth=0.2) ax1.set_xlabel("Frequency (Hz)", fontsize=fs) ax1.set_ylabel("Vertical magnetic field (-T)", fontsize=fs) ax2.set_xlabel("Time (s)", fontsize=fs) ax2.set_ylabel("Vertical magnetic field (T)", fontsize=fs) ax2.legend(fontsize=fs, loc=3) ax1.legend(fontsize=fs, loc=3) ax1.set_xlim(freqs.max() + 1e2, freqs.min() - 1e1) ax0.set_title("(a) Recovered Models", fontsize=fs) ax1.set_title("(b) FDEM observed vs. predicted", fontsize=fs) ax2.set_title("(c) TDEM observed vs. predicted", fontsize=fs) plt.tight_layout(pad=1.5) if saveFig is True: plt.savefig("example1.png", dpi=600)
def run( plotIt=True, survey_type="dipole-dipole", rho_background=1e3, rho_block=1e2, block_x0=100, block_dx=10, block_y0=-10, block_dy=5, ): np.random.seed(1) # Initiate I/O class for DC IO = DC.IO() # Obtain ABMN locations xmin, xmax = 0.0, 200.0 ymin, ymax = 0.0, 0.0 zmin, zmax = 0, 0 endl = np.array([[xmin, ymin, zmin], [xmax, ymax, zmax]]) # Generate DC survey object survey = DCutils.gen_DCIPsurvey(endl, survey_type=survey_type, dim=2, a=10, b=10, n=10) survey = IO.from_ambn_locations_to_survey( survey.locations_a, survey.locations_b, survey.locations_m, survey.locations_n, survey_type, data_dc_type="volt", ) # Obtain 2D TensorMesh mesh, actind = IO.set_mesh() # Flat topography actind = utils.surface2ind_topo( mesh, np.c_[mesh.vectorCCx, mesh.vectorCCx * 0.0]) survey.drape_electrodes_on_topography(mesh, actind, option="top") # Use Exponential Map: m = log(rho) actmap = maps.InjectActiveCells(mesh, indActive=actind, valInactive=np.log(1e8)) parametric_block = maps.ParametricBlock(mesh, slopeFact=1e2) mapping = maps.ExpMap(mesh) * parametric_block # Set true model # val_background,val_block, block_x0, block_dx, block_y0, block_dy mtrue = np.r_[np.log(1e3), np.log(10), 100, 10, -20, 10] # Set initial model m0 = np.r_[np.log(rho_background), np.log(rho_block), block_x0, block_dx, block_y0, block_dy, ] rho = mapping * mtrue rho0 = mapping * m0 # Show the true conductivity model fig = plt.figure(figsize=(12, 3)) ax = plt.subplot(111) temp = rho.copy() temp[~actind] = np.nan out = mesh.plotImage( temp, grid=False, ax=ax, gridOpts={"alpha": 0.2}, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ) ax.plot(survey.electrode_locations[:, 0], survey.electrode_locations[:, 1], "k.") ax.set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max()) ax.set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min()) cb = plt.colorbar(out[0]) cb.set_label("Resistivity (ohm-m)") ax.set_aspect("equal") ax.set_title("True resistivity model") plt.show() # Show the true conductivity model fig = plt.figure(figsize=(12, 3)) ax = plt.subplot(111) temp = rho0.copy() temp[~actind] = np.nan out = mesh.plotImage( temp, grid=False, ax=ax, gridOpts={"alpha": 0.2}, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ) ax.plot(survey.electrode_locations[:, 0], survey.electrode_locations[:, 1], "k.") ax.set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max()) ax.set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min()) cb = plt.colorbar(out[0]) cb.set_label("Resistivity (ohm-m)") ax.set_aspect("equal") ax.set_title("Initial resistivity model") plt.show() # Generate 2.5D DC problem # "N" means potential is defined at nodes prb = DC.Simulation2DNodal(mesh, survey=survey, rhoMap=mapping, storeJ=True, solver=Solver) # Make synthetic DC data with 5% Gaussian noise data = prb.make_synthetic_data(mtrue, relative_error=0.05, add_noise=True) # Show apparent resisitivty pseudo-section IO.plotPseudoSection(data=data.dobs / IO.G, data_type="apparent_resistivity") # Show apparent resisitivty histogram fig = plt.figure() out = hist(data.dobs / IO.G, bins=20) plt.show() # Set standard_deviation # floor eps = 10**(-3.2) # percentage relative = 0.05 dmisfit = data_misfit.L2DataMisfit(simulation=prb, data=data) uncert = abs(data.dobs) * relative + eps dmisfit.standard_deviation = uncert # Map for a regularization mesh_1d = discretize.TensorMesh([parametric_block.nP]) # Related to inversion reg = regularization.Simple(mesh_1d, alpha_x=0.0) opt = optimization.InexactGaussNewton(maxIter=10) invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) beta = directives.BetaSchedule(coolingFactor=5, coolingRate=2) betaest = directives.BetaEstimate_ByEig(beta0_ratio=1e0) target = directives.TargetMisfit() updateSensW = directives.UpdateSensitivityWeights() update_Jacobi = directives.UpdatePreconditioner() invProb.beta = 0.0 inv = inversion.BaseInversion(invProb, directiveList=[target]) prb.counter = opt.counter = utils.Counter() opt.LSshorten = 0.5 opt.remember("xc") # Run inversion mopt = inv.run(m0) # Convert obtained inversion model to resistivity # rho = M(m), where M(.) is a mapping rho_est = mapping * mopt rho_true = rho.copy() # show recovered conductivity vmin, vmax = rho.min(), rho.max() fig, ax = plt.subplots(2, 1, figsize=(20, 6)) out1 = mesh.plotImage( rho_true, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ax=ax[0], ) out2 = mesh.plotImage( rho_est, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ax=ax[1], ) out = [out1, out2] for i in range(2): ax[i].plot(survey.electrode_locations[:, 0], survey.electrode_locations[:, 1], "kv") ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max()) ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min()) cb = plt.colorbar(out[i][0], ax=ax[i]) cb.set_label("Resistivity ($\Omega$m)") ax[i].set_xlabel("Northing (m)") ax[i].set_ylabel("Elevation (m)") ax[i].set_aspect("equal") ax[0].set_title("True resistivity model") ax[1].set_title("Recovered resistivity model") plt.tight_layout() plt.show()
def run(plotIt=True, survey_type="dipole-dipole"): np.random.seed(1) # Initiate I/O class for DC IO = DC.IO() # Obtain ABMN locations xmin, xmax = 0.0, 200.0 ymin, ymax = 0.0, 0.0 zmin, zmax = 0, 0 endl = np.array([[xmin, ymin, zmin], [xmax, ymax, zmax]]) # Generate DC survey object survey = gen_DCIPsurvey(endl, survey_type=survey_type, dim=2, a=10, b=10, n=10) survey = IO.from_ambn_locations_to_survey( survey.locations_a, survey.locations_b, survey.locations_m, survey.locations_n, survey_type, data_dc_type="volt", ) # Obtain 2D TensorMesh mesh, actind = IO.set_mesh() topo, mesh1D = genTopography(mesh, -10, 0, its=100) actind = utils.surface2ind_topo(mesh, np.c_[mesh1D.vectorCCx, topo]) survey.drape_electrodes_on_topography(mesh, actind, option="top") # Build a conductivity model blk_inds_c = utils.model_builder.getIndicesSphere(np.r_[60.0, -25.0], 12.5, mesh.gridCC) blk_inds_r = utils.model_builder.getIndicesSphere(np.r_[140.0, -25.0], 12.5, mesh.gridCC) layer_inds = mesh.gridCC[:, 1] > -5.0 sigma = np.ones(mesh.nC) * 1.0 / 100.0 sigma[blk_inds_c] = 1.0 / 10.0 sigma[blk_inds_r] = 1.0 / 1000.0 sigma[~actind] = 1.0 / 1e8 rho = 1.0 / sigma # Show the true conductivity model if plotIt: fig = plt.figure(figsize=(12, 3)) ax = plt.subplot(111) temp = rho.copy() temp[~actind] = np.nan out = mesh.plotImage( temp, grid=True, ax=ax, gridOpts={"alpha": 0.2}, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ) ax.plot(survey.electrode_locations[:, 0], survey.electrode_locations[:, 1], "k.") ax.set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max()) ax.set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min()) cb = plt.colorbar(out[0]) cb.set_label("Resistivity (ohm-m)") ax.set_aspect("equal") plt.show() # Use Exponential Map: m = log(rho) actmap = maps.InjectActiveCells(mesh, indActive=actind, valInactive=np.log(1e8)) mapping = maps.ExpMap(mesh) * actmap # Generate mtrue mtrue = np.log(rho[actind]) # Generate 2.5D DC problem # "N" means potential is defined at nodes prb = DC.Simulation2DNodal(mesh, survey=survey, rhoMap=mapping, storeJ=True, Solver=Solver, verbose=True) geometric_factor = survey.set_geometric_factor( data_type="apparent_resistivity", survey_type="dipole-dipole", space_type="half-space", ) # Make synthetic DC data with 5% Gaussian noise data = prb.make_synthetic_data(mtrue, relative_error=0.05, add_noise=True) IO.data_dc = data.dobs # Show apparent resisitivty pseudo-section if plotIt: IO.plotPseudoSection(data=data.dobs, data_type="apparent_resistivity") # Show apparent resisitivty histogram if plotIt: fig = plt.figure() out = hist(data.dobs, bins=20) plt.xlabel("Apparent Resisitivty ($\Omega$m)") plt.show() # Set initial model based upon histogram m0 = np.ones(actmap.nP) * np.log(100.0) # Set standard_deviation # floor (10 ohm-m) eps = 1.0 # percentage relative = 0.05 dmisfit = data_misfit.L2DataMisfit(simulation=prb, data=data) uncert = abs(data.dobs) * relative + eps dmisfit.standard_deviation = uncert # Map for a regularization regmap = maps.IdentityMap(nP=int(actind.sum())) # Related to inversion reg = regularization.Sparse(mesh, indActive=actind, mapping=regmap) opt = optimization.InexactGaussNewton(maxIter=15) invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) beta = directives.BetaSchedule(coolingFactor=5, coolingRate=2) betaest = directives.BetaEstimate_ByEig(beta0_ratio=1e0) target = directives.TargetMisfit() updateSensW = directives.UpdateSensitivityWeights() update_Jacobi = directives.UpdatePreconditioner() inv = inversion.BaseInversion( invProb, directiveList=[beta, target, updateSensW, betaest, update_Jacobi]) prb.counter = opt.counter = utils.Counter() opt.LSshorten = 0.5 opt.remember("xc") # Run inversion mopt = inv.run(m0) # Get diag(JtJ) mask_inds = np.ones(mesh.nC, dtype=bool) jtj = np.sqrt(updateSensW.JtJdiag[0]) jtj /= jtj.max() temp = np.ones_like(jtj, dtype=bool) temp[jtj > 0.005] = False mask_inds[actind] = temp actind_final = np.logical_and(actind, ~mask_inds) jtj_cc = np.ones(mesh.nC) * np.nan jtj_cc[actind] = jtj # Show the sensitivity if plotIt: fig = plt.figure(figsize=(12, 3)) ax = plt.subplot(111) temp = rho.copy() temp[~actind] = np.nan out = mesh.plotImage( jtj_cc, grid=True, ax=ax, gridOpts={"alpha": 0.2}, clim=(0.005, 0.5), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ) ax.plot(survey.electrode_locations[:, 0], survey.electrode_locations[:, 1], "k.") ax.set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max()) ax.set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min()) cb = plt.colorbar(out[0]) cb.set_label("Sensitivity") ax.set_aspect("equal") plt.show() # Convert obtained inversion model to resistivity # rho = M(m), where M(.) is a mapping rho_est = mapping * mopt rho_est[~actind_final] = np.nan rho_true = rho.copy() rho_true[~actind_final] = np.nan # show recovered conductivity if plotIt: vmin, vmax = rho.min(), rho.max() fig, ax = plt.subplots(2, 1, figsize=(20, 6)) out1 = mesh.plotImage( rho_true, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ax=ax[0], ) out2 = mesh.plotImage( rho_est, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ax=ax[1], ) out = [out1, out2] for i in range(2): ax[i].plot(survey.electrode_locations[:, 0], survey.electrode_locations[:, 1], "kv") ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max()) ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min()) cb = plt.colorbar(out[i][0], ax=ax[i]) cb.set_label("Resistivity ($\Omega$m)") ax[i].set_xlabel("Northing (m)") ax[i].set_ylabel("Elevation (m)") ax[i].set_aspect("equal") plt.tight_layout() plt.show()
def run(plotIt=True, survey_type="dipole-dipole"): np.random.seed(1) # Initiate I/O class for DC IO = DC.IO() # Obtain ABMN locations xmin, xmax = 0.0, 200.0 ymin, ymax = 0.0, 0.0 zmin, zmax = 0, 0 endl = np.array([[xmin, ymin, zmin], [xmax, ymax, zmax]]) # Generate DC survey object survey_dc = gen_DCIPsurvey(endl, survey_type=survey_type, dim=2, a=10, b=10, n=10) survey_dc = IO.from_abmn_locations_to_survey( survey_dc.locations_a, survey_dc.locations_b, survey_dc.locations_m, survey_dc.locations_n, survey_type, data_dc_type="volt", data_ip_type="volt", ) # Obtain 2D TensorMesh mesh, actind = IO.set_mesh() topo, mesh1D = genTopography(mesh, -10, 0, its=100) actind = utils.surface2ind_topo(mesh, np.c_[mesh1D.vectorCCx, topo]) survey_dc.drape_electrodes_on_topography(mesh, actind, option="top") # Build conductivity and chargeability model blk_inds_c = utils.model_builder.getIndicesSphere(np.r_[60.0, -25.0], 12.5, mesh.gridCC) blk_inds_r = utils.model_builder.getIndicesSphere(np.r_[140.0, -25.0], 12.5, mesh.gridCC) blk_inds_charg = utils.model_builder.getIndicesSphere( np.r_[100.0, -25], 12.5, mesh.gridCC) sigma = np.ones(mesh.nC) * 1.0 / 100.0 sigma[blk_inds_c] = 1.0 / 10.0 sigma[blk_inds_r] = 1.0 / 1000.0 sigma[~actind] = 1.0 / 1e8 rho = 1.0 / sigma charg = np.zeros(mesh.nC) charg[blk_inds_charg] = 0.1 # Show the true conductivity model if plotIt: fig, axs = plt.subplots(2, 1, figsize=(12, 6)) temp_rho = rho.copy() temp_rho[~actind] = np.nan temp_charg = charg.copy() temp_charg[~actind] = np.nan out1 = mesh.plotImage( temp_rho, grid=True, ax=axs[0], gridOpts={"alpha": 0.2}, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ) out2 = mesh.plotImage( temp_charg, grid=True, ax=axs[1], gridOpts={"alpha": 0.2}, clim=(0, 0.1), pcolorOpts={"cmap": "magma"}, ) for i in range(2): axs[i].plot( survey_dc.electrode_locations[:, 0], survey_dc.electrode_locations[:, 1], "kv", ) axs[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max()) axs[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min()) axs[i].set_aspect("equal") cb = plt.colorbar(out1[0], ax=axs[0]) cb.set_label("Resistivity (ohm-m)") cb = plt.colorbar(out2[0], ax=axs[1]) cb.set_label("Chargeability") plt.show() # Use Exponential Map: m = log(rho) actmap = maps.InjectActiveCells(mesh, indActive=actind, valInactive=np.log(1e8)) mapping = maps.ExpMap(mesh) * actmap # Generate mtrue_dc for resistivity mtrue_dc = np.log(rho[actind]) # Generate 2.5D DC problem # "N" means potential is defined at nodes prb = DC.Simulation2DNodal(mesh, survey=survey_dc, rhoMap=mapping, storeJ=True, solver=Solver) # Make synthetic DC data with 5% Gaussian noise data_dc = prb.make_synthetic_data(mtrue_dc, relative_error=0.05, add_noise=True) IO.data_dc = data_dc.dobs # Generate mtrue_ip for chargability mtrue_ip = charg[actind] # Generate 2.5D DC problem # "N" means potential is defined at nodes survey_ip = IP.from_dc_to_ip_survey(survey_dc, dim="2.5D") prb_ip = IP.Simulation2DNodal(mesh, survey=survey_ip, etaMap=actmap, storeJ=True, rho=rho, solver=Solver) data_ip = prb_ip.make_synthetic_data(mtrue_ip, relative_error=0.05, add_noise=True) IO.data_ip = data_ip.dobs # Show apparent resisitivty pseudo-section if plotIt: IO.plotPseudoSection(data_type="apparent_resistivity", scale="log", cmap="viridis") plt.show() # Show apparent chargeability pseudo-section if plotIt: IO.plotPseudoSection(data_type="apparent_chargeability", scale="linear", cmap="magma") plt.show() # Show apparent resisitivty histogram if plotIt: fig = plt.figure(figsize=(10, 4)) ax1 = plt.subplot(121) out = hist(np.log10(abs(IO.voltages)), bins=20) ax1.set_xlabel("log10 DC voltage (V)") ax2 = plt.subplot(122) out = hist(IO.apparent_resistivity, bins=20) ax2.set_xlabel("Apparent Resistivity ($\Omega$m)") plt.tight_layout() plt.show() # Set initial model based upon histogram m0_dc = np.ones(actmap.nP) * np.log(100.0) # Set standard deviation # floor data_dc.noise_floor = 10**(-3.2) # percentage data_dc.relative_error = 0.05 mopt_dc, pred_dc = DC.run_inversion(m0_dc, prb, data_dc, actind, mesh, beta0_ratio=1e0, use_sensitivity_weight=True) # Convert obtained inversion model to resistivity # rho = M(m), where M(.) is a mapping rho_est = mapping * mopt_dc rho_est[~actind] = np.nan rho_true = rho.copy() rho_true[~actind] = np.nan # show recovered conductivity if plotIt: vmin, vmax = rho.min(), rho.max() fig, ax = plt.subplots(2, 1, figsize=(20, 6)) out1 = mesh.plotImage( rho_true, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ax=ax[0], ) out2 = mesh.plotImage( rho_est, clim=(10, 1000), pcolorOpts={ "cmap": "viridis", "norm": colors.LogNorm() }, ax=ax[1], ) out = [out1, out2] for i in range(2): ax[i].plot( survey_dc.electrode_locations[:, 0], survey_dc.electrode_locations[:, 1], "kv", ) ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max()) ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min()) cb = plt.colorbar(out[i][0], ax=ax[i]) cb.set_label("Resistivity ($\Omega$m)") ax[i].set_xlabel("Northing (m)") ax[i].set_ylabel("Elevation (m)") ax[i].set_aspect("equal") plt.tight_layout() plt.show() # Show apparent resisitivty histogram if plotIt: fig = plt.figure(figsize=(10, 4)) ax1 = plt.subplot(121) out = hist(np.log10(abs(IO.voltages_ip)), bins=20) ax1.set_xlabel("log10 IP voltage (V)") ax2 = plt.subplot(122) out = hist(IO.apparent_chargeability, bins=20) ax2.set_xlabel("Apparent Chargeability (V/V)") plt.tight_layout() plt.show() # Set initial model based upon histogram m0_ip = np.ones(actmap.nP) * 1e-10 # Set standard deviation # floor data_ip.noise_floor = 10**(-4) # percentage data_ip.relative_error = 0.05 # Clean sensitivity function formed with true resistivity prb_ip._Jmatrix = None # Input obtained resistivity to form sensitivity prb_ip.rho = mapping * mopt_dc mopt_ip, _ = IP.run_inversion( m0_ip, prb_ip, data_ip, actind, mesh, upper=np.Inf, lower=0.0, beta0_ratio=1e0, use_sensitivity_weight=True, ) # Convert obtained inversion model to chargeability # charg = M(m), where M(.) is a mapping for cells below topography charg_est = actmap * mopt_ip charg_est[~actind] = np.nan charg_true = charg.copy() charg_true[~actind] = np.nan # show recovered chargeability if plotIt: fig, ax = plt.subplots(2, 1, figsize=(20, 6)) out1 = mesh.plotImage(charg_true, clim=(0, 0.1), pcolorOpts={"cmap": "magma"}, ax=ax[0]) out2 = mesh.plotImage(charg_est, clim=(0, 0.1), pcolorOpts={"cmap": "magma"}, ax=ax[1]) out = [out1, out2] for i in range(2): ax[i].plot( survey_dc.electrode_locations[:, 0], survey_dc.electrode_locations[:, 1], "rv", ) ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max()) ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min()) cb = plt.colorbar(out[i][0], ax=ax[i]) cb.set_label("Resistivity ($\Omega$m)") ax[i].set_xlabel("Northing (m)") ax[i].set_ylabel("Elevation (m)") ax[i].set_aspect("equal") plt.tight_layout() plt.show()
# mesh csx, ncx, npadx = 25.0, 16, 10 csz, ncz, npadz = 25.0, 8, 10 pf = 1.5 # primary mesh hx = [(csx, ncx), (csx, npadx, pf)] hz = [(csz, npadz, -pf), (csz, ncz), (csz, npadz, pf)] meshp = discretize.CylMesh([hx, 1.0, hz], x0="0CC") # secondary mesh h = [(csz, npadz - 4, -pf), (csz, ncz), (csz, npadz - 4, pf)] meshs = discretize.TensorMesh(3 * [h], x0="CCC") # mappings primaryMapping = (maps.ExpMap(meshp) * maps.SurjectFull(meshp) * maps.Projection(nP=8, index=[0])) mapping = ( maps.ExpMap(meshs) * maps.ParametricBlockInLayer(meshs) * maps.Projection(nP=8, index=np.hstack([np.r_[0], np.arange(0, 8)]))) primaryMap2Meshs = (maps.ExpMap(meshs) * maps.SurjectFull(meshs) * maps.Projection(nP=8, index=[0])) class PrimSecFDEMTest(object): # --------------------- Run some tests! --------------------- # def DataTest(self): print("\nTesting Data")
# Mappings are used to take the inversion model and represent it as electrical # conductivity on the inversion mesh. We will invert for log-conductivity below # the surface, fixing the conductivity of the air cells to 1e-8 S/m # create a 2D mesh that includes air cells mesh2D = discretize.TensorMesh([mesh.hx, mesh.hz], x0=mesh.x0[[0, 2]]) active_inds = mesh2D.gridCC[:, 1] < 0 # active indices are below the surface mapping = ( maps.Surject2Dto3D(mesh) * maps.InjectActiveCells( # populates 3D space from a 2D model mesh2D, active_inds, sigma_air ) * maps.ExpMap( # adds air cells nP=inversion_mesh.nC ) # takes the exponential (log(sigma) --> sigma) ) ############################################################################### # True Model # ---------- # # Create our true model which we will use to generate synthetic data for m_true = np.log(sigma_deep) * np.ones(inversion_mesh.nC) interface_depth = interface(inversion_mesh.gridCC[:, 0]) m_true[inversion_mesh.gridCC[:, 1] > interface_depth] = np.log(sigma_surface) fig, ax = plt.subplots(1, 1) cb = plt.colorbar(inversion_mesh.plotImage(m_true, ax=ax, grid=True)[0], ax=ax)
# well as the mapping from the model space to the active cells. Starting and # reference models can be a constant background value or contain a-priori # structures. Here, the starting model is the natural log of 0.01 S/m. # # # Define conductivity model in S/m (or resistivity model in Ohm m) air_conductivity = np.log(1e-8) background_conductivity = np.log(1e-2) # Define the mapping from active cells to the entire domain active_map = maps.InjectActiveCells(mesh, ind_active, np.exp(air_conductivity)) nC = int(ind_active.sum()) # Define the mapping from the model to the conductivity of the entire domain conductivity_map = active_map * maps.ExpMap() # Define starting model starting_conductivity_model = background_conductivity * np.ones(nC) ############################################################### # Define the Physics of the DC Simulation # --------------------------------------- # # Here, we define the physics of the DC resistivity simulation. # # dc_simulation = dc.simulation.Simulation3DNodal(mesh, survey=dc_survey, sigmaMap=conductivity_map,
def halfSpaceProblemAnaDiff( meshType, srctype="MagDipole", sig_half=1e-2, rxOffset=50.0, bounds=None, plotIt=False, rxType="MagneticFluxDensityz", ): if bounds is None: bounds = [1e-5, 1e-3] if meshType == "CYL": cs, ncx, ncz, npad = 15.0, 30, 10, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = discretize.CylMesh([hx, 1, hz], "00C") elif meshType == "TENSOR": cs, nc, npad = 20.0, 13, 5 hx = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] mesh = discretize.TensorMesh([hx, hy, hz], "CCC") active = mesh.vectorCCz < 0.0 actMap = maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * actMap prb = tdem.Simulation3DMagneticFluxDensity(mesh, sigmaMap=mapping) prb.Solver = Solver prb.timeSteps = [(1e-3, 5), (1e-4, 5), (5e-5, 10), (5e-5, 10), (1e-4, 10)] out = utils.VTEMFun(prb.times, 0.00595, 0.006, 100) wavefun = interp1d(prb.times, out) t0 = 0.006 waveform = tdem.Src.RawWaveform(offTime=t0, waveFct=wavefun) rx = getattr(tdem.Rx, "Point{}".format(rxType[:-1]))(np.array([[rxOffset, 0.0, 0.0]]), np.logspace(-4, -3, 31) + t0, rxType[-1]) if srctype == "MagDipole": src = tdem.Src.MagDipole([rx], waveform=waveform, loc=np.array([0, 0.0, 0.0])) elif srctype == "CircularLoop": src = tdem.Src.CircularLoop([rx], waveform=waveform, loc=np.array([0.0, 0.0, 0.0]), radius=13.0) survey = tdem.Survey([src]) prb.pair(survey) sigma = np.ones(mesh.nCz) * 1e-8 sigma[active] = sig_half sigma = np.log(sigma[active]) if srctype == "MagDipole": bz_ana = mu_0 * analytics.hzAnalyticDipoleT(rx.locations[0][0] + 1e-3, rx.times - t0, sig_half) elif srctype == "CircularLoop": bz_ana = mu_0 * analytics.hzAnalyticCentLoopT(13, rx.times - t0, sig_half) bz_calc = prb.dpred(sigma) ind = np.logical_and(rx.times - t0 > bounds[0], rx.times - t0 < bounds[1]) log10diff = np.linalg.norm( np.log10(np.abs(bz_calc[ind])) - np.log10(np.abs(bz_ana[ind]))) / np.linalg.norm( np.log10(np.abs(bz_ana[ind]))) print(" |bz_ana| = {ana} |bz_num| = {num} |bz_ana-bz_num| = {diff}".format( ana=np.linalg.norm(bz_ana), num=np.linalg.norm(bz_calc), diff=np.linalg.norm(bz_ana - bz_calc), )) print("Difference: {}".format(log10diff)) if plotIt is True: plt.loglog( rx.times[bz_calc > 0] - t0, bz_calc[bz_calc > 0], "r", rx.times[bz_calc < 0] - t0, -bz_calc[bz_calc < 0], "r--", ) plt.loglog(rx.times - t0, abs(bz_ana), "b*") plt.title("sig_half = {:e}".format(sig_half)) plt.show() return log10diff