Esempio n. 1
0
    def setUp(self):
        cs = 10.0
        ncx, ncy, ncz = 30.0, 30.0, 30.0
        npad = 10.0
        hx = [(cs, npad, -1.5), (cs, ncx), (cs, npad, 1.5)]
        hy = [(cs, npad, -1.5), (cs, ncy), (cs, npad, 1.5)]
        hz = [(cs, npad, -1.5), (cs, ncz), (cs, npad, 1.5)]
        self.mesh = discretize.TensorMesh([hx, hy, hz], "CCC")
        mapping = maps.ExpMap(self.mesh)

        self.frequency = 1.0

        self.prob_e = fdem.Simulation3DElectricField(self.mesh,
                                                     sigmaMap=mapping)
        self.prob_b = fdem.Simulation3DMagneticFluxDensity(self.mesh,
                                                           sigmaMap=mapping)
        self.prob_h = fdem.Simulation3DMagneticField(self.mesh,
                                                     sigmaMap=mapping)
        self.prob_j = fdem.Simulation3DCurrentDensity(self.mesh,
                                                      sigmaMap=mapping)

        loc = np.r_[0.0, 0.0, 0.0]
        self.location = utils.mkvc(
            self.mesh.gridCC[utils.closestPoints(self.mesh, loc, "CC"), :])
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])
Esempio n. 3
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)
Esempio n. 4
0
def getFDEMProblem(fdemType, comp, SrcList, freq, useMu=False, verbose=False):
    cs = 10.0
    ncx, ncy, ncz = 0, 0, 0
    npad = 8
    hx = [(cs, npad, -1.3), (cs, ncx), (cs, npad, 1.3)]
    hy = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)]
    hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)]
    mesh = TensorMesh([hx, hy, hz], ["C", "C", "C"])

    if useMu is True:
        mapping = [("sigma", maps.ExpMap(mesh)),
                   ("mu", maps.IdentityMap(mesh))]
    else:
        mapping = maps.ExpMap(mesh)

    x = (
        np.array([
            np.linspace(-5.0 * cs, -2.0 * cs, 3),
            np.linspace(5.0 * cs, 2.0 * cs, 3)
        ]) + cs / 4.0
    )  # don't sample right by the source, slightly off alignment from either staggered grid
    XYZ = utils.ndgrid(x, x, np.linspace(-2.0 * cs, 2.0 * cs, 5))
    Rx0 = getattr(fdem.Rx, "Point" + comp[0])
    if comp[-1] == "r":
        real_or_imag = "real"
    elif comp[-1] == "i":
        real_or_imag = "imag"
    rx0 = Rx0(XYZ, comp[1], real_or_imag)

    Src = []

    for SrcType in SrcList:
        if SrcType == "MagDipole":
            Src.append(
                fdem.Src.MagDipole([rx0],
                                   frequency=freq,
                                   location=np.r_[0.0, 0.0, 0.0]))
        elif SrcType == "MagDipole_Bfield":
            Src.append(
                fdem.Src.MagDipole_Bfield([rx0],
                                          frequency=freq,
                                          location=np.r_[0.0, 0.0, 0.0]))
        elif SrcType == "CircularLoop":
            Src.append(
                fdem.Src.CircularLoop([rx0],
                                      frequency=freq,
                                      location=np.r_[0.0, 0.0, 0.0]))
        elif SrcType == "LineCurrent":
            Src.append(
                fdem.Src.LineCurrent(
                    [rx0],
                    frequency=freq,
                    location=np.array([[0.0, 0.0, 0.0], [20.0, 0.0, 0.0]]),
                ))
        elif SrcType == "RawVec":
            if fdemType == "e" or fdemType == "b":
                S_m = np.zeros(mesh.nF)
                S_e = np.zeros(mesh.nE)
                S_m[utils.closestPoints(mesh, [0.0, 0.0, 0.0], "Fz") +
                    np.sum(mesh.vnF[:1])] = 1e-3
                S_e[utils.closestPoints(mesh, [0.0, 0.0, 0.0], "Ez") +
                    np.sum(mesh.vnE[:1])] = 1e-3
                Src.append(
                    fdem.Src.RawVec([rx0], freq, S_m,
                                    mesh.getEdgeInnerProduct() * S_e))

            elif fdemType == "h" or fdemType == "j":
                S_m = np.zeros(mesh.nE)
                S_e = np.zeros(mesh.nF)
                S_m[utils.closestPoints(mesh, [0.0, 0.0, 0.0], "Ez") +
                    np.sum(mesh.vnE[:1])] = 1e-3
                S_e[utils.closestPoints(mesh, [0.0, 0.0, 0.0], "Fz") +
                    np.sum(mesh.vnF[:1])] = 1e-3
                Src.append(
                    fdem.Src.RawVec([rx0], freq,
                                    mesh.getEdgeInnerProduct() * S_m, S_e))

    if verbose:
        print("  Fetching {0!s} problem".format((fdemType)))

    if fdemType == "e":
        survey = fdem.Survey(Src)
        prb = fdem.Simulation3DElectricField(mesh, sigmaMap=mapping)

    elif fdemType == "b":
        survey = fdem.Survey(Src)
        prb = fdem.Simulation3DMagneticFluxDensity(mesh, sigmaMap=mapping)

    elif fdemType == "j":
        survey = fdem.Survey(Src)
        prb = fdem.Simulation3DCurrentDensity(mesh, sigmaMap=mapping)

    elif fdemType == "h":
        survey = fdem.Survey(Src)
        prb = fdem.Simulation3DMagneticField(mesh, sigmaMap=mapping)

    else:
        raise NotImplementedError()
    prb.pair(survey)

    try:
        from pymatsolver import Pardiso

        prb.solver = Pardiso
    except ImportError:
        prb.solver = SolverLU
    # prb.solver_opts = dict(check_accuracy=True)

    return prb