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])
Exemple #3
0
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
Exemple #11
0
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])
Exemple #12
0
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)
Exemple #13
0
        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)
Exemple #14
0
    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)
Exemple #16
0
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