Beispiel #1
0
def run(plotIt=True):

    M = discretize.TensorMesh([100, 100])
    h1 = utils.meshTensor([(6, 7, -1.5), (6, 10), (6, 7, 1.5)])
    h1 = h1 / h1.sum()
    M2 = discretize.TensorMesh([h1, h1])
    V = utils.model_builder.randomModel(M.vnC, seed=79, its=50)
    v = utils.mkvc(V)
    modh = maps.Mesh2Mesh([M, M2])
    modH = maps.Mesh2Mesh([M2, M])
    H = modH * v
    h = modh * H

    if not plotIt:
        return

    ax = plt.subplot(131)
    M.plotImage(v, ax=ax)
    ax.set_title("Fine Mesh (Original)")
    ax = plt.subplot(132)
    M2.plotImage(H, clim=[0, 1], ax=ax)
    ax.set_title("Course Mesh")
    ax = plt.subplot(133)
    M.plotImage(h, clim=[0, 1], ax=ax)
    ax.set_title("Fine Mesh (Interpolated)")
def run(plotIt=True):

    # ------------------ MODEL ------------------
    sigmaair = 1e-8  # air
    sigmaback = 1e-2  # background
    sigmacasing = 1e6  # casing
    sigmainside = sigmaback  # inside the casing

    casing_t = 0.006  # 1cm thickness
    casing_l = 300  # length of the casing

    casing_r = 0.1
    casing_a = casing_r - casing_t / 2.0  # inner radius
    casing_b = casing_r + casing_t / 2.0  # outer radius
    casing_z = np.r_[-casing_l, 0.0]

    # ------------------ SURVEY PARAMETERS ------------------
    freqs = np.r_[1e-6]  # [1e-1, 1, 5] # frequencies
    dsz = -300  # down-hole z source location
    src_loc = np.r_[0.0, 0.0, dsz]
    inf_loc = np.r_[0.0, 0.0, 1e4]

    print("Skin Depth: ", [(500.0 / np.sqrt(sigmaback * _)) for _ in freqs])

    # ------------------ MESH ------------------
    # fine cells near well bore
    csx1, csx2 = 2e-3, 60.0
    pfx1, pfx2 = 1.3, 1.3
    ncx1 = np.ceil(casing_b / csx1 + 2)

    # pad nicely to second cell size
    npadx1 = np.floor(np.log(csx2 / csx1) / np.log(pfx1))
    hx1a = utils.meshTensor([(csx1, ncx1)])
    hx1b = utils.meshTensor([(csx1, npadx1, pfx1)])
    dx1 = sum(hx1a) + sum(hx1b)
    dx1 = np.floor(dx1 / csx2)
    hx1b *= (dx1 * csx2 - sum(hx1a)) / sum(hx1b)

    # second chunk of mesh
    dx2 = 300.0  # uniform mesh out to here
    ncx2 = np.ceil((dx2 - dx1) / csx2)
    npadx2 = 45
    hx2a = utils.meshTensor([(csx2, ncx2)])
    hx2b = utils.meshTensor([(csx2, npadx2, pfx2)])
    hx = np.hstack([hx1a, hx1b, hx2a, hx2b])

    # z-direction
    csz = 0.05
    nza = 10
    # cell size, number of core cells, number of padding cells in the
    # x-direction
    ncz, npadzu, npadzd = np.int(np.ceil(np.diff(casing_z)[0] / csz)) + 10, 68, 68
    # vector of cell widths in the z-direction
    hz = utils.meshTensor([(csz, npadzd, -1.3), (csz, ncz), (csz, npadzu, 1.3)])

    # Mesh
    mesh = discretize.CylMesh(
        [hx, 1.0, hz], [0.0, 0.0, -np.sum(hz[: npadzu + ncz - nza])]
    )

    print(
        "Mesh Extent xmax: {0:f},: zmin: {1:f}, zmax: {2:f}".format(
            mesh.vectorCCx.max(), mesh.vectorCCz.min(), mesh.vectorCCz.max()
        )
    )
    print("Number of cells", mesh.nC)

    if plotIt is True:
        fig, ax = plt.subplots(1, 1, figsize=(6, 4))
        ax.set_title("Simulation Mesh")
        mesh.plotGrid(ax=ax)

    # Put the model on the mesh
    sigWholespace = sigmaback * np.ones((mesh.nC))

    sigBack = sigWholespace.copy()
    sigBack[mesh.gridCC[:, 2] > 0.0] = sigmaair

    sigCasing = sigBack.copy()
    iCasingZ = (mesh.gridCC[:, 2] <= casing_z[1]) & (mesh.gridCC[:, 2] >= casing_z[0])
    iCasingX = (mesh.gridCC[:, 0] >= casing_a) & (mesh.gridCC[:, 0] <= casing_b)
    iCasing = iCasingX & iCasingZ
    sigCasing[iCasing] = sigmacasing

    if plotIt is True:
        # plotting parameters
        xlim = np.r_[0.0, 0.2]
        zlim = np.r_[-350.0, 10.0]
        clim_sig = np.r_[-8, 6]

        # plot models
        fig, ax = plt.subplots(1, 1, figsize=(4, 4))

        im = mesh.plotImage(np.log10(sigCasing), ax=ax)[0]
        im.set_clim(clim_sig)
        plt.colorbar(im, ax=ax)
        ax.grid(which="both")
        ax.set_title("Log_10 (Sigma)")
        ax.set_xlim(xlim)
        ax.set_ylim(zlim)

    # -------------- Sources --------------------
    # Define Custom Current Sources

    # surface source
    sg_x = np.zeros(mesh.vnF[0], dtype=complex)
    sg_y = np.zeros(mesh.vnF[1], dtype=complex)
    sg_z = np.zeros(mesh.vnF[2], dtype=complex)

    nza = 2  # put the wire two cells above the surface

    # vertically directed wire
    # hook it up to casing at the surface
    sgv_indx = (mesh.gridFz[:, 0] > casing_a) & (mesh.gridFz[:, 0] < casing_a + csx1)
    sgv_indz = (mesh.gridFz[:, 2] <= +csz * nza) & (mesh.gridFz[:, 2] >= -csz * 2)
    sgv_ind = sgv_indx & sgv_indz
    sg_z[sgv_ind] = -1.0

    # horizontally directed wire
    sgh_indx = (mesh.gridFx[:, 0] > casing_a) & (mesh.gridFx[:, 0] <= inf_loc[2])
    sgh_indz = (mesh.gridFx[:, 2] > csz * (nza - 0.5)) & (
        mesh.gridFx[:, 2] < csz * (nza + 0.5)
    )
    sgh_ind = sgh_indx & sgh_indz
    sg_x[sgh_ind] = -1.0

    # hook it up to casing at the surface
    sgv2_indx = (mesh.gridFz[:, 0] >= mesh.gridFx[sgh_ind, 0].max()) & (
        mesh.gridFz[:, 0] <= inf_loc[2] * 1.2
    )
    sgv2_indz = (mesh.gridFz[:, 2] <= +csz * nza) & (mesh.gridFz[:, 2] >= -csz * 2)
    sgv2_ind = sgv2_indx & sgv2_indz
    sg_z[sgv2_ind] = 1.0

    # assemble the source
    sg = np.hstack([sg_x, sg_y, sg_z])
    sg_p = [FDEM.Src.RawVec_e([], _, sg / mesh.area) for _ in freqs]

    # downhole source
    dg_x = np.zeros(mesh.vnF[0], dtype=complex)
    dg_y = np.zeros(mesh.vnF[1], dtype=complex)
    dg_z = np.zeros(mesh.vnF[2], dtype=complex)

    # vertically directed wire
    dgv_indx = mesh.gridFz[:, 0] < csx1  # go through the center of the well
    dgv_indz = (mesh.gridFz[:, 2] <= +csz * nza) & (mesh.gridFz[:, 2] > dsz + csz / 2.0)
    dgv_ind = dgv_indx & dgv_indz
    dg_z[dgv_ind] = -1.0

    # couple to the casing downhole
    dgh_indx = mesh.gridFx[:, 0] < casing_a + csx1
    dgh_indz = (mesh.gridFx[:, 2] < dsz + csz) & (mesh.gridFx[:, 2] >= dsz)
    dgh_ind = dgh_indx & dgh_indz
    dg_x[dgh_ind] = 1.0

    # horizontal part at surface
    dgh2_indx = mesh.gridFx[:, 0] <= inf_loc[2] * 1.2
    dgh2_indz = sgh_indz.copy()
    dgh2_ind = dgh2_indx & dgh2_indz
    dg_x[dgh2_ind] = -1.0

    # vertical part at surface
    dgv2_ind = sgv2_ind.copy()
    dg_z[dgv2_ind] = 1.0

    # assemble the source
    dg = np.hstack([dg_x, dg_y, dg_z])
    dg_p = [FDEM.Src.RawVec_e([], _, dg / mesh.area) for _ in freqs]

    # ------------ Problem and Survey ---------------
    survey = FDEM.Survey(sg_p + dg_p)
    problem = FDEM.Simulation3DMagneticField(
        mesh, survey=survey, sigmaMap=maps.IdentityMap(mesh), solver=Solver
    )

    # ------------- Solve ---------------------------
    t0 = time.time()
    fieldsCasing = problem.fields(sigCasing)
    print("Time to solve 2 sources", time.time() - t0)

    # Plot current

    # current density
    jn0 = fieldsCasing[dg_p, "j"]
    jn1 = fieldsCasing[sg_p, "j"]

    # current
    in0 = [mesh.area * fieldsCasing[dg_p, "j"][:, i] for i in range(len(freqs))]
    in1 = [mesh.area * fieldsCasing[sg_p, "j"][:, i] for i in range(len(freqs))]

    in0 = np.vstack(in0).T
    in1 = np.vstack(in1).T

    # integrate to get z-current inside casing
    inds_inx = (mesh.gridFz[:, 0] >= casing_a) & (mesh.gridFz[:, 0] <= casing_b)
    inds_inz = (mesh.gridFz[:, 2] >= dsz) & (mesh.gridFz[:, 2] <= 0)
    inds_fz = inds_inx & inds_inz

    indsx = [False] * mesh.nFx
    inds = list(indsx) + list(inds_fz)

    in0_in = in0[np.r_[inds]]
    in1_in = in1[np.r_[inds]]
    z_in = mesh.gridFz[inds_fz, 2]

    in0_in = in0_in.reshape([in0_in.shape[0] // 3, 3])
    in1_in = in1_in.reshape([in1_in.shape[0] // 3, 3])
    z_in = z_in.reshape([z_in.shape[0] // 3, 3])

    I0 = in0_in.sum(1).real
    I1 = in1_in.sum(1).real
    z_in = z_in[:, 0]

    if plotIt is True:
        fig, ax = plt.subplots(1, 2, figsize=(12, 4))

        ax[0].plot(z_in, np.absolute(I0), z_in, np.absolute(I1))
        ax[0].legend(["top casing", "bottom casing"], loc="best")
        ax[0].set_title("Magnitude of Vertical Current in Casing")

        ax[1].semilogy(z_in, np.absolute(I0), z_in, np.absolute(I1))
        ax[1].legend(["top casing", "bottom casing"], loc="best")
        ax[1].set_title("Magnitude of Vertical Current in Casing")
        ax[1].set_ylim([1e-2, 1.0])
    def test_CylMeshEBDipoles(self, plotIt=plotIt):
        print("Testing CylMesh Electric and Magnetic Dipoles in a wholespace-"
              " Analytic: J-formulation")
        sigmaback = 1.0
        mur = 2.0
        freq = 1.0
        skdpth = 500.0 / np.sqrt(sigmaback * freq)

        csx, ncx, npadx = 5, 50, 25
        csz, ncz, npadz = 5, 50, 25

        hx = utils.meshTensor([(csx, ncx), (csx, npadx, 1.3)])
        hz = utils.meshTensor([(csz, npadz, -1.3), (csz, ncz),
                               (csz, npadz, 1.3)])

        # define the cylindrical mesh
        mesh = discretize.CylMesh([hx, 1, hz], [0.0, 0.0, -hz.sum() / 2])

        if plotIt:
            mesh.plotGrid()

        # make sure mesh is big enough
        self.assertTrue(mesh.hz.sum() > skdpth * 2.0)
        self.assertTrue(mesh.hx.sum() > skdpth * 2.0)

        # set up source
        # test electric dipole
        src_loc = np.r_[0.0, 0.0, 0.0]
        s_ind = utils.closestPoints(mesh, src_loc, "Fz") + mesh.nFx

        de = np.zeros(mesh.nF, dtype=complex)
        de[s_ind] = 1.0 / csz
        de_p = [fdem.Src.RawVec_e([], freq, de / mesh.area)]

        dm_p = [fdem.Src.MagDipole([], freq, src_loc)]

        # Pair the problem and survey
        surveye = fdem.Survey(de_p)
        surveym = fdem.Survey(dm_p)

        prbe = fdem.Simulation3DMagneticField(mesh,
                                              survey=surveye,
                                              sigma=sigmaback,
                                              mu=mur * mu_0)
        prbm = fdem.Simulation3DElectricField(mesh,
                                              survey=surveym,
                                              sigma=sigmaback,
                                              mu=mur * mu_0)

        # solve
        fieldsBackE = prbe.fields()
        fieldsBackM = prbm.fields()

        rlim = [20.0, 500.0]
        # lookAtTx = de_p
        r = mesh.vectorCCx[np.argmin(np.abs(mesh.vectorCCx - rlim[0])):np.
                           argmin(np.abs(mesh.vectorCCx - rlim[1]))]
        z = 100.0

        # where we choose to measure
        XYZ = utils.ndgrid(r, np.r_[0.0], np.r_[z])

        Pf = mesh.getInterpolationMat(XYZ, "CC")
        Zero = sp.csr_matrix(Pf.shape)
        Pfx, Pfz = sp.hstack([Pf, Zero]), sp.hstack([Zero, Pf])

        jn = fieldsBackE[de_p, "j"]
        bn = fieldsBackM[dm_p, "b"]

        SigmaBack = sigmaback * np.ones((mesh.nC))
        Rho = utils.sdiag(1.0 / SigmaBack)
        Rho = sp.block_diag([Rho, Rho])

        en = Rho * mesh.aveF2CCV * jn
        bn = mesh.aveF2CCV * bn

        ex, ez = Pfx * en, Pfz * en
        bx, bz = Pfx * bn, Pfz * bn

        # get analytic solution
        exa, eya, eza = analytics.FDEM.ElectricDipoleWholeSpace(XYZ,
                                                                src_loc,
                                                                sigmaback,
                                                                freq,
                                                                "Z",
                                                                mu_r=mur)

        exa = utils.mkvc(exa, 2)
        eya = utils.mkvc(eya, 2)
        eza = utils.mkvc(eza, 2)

        bxa, bya, bza = analytics.FDEM.MagneticDipoleWholeSpace(XYZ,
                                                                src_loc,
                                                                sigmaback,
                                                                freq,
                                                                "Z",
                                                                mu_r=mur)
        bxa = utils.mkvc(bxa, 2)
        bya = utils.mkvc(bya, 2)
        bza = utils.mkvc(bza, 2)

        print(
            " comp,       anayltic,       numeric,       num - ana,       (num - ana)/ana"
        )
        print(
            "  ex:",
            np.linalg.norm(exa),
            np.linalg.norm(ex),
            np.linalg.norm(exa - ex),
            np.linalg.norm(exa - ex) / np.linalg.norm(exa),
        )
        print(
            "  ez:",
            np.linalg.norm(eza),
            np.linalg.norm(ez),
            np.linalg.norm(eza - ez),
            np.linalg.norm(eza - ez) / np.linalg.norm(eza),
        )

        print(
            "  bx:",
            np.linalg.norm(bxa),
            np.linalg.norm(bx),
            np.linalg.norm(bxa - bx),
            np.linalg.norm(bxa - bx) / np.linalg.norm(bxa),
        )
        print(
            "  bz:",
            np.linalg.norm(bza),
            np.linalg.norm(bz),
            np.linalg.norm(bza - bz),
            np.linalg.norm(bza - bz) / np.linalg.norm(bza),
        )

        if plotIt is True:
            # Edipole
            plt.subplot(221)
            plt.plot(r, ex.real, "o", r, exa.real, linewidth=2)
            plt.grid(which="both")
            plt.title("Ex Real")
            plt.xlabel("r (m)")

            plt.subplot(222)
            plt.plot(r, ex.imag, "o", r, exa.imag, linewidth=2)
            plt.grid(which="both")
            plt.title("Ex Imag")
            plt.legend(["Num", "Ana"], bbox_to_anchor=(1.5, 0.5))
            plt.xlabel("r (m)")

            plt.subplot(223)
            plt.plot(r, ez.real, "o", r, eza.real, linewidth=2)
            plt.grid(which="both")
            plt.title("Ez Real")
            plt.xlabel("r (m)")

            plt.subplot(224)
            plt.plot(r, ez.imag, "o", r, eza.imag, linewidth=2)
            plt.grid(which="both")
            plt.title("Ez Imag")
            plt.xlabel("r (m)")

            plt.tight_layout()

            # Bdipole
            plt.subplot(221)
            plt.plot(r, bx.real, "o", r, bxa.real, linewidth=2)
            plt.grid(which="both")
            plt.title("Bx Real")
            plt.xlabel("r (m)")

            plt.subplot(222)
            plt.plot(r, bx.imag, "o", r, bxa.imag, linewidth=2)
            plt.grid(which="both")
            plt.title("Bx Imag")
            plt.legend(["Num", "Ana"], bbox_to_anchor=(1.5, 0.5))
            plt.xlabel("r (m)")

            plt.subplot(223)
            plt.plot(r, bz.real, "o", r, bza.real, linewidth=2)
            plt.grid(which="both")
            plt.title("Bz Real")
            plt.xlabel("r (m)")

            plt.subplot(224)
            plt.plot(r, bz.imag, "o", r, bza.imag, linewidth=2)
            plt.grid(which="both")
            plt.title("Bz Imag")
            plt.xlabel("r (m)")

            plt.tight_layout()

        self.assertTrue(
            np.linalg.norm(exa - ex) / np.linalg.norm(exa) < tol_EBdipole)
        self.assertTrue(
            np.linalg.norm(eza - ez) / np.linalg.norm(eza) < tol_EBdipole)

        self.assertTrue(
            np.linalg.norm(bxa - bx) / np.linalg.norm(bxa) < tol_EBdipole)
        self.assertTrue(
            np.linalg.norm(bza - bz) / np.linalg.norm(bza) < tol_EBdipole)
Beispiel #4
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)