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)
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)