def test_nC_residual(self): # x-direction cs, ncx, ncz, npad = 1.0, 10.0, 10.0, 20 hx = [(cs, ncx), (cs, npad, 1.3)] # z direction 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 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 regMesh = discretize.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = regularization.Simple(regMesh) self.assertTrue(reg._nC_residual == regMesh.nC) self.assertTrue( all([fct._nC_residual == regMesh.nC for fct in reg.objfcts]))
def plot(self, ax=None): if ax is None: fig, ax = plt.subplots(1, 2, figsize=(12, 4)) # generate a 2D mesh for plotting slices mesh2D = discretize.CylMesh( [self.mesh.hx, 1., self.mesh.hz], x0=self.mesh.x0 ) # plot Sigma sigmaplt = self.sigma.reshape(self.mesh.vnC, order='F') ax[0].set_title('$\sigma$') plt.colorbar( mesh2D.plotImage( discretize.utils.mkvc(sigmaplt[:, 0, :]), ax=ax[0], mirror=True, pcolorOpts={'norm': LogNorm()} )[0], ax=ax[0], ) # Plot mu murplt = self.mur.reshape(self.mesh.vnC, order='F') ax[1].set_title('$\mu_r$') plt.colorbar(mesh2D.plotImage( discretize.utils.mkvc(murplt[:, 0, :]), ax=ax[1], mirror=True)[0], ax=ax[1] ) plt.tight_layout() return ax
def test_getInterpMatCartMesh_Faces(self): Mr = discretize.TensorMesh([100, 100, 2], x0="CC0") Mc = discretize.CylMesh( [np.ones(10) / 5, 1, 10], x0="0C0", cartesianOrigin=[-0.2, -0.2, 0] ) Pf = Mc.getInterpolationMatCartMesh(Mr, "F") mf = np.ones(Mc.nF) frect = Pf * mf fxcc = Mr.aveFx2CC * Mr.r(frect, "F", "Fx") fycc = Mr.aveFy2CC * Mr.r(frect, "F", "Fy") fzcc = Mr.r(frect, "F", "Fz") indX = utils.closestPoints(Mr, [0.45, -0.2, 0.5]) indY = utils.closestPoints(Mr, [-0.2, 0.45, 0.5]) TOL = 1e-2 assert np.abs(float(fxcc[indX]) - 1) < TOL assert np.abs(float(fxcc[indY]) - 0) < TOL assert np.abs(float(fycc[indX]) - 0) < TOL assert np.abs(float(fycc[indY]) - 1) < TOL assert np.abs((fzcc - 1).sum()) < TOL mag = (fxcc ** 2 + fycc ** 2) ** 0.5 dist = ((Mr.gridCC[:, 0] + 0.2) ** 2 + (Mr.gridCC[:, 1] + 0.2) ** 2) ** 0.5 assert np.abs(mag[dist > 0.1].max() - 1) < TOL assert np.abs(mag[dist > 0.1].min() - 1) < TOL
def setUp(self): maps2test2D = [M for M in dir(maps) if M not in MAPS_TO_EXCLUDE_2D] maps2test3D = [M for M in dir(maps) if M not in MAPS_TO_EXCLUDE_3D] self.maps2test2D = [ getattr(maps, M) for M in maps2test2D if (inspect.isclass(getattr(maps, M)) and issubclass(getattr(maps, M), maps.IdentityMap)) ] self.maps2test3D = [ getattr(maps, M) for M in maps2test3D if inspect.isclass(getattr(maps, M)) and issubclass(getattr(maps, M), maps.IdentityMap) ] a = np.array([1, 1, 1]) b = np.array([1, 2]) self.mesh2 = discretize.TensorMesh([a, b], x0=np.array([3, 5])) self.mesh3 = discretize.TensorMesh([a, b, [3, 4]], x0=np.array([3, 5, 2])) self.mesh22 = discretize.TensorMesh([b, a], x0=np.array([3, 5])) self.meshCyl = discretize.CylMesh([10.0, 1.0, 10.0], x0="00C")
def test_getInterpMatCartMesh_Edges2Faces(self): Mr = discretize.TensorMesh([100, 100, 2], x0="CC0") Mc = discretize.CylMesh( [np.ones(10) / 5, 1, 10], x0="0C0", cartesianOrigin=[-0.2, -0.2, 0] ) Pe2f = Mc.getInterpolationMatCartMesh(Mr, "E", locTypeTo="F") me = np.ones(Mc.nE) frect = Pe2f * me excc = Mr.aveFx2CC * Mr.r(frect, "F", "Fx") eycc = Mr.aveFy2CC * Mr.r(frect, "F", "Fy") ezcc = Mr.r(frect, "F", "Fz") indX = utils.closestPoints(Mr, [0.45, -0.2, 0.5]) indY = utils.closestPoints(Mr, [-0.2, 0.45, 0.5]) TOL = 1e-2 assert np.abs(float(excc[indX]) - 0) < TOL assert np.abs(float(excc[indY]) + 1) < TOL assert np.abs(float(eycc[indX]) - 1) < TOL assert np.abs(float(eycc[indY]) - 0) < TOL assert np.abs(ezcc.sum()) < TOL mag = (excc ** 2 + eycc ** 2) ** 0.5 dist = ((Mr.gridCC[:, 0] + 0.2) ** 2 + (Mr.gridCC[:, 1] + 0.2) ** 2) ** 0.5 assert np.abs(mag[dist > 0.1].max() - 1) < TOL assert np.abs(mag[dist > 0.1].min() - 1) < TOL
def test_simpleInter(self): M = discretize.CylMesh([4, 1, 1]) locs = np.r_[0, 0, 0.5] fx = np.array([[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]) self.assertTrue(np.all(fx == M.getInterpolationMat(locs, "Fx").todense())) fz = np.array([[0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0]]) self.assertTrue(np.all(fz == M.getInterpolationMat(locs, "Fz").todense()))
def setUp(self): n = 2 self.mesh = discretize.CylMesh([n, 1, n]) self.face_vec = np.random.rand(self.mesh.nF) self.edge_vec = np.random.rand(self.mesh.nE) # make up a smooth function self.x0 = 2 * self.mesh.gridCC[:, 0]**2 + self.mesh.gridCC[:, 2]**4
def test_errors(self): h1 = np.random.rand(16) h1 /= h1.sum() h2 = np.random.rand(16) h2 /= h2.sum() mesh1D = discretize.TensorMesh([h1]) mesh2D = discretize.TensorMesh([h1, h1]) mesh3D = discretize.TensorMesh([h1, h1, h1]) hr = np.r_[1, 1, 0.5] hz = np.r_[2, 1] meshCyl = discretize.CylMesh([hr, 1, hz], np.r_[0.0, 0.0, 0.0]) mesh2 = discretize.TreeMesh([h2, h2]) mesh2.insert_cells([0.75, 0.75], [4]) with self.assertRaises(TypeError): # Gives a wrong typed object to the function volume_average(mesh1D, h1) with self.assertRaises(NotImplementedError): # Gives a wrong typed mesh volume_average(meshCyl, mesh2) with self.assertRaises(ValueError): # Gives mismatching mesh dimensions volume_average(mesh2D, mesh3D) model1 = np.random.randn(mesh2D.nC) bad_model1 = np.random.randn(3) bad_model2 = np.random.rand(1) # gives input values with incorrect lengths with self.assertRaises(ValueError): volume_average(mesh2D, mesh2, bad_model1) with self.assertRaises(ValueError): volume_average(mesh2D, mesh2, model1, bad_model2)
def test_getInterpMatCartMesh_Faces2Edges(self): Mr = discretize.TensorMesh([100, 100, 2], x0="CC0") Mc = discretize.CylMesh( [np.ones(10) / 5, 1, 10], x0="0C0", cartesianOrigin=[-0.2, -0.2, 0] ) self.assertTrue((Mc.cartesianOrigin == [-0.2, -0.2, 0]).all()) Pf2e = Mc.getInterpolationMatCartMesh(Mr, "F", locTypeTo="E") mf = np.ones(Mc.nF) ecart = Pf2e * mf excc = Mr.aveEx2CC * Mr.r(ecart, "E", "Ex") eycc = Mr.aveEy2CC * Mr.r(ecart, "E", "Ey") ezcc = Mr.r(ecart, "E", "Ez") indX = utils.closestPoints(Mr, [0.45, -0.2, 0.5]) indY = utils.closestPoints(Mr, [-0.2, 0.45, 0.5]) TOL = 1e-2 assert np.abs(float(excc[indX]) - 1) < TOL assert np.abs(float(excc[indY]) - 0) < TOL assert np.abs(float(eycc[indX]) - 0) < TOL assert np.abs(float(eycc[indY]) - 1) < TOL assert np.abs((ezcc - 1).sum()) < TOL mag = (excc ** 2 + eycc ** 2) ** 0.5 dist = ((Mr.gridCC[:, 0] + 0.2) ** 2 + (Mr.gridCC[:, 1] + 0.2) ** 2) ** 0.5 assert np.abs(mag[dist > 0.1].max() - 1) < TOL assert np.abs(mag[dist > 0.1].min() - 1) < TOL
def test_cartesianGrid(self): mesh = discretize.CylMesh([1, 4, 1]) root2over2 = np.sqrt(2.0) / 2.0 # cell centers cartCC = mesh.cartesianGrid("CC") self.assertTrue( np.allclose(cartCC[:, 0], 0.5 * root2over2 * np.r_[1.0, -1.0, -1.0, 1.0])) self.assertTrue( np.allclose(cartCC[:, 1], 0.5 * root2over2 * np.r_[1.0, 1.0, -1.0, -1.0])) self.assertTrue(np.allclose(cartCC[:, 2], 0.5 * np.ones(4))) # nodes cartN = mesh.cartesianGrid("N") self.assertTrue( np.allclose(cartN[:, 0], np.hstack(2 * [0.0, 1.0, 0.0, -1.0, 0.0]))) self.assertTrue( np.allclose(cartN[:, 1], np.hstack(2 * [0.0, 0.0, 1.0, 0.0, -1.0]))) self.assertTrue( np.allclose(cartN[:, 2], np.hstack(5 * [0.0] + 5 * [1.0])))
def setUp(self): n = 10 hx = np.random.rand(n) hy = np.random.rand(n) hy = hy * 2 * np.pi / hy.sum() hz = np.random.rand(n) self.mesh = discretize.CylMesh([hx, hy, hz])
def setUp(self): hx = utils.meshTensor([(1, 1)]) htheta = utils.meshTensor([(1.0, 4)]) htheta = htheta * 2 * np.pi / htheta.sum() hz = hx self.mesh = discretize.CylMesh([hx, htheta, hz])
def test_getInterpMatCartMesh_Edges(self): Mr = discretize.TensorMesh([100, 100, 2], x0='CC0') Mc = discretize.CylMesh([np.ones(10) / 5, 1, 10], x0='0C0', cartesianOrigin=[-0.2, -0.2, 0]) Pe = Mc.getInterpolationMatCartMesh(Mr, 'E') me = np.ones(Mc.nE) ecart = Pe * me excc = Mr.aveEx2CC * Mr.r(ecart, 'E', 'Ex') eycc = Mr.aveEy2CC * Mr.r(ecart, 'E', 'Ey') ezcc = Mr.aveEz2CC * Mr.r(ecart, 'E', 'Ez') indX = utils.closestPoints(Mr, [0.45, -0.2, 0.5]) indY = utils.closestPoints(Mr, [-0.2, 0.45, 0.5]) TOL = 1e-2 assert np.abs(float(excc[indX]) - 0) < TOL assert np.abs(float(excc[indY]) + 1) < TOL assert np.abs(float(eycc[indX]) - 1) < TOL assert np.abs(float(eycc[indY]) - 0) < TOL assert np.abs(ezcc.sum()) < TOL mag = (excc**2 + eycc**2)**0.5 dist = ((Mr.gridCC[:, 0] + 0.2)**2 + (Mr.gridCC[:, 1] + 0.2)**2)**0.5 assert np.abs(mag[dist > 0.1].max() - 1) < TOL assert np.abs(mag[dist > 0.1].min() - 1) < TOL
def plot_slice(mesh, v, ax=None, clim=None, pcolorOpts=None, theta_ind=0, cb_extend=None, show_cb=True): """ Plot a cell centered property :param numpy.array prop: cell centered property to plot :param matplotlib.axes ax: axis :param numpy.array clim: colorbar limits :param dict pcolorOpts: dictionary of pcolor options """ if ax is None: fig, ax = plt.subplots(1, 1, figsize=(6, 4)) if pcolorOpts is None: pcolorOpts = {} # generate a 2D mesh for plotting slices mesh2D = discretize.CylMesh([mesh.hx, 1., mesh.hz], x0=mesh.x0) vplt = v.reshape(mesh.vnC, order='F') plotme = discretize.utils.mkvc(vplt[:, theta_ind, :]) if not mesh.isSymmetric: theta_ind_mirror = (theta_ind + int(mesh.vnC[1] / 2) if theta_ind < int(mesh.vnC[1] / 2) else theta_ind - int(mesh.vnC[1] / 2)) mirror_data = discretize.utils.mkvc(vplt[:, theta_ind_mirror, :]) else: mirror_data = plotme out = mesh2D.plotImage(plotme, ax=ax, mirror=True, mirror_data=mirror_data, pcolorOpts=pcolorOpts, clim=clim) out += (ax, ) if show_cb: cb = plt.colorbar( out[0], ax=ax, extend=cb_extend if cb_extend is not None else "neither") out += (cb, ) if clim is not None: cb.set_clim(clim) cb.update_ticks() return out
def setupMeshModel(): cs = 10.0 nc = 20.0 npad = 15.0 hx = [(cs, nc), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] mesh = discretize.CylMesh([hx, 1.0, hz], "0CC") muMod = 1 + MuMax * np.random.randn(mesh.nC) sigmaMod = np.random.randn(mesh.nC) return mesh, muMod, sigmaMod
def plotLinesFx(mesh, field, pltType='semilogy', ax=None, theta_ind=0, xlim=[0., 2500.], zloc=0., real_or_imag='real', color_ind=0, color=None, label=None, linestyle='-', alpha=None): mesh2D = discretize.CylMesh([mesh.hx, 1., mesh.hz], x0=mesh.x0) if ax is None: fig, ax = plt.subplots(1, 1, figsize=(8, 6)) fplt = face3DthetaSlice(mesh, field, theta_ind=theta_ind) fx = discretize.utils.mkvc(fplt[:mesh2D.vnF[0]].reshape( [mesh2D.vnFx[0], mesh2D.vnFx[2]], order='F')) xind = ((mesh2D.gridFx[:, 0] > xlim[0]) & (mesh2D.gridFx[:, 0] < xlim[1])) zind = ((mesh2D.gridFx[:, 2] > -mesh2D.hz.min() + zloc) & (mesh2D.gridFx[:, 2] < zloc)) pltind = xind & zind fx = getattr(fx[pltind], real_or_imag) x = mesh2D.gridFx[pltind, 0] if pltType in ['semilogy', 'loglog']: getattr(ax, pltType)( x, -fx, '--', color=color if color is not None else 'C{}'.format(color_ind)) getattr(ax, pltType)( x, fx.real, linestyle, color=color if color is not None else 'C{}'.format(color_ind), label=label, alpha=alpha) ax.grid('both', linestyle=linestyle, linewidth=0.4, color=[0.8, 0.8, 0.8]) ax.set_xlabel('distance from well (m)') plt.tight_layout() return ax
def test_areas(self): mesh = discretize.CylMesh([1, 2, 1]) areas = np.hstack([[np.pi]*2, [1]*2, [np.pi/2]*4]) self.assertTrue(np.all(mesh.area == areas)) edges = np.hstack([[1]*4, [np.pi]*4, [1]*3]) self.assertTrue(np.all(mesh.edge == edges)) mesh = discretize.CylMesh([2, 5, 3]) hangingF = np.hstack([ getattr(mesh, '_ishangingF{}'.format(dim)) for dim in ['x', 'y', 'z'] ]) self.assertTrue(np.all(mesh._areaFull[~hangingF] == mesh.area)) hangingE = np.hstack([ getattr(mesh, '_ishangingE{}'.format(dim)) for dim in ['x', 'y', 'z'] ]) self.assertTrue(np.all(mesh._edgeFull[~hangingE] == mesh.edge))
def test_areas(self): mesh = discretize.CylMesh([1, 2, 1]) areas = np.hstack([[np.pi] * 2, [1] * 2, [np.pi / 2] * 4]) self.assertTrue(np.all(mesh.area == areas)) edges = np.hstack([[1] * 4, [np.pi] * 4, [1] * 3]) self.assertTrue(np.all(mesh.edge == edges)) mesh = discretize.CylMesh([2, 5, 3]) hangingF = np.hstack([ getattr(mesh, "_ishanging_faces_{}".format(dim)) for dim in ["x", "y", "z"] ]) self.assertTrue(np.all(mesh._face_areas_full[~hangingF] == mesh.area)) hangingE = np.hstack([ getattr(mesh, "_ishanging_edges_{}".format(dim)) for dim in ["x", "y", "z"] ]) self.assertTrue( np.all(mesh._edge_lengths_full[~hangingE] == mesh.edge))
def test_indActive_nc_residual(self): # x-direction cs, ncx, ncz, npad = 1.0, 10.0, 10.0, 20 hx = [(cs, ncx), (cs, npad, 1.3)] # z direction 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 reg = regularization.Simple(mesh, indActive=active) self.assertTrue(reg._nC_residual == len(active.nonzero()[0]))
def run(plotIt=True): sig_halfspace = 1e-6 sig_sphere = 1e0 sig_air = 1e-8 sphere_z = -50. sphere_radius = 30. # x-direction cs = 1 nc = np.ceil(2.5*(- (sphere_z-sphere_radius))/cs) # define a mesh mesh = discretize.CylMesh([[(cs, nc)], 1, [(cs, nc)]], x0='00C') # Put the model on the mesh sigma = sig_air*np.ones(mesh.nC) # start with air cells sigma[mesh.gridCC[:, 2] < 0.] = sig_halfspace # cells below the earth # indices of the sphere sphere_ind = ( (mesh.gridCC[:, 0]**2 + (mesh.gridCC[:, 2] - sphere_z)**2) <= sphere_radius**2 ) sigma[sphere_ind] = sig_sphere # sphere if plotIt is False: return # Plot a cross section through the mesh fig, ax = plt.subplots(2, 1) # Set a nice colormap! plt.set_cmap(plt.get_cmap('viridis')) plt.colorbar(mesh.plotImage(np.log10(sigma), ax=ax[0])[0], ax=ax[0]) ax[0].set_title('mirror = False') ax[0].axis('equal') ax[0].set_xlim([-200., 200.]) plt.colorbar( mesh.plotImage(np.log10(sigma), ax=ax[1], mirror=True)[0], ax=ax[1] ) ax[1].set_title('mirror = True') ax[1].axis('equal') ax[1].set_xlim([-200., 200.]) plt.tight_layout()
def test_getInterpMatCartMesh_Cells2Nodes(self): Mr = discretize.TensorMesh([100, 100, 2], x0="CC0") Mc = discretize.CylMesh( [np.ones(10) / 5, 1, 10], x0="0C0", cartesianOrigin=[-0.2, -0.2, 0] ) mc = np.arange(Mc.nC) xr = np.linspace(0, 0.4, 50) xc = np.linspace(0, 0.4, 50) + 0.2 Pr = Mr.getInterpolationMat( np.c_[xr, np.ones(50) * -0.2, np.ones(50) * 0.5], "N" ) Pc = Mc.getInterpolationMat(np.c_[xc, np.zeros(50), np.ones(50) * 0.5], "CC") Pc2r = Mc.getInterpolationMatCartMesh(Mr, "CC", locTypeTo="N") assert np.abs(Pr * (Pc2r * mc) - Pc * mc).max() < 1e-3
def setUp(self): cs = 10 nc = 20 npad = 10 mesh = discretize.CylMesh([ [(cs, nc), (cs, npad, 1.3)], np.r_[2 * np.pi], [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)], ]) mesh.x0 = np.r_[0.0, 0.0, -mesh.hz[:npad + nc].sum()] # receivers rx_x = np.linspace(10, 200, 20) rx_z = np.r_[-5] rx_locs = utils.ndgrid([rx_x, np.r_[0], rx_z]) rx_list = [ dc.receivers.BaseRx(rx_locs, projField="e", orientation="x") ] # sources src_a = np.r_[0.0, 0.0, -5.0] src_b = np.r_[55.0, 0.0, -5.0] src_list = [ dc.sources.Dipole(rx_list, locationA=src_a, locationB=src_b) ] self.mesh = mesh self.survey = dc.survey.Survey(src_list) self.sigma_map = maps.ExpMap(mesh) * maps.InjectActiveCells( mesh, mesh.gridCC[:, 2] <= 0, np.log(1e-8)) self.prob = dc.simulation.Simulation3DCellCentered( mesh=mesh, survey=self.survey, sigmaMap=self.sigma_map, Solver=Pardiso, bc_type="Dirichlet", )
def setUp(self): target_mur = [1, 50, 100, 200] target_l = 500 target_r = 50 sigma_back = 1e-5 radius_loop = 100 model_names = ["target_{}".format(mur) for mur in target_mur] # Set up a Cyl mesh csx = 5.0 # cell size in the x-direction csz = 5.0 # cell size in the z-direction domainx = 100 # go out 500m from the well # padding parameters npadx, npadz = 15, 15 # number of padding cells pfx = 1.4 # expansion factor for the padding to infinity pfz = 1.4 ncz = int(target_l / csz) mesh = discretize.CylMesh([ [(csx, int(domainx / csx)), (csx, npadx, pfx)], 1, [(csz, npadz, -pfz), (csz, ncz), (csz, npadz, pfz)], ]) mesh.x0 = [0, 0, -mesh.hz[:npadz + ncz].sum()] # Plot the mesh if plotIt: mesh.plotGrid() plt.show() self.radius_loop = radius_loop self.target_mur = target_mur self.target_l = target_l self.target_r = target_r self.sigma_back = sigma_back self.model_names = model_names self.mesh = mesh
# receivers rx_x = np.linspace(-175.0, 175.0, 8) rx_y = rx_x.copy() rx_z = np.r_[175.0] rx_locs = utils.ndgrid(rx_x, rx_y, rx_z) # mesh csx, ncx, npadx = 25.0, 16, 10 csz, ncz, npadz = 25.0, 8, 10 pf = 1.5 # primary mesh hx = [(csx, ncx), (csx, npadx, pf)] hz = [(csz, npadz, -pf), (csz, ncz), (csz, npadz, pf)] meshp = discretize.CylMesh([hx, 1.0, hz], x0="0CC") # secondary mesh h = [(csz, npadz - 4, -pf), (csz, ncz), (csz, npadz - 4, pf)] meshs = discretize.TensorMesh(3 * [h], x0="CCC") # mappings primaryMapping = (maps.ExpMap(meshp) * maps.SurjectFull(meshp) * maps.Projection(nP=8, index=[0])) mapping = ( maps.ExpMap(meshs) * maps.ParametricBlockInLayer(meshs) * maps.Projection(nP=8, index=np.hstack([np.r_[0], np.arange(0, 8)]))) primaryMap2Meshs = (maps.ExpMap(meshs) * maps.SurjectFull(meshs) * maps.Projection(nP=8, index=[0]))
csx = 5. # core cell size in the x-direction csz = 5. # core cell size in the z-direction domainx = 100 # use a uniform cell size out to a radius of 100m # padding parameters npadx, npadz = 15, 15 # number of padding cells pfx = 1.4 # expansion factor for the padding to infinity in the x-direction pfz = 1.4 # expansion factor for the padding to infinity in the z-direction ncz = int(target_l/csz) # number of z cells in the core region # create the cyl mesh mesh = discretize.CylMesh([ [(csx, int(domainx/csx)), (csx, npadx, pfx)], 1, [(csz, npadz, -pfz), (csz, ncz), (csz, npadz, pfz)] ]) # put the origin at the top of the target mesh.x0 = [0, 0, -mesh.hz[:npadz + ncz].sum()] # plot the mesh mesh.plotGrid() ############################################################################### # Assign physical properties on the mesh mur_model = np.ones(mesh.nC)
def test_active_from_xyz(self): # Create 3D topo [xx, yy] = np.meshgrid(np.linspace(-200, 200, 50), np.linspace(-200, 200, 50)) b = 50 A = 50 zz = A * np.exp(-0.5 * ((xx / b)**2.0 + (yy / b)**2.0)) h = [5.0, 5.0, 5.0] # Test 1D Mesh topo1D = zz[25, :].ravel() mesh1D = discretize.TensorMesh([np.ones(10) * 20], x0="C") indtopoCC = active_from_xyz(mesh1D, topo1D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh1D, topo1D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 3) self.assertEqual(indtopoN.sum(), 2) # Test 2D Tensor mesh topo2D = np.c_[xx[25, :].ravel(), zz[25, :].ravel()] mesh_tensor = discretize.TensorMesh([[(h[0], 24)], [(h[1], 20)]], x0="CC") indtopoCC = active_from_xyz(mesh_tensor, topo2D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_tensor, topo2D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 434) self.assertEqual(indtopoN.sum(), 412) # test 2D Curvilinear mesh nodes_x = mesh_tensor.gridN[:, 0].reshape(mesh_tensor.vnN, order="F") nodes_y = mesh_tensor.gridN[:, 1].reshape(mesh_tensor.vnN, order="F") mesh_curvi = discretize.CurvilinearMesh([nodes_x, nodes_y]) indtopoCC = active_from_xyz(mesh_curvi, topo2D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_curvi, topo2D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 434) self.assertEqual(indtopoN.sum(), 412) # Test 2D Tree mesh mesh_tree = mesh_builder_xyz(topo2D, h[:2], mesh_type="TREE") mesh_tree = refine_tree_xyz( mesh_tree, topo2D, method="surface", octree_levels=[1], octree_levels_padding=None, finalize=True, ) indtopoCC = active_from_xyz(mesh_tree, topo2D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_tree, topo2D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 167) self.assertEqual(indtopoN.sum(), 119) # Test 3D Tensor meshes topo3D = np.c_[xx.ravel(), yy.ravel(), zz.ravel()] mesh_tensor = discretize.TensorMesh( [[(h[0], 24)], [(h[1], 20)], [(h[2], 30)]], x0="CCC") indtopoCC = active_from_xyz(mesh_tensor, topo3D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_tensor, topo3D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 10496) self.assertEqual(indtopoN.sum(), 10084) # test 3D Curvilinear mesh nodes_x = mesh_tensor.gridN[:, 0].reshape(mesh_tensor.vnN, order="F") nodes_y = mesh_tensor.gridN[:, 1].reshape(mesh_tensor.vnN, order="F") nodes_z = mesh_tensor.gridN[:, 2].reshape(mesh_tensor.vnN, order="F") mesh_curvi = discretize.CurvilinearMesh([nodes_x, nodes_y, nodes_z]) indtopoCC = active_from_xyz(mesh_curvi, topo3D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_curvi, topo3D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 10496) self.assertEqual(indtopoN.sum(), 10084) # Test 3D Tree mesh mesh_tree = mesh_builder_xyz(topo3D, h, mesh_type="TREE") mesh_tree = refine_tree_xyz( mesh_tree, topo3D, method="surface", octree_levels=[1], octree_levels_padding=None, finalize=True, ) indtopoCC = active_from_xyz(mesh_tree, topo3D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_tree, topo3D, grid_reference="N", method="nearest") self.assertIn(indtopoCC.sum(), [6292, 6299]) self.assertIn(indtopoN.sum(), [4632, 4639]) # Test 3D CYL Mesh ncr = 10 # number of mesh cells in r ncz = 15 # number of mesh cells in z dr = 15 # cell width r dz = 10 # cell width z npad_r = 4 # number of padding cells in r npad_z = 4 # number of padding cells in z exp_r = 1.25 # expansion rate of padding cells in r exp_z = 1.25 # expansion rate of padding cells in z hr = [(dr, ncr), (dr, npad_r, exp_r)] hz = [(dz, npad_z, -exp_z), (dz, ncz), (dz, npad_z, exp_z)] # A value of 1 is used to define the discretization in phi for this case. mesh_cyl = discretize.CylMesh([hr, 1, hz], x0="00C") indtopoCC = active_from_xyz(mesh_cyl, topo3D, grid_reference="CC", method="nearest") indtopoN = active_from_xyz(mesh_cyl, topo3D, grid_reference="N", method="nearest") self.assertEqual(indtopoCC.sum(), 183) self.assertEqual(indtopoN.sum(), 171) htheta = meshTensor([(1.0, 4)]) htheta = htheta * 2 * np.pi / htheta.sum() mesh_cyl2 = discretize.CylMesh([hr, htheta, hz], x0="00C") with self.assertRaises(NotImplementedError): indtopoCC = active_from_xyz(mesh_cyl2, topo3D, grid_reference="CC", method="nearest")
def run(runIt=False, plotIt=True, saveIt=False, saveFig=False, cleanup=True): """ Run the bookpurnong 1D stitched RESOLVE inversions. :param bool runIt: re-run the inversions? Default downloads and plots saved results :param bool plotIt: show the plots? :param bool saveIt: save the re-inverted results? :param bool saveFig: save the figure :param bool cleanup: remove the downloaded results """ # download the data downloads, directory = download_and_unzip_data() # Load resolve data resolve = h5py.File(os.path.sep.join([directory, "booky_resolve.hdf5"]), "r") river_path = resolve["river_path"][()] # River path nSounding = resolve["data"].shape[0] # the # of soundings # Bird height from surface b_height_resolve = resolve["src_elevation"][()] # fetch the frequencies we are considering cpi_inds = [0, 2, 6, 8, 10] # Indices for HCP in-phase cpq_inds = [1, 3, 7, 9, 11] # Indices for HCP quadrature frequency_cp = resolve["frequency_cp"][()] # build a 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 # survey parameters rxOffset = 7.86 # tx-rx separation bp = -mu_0 / (4 * np.pi * rxOffset**3) # primary magnetic field # re-run the inversion if runIt: # set up the mappings - we are inverting for 1D log conductivity # below the earth's surface. actMap = maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * actMap # build starting and reference model sig_half = 1e-1 sig_air = 1e-8 sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half m0 = np.log(1e-1) * np.ones(active.sum()) # starting model mref = np.log(1e-1) * np.ones(active.sum()) # reference model # initalize empty lists for storing inversion results mopt_re = [] # recovered model dpred_re = [] # predicted data dobs_re = [] # observed data # downsample the data for the inversion nskip = 40 # set up a noise model # 10% for the 3 lowest frequencies, 15% for the two highest relative = np.repeat(np.r_[np.ones(3) * 0.1, np.ones(2) * 0.15], 2) floor = abs(20 * bp * 1e-6) # floor of 20ppm # loop over the soundings and invert each for rxind in range(nSounding): # convert data from ppm to magnetic field (A/m^2) dobs = (np.c_[resolve["data"][rxind, :][cpi_inds].astype(float), resolve["data"][ rxind, :][cpq_inds].astype(float), ].flatten() * bp * 1e-6) # perform the inversion src_height = b_height_resolve[rxind].astype(float) mopt, dpred, dobs = resolve_1Dinversions( mesh, dobs, src_height, frequency_cp, m0, mref, mapping, relative=relative, floor=floor, ) # add results to our list mopt_re.append(mopt) dpred_re.append(dpred) dobs_re.append(dobs) # save results mopt_re = np.vstack(mopt_re) dpred_re = np.vstack(dpred_re) dobs_re = np.vstack(dobs_re) if saveIt: np.save("mopt_re_final", mopt_re) np.save("dobs_re_final", dobs_re) np.save("dpred_re_final", dpred_re) mopt_re = resolve["mopt"][()] dobs_re = resolve["dobs"][()] dpred_re = resolve["dpred"][()] sigma = np.exp(mopt_re) indz = -7 # depth index # so that we can visually compare with literature (eg Viezzoli, 2010) cmap = "jet" # dummy figure for colobar fig = plt.figure() out = plt.scatter(np.ones(3), np.ones(3), c=np.linspace(-2, 1, 3), cmap=cmap) plt.close(fig) # plot from the paper fs = 13 # fontsize # matplotlib.rcParams['font.size'] = fs plt.figure(figsize=(13, 7)) ax0 = plt.subplot2grid((2, 3), (0, 0), rowspan=2, colspan=2) ax1 = plt.subplot2grid((2, 3), (0, 2)) ax2 = plt.subplot2grid((2, 3), (1, 2)) # titles of plots title = [ ("(a) Recovered model, %.1f m depth") % (-mesh.vectorCCz[active][indz]), "(b) Obs (Real 400 Hz)", "(c) Pred (Real 400 Hz)", ] temp = sigma[:, indz] tree = cKDTree(list(zip(resolve["xy"][:, 0], resolve["xy"][:, 1]))) d, d_inds = tree.query(list(zip(resolve["xy"][:, 0], resolve["xy"][:, 1])), k=20) w = 1.0 / (d + 100.0)**2.0 w = utils.sdiag(1.0 / np.sum(w, axis=1)) * (w) xy = resolve["xy"] temp = (temp.flatten()[d_inds] * w).sum(axis=1) utils.plot2Ddata( xy, temp, ncontour=100, scale="log", dataloc=False, contourOpts={ "cmap": cmap, "vmin": 1e-2, "vmax": 1e1 }, ax=ax0, ) ax0.plot(resolve["xy"][:, 0], resolve["xy"][:, 1], "k.", alpha=0.02, ms=1) cb = plt.colorbar(out, ax=ax0, ticks=np.linspace(-2, 1, 4), format="$10^{%.1f}$") cb.set_ticklabels(["0.01", "0.1", "1", "10"]) cb.set_label("Conductivity (S/m)") ax0.plot(river_path[:, 0], river_path[:, 1], "k-", lw=0.5) # plot observed and predicted data freq_ind = 0 axs = [ax1, ax2] temp_dobs = dobs_re[:, freq_ind].copy() ax1.plot(river_path[:, 0], river_path[:, 1], "k-", lw=0.5) inf = temp_dobs / abs(bp) * 1e6 print(inf.min(), inf.max()) out = utils.plot2Ddata( resolve["xy"][()], temp_dobs / abs(bp) * 1e6, ncontour=100, scale="log", dataloc=False, ax=ax1, contourOpts={"cmap": "viridis"}, ) vmin, vmax = out[0].get_clim() print(vmin, vmax) cb = plt.colorbar( out[0], ticks=np.logspace(np.log10(vmin), np.log10(vmax), 3), ax=ax1, format="%.1e", fraction=0.046, pad=0.04, ) cb.set_label("Bz (ppm)") temp_dpred = dpred_re[:, freq_ind].copy() # temp_dpred[mask_:_data] = np.nan ax2.plot(river_path[:, 0], river_path[:, 1], "k-", lw=0.5) utils.plot2Ddata( resolve["xy"][()], temp_dpred / abs(bp) * 1e6, ncontour=100, scale="log", dataloc=False, contourOpts={ "vmin": vmin, "vmax": vmax, "cmap": "viridis" }, ax=ax2, ) cb = plt.colorbar( out[0], ticks=np.logspace(np.log10(vmin), np.log10(vmax), 3), ax=ax2, format="%.1e", fraction=0.046, pad=0.04, ) cb.set_label("Bz (ppm)") for i, ax in enumerate([ax0, ax1, ax2]): xticks = [460000, 463000] yticks = [6195000, 6198000, 6201000] xloc, yloc = 462100.0, 6196500.0 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") 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]) plt.tight_layout() if plotIt: plt.show() if saveFig is True: fig.savefig("obspred_resolve.png", dpi=200) resolve.close() if cleanup: os.remove(downloads) shutil.rmtree(directory)
def run(plotIt=True, saveFig=False): # Set up cylindrically symmeric mesh cs, ncx, ncz, npad = 10.0, 15, 25, 13 # padded cyl mesh hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = discretize.CylMesh([hx, 1, hz], "00C") # Conductivity model layerz = np.r_[-200.0, -100.0] layer = (mesh.vectorCCz >= layerz[0]) & (mesh.vectorCCz <= layerz[1]) active = mesh.vectorCCz < 0.0 sig_half = 1e-2 # Half-space conductivity sig_air = 1e-8 # Air conductivity sig_layer = 5e-2 # Layer conductivity sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half sigma[layer] = sig_layer # Mapping actMap = maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * actMap mtrue = np.log(sigma[active]) # ----- FDEM problem & survey ----- # rxlocs = utils.ndgrid([np.r_[50.0], np.r_[0], np.r_[0.0]]) bzr = FDEM.Rx.PointMagneticFluxDensitySecondary(rxlocs, "z", "real") bzi = FDEM.Rx.PointMagneticFluxDensitySecondary(rxlocs, "z", "imag") freqs = np.logspace(2, 3, 5) srcLoc = np.array([0.0, 0.0, 0.0]) print( "min skin depth = ", 500.0 / np.sqrt(freqs.max() * sig_half), "max skin depth = ", 500.0 / np.sqrt(freqs.min() * sig_half), ) print( "max x ", mesh.vectorCCx.max(), "min z ", mesh.vectorCCz.min(), "max z ", mesh.vectorCCz.max(), ) source_list = [ FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation="Z") for freq in freqs ] surveyFD = FDEM.Survey(source_list) prbFD = FDEM.Simulation3DMagneticFluxDensity( mesh, survey=surveyFD, sigmaMap=mapping, solver=Solver ) rel_err = 0.03 dataFD = prbFD.make_synthetic_data(mtrue, relative_error=rel_err, add_noise=True) dataFD.noise_floor = np.linalg.norm(dataFD.dclean) * 1e-5 # FDEM inversion np.random.seed(1) dmisfit = data_misfit.L2DataMisfit(simulation=prbFD, data=dataFD) regMesh = discretize.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = regularization.Simple(regMesh) opt = optimization.InexactGaussNewton(maxIterCG=10) invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) # Inversion Directives beta = directives.BetaSchedule(coolingFactor=4, coolingRate=3) betaest = directives.BetaEstimate_ByEig(beta0_ratio=1.0, seed=518936) target = directives.TargetMisfit() directiveList = [beta, betaest, target] inv = inversion.BaseInversion(invProb, directiveList=directiveList) m0 = np.log(np.ones(mtrue.size) * sig_half) reg.alpha_s = 5e-1 reg.alpha_x = 1.0 prbFD.counter = opt.counter = utils.Counter() opt.remember("xc") moptFD = inv.run(m0) # TDEM problem times = np.logspace(-4, np.log10(2e-3), 10) print( "min diffusion distance ", 1.28 * np.sqrt(times.min() / (sig_half * mu_0)), "max diffusion distance ", 1.28 * np.sqrt(times.max() / (sig_half * mu_0)), ) rx = TDEM.Rx.PointMagneticFluxDensity(rxlocs, times, "z") src = TDEM.Src.MagDipole( [rx], waveform=TDEM.Src.StepOffWaveform(), location=srcLoc, # same src location as FDEM problem ) surveyTD = TDEM.Survey([src]) prbTD = TDEM.Simulation3DMagneticFluxDensity( mesh, survey=surveyTD, sigmaMap=mapping, solver=Solver ) prbTD.time_steps = [(5e-5, 10), (1e-4, 10), (5e-4, 10)] rel_err = 0.03 dataTD = prbTD.make_synthetic_data(mtrue, relative_error=rel_err, add_noise=True) dataTD.noise_floor = np.linalg.norm(dataTD.dclean) * 1e-5 # TDEM inversion dmisfit = data_misfit.L2DataMisfit(simulation=prbTD, data=dataTD) regMesh = discretize.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = regularization.Simple(regMesh) opt = optimization.InexactGaussNewton(maxIterCG=10) invProb = inverse_problem.BaseInvProblem(dmisfit, reg, opt) # directives beta = directives.BetaSchedule(coolingFactor=4, coolingRate=3) betaest = directives.BetaEstimate_ByEig(beta0_ratio=1.0, seed=518936) target = directives.TargetMisfit() directiveList = [beta, betaest, target] inv = inversion.BaseInversion(invProb, directiveList=directiveList) m0 = np.log(np.ones(mtrue.size) * sig_half) reg.alpha_s = 5e-1 reg.alpha_x = 1.0 prbTD.counter = opt.counter = utils.Counter() opt.remember("xc") moptTD = inv.run(m0) # Plot the results if plotIt: plt.figure(figsize=(10, 8)) ax0 = plt.subplot2grid((2, 2), (0, 0), rowspan=2) ax1 = plt.subplot2grid((2, 2), (0, 1)) ax2 = plt.subplot2grid((2, 2), (1, 1)) fs = 13 # fontsize matplotlib.rcParams["font.size"] = fs # Plot the model # z_true = np.repeat(mesh.vectorCCz[active][1:], 2, axis=0) # z_true = np.r_[mesh.vectorCCz[active][0], z_true, mesh.vectorCCz[active][-1]] activeN = mesh.vectorNz <= 0.0 + cs / 2.0 z_true = np.repeat(mesh.vectorNz[activeN][1:-1], 2, axis=0) z_true = np.r_[mesh.vectorNz[activeN][0], z_true, mesh.vectorNz[activeN][-1]] sigma_true = np.repeat(sigma[active], 2, axis=0) ax0.semilogx(sigma_true, z_true, "k-", lw=2, label="True") ax0.semilogx( np.exp(moptFD), mesh.vectorCCz[active], "bo", ms=6, markeredgecolor="k", markeredgewidth=0.5, label="FDEM", ) ax0.semilogx( np.exp(moptTD), mesh.vectorCCz[active], "r*", ms=10, markeredgecolor="k", markeredgewidth=0.5, label="TDEM", ) ax0.set_ylim(-700, 0) ax0.set_xlim(5e-3, 1e-1) ax0.set_xlabel("Conductivity (S/m)", fontsize=fs) ax0.set_ylabel("Depth (m)", fontsize=fs) ax0.grid(which="both", color="k", alpha=0.5, linestyle="-", linewidth=0.2) ax0.legend(fontsize=fs, loc=4) # plot the data misfits - negative b/c we choose positive to be in the # direction of primary ax1.plot(freqs, -dataFD.dobs[::2], "k-", lw=2, label="Obs (real)") ax1.plot(freqs, -dataFD.dobs[1::2], "k--", lw=2, label="Obs (imag)") dpredFD = prbFD.dpred(moptTD) ax1.loglog( freqs, -dpredFD[::2], "bo", ms=6, markeredgecolor="k", markeredgewidth=0.5, label="Pred (real)", ) ax1.loglog( freqs, -dpredFD[1::2], "b+", ms=10, markeredgewidth=2.0, label="Pred (imag)" ) ax2.loglog(times, dataTD.dobs, "k-", lw=2, label="Obs") ax2.loglog( times, prbTD.dpred(moptTD), "r*", ms=10, markeredgecolor="k", markeredgewidth=0.5, label="Pred", ) ax2.set_xlim(times.min() - 1e-5, times.max() + 1e-4) # Labels, gridlines, etc ax2.grid(which="both", alpha=0.5, linestyle="-", linewidth=0.2) ax1.grid(which="both", alpha=0.5, linestyle="-", linewidth=0.2) ax1.set_xlabel("Frequency (Hz)", fontsize=fs) ax1.set_ylabel("Vertical magnetic field (-T)", fontsize=fs) ax2.set_xlabel("Time (s)", fontsize=fs) ax2.set_ylabel("Vertical magnetic field (T)", fontsize=fs) ax2.legend(fontsize=fs, loc=3) ax1.legend(fontsize=fs, loc=3) ax1.set_xlim(freqs.max() + 1e2, freqs.min() - 1e1) ax0.set_title("(a) Recovered Models", fontsize=fs) ax1.set_title("(b) FDEM observed vs. predicted", fontsize=fs) ax2.set_title("(c) TDEM observed vs. predicted", fontsize=fs) plt.tight_layout(pad=1.5) if saveFig is True: plt.savefig("example1.png", dpi=600)
def run(plotIt=True): # ------------------ 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 plotLinesFx(mesh, srcList, fields3D=None, fieldsDC=None, fieldType='e', pltType='semilogy', ax=None, theta_ind=0, xlim=[0., 2500.], zloc=0.): mesh2D = discretize.CylMesh([mesh.hx, 1., mesh.hz], x0=mesh.x0) if ax is None: fig, ax = plt.subplots(1, 2, figsize=(15, 6)) ax = discretize.utils.mkvc(ax) for i, src in enumerate(srcList): if fields3D is not None: field = fields3D[src, fieldType] fplt = utils.face3DthetaSlice(mesh, field, theta_ind=theta_ind) fx = discretize.utils.mkvc(fplt[:mesh2D.vnF[0]].reshape( [mesh2D.vnFx[0], mesh2D.vnFx[2]], order='F')) xind = ((mesh2D.gridFx[:, 0] > xlim[0]) & (mesh2D.gridFx[:, 0] < xlim[1])) zind = ((mesh2D.gridFx[:, 2] > -mesh2D.hz.min()) & (mesh2D.gridFx[:, 2] < 0.)) pltind = xind & zind fx = fx[pltind] x = mesh2D.gridFx[pltind, 0] label = '{} Hz'.format(src.freq) getattr(ax[0], pltType)(x, -fx.real, '--', color='C{}'.format(i)) getattr(ax[1], pltType)(x, -fx.imag, '--', color='C{}'.format(i)) getattr(ax[0], pltType)(x, fx.real, '-', color='C{}'.format(i), label='{} Hz'.format(src.freq)) getattr(ax[1], pltType)(x, fx.imag, '-', color='C{}'.format(i), label='{} Hz'.format(src.freq)) # plot the DC solution fxDC = utils.face3DthetaSlice(mesh, fieldsDC[:, fieldType], theta_ind=theta_ind) fxDC = discretize.utils.mkvc(fxDC[:mesh2D.vnF[0]].reshape( [mesh2D.vnFx[0], mesh2D.vnFx[2]], order='F')) fxDC = fxDC[pltind] getattr(ax[0], pltType)(x, -fxDC, '--', color='k') getattr(ax[0], pltType)(x, fxDC, '-', color='k', label='DC') ax[0].legend() ax[1].legend() ax[0].set_title('${}_r$ real'.format(fieldType)) ax[1].set_title('${}_r$ imag'.format(fieldType)) # [a.set_xlim([2., 1000.]) for a in ax] [ a.grid('both', linestyle='-', linewidth=0.4, color=[0.8, 0.8, 0.8]) for a in ax ] [a.set_xlabel('distance from well (m)') for a in ax] plt.tight_layout() return ax