def setUp_TDEM(prbtype="MagneticFluxDensity", rxcomp="bz", waveform="stepoff"): cs = 5.0 ncx = 8 ncy = 8 ncz = 8 npad = 4 # 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 prb = getattr(tdem, "Simulation3D{}".format(prbtype))(mesh, sigmaMap=mapping) rxtimes = np.logspace(-4, -3, 20) if waveform.upper() == "RAW": 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) prb.timeSteps = [(1e-3, 5), (1e-4, 5), (5e-5, 10), (5e-5, 10), (1e-4, 10)] rxtimes = t0 + rxtimes else: waveform = tdem.Src.StepOffWaveform() prb.timeSteps = [(1e-05, 10), (5e-05, 10), (2.5e-4, 10)] rxOffset = 10.0 rx = getattr(tdem.Rx, "Point{}".format(rxcomp[:-1]))(np.r_[rxOffset, 0.0, -1e-2], rxtimes, rxcomp[-1]) src = tdem.Src.MagDipole([rx], loc=np.array([0.0, 0.0, 0.0]), waveform=waveform) survey = tdem.Survey([src]) prb.Solver = Solver m = np.log(1e-1) * np.ones(prb.sigmaMap.nP) + 1e-2 * np.random.rand( prb.sigmaMap.nP) prb.pair(survey) mesh = mesh return prb, m, mesh
def get_survey(prob, t0): out = utils.VTEMFun(prob.times, 0.00595, 0.006, 100) wavefun = interp1d(prob.times, out) waveform = tdem.Src.RawWaveform(offTime=t0, waveFct=wavefun) src = tdem.Src.MagDipole([], waveform=waveform, loc=np.array([0.0, 0.0, 0.0])) return tdem.Survey([src])
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
) tdem_receivers_list = [ dbzdt_receiver ] # Make a list containing all receivers even if just one tdem_source_list.append( tdem.sources.MagDipole( tdem_receivers_list, location=source_locations[ii], waveform=tdem_waveform, moment=1.0, orientation="z", ) ) tdem_survey = tdem.Survey(tdem_source_list) # Define cylindrical mesh hr = [(10.0, 50), (10.0, 10, 1.5)] hz = [(10.0, 10, -1.5), (10.0, 100), (10.0, 10, 1.5)] mesh = CylMesh([hr, 1, hz], x0="00C") # Define model air_conductivity = 1e-8 background_conductivity = 1e-1 layer_conductivity = 1e-2 pipe_conductivity = 1e1 ind_active = mesh.gridCC[:, 2] < 0 model_map = maps.InjectActiveCells(mesh, ind_active, air_conductivity)
receiver_locations[ii, :], time_channels, "z") receivers_list = [ dbzdt_receiver ] # Make a list containing all receivers even if just one # Must define the transmitter properties and associated receivers source_list.append( tdem.sources.MagDipole( receivers_list, location=source_locations[ii], waveform=waveform, moment=1.0, orientation="z", )) survey = tdem.Survey(source_list) ############################################################### # Create Cylindrical Mesh # ----------------------- # # Here we create the cylindrical mesh that will be used for this tutorial # example. We chose to design a coarser mesh to decrease the run time. # When designing a mesh to solve practical time domain problems: # # - Your smallest cell size should be 10%-20% the size of your smallest diffusion distance # - The thickness of your padding needs to be 2-3 times biggest than your largest diffusion distance # - The diffusion distance is ~1260*np.sqrt(rho*t) # #
src_list_magnetostatic = [src_magnetostatic] src_list_ramp_on = [src_ramp_on] ############################################################################### # Create the simulations # ---------------------- # # To simulate magnetic flux data, we use the b-formulation of Maxwell's # equations prob_magnetostatic = TDEM.Simulation3DMagneticFluxDensity( mesh=mesh, sigmaMap=maps.IdentityMap(mesh), timeSteps=ramp, Solver=Pardiso) prob_ramp_on = TDEM.Simulation3DMagneticFluxDensity( mesh=mesh, sigmaMap=maps.IdentityMap(mesh), timeSteps=ramp, Solver=Pardiso) survey_magnetostatic = TDEM.Survey(srcList=src_list_magnetostatic) survey_ramp_on = TDEM.Survey(src_list_ramp_on) prob_magnetostatic.pair(survey_magnetostatic) prob_ramp_on.pair(survey_ramp_on) ############################################################################### # Run the long on-time simulation # ------------------------------- t = time.time() print("--- Running Long On-Time Simulation ---") prob_ramp_on.mu = mu_model fields = prob_ramp_on.fields(sigma)
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)
def test_permeable_sources(self): target_mur = self.target_mur target_l = self.target_l target_r = self.target_r sigma_back = self.sigma_back model_names = self.model_names mesh = self.mesh radius_loop = self.radius_loop # Assign physical properties on the mesh def populate_target(mur): mu_model = np.ones(mesh.nC) x_inds = mesh.gridCC[:, 0] < target_r z_inds = (mesh.gridCC[:, 2] <= 0) & (mesh.gridCC[:, 2] >= -target_l) mu_model[x_inds & z_inds] = mur return mu_0 * mu_model mu_dict = { key: populate_target(mu) for key, mu in zip(model_names, target_mur) } sigma = np.ones(mesh.nC) * sigma_back # Plot the models if plotIt: xlim = np.r_[-200, 200] # x-limits in meters zlim = np.r_[-1.5 * target_l, 10.0] # z-limits in meters. (z-positive up) fig, ax = plt.subplots(1, len(model_names), figsize=(6 * len(model_names), 5)) if len(model_names) == 1: ax = [ax] for a, key in zip(ax, model_names): plt.colorbar( mesh.plotImage( mu_dict[key], ax=a, pcolorOpts={"norm": LogNorm()}, # plot on a log-scale mirror=True, )[0], ax=a, ) a.set_title("{}".format(key), fontsize=13) # cylMeshGen.mesh.plotGrid(ax=a, slice='theta') # uncomment to plot the mesh on top of this a.set_xlim(xlim) a.set_ylim(zlim) plt.tight_layout() plt.show() ramp = [ (1e-5, 20), (1e-4, 20), (3e-4, 20), (1e-3, 20), (3e-3, 20), (1e-2, 20), (3e-2, 20), (1e-1, 20), (3e-1, 20), (1, 50), ] time_steps = ramp time_mesh = discretize.TensorMesh([ramp]) offTime = 10000 waveform = tdem.Src.QuarterSineRampOnWaveform(ramp_on=np.r_[1e-4, 20], ramp_off=offTime - np.r_[1e-4, 0]) if plotIt: wave = np.r_[[waveform.eval(t) for t in time_mesh.gridN]] plt.plot(time_mesh.gridN, wave) plt.plot(time_mesh.gridN, np.zeros(time_mesh.nN), "-|", color="k") plt.show() src_magnetostatic = tdem.Src.CircularLoop( [], location=np.r_[0.0, 0.0, 0.0], orientation="z", radius=100, ) src_ramp_on = tdem.Src.CircularLoop( [], location=np.r_[0.0, 0.0, 0.0], orientation="z", radius=100, waveform=waveform, ) src_list = [src_magnetostatic] src_list_late_ontime = [src_ramp_on] survey = tdem.Survey(source_list=src_list) survey_late_ontime = tdem.Survey(src_list_late_ontime) prob = tdem.Simulation3DMagneticFluxDensity( mesh=mesh, survey=survey, time_steps=time_steps, sigmaMap=maps.IdentityMap(mesh), solver=Pardiso, ) prob_late_ontime = tdem.Simulation3DMagneticFluxDensity( mesh=mesh, survey=survey_late_ontime, time_steps=time_steps, sigmaMap=maps.IdentityMap(mesh), solver=Pardiso, ) fields_dict = {} for key in model_names: t = time.time() print("--- Running {} ---".format(key)) prob_late_ontime.mu = mu_dict[key] fields_dict[key] = prob_late_ontime.fields(sigma) print(" ... done. Elapsed time {}".format(time.time() - t)) print("\n") b_magnetostatic = {} b_late_ontime = {} for key in model_names: prob.mu = mu_dict[key] prob.sigma = sigma b_magnetostatic[key] = src_magnetostatic.bInitial(prob) prob_late_ontime.mu = mu_dict[key] b_late_ontime[key] = utils.mkvc(fields_dict[key][:, "b", -1]) if plotIt: fig, ax = plt.subplots(len(model_names), 2, figsize=(3 * len(model_names), 5)) for i, key in enumerate(model_names): ax[i][0].semilogy(np.absolute(b_magnetostatic[key]), label="magnetostatic") ax[i][0].semilogy(np.absolute(b_late_ontime[key]), label="late on-time") ax[i][0].legend() ax[i][1].semilogy( np.absolute(b_magnetostatic[key] - b_late_ontime[key])) plt.tight_layout() plt.show() print("Testing TDEM with permeable targets") passed = [] for key in model_names: norm_magneotstatic = np.linalg.norm(b_magnetostatic[key]) norm_late_ontime = np.linalg.norm(b_late_ontime[key]) norm_diff = np.linalg.norm(b_magnetostatic[key] - b_late_ontime[key]) passed_test = (norm_diff / (0.5 * (norm_late_ontime + norm_magneotstatic)) < TOL) print("\n{}".format(key)) print("||magnetostatic||: {:1.2e}, " "||late on-time||: {:1.2e}, " "||difference||: {:1.2e} passed?: {}".format( norm_magneotstatic, norm_late_ontime, norm_diff, passed_test)) passed += [passed_test] assert all(passed) prob.sigma = 1e-4 * np.ones(mesh.nC) v = utils.mkvc(np.random.rand(mesh.nE)) w = utils.mkvc(np.random.rand(mesh.nF)) assert np.all( mesh.getEdgeInnerProduct(1e-4 * np.ones(mesh.nC)) * v == prob.MeSigma * v) assert np.all( mesh.getEdgeInnerProduct(1e-4 * np.ones(mesh.nC), invMat=True) * v == prob.MeSigmaI * v) assert np.all( mesh.getFaceInnerProduct(1.0 / 1e-4 * np.ones(mesh.nC)) * w == prob.MfRho * w) assert np.all( mesh.getFaceInnerProduct(1.0 / 1e-4 * np.ones(mesh.nC), invMat=True) * w == prob.MfRhoI * w) prob.rho = 1.0 / 1e-3 * np.ones(mesh.nC) v = utils.mkvc(np.random.rand(mesh.nE)) w = utils.mkvc(np.random.rand(mesh.nF)) assert np.all( mesh.getEdgeInnerProduct(1e-3 * np.ones(mesh.nC)) * v == prob.MeSigma * v) assert np.all( mesh.getEdgeInnerProduct(1e-3 * np.ones(mesh.nC), invMat=True) * v == prob.MeSigmaI * v) assert np.all( mesh.getFaceInnerProduct(1.0 / 1e-3 * np.ones(mesh.nC)) * w == prob.MfRho * w) assert np.all( mesh.getFaceInnerProduct(1.0 / 1e-3 * np.ones(mesh.nC), invMat=True) * w == prob.MfRhoI * w)
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}$"])
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 get_survey(): src1 = tdem.Src.MagDipole([], location=np.array([0.0, 0.0, 0.0])) src2 = tdem.Src.MagDipole([], location=np.array([0.0, 0.0, 8.0])) return tdem.Survey([src1, src2])
def run_simulation(fname="tdem_vmd.h5", sigma_halfspace=0.01, src_type="VMD"): from SimPEG.electromagnetics import time_domain from scipy.constants import mu_0 import numpy as np from SimPEG import maps from pymatsolver import Pardiso cs = 20.0 ncx, ncy, ncz = 5, 3, 4 npad = 10 npadz = 10 pad_rate = 1.3 hx = [(cs, npad, -pad_rate), (cs, ncx), (cs, npad, pad_rate)] hy = [(cs, npad, -pad_rate), (cs, ncy), (cs, npad, pad_rate)] hz = utils.meshTensor([(cs, npadz, -1.3), (cs / 2.0, ncz), (cs, 5, 2)]) mesh = TensorMesh([hx, hy, hz], x0=["C", "C", -hz[:int(npadz + ncz / 2)].sum()]) sigma = np.ones(mesh.nC) * sigma_halfspace sigma[mesh.gridCC[:, 2] > 0.0] = 1e-8 xmin, xmax = -600.0, 600.0 ymin, ymax = -600.0, 600.0 zmin, zmax = -600, 100.0 times = np.logspace(-5, -2, 21) rxList = time_domain.receivers.PointMagneticFluxTimeDerivative( np.r_[10.0, 0.0, 30.0], times, orientation="z") if src_type == "VMD": src = time_domain.sources.CircularLoop( [rxList], loc=np.r_[0.0, 0.0, 30.0], orientation="Z", waveform=time_domain.sources.StepOffWaveform(), radius=13.0, ) elif src_type == "HMD": src = time_domain.sources.MagDipole( [rxList], loc=np.r_[0.0, 0.0, 30.0], orientation="X", waveform=time_domain.sources.StepOffWaveform(), ) SrcList = [src] survey = time_domain.Survey(SrcList) sig = 1e-2 sigma = np.ones(mesh.nC) * sig sigma[mesh.gridCC[:, 2] > 0] = 1e-8 prb = time_domain.Simulation3DMagneticFluxDensity( mesh, sigmaMap=maps.IdentityMap(mesh), verbose=True, survey=survey, solver=Pardiso, ) prb.time_steps = [ (1e-06, 5), (5e-06, 5), (1e-05, 10), (5e-05, 10), (1e-4, 15), (5e-4, 16), ] f = prb.fields(sigma) xyzlim = np.array([[xmin, xmax], [ymin, ymax], [zmin, zmax]]) actinds, meshCore = utils.ExtractCoreMesh(xyzlim, mesh) Pex = mesh.getInterpolationMat(meshCore.gridCC, locType="Ex") Pey = mesh.getInterpolationMat(meshCore.gridCC, locType="Ey") Pez = mesh.getInterpolationMat(meshCore.gridCC, locType="Ez") Pfx = mesh.getInterpolationMat(meshCore.gridCC, locType="Fx") Pfy = mesh.getInterpolationMat(meshCore.gridCC, locType="Fy") Pfz = mesh.getInterpolationMat(meshCore.gridCC, locType="Fz") sigma_core = sigma[actinds] def getEBJcore(src0): B0 = np.r_[Pfx * f[src0, "b"], Pfy * f[src0, "b"], Pfz * f[src0, "b"]] E0 = np.r_[Pex * f[src0, "e"], Pey * f[src0, "e"], Pez * f[src0, "e"]] J0 = utils.sdiag(np.r_[sigma_core, sigma_core, sigma_core]) * E0 return E0, B0, J0 E, B, J = getEBJcore(src) tdem_is = { "E": E, "B": B, "J": J, "sigma": sigma_core, "mesh": meshCore.serialize(), "time": prb.times, } dd.io.save(fname, tdem_is)
locations=np.array([ [*rec[:3]], ]), ), ] # Set up the source list src_list = [ TDEM.Src.LineCurrent( receiver_list=rec_list, location=np.array([[*src[::2]], [*src[1::2]]]), ), ] # Create `Survey` survey = TDEM.Survey(src_list) # Define the `Simulation` prob = TDEM.Simulation3DElectricField( mesh, survey=survey, rhoMap=maps.IdentityMap(mesh), solver=Solver, time_steps=time_steps, ) ############################################################################### # Compute # """"""" spg_bg = prob.dpred(mres_bg)
def setUpClass(self): # mesh cs = 10 npad = 4 ncore = 5 h = [(cs, npad, -1.5), (cs, ncore), (cs, npad, 1.5)] mesh = discretize.TensorMesh([h, h, h], x0="CCC") # source src_a = np.r_[-cs * 2, 0.0, 0.0] src_b = np.r_[cs * 2, 0.0, 0.0] s_e = np.zeros(mesh.nFx) src_inds = ((mesh.gridFx[:, 0] >= src_a[0]) & (mesh.gridFx[:, 0] <= src_b[0]) & (mesh.gridFx[:, 1] >= src_a[1]) & (mesh.gridFx[:, 1] <= src_b[1]) & (mesh.gridFx[:, 2] >= src_a[2]) & (mesh.gridFx[:, 2] <= src_b[2])) s_e[src_inds] = 1.0 s_e = np.hstack([s_e, np.zeros(mesh.nFy + mesh.nFz)]) # define a model with a conductive, permeable target sigma0 = 1e-1 sigma1 = 1 mu0 = mu_0 mu1 = 100 * mu_0 h_target = np.r_[-30, 30] target_inds = ((mesh.gridCC[:, 0] >= h_target[0]) & (mesh.gridCC[:, 0] <= h_target[1]) & (mesh.gridCC[:, 1] >= h_target[0]) & (mesh.gridCC[:, 1] <= h_target[1]) & (mesh.gridCC[:, 2] >= h_target[0]) & (mesh.gridCC[:, 2] <= h_target[1])) sigma = sigma0 * np.ones(mesh.nC) sigma[target_inds] = sigma1 mu = mu0 * np.ones(mesh.nC) mu[target_inds] = mu1 src = tdem.Src.RawVec_Grounded([], s_e=s_e) timeSteps = [ (1e-6, 20), (1e-5, 30), (3e-5, 30), (1e-4, 40), (3e-4, 30), (1e-3, 20), (1e-2, 17), ] prob = getattr(tdem, "Simulation3D{}".format(self.prob_type))( mesh, timeSteps=timeSteps, mu=mu, sigmaMap=maps.ExpMap(mesh), Solver=Pardiso) survey = tdem.Survey([src]) prob.model = sigma self.mesh = mesh self.prob = prob self.survey = survey self.src = src self.sigma = sigma self.mu = mu print("Testing problem {} \n\n".format(self.prob_type))
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): 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 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