def MfRhoIDeriv(self, u, v, adjoint=False): """ Derivative of :code:`MfRhoI` with respect to the model. """ dMfRhoI_dI = -self.MfRhoI**2 if self.storeInnerProduct: if adjoint: return ( self.MfRhoDerivMat.T * ( Utils.sdiag(u) * (dMfRhoI_dI.T * v) ) ) else: return dMfRhoI_dI * (Utils.sdiag(u) * (self.MfRhoDerivMat*v)) else: if self.storeJ: drho_dlogrho = Utils.sdiag(self.rho)*self.actMap.P else: drho_dlogrho = Utils.sdiag(self.rho) dMf_drho = self.mesh.getFaceInnerProductDeriv(self.rho)(u) if adjoint: return drho_dlogrho.T * (dMf_drho.T * (dMfRhoI_dI.T*v)) else: return dMfRhoI_dI * (dMf_drho * (drho_dlogrho*v))
def MeSigmaDeriv(self, u, v, adjoint=False): """ Derivative of MeSigma with respect to the model times a vector (u) """ if self.storeInnerProduct: if adjoint: return self.MeSigmaDerivMat.T * (Utils.sdiag(u)*v) else: return Utils.sdiag(u)*(self.MeSigmaDerivMat * v) else: if self.storeJ: dsigma_dlogsigma = Utils.sdiag(self.sigma)*self.actMap.P else: dsigma_dlogsigma = Utils.sdiag(self.sigma) if adjoint: return ( dsigma_dlogsigma.T * ( self.mesh.getEdgeInnerProductDeriv(self.sigma)(u).T * v ) ) else: return ( self.mesh.getEdgeInnerProductDeriv(self.sigma)(u) * (dsigma_dlogsigma * v) )
def Wd(self): """getWd(survey) The data weighting matrix. The default is based on the norm of the data plus a noise floor. :rtype: scipy.sparse.csr_matrix :return: Wd """ if getattr(self, '_Wd', None) is None: survey = self.survey if getattr(survey,'std', None) is None: print('SimPEG.DataMisfit.l2_DataMisfit assigning default std of 5%') survey.std = 0.05 if getattr(survey, 'eps', None) is None: print('SimPEG.DataMisfit.l2_DataMisfit assigning default eps of 1e-5 * ||dobs||') survey.eps = np.linalg.norm(Utils.mkvc(survey.dobs),2)*1e-5 self._Wd = Utils.sdiag(1/(abs(survey.dobs)*survey.std+survey.eps)) return self._Wd
def getInterpolationMatCartMesh(self, Mrect, locType="CC", locTypeTo=None): """ Takes a cartesian mesh and returns a projection to translate onto the cartesian grid. """ assert self.isSymmetric, ( "Currently we have not taken into account " "other projections for more complicated " "CylMeshes" ) if locTypeTo is None: locTypeTo = locType if locType == "F": # do this three times for each component X = self.getInterpolationMatCartMesh(Mrect, locType="Fx", locTypeTo=locTypeTo + "x") Y = self.getInterpolationMatCartMesh(Mrect, locType="Fy", locTypeTo=locTypeTo + "y") Z = self.getInterpolationMatCartMesh(Mrect, locType="Fz", locTypeTo=locTypeTo + "z") return sp.vstack((X, Y, Z)) if locType == "E": X = self.getInterpolationMatCartMesh(Mrect, locType="Ex", locTypeTo=locTypeTo + "x") Y = self.getInterpolationMatCartMesh(Mrect, locType="Ey", locTypeTo=locTypeTo + "y") Z = Utils.spzeros(getattr(Mrect, "n" + locTypeTo + "z"), self.nE) return sp.vstack((X, Y, Z)) grid = getattr(Mrect, "grid" + locTypeTo) # This is unit circle stuff, 0 to 2*pi, starting at x-axis, rotating # counter clockwise in an x-y slice theta = -np.arctan2(grid[:, 0] - self.cartesianOrigin[0], grid[:, 1] - self.cartesianOrigin[1]) + np.pi / 2 theta[theta < 0] += np.pi * 2.0 r = ((grid[:, 0] - self.cartesianOrigin[0]) ** 2 + (grid[:, 1] - self.cartesianOrigin[1]) ** 2) ** 0.5 if locType in ["CC", "N", "Fz", "Ez"]: G, proj = np.c_[r, theta, grid[:, 2]], np.ones(r.size) else: dotMe = { "Fx": Mrect.normals[: Mrect.nFx, :], "Fy": Mrect.normals[Mrect.nFx : (Mrect.nFx + Mrect.nFy), :], "Fz": Mrect.normals[-Mrect.nFz :, :], "Ex": Mrect.tangents[: Mrect.nEx, :], "Ey": Mrect.tangents[Mrect.nEx : (Mrect.nEx + Mrect.nEy), :], "Ez": Mrect.tangents[-Mrect.nEz :, :], }[locTypeTo] if "F" in locType: normals = np.c_[np.cos(theta), np.sin(theta), np.zeros(theta.size)] proj = (normals * dotMe).sum(axis=1) if "E" in locType: tangents = np.c_[-np.sin(theta), np.cos(theta), np.zeros(theta.size)] proj = (tangents * dotMe).sum(axis=1) G = np.c_[r, theta, grid[:, 2]] interpType = locType if interpType == "Fy": interpType = "Fx" elif interpType == "Ex": interpType = "Ey" Pc2r = self.getInterpolationMat(G, interpType) Proj = Utils.sdiag(proj) return Proj * Pc2r
def setUp(self): cs = 25. hx = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)] hy = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)] hz = [(cs,7, -1.3),(cs,20)] mesh = Mesh.TensorMesh([hx, hy, hz],x0="CCN") sigma = np.ones(mesh.nC)*1e-2 x = mesh.vectorCCx[(mesh.vectorCCx>-155.)&(mesh.vectorCCx<155.)] y = mesh.vectorCCx[(mesh.vectorCCy>-155.)&(mesh.vectorCCy<155.)] Aloc = np.r_[-200., 0., 0.] Bloc = np.r_[200., 0., 0.] M = Utils.ndgrid(x-25.,y, np.r_[0.]) N = Utils.ndgrid(x+25.,y, np.r_[0.]) phiA = EM.Analytics.DCAnalyticHalf(Aloc, [M,N], 1e-2, earth_type="halfspace") phiB = EM.Analytics.DCAnalyticHalf(Bloc, [M,N], 1e-2, earth_type="halfspace") data_anal = phiA-phiB rx = DC.Rx.Dipole(M, N) src = DC.Src.Dipole([rx], Aloc, Bloc) survey = DC.Survey([src]) self.survey = survey self.mesh = mesh self.sigma = sigma self.data_anal = data_anal try: from pymatsolver import PardisoSolver self.Solver = PardisoSolver except ImportError: self.Solver = SolverLU
def test_regularizationMesh(self): for i, mesh in enumerate(self.meshlist): print('Testing {0:d}D'.format(mesh.dim)) # mapping = r.mapPair(mesh) # reg = r(mesh, mapping=mapping) # m = np.random.rand(mapping.nP) if mesh.dim == 1: indAct = Utils.mkvc(mesh.gridCC <= 0.8) elif mesh.dim == 2: indAct = ( Utils.mkvc( mesh.gridCC[:,-1] <= 2*np.sin(2*np.pi*mesh.gridCC[:, 0]) + 0.5 ) ) elif mesh.dim == 3: indAct = ( Utils.mkvc( mesh.gridCC[:, -1] <= 2*np.sin(2*np.pi*mesh.gridCC[:, 0]) + 0.5 * 2*np.sin(2*np.pi*mesh.gridCC[:, 1]) + 0.5 ) ) regmesh = Regularization.RegularizationMesh( mesh, indActive=indAct ) assert (regmesh.vol == mesh.vol[indAct]).all()
def meshs(self): if getattr(self, '_meshs', None) is None: csx, ncx, npadx = 50, 21, 12 csy, ncy, npady = 50, 21, 12 csz, ncz, npadz = 25, 40, 14 pf = 1.5 hx = Utils.meshTensor( [(csx, npadx, -pf), (csx, ncx), (csx, npadx, pf)] ) hy = Utils.meshTensor( [(csy, npady, -pf), (csy, ncy), (csy, npady, pf)] ) hz = Utils.meshTensor( [(csz, npadz, -pf), (csz, ncz), (csz, npadz, pf)] ) x0 = np.r_[-hx.sum()/2., -hy.sum()/2., -hz[:npadz+ncz].sum()] self._meshs = Mesh.TensorMesh([hx, hy, hz], x0=x0) print('Secondary Mesh ... ') print( ' xmin, xmax, zmin, zmax: ', self._meshs.vectorCCx.min(), self._meshs.vectorCCx.max(), self._meshs.vectorCCy.min(), self._meshs.vectorCCy.max(), self._meshs.vectorCCz.min(), self._meshs.vectorCCz.max() ) print(' nC, vnC', self._meshs.nC, self._meshs.vnC) return self._meshs
def __init__(self, rxList, freq, loc, orientation="Z", moment=1.0, mu=mu_0, **kwargs): self.freq = float(freq) self.loc = loc if isinstance(orientation, str): assert orientation.upper() in ["X", "Y", "Z"], ( "orientation must " "be in 'X', 'Y', " "'Z' not {}".format(orientation) ) orientation = orientationDict[orientation.upper()] elif ( np.linalg.norm(orientation - np.r_[1.0, 0.0, 0.0]) > 1e-6 or np.linalg.norm(orientation - np.r_[0.0, 1.0, 0.0]) > 1e-6 or np.linalg.norm(orientation - np.r_[0.0, 0.0, 1.0]) > 1e-6 ): warnings.warn( "Using orientations that are not in aligned with" " the mesh axes is not thoroughly tested. PR on " "a test??" ) assert np.linalg.norm(orientation) == 1.0, "Orientation must have unit" " length, not {}".format( np.linalg.norm(orientation) ) self.orientation = orientation self.moment = moment self.mu = mu Utils.setKwargs(self, **kwargs) BaseSrc.__init__(self, rxList)
def evalDeriv(self, f, freq, P0, df_dm_v=None, v=None, adjoint=False): if adjoint: if self.component == "real": PTvr = (P0.T*v).astype(complex) dZr_dfT_v = Utils.sdiag((1./(f**2)))*PTvr return dZr_dfT_v elif self.component == "imag": PTvi = P0.T*v*-1j dZi_dfT_v = Utils.sdiag((1./(f**2)))*PTvi return dZi_dfT_v elif self.component == "both": PTvr = (P0.T*np.r_[v[0]]).astype(complex) PTvi = P0.T*np.r_[v[1]]*-1j dZr_dfT_v = Utils.sdiag((1./(f**2)))*PTvr dZi_dfT_v = Utils.sdiag((1./(f**2)))*PTvi return dZr_dfT_v + dZi_dfT_v else: raise NotImplementedError('must be real, imag or both') else: dZd_dm_v = P0 * (Utils.sdiag(1./(f**2)) * df_dm_v) if self.component == "real": return dZd_dm_v.real elif self.component == "imag": return dZd_dm_v.imag elif self.component == "both": return np.r_[dZd_dm_v.real, dZd_dm_v.imag] else: raise NotImplementedError('must be real, imag or both')
def test_getInterpMatCartMesh_Edges2Faces(self): Mr = Mesh.TensorMesh([100,100,2], x0='CC0') Mc = Mesh.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_regularization_ActiveCells(self): for R in dir(Regularization): r = getattr(Regularization, R) if not inspect.isclass(r): continue if not issubclass(r, Regularization.BaseRegularization): continue for i, mesh in enumerate(self.meshlist): print('Testing Active Cells {0:d}D'.format((mesh.dim))) if mesh.dim == 1: indActive = Utils.mkvc(mesh.gridCC <= 0.8) elif mesh.dim == 2: indActive = Utils.mkvc(mesh.gridCC[:,-1] <= 2*np.sin(2*np.pi*mesh.gridCC[:,0])+0.5) elif mesh.dim == 3: indActive = Utils.mkvc(mesh.gridCC[:,-1] <= 2*np.sin(2*np.pi*mesh.gridCC[:,0])+0.5 * 2*np.sin(2*np.pi*mesh.gridCC[:,1])+0.5) for indAct in [indActive, indActive.nonzero()[0]]: # test both bool and integers reg = r(mesh, indActive=indAct) m = np.random.rand(mesh.nC)[indAct] reg.mref = np.ones_like(m)*np.mean(m) print('Check: phi_m (mref) = {0:f}'.format(reg.eval(reg.mref))) passed = reg.eval(reg.mref) < TOL self.assertTrue(passed) print('Check:', R) passed = Tests.checkDerivative(lambda m : [reg.eval(m), reg.evalDeriv(m)], m, plotIt=False) self.assertTrue(passed) print('Check 2 Deriv:', R) passed = Tests.checkDerivative(lambda m : [reg.evalDeriv(m), reg.eval2Deriv(m)], m, plotIt=False) self.assertTrue(passed)
def test_getInterpMatCartMesh_Faces2Edges(self): Mr = Mesh.TensorMesh([100,100,2], x0='CC0') Mc = Mesh.CylMesh([np.ones(10)/5,1,10],x0='0C0',cartesianOrigin=[-0.2,-0.2,0]) 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_getInterpMatCartMesh_Faces(self): Mr = Mesh.TensorMesh([100,100,2], x0='CC0') Mc = Mesh.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): cs = 12.5 hx = [(cs, 7, -1.3), (cs, 61), (cs, 7, 1.3)] hy = [(cs, 7, -1.3), (cs, 20)] mesh = Mesh.TensorMesh([hx, hy], x0="CN") sighalf = 1e-2 sigma = np.ones(mesh.nC)*sighalf x = np.linspace(0, 250., 20) M = Utils.ndgrid(x-12.5, np.r_[0.]) N = Utils.ndgrid(x+12.5, np.r_[0.]) A0loc = np.r_[-150, 0.] A1loc = np.r_[-125, 0.] rxloc = np.c_[M, np.zeros(20)] data_ana = EM.Analytics.DCAnalytic_Dipole_Pole( [np.r_[A0loc, 0.], np.r_[A1loc, 0.]], rxloc, sighalf, earth_type="halfspace") rx = DC.Rx.Pole_ky(M) src0 = DC.Src.Dipole([rx], A0loc, A1loc) survey = DC.Survey_ky([src0]) self.survey = survey self.mesh = mesh self.sigma = sigma self.data_ana = data_ana self.plotIt = False try: from pymatsolver import PardisoSolver self.Solver = PardisoSolver except ImportError: self.Solver = SolverLU
def test_updateMultipliers(self): nP = 10 m = np.random.rand(nP) W1 = Utils.sdiag(np.random.rand(nP)) W2 = Utils.sdiag(np.random.rand(nP)) phi1 = ObjectiveFunction.L2ObjectiveFunction(W=W1) phi2 = ObjectiveFunction.L2ObjectiveFunction(W=W2) phi = phi1 + phi2 self.assertTrue(phi(m) == phi1(m) + phi2(m)) phi.multipliers[0] = Utils.Zero() self.assertTrue(phi(m) == phi2(m)) phi.multipliers[0] = 1. phi.multipliers[1] = Utils.Zero() self.assertTrue(len(phi.objfcts) == 2) self.assertTrue(len(phi.multipliers) == 2) self.assertTrue(len(phi) == 2) self.assertTrue(phi(m) == phi1(m))
def drapeTopotoLoc(mesh, pts, actind=None, option="top", topo=None): """ Drape location right below (cell center) the topography """ if mesh.dim == 2: if pts.ndim > 1: raise Exception("pts should be 1d array") elif mesh.dim == 3: if pts.shape[1] == 3: raise Exception("shape of pts should be (x,3)") else: raise NotImplementedError() if actind is None: actind = Utils.surface2ind_topo(mesh, topo) if mesh._meshType == "TENSOR": meshtemp, topoCC = gettopoCC(mesh, actind, option=option) inds = Utils.closestPoints(meshtemp, pts) elif mesh._meshType == "TREE": if mesh.dim == 3: uniqXYlocs, topoCC = gettopoCC(mesh, actind, option=option) inds = closestPointsGrid(uniqXYlocs, pts) else: raise NotImplementedError() else: raise NotImplementedError() out = np.c_[pts, topoCC[inds]] return out
def forward(self, m, f=None): if f is None: f = self.fields(m) self.curModel = m Jv = self.dataPair(self.survey) #same size as the data # A = self.getA() JvAll = [] for tind in range(len(self.survey.times)): #Pseudo-chareability t = self.survey.times[tind] v = self.DebyeTime(t) for src in self.survey.srcList: u_src = f[src, self._solutionType] # solution vector dA_dm_v = self.getADeriv(u_src, v) dRHS_dm_v = self.getRHSDeriv(src, v) du_dm_v = self.Ainv * ( - dA_dm_v + dRHS_dm_v ) for rx in src.rxList: timeindex = rx.getTimeP(self.survey.times) if timeindex[tind]: df_dmFun = getattr(f, '_{0!s}Deriv'.format(rx.projField), None) df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False) Jv[src, rx, t] = rx.evalDeriv(src, self.mesh, f, df_dm_v) # Conductivity (d u / d log sigma) if self._formulation is 'EB': return -Utils.mkvc(Jv) # Resistivity (d u / d log rho) if self._formulation is 'HJ': return Utils.mkvc(Jv)
def Jfull(self, m=None, f=None): if f is None: f = self.fields(m) nn = len(f)-1 Asubs, Adiags, Bs = list(range(nn)), list(range(nn)), list(range(nn)) for ii in range(nn): dt = self.timeSteps[ii] bc = self.getBoundaryConditions(ii, f[ii]) Asubs[ii], Adiags[ii], Bs[ii] = self.diagsJacobian( m, f[ii], f[ii+1], dt, bc ) Ad = sp.block_diag(Adiags) zRight = Utils.spzeros( (len(Asubs)-1)*Asubs[0].shape[0], Adiags[0].shape[1] ) zTop = Utils.spzeros( Adiags[0].shape[0], len(Adiags)*Adiags[0].shape[1] ) As = sp.vstack((zTop, sp.hstack((sp.block_diag(Asubs[1:]), zRight)))) A = As + Ad B = np.array(sp.vstack(Bs).todense()) Ainv = self.Solver(A, **self.solverOpts) AinvB = Ainv * B z = np.zeros((self.mesh.nC, B.shape[1])) du_dm = np.vstack((z, AinvB)) J = self.survey.deriv(f, du_dm_v=du_dm) # not multiplied by v return J
def Jvec(self, m, v, f=None): if f is None: f = self.fields(m) self.curModel = m Jv = self.dataPair(self.survey) #same size as the data A = self.getA() for src in self.survey.srcList: u_src = f[src, self._solutionType] # solution vector dA_dm_v = self.getADeriv(u_src, v) dRHS_dm_v = self.getRHSDeriv(src, v) du_dm_v = self.Ainv * ( - dA_dm_v + dRHS_dm_v ) for rx in src.rxList: df_dmFun = getattr(f, '_{0!s}Deriv'.format(rx.projField), None) df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False) Jv[src, rx] = rx.evalDeriv(src, self.mesh, f, df_dm_v) # Conductivity (d u / d log sigma) if self._formulation is 'EB': return -Utils.mkvc(Jv) # Conductivity (d u / d log rho) if self._formulation is 'HJ': return Utils.mkvc(Jv)
def setUp(self): cs = 25. hx = [(cs, 7, -1.3), (cs, 21), (cs, 7, 1.3)] hy = [(cs, 7, -1.3), (cs, 21), (cs, 7, 1.3)] hz = [(cs, 7, -1.3), (cs, 20), (cs, 7, -1.3)] mesh = Mesh.TensorMesh([hx, hy, hz], x0="CCC") sigma = np.ones(mesh.nC)*1e-2 x = mesh.vectorCCx[(mesh.vectorCCx > -155.) & (mesh.vectorCCx < 155.)] y = mesh.vectorCCx[(mesh.vectorCCy > -155.) & (mesh.vectorCCy < 155.)] Aloc = np.r_[-200., 0., 0.] Bloc = np.r_[200., 0., 0.] M = Utils.ndgrid(x-25., y, np.r_[0.]) N = Utils.ndgrid(x+25., y, np.r_[0.]) phiA = EM.Analytics.DCAnalytic_Pole_Dipole( Aloc, [M, N], 1e-2, earth_type="wholespace" ) phiB = EM.Analytics.DCAnalytic_Pole_Dipole( Bloc, [M, N], 1e-2, earth_type="wholespace" ) data_anal = phiA-phiB rx = DC.Rx.Dipole(M, N) src = DC.Src.Dipole([rx], Aloc, Bloc) survey = DC.Survey([src]) self.survey = survey self.mesh = mesh self.sigma = sigma self.data_anal = data_anal
def Jtvec(self, m, v, f=None): if f is None: f = self.fields(m) self.model = m # Ensure v is a data object. if not isinstance(v, self.dataPair): v = self.dataPair(self.survey, v) Jtv = np.zeros(m.size) AT = self.getA() for src in self.survey.srcList: u_src = f[src, self._solutionType] for rx in src.rxList: PTv = rx.evalDeriv(src, self.mesh, f, v[src, rx], adjoint=True) # wrt f, need possibility wrt m df_duTFun = getattr(f, '_{0!s}Deriv'.format(rx.projField), None) df_duT, df_dmT = df_duTFun(src, None, PTv, adjoint=True) ATinvdf_duT = self.Ainv * df_duT dA_dmT = self.getADeriv(u_src, ATinvdf_duT, adjoint=True) dRHS_dmT = self.getRHSDeriv(src, ATinvdf_duT, adjoint=True) du_dmT = -dA_dmT + dRHS_dmT Jtv += (df_dmT + du_dmT).astype(float) # Conductivity ((d u / d log sigma).T) if self._formulation == 'EB': return -Utils.mkvc(Jtv) # Conductivity ((d u / d log rho).T) if self._formulation == 'HJ': return Utils.mkvc(Jtv)
def setUp(self): cs = 12.5 npad = 2 hx = [(cs, npad, -1.3), (cs, 21), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, 21), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, 20)] mesh = Mesh.TensorMesh([hx, hy, hz], x0="CCN") x = mesh.vectorCCx[(mesh.vectorCCx > -80.) & (mesh.vectorCCx < 80.)] y = mesh.vectorCCx[(mesh.vectorCCy > -80.) & (mesh.vectorCCy < 80.)] Aloc = np.r_[-100., 0., 0.] Bloc = np.r_[100., 0., 0.] M = Utils.ndgrid(x-12.5, y, np.r_[0.]) N = Utils.ndgrid(x+12.5, y, np.r_[0.]) radius = 50. xc = np.r_[0., 0., -100] blkind = Utils.ModelBuilder.getIndicesSphere(xc, radius, mesh.gridCC) sigmaInf = np.ones(mesh.nC)*1e-2 eta = np.zeros(mesh.nC) eta[blkind] = 0.1 sigma0 = sigmaInf*(1.-eta) rx = DC.Rx.Dipole(M, N) src = DC.Src.Dipole([rx], Aloc, Bloc) surveyDC = DC.Survey([src]) self.surveyDC = surveyDC self.mesh = mesh self.sigmaInf = sigmaInf self.sigma0 = sigma0 self.src = src self.eta = eta
def run(plotIt=True): M = Mesh.TensorMesh([100, 100]) h1 = Utils.meshTensor([(6, 7, -1.5), (6, 10), (6, 7, 1.5)]) h1 = h1/h1.sum() M2 = Mesh.TensorMesh([h1, h1]) V = Utils.ModelBuilder.randomModel(M.vnC, seed=79, its=50) v = Utils.mkvc(V) modh = Maps.Mesh2Mesh([M, M2]) modH = Maps.Mesh2Mesh([M2, M]) H = modH * v h = modh * H if not plotIt: return ax = plt.subplot(131) M.plotImage(v, ax=ax) ax.set_title('Fine Mesh (Original)') ax = plt.subplot(132) M2.plotImage(H, clim=[0, 1], ax=ax) ax.set_title('Course Mesh') ax = plt.subplot(133) M.plotImage(h, clim=[0, 1], ax=ax) ax.set_title('Fine Mesh (Interpolated)')
def test_ana_forward(self): survey = PF.BaseMag.BaseMagSurvey() Inc = 45.0 Dec = 45.0 Btot = 51000 b0 = PF.MagAnalytics.IDTtoxyz(Inc, Dec, Btot) survey.setBackgroundField(Inc, Dec, Btot) xr = np.linspace(-300, 300, 41) yr = np.linspace(-300, 300, 41) X, Y = np.meshgrid(xr, yr) Z = np.ones((xr.size, yr.size)) * 150 rxLoc = np.c_[Utils.mkvc(X), Utils.mkvc(Y), Utils.mkvc(Z)] survey.rxLoc = rxLoc self.prob.pair(survey) u = self.prob.fields(self.chi) B = u["B"] bxa, bya, bza = PF.MagAnalytics.MagSphereAnaFunA( rxLoc[:, 0], rxLoc[:, 1], rxLoc[:, 2], 100.0, 0.0, 0.0, 0.0, 0.01, b0, "secondary" ) dpred = survey.projectFieldsAsVector(B) err = np.linalg.norm(dpred - np.r_[bxa, bya, bza]) / np.linalg.norm(np.r_[bxa, bya, bza]) self.assertTrue(err < 0.08)
def set_ij_height(self): """ Compute (I, J) indicies to form sparse sensitivity matrix This will be used in GlobalEM1DProblem when after sensitivity matrix for each sounding is computed """ I = [] J = [] shift_for_J = 0 shift_for_I = 0 m = self.n_layer for i in range(n_sounding): n = self.nD_vec[i] J_temp = np.tile(np.arange(m), (n, 1)) + shift_for_J I_temp = ( np.tile(np.arange(n), (1, m)).reshape((n, m), order='F') + shift_for_I ) J.append(Utils.mkvc(J_temp)) I.append(Utils.mkvc(I_temp)) shift_for_J += m shift_for_I = I_temp[-1, -1] + 1 J = np.hstack(J).astype(int) I = np.hstack(I).astype(int) return (I, J)
def setUp(self): cs = 25. hx = [(cs, 0, -1.3), (cs, 21), (cs, 0, 1.3)] hy = [(cs, 0, -1.3), (cs, 21), (cs, 0, 1.3)] hz = [(cs, 0, -1.3), (cs, 20)] mesh = Mesh.TensorMesh([hx, hy, hz], x0="CCN") blkind0 = Utils.ModelBuilder.getIndicesSphere( np.r_[-100., -100., -200.], 75., mesh.gridCC ) blkind1 = Utils.ModelBuilder.getIndicesSphere( np.r_[100., 100., -200.], 75., mesh.gridCC ) sigma = np.ones(mesh.nC)*1e-2 eta = np.zeros(mesh.nC) tau = np.ones_like(sigma)*1. eta[blkind0] = 0.1 eta[blkind1] = 0.1 tau[blkind0] = 0.1 tau[blkind1] = 0.01 x = mesh.vectorCCx[(mesh.vectorCCx > -155.) & (mesh.vectorCCx < 155.)] y = mesh.vectorCCx[(mesh.vectorCCy > -155.) & (mesh.vectorCCy < 155.)] Aloc = np.r_[-200., 0., 0.] Bloc = np.r_[200., 0., 0.] M = Utils.ndgrid(x-25., y, np.r_[0.]) N = Utils.ndgrid(x+25., y, np.r_[0.]) times = np.arange(10)*1e-3 + 1e-3 rx = SIP.Rx.Dipole(M, N, times) src = SIP.Src.Dipole([rx], Aloc, Bloc) survey = SIP.Survey([src]) wires = Maps.Wires(('eta', mesh.nC), ('taui', mesh.nC)) problem = SIP.Problem3D_N( mesh, sigma=sigma, etaMap=wires.eta, tauiMap=wires.taui ) problem.Solver = Solver problem.pair(survey) mSynth = np.r_[eta, 1./tau] survey.makeSyntheticData(mSynth) # Now set up the problem to do some minimization dmis = DataMisfit.l2_DataMisfit(survey) reg = Regularization.Tikhonov(mesh) opt = Optimization.InexactGaussNewton( maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6 ) invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=1e4) inv = Inversion.BaseInversion(invProb) self.inv = inv self.reg = reg self.p = problem self.mesh = mesh self.m0 = mSynth self.survey = survey self.dmis = dmis
def setUp(self): cs = 12.5 hx = [(cs,7, -1.3),(cs,61),(cs,7, 1.3)] hy = [(cs,7, -1.3),(cs,20)] mesh = Mesh.TensorMesh([hx, hy],x0="CN") sighalf = 1e-2 sigma = np.ones(mesh.nC)*sighalf x = np.linspace(-135, 250., 20) M = Utils.ndgrid(x-12.5, np.r_[0.]) N = Utils.ndgrid(x+12.5, np.r_[0.]) A0loc = np.r_[-150, 0.] A1loc = np.r_[-130, 0.] rxloc = [np.c_[M, np.zeros(20)], np.c_[N, np.zeros(20)]] data_anal = EM.Analytics.DCAnalyticHalf(np.r_[A0loc, 0.], rxloc, sighalf, earth_type="halfspace") rx = DC.Rx.Dipole_ky(M, N) src0 = DC.Src.Pole([rx], A0loc) survey = DC.Survey_ky([src0]) self.survey = survey self.mesh = mesh self.sigma = sigma self.data_anal = data_anal try: from pymatsolver import MumpsSolver self.Solver = MumpsSolver except ImportError, e: self.Solver = SolverLU
def __init__(self, h_in, x0_in=None): assert type(h_in) in [list, tuple], 'h_in must be a list' assert len(h_in) in [1,2,3], 'h_in must be of dimension 1, 2, or 3' h = range(len(h_in)) for i, h_i in enumerate(h_in): if Utils.isScalar(h_i) and type(h_i) is not np.ndarray: # This gives you something over the unit cube. h_i = self._unitDimensions[i] * np.ones(int(h_i))/int(h_i) elif type(h_i) is list: h_i = Utils.meshTensor(h_i) assert isinstance(h_i, np.ndarray), ("h[%i] is not a numpy array." % i) assert len(h_i.shape) == 1, ("h[%i] must be a 1D numpy array." % i) h[i] = h_i[:] # make a copy. x0 = np.zeros(len(h)) if x0_in is not None: assert len(h) == len(x0_in), "Dimension mismatch. x0 != len(h)" for i in range(len(h)): x_i, h_i = x0_in[i], h[i] if Utils.isScalar(x_i): x0[i] = x_i elif x_i == '0': x0[i] = 0.0 elif x_i == 'C': x0[i] = -h_i.sum()*0.5 elif x_i == 'N': x0[i] = -h_i.sum() else: raise Exception("x0[%i] must be a scalar or '0' to be zero, 'C' to center, or 'N' to be negative." % i) BaseRectangularMesh.__init__(self, np.array([x.size for x in h]), x0) # Ensure h contains 1D vectors self._h = [Utils.mkvc(x.astype(float)) for x in h]
def MnSigmaDeriv(self, u): """ Derivative of MnSigma with respect to the model """ sigma = self.curModel.sigma sigmaderiv = self.curModel.sigmaDeriv vol = self.mesh.vol return Utils.sdiag(u)*self.mesh.aveN2CC.T*Utils.sdiag(vol) * self.curModel.sigmaDeriv
def diagsJacobian(self, m, hn, hn1, dt, bc): """Diagonals and rhs of the jacobian system The matrix that we are computing has the form:: .- -. .- -. .- -. | Adiag | | h1 | | b1 | | Asub Adiag | | h2 | | b2 | | Asub Adiag | | h3 | = | b3 | | ... ... | | .. | | .. | | Asub Adiag | | hn | | bn | '- -' '- -' '- -' """ if m is not None: self.model = m DIV = self.mesh.faceDiv GRAD = self.mesh.cellGrad BC = self.mesh.cellGradBC AV = self.mesh.aveF2CC.T Dz = self.Dz dT = self.water_retention.derivU(hn) dT1 = self.water_retention.derivU(hn1) dTm = self.water_retention.derivM(hn) dTm1 = self.water_retention.derivM(hn1) K1 = self.hydraulic_conductivity(hn1) dK1 = self.hydraulic_conductivity.derivU(hn1) dKm1 = self.hydraulic_conductivity.derivM(hn1) # Compute part of the derivative of: # # DIV*diag(GRAD*hn1+BC*bc)*(AV*(1.0/K))^-1 DdiagGh1 = DIV*Utils.sdiag(GRAD*hn1+BC*bc) diagAVk2_AVdiagK2 = ( Utils.sdiag((AV*(1./K1))**(-2)) * AV*Utils.sdiag(K1**(-2)) ) Asub = (-1.0/dt)*dT Adiag = ( (1.0/dt)*dT1 - DdiagGh1*diagAVk2_AVdiagK2*dK1 - DIV*Utils.sdiag(1./(AV*(1./K1)))*GRAD - Dz*diagAVk2_AVdiagK2*dK1 ) B = ( DdiagGh1*diagAVk2_AVdiagK2*dKm1 + Dz*diagAVk2_AVdiagK2*dKm1 + (1.0/dt)*(dTm - dTm1) ) return Asub, Adiag, B
def get_interpolation_matrix( self, npts=20, epsilon=None ): tree_2d = kdtree(self.topography[:, :2]) xy = Utils.ndgrid(self.mesh_3d.vectorCCx, self.mesh_3d.vectorCCy) distance, inds = tree_2d.query(xy, k=npts) if epsilon is None: epsilon = np.min([self.mesh_3d.hx.min(), self.mesh_3d.hy.min()]) w = 1. / (distance + epsilon)**2 w = Utils.sdiag(1./np.sum(w, axis=1)) * (w) I = Utils.mkvc( np.arange(inds.shape[0]).reshape([-1, 1]).repeat(npts, axis=1) ) J = Utils.mkvc(inds) self._P = sp.coo_matrix( (Utils.mkvc(w), (I, J)), shape=(inds.shape[0], self.topography.shape[0]) ) mesh_1d = Mesh.TensorMesh([np.r_[self.hz[:-1], 1e20]]) z = self.P*self.topography[:, 2] self._actinds = Utils.surface2ind_topo(self.mesh_3d, np.c_[xy, z]) Z = np.empty(self.mesh_3d.vnC, dtype=float, order='F') Z = self.mesh_3d.gridCC[:, 2].reshape( (self.mesh_3d.nCx*self.mesh_3d.nCy, self.mesh_3d.nCz), order='F' ) ACTIND = self._actinds.reshape( (self.mesh_3d.nCx*self.mesh_3d.nCy, self.mesh_3d.nCz), order='F' ) self._Pz = [] # This part can be cythonized or parallelized for i_xy in range(self.mesh_3d.nCx*self.mesh_3d.nCy): actind_temp = ACTIND[i_xy, :] z_temp = -(Z[i_xy, :] - z[i_xy]) self._Pz.append(mesh_1d.getInterpolationMat(z_temp[actind_temp]))
def switchKernal(xx): """Switches over the different options.""" if xType in ['CC', 'N']: nn = (self._n) if xType == 'CC' else (self._n + 1) assert xx.size == np.prod( nn), "Number of elements must not change." return outKernal(xx, nn) elif xType in ['F', 'E']: # This will only deal with components of fields, not full 'F' or 'E' xx = Utils.mkvc(xx) # unwrap it in case it is a matrix nn = self.vnF if xType == 'F' else self.vnE nn = np.r_[0, nn] nx = [0, 0, 0] nx[0] = self.vnFx if xType == 'F' else self.vnEx nx[1] = self.vnFy if xType == 'F' else self.vnEy nx[2] = self.vnFz if xType == 'F' else self.vnEz for dim, dimName in enumerate(['x', 'y', 'z']): if dimName in outType: assert self.dim > dim, ( "Dimensions of mesh not great enough for %s%s", (xType, dimName)) assert xx.size == np.sum( nn), 'Vector is not the right size.' start = np.sum(nn[:dim + 1]) end = np.sum(nn[:dim + 2]) return outKernal(xx[start:end], nx[dim]) elif xTypeIsFExyz: # This will deal with partial components (x, y or z) lying on edges or faces if 'x' in xType: nn = self.vnFx if 'F' in xType else self.vnEx elif 'y' in xType: nn = self.vnFy if 'F' in xType else self.vnEy elif 'z' in xType: nn = self.vnFz if 'F' in xType else self.vnEz assert xx.size == np.prod(nn), 'Vector is not the right size.' return outKernal(xx, nn)
def ePrimaryDeriv(self, prob, v, adjoint=False, f=None): if f is None: f = self._primaryFields(prob) # if adjoint is True: # raise NotImplementedError if self.primaryProblem._formulation == 'EB': if adjoint is True: epDeriv = self._primaryFieldsDeriv( prob, (self._ProjPrimary(prob, 'E', 'E').T * v), f=f, adjoint=adjoint) else: epDeriv = (self._ProjPrimary(prob, 'E', 'E') * self._primaryFieldsDeriv(prob, v, f=f)) elif self.primaryProblem._formulation == 'HJ': if adjoint is True: PTv = (self.primaryProblem.MfI.T * (self._ProjPrimary(prob, 'F', 'E').T * v)) epDeriv = ( self.primaryProblem.MfRhoDeriv(f[:, 'j']).T * PTv + self._primaryFieldsDeriv(prob, self.primaryProblem.MfRho.T * PTv, adjoint=adjoint, f=f)) # epDeriv =( # (self.primaryProblem.MfI.T * PTv) # ) else: epDeriv = (self._ProjPrimary(prob, 'F', 'E') * (self.primaryProblem.MfI * ((self.primaryProblem.MfRhoDeriv(f[:, 'j']) * v) + (self.primaryProblem.MfRho * self._primaryFieldsDeriv(prob, v, f=f))))) return Utils.mkvc(epDeriv)
def bPrimary(self, prob): """ The primary magnetic flux density from the analytic solution for magnetic fields from a dipole :param BaseFDEMProblem prob: FDEM problem :rtype: numpy.ndarray :return: primary magnetic field """ formulation = prob._formulation if formulation is 'EB': gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz elif formulation is 'HJ': gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz srcfct = MagneticDipoleFields if prob.mesh._meshType is 'CYL': if not prob.mesh.isSymmetric: # TODO ? raise NotImplementedError( 'Non-symmetric cyl mesh not implemented yet!') bx = srcfct(self.loc, gridX, 'x', mu=self.mu, moment=self.moment) bz = srcfct(self.loc, gridZ, 'z', mu=self.mu, moment=self.moment) b = np.concatenate((bx, bz)) else: bx = srcfct(self.loc, gridX, 'x', mu=self.mu, moment=self.moment) by = srcfct(self.loc, gridY, 'y', mu=self.mu, moment=self.moment) bz = srcfct(self.loc, gridZ, 'z', mu=self.mu, moment=self.moment) b = np.concatenate((bx, by, bz)) return Utils.mkvc(b)
def magnetizationModel(self): """ magnetization vector """ if getattr(self, 'magfile', None) is None: M = Magnetics.dipazm_2_xyz( np.ones(self.nC) * self.survey.srcField.param[1], np.ones(self.nC) * self.survey.srcField.param[2]) else: with open(self.basePath + self.magfile) as f: magmodel = f.read() magmodel = magmodel.splitlines() M = [] for line in magmodel: M.append(map(float, line.split())) # Convert list to 2d array M = np.vstack(M) # Cycle through three components and permute from UBC to SimPEG for ii in range(3): m = np.reshape(M[:, ii], (self.mesh.nCz, self.mesh.nCx, self.mesh.nCy), order='F') m = m[::-1, :, :] m = np.transpose(m, (1, 2, 0)) M[:, ii] = Utils.mkvc(m) self._M = M return self._M
def setUp(self): M = Mesh.TensorMesh([np.ones(8), np.ones(30)]) M.setCellGradBC(['neumann', 'dirichlet']) params = Richards.Empirical.HaverkampParams().celia1990 params['Ks'] = np.log(params['Ks']) E = Richards.Empirical.Haverkamp(M, **params) bc = np.array([-61.5, -20.7]) bc = np.r_[np.zeros(M.nCy * 2), np.ones(M.nCx) * bc[0], np.ones(M.nCx) * bc[1]] h = np.zeros(M.nC) + bc[0] prob = Richards.RichardsProblem(M, E, timeSteps=[(40, 3), (60, 3)], boundaryConditions=bc, initialConditions=h, doNewton=False, method='mixed', tolRootFinder=1e-6, debug=False) prob.Solver = Solver locs = Utils.ndgrid(np.array([5, 7.]), np.array([5, 15, 25.])) times = prob.times[3:5] rxSat = Richards.RichardsRx(locs, times, 'saturation') rxPre = Richards.RichardsRx(locs, times, 'pressureHead') survey = Richards.RichardsSurvey([rxSat, rxPre]) prob.pair(survey) self.h0 = h self.M = M self.Ks = params['Ks'] self.prob = prob self.survey = survey
def setUp(self): print('\nTesting Transect for analytic') cs = 10. ncx, ncy, ncz = 10, 10, 10 npad = 5 freq = 1e2 hx = [(cs, npad, -1.3), (cs, ncx), (cs, npad, 1.3)] hy = [(cs, npad, -1.3), (cs, ncy), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.TensorMesh([hx, hy, hz], 'CCC') mapping = Maps.ExpMap(mesh) x = np.linspace(-10, 10, 5) XYZ = Utils.ndgrid(x, np.r_[0], np.r_[0]) rxList = EM.FDEM.Rx.Point_e(XYZ, orientation='x', component='imag') SrcList = [ EM.FDEM.Src.MagDipole([rxList], loc=np.r_[0., 0., 0.], freq=freq), EM.FDEM.Src.CircularLoop([rxList], loc=np.r_[0., 0., 0.], freq=freq, radius=np.sqrt(1. / np.pi)), # EM.FDEM.Src.MagDipole_Bfield([rxList], loc=np.r_[0., 0., 0.], # freq=freq), # less accurate ] survey = EM.FDEM.Survey(SrcList) prb = EM.FDEM.Problem3D_b(mesh, mapping=mapping) prb.pair(survey) try: from pymatsolver import MumpsSolver prb.Solver = MumpsSolver except ImportError, e: prb.Solver = SolverLU
def test_2sum(self): nP = 80 alpha1 = 100 alpha2 = 200 phi1 = (ObjectiveFunction.L2ObjectiveFunction( W=Utils.sdiag(np.random.rand(nP))) + alpha1 * ObjectiveFunction.L2ObjectiveFunction()) phi2 = ObjectiveFunction.L2ObjectiveFunction() + alpha2 * phi1 self.assertTrue(phi2.test(eps=EPS)) self.assertTrue(len(phi1.multipliers) == 2) self.assertTrue(len(phi2.multipliers) == 2) self.assertTrue(len(phi1.objfcts) == 2) self.assertTrue(len(phi2.objfcts) == 2) self.assertTrue(len(phi2) == 2) self.assertTrue(len(phi1) == 2) self.assertTrue(len(phi2) == 2) self.assertTrue(np.all(phi1.multipliers == np.r_[1., alpha1])) self.assertTrue(np.all(phi2.multipliers == np.r_[1., alpha2]))
def B_field_from_SheetCurruent(XYZ, srcLoc, sig, f, E0=1., orientation='X', kappa=0., epsr=1., t=0.): """ Plane wave propagating downward (negative z (depth)) """ XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single frequency can be specified.") mu = mu_0*(1+kappa) epsilon = epsilon_0*epsr sig_hat = sig + 1j*omega(f)*epsilon k = np.sqrt( omega(f)**2. *mu*epsilon -1j*omega(f)*mu*sig ) Z = omega(f)*mu/k if orientation == "X": z = XYZ[:,2] Bx = mu*np.zeros_like(z) By = mu*E0/Z*np.exp(1j*(k*(z-srcLoc)+omega(f)*t)) Bz = mu*np.zeros_like(z) return Bx, By, Bz else: raise NotImplementedError()
def isInside(self, pts, locType='N'): """ Determines if a set of points are inside a mesh. :param numpy.ndarray pts: Location of points to test :rtype numpy.ndarray :return inside, numpy array of booleans """ pts = Utils.asArray_N_x_Dim(pts, self.dim) tensors = self.getTensor(locType) if locType == 'N' and self._meshType == 'CYL': #NOTE: for a CYL mesh we add a node to check if we are inside in the radial direction! tensors[0] = np.r_[0., tensors[0]] tensors[1] = np.r_[tensors[1], 2.0 * np.pi] inside = np.ones(pts.shape[0], dtype=bool) for i, tensor in enumerate(tensors): TOL = np.diff(tensor).min() * 1.0e-10 inside = inside & (pts[:, i] >= tensor.min() - TOL) & ( pts[:, i] <= tensor.max() + TOL) return inside
def activeCells(self): if getattr(self, '_activeCells', None) is None: if getattr(self, 'topofile', None) is not None: topo = np.genfromtxt(self.basePath + self.topofile, skip_header=1) # Find the active cells active = Utils.surface2ind_topo(self.mesh, topo, 'N') elif isinstance(self._staticInput, float): active = self.m0 != self._staticInput else: # Read from file active cells with 0:air, 1:dynamic, -1 static active = self.activeModel != 0 inds = np.asarray([inds for inds, elem in enumerate(active, 1) if elem], dtype=int) - 1 self._activeCells = inds # Reduce m0 to active space if len(self.m0) > len(self._activeCells): self._m0 = self.m0[self._activeCells] return self._activeCells
def fields(self, m): """ Return magnetic potential (u) and flux (B) u: defined on the cell center [nC x 1] B: defined on the cell center [nF x 1] After we compute u, then we update B. .. math :: \mathbf{B}_s = (\MfMui)^{-1}\mathbf{M}^f_{\mu_0^{-1}}\mathbf{B}_0-\mathbf{B}_0 -(\MfMui)^{-1}\Div^T \mathbf{u} """ self.makeMassMatrices(m) A = self.getA(m) rhs = self.getRHS(m) m1 = sp.linalg.interface.aslinearoperator(Utils.sdiag(1 / A.diagonal())) u, info = sp.linalg.bicgstab(A, rhs, tol=1e-6, maxiter=1000, M=m1) B0 = self.getB0() B = self.MfMuI * self.MfMu0 * B0 - B0 - self.MfMuI * self._Div.T * u return {'B': B, 'u': u}
def writeVectorUBC(mesh, fileName, model): """ Writes a vector model associated with a SimPEG TensorMesh to a UBC-GIF format model file. :param string fileName: File to write to :param numpy.ndarray model: The model """ modelMatTR = np.zeros_like(model) for ii in range(3): # Reshape model to a matrix modelMat = mesh.r(model[:, ii], "CC", "CC", "M") # Transpose the axes modelMatT = modelMat.transpose((2, 0, 1)) # Flip UBC order modelMatTR[:, ii] = Utils.mkvc(modelMatT[::-1, :, :]) # Flip z to positive down for MeshTools3D if ii == 2: modelMatTR[:, ii] *= -1 np.savetxt(fileName, modelMatTR)
def getInitialFieldsDeriv(self, src, v, adjoint=False, f=None): ifieldsDeriv = Utils.mkvc( getattr( src, '{}InitialDeriv'.format(self._fieldType), None )(self, v, adjoint, f) ) # take care of any utils.zero cases if adjoint is False: if self._fieldType in ['b', 'j']: ifieldsDeriv += np.zeros(self.mesh.nF) elif self._fieldType in ['e', 'h']: ifieldsDeriv += np.zeros(self.mesh.nE) elif adjoint is True: if self._fieldType in ['b', 'j']: ifieldsDeriv += np.zeros(self.mesh.nF) elif self._fieldType in ['e', 'h']: ifieldsDeriv[0] += np.zeros(self.mesh.nE) ifieldsDeriv[1] += np.zeros_like(self.model) # take care of a Utils.Zero() case return ifieldsDeriv
def run(plotIt=True): M = Mesh.TensorMesh([32, 32]) v = Utils.ModelBuilder.randomModel(M.vnC, seed=789) v = Utils.mkvc(v) O = Mesh.TreeMesh([32, 32]) O.refine(1) def function(cell): if (cell.center[0] < 0.75 and cell.center[0] > 0.25 and cell.center[1] < 0.75 and cell.center[1] > 0.25): return 5 if (cell.center[0] < 0.9 and cell.center[0] > 0.1 and cell.center[1] < 0.9 and cell.center[1] > 0.1): return 4 return 3 O.refine(function) P = M.getInterpolationMat(O.gridCC, 'CC') ov = P * v if not plotIt: return fig, axes = plt.subplots(1, 2, figsize=(10, 5)) out = M.plotImage(v, grid=True, ax=axes[0]) cb = plt.colorbar(out[0], ax=axes[0]) cb.set_label("Random Field") axes[0].set_title('TensorMesh') out = O.plotImage(ov, grid=True, ax=axes[1], clim=[0, 1]) cb = plt.colorbar(out[0], ax=axes[1]) cb.set_label("Random Field") axes[1].set_title('TreeMesh')
def ElectricDipoleWholeSpace(XYZ, srcLoc, sig, f, current=1., length=1., orientation='X', mu=mu_0): XYZ = Utils.asArray_N_x_Dim(XYZ, 3) dx = XYZ[:,0]-srcLoc[0] dy = XYZ[:,1]-srcLoc[1] dz = XYZ[:,2]-srcLoc[2] r = np.sqrt( dx**2. + dy**2. + dz**2.) k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) kr = k*r front = current * length / (4. * np.pi * sig * r**3) * np.exp(-1j*k*r) mid = -k**2 * r**2 + 3*1j*k*r + 3 # Ex = front*((dx**2 / r**2)*mid + (k**2 * r**2 -1j*k*r)) # Ey = front*(dx*dy / r**2)*mid # Ez = front*(dx*dz / r**2)*mid if orientation.upper() == 'X': Ex = front*((dx**2 / r**2)*mid + (k**2 * r**2 -1j*k*r-1.)) Ey = front*(dx*dy / r**2)*mid Ez = front*(dx*dz / r**2)*mid return Ex, Ey, Ez elif orientation.upper() == 'Y': # x--> y, y--> z, z-->x Ey = front*((dy**2 / r**2)*mid + (k**2 * r**2 -1j*k*r-1.)) Ez = front*(dy*dz / r**2)*mid Ex = front*(dy*dx / r**2)*mid return Ex, Ey, Ez elif orientation.upper() == 'Z': # x --> z, y --> x, z --> y Ez = front*((dz**2 / r**2)*mid + (k**2 * r**2 -1j*k*r-1.)) Ex = front*(dz*dx / r**2)*mid Ey = front*(dz*dy / r**2)*mid return Ex, Ey, Ez
def Jvec(self, m, v, f=None): """ Sensitivity times a vector. :param numpy.array m: inversion model (nP,) :param numpy.array v: vector which we take sensitivity product with (nP,) :param SimPEG.EM.FDEM.FieldsFDEM.FieldsFDEM u: fields object :rtype numpy.array: :return: Jv (ndata,) """ if f is None: f = self.fields(m) self.curModel = m Jv = self.dataPair(self.survey) for freq in self.survey.freqs: A = self.getA(freq) Ainv = self.Solver( A, **self.solverOpts ) # create the concept of Ainv (actually a solve) for src in self.survey.getSrcByFreq(freq): u_src = f[src, self._solutionType] dA_dm_v = self.getADeriv(freq, u_src, v) dRHS_dm_v = self.getRHSDeriv(freq, src, v) du_dm_v = Ainv * (-dA_dm_v + dRHS_dm_v) for rx in src.rxList: df_dmFun = getattr(f, '_{0}Deriv'.format(rx.projField), None) df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False) Jv[src, rx] = rx.evalDeriv(src, self.mesh, f, df_dm_v) Ainv.clean() return Utils.mkvc(Jv)
def E_field_from_SheetCurruent(XYZ, srcLoc, sig, t, E0=1., orientation='X', kappa=0., epsr=1.): """ Computing Analytic Electric fields from Plane wave in a Wholespace TODO: Add description of parameters """ XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & t.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single frequency can be specified.") mu = mu_0*(1+kappa) if orientation == "X": z = XYZ[:, 2] bunja = -E0*(mu*sig)**0.5 * z * np.exp(-(mu*sig*z**2) / (4*t)) bunmo = 2 * np.pi**0.5 * t**1.5 Ex = bunja / bunmo Ey = np.zeros_like(z) Ez = np.zeros_like(z) return Ex, Ey, Ez else: raise NotImplementedError()
def hzAnalyticDipoleF(r, freq, sigma, secondary=True, mu=mu_0): """ 4.56 in Ward and Hohmann .. plot:: import matplotlib.pyplot as plt from SimPEG import EM freq = np.logspace(-1, 6, 61) test = EM.Analytics.FDEM.hzAnalyticDipoleF(100, freq, 0.001, secondary=False) plt.loglog(freq, abs(test.real)) plt.loglog(freq, abs(test.imag)) plt.title('Response at $r$=100m') plt.xlabel('Frequency') plt.ylabel('Response') plt.legend(('real','imag')) plt.show() """ r = np.abs(r) k = np.sqrt(-1j * 2. * np.pi * freq * mu * sigma) m = 1 front = m / (2. * np.pi * (k**2) * (r**5)) back = 9 - (9 + 9j * k * r - 4 * (k**2) * (r**2) - 1j * (k**3) * (r**3)) * np.exp(-1j * k * r) hz = front * back if secondary: hp = -1 / (4 * np.pi * r**3) hz = hz - hp if hz.ndim == 1: hz = Utils.mkvc(hz, 2) return hz
def bPrimary(self, prob): """ The primary magnetic flux density from the analytic solution for magnetic fields from a dipole :param BaseFDEMProblem prob: FDEM problem :rtype: numpy.ndarray :return: primary magnetic field """ formulation = prob._formulation coordinates = "cartesian" if formulation == 'EB': gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz elif formulation == 'HJ': gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz if prob.mesh._meshType == 'CYL': coordinates = "cylindrical" if prob.mesh.isSymmetric: bx = self._srcFct(gridX)[:, 0] bz = self._srcFct(gridZ)[:, 2] b = np.concatenate((bx, bz)) else: bx = self._srcFct(gridX, coordinates=coordinates)[:, 0] by = self._srcFct(gridY, coordinates=coordinates)[:, 1] bz = self._srcFct(gridZ, coordinates=coordinates)[:, 2] b = np.concatenate((bx, by, bz)) return Utils.mkvc(b)
def getFields(self, itime): src = self.srcList[0] Ey = self.mesh.aveE2CC * self.f[src, "e", itime] Jy = Utils.sdiag(self.prb.sigma) * Ey self.Ey = Utils.mkvc(self.mirrorArray(Ey[self.activeCC], direction="y")) self.Jy = Utils.mkvc(self.mirrorArray(Jy[self.activeCC], direction="y")) self.Bx = Utils.mkvc( self.mirrorArray(self.Pfx * self.f[src, "b", itime], direction="x")) self.Bz = Utils.mkvc( self.mirrorArray(self.Pfz * self.f[src, "b", itime], direction="z")) self.dBxdt = Utils.mkvc( self.mirrorArray(-self.Pfx * self.mesh.edgeCurl * self.f[src, "e", itime], direction="x")) self.dBzdt = Utils.mkvc( self.mirrorArray(-self.Pfz * self.mesh.edgeCurl * self.f[src, "e", itime], direction="z"))
def Intrgl_Fwr_Op(xn, yn, zn, rxLoc): """ Magnetic forward operator in integral form flag = 'ind' | 'full' 1- ind : Magnetization fixed by user 3- full: Full tensor matrix stored with shape([3*ndata, 3*nc]) Return _G = Linear forward modeling operation """ yn2, xn2, zn2 = np.meshgrid(yn[1:], xn[1:], zn[1:]) yn1, xn1, zn1 = np.meshgrid(yn[0:-1], xn[0:-1], zn[0:-1]) Yn = np.c_[Utils.mkvc(yn1), Utils.mkvc(yn2)] Xn = np.c_[Utils.mkvc(xn1), Utils.mkvc(xn2)] Zn = np.c_[Utils.mkvc(zn1), Utils.mkvc(zn2)] ndata = rxLoc.shape[0] # Pre-allocate forward matrix G = np.zeros((int(3 * ndata), 3)) for ii in range(ndata): tx, ty, tz = PF.Magnetics.get_T_mat(Xn, Yn, Zn, rxLoc[ii, :]) G[ii, :] = tx / 1e-9 * mu_0 G[ii + ndata, :] = ty / 1e-9 * mu_0 G[ii + 2 * ndata, :] = tz / 1e-9 * mu_0 return G
def resolve_1Dinversions(mesh, dobs, src_height, freqs, m0, mref, mapping, std=0.08, floor=1e-14, rxOffset=7.86): """ Perform a single 1D inversion for a RESOLVE sounding for Horizontal Coplanar Coil data (both real and imaginary). :param discretize.CylMesh mesh: mesh used for the forward simulation :param numpy.array dobs: observed data :param float src_height: height of the source above the ground :param numpy.array freqs: frequencies :param numpy.array m0: starting model :param numpy.array mref: reference model :param Maps.IdentityMap mapping: mapping that maps the model to electrical conductivity :param float std: percent error used to construct the data misfit term :param float floor: noise floor used to construct the data misfit term :param float rxOffset: offset between source and receiver. """ # ------------------- Forward Simulation ------------------- # # set up the receivers bzr = EM.FDEM.Rx.Point_bSecondary(np.array([[rxOffset, 0., src_height]]), orientation='z', component='real') bzi = EM.FDEM.Rx.Point_b(np.array([[rxOffset, 0., src_height]]), orientation='z', component='imag') # source location srcLoc = np.array([0., 0., src_height]) srcList = [ EM.FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation='Z') for freq in freqs ] # construct a forward simulation survey = EM.FDEM.Survey(srcList) prb = EM.FDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=PardisoSolver) prb.pair(survey) # ------------------- Inversion ------------------- # # data misfit term survey.dobs = dobs dmisfit = DataMisfit.l2_DataMisfit(survey) uncert = abs(dobs) * std + floor dmisfit.W = 1. / uncert # regularization regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Simple(regMesh) reg.mref = mref # optimization opt = Optimization.InexactGaussNewton(maxIter=10) # statement of the inverse problem invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # Inversion directives and parameters target = Directives.TargetMisfit() inv = Inversion.BaseInversion(invProb, directiveList=[target]) invProb.beta = 2. # Fix beta in the nonlinear iterations reg.alpha_s = 1e-3 reg.alpha_x = 1. prb.counter = opt.counter = Utils.Counter() opt.LSshorten = 0.5 opt.remember('xc') # run the inversion mopt = inv.run(m0) return mopt, invProb.dpred, survey.dobs
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)
# We will assume a vertical inducing field H0 = (50000., 90., 0.) # The magnetization is set along a different direction (induced + remanence) M = np.array([45., 90.]) # Create grid of points for topography # Lets create a simple Gaussian topo and set the active cells [xx, yy] = np.meshgrid(np.linspace(-200, 200, 50), np.linspace(-200, 200, 50)) b = 100 A = 50 zz = A * np.exp(-0.5 * ((xx / b)**2. + (yy / b)**2.)) # We would usually load a topofile topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)] # Create and array of observation points xr = np.linspace(-100., 100., 20) yr = np.linspace(-100., 100., 20) X, Y = np.meshgrid(xr, yr) Z = A * np.exp(-0.5 * ((X / b)**2. + (Y / b)**2.)) + 5 # Create a MAGsurvey xyzLoc = np.c_[Utils.mkvc(X.T), Utils.mkvc(Y.T), Utils.mkvc(Z.T)] rxLoc = PF.BaseMag.RxObs(xyzLoc) srcField = PF.BaseMag.SrcField([rxLoc], param=H0) survey = PF.BaseMag.LinearSurvey(srcField) # Here how the topography looks with a quick interpolation, just a Gaussian... tri = sp.spatial.Delaunay(topo)
def MagneticDipoleWholeSpace(XYZ, srcLoc, sig, f, moment=1., orientation='X', mu = mu_0): """ Analytical solution for a dipole in a whole-space. Equation 2.57 of Ward and Hohmann TODOs: - set it up to instead take a mesh & survey - add E-fields - handle multiple frequencies - add divide by zero safety .. plot:: from SimPEG import EM import matplotlib.pyplot as plt from scipy.constants import mu_0 freqs = np.logspace(-2,5,100) Bx, By, Bz = EM.Analytics.FDEM.MagneticDipoleWholeSpace([0,100,0], [0,0,0], 1e-2, freqs, moment=1, orientation='Z') plt.loglog(freqs, np.abs(Bz.real)/mu_0, 'b') plt.loglog(freqs, np.abs(Bz.imag)/mu_0, 'r') plt.legend(('real','imag')) plt.show() """ XYZ = Utils.asArray_N_x_Dim(XYZ, 3) dx = XYZ[:,0]-srcLoc[0] dy = XYZ[:,1]-srcLoc[1] dz = XYZ[:,2]-srcLoc[2] r = np.sqrt( dx**2. + dy**2. + dz**2.) k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) kr = k*r front = moment / (4.*pi * r**3.) * np.exp(-1j*kr) mid = -kr**2. + 3.*1j*kr + 3. if orientation.upper() == 'X': Hx = front*( (dx/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Hy = front*( (dx*dy/r**2.) * mid ) Hz = front*( (dx*dz/r**2.) * mid ) elif orientation.upper() == 'Y': Hx = front*( (dy*dx/r**2.) * mid ) Hy = front*( (dy/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Hz = front*( (dy*dz/r**2.) * mid ) elif orientation.upper() == 'Z': Hx = front*( (dx*dz/r**2.) * mid ) Hy = front*( (dy*dz/r**2.) * mid ) Hz = front*( (dz/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Bx = mu*Hx By = mu*Hy Bz = mu*Hz if Bx.ndim is 1: Bx = Utils.mkvc(Bx,2) if By.ndim is 1: By = Utils.mkvc(By,2) if Bz.ndim is 1: Bz = Utils.mkvc(Bz,2) return Bx, By, Bz
def evalDeriv(self, src, mesh, f, v, adjoint=False): """ The derivative of the projection wrt u :param MTsrc src: MT source :param TensorMesh mesh: Mesh defining the topology of the problem :param MTfields f: MT fields object of the source :param numpy.ndarray v: Random vector of size """ real_or_imag = self.projComp if not adjoint: if self.projType is 'Z1D': Pex = mesh.getInterpolationMat(self.locs[:,-1],'Fx') Pbx = mesh.getInterpolationMat(self.locs[:,-1],'Ex') # ex = Pex*mkvc(f[src,'e_1d'],2) # bx = Pbx*mkvc(f[src,'b_1d'],2)/mu_0 dP_de = -mkvc(Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0))*(Pex*v),2) dP_db = mkvc( Utils.sdiag(Pex*mkvc(f[src,'e_1d'],2))*(Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)).T*Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)))*(Pbx*f._bDeriv_u(src,v)/mu_0),2) PDeriv_complex = np.sum(np.hstack((dP_de,dP_db)),1) elif self.projType is 'Z2D': raise NotImplementedError('Has not been implement for 2D impedance tensor') elif self.projType is 'Z3D': if self.locs.ndim == 3: eFLocs = self.locs[:,:,0] bFLocs = self.locs[:,:,1] else: eFLocs = self.locs bFLocs = self.locs # Get the projection Pex = mesh.getInterpolationMat(eFLocs,'Ex') Pey = mesh.getInterpolationMat(eFLocs,'Ey') Pbx = mesh.getInterpolationMat(bFLocs,'Fx') Pby = mesh.getInterpolationMat(bFLocs,'Fy') # Get the fields at location # px: x-polaration and py: y-polaration. ex_px = Pex*f[src,'e_px'] ey_px = Pey*f[src,'e_px'] ex_py = Pex*f[src,'e_py'] ey_py = Pey*f[src,'e_py'] hx_px = Pbx*f[src,'b_px']/mu_0 hy_px = Pby*f[src,'b_px']/mu_0 hx_py = Pbx*f[src,'b_py']/mu_0 hy_py = Pby*f[src,'b_py']/mu_0 # Derivatives as lambda functions # The size of the diratives should be nD,nU ex_px_u = lambda vec: Pex*f._e_pxDeriv_u(src,vec) ey_px_u = lambda vec: Pey*f._e_pxDeriv_u(src,vec) ex_py_u = lambda vec: Pex*f._e_pyDeriv_u(src,vec) ey_py_u = lambda vec: Pey*f._e_pyDeriv_u(src,vec) # NOTE: Think b_p?Deriv_u should return a 2*nF size matrix hx_px_u = lambda vec: Pbx*f._b_pxDeriv_u(src,vec)/mu_0 hy_px_u = lambda vec: Pby*f._b_pxDeriv_u(src,vec)/mu_0 hx_py_u = lambda vec: Pbx*f._b_pyDeriv_u(src,vec)/mu_0 hy_py_u = lambda vec: Pby*f._b_pyDeriv_u(src,vec)/mu_0 # Update the input vector sDiag = lambda t: Utils.sdiag(mkvc(t,2)) # Define the components of the derivative Hd = sDiag(1./(sDiag(hx_px)*hy_py - sDiag(hx_py)*hy_px)) Hd_uV = sDiag(hy_py)*hx_px_u(v) + sDiag(hx_px)*hy_py_u(v) - sDiag(hx_py)*hy_px_u(v) - sDiag(hy_px)*hx_py_u(v) # Calculate components if 'zxx' in self.rxType: Zij = sDiag(Hd*( sDiag(ex_px)*hy_py - sDiag(ex_py)*hy_px )) ZijN_uV = sDiag(hy_py)*ex_px_u(v) + sDiag(ex_px)*hy_py_u(v) - sDiag(ex_py)*hy_px_u(v) - sDiag(hy_px)*ex_py_u(v) elif 'zxy' in self.rxType: Zij = sDiag(Hd*(-sDiag(ex_px)*hx_py + sDiag(ex_py)*hx_px )) ZijN_uV = -sDiag(hx_py)*ex_px_u(v) - sDiag(ex_px)*hx_py_u(v) + sDiag(ex_py)*hx_px_u(v) + sDiag(hx_px)*ex_py_u(v) elif 'zyx' in self.rxType: Zij = sDiag(Hd*( sDiag(ey_px)*hy_py - sDiag(ey_py)*hy_px )) ZijN_uV = sDiag(hy_py)*ey_px_u(v) + sDiag(ey_px)*hy_py_u(v) - sDiag(ey_py)*hy_px_u(v) - sDiag(hy_px)*ey_py_u(v) elif 'zyy' in self.rxType: Zij = sDiag(Hd*(-sDiag(ey_px)*hx_py + sDiag(ey_py)*hx_px )) ZijN_uV = -sDiag(hx_py)*ey_px_u(v) - sDiag(ey_px)*hx_py_u(v) + sDiag(ey_py)*hx_px_u(v) + sDiag(hx_px)*ey_py_u(v) # Calculate the complex derivative PDeriv_complex = Hd * (ZijN_uV - Zij * Hd_uV ) elif self.projType is 'T3D': if self.locs.ndim == 3: eFLocs = self.locs[:,:,0] bFLocs = self.locs[:,:,1] else: eFLocs = self.locs bFLocs = self.locs # Get the projection Pbx = mesh.getInterpolationMat(bFLocs,'Fx') Pby = mesh.getInterpolationMat(bFLocs,'Fy') Pbz = mesh.getInterpolationMat(bFLocs,'Fz') # Get the fields at location # px: x-polaration and py: y-polaration. bx_px = Pbx*f[src,'b_px'] by_px = Pby*f[src,'b_px'] bz_px = Pbz*f[src,'b_px'] bx_py = Pbx*f[src,'b_py'] by_py = Pby*f[src,'b_py'] bz_py = Pbz*f[src,'b_py'] # Derivatives as lambda functions # NOTE: Think b_p?Deriv_u should return a 2*nF size matrix bx_px_u = lambda vec: Pbx*f._b_pxDeriv_u(src,vec) by_px_u = lambda vec: Pby*f._b_pxDeriv_u(src,vec) bz_px_u = lambda vec: Pbz*f._b_pxDeriv_u(src,vec) bx_py_u = lambda vec: Pbx*f._b_pyDeriv_u(src,vec) by_py_u = lambda vec: Pby*f._b_pyDeriv_u(src,vec) bz_py_u = lambda vec: Pbz*f._b_pyDeriv_u(src,vec) # Update the input vector sDiag = lambda t: Utils.sdiag(mkvc(t,2)) # Define the components of the derivative Hd = sDiag(1./(sDiag(bx_px)*by_py - sDiag(bx_py)*by_px)) Hd_uV = sDiag(by_py)*bx_px_u(v) + sDiag(bx_px)*by_py_u(v) - sDiag(bx_py)*by_px_u(v) - sDiag(by_px)*bx_py_u(v) if 'tzx' in self.rxType: Tij = sDiag(Hd*( - sDiag(by_px)*bz_py + sDiag(by_py)*bz_px )) TijN_uV = -sDiag(by_px)*bz_py_u(v) - sDiag(bz_py)*by_px_u(v) + sDiag(by_py)*bz_px_u(v) + sDiag(bz_px)*by_py_u(v) elif 'tzy' in self.rxType: Tij = sDiag(Hd*( sDiag(bx_px)*bz_py - sDiag(bx_py)*bz_px )) TijN_uV = sDiag(bz_py)*bx_px_u(v) + sDiag(bx_px)*bz_py_u(v) - sDiag(bx_py)*bz_px_u(v) - sDiag(bz_px)*bx_py_u(v) # Calculate the complex derivative PDeriv_complex = Hd * (TijN_uV - Tij * Hd_uV ) # Extract the real number for the real/imag components. Pv = np.array(getattr(PDeriv_complex, real_or_imag)) elif adjoint: # Note: The v vector is real and the return should be complex if self.projType is 'Z1D': Pex = mesh.getInterpolationMat(self.locs[:,-1],'Fx') Pbx = mesh.getInterpolationMat(self.locs[:,-1],'Ex') # ex = Pex*mkvc(f[src,'e_1d'],2) # bx = Pbx*mkvc(f[src,'b_1d'],2)/mu_0 dP_deTv = -mkvc(Pex.T*Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)).T*v,2) db_duv = Pbx.T/mu_0*Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0))*(Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0))).T*Utils.sdiag(Pex*mkvc(f[src,'e_1d'],2)).T*v dP_dbTv = mkvc(f._bDeriv_u(src,db_duv,adjoint=True),2) PDeriv_real = np.sum(np.hstack((dP_deTv,dP_dbTv)),1) elif self.projType is 'Z2D': raise NotImplementedError('Has not be implement for 2D impedance tensor') elif self.projType is 'Z3D': if self.locs.ndim == 3: eFLocs = self.locs[:,:,0] bFLocs = self.locs[:,:,1] else: eFLocs = self.locs bFLocs = self.locs # Get the projection Pex = mesh.getInterpolationMat(eFLocs,'Ex') Pey = mesh.getInterpolationMat(eFLocs,'Ey') Pbx = mesh.getInterpolationMat(bFLocs,'Fx') Pby = mesh.getInterpolationMat(bFLocs,'Fy') # Get the fields at location # px: x-polaration and py: y-polaration. aex_px = mkvc(mkvc(f[src,'e_px'],2).T*Pex.T) aey_px = mkvc(mkvc(f[src,'e_px'],2).T*Pey.T) aex_py = mkvc(mkvc(f[src,'e_py'],2).T*Pex.T) aey_py = mkvc(mkvc(f[src,'e_py'],2).T*Pey.T) ahx_px = mkvc(mkvc(f[src,'b_px'],2).T/mu_0*Pbx.T) ahy_px = mkvc(mkvc(f[src,'b_px'],2).T/mu_0*Pby.T) ahx_py = mkvc(mkvc(f[src,'b_py'],2).T/mu_0*Pbx.T) ahy_py = mkvc(mkvc(f[src,'b_py'],2).T/mu_0*Pby.T) # Derivatives as lambda functions aex_px_u = lambda vec: f._e_pxDeriv_u(src,Pex.T*vec,adjoint=True) aey_px_u = lambda vec: f._e_pxDeriv_u(src,Pey.T*vec,adjoint=True) aex_py_u = lambda vec: f._e_pyDeriv_u(src,Pex.T*vec,adjoint=True) aey_py_u = lambda vec: f._e_pyDeriv_u(src,Pey.T*vec,adjoint=True) ahx_px_u = lambda vec: f._b_pxDeriv_u(src,Pbx.T*vec,adjoint=True)/mu_0 ahy_px_u = lambda vec: f._b_pxDeriv_u(src,Pby.T*vec,adjoint=True)/mu_0 ahx_py_u = lambda vec: f._b_pyDeriv_u(src,Pbx.T*vec,adjoint=True)/mu_0 ahy_py_u = lambda vec: f._b_pyDeriv_u(src,Pby.T*vec,adjoint=True)/mu_0 # Update the input vector # Define shortcuts sDiag = lambda t: Utils.sdiag(mkvc(t,2)) sVec = lambda t: Utils.sp.csr_matrix(mkvc(t,2)) # Define the components of the derivative aHd = sDiag(1./(sDiag(ahx_px)*ahy_py - sDiag(ahx_py)*ahy_px)) aHd_uV = lambda x: ahx_px_u(sDiag(ahy_py)*x) + ahx_px_u(sDiag(ahy_py)*x) - ahy_px_u(sDiag(ahx_py)*x) - ahx_py_u(sDiag(ahy_px)*x) # Need to fix this to reflect the adjoint if 'zxx' in self.rxType: Zij = sDiag(aHd*( sDiag(ahy_py)*aex_px - sDiag(ahy_px)*aex_py)) ZijN_uV = lambda x: aex_px_u(sDiag(ahy_py)*x) + ahy_py_u(sDiag(aex_px)*x) - ahy_px_u(sDiag(aex_py)*x) - aex_py_u(sDiag(ahy_px)*x) elif 'zxy' in self.rxType: Zij = sDiag(aHd*(-sDiag(ahx_py)*aex_px + sDiag(ahx_px)*aex_py)) ZijN_uV = lambda x:-aex_px_u(sDiag(ahx_py)*x) - ahx_py_u(sDiag(aex_px)*x) + ahx_px_u(sDiag(aex_py)*x) + aex_py_u(sDiag(ahx_px)*x) elif 'zyx' in self.rxType: Zij = sDiag(aHd*( sDiag(ahy_py)*aey_px - sDiag(ahy_px)*aey_py)) ZijN_uV = lambda x: aey_px_u(sDiag(ahy_py)*x) + ahy_py_u(sDiag(aey_px)*x) - ahy_px_u(sDiag(aey_py)*x) - aey_py_u(sDiag(ahy_px)*x) elif 'zyy' in self.rxType: Zij = sDiag(aHd*(-sDiag(ahx_py)*aey_px + sDiag(ahx_px)*aey_py)) ZijN_uV = lambda x:-aey_px_u(sDiag(ahx_py)*x) - ahx_py_u(sDiag(aey_px)*x) + ahx_px_u(sDiag(aey_py)*x) + aey_py_u(sDiag(ahx_px)*x) # Calculate the complex derivative PDeriv_real = ZijN_uV(aHd*v) - aHd_uV(Zij.T*aHd*v)# # NOTE: Need to reshape the output to go from 2*nU array to a (nU,2) matrix for each polarization # PDeriv_real = np.hstack((mkvc(PDeriv_real[:len(PDeriv_real)/2],2),mkvc(PDeriv_real[len(PDeriv_real)/2::],2))) PDeriv_real = PDeriv_real.reshape((2,mesh.nE)).T elif self.projType is 'T3D': if self.locs.ndim == 3: bFLocs = self.locs[:,:,1] else: bFLocs = self.locs # Get the projection Pbx = mesh.getInterpolationMat(bFLocs,'Fx') Pby = mesh.getInterpolationMat(bFLocs,'Fy') Pbz = mesh.getInterpolationMat(bFLocs,'Fz') # Get the fields at location # px: x-polaration and py: y-polaration. abx_px = mkvc(mkvc(f[src,'b_px'],2).T*Pbx.T) aby_px = mkvc(mkvc(f[src,'b_px'],2).T*Pby.T) abz_px = mkvc(mkvc(f[src,'b_px'],2).T*Pbz.T) abx_py = mkvc(mkvc(f[src,'b_py'],2).T*Pbx.T) aby_py = mkvc(mkvc(f[src,'b_py'],2).T*Pby.T) abz_py = mkvc(mkvc(f[src,'b_py'],2).T*Pbz.T) # Derivatives as lambda functions abx_px_u = lambda vec: f._b_pxDeriv_u(src,Pbx.T*vec,adjoint=True) aby_px_u = lambda vec: f._b_pxDeriv_u(src,Pby.T*vec,adjoint=True) abz_px_u = lambda vec: f._b_pxDeriv_u(src,Pbz.T*vec,adjoint=True) abx_py_u = lambda vec: f._b_pyDeriv_u(src,Pbx.T*vec,adjoint=True) aby_py_u = lambda vec: f._b_pyDeriv_u(src,Pby.T*vec,adjoint=True) abz_py_u = lambda vec: f._b_pyDeriv_u(src,Pbz.T*vec,adjoint=True) # Update the input vector # Define shortcuts sDiag = lambda t: Utils.sdiag(mkvc(t,2)) sVec = lambda t: Utils.sp.csr_matrix(mkvc(t,2)) # Define the components of the derivative aHd = sDiag(1./(sDiag(abx_px)*aby_py - sDiag(abx_py)*aby_px)) aHd_uV = lambda x: abx_px_u(sDiag(aby_py)*x) + abx_px_u(sDiag(aby_py)*x) - aby_px_u(sDiag(abx_py)*x) - abx_py_u(sDiag(aby_px)*x) # Need to fix this to reflect the adjoint if 'tzx' in self.rxType: Tij = sDiag(aHd*( -sDiag(abz_py)*aby_px + sDiag(abz_px)*aby_py)) TijN_uV = lambda x: -abz_py_u(sDiag(aby_px)*x) - aby_px_u(sDiag(abz_py)*x) + aby_py_u(sDiag(abz_px)*x) + abz_px_u(sDiag(aby_py)*x) elif 'tzy' in self.rxType: Tij = sDiag(aHd*( sDiag(abz_py)*abx_px - sDiag(abz_px)*abx_py)) TijN_uV = lambda x: abx_px_u(sDiag(abz_py)*x) + abz_py_u(sDiag(abx_px)*x) - abx_py_u(sDiag(abz_px)*x) - abz_px_u(sDiag(abx_py)*x) # Calculate the complex derivative PDeriv_real = TijN_uV(aHd*v) - aHd_uV(Tij.T*aHd*v)# # NOTE: Need to reshape the output to go from 2*nU array to a (nU,2) matrix for each polarization # PDeriv_real = np.hstack((mkvc(PDeriv_real[:len(PDeriv_real)/2],2),mkvc(PDeriv_real[len(PDeriv_real)/2::],2))) PDeriv_real = PDeriv_real.reshape((2,mesh.nE)).T # Extract the data if real_or_imag == 'imag': Pv = 1j*PDeriv_real elif real_or_imag == 'real': Pv = PDeriv_real.astype(complex) return Pv
overb = (mesh.gridCC[:, 1] > -overburden_extent) & (mesh.gridCC[:, 1] <= 0) mtrue[overb] = ln_over * np.ones_like(mtrue[overb]) + norm( noisemean, noisevar).rvs(np.prod((mtrue[overb]).shape)) csph = (np.sqrt((mesh.gridCC[:, 1] - z0)**2. + (mesh.gridCC[:, 0] - x0)**2.)) < r0 mtrue[csph] = ln_sigc * np.ones_like(mtrue[csph]) + norm( noisemean, noisevar).rvs(np.prod((mtrue[csph]).shape)) #Define the sphere limit rsph = (np.sqrt((mesh.gridCC[:, 1] - z1)**2. + (mesh.gridCC[:, 0] - x1)**2.)) < r1 mtrue[rsph] = ln_sigr * np.ones_like(mtrue[rsph]) + norm( noisemean, noisevar).rvs(np.prod((mtrue[rsph]).shape)) mtrue = Utils.mkvc(mtrue) mesh.plotGrid() plt.gca().set_xlim([-10, 10]) plt.gca().set_ylim([-10, 0]) xyzlim = np.r_[[[-10., 10.], [-10., 1.]]] actind, meshCore = Utils.meshutils.ExtractCoreMesh(xyzlim, mesh) plt.hist(mtrue[actind], bins=50, normed=True) fig0 = plt.figure() ax0 = fig0.add_subplot(111) mm = meshCore.plotImage(mtrue[actind], ax=ax0) plt.colorbar(mm[0]) ax0.set_aspect("equal") #plt.show()
def run(plotIt=True): """ Mesh: Plotting with defining range ================================== When using a large Mesh with the cylindrical code, it is advantageous to define a :code:`range_x` and :code:`range_y` when plotting with vectors. In this case, only the region inside of the range is interpolated. In particular, you often want to ignore padding cells. """ # ## Model Parameters # # We define a # - resistive halfspace and # - conductive sphere # - radius of 30m # - center is 50m below the surface # electrical conductivities in S/m sig_halfspace = 1e-6 sig_sphere = 1e0 sig_air = 1e-8 # depth to center, radius in m sphere_z = -50. sphere_radius = 30. # ## Survey Parameters # # - Transmitter and receiver 20m above the surface # - Receiver offset from transmitter by 8m horizontally # - 25 frequencies, logaritmically between $10$ Hz and $10^5$ Hz boom_height = 20. rx_offset = 8. freqs = np.r_[1e1, 1e5] # source and receiver location in 3D space src_loc = np.r_[0., 0., boom_height] rx_loc = np.atleast_2d(np.r_[rx_offset, 0., boom_height]) # print the min and max skin depths to make sure mesh is fine enough and # extends far enough def skin_depth(sigma, f): return 500. / np.sqrt(sigma * f) print('Minimum skin depth (in sphere): {:.2e} m '.format( skin_depth(sig_sphere, freqs.max()))) print('Maximum skin depth (in background): {:.2e} m '.format( skin_depth(sig_halfspace, freqs.min()))) # ## Mesh # # Here, we define a cylindrically symmetric tensor mesh. # # ### Mesh Parameters # # For the mesh, we will use a cylindrically symmetric tensor mesh. To # construct a tensor mesh, all that is needed is a vector of cell widths in # the x and z-directions. We will define a core mesh region of uniform cell # widths and a padding region where the cell widths expand "to infinity". # x-direction csx = 2 # core mesh cell width in the x-direction ncx = np.ceil( 1.2 * sphere_radius / csx ) # number of core x-cells (uniform mesh slightly beyond sphere radius) npadx = 50 # number of x padding cells # z-direction csz = 1 # core mesh cell width in the z-direction ncz = np.ceil( 1.2 * (boom_height - (sphere_z - sphere_radius)) / csz ) # number of core z-cells (uniform cells slightly below bottom of sphere) npadz = 52 # number of z padding cells # padding factor (expand cells to infinity) pf = 1.3 # cell spacings in the x and z directions hx = Utils.meshTensor([(csx, ncx), (csx, npadx, pf)]) hz = Utils.meshTensor([(csz, npadz, -pf), (csz, ncz), (csz, npadz, pf)]) # define a SimPEG mesh mesh = Mesh.CylMesh([hx, 1, hz], x0=np.r_[0., 0., -hz.sum() / 2. - boom_height]) # ### Plot the mesh # # Below, we plot the mesh. The cyl mesh is rotated around x=0. Ensure that # each dimension extends beyond the maximum skin depth. # # Zoom in by changing the xlim and zlim. # X and Z limits we want to plot to. Try xlim = np.r_[0., 2.5e6] zlim = np.r_[-2.5e6, 2.5e6] fig, ax = plt.subplots(1, 1) mesh.plotGrid(ax=ax) ax.set_title('Simulation Mesh') ax.set_xlim(xlim) ax.set_ylim(zlim) print('The maximum skin depth is (in background): {:.2e} m. ' 'Does the mesh go sufficiently past that?'.format( skin_depth(sig_halfspace, freqs.min()))) # ## Put Model on Mesh # # Now that the model parameters and mesh are defined, we can define # electrical conductivity on the mesh. # # The electrical conductivity is defined at cell centers when using the # finite volume method. So here, we define a vector that contains an # electrical conductivity value for every cell center. # create a vector that has one entry for every cell center sigma = sig_air * np.ones( mesh.nC) # start by defining the conductivity of the air everwhere sigma[mesh.gridCC[:, 2] < 0.] = sig_halfspace # assign halfspace cells below the earth # indices of the sphere (where (x-x0)**2 + (z-z0)**2 <= R**2) sphere_ind = ((mesh.gridCC[:, 0]**2 + (mesh.gridCC[:, 2] - sphere_z)**2) <= sphere_radius**2) sigma[sphere_ind] = sig_sphere # assign the conductivity of the sphere # Plot a cross section of the conductivity model fig, ax = plt.subplots(1, 1) cb = plt.colorbar(mesh.plotImage(np.log10(sigma), ax=ax, mirror=True)[0]) # plot formatting and titles cb.set_label('$\log_{10}\sigma$', fontsize=13) ax.axis('equal') ax.set_xlim([-120., 120.]) ax.set_ylim([-100., 30.]) ax.set_title('Conductivity Model') # ## Set up the Survey # # Here, we define sources and receivers. For this example, the receivers # are magnetic flux recievers, and are only looking at the secondary field # (eg. if a bucking coil were used to cancel the primary). The source is a # vertical magnetic dipole with unit moment. # Define the receivers, we will sample the real secondary magnetic flux # density as well as the imaginary magnetic flux density bz_r = FDEM.Rx.Point_bSecondary( locs=rx_loc, orientation='z', component='real') # vertical real b-secondary bz_i = FDEM.Rx.Point_b( locs=rx_loc, orientation='z', component='imag') # vertical imag b (same as b-secondary) rxList = [bz_r, bz_i] # list of receivers # Define the list of sources - one source for each frequency. The source is # a point dipole oriented in the z-direction srcList = [ FDEM.Src.MagDipole(rxList, f, src_loc, orientation='z') for f in freqs ] print( 'There are {nsrc} sources (same as the number of frequencies - {nfreq}). ' 'Each source has {nrx} receivers sampling the resulting b-fields'. format(nsrc=len(srcList), nfreq=len(freqs), nrx=len(rxList))) # ## Set up Forward Simulation # # A forward simulation consists of a paired SimPEG problem and Survey. # For this example, we use the E-formulation of Maxwell's equations, # solving the second-order system for the electric field, which is defined # on the cell edges of the mesh. This is the `prob` variable below. The # `survey` takes the source list which is used to construct the RHS for the # problem. The source list also contains the receiver information, so the # `survey` knows how to sample fields and fluxes that are produced by # solving the `prob`. # define a problem - the statement of which discrete pde system we want to # solve prob = FDEM.Problem3D_e(mesh, sigmaMap=Maps.IdentityMap(mesh)) prob.solver = Solver survey = FDEM.Survey(srcList) # tell the problem and survey about each other - so the RHS can be # constructed for the problem and the # resulting fields and fluxes can be sampled by the receiver. prob.pair(survey) # ### Solve the forward simulation # # Here, we solve the problem for the fields everywhere on the mesh. fields = prob.fields(sigma) # ### Plot the fields # # Lets look at the physics! # log-scale the colorbar from matplotlib.colors import LogNorm fig, ax = plt.subplots(1, 2, figsize=(12, 6)) def plotMe(field, ax): plt.colorbar(mesh.plotImage(field, vType='F', view='vec', range_x=[-100., 100.], range_y=[-180., 60.], pcolorOpts={ 'norm': LogNorm(), 'cmap': plt.get_cmap('viridis') }, streamOpts={'color': 'k'}, ax=ax, mirror=True)[0], ax=ax) plotMe(fields[srcList[0], 'bSecondary'].real, ax[0]) ax[0].set_title('Real B-Secondary, {}Hz'.format(freqs[0])) plotMe(fields[srcList[1], 'bSecondary'].real, ax[1]) ax[1].set_title('Real B-Secondary, {}Hz'.format(freqs[1])) plt.tight_layout() if plotIt: plt.show()
invProb = InvProblem.BaseInvProblem(dmis, regT, opt) # Directives for Inversions beta = Directives.BetaEstimate_ByEig(beta0_ratio=1e+1) Target = Directives.TargetMisfit() betaSched = Directives.BetaSchedule(coolingFactor=5., coolingRate=2) inv = Inversion.BaseInversion(invProb, directiveList=[beta, Target, betaSched]) # Run Inversion minv = inv.run(m0) # Final Plot ############ fig, ax = plt.subplots(2, 2, figsize=(12, 6)) ax = Utils.mkvc(ax) cyl0v = getCylinderPoints(x0, z0, r0) cyl1v = getCylinderPoints(x1, z1, r1) cyl0h = getCylinderPoints(x0, y0, r0) cyl1h = getCylinderPoints(x1, y1, r1) clim = [(mtrue[actind]).min(), (mtrue[actind]).max()] dat = meshCore.plotSlice(((mtrue[actind])), ax=ax[0], normal='Y', clim=clim, ind=int(ncy / 2)) ax[0].set_title('Ground Truth, Vertical')