def getRHSDeriv_m(self, src, v, adjoint=False): C = self.mesh.edgeCurl MeMuI = self.MeMuI S_mDeriv, S_eDeriv = src.evalDeriv(self, adjoint) if adjoint: if self._makeASymmetric: MfRho = self.MfRho v = MfRho*v S_mDerivv = S_mDeriv(MeMuI.T * (C.T * v)) S_eDerivv = S_eDeriv(v) if S_mDerivv is not None and S_eDerivv is not None: return S_mDerivv - 1j * omega(freq) * S_eDerivv elif S_mDerivv is not None: return S_mDerivv elif S_eDerivv is not None: return - 1j * omega(freq) * S_eDerivv else: return None else: S_mDerivv, S_eDerivv = S_mDeriv(v), S_eDeriv(v) if S_mDerivv is not None and S_eDerivv is not None: RHSDeriv = C * (MeMuI * S_mDerivv) - 1j * omega(freq) * S_eDerivv elif S_mDerivv is not None: RHSDeriv = C * (MeMuI * S_mDerivv) elif S_eDerivv is not None: RHSDeriv = - 1j * omega(freq) * S_eDerivv else: return None if self._makeASymmetric: MfRho = self.MfRho return MfRho.T * RHSDeriv return RHSDeriv
def getRHSDeriv_m(self, src, v, adjoint=False): C = self.mesh.edgeCurl MfMui = self.MfMui S_mDeriv, S_eDeriv = src.evalDeriv(self, adjoint) if adjoint: dRHS = MfMui * (C * v) S_mDerivv = S_mDeriv(dRHS) S_eDerivv = S_eDeriv(v) if S_mDerivv is not None and S_eDerivv is not None: return S_mDerivv - 1j * omega(freq) * S_eDerivv elif S_mDerivv is not None: return S_mDerivv elif S_eDerivv is not None: return - 1j * omega(freq) * S_eDerivv else: return None else: S_mDerivv, S_eDerivv = S_mDeriv(v), S_eDeriv(v) if S_mDerivv is not None and S_eDerivv is not None: return C.T * (MfMui * S_mDerivv) -1j * omega(freq) * S_eDerivv elif S_mDerivv is not None: return C.T * (MfMui * S_mDerivv) elif S_eDerivv is not None: return -1j * omega(freq) * S_eDerivv else: return None
def getADeriv_m(self, freq, u, v, adjoint=False): dsig_dm = self.curModel.sigmaDeriv dMe_dsig = self.MeSigmaDeriv(u) if adjoint: return 1j * omega(freq) * ( dMe_dsig.T * v ) return 1j * omega(freq) * ( dMe_dsig * v )
def _hSecondary(self, jSolution, srcList): h = self._MeMuI * (self._edgeCurl.T * (self._MfRho * jSolution) ) for i, src in enumerate(srcList): h[:,i] *= -1./(1j*omega(src.freq)) S_m,_ = src.eval(self.prob) if S_m is not None: h[:,i] += 1./(1j*omega(src.freq)) * self._MeMuI * (S_m) return h
def getADeriv(self, freq, u, v, adjoint=False): sig = self.curTModel dsig_dm = self.curTModelDeriv dMe_dsig = self.mesh.getEdgeInnerProductDeriv(sig, v=u) if adjoint: return 1j * omega(freq) * (dsig_dm.T * (dMe_dsig.T * v)) return 1j * omega(freq) * (dMe_dsig * (dsig_dm * v))
def _bSecondary(self, eSolution, srcList): C = self._edgeCurl b = (C * eSolution) for i, src in enumerate(srcList): b[:,i] *= - 1./(1j*omega(src.freq)) S_m, _ = src.eval(self.prob) if S_m is not None: b[:,i] += 1./(1j*omega(src.freq)) * S_m return b
def getADeriv(self, freq, u, v, adjoint=False): sig = self.curTModel dsig_dm = self.curTModelDeriv dMe_dsig = self.mesh.getEdgeInnerProductDeriv(sig, v=u) if adjoint: return 1j * omega(freq) * ( dsig_dm.T * ( dMe_dsig.T * v ) ) return 1j * omega(freq) * ( dMe_dsig * ( dsig_dm * v ) )
def getADeriv_m(self, freq, u, v, adjoint=False): """ The derivative of A wrt sigma """ dsig_dm = self.curModel.sigmaDeriv MeMui = self.mesh.getEdgeInnerProduct(1.0/mu_0) # u_src = u['e_1dSolution'] dMf_dsig = self.mesh.getFaceInnerProductDeriv(self.curModel.sigma)(u_src) * self.curModel.sigmaDeriv if adjoint: return 1j * omega(freq) * ( dMf_dsig.T * v ) # Note: output has to be nN/nF, not nC/nE. # v should be nC return 1j * omega(freq) * ( dMf_dsig * v )
def fields(self, m, m_back): ''' Function to calculate all the fields for the model m. :param np.ndarray (nC,) m: Conductivity model :param np.ndarray (nC,) m_back: Background conductivity model ''' self.curModel = m self.backModel = m_back # RHS, CalcFields = self.getRHS(freq,m_back), self.calcFields F = FieldsMT_3D(self.mesh, self.survey) for freq in self.survey.freqs: if self.verbose: startTime = time.time() print 'Starting work for {:.3e}'.format(freq) sys.stdout.flush() A = self.getA(freq) rhs, e_p = self.getRHS(freq, m_back) Ainv = self.Solver(A, **self.solverOpts) e_s = Ainv * rhs e = e_s # Store the fields Src = self.survey.getSources(freq) # Store the fieldss F[Src, 'e_px'] = e[:, 0] F[Src, 'e_py'] = e[:, 1] # Note curl e = -iwb so b = -curl/iw b = -(self.mesh.edgeCurl * e) / (1j * omega(freq)) F[Src, 'b_px'] = b[:, 0] F[Src, 'b_py'] = b[:, 1] if self.verbose: print 'Ran for {:f} seconds'.format(time.time() - startTime) sys.stdout.flush() return F
def getA(self, freq, full=False): """ Function to get the A matrix. :param float freq: Frequency :param logic full: Return full A or the inner part :rtype: scipy.sparse.csr_matrix :return: A """ Mmui = self.mesh.getEdgeInnerProduct(1.0/mu_0) Msig = self.mesh.getFaceInnerProduct(self.curModel.sigma) # Note: need to use the code above since in the 1D problem I want # e to live on Faces(nodes) and h on edges(cells). Might need to rethink this # Possible that _fieldType and _eqLocs can fix this # Mmui = self.MfMui # Msig = self.MeSigma C = self.mesh.nodalGrad # Make A A = C.T*Mmui*C + 1j*omega(freq)*Msig # Either return full or only the inner part of A if full: return A else: return A[1:-1,1:-1]
def getADeriv_m(self, freq, u, v, adjoint=False): """ The derivative of A wrt sigma """ dsig_dm = self.curModel.sigmaDeriv MeMui = self.mesh.getEdgeInnerProduct(1.0 / mu_0) # u_src = u['e_1dSolution'] dMf_dsig = self.mesh.getFaceInnerProductDeriv( self.curModel.sigma)(u_src) * self.curModel.sigmaDeriv if adjoint: return 1j * omega(freq) * (dMf_dsig.T * v) # Note: output has to be nN/nF, not nC/nE. # v should be nC return 1j * omega(freq) * (dMf_dsig * v)
def getA(self, freq, full=False): """ Function to get the A matrix. :param float freq: Frequency :param logic full: Return full A or the inner part :rtype: scipy.sparse.csr_matrix :return: A """ Mmui = self.mesh.getEdgeInnerProduct(1.0 / mu_0) Msig = self.mesh.getFaceInnerProduct(self.curModel.sigma) # Note: need to use the code above since in the 1D problem I want # e to live on Faces(nodes) and h on edges(cells). Might need to rethink this # Possible that _fieldType and _eqLocs can fix this # Mmui = self.MfMui # Msig = self.MeSigma C = self.mesh.nodalGrad # Make A A = C.T * Mmui * C + 1j * omega(freq) * Msig # Either return full or only the inner part of A if full: return A else: return A[1:-1, 1:-1]
def getRHSDeriv_m(self, freq, v, adjoint=False): """ The derivative of the RHS with respect to sigma """ Src = self.survey.getSrcByFreq(freq)[0] S_eDeriv = Src.S_eDeriv_m(self, v, adjoint) return -1j * omega(freq) * S_eDeriv
def getRHSDeriv_m(self, freq, v, adjoint=False): """ The derivative of the RHS wrt sigma """ Src = self.survey.getSrcByFreq(freq)[0] S_eDeriv = Src.S_eDeriv_m(self, v, adjoint) return -1j * omega(freq) * S_eDeriv
def bPrimary(self,problem): # Project ePrimary to bPrimary # Satisfies the primary(background) field conditions if problem.mesh.dim == 1: C = problem.mesh.nodalGrad elif problem.mesh.dim == 3: C = problem.mesh.edgeCurl bBG_bp = (- C * self.ePrimary(problem) )*(1/( 1j*omega(self.freq) )) return bBG_bp
def bPrimary(self, problem): # Project ePrimary to bPrimary # Satisfies the primary(background) field conditions if problem.mesh.dim == 1: C = problem.mesh.nodalGrad elif problem.mesh.dim == 3: C = problem.mesh.edgeCurl bBG_bp = (-C * self.ePrimary(problem)) * (1 / (1j * omega(self.freq))) return bBG_bp
def _bSecondary(self, eSolution, srcList): C = self.mesh.nodalGrad b = C * eSolution for i, src in enumerate(srcList): b[:, i] *= -1.0 / (1j * omega(src.freq)) # There is no magnetic source in the MT problem # S_m, _ = src.eval(self.survey.prob) # if S_m is not None: # b[:,i] += 1./(1j*omega(src.freq)) * S_m return b
def _bSecondary(self, eSolution, srcList): C = self.mesh.nodalGrad b = (C * eSolution) for i, src in enumerate(srcList): b[:,i] *= - 1./(1j*omega(src.freq)) # There is no magnetic source in the MT problem # S_m, _ = src.eval(self.survey.prob) # if S_m is not None: # b[:,i] += 1./(1j*omega(src.freq)) * S_m return b
def getRHS(self, freq): """ Function to return the right hand side for the system. :param float freq: Frequency :rtype: numpy.ndarray (nE, 2), numpy.ndarray (nE, 2) :return: RHS for both polarizations, primary fields """ # Get sources for the frequncy(polarizations) Src = self.survey.getSrcByFreq(freq)[0] S_e = Src.S_e(self) return -1j * omega(freq) * S_e
def getRHS(self, freq): """ Function to return the right hand side for the system. :param float freq: Frequency :rtype: numpy.ndarray (nF, 1), numpy.ndarray (nF, 1) :return: RHS for 1 polarizations, primary fields """ # Get sources for the frequncy(polarizations) Src = self.survey.getSrcByFreq(freq)[0] S_e = Src.S_e(self) return -1j * omega(freq) * S_e
def getA(self, freq): """ Function to get the A matrix. :param float freq: Frequency :rtype: scipy.sparse.csr_matrix :return: A """ Mmui = self.MfMui Msig = self.MeSigma C = self.mesh.edgeCurl return C.T * Mmui * C + 1j * omega(freq) * Msig
def getA(self, freq): """ .. math :: \mathbf{A} = \mathbf{C}^T \mathbf{M_{\mu^{-1}}^f} \mathbf{C} + i \omega \mathbf{M^e_{\sigma}} :param float freq: Frequency :rtype: scipy.sparse.csr_matrix :return: A """ MfMui = self.MfMui MeSigma = self.MeSigma C = self.mesh.edgeCurl return C.T*MfMui*C + 1j*omega(freq)*MeSigma
def _hSecondaryDeriv_m(self, src, v, adjoint=False): jSolution = self[[src],'jSolution'] MeMuI = self._MeMuI C = self._edgeCurl MfRho = self._MfRho MfRhoDeriv = self._MfRhoDeriv Me = self._Me if not adjoint: hDeriv_m = -1./(1j*omega(src.freq)) * MeMuI * (C.T * (MfRhoDeriv(jSolution)*v ) ) elif adjoint: hDeriv_m = -1./(1j*omega(src.freq)) * MfRhoDeriv(jSolution).T * ( C * (MeMuI.T * v ) ) S_mDeriv,_ = src.evalDeriv(self.prob, adjoint) if not adjoint: S_mDeriv = S_mDeriv(v) if S_mDeriv is not None: hDeriv_m += 1./(1j*omega(src.freq)) * MeMuI * (Me * S_mDeriv) elif adjoint: S_mDeriv = S_mDeriv(Me.T * (MeMuI.T * v)) if S_mDeriv is not None: hDeriv_m += 1./(1j*omega(src.freq)) * S_mDeriv return hDeriv_m
def getA(self, freq): """ .. math :: \mathbf{A} = \mathbf{C}^T \mathbf{M_{\\rho}^f} \mathbf{C} + i \omega \mathbf{M_{\mu}^e} :param float freq: Frequency :rtype: scipy.sparse.csr_matrix :return: A """ MeMu = self.MeMu MfRho = self.MfRho C = self.mesh.edgeCurl return C.T * (MfRho * C) + 1j*omega(freq)*MeMu
def getRHS(self, freq): """ .. math :: \mathbf{RHS} = \mathbf{C}^T \mathbf{M_{\mu^{-1}}^f}\mathbf{s_m} -i\omega\mathbf{M_e}\mathbf{s_e} :param float freq: Frequency :rtype: numpy.ndarray (nE, nSrc) :return: RHS """ S_m, S_e = self.getSourceTerm(freq) C = self.mesh.edgeCurl MfMui = self.MfMui # RHS = C.T * (MfMui * S_m) -1j * omega(freq) * Me * S_e RHS = C.T * (MfMui * S_m) -1j * omega(freq) * S_e return RHS
def getA(self, freq): """ .. math :: \mathbf{A} = \mathbf{C} \mathbf{M^e_{\sigma}}^{-1} \mathbf{C}^T \mathbf{M_{\mu^{-1}}^f} + i \omega :param float freq: Frequency :rtype: scipy.sparse.csr_matrix :return: A """ MfMui = self.MfMui MeSigmaI = self.MeSigmaI C = self.mesh.edgeCurl iomega = 1j * omega(freq) * sp.eye(self.mesh.nF) A = C * (MeSigmaI * (C.T * MfMui)) + iomega if self._makeASymmetric is True: return MfMui.T*A return A
def getA(self, freq): """ .. math :: \\mathbf{A} = \\mathbf{C} \\mathbf{M^e_{mu^{-1}}} \\mathbf{C}^T \\mathbf{M^f_{\\sigma^{-1}}} + i\\omega :param float freq: Frequency :rtype: scipy.sparse.csr_matrix :return: A """ MeMuI = self.MeMuI MfRho = self.MfRho C = self.mesh.edgeCurl iomega = 1j * omega(freq) * sp.eye(self.mesh.nF) A = C * MeMuI * C.T * MfRho + iomega if self._makeASymmetric is True: return MfRho.T*A return A
def getRHS(self, freq): """ .. math :: \mathbf{RHS} = \mathbf{C} \mathbf{M_{\mu}^e}^{-1}\mathbf{s_m} -i\omega \mathbf{s_e} :param float freq: Frequency :rtype: numpy.ndarray (nE, nSrc) :return: RHS """ S_m, S_e = self.getSourceTerm(freq) C = self.mesh.edgeCurl MeMuI = self.MeMuI RHS = C * (MeMuI * S_m) - 1j * omega(freq) * S_e if self._makeASymmetric is True: MfRho = self.MfRho return MfRho.T*RHS return RHS
def getRHS(self, freq, backSigma): """ Function to return the right hand side for the system. :param float freq: Frequency :param numpy.ndarray (nC,) backSigma: Background conductivity model :rtype: numpy.ndarray (nE, 2) :return: one RHS for both polarizations """ # Get sources for the frequency src = self.survey.getSources(freq) # Make sure that there is 2 polarizations. # assert len() # Get the background electric fields from simpegMT.Sources import homo1DModelSource eBG_bp = homo1DModelSource(self.mesh, freq, backSigma) MeBack = self.MeSigmaBack # Set up the A system mui = self.MfMui C = self.mesh.edgeCurl Abg = C.T * mui * C + 1j * omega(freq) * MeBack return Abg * eBG_bp, eBG_bp
def getADeriv_m(self, freq, u, v, adjoint=False): # Nee to account for both the polarizations # dMe_dsig = (self.MeSigmaDeriv( u['e_pxSolution'] ) + self.MeSigmaDeriv( u['e_pySolution'] )) # dMe_dsig = (self.MeSigmaDeriv( u['e_pxSolution'] + u['e_pySolution'] )) # # dMe_dsig = self.MeSigmaDeriv( u ) # if adjoint: # return 1j * omega(freq) * ( dMe_dsig.T * v ) # As in simpegEM # return 1j * omega(freq) * ( dMe_dsig * v ) # As in simpegEM # This considers both polarizations and returns a nE,2 matrix for each polarization if adjoint: dMe_dsigV = sp.hstack((self.MeSigmaDeriv(u['e_pxSolution']).T, self.MeSigmaDeriv(u['e_pySolution']).T)) * v else: # Need a nE,2 matrix to be returned dMe_dsigV = np.hstack( (mkvc(self.MeSigmaDeriv(u['e_pxSolution']) * v, 2), mkvc(self.MeSigmaDeriv(u['e_pySolution']) * v, 2))) return 1j * omega(freq) * dMe_dsigV
def _b_pySecondaryDeriv_u(self, src, v, adjoint = False): # C = sp.kron(self.mesh.edgeCurl,[[0,0],[0,1]]) C = sp.hstack((Utils.spzeros(self.mesh.nF,self.mesh.nE),self.mesh.edgeCurl)) # This works for adjoint = None if adjoint: return - 1./(1j*omega(src.freq)) * (C.T * v) return - 1./(1j*omega(src.freq)) * (C * v)
def S_m(self, prob): b = self.bPrimary(prob) return -1j*omega(self.freq)*b
def _bSecondaryDeriv_u(self, src, v, adjoint = False): C = self.mesh.nodalGrad if adjoint: return - 1./(1j*omega(src.freq)) * (C.T * v) return - 1./(1j*omega(src.freq)) * (C * v)
def _b_pySecondaryDeriv_u(self, src, v, adjoint=False): # C = sp.kron(self.mesh.edgeCurl,[[0,0],[0,1]]) C = sp.hstack((Utils.spzeros(self.mesh.nF, self.mesh.nE), self.mesh.edgeCurl)) # This works for adjoint = None if adjoint: return -1.0 / (1j * omega(src.freq)) * (C.T * v) return -1.0 / (1j * omega(src.freq)) * (C * v)
def _bSecondaryDeriv_m(self, src, v, adjoint = False): S_mDeriv, _ = src.evalDeriv(self.prob, adjoint) S_mDeriv = S_mDeriv(v) if S_mDeriv is not None: return 1./(1j * omega(src.freq)) * S_mDeriv return None
def _bSecondaryDeriv_u(self, src, v, adjoint = False): C = self._edgeCurl if adjoint: return - 1./(1j*omega(src.freq)) * (C.T * v) return - 1./(1j*omega(src.freq)) * (C * v)
def _bSecondaryDeriv_u(self, src, v, adjoint=False): C = self.mesh.nodalGrad if adjoint: return -1.0 / (1j * omega(src.freq)) * (C.T * v) return -1.0 / (1j * omega(src.freq)) * (C * v)
def _hSecondaryDeriv_u(self, src, v, adjoint=False): if not adjoint: return -1./(1j*omega(src.freq)) * self._MeMuI * (self._edgeCurl.T * (self._MfRho * v) ) elif adjoint: return -1./(1j*omega(src.freq)) * self._MfRho.T * (self._edgeCurl * ( self._MeMuI.T * v))