def test_tripleMultiply(self): M = Mesh.TensorMesh([2, 4], '0C') expMap = Maps.ExpMap(M) vertMap = Maps.SurjectVertical1D(M) actMap = Maps.InjectActiveCells(M, M.vectorCCy <= 0, 10, nC=M.nCy) m = np.r_[1., 2.] t_true = np.exp(np.r_[1, 1, 2, 2, 10, 10, 10, 10.]) self.assertLess( np.linalg.norm((expMap * vertMap * actMap * m) - t_true, np.inf), TOL) self.assertLess( np.linalg.norm(((expMap * vertMap * actMap) * m) - t_true, np.inf), TOL) self.assertLess( np.linalg.norm((expMap * vertMap * (actMap * m)) - t_true, np.inf), TOL) self.assertLess( np.linalg.norm((expMap * (vertMap * actMap) * m) - t_true, np.inf), TOL) self.assertLess( np.linalg.norm(((expMap * vertMap) * actMap * m) - t_true, np.inf), TOL) self.assertRaises(ValueError, lambda: expMap * actMap * vertMap) self.assertRaises(ValueError, lambda: actMap * vertMap * expMap)
def test_mapMultiplication(self): M = Mesh.TensorMesh([2, 3]) expMap = Maps.ExpMap(M) vertMap = Maps.SurjectVertical1D(M) combo = expMap * vertMap m = np.arange(3.0) t_true = np.exp(np.r_[0, 0, 1, 1, 2, 2.]) self.assertLess(np.linalg.norm((combo * m) - t_true, np.inf), TOL) self.assertLess( np.linalg.norm((expMap * vertMap * m) - t_true, np.inf), TOL) self.assertLess( np.linalg.norm(expMap * (vertMap * m) - t_true, np.inf), TOL) self.assertLess( np.linalg.norm((expMap * vertMap) * m - t_true, np.inf), TOL) # Try making a model mod = Models.Model(m, mapping=combo) # print mod.transform # import matplotlib.pyplot as plt # plt.colorbar(M.plotImage(mod.transform)[0]) # plt.show() self.assertLess(np.linalg.norm(mod.transform - t_true, np.inf), TOL) self.assertRaises(Exception, Models.Model, np.r_[1.0], mapping=combo) self.assertRaises(ValueError, lambda: combo * (vertMap * expMap)) self.assertRaises(ValueError, lambda: (combo * vertMap) * expMap) self.assertRaises(ValueError, lambda: vertMap * expMap) self.assertRaises(ValueError, lambda: expMap * np.ones(100)) self.assertRaises(ValueError, lambda: expMap * np.ones((100, 1))) self.assertRaises(ValueError, lambda: expMap * np.ones((100, 5))) self.assertRaises(ValueError, lambda: combo * np.ones(100)) self.assertRaises(ValueError, lambda: combo * np.ones((100, 1))) self.assertRaises(ValueError, lambda: combo * np.ones((100, 5)))
def setUp(self): cs = 5. ncx = 20 ncy = 6 npad = 20 hx = [(cs, ncx), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hy], '00C') active = mesh.vectorCCz < 0. activeMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * activeMap rxOffset = 40. rx = EM.TDEM.RxTDEM(np.array([[rxOffset, 0., 0.]]), np.logspace(-4, -3, 20), 'bz') src = EM.TDEM.SrcTDEM_VMD_MVP([rx], loc=np.array([0., 0., 0.])) survey = EM.TDEM.SurveyTDEM([src]) self.prb = EM.TDEM.ProblemTDEM_b(mesh, mapping=mapping) # self.prb.timeSteps = [1e-5] self.prb.timeSteps = [(1e-05, 10), (5e-05, 10), (2.5e-4, 10)] # self.prb.timeSteps = [(1e-05, 100)] try: from pymatsolver import MumpsSolver self.prb.Solver = MumpsSolver except ImportError, e: self.prb.Solver = SolverLU
def setThreeLayerParam(self, h1=12, h2=12, sig0=1e-8, sig1=1e-2, sig2=1e-2, sig3=1e-2, chi=0.): self.h1 = h1 # 1st layer thickness self.h2 = h2 # 2nd layer thickness self.z0 = 0. self.z1 = self.z0 - h1 self.z2 = self.z0 - h1 - h2 self.sig0 = sig0 # 0th layer \sigma (assumed to be air) self.sig1 = sig1 # 1st layer \sigma self.sig2 = sig2 # 2nd layer \sigma self.sig3 = sig3 # 3rd layer \sigma active = self.mesh.vectorCCz < self.z0 ind1 = ((self.mesh.vectorCCz < self.z0) & (self.mesh.vectorCCz >= self.z1)) ind2 = ((self.mesh.vectorCCz < self.z1) & (self.mesh.vectorCCz >= self.z2)) self.mapping = ( Maps.SurjectVertical1D(self.mesh) * Maps.InjectActiveCells(self.mesh, active, sig0, nC=self.mesh.nCz)) model = np.ones(self.mesh.nCz) * sig3 model[ind1] = sig1 model[ind2] = sig2 self.m = model[active] self.mu = np.ones(self.mesh.nC) * mu_0 self.mu[self.mesh.gridCC[:, 2] < 0.] = (1. + chi) * mu_0 return self.m
def getCoreModel(self, Type): if Type == 'Layer': active = self.mesh2D.vectorCCy < self.z0 ind1 = ((self.mesh2D.vectorCCy < self.z0) & (self.mesh2D.vectorCCy >= self.z1)) ind2 = ((self.mesh2D.vectorCCy < self.z1) & (self.mesh2D.vectorCCy >= self.z2)) mapping2D = ( Maps.SurjectVertical1D(self.mesh2D) * Maps.InjectActiveCells( self.mesh2D, active, self.sig0, nC=self.mesh2D.nCy)) model2D = np.ones(self.mesh2D.nCy) * self.sig3 model2D[ind1] = self.sig1 model2D[ind2] = self.sig2 model2D = model2D[active] elif Type == 'Sphere': active = self.mesh2D.gridCC[:, 1] < self.z0 ind1 = ((self.mesh2D.gridCC[:, 1] < self.z1) & (self.mesh2D.gridCC[:, 1] >= self.z1 - self.h)) ind2 = np.sqrt((self.mesh2D.gridCC[:, 0])**2 + (self.mesh2D.gridCC[:, 1] - self.z2)**2) <= self.R mapping2D = (Maps.InjectActiveCells(self.mesh2D, active, self.sig0, nC=self.mesh2D.nC)) model2D = np.ones(self.mesh2D.nC) * self.sigb model2D[ind1] = self.sig1 model2D[ind2] = self.sig2 model2D = model2D[active] return model2D, mapping2D
def test_nC_residual(self): # x-direction cs, ncx, ncz, npad = 1., 10., 10., 20 hx = [(cs, ncx), (cs, npad, 1.3)] # z direction npad = 12 temp = np.logspace(np.log10(1.), np.log10(12.), 19) temp_pad = temp[-1] * 1.3**np.arange(npad) hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad] mesh = Mesh.CylMesh([hx, 1, hz], '00C') active = mesh.vectorCCz < 0. active = mesh.vectorCCz < 0. actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap regMesh = Mesh.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 run(plotIt=True): M = Mesh.TensorMesh([7, 5]) v1dMap = Maps.SurjectVertical1D(M) expMap = Maps.ExpMap(M) myMap = expMap * v1dMap m = np.r_[0.2, 1, 0.1, 2, 2.9] # only 5 model parameters! sig = myMap * m if not plotIt: return figs, axs = plt.subplots(1, 2) axs[0].plot(m, M.vectorCCy, 'b-o') axs[0].set_title('Model') axs[0].set_ylabel('Depth, y') axs[0].set_xlabel('Value, $m_i$') axs[0].set_xlim(0, 3) axs[0].set_ylim(0, 1) clbar = plt.colorbar( M.plotImage(sig, ax=axs[1], grid=True, gridOpts=dict(color='grey'))[0]) axs[1].set_title('Physical Property') axs[1].set_ylabel('Depth, y') clbar.set_label('$\sigma = \exp(\mathbf{P}m)$') plt.tight_layout()
def run(plotIt=True): """ EM: FDEM: 1D: Inversion ======================= Here we will create and run a FDEM 1D inversion. """ cs, ncx, ncz, npad = 5., 25, 15, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hz], '00C') layerz = -100. active = mesh.vectorCCz < 0. layer = (mesh.vectorCCz < 0.) & (mesh.vectorCCz >= layerz) actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap sig_half = 2e-2 sig_air = 1e-8 sig_layer = 1e-2 sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half sigma[layer] = sig_layer mtrue = np.log(sigma[active]) if plotIt: import matplotlib.pyplot as plt fig, ax = plt.subplots(1, 1, figsize=(3, 6)) plt.semilogx(sigma[active], mesh.vectorCCz[active]) ax.set_ylim(-500, 0) ax.set_xlim(1e-3, 1e-1) ax.set_xlabel('Conductivity (S/m)', fontsize=14) ax.set_ylabel('Depth (m)', fontsize=14) ax.grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5) rxOffset = 10. bzi = EM.FDEM.Rx.Point_b(np.array([[rxOffset, 0., 1e-3]]), orientation='z', component='imag') freqs = np.logspace(1, 3, 10) srcLoc = np.array([0., 0., 10.]) srcList = [ EM.FDEM.Src.MagDipole([bzi], freq, srcLoc, orientation='Z') for freq in freqs ] survey = EM.FDEM.Survey(srcList) prb = EM.FDEM.Problem3D_b(mesh, mapping=mapping) try: from pymatsolver import MumpsSolver prb.Solver = MumpsSolver except ImportError, e: prb.Solver = SolverLU
def setUp_TDEM(prbtype='b', rxcomp='bz', waveform='stepoff'): cs = 5. ncx = 8 ncy = 8 ncz = 8 npad = 4 # hx = [(cs, ncx), (cs, npad, 1.3)] # hz = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)] mesh = Mesh.TensorMesh( [ [(cs, npad, -1.3), (cs, ncx), (cs, npad, 1.3)], [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)], [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] ], 'CCC' ) active = mesh.vectorCCz < 0. activeMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * activeMap prb = getattr(EM.TDEM, 'Problem3D_{}'.format(prbtype))(mesh, sigmaMap=mapping) rxtimes = np.logspace(-4, -3, 20) if waveform.upper() == 'RAW': out = EM.Utils.VTEMFun(prb.times, 0.00595, 0.006, 100) wavefun = interp1d(prb.times, out) t0 = 0.006 waveform = EM.TDEM.Src.RawWaveform(offTime=t0, waveFct=wavefun) prb.timeSteps = [(1e-3, 5), (1e-4, 5), (5e-5, 10), (5e-5, 10), (1e-4, 10)] rxtimes = t0+rxtimes else: waveform = EM.TDEM.Src.StepOffWaveform() prb.timeSteps = [(1e-05, 10), (5e-05, 10), (2.5e-4, 10)] rxOffset = 10. rx = getattr(EM.TDEM.Rx, 'Point_{}'.format(rxcomp[:-1]))( np.array([[rxOffset, 0., -1e-2]]), rxtimes, rxcomp[-1] ) src = EM.TDEM.Src.MagDipole( [rx], loc=np.array([0., 0., 0.]), waveform=waveform ) survey = EM.TDEM.Survey([src]) prb.Solver = Solver m = (np.log(1e-1)*np.ones(prb.sigmaMap.nP) + 1e-2*np.random.rand(prb.sigmaMap.nP)) prb.pair(survey) mesh = mesh return prb, m, mesh
def run(plotIt=True): """ Maps: ComboMaps =============== We will use an example where we want a 1D layered earth as our model, but we want to map this to a 2D discretization to do our forward modeling. We will also assume that we are working in log conductivity still, so after the transformation we map to conductivity space. To do this we will introduce the vertical 1D map (:class:`SimPEG.Maps.SurjectVertical1D`), which does the first part of what we just described. The second part will be done by the :class:`SimPEG.Maps.ExpMap` described above. .. code-block:: python :linenos: M = Mesh.TensorMesh([7,5]) v1dMap = Maps.SurjectVertical1D(M) expMap = Maps.ExpMap(M) myMap = expMap * v1dMap m = np.r_[0.2,1,0.1,2,2.9] # only 5 model parameters! sig = myMap * m If you noticed, it was pretty easy to combine maps. What is even cooler is that the derivatives also are made for you (if everything goes right). Just to be sure that the derivative is correct, you should always run the test on the mapping that you create. """ M = Mesh.TensorMesh([7, 5]) v1dMap = Maps.SurjectVertical1D(M) expMap = Maps.ExpMap(M) myMap = expMap * v1dMap m = np.r_[0.2, 1, 0.1, 2, 2.9] # only 5 model parameters! sig = myMap * m if not plotIt: return figs, axs = plt.subplots(1, 2) axs[0].plot(m, M.vectorCCy, 'b-o') axs[0].set_title('Model') axs[0].set_ylabel('Depth, y') axs[0].set_xlabel('Value, $m_i$') axs[0].set_xlim(0, 3) axs[0].set_ylim(0, 1) clbar = plt.colorbar( M.plotImage(sig, ax=axs[1], grid=True, gridOpts=dict(color='grey'))[0]) axs[1].set_title('Physical Property') axs[1].set_ylabel('Depth, y') clbar.set_label('$\sigma = \exp(\mathbf{P}m)$') plt.tight_layout()
def halfSpaceProblemAnaDiff(meshType, sig_half=1e-2, rxOffset=50., bounds=None, showIt=False): print '\nTesting sig_half = {0}, rxOffset= {1}'.format(sig_half, rxOffset) if bounds is None: bounds = [1e-5, 1e-3] if meshType == 'CYL': cs, ncx, ncz, npad = 5., 30, 10, 20 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hz], '00C') elif meshType == 'TENSOR': cs, nc, npad = 20., 13, 5 hx = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] mesh = Mesh.TensorMesh([hx, hy, hz], 'CCC') active = mesh.vectorCCz < 0. actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap rx = EM.TDEM.RxTDEM(np.array([[rxOffset, 0., 0.]]), np.logspace(-5, -4, 21), 'bz') src = EM.TDEM.SrcTDEM_VMD_MVP([rx], loc=np.array([0., 0., 0.])) # src = EM.TDEM.SrcTDEM([rx], loc=np.array([0., 0., 0.])) survey = EM.TDEM.SurveyTDEM([src]) prb = EM.TDEM.ProblemTDEM_b(mesh, mapping=mapping) prb.Solver = MumpsSolver prb.timeSteps = [(1e-06, 40), (5e-06, 40), (1e-05, 40), (5e-05, 40), (0.0001, 40), (0.0005, 40)] sigma = np.ones(mesh.nCz)*1e-8 sigma[active] = sig_half sigma = np.log(sigma[active]) prb.pair(survey) bz_ana = mu_0*EM.Analytics.hzAnalyticDipoleT(rx.locs[0][0]+1e-3, rx.times, sig_half) bz_calc = survey.dpred(sigma) ind = np.logical_and(rx.times > bounds[0], rx.times < bounds[1]) log10diff = np.linalg.norm(np.log10(np.abs(bz_calc[ind])) - np.log10(np.abs(bz_ana[ind])))/np.linalg.norm(np.log10(np.abs(bz_ana[ind]))) print 'Difference: ', log10diff if showIt == True: plt.loglog(rx.times[bz_calc>0], bz_calc[bz_calc>0], 'r', rx.times[bz_calc<0], -bz_calc[bz_calc<0], 'r--') plt.loglog(rx.times, abs(bz_ana), 'b*') plt.title('sig_half = {0:e}'.format(sig_half)) plt.show() return log10diff
def test_activeCells(self): M = Mesh.TensorMesh([2, 4], '0C') for actMap in [Maps.InjectActiveCells(M, M.vectorCCy <= 0, 10, nC=M.nCy), Maps.ActiveCells(M, M.vectorCCy <= 0, 10, nC=M.nCy)]: vertMap = Maps.SurjectVertical1D(M) combo = vertMap * actMap m = np.r_[1., 2.] mod = Models.Model(m, combo) self.assertLess(np.linalg.norm(mod.transform - np.r_[1, 1, 2, 2, 10, 10, 10, 10.]), TOL) self.assertLess((mod.transformDeriv - combo.deriv(m)).toarray().sum(), TOL)
def setUp_TDEM(prbtype='e', rxcomp='ex'): cs = 5. ncx = 8 ncy = 8 ncz = 8 npad = 0 # hx = [(cs, ncx), (cs, npad, 1.3)] # hz = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)] mesh = Mesh.TensorMesh([[ (cs, npad, -1.3), (cs, ncx), (cs, npad, 1.3) ], [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)], [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)]], 'CCC') # active = mesh.vectorCCz < 0. activeMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * activeMap rxOffset = 0. rxlocs = np.array([[20, 20., 0.]]) rxtimes = np.logspace(-4, -3, 20) rx = getattr(EM.TDEM.Rx, 'Point_{}'.format(rxcomp[:-1]))(locs=rxlocs, times=rxtimes, orientation=rxcomp[-1]) Aloc = np.r_[-10., 0., 0.] Bloc = np.r_[10., 0., 0.] srcloc = np.vstack((Aloc, Bloc)) src = EM.TDEM.Src.LineCurrent([rx], loc=srcloc, waveform=EM.TDEM.Src.StepOffWaveform()) survey = EM.TDEM.Survey([src]) prb = getattr(EM.TDEM, 'Problem3D_{}'.format(prbtype))(mesh, sigmaMap=mapping) prb.timeSteps = [(1e-05, 10), (5e-05, 10), (2.5e-4, 10)] prb.Solver = Solver m = (np.log(1e-1) * np.ones(prb.sigmaMap.nP) + 1e-3 * np.random.randn(prb.sigmaMap.nP)) prb.pair(survey) mesh = mesh return prb, m, mesh
def S_e(self, problem): """ Get the electrical field source """ e_p = self.ePrimary(problem) Map_sigma_p = Maps.SurjectVertical1D(problem.mesh) sigma_p = Map_sigma_p._transform(self.sigma1d) # Make mass matrix # Note: M(sig) - M(sig_p) = M(sig - sig_p) # Need to deal with the edge/face discrepencies between 1d/2d/3d if problem.mesh.dim == 1: Mesigma = problem.mesh.getFaceInnerProduct(problem.sigma) Mesigma_p = problem.mesh.getFaceInnerProduct(sigma_p) if problem.mesh.dim == 2: pass if problem.mesh.dim == 3: Mesigma = problem.MeSigma Mesigma_p = problem.mesh.getEdgeInnerProduct(sigma_p) return (Mesigma - Mesigma_p) * e_p
def test_activeCells(self): M = Mesh.TensorMesh([2, 4], '0C') expMap = Maps.ExpMap(M) for actMap in [ Maps.InjectActiveCells(M, M.vectorCCy <= 0, 10, nC=M.nCy), Maps.ActiveCells(M, M.vectorCCy <= 0, 10, nC=M.nCy) ]: # actMap = Maps.InjectActiveCells(M, M.vectorCCy <=0, 10, nC=M.nCy) vertMap = Maps.SurjectVertical1D(M) combo = vertMap * actMap m = np.r_[1, 2.] mod = Models.Model(m, combo) # import matplotlib.pyplot as plt # plt.colorbar(M.plotImage(mod.transform)[0]) # plt.show() self.assertLess( np.linalg.norm(mod.transform - np.r_[1, 1, 2, 2, 10, 10, 10, 10.]), TOL) self.assertLess( (mod.transformDeriv - combo.deriv(m)).toarray().sum(), TOL)
def setUp_TDEM(prbtype='b', rxcomp='bz'): cs = 5. ncx = 20 ncy = 15 npad = 20 hx = [(cs, ncx), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hy], '00C') # active = mesh.vectorCCz < 0. activeMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * activeMap rxOffset = 10. if prbtype == 'b': prb = EM.TDEM.Problem3D_b(mesh, mapping=mapping) elif prbtype == 'e': prb = EM.TDEM.Problem3D_e(mesh, mapping=mapping) prb.timeSteps = [(1e-3, 5), (1e-4, 5), (5e-5, 10), (5e-5, 10), (1e-4, 10)] out = EM.Utils.VTEMFun(prb.times, 0.00595, 0.006, 100) wavefun = interp1d(prb.times, out) t0 = 0.006 waveform = EM.TDEM.Src.RawWaveform(offTime=t0, waveFct=wavefun) timerx = np.logspace(-4, -3, 20) rx = EM.TDEM.Rx(np.array([[rxOffset, 0., 0.]]), timerx, rxcomp) src = EM.TDEM.Src.MagDipole([rx], waveform= waveform, loc=np.array([0., 0., 0.])) survey = EM.TDEM.Survey([src]) prb.Solver = Solver m = np.log(1e-1)*np.ones(prb.mapping.nP) # + 1e-2*np.random.randn(prb.mapping.nP) prb.pair(survey) mesh = mesh return prb, m, mesh
def setUp_TDEM(self, rxcomp='bz'): cs = 5. ncx = 20 ncy = 6 npad = 20 hx = [(cs, ncx), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hy], '00C') active = mesh.vectorCCz < 0. activeMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * activeMap rxOffset = 40. rx = EM.TDEM.Rx(np.array([[rxOffset, 0., 0.]]), np.logspace(-4, -3, 20), rxcomp) src = EM.TDEM.Src.MagDipole([rx], loc=np.array([0., 0., 0.])) rx2 = EM.TDEM.Rx(np.array([[rxOffset-10, 0., 0.]]), np.logspace(-5, -4, 25), rxcomp) src2 = EM.TDEM.Src.MagDipole( [rx2], loc=np.array([0., 0., 0.])) survey = EM.TDEM.Survey([src, src2]) prb = EM.TDEM.Problem3D_b(mesh, mapping=mapping) # prb.timeSteps = [1e-5] prb.timeSteps = [(1e-05, 10), (5e-05, 10), (2.5e-4, 10)] # prb.timeSteps = [(1e-05, 100)] prb.Solver = Solver m = (np.log(1e-1)*np.ones(prb.mapping.nP) + 1e-2*np.random.randn(prb.mapping.nP)) prb.pair(survey) return mesh, prb, m
def setUp_TDEM(prbtype='b', rxcomp='bz'): cs = 5. ncx = 20 ncy = 15 npad = 20 hx = [(cs, ncx), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hy], '00C') # active = mesh.vectorCCz < 0. activeMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * activeMap rxOffset = 10. rx = EM.TDEM.Rx(np.array([[rxOffset, 0., -1e-2]]), np.logspace(-4, -3, 20), rxcomp) src = EM.TDEM.Src.MagDipole([rx], loc=np.array([0., 0., 0.])) survey = EM.TDEM.Survey([src]) if prbtype == 'b': prb = EM.TDEM.Problem3D_b(mesh, mapping=mapping) elif prbtype == 'e': prb = EM.TDEM.Problem3D_e(mesh, mapping=mapping) prb.timeSteps = [(1e-05, 10), (5e-05, 10), (2.5e-4, 10)] # prb.timeSteps = [(1e-05, 10), (1e-05, 50), (1e-05, 50) ] #, (2.5e-4, 10)] prb.Solver = Solver m = (np.log(1e-1) * np.ones(prb.mapping.nP) + 1e-3 * np.random.randn(prb.mapping.nP)) prb.pair(survey) mesh = mesh return prb, m, mesh
def getProb(meshType='CYL', rxTypes='bx,bz', nSrc=1): cs = 5. ncx = 20 ncy = 6 npad = 20 hx = [(cs, ncx), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hy], '00C') active = mesh.vectorCCz < 0. activeMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * activeMap rxOffset = 40. srcs = [] for ii in range(nSrc): rxs = [ EM.TDEM.RxTDEM(np.array([[rxOffset, 0., 0.]]), np.logspace(-4, -3, 20 + ii), rxType) for rxType in rxTypes.split(',') ] srcs += [EM.TDEM.SrcTDEM_VMD_MVP(rxs, np.array([0., 0., 0.]))] survey = EM.TDEM.SurveyTDEM(srcs) prb = EM.TDEM.ProblemTDEM_b(mesh, mapping=mapping) # prb.timeSteps = [1e-5] prb.timeSteps = [(1e-05, 10), (5e-05, 10), (2.5e-4, 10)] # prb.timeSteps = [(1e-05, 100)] try: from pymatsolver import MumpsSolver prb.Solver = MumpsSolver except ImportError, e: prb.Solver = SolverLU
def run(plotIt=True): """ 1D FDEM Mu Inversion ==================== 1D inversion of Magnetic Susceptibility from FDEM data assuming a fixed electrical conductivity """ # Set up cylindrically symmeric mesh cs, ncx, ncz, npad = 10., 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 = Mesh.CylMesh([hx, 1, hz], '00C') # Geologic Parameters model layerz = np.r_[-100., -50.] layer = (mesh.vectorCCz >= layerz[0]) & (mesh.vectorCCz <= layerz[1]) active = mesh.vectorCCz < 0. # Electrical Conductivity sig_half = 1e-2 # Half-space conductivity sig_air = 1e-8 # Air conductivity sig_layer = 1e-2 # Layer conductivity sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half sigma[layer] = sig_layer # mur - relative magnetic permeability mur_half = 1. mur_air = 1. mur_layer = 2. mur = np.ones(mesh.nCz) * mur_air mur[active] = mur_half mur[layer] = mur_layer mtrue = mur[active] # Maps actMap = Maps.InjectActiveCells(mesh, active, mur_air, nC=mesh.nCz) surj1Dmap = Maps.SurjectVertical1D(mesh) murMap = Maps.MuRelative(mesh) # Mapping muMap = murMap * surj1Dmap * actMap # ----- FDEM problem & survey ----- rxlocs = Utils.ndgrid([np.r_[10.], np.r_[0], np.r_[30.]]) bzr = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'real') # bzi = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'imag') freqs = np.linspace(2000, 10000, 10) #np.logspace(3, 4, 10) srcLoc = np.array([0., 0., 30.]) print('min skin depth = ', 500. / np.sqrt(freqs.max() * sig_half), 'max skin depth = ', 500. / np.sqrt(freqs.min() * sig_half)) print('max x ', mesh.vectorCCx.max(), 'min z ', mesh.vectorCCz.min(), 'max z ', mesh.vectorCCz.max()) srcList = [ FDEM.Src.MagDipole([bzr], freq, srcLoc, orientation='Z') for freq in freqs ] surveyFD = FDEM.Survey(srcList) prbFD = FDEM.Problem3D_b(mesh, sigma=surj1Dmap * sigma, muMap=muMap, Solver=Solver) prbFD.pair(surveyFD) std = 0.03 surveyFD.makeSyntheticData(mtrue, std) surveyFD.eps = np.linalg.norm(surveyFD.dtrue) * 1e-6 # FDEM inversion np.random.seed(13472) dmisfit = DataMisfit.l2_DataMisfit(surveyFD) regMesh = Mesh.TensorMesh([mesh.hz[muMap.maps[-1].indActive]]) reg = Regularization.Simple(regMesh) opt = Optimization.InexactGaussNewton(maxIterCG=10) invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # Inversion Directives betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.) beta = Directives.BetaSchedule(coolingFactor=4, coolingRate=3) betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.) target = Directives.TargetMisfit() directiveList = [beta, betaest, target] inv = Inversion.BaseInversion(invProb, directiveList=directiveList) m0 = mur_half * np.ones(mtrue.size) reg.alpha_s = 2e-2 reg.alpha_x = 1. prbFD.counter = opt.counter = Utils.Counter() opt.remember('xc') moptFD = inv.run(m0) dpredFD = surveyFD.dpred(moptFD) if plotIt: fig, ax = plt.subplots(1, 3, figsize=(10, 6)) fs = 13 # fontsize matplotlib.rcParams['font.size'] = fs # Plot the conductivity model ax[0].semilogx(sigma[active], mesh.vectorCCz[active], 'k-', lw=2) ax[0].set_ylim(-500, 0) ax[0].set_xlim(5e-3, 1e-1) ax[0].set_xlabel('Conductivity (S/m)', fontsize=fs) ax[0].set_ylabel('Depth (m)', fontsize=fs) ax[0].grid(which='both', color='k', alpha=0.5, linestyle='-', linewidth=0.2) ax[0].legend(['Conductivity Model'], fontsize=fs, loc=4) # Plot the permeability model ax[1].plot(mur[active], mesh.vectorCCz[active], 'k-', lw=2) ax[1].plot(moptFD, mesh.vectorCCz[active], 'b-', lw=2) ax[1].set_ylim(-500, 0) ax[1].set_xlim(0.5, 2.1) ax[1].set_xlabel('Relative Permeability', fontsize=fs) ax[1].set_ylabel('Depth (m)', fontsize=fs) ax[1].grid(which='both', color='k', alpha=0.5, linestyle='-', linewidth=0.2) ax[1].legend(['True', 'Predicted'], fontsize=fs, loc=4) # plot the data misfits - negative b/c we choose positive to be in the # direction of primary ax[2].plot(freqs, -surveyFD.dobs, 'k-', lw=2) # ax[2].plot(freqs, -surveyFD.dobs[1::2], 'k--', lw=2) ax[2].loglog(freqs, -dpredFD, 'bo', ms=6) # ax[2].loglog(freqs, -dpredFD[1::2], 'b+', markeredgewidth=2., ms=10) # Labels, gridlines, etc ax[2].grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2) ax[2].grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2) ax[2].set_xlabel('Frequency (Hz)', fontsize=fs) ax[2].set_ylabel('Vertical magnetic field (-T)', fontsize=fs) # ax[2].legend(("Obs", "Pred"), fontsize=fs) ax[2].legend(("z-Obs (real)", "z-Pred (real)"), fontsize=fs) ax[2].set_xlim(freqs.max(), freqs.min()) ax[0].set_title("(a) Conductivity Model", fontsize=fs) ax[1].set_title("(b) $\mu_r$ Model", fontsize=fs) ax[2].set_title("(c) FDEM observed vs. predicted", fontsize=fs) # ax[2].set_title("(c) TDEM observed vs. predicted", fontsize=fs) plt.tight_layout(pad=1.5)
def run(plotIt=True): """ EM: TDEM: 1D: Inversion with VTEM waveform ========================================== Here we will create and run a TDEM 1D inversion, with VTEM waveform of which initial condition is zero, but have some on- and off-time. """ cs, ncx, ncz, npad = 5., 25, 24, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hz], '00C') active = mesh.vectorCCz < 0. layer = (mesh.vectorCCz < -50.) & (mesh.vectorCCz >= -150.) actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap sig_half = 1e-3 sig_air = 1e-8 sig_layer = 1e-2 sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half sigma[layer] = sig_layer mtrue = np.log(sigma[active]) x = np.r_[30, 50, 70, 90] rxloc = np.c_[x, x * 0., np.zeros_like(x)] prb = EM.TDEM.Problem3D_b(mesh, sigmaMap=mapping) prb.Solver = Solver prb.timeSteps = [(1e-3, 5), (1e-4, 5), (5e-5, 10), (5e-5, 5), (1e-4, 10), (5e-4, 10)] # Use VTEM waveform out = EM.Utils.VTEMFun(prb.times, 0.00595, 0.006, 100) # Forming function handle for waveform using 1D linear interpolation wavefun = interp1d(prb.times, out) t0 = 0.006 waveform = EM.TDEM.Src.RawWaveform(offTime=t0, waveFct=wavefun) rx = EM.TDEM.Rx.Point_dbdt(rxloc, np.logspace(-4, -2.5, 11) + t0, 'z') src = EM.TDEM.Src.CircularLoop([rx], waveform=waveform, loc=np.array([0., 0., 0.]), radius=10.) survey = EM.TDEM.Survey([src]) prb.pair(survey) # create observed data std = 0.02 survey.dobs = survey.makeSyntheticData(mtrue, std) # dobs = survey.dpred(mtrue) survey.std = std survey.eps = 1e-11 dmisfit = DataMisfit.l2_DataMisfit(survey) regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Simple(regMesh) opt = Optimization.InexactGaussNewton(maxIter=5, LSshorten=0.5) invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) target = Directives.TargetMisfit() # Create an inversion object beta = Directives.BetaSchedule(coolingFactor=1., coolingRate=2.) betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0) invProb.beta = 1e2 inv = Inversion.BaseInversion(invProb, directiveList=[beta, target]) m0 = np.log(np.ones(mtrue.size) * sig_half) prb.counter = opt.counter = Utils.Counter() opt.remember('xc') mopt = inv.run(m0) if plotIt: fig, ax = plt.subplots(1, 2, figsize=(10, 6)) Dobs = survey.dobs.reshape((len(rx.times), len(x))) Dpred = invProb.dpred.reshape((len(rx.times), len(x))) for i in range(len(x)): ax[0].loglog(rx.times - t0, -Dobs[:, i].flatten(), 'k') ax[0].loglog(rx.times - t0, -Dpred[:, i].flatten(), 'k.') if i == 0: ax[0].legend(('$d^{obs}$', '$d^{pred}$'), fontsize=16) ax[0].set_xlabel('Time (s)', fontsize=14) ax[0].set_ylabel('$db_z / dt$ (nT/s)', fontsize=16) ax[0].set_xlabel('Time (s)', fontsize=14) ax[0].grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5) plt.semilogx(sigma[active], mesh.vectorCCz[active]) plt.semilogx(np.exp(mopt), mesh.vectorCCz[active]) ax[1].set_ylim(-600, 0) ax[1].set_xlim(1e-4, 1e-1) ax[1].set_xlabel('Conductivity (S/m)', fontsize=14) ax[1].set_ylabel('Depth (m)', fontsize=14) ax[1].grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5) plt.legend(['$\sigma_{true}$', '$\sigma_{pred}$'])
def run(plotIt=True): cs, ncx, ncz, npad = 5., 25, 15, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hz], '00C') layerz = -100. active = mesh.vectorCCz < 0. layer = (mesh.vectorCCz < 0.) & (mesh.vectorCCz >= layerz) actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap sig_half = 2e-2 sig_air = 1e-8 sig_layer = 1e-2 sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half sigma[layer] = sig_layer mtrue = np.log(sigma[active]) if plotIt: fig, ax = plt.subplots(1, 1, figsize=(3, 6)) plt.semilogx(sigma[active], mesh.vectorCCz[active]) ax.set_ylim(-500, 0) ax.set_xlim(1e-3, 1e-1) ax.set_xlabel('Conductivity (S/m)', fontsize=14) ax.set_ylabel('Depth (m)', fontsize=14) ax.grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5) rxOffset = 10. bzi = EM.FDEM.Rx.Point_b(np.array([[rxOffset, 0., 1e-3]]), orientation='z', component='imag') freqs = np.logspace(1, 3, 10) srcLoc = np.array([0., 0., 10.]) srcList = [ EM.FDEM.Src.MagDipole([bzi], freq, srcLoc, orientation='Z') for freq in freqs ] survey = EM.FDEM.Survey(srcList) prb = EM.FDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=Solver) prb.pair(survey) std = 0.05 survey.makeSyntheticData(mtrue, std) survey.std = std survey.eps = np.linalg.norm(survey.dtrue) * 1e-5 if plotIt: fig, ax = plt.subplots(1, 1, figsize=(6, 6)) ax.semilogx(freqs, survey.dtrue[:freqs.size], 'b.-') ax.semilogx(freqs, survey.dobs[:freqs.size], 'r.-') ax.legend(('Noisefree', '$d^{obs}$'), fontsize=16) ax.set_xlabel('Time (s)', fontsize=14) ax.set_ylabel('$B_z$ (T)', fontsize=16) ax.set_xlabel('Time (s)', fontsize=14) ax.grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5) dmisfit = DataMisfit.l2_DataMisfit(survey) regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Tikhonov(regMesh) opt = Optimization.InexactGaussNewton(maxIter=6) invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # Create an inversion object beta = Directives.BetaSchedule(coolingFactor=5, coolingRate=2) betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0) inv = Inversion.BaseInversion(invProb, directiveList=[beta, betaest]) m0 = np.log(np.ones(mtrue.size) * sig_half) reg.alpha_s = 1e-3 reg.alpha_x = 1. prb.counter = opt.counter = Utils.Counter() opt.LSshorten = 0.5 opt.remember('xc') mopt = inv.run(m0) if plotIt: fig, ax = plt.subplots(1, 1, figsize=(3, 6)) plt.semilogx(sigma[active], mesh.vectorCCz[active]) plt.semilogx(np.exp(mopt), mesh.vectorCCz[active]) ax.set_ylim(-500, 0) ax.set_xlim(1e-3, 1e-1) ax.set_xlabel('Conductivity (S/m)', fontsize=14) ax.set_ylabel('Depth (m)', fontsize=14) ax.grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5) plt.legend(['$\sigma_{true}$', '$\sigma_{pred}$'], loc='best')
def halfSpaceProblemAnaDiff(meshType, srctype="MagDipole", sig_half=1e-2, rxOffset=50., bounds=None, plotIt=False, rxType='bz'): if bounds is None: bounds = [1e-5, 1e-3] if meshType == 'CYL': cs, ncx, ncz, npad = 15., 30, 10, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hz], '00C') elif meshType == 'TENSOR': cs, nc, npad = 20., 13, 5 hx = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] mesh = Mesh.TensorMesh([hx, hy, hz], 'CCC') active = mesh.vectorCCz < 0. actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap prb = EM.TDEM.Problem3D_b(mesh, sigmaMap=mapping) prb.Solver = Solver prb.timeSteps = [(1e-3, 5), (1e-4, 5), (5e-5, 10), (5e-5, 10), (1e-4, 10)] out = EM.Utils.VTEMFun(prb.times, 0.00595, 0.006, 100) wavefun = interp1d(prb.times, out) t0 = 0.006 waveform = EM.TDEM.Src.RawWaveform(offTime=t0, waveFct=wavefun) rx = getattr(EM.TDEM.Rx, 'Point_{}'.format(rxType[:-1]))(np.array([[rxOffset, 0., 0.]]), np.logspace(-4, -3, 31) + t0, rxType[-1]) if srctype == "MagDipole": src = EM.TDEM.Src.MagDipole([rx], waveform=waveform, loc=np.array([0, 0., 0.])) elif srctype == "CircularLoop": src = EM.TDEM.Src.CircularLoop([rx], waveform=waveform, loc=np.array([0., 0., 0.]), radius=13.) survey = EM.TDEM.Survey([src]) prb.pair(survey) sigma = np.ones(mesh.nCz) * 1e-8 sigma[active] = sig_half sigma = np.log(sigma[active]) if srctype == "MagDipole": bz_ana = mu_0 * EM.Analytics.hzAnalyticDipoleT(rx.locs[0][0] + 1e-3, rx.times - t0, sig_half) elif srctype == "CircularLoop": bz_ana = mu_0 * EM.Analytics.hzAnalyticCentLoopT( 13, rx.times - t0, sig_half) bz_calc = survey.dpred(sigma) ind = np.logical_and(rx.times - t0 > bounds[0], rx.times - t0 < bounds[1]) log10diff = (np.linalg.norm( np.log10(np.abs(bz_calc[ind])) - np.log10(np.abs(bz_ana[ind]))) / np.linalg.norm(np.log10(np.abs(bz_ana[ind])))) print(' |bz_ana| = {ana} |bz_num| = {num} |bz_ana-bz_num| = {diff}'.format( ana=np.linalg.norm(bz_ana), num=np.linalg.norm(bz_calc), diff=np.linalg.norm(bz_ana - bz_calc))) print('Difference: {}'.format(log10diff)) if plotIt is True: plt.loglog(rx.times[bz_calc > 0] - t0, bz_calc[bz_calc > 0], 'r', rx.times[bz_calc < 0] - t0, -bz_calc[bz_calc < 0], 'r--') plt.loglog(rx.times - t0, abs(bz_ana), 'b*') plt.title('sig_half = {:e}'.format(sig_half)) plt.show() return log10diff
# Generate mesh cs = 25. npad = 11 hx = [(cs, npad, -1.3), (cs, 41), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, 17), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, 20)] mesh = Mesh.TensorMesh([hx, hy, hz], 'CCN') ############################################################################### # Step 2 # ------ # # Generating model and mapping (1D to 3D) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) siglay1 = 1. / (100.) siglay2 = 1. / (500.) sighalf = 1. / (100.) sigma = np.ones(mesh.nCz) * siglay1 sigma[mesh.vectorCCz <= -100.] = siglay2 sigma[mesh.vectorCCz < -150.] = sighalf mtrue = np.log(sigma) fig, ax = plt.subplots(1, 2, figsize=(18 * 0.8, 7 * 0.8)) plotLayer(np.log(sigma), mesh.vectorCCz, 'linear', showlayers=True, ax=ax[0]) ax[0].invert_xaxis() ax[0].set_ylim(-500, 0) ax[0].set_xlim(-7, -4) ax[0].set_xlabel('$log(\sigma)$', fontsize=25) ax[0].set_ylabel('Depth (m)', fontsize=25)
def run(plotIt=True, saveFig=False): # Set up cylindrically symmeric mesh cs, ncx, ncz, npad = 10., 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 = Mesh.CylMesh([hx, 1, hz], '00C') # Conductivity model layerz = np.r_[-200., -100.] layer = (mesh.vectorCCz >= layerz[0]) & (mesh.vectorCCz <= layerz[1]) active = mesh.vectorCCz < 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.], np.r_[0], np.r_[0.]]) bzr = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'real') bzi = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'imag') freqs = np.logspace(2, 3, 5) srcLoc = np.array([0., 0., 0.]) print('min skin depth = ', 500. / np.sqrt(freqs.max() * sig_half), 'max skin depth = ', 500. / np.sqrt(freqs.min() * sig_half)) print('max x ', mesh.vectorCCx.max(), 'min z ', mesh.vectorCCz.min(), 'max z ', mesh.vectorCCz.max()) srcList = [ FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation='Z') for freq in freqs ] surveyFD = FDEM.Survey(srcList) prbFD = FDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=Solver) prbFD.pair(surveyFD) std = 0.03 surveyFD.makeSyntheticData(mtrue, std) surveyFD.eps = np.linalg.norm(surveyFD.dtrue) * 1e-5 # FDEM inversion np.random.seed(1) dmisfit = DataMisfit.l2_DataMisfit(surveyFD) regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Simple(regMesh) opt = Optimization.InexactGaussNewton(maxIterCG=10) invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # Inversion Directives beta = Directives.BetaSchedule(coolingFactor=4, coolingRate=3) betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.) 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. 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.Point_b(rxlocs, times, 'z') src = TDEM.Src.MagDipole( [rx], waveform=TDEM.Src.StepOffWaveform(), loc=srcLoc # same src location as FDEM problem ) surveyTD = TDEM.Survey([src]) prbTD = TDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=Solver) prbTD.timeSteps = [(5e-5, 10), (1e-4, 10), (5e-4, 10)] prbTD.pair(surveyTD) std = 0.03 surveyTD.makeSyntheticData(mtrue, std) surveyTD.std = std surveyTD.eps = np.linalg.norm(surveyTD.dtrue) * 1e-5 # TDEM inversion dmisfit = DataMisfit.l2_DataMisfit(surveyTD) regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Simple(regMesh) opt = Optimization.InexactGaussNewton(maxIterCG=10) invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # directives beta = Directives.BetaSchedule(coolingFactor=4, coolingRate=3) betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.) 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. 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 ax0.semilogx(sigma[active], mesh.vectorCCz[active], '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, -surveyFD.dobs[::2], 'k-', lw=2, label="Obs (real)") ax1.plot(freqs, -surveyFD.dobs[1::2], 'k--', lw=2, label="Obs (imag)") dpredFD = surveyFD.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., label="Pred (imag)") ax2.loglog(times, surveyTD.dobs, 'k-', lw=2, label='Obs') ax2.loglog(times, surveyTD.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 get_mapping(mesh): active = mesh.vectorCCz < 0. activeMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) return Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * activeMap
def run(plotIt=True): """ EM: TDEM: 1D: Inversion ======================= Here we will create and run a TDEM 1D inversion. """ cs, ncx, ncz, npad = 5., 25, 15, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hz], '00C') active = mesh.vectorCCz < 0. layer = (mesh.vectorCCz < 0.) & (mesh.vectorCCz >= -100.) actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap sig_half = 2e-3 sig_air = 1e-8 sig_layer = 1e-3 sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half sigma[layer] = sig_layer mtrue = np.log(sigma[active]) rxOffset = 1e-3 rx = EM.TDEM.Rx.Point_b(np.array([[rxOffset, 0., 30]]), np.logspace(-5, -3, 31), 'z') src = EM.TDEM.Src.MagDipole([rx], loc=np.array([0., 0., 80])) survey = EM.TDEM.Survey([src]) prb = EM.TDEM.Problem3D_b(mesh, sigmaMap=mapping) prb.Solver = SolverLU prb.timeSteps = [(1e-06, 20), (1e-05, 20), (0.0001, 20)] prb.pair(survey) # create observed data std = 0.05 survey.dobs = survey.makeSyntheticData(mtrue, std) survey.std = std survey.eps = 1e-5 * np.linalg.norm(survey.dobs) dmisfit = DataMisfit.l2_DataMisfit(survey) regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Tikhonov(regMesh, alpha_s=1e-2, alpha_x=1.) opt = Optimization.InexactGaussNewton(maxIter=5, LSshorten=0.5) invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # Create an inversion object beta = Directives.BetaSchedule(coolingFactor=5, coolingRate=2) betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0) inv = Inversion.BaseInversion(invProb, directiveList=[beta, betaest]) m0 = np.log(np.ones(mtrue.size) * sig_half) prb.counter = opt.counter = Utils.Counter() opt.remember('xc') mopt = inv.run(m0) if plotIt: fig, ax = plt.subplots(1, 2, figsize=(10, 6)) ax[0].loglog(rx.times, survey.dtrue, 'b.-') ax[0].loglog(rx.times, survey.dobs, 'r.-') ax[0].legend(('Noisefree', '$d^{obs}$'), fontsize=16) ax[0].set_xlabel('Time (s)', fontsize=14) ax[0].set_ylabel('$B_z$ (T)', fontsize=16) ax[0].set_xlabel('Time (s)', fontsize=14) ax[0].grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5) plt.semilogx(sigma[active], mesh.vectorCCz[active]) plt.semilogx(np.exp(mopt), mesh.vectorCCz[active]) ax[1].set_ylim(-600, 0) ax[1].set_xlim(1e-4, 1e-2) ax[1].set_xlabel('Conductivity (S/m)', fontsize=14) ax[1].set_ylabel('Depth (m)', fontsize=14) ax[1].grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5) plt.legend(['$\sigma_{true}$', '$\sigma_{pred}$'])
def halfSpaceProblemAnaDiff(meshType, srctype="MagDipole", sig_half=1e-2, rxOffset=50., bounds=None, plotIt=False): if bounds is None: bounds = [1e-5, 1e-3] if meshType == 'CYL': cs, ncx, ncz, npad = 5., 30, 10, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hz], '00C') elif meshType == 'TENSOR': cs, nc, npad = 20., 13, 5 hx = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, nc), (cs, npad, 1.3)] mesh = Mesh.TensorMesh([hx, hy, hz], 'CCC') active = mesh.vectorCCz < 0. actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap rx = EM.TDEM.Rx(np.array([[rxOffset, 0., 0.]]), np.logspace(-5, -4, 21), 'bz') if srctype == "MagDipole": src = EM.TDEM.Src.MagDipole([rx], waveform=EM.TDEM.Src.StepOffWaveform(), loc=np.array([0., 0., 0.])) elif srctype == "CircularLoop": src = EM.TDEM.Src.CircularLoop([rx], waveform=EM.TDEM.Src.StepOffWaveform(), loc=np.array([0., 0., 0.]), radius=0.1) survey = EM.TDEM.Survey([src]) prb = EM.TDEM.Problem3D_b(mesh, sigmaMap=mapping) prb.Solver = Solver prb.timeSteps = [(1e-06, 40), (5e-06, 40), (1e-05, 40), (5e-05, 40), (0.0001, 40), (0.0005, 40)] sigma = np.ones(mesh.nCz) * 1e-8 sigma[active] = sig_half sigma = np.log(sigma[active]) prb.pair(survey) if srctype == "MagDipole": bz_ana = mu_0 * EM.Analytics.hzAnalyticDipoleT(rx.locs[0][0] + 1e-3, rx.times, sig_half) elif srctype == "CircularLoop": bz_ana = mu_0 * EM.Analytics.hzAnalyticDipoleT(13, rx.times, sig_half) bz_calc = survey.dpred(sigma) ind = np.logical_and(rx.times > bounds[0], rx.times < bounds[1]) log10diff = (np.linalg.norm( np.log10(np.abs(bz_calc[ind])) - np.log10(np.abs(bz_ana[ind]))) / np.linalg.norm(np.log10(np.abs(bz_ana[ind])))) print(' |bz_ana| = {ana} |bz_num| = {num} |bz_ana-bz_num| = {diff}'.format( ana=np.linalg.norm(bz_ana), num=np.linalg.norm(bz_calc), diff=np.linalg.norm(bz_ana - bz_calc))) print('Difference: {}'.format(log10diff)) if plotIt is True: plt.loglog(rx.times[bz_calc > 0], bz_calc[bz_calc > 0], 'r', rx.times[bz_calc < 0], -bz_calc[bz_calc < 0], 'r--') plt.loglog(rx.times, abs(bz_ana), 'b*') plt.title('sig_half = {0:e}'.format(sig_half)) plt.show() return log10diff
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., 10., 10., 20 hx = [(cs, ncx), (cs, npad, 1.3)] npad = 12 temp = np.logspace(np.log10(1.), np.log10(12.), 19) temp_pad = temp[-1] * 1.3**np.arange(npad) hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad] mesh = Mesh.CylMesh([hx, 1, hz], '00C') active = mesh.vectorCCz < 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 std = 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, std=std, 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. / (d + 100.)**2. w = Utils.sdiag(1. / 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) 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() cb = plt.colorbar(out[0], ticks=np.linspace(vmin, 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": 10**vmin, "vmax": 10**vmax, "cmap": "viridis" }, ax=ax2) cb = plt.colorbar(out[0], ticks=np.linspace(vmin, 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, cleanup=True): """ Run 1D inversions for a single sounding of the RESOLVE and SkyTEM bookpurnong data :param bool plotIt: show the plots? :param bool saveFig: save the figure :param bool cleanup: remove the downloaded results """ downloads, directory = download_and_unzip_data() resolve = h5py.File( os.path.sep.join([directory, "booky_resolve.hdf5"]), "r" ) skytem = h5py.File( os.path.sep.join([directory, "booky_skytem.hdf5"]), "r" ) river_path = resolve["river_path"].value # Choose a sounding location to invert xloc, yloc = 462100.0, 6196500.0 rxind_skytem = np.argmin( abs(skytem["xy"][:, 0]-xloc)+abs(skytem["xy"][:, 1]-yloc) ) rxind_resolve = np.argmin( abs(resolve["xy"][:, 0]-xloc)+abs(resolve["xy"][:, 1]-yloc) ) # Plot both resolve and skytem data on 2D plane fig = plt.figure(figsize=(13, 6)) title = ["RESOLVE In-phase 400 Hz", "SkyTEM High moment 156 $\mu$s"] ax1 = plt.subplot(121) ax2 = plt.subplot(122) axs = [ax1, ax2] out_re = Utils.plot2Ddata( resolve["xy"], resolve["data"][:, 0], ncontour=100, contourOpts={"cmap": "viridis"}, ax=ax1 ) vmin, vmax = out_re[0].get_clim() cb_re = plt.colorbar( out_re[0], ticks=np.linspace(vmin, vmax, 3), ax=ax1, fraction=0.046, pad=0.04 ) temp_skytem = skytem["data"][:, 5].copy() temp_skytem[skytem["data"][:, 5] > 7e-10] = 7e-10 out_sky = Utils.plot2Ddata( skytem["xy"][:, :2], temp_skytem, ncontour=100, contourOpts={"cmap": "viridis", "vmax": 7e-10}, ax=ax2 ) vmin, vmax = out_sky[0].get_clim() cb_sky = plt.colorbar( out_sky[0], ticks=np.linspace(vmin, vmax*0.99, 3), ax=ax2, format="%.1e", fraction=0.046, pad=0.04 ) cb_re.set_label("Bz (ppm)") cb_sky.set_label("dB$_z$ / dt (V/A-m$^4$)") for i, ax in enumerate(axs): xticks = [460000, 463000] yticks = [6195000, 6198000, 6201000] ax.set_xticks(xticks) ax.set_yticks(yticks) ax.plot(xloc, yloc, 'wo') ax.plot(river_path[:, 0], river_path[:, 1], 'k', lw=0.5) ax.set_aspect("equal") if i == 1: ax.plot( skytem["xy"][:, 0], skytem["xy"][:, 1], 'k.', alpha=0.02, ms=1 ) ax.set_yticklabels([str(" ") for f in yticks]) else: ax.plot( resolve["xy"][:, 0], resolve["xy"][:, 1], 'k.', alpha=0.02, ms=1 ) ax.set_yticklabels([str(f) for f in yticks]) ax.set_ylabel("Northing (m)") ax.set_xlabel("Easting (m)") ax.set_title(title[i]) ax.axis('equal') # plt.tight_layout() if saveFig is True: fig.savefig("resolve_skytem_data.png", dpi=600) # ------------------ Mesh ------------------ # # Step1: Set 2D cylindrical mesh cs, ncx, ncz, npad = 1., 10., 10., 20 hx = [(cs, ncx), (cs, npad, 1.3)] npad = 12 temp = np.logspace(np.log10(1.), np.log10(12.), 19) temp_pad = temp[-1] * 1.3 ** np.arange(npad) hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad] mesh = Mesh.CylMesh([hx, 1, hz], '00C') active = mesh.vectorCCz < 0. # Step2: Set a SurjectVertical1D mapping # Note: this sets our inversion model as 1D log conductivity # below subsurface active = mesh.vectorCCz < 0. actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap sig_half = 1e-1 sig_air = 1e-8 sigma = np.ones(mesh.nCz)*sig_air sigma[active] = sig_half # Initial and reference model m0 = np.log(sigma[active]) # ------------------ RESOLVE Forward Simulation ------------------ # # Step3: Invert Resolve data # Bird height from the surface b_height_resolve = resolve["src_elevation"].value src_height_resolve = b_height_resolve[rxind_resolve] # Set Rx (In-phase and Quadrature) rxOffset = 7.86 bzr = EM.FDEM.Rx.Point_bSecondary( np.array([[rxOffset, 0., src_height_resolve]]), orientation='z', component='real' ) bzi = EM.FDEM.Rx.Point_b( np.array([[rxOffset, 0., src_height_resolve]]), orientation='z', component='imag' ) # Set Source (In-phase and Quadrature) frequency_cp = resolve["frequency_cp"].value freqs = frequency_cp.copy() srcLoc = np.array([0., 0., src_height_resolve]) srcList = [EM.FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation='Z') for freq in freqs] # Set FDEM survey (In-phase and Quadrature) survey = EM.FDEM.Survey(srcList) prb = EM.FDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=Solver) prb.pair(survey) # ------------------ RESOLVE Inversion ------------------ # # Primary field bp = - mu_0/(4*np.pi*rxOffset**3) # Observed data cpi_inds = [0, 2, 6, 8, 10] cpq_inds = [1, 3, 7, 9, 11] dobs_re = np.c_[ resolve["data"][rxind_resolve, :][cpi_inds], resolve["data"][rxind_resolve, :][cpq_inds] ].flatten() * bp * 1e-6 # Uncertainty std = np.repeat(np.r_[np.ones(3)*0.1, np.ones(2)*0.15], 2) floor = 20 * abs(bp) * 1e-6 uncert = abs(dobs_re) * std + floor # Data Misfit survey.dobs = dobs_re dmisfit = DataMisfit.l2_DataMisfit(survey) dmisfit.W = 1./uncert # Regularization regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Simple(regMesh) # Optimization opt = Optimization.InexactGaussNewton(maxIter=5) # statement of the inverse problem invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # Inversion directives and parameters target = Directives.TargetMisfit() # stop when we hit target misfit invProb.beta = 2. # betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0) inv = Inversion.BaseInversion(invProb, directiveList=[target]) reg.alpha_s = 1e-3 reg.alpha_x = 1. reg.mref = m0.copy() opt.LSshorten = 0.5 opt.remember('xc') # run the inversion mopt_re = inv.run(m0) dpred_re = invProb.dpred # ------------------ SkyTEM Forward Simulation ------------------ # # Step4: Invert SkyTEM data # Bird height from the surface b_height_skytem = skytem["src_elevation"].value src_height = b_height_skytem[rxind_skytem] srcLoc = np.array([[0., 0., src_height]]) # Radius of the source loop area = skytem["area"].value radius = np.sqrt(area/np.pi) rxLoc = np.array([[radius, 0., src_height]]) # Parameters for current waveform t0 = skytem["t0"].value times = skytem["times"].value waveform_skytem = skytem["waveform"].value offTime = t0 times_off = times - t0 # Note: we are Using theoretical VTEM waveform, # but effectively fits SkyTEM waveform peakTime = 1.0000000e-02 a = 3. dbdt_z = EM.TDEM.Rx.Point_dbdt( locs=rxLoc, times=times_off[:-3]+offTime, orientation='z' ) # vertical db_dt rxList = [dbdt_z] # list of receivers srcList = [ EM.TDEM.Src.CircularLoop( rxList, loc=srcLoc, radius=radius, orientation='z', waveform=EM.TDEM.Src.VTEMWaveform( offTime=offTime, peakTime=peakTime, a=3. ) ) ] # solve the problem at these times timeSteps = [ (peakTime/5, 5), ((offTime-peakTime)/5, 5), (1e-5, 5), (5e-5, 5), (1e-4, 10), (5e-4, 15) ] prob = EM.TDEM.Problem3D_e( mesh, timeSteps=timeSteps, sigmaMap=mapping, Solver=Solver ) survey = EM.TDEM.Survey(srcList) prob.pair(survey) src = srcList[0] rx = src.rxList[0] wave = [] for time in prob.times: wave.append(src.waveform.eval(time)) wave = np.hstack(wave) out = survey.dpred(m0) # plot the waveform fig = plt.figure(figsize=(5, 3)) times_off = times-t0 plt.plot(waveform_skytem[:, 0], waveform_skytem[:, 1], 'k.') plt.plot(prob.times, wave, 'k-', lw=2) plt.legend(("SkyTEM waveform", "Waveform (fit)"), fontsize=10) for t in rx.times: plt.plot(np.ones(2)*t, np.r_[-0.03, 0.03], 'k-') plt.ylim(-0.1, 1.1) plt.grid(True) plt.xlabel("Time (s)") plt.ylabel("Normalized current") if saveFig: fig.savefig("skytem_waveform", dpi=200) # Observed data dobs_sky = skytem["data"][rxind_skytem, :-3] * area # ------------------ SkyTEM Inversion ------------------ # # Uncertainty std = 0.12 floor = 7.5e-12 uncert = abs(dobs_sky) * std + floor # Data Misfit survey.dobs = -dobs_sky dmisfit = DataMisfit.l2_DataMisfit(survey) uncert = 0.12*abs(dobs_sky) + 7.5e-12 dmisfit.W = Utils.sdiag(1./uncert) # Regularization regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Simple(regMesh) # Optimization opt = Optimization.InexactGaussNewton(maxIter=5) # statement of the inverse problem invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # Directives and Inversion Parameters target = Directives.TargetMisfit() # betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0) invProb.beta = 20. inv = Inversion.BaseInversion(invProb, directiveList=[target]) reg.alpha_s = 1e-1 reg.alpha_x = 1. opt.LSshorten = 0.5 opt.remember('xc') reg.mref = mopt_re # Use RESOLVE model as a reference model # run the inversion mopt_sky = inv.run(m0) dpred_sky = invProb.dpred # Plot the figure from the paper plt.figure(figsize=(12, 8)) fs = 13 # fontsize matplotlib.rcParams['font.size'] = fs ax0 = plt.subplot2grid((2, 2), (0, 0), rowspan=2) ax1 = plt.subplot2grid((2, 2), (0, 1)) ax2 = plt.subplot2grid((2, 2), (1, 1)) # Recovered Models sigma_re = np.repeat(np.exp(mopt_re), 2, axis=0) sigma_sky = np.repeat(np.exp(mopt_sky), 2, axis=0) z = np.repeat(mesh.vectorCCz[active][1:], 2, axis=0) z = np.r_[mesh.vectorCCz[active][0], z, mesh.vectorCCz[active][-1]] ax0.semilogx(sigma_re, z, 'k', lw=2, label="RESOLVE") ax0.semilogx(sigma_sky, z, 'b', lw=2, label="SkyTEM") ax0.set_ylim(-50, 0) # ax0.set_xlim(5e-4, 1e2) ax0.grid(True) ax0.set_ylabel("Depth (m)") ax0.set_xlabel("Conducivity (S/m)") ax0.legend(loc=3) ax0.set_title("(a) Recovered Models") # RESOLVE Data ax1.loglog( frequency_cp, dobs_re.reshape((5, 2))[:, 0]/bp*1e6, 'k-', label="Obs (real)" ) ax1.loglog( frequency_cp, dobs_re.reshape((5, 2))[:, 1]/bp*1e6, 'k--', label="Obs (imag)" ) ax1.loglog( frequency_cp, dpred_re.reshape((5, 2))[:, 0]/bp*1e6, 'k+', ms=10, markeredgewidth=2., label="Pred (real)" ) ax1.loglog( frequency_cp, dpred_re.reshape((5, 2))[:, 1]/bp*1e6, 'ko', ms=6, markeredgecolor='k', markeredgewidth=0.5, label="Pred (imag)" ) ax1.set_title("(b) RESOLVE") ax1.set_xlabel("Frequency (Hz)") ax1.set_ylabel("Bz (ppm)") ax1.grid(True) ax1.legend(loc=3, fontsize=11) # SkyTEM data ax2.loglog(times_off[3:]*1e6, dobs_sky/area, 'b-', label="Obs") ax2.loglog( times_off[3:]*1e6, -dpred_sky/area, 'bo', ms=4, markeredgecolor='k', markeredgewidth=0.5, label="Pred" ) ax2.set_xlim(times_off.min()*1e6*1.2, times_off.max()*1e6*1.1) ax2.set_xlabel("Time ($\mu s$)") ax2.set_ylabel("dBz / dt (V/A-m$^4$)") ax2.set_title("(c) SkyTEM High-moment") ax2.grid(True) ax2.legend(loc=3) a3 = plt.axes([0.86, .33, .1, .09], facecolor=[0.8, 0.8, 0.8, 0.6]) a3.plot(prob.times*1e6, wave, 'k-') a3.plot( rx.times*1e6, np.zeros_like(rx.times), 'k|', markeredgewidth=1, markersize=12 ) a3.set_xlim([prob.times.min()*1e6*0.75, prob.times.max()*1e6*1.1]) a3.set_title('(d) Waveform', fontsize=11) a3.set_xticks([prob.times.min()*1e6, t0*1e6, prob.times.max()*1e6]) a3.set_yticks([]) # a3.set_xticklabels(['0', '2e4']) a3.set_xticklabels(['-1e4', '0', '1e4']) plt.tight_layout() if saveFig: plt.savefig("booky1D_time_freq.png", dpi=600) if plotIt: plt.show() if cleanup: print( os.path.split(directory)[:-1]) os.remove( os.path.sep.join( directory.split()[:-1] + ["._bookpurnong_inversion"] ) ) os.remove(downloads) shutil.rmtree(directory)