From 8aa23c31de6fdadde3b3f3059d411251851ebcd4 Mon Sep 17 00:00:00 2001 From: Rowan Cockett Date: Tue, 16 Feb 2016 21:53:31 -0800 Subject: [PATCH 01/18] Allow moving off bounds in projected gradient. The current implementation does not allow you to move off the bounds (lower/upper) once you have gotten on them, this allows you to move off of the bound. Please note that more testing should be done to ensure that this does not introduce oscillations into the optimization routine. --- SimPEG/Optimization.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/SimPEG/Optimization.py b/SimPEG/Optimization.py index 4f2cb062..54f6c4ff 100644 --- a/SimPEG/Optimization.py +++ b/SimPEG/Optimization.py @@ -990,4 +990,18 @@ class ProjectedGNCG(BFGS, Minimize, Remember): cgFlag = 1 # End CG Iterations + # Take a gradient step on the active cells if exist + if temp != self.xc.size: + + rhs_a = (Active) * -self.g + + dm_i = max( abs( delx ) ) + dm_a = max( abs(rhs_a) ) + + delx = delx + rhs_a * dm_i / dm_a /10. + + # Only keep gradients going in the right direction on the active set + indx = ((self.xc<=self.lower) & (delx < 0)) | ((self.xc>=self.upper) & (delx > 0)) + delx[indx] = 0. + return delx From 3d11431f2fc88da5553179072f57a84f6e0cde69 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Sun, 20 Mar 2016 11:47:57 -0700 Subject: [PATCH 02/18] use f where we are talking about fields --- SimPEG/EM/FDEM/FDEM.py | 112 ++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/SimPEG/EM/FDEM/FDEM.py b/SimPEG/EM/FDEM/FDEM.py index cf3dee7f..834c0187 100644 --- a/SimPEG/EM/FDEM/FDEM.py +++ b/SimPEG/EM/FDEM/FDEM.py @@ -18,9 +18,9 @@ class BaseFDEMProblem(BaseEMProblem): {\mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f} \mathbf{b} - \mathbf{M_{\sigma}^e} \mathbf{e} = \mathbf{s_e}} if using the E-B formulation (:code:`Problem_e` - or :code:`Problem_b`). Note that in this case, :math:`\mathbf{s_e}` is an integrated quantity. + or :code:`Problem_b`). Note that in this case, :math:`\mathbf{s_e}` is an integrated quantity. - If we write Maxwell's equations in terms of + If we write Maxwell's equations in terms of \\\(\\\mathbf{h}\\\) and current density \\\(\\\mathbf{j}\\\) .. math :: @@ -28,7 +28,7 @@ class BaseFDEMProblem(BaseEMProblem): \mathbf{C}^{\\top} \mathbf{M_{\\rho}^f} \mathbf{j} + i \omega \mathbf{M_{\mu}^e} \mathbf{h} = \mathbf{s_m} \\\\ \mathbf{C} \mathbf{h} - \mathbf{j} = \mathbf{s_e} - if using the H-J formulation (:code:`Problem_j` or :code:`Problem_h`). Note that here, :math:`\mathbf{s_m}` is an integrated quantity. + if using the H-J formulation (:code:`Problem_j` or :code:`Problem_h`). Note that here, :math:`\mathbf{s_m}` is an integrated quantity. The problem performs the elimination so that we are solving the system for \\\(\\\mathbf{e},\\\mathbf{b},\\\mathbf{j} \\\) or \\\(\\\mathbf{h}\\\) """ @@ -39,73 +39,73 @@ class BaseFDEMProblem(BaseEMProblem): def fields(self, m=None): """ Solve the forward problem for the fields. - + :param numpy.array m: inversion model (nP,) :rtype numpy.array: - :return F: forward solution + :return f: forward solution """ self.curModel = m - F = self.fieldsPair(self.mesh, self.survey) + f = self.fieldsPair(self.mesh, self.survey) for freq in self.survey.freqs: A = self.getA(freq) rhs = self.getRHS(freq) Ainv = self.Solver(A, **self.solverOpts) - sol = Ainv * rhs + u = Ainv * rhs Srcs = self.survey.getSrcByFreq(freq) - F[Srcs, self._solutionType] = sol + f[Srcs, self._solutionType] = u Ainv.clean() - return F + return f - def Jvec(self, m, v, u=None): + 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.Fields u: fields object + :param SimPEG.EM.FDEM.Fields u: fields object :rtype numpy.array: - :return: Jv (ndata,) + :return: Jv (ndata,) """ - if u is None: - u = self.fields(m) + 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) + 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 = u[src, self._solutionType] - dA_dm_v = self.getADeriv(freq, u_src, v) - dRHS_dm_v = self.getRHSDeriv(freq, src, v) + f_src = f[src, self._solutionType] + dA_dm_v = self.getADeriv(freq, f_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(u, '_%sDeriv'%rx.projField, None) + df_dmFun = getattr(f, '_%sDeriv'%rx.projField, None) df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False) - Jv[src, rx] = rx.evalDeriv(src, self.mesh, u, df_dm_v) + Jv[src, rx] = rx.evalDeriv(src, self.mesh, f, df_dm_v) Ainv.clean() return Utils.mkvc(Jv) - def Jtvec(self, m, v, u=None): + def Jtvec(self, m, v, f=None): """ Sensitivity transpose times a vector :param numpy.array m: inversion model (nP,) :param numpy.array v: vector which we take adjoint product with (nP,) - :param SimPEG.EM.FDEM.Fields u: fields object + :param SimPEG.EM.FDEM.Fields u: fields object :rtype numpy.array: - :return: Jv (ndata,) + :return: Jv (ndata,) """ - if u is None: - u = self.fields(m) + if f is None: + f = self.fields(m) self.curModel = m @@ -120,17 +120,17 @@ class BaseFDEMProblem(BaseEMProblem): ATinv = self.Solver(AT, **self.solverOpts) for src in self.survey.getSrcByFreq(freq): - u_src = u[src, self._solutionType] + f_src = f[src, self._solutionType] for rx in src.rxList: - PTv = rx.evalDeriv(src, self.mesh, u, v[src, rx], adjoint=True) # wrt u, need possibility wrt m + PTv = rx.evalDeriv(src, self.mesh, f, v[src, rx], adjoint=True) # wrt f, need possibility wrt m - df_duTFun = getattr(u, '_%sDeriv'%rx.projField, None) + df_duTFun = getattr(f, '_%sDeriv'%rx.projField, None) df_duT, df_dmT = df_duTFun(src, None, PTv, adjoint=True) ATinvdf_duT = ATinv * df_duT - dA_dmT = self.getADeriv(freq, u_src, ATinvdf_duT, adjoint=True) + dA_dmT = self.getADeriv(freq, f_src, ATinvdf_duT, adjoint=True) dRHS_dmT = self.getRHSDeriv(freq, src, ATinvdf_duT, adjoint=True) du_dmT = -dA_dmT + dRHS_dmT @@ -144,7 +144,7 @@ class BaseFDEMProblem(BaseEMProblem): Jtv += - np.array(df_dmT, dtype=complex).real else: raise Exception('Must be real or imag') - + ATinv.clean() return Utils.mkvc(Jtv) @@ -154,7 +154,7 @@ class BaseFDEMProblem(BaseEMProblem): Evaluates the sources for a given frequency and puts them in matrix form :param float freq: Frequency - :rtype: (numpy.ndarray, numpy.ndarray) + :rtype: (numpy.ndarray, numpy.ndarray) :return: S_m, S_e (nE or nF, nSrc) """ Srcs = self.survey.getSrcByFreq(freq) @@ -207,7 +207,7 @@ class Problem_e(BaseFDEMProblem): def getA(self, freq): """ System matrix - + .. math :: \mathbf{A} = \mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f} \mathbf{C} + i \omega \mathbf{M^e_{\sigma}} @@ -230,12 +230,12 @@ class Problem_e(BaseFDEMProblem): .. math :: \\frac{\mathbf{A}(\mathbf{m}) \mathbf{v}}{d \mathbf{m}} = i \omega \\frac{d \mathbf{M^e_{\sigma}}\mathbf{v} }{d\mathbf{m}} - :param float freq: frequency - :param numpy.ndarray u: solution vector (nE,) + :param float freq: frequency + :param numpy.ndarray u: solution vector (nE,) :param numpy.ndarray v: vector to take prodct with (nP,) or (nD,) for adjoint :param bool adjoint: adjoint? :rtype: numpy.ndarray - :return: derivative of the system matrix times a vector (nP,) or adjoint (nD,) + :return: derivative of the system matrix times a vector (nP,) or adjoint (nD,) """ dsig_dm = self.curModel.sigmaDeriv @@ -248,13 +248,13 @@ class Problem_e(BaseFDEMProblem): def getRHS(self, freq): """ - Right hand side for the system + Right hand side for the system .. math :: \mathbf{RHS} = \mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f}\mathbf{s_m} -i\omega\mathbf{M_e}\mathbf{s_e} :param float freq: Frequency - :rtype: numpy.ndarray + :rtype: numpy.ndarray :return: RHS (nE, nSrc) """ @@ -266,7 +266,7 @@ class Problem_e(BaseFDEMProblem): def getRHSDeriv(self, freq, src, v, adjoint=False): """ - Derivative of the right hand side with respect to the model + Derivative of the right hand side with respect to the model :param float freq: frequency :param SimPEG.EM.FDEM.Src src: FDEM source @@ -346,12 +346,12 @@ class Problem_b(BaseFDEMProblem): .. math :: \\frac{\mathbf{A}(\mathbf{m}) \mathbf{v}}{d \mathbf{m}} = \mathbf{C} \\frac{\mathbf{M^e_{\sigma}} \mathbf{v}}{d\mathbf{m}} - :param float freq: frequency - :param numpy.ndarray u: solution vector (nF,) + :param float freq: frequency + :param numpy.ndarray u: solution vector (nF,) :param numpy.ndarray v: vector to take prodct with (nP,) or (nD,) for adjoint :param bool adjoint: adjoint? :rtype: numpy.ndarray - :return: derivative of the system matrix times a vector (nP,) or adjoint (nD,) + :return: derivative of the system matrix times a vector (nP,) or adjoint (nD,) """ MfMui = self.MfMui @@ -373,13 +373,13 @@ class Problem_b(BaseFDEMProblem): def getRHS(self, freq): """ - Right hand side for the system + Right hand side for the system .. math :: \mathbf{RHS} = \mathbf{s_m} + \mathbf{M^e_{\sigma}}^{-1}\mathbf{s_e} :param float freq: Frequency - :rtype: numpy.ndarray + :rtype: numpy.ndarray :return: RHS (nE, nSrc) """ @@ -497,12 +497,12 @@ class Problem_j(BaseFDEMProblem): \\frac{\mathbf{A(\sigma)} \mathbf{v}}{d \mathbf{m}} = \mathbf{C} \mathbf{M^e_{mu^{-1}}} \mathbf{C^{\\top}} \\frac{d \mathbf{M^f_{\sigma^{-1}}}\mathbf{v} }{d \mathbf{m}} - :param float freq: frequency - :param numpy.ndarray u: solution vector (nF,) + :param float freq: frequency + :param numpy.ndarray u: solution vector (nF,) :param numpy.ndarray v: vector to take prodct with (nP,) or (nD,) for adjoint :param bool adjoint: adjoint? :rtype: numpy.ndarray - :return: derivative of the system matrix times a vector (nP,) or adjoint (nD,) + :return: derivative of the system matrix times a vector (nP,) or adjoint (nD,) """ MeMuI = self.MeMuI @@ -522,7 +522,7 @@ class Problem_j(BaseFDEMProblem): def getRHS(self, freq): """ - Right hand side for the system + Right hand side for the system .. math :: @@ -546,7 +546,7 @@ class Problem_j(BaseFDEMProblem): def getRHSDeriv(self, freq, src, v, adjoint=False): """ - Derivative of the right hand side with respect to the model + Derivative of the right hand side with respect to the model :param float freq: frequency :param SimPEG.EM.FDEM.Src src: FDEM source @@ -626,12 +626,12 @@ class Problem_h(BaseFDEMProblem): .. math:: \\frac{\mathbf{A}(\mathbf{m}) \mathbf{v}}{d \mathbf{m}} = \mathbf{C}^{\\top}\\frac{d \mathbf{M^f_{\\rho}}\mathbf{v} }{d\mathbf{m}} - :param float freq: frequency - :param numpy.ndarray u: solution vector (nE,) + :param float freq: frequency + :param numpy.ndarray u: solution vector (nE,) :param numpy.ndarray v: vector to take prodct with (nP,) or (nD,) for adjoint :param bool adjoint: adjoint? :rtype: numpy.ndarray - :return: derivative of the system matrix times a vector (nP,) or adjoint (nD,) + :return: derivative of the system matrix times a vector (nP,) or adjoint (nD,) """ MeMu = self.MeMu @@ -644,14 +644,14 @@ class Problem_h(BaseFDEMProblem): def getRHS(self, freq): """ - Right hand side for the system + Right hand side for the system .. math :: \mathbf{RHS} = \mathbf{M^e} \mathbf{s_m} + \mathbf{C}^{\\top} \mathbf{M_{\\rho}^f} \mathbf{s_e} :param float freq: Frequency - :rtype: numpy.ndarray + :rtype: numpy.ndarray :return: RHS (nE, nSrc) """ @@ -663,7 +663,7 @@ class Problem_h(BaseFDEMProblem): def getRHSDeriv(self, freq, src, v, adjoint=False): """ - Derivative of the right hand side with respect to the model + Derivative of the right hand side with respect to the model :param float freq: frequency :param SimPEG.EM.FDEM.Src src: FDEM source From d5f73d0fd35ac9b671cb70ffad4f4418e5955c65 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Sun, 20 Mar 2016 11:56:58 -0700 Subject: [PATCH 03/18] f_src is actually u_src --- SimPEG/EM/FDEM/FDEM.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SimPEG/EM/FDEM/FDEM.py b/SimPEG/EM/FDEM/FDEM.py index 834c0187..5c2683b2 100644 --- a/SimPEG/EM/FDEM/FDEM.py +++ b/SimPEG/EM/FDEM/FDEM.py @@ -81,8 +81,8 @@ class BaseFDEMProblem(BaseEMProblem): Ainv = self.Solver(A, **self.solverOpts) # create the concept of Ainv (actually a solve) for src in self.survey.getSrcByFreq(freq): - f_src = f[src, self._solutionType] - dA_dm_v = self.getADeriv(freq, f_src, v) + 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 ) @@ -120,7 +120,7 @@ class BaseFDEMProblem(BaseEMProblem): ATinv = self.Solver(AT, **self.solverOpts) for src in self.survey.getSrcByFreq(freq): - f_src = f[src, self._solutionType] + 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 @@ -130,7 +130,7 @@ class BaseFDEMProblem(BaseEMProblem): ATinvdf_duT = ATinv * df_duT - dA_dmT = self.getADeriv(freq, f_src, ATinvdf_duT, adjoint=True) + dA_dmT = self.getADeriv(freq, u_src, ATinvdf_duT, adjoint=True) dRHS_dmT = self.getRHSDeriv(freq, src, ATinvdf_duT, adjoint=True) du_dmT = -dA_dmT + dRHS_dmT From 055061ac3b34c04e03d3037006729a22e0d5a295 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Sun, 20 Mar 2016 12:15:52 -0700 Subject: [PATCH 04/18] abstracted FDEM survey to BaseEMSurvey (with methods eval and eval deriv) as this should be common to FDEM and TDEM problems (only implemented on FDEM problem, TDEM inheritance will be taken care of on the TDEM refactor branch) --- SimPEG/EM/Base.py | 51 ++++++++++++++++++++++++++---------- SimPEG/EM/FDEM/SurveyFDEM.py | 27 +++++-------------- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/SimPEG/EM/Base.py b/SimPEG/EM/Base.py index 32018f7e..12d1ae43 100644 --- a/SimPEG/EM/Base.py +++ b/SimPEG/EM/Base.py @@ -2,14 +2,14 @@ from SimPEG import Survey, Problem, Utils, Models, Maps, PropMaps, np, sp, Solve from scipy.constants import mu_0 class EMPropMap(Maps.PropMap): - """ + """ Property Map for EM Problems. The electrical conductivity (\\(\\sigma\\)) is the default inversion property, and the default value of the magnetic permeability is that of free space (\\(\\mu = 4\\pi\\times 10^{-7} \\) H/m) """ sigma = Maps.Property("Electrical Conductivity", defaultInvProp = True, propertyLink=('rho',Maps.ReciprocalMap)) mu = Maps.Property("Inverse Magnetic Permeability", defaultVal = mu_0, propertyLink=('mui',Maps.ReciprocalMap)) - rho = Maps.Property("Electrical Resistivity", propertyLink=('sigma', Maps.ReciprocalMap)) + rho = Maps.Property("Electrical Resistivity", propertyLink=('sigma', Maps.ReciprocalMap)) mui = Maps.Property("Inverse Magnetic Permeability", defaultVal = 1./mu_0, propertyLink=('mu', Maps.ReciprocalMap)) @@ -21,7 +21,7 @@ class BaseEMProblem(Problem.BaseProblem): surveyPair = Survey.BaseSurvey dataPair = Survey.Data - + PropMap = EMPropMap Solver = SimpegSolver @@ -51,7 +51,7 @@ class BaseEMProblem(Problem.BaseProblem): if self.mapping.muMap is not None or self.mapping.muiMap is not None: toDelete += ['_MeMu', '_MeMuI','_MfMui','_MfMuiI'] return toDelete - + @property def Me(self): """ @@ -71,7 +71,7 @@ class BaseEMProblem(Problem.BaseProblem): return self._Mf - # ----- Magnetic Permeability ----- # + # ----- Magnetic Permeability ----- # @property def MfMui(self): """ @@ -109,7 +109,7 @@ class BaseEMProblem(Problem.BaseProblem): return self._MeMuI - # ----- Electrical Conductivity ----- # + # ----- Electrical Conductivity ----- # #TODO: hardcoded to sigma as the model @property def MeSigma(self): @@ -120,18 +120,18 @@ class BaseEMProblem(Problem.BaseProblem): self._MeSigma = self.mesh.getEdgeInnerProduct(self.curModel.sigma) return self._MeSigma - # TODO: This should take a vector + # TODO: This should take a vector def MeSigmaDeriv(self, u): """ Derivative of MeSigma with respect to the model - """ + """ return self.mesh.getEdgeInnerProductDeriv(self.curModel.sigma)(u) * self.curModel.sigmaDeriv - + @property def MeSigmaI(self): """ - Inverse of the edge inner product matrix for \\(\\sigma\\). + Inverse of the edge inner product matrix for \\(\\sigma\\). """ if getattr(self, '_MeSigmaI', None) is None: self._MeSigmaI = self.mesh.getEdgeInnerProduct(self.curModel.sigma, invMat=True) @@ -140,8 +140,8 @@ class BaseEMProblem(Problem.BaseProblem): # TODO: This should take a vector def MeSigmaIDeriv(self, u): """ - Derivative of :code:`MeSigma` with respect to the model - """ + Derivative of :code:`MeSigma` with respect to the model + """ # TODO: only works for diagonal tensors. getEdgeInnerProductDeriv, invMat=True should be implemented in SimPEG dMeSigmaI_dI = -self.MeSigmaI**2 @@ -163,7 +163,7 @@ class BaseEMProblem(Problem.BaseProblem): # TODO: This should take a vector def MfRhoDeriv(self,u): """ - Derivative of :code:`MfRho` with respect to the model. + Derivative of :code:`MfRho` with respect to the model. """ return self.mesh.getFaceInnerProductDeriv(self.curModel.rho)(u) * (-Utils.sdiag(self.curModel.rho**2) * self.curModel.sigmaDeriv) # self.curModel.rhoDeriv @@ -181,6 +181,29 @@ class BaseEMProblem(Problem.BaseProblem): # TODO: This should take a vector def MfRhoIDeriv(self,u): """ - Derivative of :code:`MfRhoI` with respect to the model. + Derivative of :code:`MfRhoI` with respect to the model. """ return self.mesh.getFaceInnerProductDeriv(self.curModel.rho, invMat=True)(u) * self.curModel.rhoDeriv + +class BaseEMSurvey(Survey.BaseSurvey): + + def __init__(self, srcList, **kwargs): + # Sort these by frequency + self.srcList = srcList + Survey.BaseSurvey.__init__(self, **kwargs) + + def eval(self, u): + """ + Project fields to receiver locations + :param Fields u: fields object + :rtype: numpy.ndarray + :return: data + """ + data = SimPEG.Survey.Data(self) + for src in self.srcList: + for rx in src.rxList: + data[src, rx] = rx.eval(src, self.mesh, u) + return data + + def evalDeriv(self, u): + raise Exception('Use Receivers to project fields deriv.') diff --git a/SimPEG/EM/FDEM/SurveyFDEM.py b/SimPEG/EM/FDEM/SurveyFDEM.py index ce803ed1..163f6914 100644 --- a/SimPEG/EM/FDEM/SurveyFDEM.py +++ b/SimPEG/EM/FDEM/SurveyFDEM.py @@ -1,5 +1,6 @@ import SimPEG from SimPEG.EM.Utils import * +from SimPEG.EM.Base import BaseEMSurvey from scipy.constants import mu_0 from SimPEG.Utils import Zero, Identity import SrcFDEM as Src @@ -84,7 +85,7 @@ class Rx(SimPEG.Survey.BaseRx): # get the real or imag component real_or_imag = self.projComp u_part = getattr(u_part_complex, real_or_imag) - + return P*u_part def evalDeriv(self, src, mesh, u, v, adjoint=False): @@ -123,7 +124,7 @@ class Rx(SimPEG.Survey.BaseRx): # Survey #################################################### -class Survey(SimPEG.Survey.BaseSurvey): +class Survey(BaseEMSurvey): """ Frequency domain electromagnetic survey @@ -131,12 +132,12 @@ class Survey(SimPEG.Survey.BaseSurvey): """ srcPair = Src.BaseSrc - rxPaair = Rx + rxPair = Rx def __init__(self, srcList, **kwargs): # Sort these by frequency self.srcList = srcList - SimPEG.Survey.BaseSurvey.__init__(self, **kwargs) + BaseEMSurvey.__init__(self, srcList, **kwargs) _freqDict = {} for src in srcList: @@ -171,24 +172,8 @@ class Survey(SimPEG.Survey.BaseSurvey): Returns the sources associated with a specific frequency. :param float freq: frequency for which we look up sources :rtype: dictionary - :return: sources at the sepcified frequency + :return: sources at the sepcified frequency """ assert freq in self._freqDict, "The requested frequency is not in this survey." return self._freqDict[freq] - def eval(self, u): - """ - Project fields to receiver locations - :param Fields u: fields object - :rtype: numpy.ndarray - :return: data - """ - data = SimPEG.Survey.Data(self) - for src in self.srcList: - for rx in src.rxList: - data[src, rx] = rx.eval(src, self.mesh, u) - return data - - def evalDeriv(self, u): - raise Exception('Use Receivers to project fields deriv.') - From cc9d2e5ac79b142ac3f412fa530193d77cfdf116 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Sun, 20 Mar 2016 12:18:07 -0700 Subject: [PATCH 05/18] we don't support m is none --- SimPEG/EM/FDEM/FDEM.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SimPEG/EM/FDEM/FDEM.py b/SimPEG/EM/FDEM/FDEM.py index 5c2683b2..3c2183b1 100644 --- a/SimPEG/EM/FDEM/FDEM.py +++ b/SimPEG/EM/FDEM/FDEM.py @@ -36,7 +36,7 @@ class BaseFDEMProblem(BaseEMProblem): surveyPair = SurveyFDEM fieldsPair = Fields - def fields(self, m=None): + def fields(self, m): """ Solve the forward problem for the fields. From c51afa4aad66487fd2c9f104385a93f9fd8229b5 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Sun, 20 Mar 2016 13:04:02 -0700 Subject: [PATCH 06/18] s_m, s_e are vectors (so they should not be capitalized) --- SimPEG/EM/FDEM/FDEM.py | 62 ++++----- SimPEG/EM/FDEM/FieldsFDEM.py | 254 +++++++++++++++++------------------ SimPEG/EM/FDEM/SrcFDEM.py | 96 ++++++------- 3 files changed, 206 insertions(+), 206 deletions(-) diff --git a/SimPEG/EM/FDEM/FDEM.py b/SimPEG/EM/FDEM/FDEM.py index 3c2183b1..caca7602 100644 --- a/SimPEG/EM/FDEM/FDEM.py +++ b/SimPEG/EM/FDEM/FDEM.py @@ -155,22 +155,22 @@ class BaseFDEMProblem(BaseEMProblem): :param float freq: Frequency :rtype: (numpy.ndarray, numpy.ndarray) - :return: S_m, S_e (nE or nF, nSrc) + :return: s_m, s_e (nE or nF, nSrc) """ Srcs = self.survey.getSrcByFreq(freq) if self._formulation is 'EB': - S_m = np.zeros((self.mesh.nF,len(Srcs)), dtype=complex) - S_e = np.zeros((self.mesh.nE,len(Srcs)), dtype=complex) + s_m = np.zeros((self.mesh.nF,len(Srcs)), dtype=complex) + s_e = np.zeros((self.mesh.nE,len(Srcs)), dtype=complex) elif self._formulation is 'HJ': - S_m = np.zeros((self.mesh.nE,len(Srcs)), dtype=complex) - S_e = np.zeros((self.mesh.nF,len(Srcs)), dtype=complex) + s_m = np.zeros((self.mesh.nE,len(Srcs)), dtype=complex) + s_e = np.zeros((self.mesh.nF,len(Srcs)), dtype=complex) for i, src in enumerate(Srcs): smi, sei = src.eval(self) - S_m[:,i] = S_m[:,i] + smi - S_e[:,i] = S_e[:,i] + sei + s_m[:,i] = s_m[:,i] + smi + s_e[:,i] = s_e[:,i] + sei - return S_m, S_e + return s_m, s_e ########################################################################################## @@ -258,11 +258,11 @@ class Problem_e(BaseFDEMProblem): :return: RHS (nE, nSrc) """ - S_m, S_e = self.getSourceTerm(freq) + s_m, s_e = self.getSourceTerm(freq) C = self.mesh.edgeCurl MfMui = self.MfMui - return C.T * (MfMui * S_m) -1j * omega(freq) * S_e + return C.T * (MfMui * s_m) -1j * omega(freq) * s_e def getRHSDeriv(self, freq, src, v, adjoint=False): """ @@ -278,14 +278,14 @@ class Problem_e(BaseFDEMProblem): C = self.mesh.edgeCurl MfMui = self.MfMui - S_mDeriv, S_eDeriv = src.evalDeriv(self, adjoint=adjoint) + s_mDeriv, s_eDeriv = src.evalDeriv(self, adjoint=adjoint) if adjoint: dRHS = MfMui * (C * v) - return S_mDeriv(dRHS) - 1j * omega(freq) * S_eDeriv(v) + return s_mDeriv(dRHS) - 1j * omega(freq) * s_eDeriv(v) else: - return C.T * (MfMui * S_mDeriv(v)) -1j * omega(freq) * S_eDeriv(v) + return C.T * (MfMui * s_mDeriv(v)) -1j * omega(freq) * s_eDeriv(v) class Problem_b(BaseFDEMProblem): @@ -383,11 +383,11 @@ class Problem_b(BaseFDEMProblem): :return: RHS (nE, nSrc) """ - S_m, S_e = self.getSourceTerm(freq) + s_m, s_e = self.getSourceTerm(freq) C = self.mesh.edgeCurl MeSigmaI = self.MeSigmaI - RHS = S_m + C * ( MeSigmaI * S_e ) + RHS = s_m + C * ( MeSigmaI * s_e ) if self._makeASymmetric is True: MfMui = self.MfMui @@ -408,21 +408,21 @@ class Problem_b(BaseFDEMProblem): """ C = self.mesh.edgeCurl - S_m, S_e = src.eval(self) + s_m, s_e = src.eval(self) MfMui = self.MfMui if self._makeASymmetric and adjoint: v = self.MfMui * v - MeSigmaIDeriv = self.MeSigmaIDeriv(S_e) - S_mDeriv, S_eDeriv = src.evalDeriv(self, adjoint=adjoint) + MeSigmaIDeriv = self.MeSigmaIDeriv(s_e) + s_mDeriv, s_eDeriv = src.evalDeriv(self, adjoint=adjoint) if not adjoint: RHSderiv = C * (MeSigmaIDeriv * v) - SrcDeriv = S_mDeriv(v) + C * (self.MeSigmaI * S_eDeriv(v)) + SrcDeriv = s_mDeriv(v) + C * (self.MeSigmaI * s_eDeriv(v)) elif adjoint: RHSderiv = MeSigmaIDeriv.T * (C.T * v) - SrcDeriv = S_mDeriv(v) + self.MeSigmaI.T * (C.T * S_eDeriv(v)) + SrcDeriv = s_mDeriv(v) + self.MeSigmaI.T * (C.T * s_eDeriv(v)) if self._makeASymmetric is True and not adjoint: return MfMui.T * (SrcDeriv + RHSderiv) @@ -533,11 +533,11 @@ class Problem_j(BaseFDEMProblem): :return: RHS """ - S_m, S_e = self.getSourceTerm(freq) + s_m, s_e = self.getSourceTerm(freq) C = self.mesh.edgeCurl MeMuI = self.MeMuI - RHS = C * (MeMuI * S_m) - 1j * omega(freq) * S_e + RHS = C * (MeMuI * s_m) - 1j * omega(freq) * s_e if self._makeASymmetric is True: MfRho = self.MfRho return MfRho.T*RHS @@ -558,16 +558,16 @@ class Problem_j(BaseFDEMProblem): C = self.mesh.edgeCurl MeMuI = self.MeMuI - S_mDeriv, S_eDeriv = src.evalDeriv(self, adjoint=adjoint) + s_mDeriv, s_eDeriv = src.evalDeriv(self, adjoint=adjoint) if adjoint: if self._makeASymmetric: MfRho = self.MfRho v = MfRho*v - return S_mDeriv(MeMuI.T * (C.T * v)) - 1j * omega(freq) * S_eDeriv(v) + return s_mDeriv(MeMuI.T * (C.T * v)) - 1j * omega(freq) * s_eDeriv(v) else: - RHSDeriv = C * (MeMuI * S_mDeriv(v)) - 1j * omega(freq) * S_eDeriv(v) + RHSDeriv = C * (MeMuI * s_mDeriv(v)) - 1j * omega(freq) * s_eDeriv(v) if self._makeASymmetric: MfRho = self.MfRho @@ -655,11 +655,11 @@ class Problem_h(BaseFDEMProblem): :return: RHS (nE, nSrc) """ - S_m, S_e = self.getSourceTerm(freq) + s_m, s_e = self.getSourceTerm(freq) C = self.mesh.edgeCurl MfRho = self.MfRho - return S_m + C.T * ( MfRho * S_e ) + return s_m + C.T * ( MfRho * s_e ) def getRHSDeriv(self, freq, src, v, adjoint=False): """ @@ -673,17 +673,17 @@ class Problem_h(BaseFDEMProblem): :return: product of rhs deriv with a vector """ - _, S_e = src.eval(self) + _, s_e = src.eval(self) C = self.mesh.edgeCurl MfRho = self.MfRho - MfRhoDeriv = self.MfRhoDeriv(S_e) + MfRhoDeriv = self.MfRhoDeriv(s_e) if not adjoint: RHSDeriv = C.T * (MfRhoDeriv * v) elif adjoint: RHSDeriv = MfRhoDeriv.T * (C * v) - S_mDeriv, S_eDeriv = src.evalDeriv(self, adjoint=adjoint) + s_mDeriv, s_eDeriv = src.evalDeriv(self, adjoint=adjoint) - return RHSDeriv + S_mDeriv(v) + C.T * (MfRho * S_eDeriv(v)) + return RHSDeriv + s_mDeriv(v) + C.T * (MfRho * s_eDeriv(v)) diff --git a/SimPEG/EM/FDEM/FieldsFDEM.py b/SimPEG/EM/FDEM/FieldsFDEM.py index 0f0a4963..e2193973 100644 --- a/SimPEG/EM/FDEM/FieldsFDEM.py +++ b/SimPEG/EM/FDEM/FieldsFDEM.py @@ -8,7 +8,7 @@ from SimPEG.Utils import Zero, Identity, sdiag class Fields(SimPEG.Problem.Fields): """ - + Fancy Field Storage for a FDEM survey. Only one field type is stored for each problem, the rest are computed. The fields obejct acts like an array and is indexed by @@ -34,56 +34,56 @@ class Fields(SimPEG.Problem.Fields): def _e(self, solution, srcList): """ - Total electric field is sum of primary and secondary - + Total electric field is sum of primary and secondary + :param numpy.ndarray solution: field we solved for :param list srcList: list of sources :rtype: numpy.ndarray :return: total electric field """ - if getattr(self, '_ePrimary', None) is None or getattr(self, '_eSecondary', None) is None: + if getattr(self, '_ePrimary', None) is None or getattr(self, '_eSecondary', None) is None: raise NotImplementedError ('Getting e from %s is not implemented' %self.knownFields.keys()[0]) return self._ePrimary(solution,srcList) + self._eSecondary(solution,srcList) def _b(self, solution, srcList): """ - Total magnetic flux density is sum of primary and secondary - + Total magnetic flux density is sum of primary and secondary + :param numpy.ndarray solution: field we solved for :param list srcList: list of sources :rtype: numpy.ndarray - :return: total magnetic flux density + :return: total magnetic flux density """ - if getattr(self, '_bPrimary', None) is None or getattr(self, '_bSecondary', None) is None: + if getattr(self, '_bPrimary', None) is None or getattr(self, '_bSecondary', None) is None: raise NotImplementedError ('Getting b from %s is not implemented' %self.knownFields.keys()[0]) return self._bPrimary(solution, srcList) + self._bSecondary(solution, srcList) def _h(self, solution, srcList): """ - Total magnetic field is sum of primary and secondary - + Total magnetic field is sum of primary and secondary + :param numpy.ndarray solution: field we solved for :param list srcList: list of sources :rtype: numpy.ndarray :return: total magnetic field """ - if getattr(self, '_hPrimary', None) is None or getattr(self, '_hSecondary', None) is None: + if getattr(self, '_hPrimary', None) is None or getattr(self, '_hSecondary', None) is None: raise NotImplementedError ('Getting h from %s is not implemented' %self.knownFields.keys()[0]) return self._hPrimary(solution, srcList) + self._hSecondary(solution, srcList) def _j(self, solution, srcList): """ - Total current density is sum of primary and secondary - + Total current density is sum of primary and secondary + :param numpy.ndarray solution: field we solved for :param list srcList: list of sources :rtype: numpy.ndarray - :return: total current density + :return: total current density """ - if getattr(self, '_jPrimary', None) is None or getattr(self, '_jSecondary', None) is None: + if getattr(self, '_jPrimary', None) is None or getattr(self, '_jSecondary', None) is None: raise NotImplementedError ('Getting j from %s is not implemented' %self.knownFields.keys()[0]) return self._jPrimary(solution, srcList) + self._jSecondary(solution, srcList) @@ -99,7 +99,7 @@ class Fields(SimPEG.Problem.Fields): :rtype: numpy.ndarray :return: derivative times a vector (or tuple for adjoint) """ - if getattr(self, '_eDeriv_u', None) is None or getattr(self, '_eDeriv_m', None) is None: + if getattr(self, '_eDeriv_u', None) is None or getattr(self, '_eDeriv_m', None) is None: raise NotImplementedError ('Getting eDerivs from %s is not implemented' %self.knownFields.keys()[0]) if adjoint: @@ -117,12 +117,12 @@ class Fields(SimPEG.Problem.Fields): :rtype: numpy.ndarray :return: derivative times a vector (or tuple for adjoint) """ - if getattr(self, '_bDeriv_u', None) is None or getattr(self, '_bDeriv_m', None) is None: + if getattr(self, '_bDeriv_u', None) is None or getattr(self, '_bDeriv_m', None) is None: raise NotImplementedError ('Getting bDerivs from %s is not implemented' %self.knownFields.keys()[0]) if adjoint: return self._bDeriv_u(src, v, adjoint), self._bDeriv_m(src, v, adjoint) - return np.array(self._bDeriv_u(src, du_dm_v, adjoint) + self._bDeriv_m(src, v, adjoint), dtype = complex) + return np.array(self._bDeriv_u(src, du_dm_v, adjoint) + self._bDeriv_m(src, v, adjoint), dtype = complex) def _hDeriv(self, src, du_dm_v, v, adjoint = False): """ @@ -135,10 +135,10 @@ class Fields(SimPEG.Problem.Fields): :rtype: numpy.ndarray :return: derivative times a vector (or tuple for adjoint) """ - if getattr(self, '_hDeriv_u', None) is None or getattr(self, '_hDeriv_m', None) is None: + if getattr(self, '_hDeriv_u', None) is None or getattr(self, '_hDeriv_m', None) is None: raise NotImplementedError ('Getting hDerivs from %s is not implemented' %self.knownFields.keys()[0]) - if adjoint: + if adjoint: return self._hDeriv_u(src, v, adjoint), self._hDeriv_m(src, v, adjoint) return np.array(self._hDeriv_u(src, du_dm_v, adjoint) + self._hDeriv_m(src, v, adjoint), dtype = complex) @@ -153,7 +153,7 @@ class Fields(SimPEG.Problem.Fields): :rtype: numpy.ndarray :return: derivative times a vector (or tuple for adjoint) """ - if getattr(self, '_jDeriv_u', None) is None or getattr(self, '_jDeriv_m', None) is None: + if getattr(self, '_jDeriv_u', None) is None or getattr(self, '_jDeriv_m', None) is None: raise NotImplementedError ('Getting jDerivs from %s is not implemented' %self.knownFields.keys()[0]) if adjoint: @@ -162,10 +162,10 @@ class Fields(SimPEG.Problem.Fields): class Fields_e(Fields): """ - Fields object for Problem_e. + Fields object for Problem_e. :param Mesh mesh: mesh - :param Survey survey: survey + :param Survey survey: survey """ knownFields = {'eSolution':'E'} @@ -233,9 +233,9 @@ class Fields_e(Fields): def _eDeriv_u(self, src, v, adjoint = False): """ - Partial derivative of the total electric field with respect to the thing we + Partial derivative of the total electric field with respect to the thing we solved for. - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -247,8 +247,8 @@ class Fields_e(Fields): def _eDeriv_m(self, src, v, adjoint = False): """ - Partial derivative of the total electric field with respect to the inversion model. Here, we assume that the primary does not depend on the model. Note that this also includes derivative contributions from the sources. - + Partial derivative of the total electric field with respect to the inversion model. Here, we assume that the primary does not depend on the model. Note that this also includes derivative contributions from the sources. + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -289,14 +289,14 @@ class Fields_e(Fields): b = (C * eSolution) for i, src in enumerate(srcList): b[:,i] *= - 1./(1j*omega(src.freq)) - S_m, _ = src.eval(self.prob) - b[:,i] = b[:,i]+ 1./(1j*omega(src.freq)) * S_m + s_m, _ = src.eval(self.prob) + b[:,i] = b[:,i]+ 1./(1j*omega(src.freq)) * s_m return b def _bDeriv_u(self, src, du_dm_v, adjoint = False): """ Derivative of the magnetic flux density with respect to the thing we solved for - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -312,8 +312,8 @@ class Fields_e(Fields): def _bDeriv_m(self, src, v, adjoint = False): """ - Derivative of the magnetic flux density with respect to the inversion model. - + Derivative of the magnetic flux density with respect to the inversion model. + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -321,8 +321,8 @@ class Fields_e(Fields): :return: product of the magnetic flux density derivative with respect to the inversion model with a vector """ - S_mDeriv, _ = src.evalDeriv(self.prob, v, adjoint) - return 1./(1j * omega(src.freq)) * S_mDeriv + s_mDeriv, _ = src.evalDeriv(self.prob, v, adjoint) + return 1./(1j * omega(src.freq)) * s_mDeriv def _j(self, eSolution, srcList): """ @@ -341,7 +341,7 @@ class Fields_e(Fields): def _jDeriv_u(self, src, du_dm_v, adjoint = False): """ Derivative of the current density with respect to the thing we solved for - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -351,15 +351,15 @@ class Fields_e(Fields): n = int(self._aveE2CCV.shape[0] / self._nC) # number of components (instead of checking if cyl or not) VI = sdiag(np.kron(np.ones(n), 1./self.prob.mesh.vol)) - if adjoint: + if adjoint: return self._eDeriv_u(src, self._MeSigma.T * (self._aveE2CCV.T * (VI.T * du_dm_v) ), adjoint = adjoint) return VI * (self._aveE2CCV * (self._MeSigma * (self._eDeriv_u(src, du_dm_v, adjoint=adjoint) ) ) ) - + def _jDeriv_m(self, src, v, adjoint = False): """ - Derivative of the current density with respect to the inversion model. - + Derivative of the current density with respect to the inversion model. + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -373,7 +373,7 @@ class Fields_e(Fields): if adjoint: return self._MeSigmaDeriv(e).T * (self._aveE2CCV.T * (VI.T * v)) + self._eDeriv_m(src, self._aveE2CCV.T * (VI.T * v), adjoint=adjoint) return VI * (self._aveE2CCV * ( self._eDeriv_m(src, v, adjoint=adjoint) + self._MeSigmaDeriv(e) * v)) - + def _h(self, eSolution, srcList): @@ -393,7 +393,7 @@ class Fields_e(Fields): def _hDeriv_u(self, src, du_dm_v, adjoint = False): """ Derivative of the magnetic field with respect to the thing we solved for - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -409,8 +409,8 @@ class Fields_e(Fields): def _hDeriv_m(self, src, v, adjoint = False): """ - Derivative of the magnetic field with respect to the inversion model. - + Derivative of the magnetic field with respect to the inversion model. + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -428,10 +428,10 @@ class Fields_e(Fields): class Fields_b(Fields): """ - Fields object for Problem_b. + Fields object for Problem_b. :param Mesh mesh: mesh - :param Survey survey: survey + :param Survey survey: survey """ knownFields = {'bSolution':'F'} @@ -506,9 +506,9 @@ class Fields_b(Fields): def _bDeriv_u(self, src, du_dm_v, adjoint=False): """ - Partial derivative of the total magnetic flux density with respect to the thing we + Partial derivative of the total magnetic flux density with respect to the thing we solved for. - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -520,8 +520,8 @@ class Fields_b(Fields): def _bDeriv_m(self, src, v, adjoint=False): """ - Partial derivative of the total magnetic flux density with respect to the inversion model. Here, we assume that the primary does not depend on the model. Note that this also includes derivative contributions from the sources. - + Partial derivative of the total magnetic flux density with respect to the inversion model. Here, we assume that the primary does not depend on the model. Note that this also includes derivative contributions from the sources. + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -560,15 +560,15 @@ class Fields_b(Fields): e = ( self._edgeCurl.T * ( self._MfMui * bSolution)) for i,src in enumerate(srcList): - _,S_e = src.eval(self.prob) - e[:,i] = e[:,i] + - S_e + _,s_e = src.eval(self.prob) + e[:,i] = e[:,i] + - s_e return self._MeSigmaI * e def _eDeriv_u(self, src, du_dm_v, adjoint=False): """ Derivative of the electric field with respect to the thing we solved for - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -583,8 +583,8 @@ class Fields_b(Fields): def _eDeriv_m(self, src, v, adjoint=False): """ - Derivative of the electric field with respect to the inversion model - + Derivative of the electric field with respect to the inversion model + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -593,15 +593,15 @@ class Fields_b(Fields): """ bSolution = Utils.mkvc(self[src, 'bSolution']) - _,S_e = src.eval(self.prob) + _,s_e = src.eval(self.prob) - w = -S_e + self._edgeCurl.T * (self._MfMui * bSolution) - _, S_eDeriv = src.evalDeriv(self.prob, v, adjoint) + w = -s_e + self._edgeCurl.T * (self._MfMui * bSolution) + _, s_eDeriv = src.evalDeriv(self.prob, v, adjoint) if adjoint: - return self._MeSigmaIDeriv(w).T * v - self._MeSigmaI.T * S_eDeriv - return self._MeSigmaIDeriv(w) * v - self._MeSigmaI * S_eDeriv + return self._MeSigmaIDeriv(w).T * v - self._MeSigmaI.T * s_eDeriv + return self._MeSigmaIDeriv(w) * v - self._MeSigmaI * s_eDeriv def _j(self, bSolution, srcList): """ @@ -617,13 +617,13 @@ class Fields_b(Fields): VI = sdiag(np.kron(np.ones(n), 1./self.prob.mesh.vol)) return VI * (self._aveE2CCV * ( self._MeSigma * self._e(bSolution,srcList ) ) ) - + def _jDeriv_u(self, src, du_dm_v, adjoint=False): """ - Partial derivative of the current density with respect to the thing we + Partial derivative of the current density with respect to the thing we solved for. - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -639,8 +639,8 @@ class Fields_b(Fields): def _jDeriv_m(self, src, v, adjoint=False): """ - Derivative of the current density with respect to the inversion model - + Derivative of the current density with respect to the inversion model + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -664,9 +664,9 @@ class Fields_b(Fields): def _hDeriv_u(self, src, du_dm_v, adjoint=False): """ - Partial derivative of the magnetic field with respect to the thing we + Partial derivative of the magnetic field with respect to the thing we solved for. - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -682,8 +682,8 @@ class Fields_b(Fields): def _hDeriv_m(self, src, v, adjoint=False): """ - Derivative of the magnetic field with respect to the inversion model - + Derivative of the magnetic field with respect to the inversion model + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -695,10 +695,10 @@ class Fields_b(Fields): class Fields_j(Fields): """ - Fields object for Problem_j. + Fields object for Problem_j. :param Mesh mesh: mesh - :param Survey survey: survey + :param Survey survey: survey """ knownFields = {'jSolution':'F'} @@ -769,12 +769,12 @@ class Fields_j(Fields): def _j(self, jSolution, srcList): """ - Total current density is sum of primary and secondary - + Total current density is sum of primary and secondary + :param numpy.ndarray jSolution: field we solved for :param list srcList: list of sources :rtype: numpy.ndarray - :return: total current density + :return: total current density """ return self._jPrimary(jSolution, srcList) + self._jSecondary(jSolution, srcList) @@ -782,9 +782,9 @@ class Fields_j(Fields): def _jDeriv_u(self, src, du_dm_v, adjoint=False): """ - Partial derivative of the total current density with respect to the thing we + Partial derivative of the total current density with respect to the thing we solved for. - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -797,8 +797,8 @@ class Fields_j(Fields): def _jDeriv_m(self, src, v, adjoint=False): """ - Partial derivative of the total current density with respect to the inversion model. Here, we assume that the primary does not depend on the model. Note that this also includes derivative contributions from the sources. - + Partial derivative of the total current density with respect to the inversion model. Here, we assume that the primary does not depend on the model. Note that this also includes derivative contributions from the sources. + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -837,15 +837,15 @@ class Fields_j(Fields): h = (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) - h[:,i] = h[:,i] + 1./(1j*omega(src.freq)) * (S_m) + s_m,_ = src.eval(self.prob) + h[:,i] = h[:,i] + 1./(1j*omega(src.freq)) * (s_m) return self._MeMuI * h def _hDeriv_u(self, src, du_dm_v, adjoint=False): """ Derivative of the magnetic field with respect to the thing we solved for - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -856,13 +856,13 @@ class Fields_j(Fields): if adjoint: return -1./(1j*omega(src.freq)) * self._MfRho.T * (self._edgeCurl * ( self._MeMuI.T * du_dm_v)) return -1./(1j*omega(src.freq)) * self._MeMuI * (self._edgeCurl.T * (self._MfRho * du_dm_v) ) - + def _hDeriv_m(self, src, v, adjoint=False): """ - Derivative of the magnetic field with respect to the inversion model - + Derivative of the magnetic field with respect to the inversion model + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -875,19 +875,19 @@ class Fields_j(Fields): C = self._edgeCurl MfRho = self._MfRho MfRhoDeriv = self._MfRhoDeriv - S_mDeriv,_ = src.evalDeriv(self.prob, adjoint = adjoint) + s_mDeriv,_ = src.evalDeriv(self.prob, adjoint = adjoint) if not adjoint: hDeriv_m = -1./(1j*omega(src.freq)) * MeMuI * (C.T * (MfRhoDeriv(jSolution)*v ) ) - S_mDeriv = S_mDeriv(v) - hDeriv_m = hDeriv_m + 1./(1j*omega(src.freq)) * MeMuI * ( S_mDeriv) + s_mDeriv = s_mDeriv(v) + hDeriv_m = hDeriv_m + 1./(1j*omega(src.freq)) * MeMuI * ( s_mDeriv) elif adjoint: hDeriv_m = -1./(1j*omega(src.freq)) * MfRhoDeriv(jSolution).T * ( C * (MeMuI.T * v ) ) - S_mDeriv = S_mDeriv(MeMuI.T * v) - hDeriv_m = hDeriv_m + 1./(1j*omega(src.freq)) * S_mDeriv - + s_mDeriv = s_mDeriv(MeMuI.T * v) + hDeriv_m = hDeriv_m + 1./(1j*omega(src.freq)) * s_mDeriv + return hDeriv_m def _e(self, jSolution, srcList): @@ -901,12 +901,12 @@ class Fields_j(Fields): """ n = int(self._aveF2CCV.shape[0] / self._nC) # number of components VI = sdiag(np.kron(np.ones(n), 1./self.prob.mesh.vol)) - return VI * (self._aveF2CCV * (self._MfRho * self._j(jSolution, srcList))) + return VI * (self._aveF2CCV * (self._MfRho * self._j(jSolution, srcList))) def _eDeriv_u(self, src, du_dm_v, adjoint=False): """ Derivative of the electric field with respect to the thing we solved for - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -921,8 +921,8 @@ class Fields_j(Fields): def _eDeriv_m(self, src, v, adjoint=False): """ - Derivative of the electric field with respect to the inversion model - + Derivative of the electric field with respect to the inversion model + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -943,17 +943,17 @@ class Fields_j(Fields): :param numpy.ndarray hSolution: field we solved for :param list srcList: list of sources :rtype: numpy.ndarray - :return: secondary magnetic flux density + :return: secondary magnetic flux density """ n = int(self._aveE2CCV.shape[0] / self._nC) # number of components VI = sdiag(np.kron(np.ones(n), 1./self.prob.mesh.vol)) - return VI * (self._aveE2CCV * ( self._MeMu * self._h(jSolution,srcList)) ) + return VI * (self._aveE2CCV * ( self._MeMu * self._h(jSolution,srcList)) ) def _bDeriv_u(self, src, du_dm_v, adjoint=False): """ Derivative of the magnetic flux density with respect to the thing we solved for - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -969,8 +969,8 @@ class Fields_j(Fields): def _bDeriv_m(self, src, v, adjoint=False): """ - Derivative of the magnetic flux density with respect to the inversion model - + Derivative of the magnetic flux density with respect to the inversion model + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -980,20 +980,20 @@ class Fields_j(Fields): jSolution = self[src,'jSolution'] n = int(self._aveE2CCV.shape[0] / self._nC) # number of components VI = sdiag(np.kron(np.ones(n), 1./self.prob.mesh.vol)) - S_mDeriv,_ = src.evalDeriv(self.prob, adjoint = adjoint) + s_mDeriv,_ = src.evalDeriv(self.prob, adjoint = adjoint) if adjoint: v = self._aveE2CCV.T * ( VI.T * v) - return 1./(1j * omega(src.freq)) * ( S_mDeriv(v) - self._MfRhoDeriv(jSolution).T * (self._edgeCurl * v )) - return 1./(1j * omega(src.freq)) * VI * (self._aveE2CCV * ( S_mDeriv(v) - self._edgeCurl.T * ( self._MfRhoDeriv(jSolution) * v ) ) ) + return 1./(1j * omega(src.freq)) * ( s_mDeriv(v) - self._MfRhoDeriv(jSolution).T * (self._edgeCurl * v )) + return 1./(1j * omega(src.freq)) * VI * (self._aveE2CCV * ( s_mDeriv(v) - self._edgeCurl.T * ( self._MfRhoDeriv(jSolution) * v ) ) ) class Fields_h(Fields): """ - Fields object for Problem_h. + Fields object for Problem_h. :param Mesh mesh: mesh - :param Survey survey: survey + :param Survey survey: survey """ knownFields = {'hSolution':'E'} @@ -1065,9 +1065,9 @@ class Fields_h(Fields): def _hDeriv_u(self, src, du_dm_v, adjoint=False): """ - Partial derivative of the total magnetic field with respect to the thing we + Partial derivative of the total magnetic field with respect to the thing we solved for. - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -1079,8 +1079,8 @@ class Fields_h(Fields): def _hDeriv_m(self, src, v, adjoint=False): """ - Partial derivative of the total magnetic field with respect to the inversion model. Here, we assume that the primary does not depend on the model. Note that this also includes derivative contributions from the sources. - + Partial derivative of the total magnetic field with respect to the inversion model. Here, we assume that the primary does not depend on the model. Note that this also includes derivative contributions from the sources. + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -1119,14 +1119,14 @@ class Fields_h(Fields): j = self._edgeCurl*hSolution for i, src in enumerate(srcList): - _,S_e = src.eval(self.prob) - j[:,i] = j[:,i]+ -S_e + _,s_e = src.eval(self.prob) + j[:,i] = j[:,i]+ -s_e return j def _jDeriv_u(self, src, du_dm_v, adjoint=False): """ Derivative of the current density with respect to the thing we solved for - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -1142,8 +1142,8 @@ class Fields_h(Fields): def _jDeriv_m(self, src, v, adjoint=False): """ - Derivative of the current density with respect to the inversion model. - + Derivative of the current density with respect to the inversion model. + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -1151,9 +1151,9 @@ class Fields_h(Fields): :return: product of the current density derivative with respect to the inversion model with a vector """ - _,S_eDeriv = src.evalDeriv(self.prob, v, adjoint) - return -S_eDeriv - + _,s_eDeriv = src.evalDeriv(self.prob, v, adjoint) + return -s_eDeriv + def _e(self, hSolution, srcList): """ Electric field from hSolution @@ -1165,12 +1165,12 @@ class Fields_h(Fields): """ n = int(self._aveF2CCV.shape[0] / self._nC) #number of components VI = sdiag(np.kron(np.ones(n), 1./self.prob.mesh.vol)) - return VI * (self._aveF2CCV * (self._MfRho * self._j(hSolution, srcList))) + return VI * (self._aveF2CCV * (self._MfRho * self._j(hSolution, srcList))) def _eDeriv_u(self, src, du_dm_v, adjoint=False): """ Derivative of the electric field with respect to the thing we solved for - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? @@ -1181,12 +1181,12 @@ class Fields_h(Fields): VI = sdiag(np.kron(np.ones(n), 1./self.prob.mesh.vol)) if adjoint: return self._edgeCurl.T * ( self._MfRho.T * ( self._aveF2CCV.T * ( VI.T * du_dm_v ) ) ) - return VI * (self._aveF2CCV * (self._MfRho * self._edgeCurl * du_dm_v )) + return VI * (self._aveF2CCV * (self._MfRho * self._edgeCurl * du_dm_v )) def _eDeriv_m(self, src, v, adjoint=False): """ - Derivative of the electric field with respect to the inversion model. - + Derivative of the electric field with respect to the inversion model. + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? @@ -1196,7 +1196,7 @@ class Fields_h(Fields): hSolution = Utils.mkvc(self[src,'hSolution']) n = int(self._aveF2CCV.shape[0] / self._nC) #number of components VI = sdiag(np.kron(np.ones(n), 1./self.prob.mesh.vol)) - if adjoint: + if adjoint: return ( self._MfRhoDeriv(self._edgeCurl * hSolution).T * ( self._aveF2CCV.T * (VI.T * v) ) ) return VI * (self._aveF2CCV * (self._MfRhoDeriv(self._edgeCurl * hSolution) * v )) @@ -1207,10 +1207,10 @@ class Fields_h(Fields): :param numpy.ndarray hSolution: field we solved for :param list srcList: list of sources :rtype: numpy.ndarray - :return: magnetic flux density + :return: magnetic flux density """ h = self._h(hSolution, srcList) - n = int(self._aveE2CCV.shape[0] / self._nC) #number of components + n = int(self._aveE2CCV.shape[0] / self._nC) #number of components VI = sdiag(np.kron(np.ones(n), 1./self.prob.mesh.vol)) return VI * (self._aveE2CCV * (self._MeMu * h)) @@ -1218,14 +1218,14 @@ class Fields_h(Fields): def _bDeriv_u(self, src, du_dm_v, adjoint=False): """ Derivative of the magnetic flux density with respect to the thing we solved for - + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray du_dm_v: vector to take product with :param bool adjoint: adjoint? :rtype: numpy.ndarray :return: product of the derivative of the magnetic flux density with respect to the field we solved for with a vector """ - n = int(self._aveE2CCV.shape[0] / self._nC) #number of components + n = int(self._aveE2CCV.shape[0] / self._nC) #number of components VI = sdiag(np.kron(np.ones(n), 1./self.prob.mesh.vol)) if adjoint: return self._MeMu.T * (self._aveE2CCV.T * ( VI.T * du_dm_v )) @@ -1233,8 +1233,8 @@ class Fields_h(Fields): def _bDeriv_m(self, src, v, adjoint=False): """ - Derivative of the magnetic flux density with respect to the inversion model. - + Derivative of the magnetic flux density with respect to the inversion model. + :param SimPEG.EM.FDEM.Src src: source :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? diff --git a/SimPEG/EM/FDEM/SrcFDEM.py b/SimPEG/EM/FDEM/SrcFDEM.py index 31e4224f..87967dd5 100644 --- a/SimPEG/EM/FDEM/SrcFDEM.py +++ b/SimPEG/EM/FDEM/SrcFDEM.py @@ -15,22 +15,22 @@ class BaseSrc(Survey.BaseSrc): def eval(self, prob): """ Evaluate the source terms. - - :math:`S_m` : magnetic source term - - :math:`S_e` : electric source term + - :math:`s_m` : magnetic source term + - :math:`s_e` : electric source term :param Problem prob: FDEM Problem :rtype: (numpy.ndarray, numpy.ndarray) :return: tuple with magnetic source term and electric source term """ - S_m = self.S_m(prob) - S_e = self.S_e(prob) - return S_m, S_e + s_m = self.s_m(prob) + s_e = self.s_e(prob) + return s_m, s_e def evalDeriv(self, prob, v=None, adjoint=False): """ Derivatives of the source terms with respect to the inversion model - - :code:`S_mDeriv` : derivative of the magnetic source term - - :code:`S_eDeriv` : derivative of the electric source term + - :code:`s_mDeriv` : derivative of the magnetic source term + - :code:`s_eDeriv` : derivative of the electric source term :param Problem prob: FDEM Problem :param numpy.ndarray v: vector to take product with @@ -39,9 +39,9 @@ class BaseSrc(Survey.BaseSrc): :return: tuple with magnetic source term and electric source term derivatives times a vector """ if v is not None: - return self.S_mDeriv(prob, v, adjoint), self.S_eDeriv(prob, v, adjoint) + return self.s_mDeriv(prob, v, adjoint), self.s_eDeriv(prob, v, adjoint) else: - return lambda v: self.S_mDeriv(prob, v, adjoint), lambda v: self.S_eDeriv(prob, v, adjoint) + return lambda v: self.s_mDeriv(prob, v, adjoint), lambda v: self.s_eDeriv(prob, v, adjoint) def bPrimary(self, prob): """ @@ -83,7 +83,7 @@ class BaseSrc(Survey.BaseSrc): """ return Zero() - def S_m(self, prob): + def s_m(self, prob): """ Magnetic source term @@ -93,7 +93,7 @@ class BaseSrc(Survey.BaseSrc): """ return Zero() - def S_e(self, prob): + def s_e(self, prob): """ Electric source term @@ -103,7 +103,7 @@ class BaseSrc(Survey.BaseSrc): """ return Zero() - def S_mDeriv(self, prob, v, adjoint = False): + def s_mDeriv(self, prob, v, adjoint = False): """ Derivative of magnetic source term with respect to the inversion model @@ -116,7 +116,7 @@ class BaseSrc(Survey.BaseSrc): return Zero() - def S_eDeriv(self, prob, v, adjoint = False): + def s_eDeriv(self, prob, v, adjoint = False): """ Derivative of electric source term with respect to the inversion model @@ -131,22 +131,22 @@ class BaseSrc(Survey.BaseSrc): class RawVec_e(BaseSrc): """ - RawVec electric source. It is defined by the user provided vector S_e + RawVec electric source. It is defined by the user provided vector s_e :param list rxList: receiver list :param float freq: frequency - :param numpy.array S_e: electric source term + :param numpy.array s_e: electric source term :param bool integrate: Integrate the source term (multiply by Me) [True] """ - def __init__(self, rxList, freq, S_e, integrate=True): #, ePrimary=None, bPrimary=None, hPrimary=None, jPrimary=None): - self._S_e = np.array(S_e, dtype=complex) + def __init__(self, rxList, freq, s_e, integrate=True): #, ePrimary=None, bPrimary=None, hPrimary=None, jPrimary=None): + self._s_e = np.array(s_e, dtype=complex) self.freq = float(freq) self.integrate = integrate BaseSrc.__init__(self, rxList) - def S_e(self, prob): + def s_e(self, prob): """ Electric source term @@ -155,28 +155,28 @@ class RawVec_e(BaseSrc): :return: electric source term on mesh """ if prob._formulation is 'EB' and self.integrate is True: - return prob.Me * self._S_e - return self._S_e + return prob.Me * self._s_e + return self._s_e class RawVec_m(BaseSrc): """ - RawVec magnetic source. It is defined by the user provided vector S_m + RawVec magnetic source. It is defined by the user provided vector s_m :param float freq: frequency :param rxList: receiver list - :param numpy.array S_m: magnetic source term + :param numpy.array s_m: magnetic source term :param bool integrate: Integrate the source term (multiply by Me) [True] """ - def __init__(self, rxList, freq, S_m, integrate=True): #ePrimary=Zero(), bPrimary=Zero(), hPrimary=Zero(), jPrimary=Zero()): - self._S_m = np.array(S_m, dtype=complex) + def __init__(self, rxList, freq, s_m, integrate=True): #ePrimary=Zero(), bPrimary=Zero(), hPrimary=Zero(), jPrimary=Zero()): + self._s_m = np.array(s_m, dtype=complex) self.freq = float(freq) self.integrate = integrate BaseSrc.__init__(self, rxList) - def S_m(self, prob): + def s_m(self, prob): """ Magnetic source term @@ -185,28 +185,28 @@ class RawVec_m(BaseSrc): :return: magnetic source term on mesh """ if prob._formulation is 'HJ' and self.integrate is True: - return prob.Me * self._S_m - return self._S_m + return prob.Me * self._s_m + return self._s_m class RawVec(BaseSrc): """ - RawVec source. It is defined by the user provided vectors S_m, S_e + RawVec source. It is defined by the user provided vectors s_m, s_e :param rxList: receiver list :param float freq: frequency - :param numpy.array S_m: magnetic source term - :param numpy.array S_e: electric source term + :param numpy.array s_m: magnetic source term + :param numpy.array s_e: electric source term :param bool integrate: Integrate the source term (multiply by Me) [True] """ - def __init__(self, rxList, freq, S_m, S_e, integrate=True): - self._S_m = np.array(S_m, dtype=complex) - self._S_e = np.array(S_e, dtype=complex) + def __init__(self, rxList, freq, s_m, s_e, integrate=True): + self._s_m = np.array(s_m, dtype=complex) + self._s_e = np.array(s_e, dtype=complex) self.freq = float(freq) self.integrate = integrate BaseSrc.__init__(self, rxList) - def S_m(self, prob): + def s_m(self, prob): """ Magnetic source term @@ -215,10 +215,10 @@ class RawVec(BaseSrc): :return: magnetic source term on mesh """ if prob._formulation is 'HJ' and self.integrate is True: - return prob.Me * self._S_m - return self._S_m + return prob.Me * self._s_m + return self._s_m - def S_e(self, prob): + def s_e(self, prob): """ Electric source term @@ -227,8 +227,8 @@ class RawVec(BaseSrc): :return: electric source term on mesh """ if prob._formulation is 'EB' and self.integrate is True: - return prob.Me * self._S_e - return self._S_e + return prob.Me * self._s_e + return self._s_e class MagDipole(BaseSrc): @@ -335,9 +335,9 @@ class MagDipole(BaseSrc): :return: primary magnetic field """ b = self.bPrimary(prob) - return 1./self.mu * b + return 1./self.mu * b - def S_m(self, prob): + def s_m(self, prob): """ The magnetic source term @@ -348,10 +348,10 @@ class MagDipole(BaseSrc): b_p = self.bPrimary(prob) if prob._formulation is 'HJ': - b_p = prob.Me * b_p + b_p = prob.Me * b_p return -1j*omega(self.freq)*b_p - def S_e(self, prob): + def s_e(self, prob): """ The electric source term @@ -453,7 +453,7 @@ class MagDipole_Bfield(BaseSrc): b = self.bPrimary(prob) return 1/self.mu * b - def S_m(self, prob): + def s_m(self, prob): """ The magnetic source term @@ -466,7 +466,7 @@ class MagDipole_Bfield(BaseSrc): b = prob.Me * b return -1j*omega(self.freq)*b - def S_e(self, prob): + def s_e(self, prob): """ The electric source term @@ -565,7 +565,7 @@ class CircularLoop(BaseSrc): b = self.bPrimary(prob) return 1./self.mu*b - def S_m(self, prob): + def s_m(self, prob): """ The magnetic source term @@ -578,7 +578,7 @@ class CircularLoop(BaseSrc): b = prob.Me * b return -1j*omega(self.freq)*b - def S_e(self, prob): + def s_e(self, prob): """ The electric source term @@ -604,6 +604,6 @@ class CircularLoop(BaseSrc): return -C.T * (MMui_s * self.bPrimary(prob)) - + From 579f1d7a65193bdf81cf05966363f7ef053641eb Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Sun, 20 Mar 2016 13:36:19 -0700 Subject: [PATCH 07/18] FDEM uses f (so the u kwarg breaks). replace with f across the entire codebase?? --- SimPEG/DataMisfit.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SimPEG/DataMisfit.py b/SimPEG/DataMisfit.py index 425fe4ce..13574771 100644 --- a/SimPEG/DataMisfit.py +++ b/SimPEG/DataMisfit.py @@ -89,7 +89,7 @@ class l2_DataMisfit(BaseDataMisfit): """ if getattr(self, '_Wd', None) is None: - + survey = self.survey if getattr(survey,'std', None) is None: @@ -112,7 +112,7 @@ class l2_DataMisfit(BaseDataMisfit): "eval(m, u=None)" prob = self.prob survey = self.survey - R = self.Wd * survey.residual(m, u=u) + R = self.Wd * survey.residual(m, u) return 0.5*np.vdot(R, R) @Utils.timeIt @@ -121,11 +121,11 @@ class l2_DataMisfit(BaseDataMisfit): prob = self.prob survey = self.survey if u is None: u = prob.fields(m) - return prob.Jtvec(m, self.Wd * (self.Wd * survey.residual(m, u=u)), u=u) + return prob.Jtvec(m, self.Wd * (self.Wd * survey.residual(m, u)), u) @Utils.timeIt def eval2Deriv(self, m, v, u=None): "eval2Deriv(m, v, u=None)" prob = self.prob if u is None: u = prob.fields(m) - return prob.Jtvec_approx(m, self.Wd * (self.Wd * prob.Jvec_approx(m, v, u=u)), u=u) + return prob.Jtvec_approx(m, self.Wd * (self.Wd * prob.Jvec_approx(m, v, u=u)), u) From c66db805af651598a8a087d4cd2e6fb0768008d6 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Sun, 20 Mar 2016 14:44:34 -0700 Subject: [PATCH 08/18] typo fix --- SimPEG/EM/Base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SimPEG/EM/Base.py b/SimPEG/EM/Base.py index 12d1ae43..a16cdb91 100644 --- a/SimPEG/EM/Base.py +++ b/SimPEG/EM/Base.py @@ -199,7 +199,7 @@ class BaseEMSurvey(Survey.BaseSurvey): :rtype: numpy.ndarray :return: data """ - data = SimPEG.Survey.Data(self) + data = Survey.Data(self) for src in self.srcList: for rx in src.rxList: data[src, rx] = rx.eval(src, self.mesh, u) From 5fb8cdb88c8608daf198ad8e9b351153119c7fbd Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Tue, 29 Mar 2016 13:00:37 -0700 Subject: [PATCH 09/18] example casing forward simulation to calculate vertical current --- .../Examples/EM_Schenkel_Morrison_Casing.py | 269 ++++++++++++++++++ SimPEG/Examples/__init__.py | 3 +- docs/examples/EM_Schenkel_Morrison_Casing.rst | 52 ++++ 3 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 SimPEG/Examples/EM_Schenkel_Morrison_Casing.py create mode 100644 docs/examples/EM_Schenkel_Morrison_Casing.rst diff --git a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py new file mode 100644 index 00000000..ef51b25c --- /dev/null +++ b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py @@ -0,0 +1,269 @@ +from SimPEG import * +from SimPEG.EM import FDEM, Analytics, mu_0 +import time + +try: + from pymatsolver import MumpsSolver + solver = MumpsSolver +except Exception: + solver = SolverLU + pass + +def run(plotIt=True): + """ + EM: Schenkel and Morrison Casing Model + ====================================== + + Here we will create and run a FDEM forward simulation based on the + Schenkel and Morrison Casing Model + + - `Schenkel, C.J., and H.F. Morrison, 1990`_, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. + + .. _Schenkel, C. J., and H. F. Morrison, 1990: http://onlinelibrary.wiley.com/store/10.1111/j.1365-2478.1990.tb01868.x/asset/j.1365-2478.1990.tb01868.x.pdf?v=1&t=imdt3o85&s=38248af166c2887ed587d94c8ccafad30b480529 + + The model consists of: + - Air: Conductivity 1e-8 S/m, above z = 0 + - Background: conductivity 1e-2 S/m, below z = 0 + - Casing: conductivity 1e6 S/m + - 300m long + - radius of 0.1m + - thickness of 6e-3m + + Inside the casing, we take the same conductivity as the background. + + We are using an EM code to simulate DC, so we use frequency low enough + that the skin depth inside the casing is longer than the casing length (f + = 1e-6 Hz). The plot produced is of the current inside the casing. + + These results are shown in the SEG abstract by Yang et al., 2016: 3D DC + resistivity modeling of steel casing for reservoir monitoring using + equivalent resistor network. The solver used to produce these results and + achieve the CPU time of ~30s is Mumps, which was installed using pymatsolver_ + + .. _pymatsolver: https://github.com/rowanc1/pymatsolver + + """ + + if plotIt: + import matplotlib.pylab as plt + + # ------------------ MODEL ------------------ + sigmaair = 1e-8 # air + sigmaback = 1e-2 # background + sigmacasing = 1e6 # casing + sigmainside = sigmaback # inside the casing + + + casing_t = 0.006 # 1cm thickness + casing_l = 300 # length of the casing + + casing_r = 0.1 + casing_a = casing_r - casing_t/2. # inner radius + casing_b = casing_r + casing_t/2. # outer radius + casing_z = np.r_[-casing_l,0.] + + + # ------------------ SURVEY PARAMETERS ------------------ + freqs = np.r_[1e-6] #[1e-1, 1, 5] # frequencies + dsz = -300 # down-hole z source location + src_loc = np.r_[0.,0.,dsz] + inf_loc = np.r_[0.,0.,1e4] + + print 'Skin Depth: ', [(500./np.sqrt(sigmaback*_)) for _ in freqs] + + + # ------------------ MESH ------------------ + # fine cells near well bore + csx1, csx2 = 2e-3, 60. + pfx1, pfx2 = 1.3, 1.3 + ncx1 = np.ceil(casing_b/csx1+2) + + # pad nicely to second cell size + npadx1 = np.floor(np.log(csx2/csx1) / np.log(pfx1)) + hx1a,hx1b = Utils.meshTensor([(csx1,ncx1)]),Utils.meshTensor([(csx1,npadx1,pfx1)]) + dx1 = sum(hx1a)+sum(hx1b) + dx1 = np.floor(dx1/csx2) + hx1b *= (dx1*csx2 - sum(hx1a))/sum(hx1b) + + # second chunk of mesh + dx2 = 300. # uniform mesh out to here + ncx2 = np.ceil((dx2 - dx1)/csx2) + npadx2 = 45 + hx2a, hx2b = Utils.meshTensor([(csx2,ncx2)]), Utils.meshTensor([(csx2,npadx2,pfx2)]) + hx = np.hstack([hx1a,hx1b,hx2a,hx2b]) + + # z-direction + csz = 0.05 + nza = 10 + ncz, npadzu, npadzd = np.int(np.ceil(np.diff(casing_z)[0]/csz))+10, 68, 68 # cell size, number of core cells, number of padding cells in the x- direction + hz = Utils.meshTensor([(csz,npadzd,-1.3), (csz,ncz), (csz,npadzu,1.3)]) # vector of cell widths in the z-direction + + # Mesh + mesh = Mesh.CylMesh([hx,1.,hz], [0.,0.,-np.sum(hz[:npadzu+ncz-nza])]) + + print 'Mesh Extent xmax: %f,: zmin: %f, zmax: %f'%(mesh.vectorCCx.max(), mesh.vectorCCz.min(), mesh.vectorCCz.max()) + print 'Number of cells', mesh.nC + + if plotIt is True: + fig, ax = plt.subplots(1, 1, figsize=(6, 4)) + ax.set_title('Simulation Mesh') + mesh.plotGrid(ax=ax) + plt.show() + + # Put the model on the mesh + sigWholespace = sigmaback*np.ones((mesh.nC)) + + sigBack = sigWholespace.copy() + sigBack[mesh.gridCC[:,2] > 0.] = sigmaair + + sigCasing = sigBack.copy() + iCasingZ = (mesh.gridCC[:,2] <= casing_z[1]) & (mesh.gridCC[:,2] >= casing_z[0]) + iCasingX = (mesh.gridCC[:,0] >= casing_a) & (mesh.gridCC[:,0] <= casing_b) + iCasing = iCasingX & iCasingZ + sigCasing[iCasing] = sigmacasing + + + if plotIt is True: + + # plotting parameters + xlim = np.r_[0., 0.2] + zlim = np.r_[-350., 10.] + clim_sig = np.r_[-8,6] + + # plot models + fig, ax = plt.subplots(1,1,figsize=(4,4)) + + f = plt.colorbar(mesh.plotImage(np.log10(sigCasing),ax=ax)[0], ax=ax) + ax.grid(which='both') + ax.set_title('Log_10 (Sigma)') + ax.set_xlim(xlim) + ax.set_ylim(zlim) + f.set_clim(clim_sig) + + plt.show() + + + # -------------- Sources -------------------- + # Define Custom Current Sources + + # surface source + sg_x = np.zeros(mesh.vnF[0],dtype=complex) + sg_y = np.zeros(mesh.vnF[1],dtype=complex) + sg_z = np.zeros(mesh.vnF[2],dtype=complex) + + nza = 2 # put the wire two cells above the surface + ncin = 2 + + # vertically directed wire + sgv_indx = (mesh.gridFz[:,0] > casing_a) & (mesh.gridFz[:,0] < casing_a + csx1) # hook it up to casing at the surface + sgv_indz = (mesh.gridFz[:,2] <= +csz*nza) & (mesh.gridFz[:,2] >= -csz*2) + sgv_ind = sgv_indx & sgv_indz + sg_z[sgv_ind] = -1. + + # horizontally directed wire + sgh_indx = (mesh.gridFx[:,0] > casing_a) & (mesh.gridFx[:,0] <= inf_loc[2]) + sgh_indz = (mesh.gridFx[:,2] > csz*(nza-0.5)) & (mesh.gridFx[:,2] < csz*(nza+0.5)) + sgh_ind = sgh_indx & sgh_indz + sg_x[sgh_ind] = -1. + + sgv2_indx = (mesh.gridFz[:,0] >= mesh.gridFx[sgh_ind,0].max()) & (mesh.gridFz[:,0] <= inf_loc[2]*1.2) # hook it up to casing at the surface + sgv2_indz = (mesh.gridFz[:,2] <= +csz*nza) & (mesh.gridFz[:,2] >= -csz*2) + sgv2_ind = sgv2_indx & sgv2_indz + sg_z[sgv2_ind] = 1. + + # assemble the source + sg = np.hstack([sg_x,sg_y,sg_z]) + sg_p = [FDEM.Src.RawVec_e([],_,sg/mesh.area) for _ in freqs] + + # downhole source + dg_x = np.zeros(mesh.vnF[0],dtype=complex) + dg_y = np.zeros(mesh.vnF[1],dtype=complex) + dg_z = np.zeros(mesh.vnF[2],dtype=complex) + + # vertically directed wire + dgv_indx = (mesh.gridFz[:,0] < csx1) # go through the center of the well + dgv_indz = (mesh.gridFz[:,2] <= +csz*nza) & (mesh.gridFz[:,2] > dsz + csz/2.) + dgv_ind = dgv_indx & dgv_indz + dg_z[dgv_ind] = -1. + + # couple to the casing downhole + dgh_indx = mesh.gridFx[:,0] < casing_a + csx1 + dgh_indz = (mesh.gridFx[:,2] < dsz + csz) & (mesh.gridFx[:,2] >= dsz) + dgh_ind = dgh_indx & dgh_indz + dg_x[dgh_ind] = 1. + + # horizontal part at surface + dgh2_indx = mesh.gridFx[:,0] <= inf_loc[2]*1.2 + dgh2_indz = sgh_indz.copy() + dgh2_ind = dgh2_indx & dgh2_indz + dg_x[dgh2_ind] = -1. + + # vertical part at surface + dgv2_ind = sgv2_ind.copy() + dg_z[dgv2_ind] = 1. + + # assemble the source + dg = np.hstack([dg_x,dg_y,dg_z]) + dg_p = [FDEM.Src.RawVec_e([],_,dg/mesh.area) for _ in freqs] + + # ------------ Problem and Survey --------------- + survey = FDEM.Survey(sg_p + dg_p) + mapping = [('sigma', Maps.IdentityMap(mesh))] + problem = FDEM.Problem_h(mesh, mapping=mapping) + problem.pair(survey) + + # ------------- Solve --------------------------- + t0 = time.time() + fieldsCasing = problem.fields(sigCasing) + print 'Time to solve 2 sources', time.time() - t0 + + # Plot current + + # current density + jn0 = fieldsCasing[dg_p,'j'] + jn1 = fieldsCasing[sg_p,'j'] + + # current + in0 = [mesh.area*fieldsCasing[dg_p,'j'][:,i] for i in range(len(freqs))] + in1 = [mesh.area*fieldsCasing[sg_p,'j'][:,i] for i in range(len(freqs))] + + in0 = np.vstack(in0).T + in1 = np.vstack(in1).T + + # integrate to get z-current inside casing + inds_inx = (mesh.gridFz[:,0] >= casing_a) & (mesh.gridFz[:,0] <= casing_b) + inds_inz = (mesh.gridFz[:,2] >= dsz ) & (mesh.gridFz[:,2] <= 0) + inds_fz = inds_inx & inds_inz + + indsx = [False]*mesh.nFx + inds = list(indsx) + list(inds_fz) + + in0_in = in0[np.r_[inds]] + in1_in = in1[np.r_[inds]] + z_in = mesh.gridFz[inds_fz,2] + + in0_in = in0_in.reshape([in0_in.shape[0]/3,3]) + in1_in = in1_in.reshape([in1_in.shape[0]/3,3]) + z_in = z_in.reshape([z_in.shape[0]/3,3]) + + I0 = in0_in.sum(1).real + I1 = in1_in.sum(1).real + z_in = z_in[:,0] + + if plotIt is True: + fig, ax = plt.subplots(1,2,figsize=(12,4)) + + ax[0].plot(z_in,np.absolute(I0), z_in,np.absolute(I1)) + ax[0].legend(['top casing', 'bottom casing'],loc='best') + ax[0].set_title('Magnitude of Current') + + ax[1].semilogy(z_in,np.absolute(I0), z_in,np.absolute(I1)) + ax[1].legend(['top casing', 'bottom casing'],loc='best') + ax[1].set_title('Magnitude of Current') + ax[1].set_ylim([1e-2, 1.]) + + plt.show() + +if __name__ == '__main__': + run() + diff --git a/SimPEG/Examples/__init__.py b/SimPEG/Examples/__init__.py index cce22296..4647ad90 100644 --- a/SimPEG/Examples/__init__.py +++ b/SimPEG/Examples/__init__.py @@ -5,6 +5,7 @@ import DC_Analytic_Dipole import DC_Forward_PseudoSection import EM_FDEM_1D_Inversion import EM_FDEM_Analytic_MagDipoleWholespace +import EM_Schenkel_Morrison_Casing import EM_TDEM_1D_Inversion import FLOW_Richards_1D_Celia1990 import Forward_BasicDirectCurrent @@ -19,7 +20,7 @@ import Mesh_Tensor_Creation import MT_1D_ForwardAndInversion import MT_3D_Foward -__examples__ = ["DC_Analytic_Dipole", "DC_Forward_PseudoSection", "EM_FDEM_1D_Inversion", "EM_FDEM_Analytic_MagDipoleWholespace", "EM_TDEM_1D_Inversion", "FLOW_Richards_1D_Celia1990", "Forward_BasicDirectCurrent", "Inversion_Linear", "Mesh_Basic_PlotImage", "Mesh_Basic_Types", "Mesh_Operators_CahnHilliard", "Mesh_QuadTree_Creation", "Mesh_QuadTree_FaceDiv", "Mesh_QuadTree_HangingNodes", "Mesh_Tensor_Creation", "MT_1D_ForwardAndInversion", "MT_3D_Foward"] +__examples__ = ["DC_Analytic_Dipole", "DC_Forward_PseudoSection", "EM_FDEM_1D_Inversion", "EM_FDEM_Analytic_MagDipoleWholespace", "EM_Schenkel_Morrison_Casing", "EM_TDEM_1D_Inversion", "FLOW_Richards_1D_Celia1990", "Forward_BasicDirectCurrent", "Inversion_Linear", "Mesh_Basic_PlotImage", "Mesh_Basic_Types", "Mesh_Operators_CahnHilliard", "Mesh_QuadTree_Creation", "Mesh_QuadTree_FaceDiv", "Mesh_QuadTree_HangingNodes", "Mesh_Tensor_Creation", "MT_1D_ForwardAndInversion", "MT_3D_Foward"] ##### AUTOIMPORTS ##### diff --git a/docs/examples/EM_Schenkel_Morrison_Casing.rst b/docs/examples/EM_Schenkel_Morrison_Casing.rst new file mode 100644 index 00000000..54e74dba --- /dev/null +++ b/docs/examples/EM_Schenkel_Morrison_Casing.rst @@ -0,0 +1,52 @@ +.. _examples_EM_Schenkel_Morrison_Casing: + +.. --------------------------------- .. +.. .. +.. THIS FILE IS AUTO GENEREATED .. +.. .. +.. SimPEG/Examples/__init__.py .. +.. .. +.. --------------------------------- .. + + +Schenkel and Morrison Casing Model +================================== + + we will create and run a FDEM forward simulation based on the +nkel and Morrison Casing Model + +chenkel, C.J., and H.F. Morrison, 1990`_, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. + +Schenkel, C. J., and H. F. Morrison, 1990: http://onlinelibrary.wiley.com/store/10.1111/j.1365-2478.1990.tb01868.x/asset/j.1365-2478.1990.tb01868.x.pdf?v=1&t=imdt3o85&s=38248af166c2887ed587d94c8ccafad30b480529 + +model consists of: +r: Conductivity 1e-8 S/m, above z = 0 +ckground: conductivity 1e-2 S/m, below z = 0 +sing: conductivity 1e6 S/m +- 300m long +- radius of 0.1m +- thickness of 6e-3m + +de the casing, we take the same conductivity as the background. + +re using an EM code to simulate DC, so we use frequency low enough + the skin depth inside the casing is longer than the casing length (f +-6 Hz). The plot produced is of the current inside the casing. + +e results are shown in the SEG abstract by Yang et al., 2016: 3D DC +stivity modeling of steel casing for reservoir monitoring using +valent resistor network. The solver used to produce these results and +eve the CPU time of ~30s is Mumps, which was installed using pymatsolver_ + +pymatsolver: https://github.com/rowanc1/pymatsolver + + + +.. plot:: + + from SimPEG import Examples + Examples.EM_Schenkel_Morrison_Casing.run() + +.. literalinclude:: ../../SimPEG/Examples/EM_Schenkel_Morrison_Casing.py + :language: python + :linenos: From fbec011983e6939e8e8435a6cc827ed856135216 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Tue, 29 Mar 2016 14:29:39 -0700 Subject: [PATCH 10/18] typo fix --- SimPEG/Examples/EM_Schenkel_Morrison_Casing.py | 2 +- docs/examples/EM_Schenkel_Morrison_Casing.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py index ef51b25c..bcf277e1 100644 --- a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py +++ b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py @@ -19,7 +19,7 @@ def run(plotIt=True): - `Schenkel, C.J., and H.F. Morrison, 1990`_, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. - .. _Schenkel, C. J., and H. F. Morrison, 1990: http://onlinelibrary.wiley.com/store/10.1111/j.1365-2478.1990.tb01868.x/asset/j.1365-2478.1990.tb01868.x.pdf?v=1&t=imdt3o85&s=38248af166c2887ed587d94c8ccafad30b480529 + .. _Schenkel, C.J., and H.F. Morrison, 1990: http://onlinelibrary.wiley.com/store/10.1111/j.1365-2478.1990.tb01868.x/asset/j.1365-2478.1990.tb01868.x.pdf?v=1&t=imdt3o85&s=38248af166c2887ed587d94c8ccafad30b480529 The model consists of: - Air: Conductivity 1e-8 S/m, above z = 0 diff --git a/docs/examples/EM_Schenkel_Morrison_Casing.rst b/docs/examples/EM_Schenkel_Morrison_Casing.rst index 54e74dba..6f356277 100644 --- a/docs/examples/EM_Schenkel_Morrison_Casing.rst +++ b/docs/examples/EM_Schenkel_Morrison_Casing.rst @@ -17,7 +17,7 @@ nkel and Morrison Casing Model chenkel, C.J., and H.F. Morrison, 1990`_, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. -Schenkel, C. J., and H. F. Morrison, 1990: http://onlinelibrary.wiley.com/store/10.1111/j.1365-2478.1990.tb01868.x/asset/j.1365-2478.1990.tb01868.x.pdf?v=1&t=imdt3o85&s=38248af166c2887ed587d94c8ccafad30b480529 +Schenkel, C.J., and H.F. Morrison, 1990: http://onlinelibrary.wiley.com/store/10.1111/j.1365-2478.1990.tb01868.x/asset/j.1365-2478.1990.tb01868.x.pdf?v=1&t=imdt3o85&s=38248af166c2887ed587d94c8ccafad30b480529 model consists of: r: Conductivity 1e-8 S/m, above z = 0 From 7aa559921145503a5b42dd317cbdda0f47ca5bd1 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Tue, 29 Mar 2016 14:41:45 -0700 Subject: [PATCH 11/18] improve the description --- SimPEG/Examples/EM_Schenkel_Morrison_Casing.py | 6 ++++-- docs/examples/EM_Schenkel_Morrison_Casing.rst | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py index bcf277e1..7cfd4c9c 100644 --- a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py +++ b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py @@ -14,8 +14,10 @@ def run(plotIt=True): EM: Schenkel and Morrison Casing Model ====================================== - Here we will create and run a FDEM forward simulation based on the - Schenkel and Morrison Casing Model + Here we create and run a FDEM forward simulation to calculate the vertical + current inside a steel-cased. The model is based on the Schenkel and + Morrison Casing Model, and the results are used in a 2016 SEG abstract by + Yang et al. - `Schenkel, C.J., and H.F. Morrison, 1990`_, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. diff --git a/docs/examples/EM_Schenkel_Morrison_Casing.rst b/docs/examples/EM_Schenkel_Morrison_Casing.rst index 6f356277..730b8507 100644 --- a/docs/examples/EM_Schenkel_Morrison_Casing.rst +++ b/docs/examples/EM_Schenkel_Morrison_Casing.rst @@ -12,8 +12,10 @@ Schenkel and Morrison Casing Model ================================== - we will create and run a FDEM forward simulation based on the -nkel and Morrison Casing Model + we create and run a FDEM forward simulation to calculate the vertical +ent inside a steel-cased. The model is based on the Schenkel and +ison Casing Model, and the results are used in a 2016 SEG abstract by + et al. chenkel, C.J., and H.F. Morrison, 1990`_, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. From 824ce64c7e7e00f25fa1dd76bfcb88488f1de785 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Tue, 29 Mar 2016 14:56:56 -0700 Subject: [PATCH 12/18] more descriptive titles --- SimPEG/Examples/EM_Schenkel_Morrison_Casing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py index 7cfd4c9c..701c67d4 100644 --- a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py +++ b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py @@ -257,11 +257,11 @@ def run(plotIt=True): ax[0].plot(z_in,np.absolute(I0), z_in,np.absolute(I1)) ax[0].legend(['top casing', 'bottom casing'],loc='best') - ax[0].set_title('Magnitude of Current') + ax[0].set_title('Magnitude of Vertical Current in Casing') ax[1].semilogy(z_in,np.absolute(I0), z_in,np.absolute(I1)) ax[1].legend(['top casing', 'bottom casing'],loc='best') - ax[1].set_title('Magnitude of Current') + ax[1].set_title('Magnitude of Vertical Current in Casing') ax[1].set_ylim([1e-2, 1.]) plt.show() From b6438688d8224d136eaf993932a29d6b09ab4192 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Tue, 29 Mar 2016 15:40:06 -0700 Subject: [PATCH 13/18] removed link for Schenkel paper (it seems to time-out) --- SimPEG/Examples/EM_Schenkel_Morrison_Casing.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py index 701c67d4..e9d37cfe 100644 --- a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py +++ b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py @@ -19,9 +19,8 @@ def run(plotIt=True): Morrison Casing Model, and the results are used in a 2016 SEG abstract by Yang et al. - - `Schenkel, C.J., and H.F. Morrison, 1990`_, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. + - Schenkel, C.J., and H.F. Morrison, 1990, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. - .. _Schenkel, C.J., and H.F. Morrison, 1990: http://onlinelibrary.wiley.com/store/10.1111/j.1365-2478.1990.tb01868.x/asset/j.1365-2478.1990.tb01868.x.pdf?v=1&t=imdt3o85&s=38248af166c2887ed587d94c8ccafad30b480529 The model consists of: - Air: Conductivity 1e-8 S/m, above z = 0 From 0a0caceaca45da0a542e8f4cc4e9750cebd03409 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Tue, 29 Mar 2016 22:49:03 -0700 Subject: [PATCH 14/18] Problem.Jvec, Problem.Jtvec, Problem.fields, DataMisfit, survey.dpred take a fields object f (not a solution vector, u) --- SimPEG/DCIP/BaseDC.py | 24 +++++----- SimPEG/DCIP/BaseIP.py | 8 ++-- SimPEG/DataMisfit.py | 46 +++++++++----------- SimPEG/FLOW/Richards/RichardsProblem.py | 58 ++++++++++++------------- SimPEG/Problem.py | 28 ++++++------ SimPEG/Survey.py | 26 +++++------ tests/flow/test_Richards.py | 12 ++--- 7 files changed, 98 insertions(+), 104 deletions(-) diff --git a/SimPEG/DCIP/BaseDC.py b/SimPEG/DCIP/BaseDC.py index e3d353d7..475c621e 100644 --- a/SimPEG/DCIP/BaseDC.py +++ b/SimPEG/DCIP/BaseDC.py @@ -200,11 +200,11 @@ class ProblemDC_CC(Problem.BaseProblem): return F - def Jvec(self, m, v, u=None): + def Jvec(self, m, v, f=None): """ :param numpy.array m: model :param numpy.array v: vector to multiply - :param numpy.array u: fields + :param Fields f: fields :rtype: numpy.array :return: Jv @@ -225,11 +225,10 @@ class ProblemDC_CC(Problem.BaseProblem): # Set current model; clear dependent property $\mathbf{A(m)}$ self.curModel = m sigma = self.curModel.transform # $\sigma = \mathcal{M}(\m)$ - if u is None: + if f is None: # Run forward simulation if $u$ not provided - u = self.fields(self.curModel)[self.survey.srcList, 'phi_sol'] - else: - u = u[self.survey.srcList, 'phi_sol'] + f = self.fields(self.curModel) + u = f[self.survey.srcList, 'phi_sol'] D = self.mesh.faceDiv G = self.mesh.cellGrad @@ -251,19 +250,18 @@ class ProblemDC_CC(Problem.BaseProblem): if self.Ainv is None: self.Ainv = self.Solver(dA_du, **self.solverOpts) - P = self.survey.getP(self.mesh) + P = self.survey.getP(self.mesh) Jv = - P * mkvc( self.Ainv * dCdm_x_v ) return Jv - def Jtvec(self, m, v, u=None): + def Jtvec(self, m, v, f=None): self.curModel = m sigma = self.curModel.transform # $\sigma = \mathcal{M}(\m)$ - if u is None: - # Run forward simulation if $u$ not provided - u = self.fields(self.curModel)[self.survey.srcList, 'phi_sol'] - else: - u = u[self.survey.srcList, 'phi_sol'] + if f is None: + # Run forward simulation if $f$ not provided + f = self.fields(self.curModel) + u = f[self.survey.srcList, 'phi_sol'] shp = u.shape P = self.survey.getP(self.mesh) diff --git a/SimPEG/DCIP/BaseIP.py b/SimPEG/DCIP/BaseIP.py index cec0ea2e..a18b5a47 100644 --- a/SimPEG/DCIP/BaseIP.py +++ b/SimPEG/DCIP/BaseIP.py @@ -14,12 +14,12 @@ class SurveyIP(SurveyDC): Survey.BaseSurvey.__init__(self, **kwargs) self._Ps = {} - def dpred(self, m, u=None): + def dpred(self, m, f=None): """ Predicted data. .. math:: - d_\\text{pred} = Pu(m) + d_\\text{pred} = Pf(m) """ return self.prob.forward(m) @@ -143,10 +143,10 @@ class ProblemIP(Problem.BaseProblem): J_x_v = - P * mkvc( self.Ainv * dCdm_x_v ) return -J_x_v - def Jvec(self, m, v, u=None): + def Jvec(self, m, v, f=None): return self.forward(v) - def Jtvec(self, m, v, u=None): + def Jtvec(self, m, v, f=None): self.curModel = m # sigma = self.curModel.transform # $\sigma = \mathcal{M}(\m)$ diff --git a/SimPEG/DataMisfit.py b/SimPEG/DataMisfit.py index 13574771..1fbf7b2d 100644 --- a/SimPEG/DataMisfit.py +++ b/SimPEG/DataMisfit.py @@ -22,11 +22,11 @@ class BaseDataMisfit(object): Utils.setKwargs(self,**kwargs) @Utils.timeIt - def eval(self, m, u=None): - """eval(m, u=None) + def eval(self, m, f=None): + """eval(m, f=None) :param numpy.array m: geophysical model - :param numpy.array u: fields + :param Fields f: fields :rtype: float :return: data misfit @@ -34,11 +34,11 @@ class BaseDataMisfit(object): raise NotImplementedError('This method should be overwritten.') @Utils.timeIt - def evalDeriv(self, m, u=None): - """evalDeriv(m, u=None) + def evalDeriv(self, m, f=None): + """evalDeriv(m, f=None) :param numpy.array m: geophysical model - :param numpy.array u: fields + :param Fields f: fields :rtype: numpy.array :return: data misfit derivative @@ -47,12 +47,12 @@ class BaseDataMisfit(object): @Utils.timeIt - def eval2Deriv(self, m, v, u=None): - """eval2Deriv(m, v, u=None) + def eval2Deriv(self, m, v, f=None): + """eval2Deriv(m, v, f=None) :param numpy.array m: geophysical model :param numpy.array v: vector to multiply - :param numpy.array u: fields + :param Fields f: fields :rtype: numpy.array :return: data misfit derivative @@ -108,24 +108,20 @@ class l2_DataMisfit(BaseDataMisfit): self._Wd = value @Utils.timeIt - def eval(self, m, u=None): - "eval(m, u=None)" - prob = self.prob - survey = self.survey - R = self.Wd * survey.residual(m, u) + def eval(self, m, f=None): + "eval(m, f=None)" + if f is None: f = self.prob.fields(m) + R = self.Wd * self.survey.residual(m, f) return 0.5*np.vdot(R, R) @Utils.timeIt - def evalDeriv(self, m, u=None): - "evalDeriv(m, u=None)" - prob = self.prob - survey = self.survey - if u is None: u = prob.fields(m) - return prob.Jtvec(m, self.Wd * (self.Wd * survey.residual(m, u)), u) + def evalDeriv(self, m, f=None): + "evalDeriv(m, f=None)" + if f is None: f = self.prob.fields(m) + return self.prob.Jtvec(m, self.Wd * (self.Wd * self.survey.residual(m, f=f)), f=f) @Utils.timeIt - def eval2Deriv(self, m, v, u=None): - "eval2Deriv(m, v, u=None)" - prob = self.prob - if u is None: u = prob.fields(m) - return prob.Jtvec_approx(m, self.Wd * (self.Wd * prob.Jvec_approx(m, v, u=u)), u) + def eval2Deriv(self, m, v, f=None): + "eval2Deriv(m, v, f=None)" + if f is None: f = prob.fields(m) + return self.prob.Jtvec_approx(m, self.Wd * (self.Wd * prob.Jvec_approx(m, v, f=f)), f=f) diff --git a/SimPEG/FLOW/Richards/RichardsProblem.py b/SimPEG/FLOW/Richards/RichardsProblem.py index 4dcabe60..2346f4da 100644 --- a/SimPEG/FLOW/Richards/RichardsProblem.py +++ b/SimPEG/FLOW/Richards/RichardsProblem.py @@ -45,19 +45,19 @@ class RichardsSurvey(Survey.BaseSurvey): @Utils.count @Utils.requires('prob') - def dpred(self, m, u=None): + def dpred(self, m, f=None): """ Create the projected data from a model. - The field, u, (if provided) will be used for the predicted data + The field, f, (if provided) will be used for the predicted data instead of recalculating the fields (which may be expensive!). .. math:: - d_\\text{pred} = P(u(m), m) + d_\\text{pred} = P(f(m), m) Where P is a projection of the fields onto the data space. """ - if u is None: u = self.prob.fields(m) - return Utils.mkvc(self.eval(u, m)) + if f is None: f = self.prob.fields(m) + return Utils.mkvc(self.eval(f, m)) @Utils.requires('prob') def eval(self, U, m): @@ -233,16 +233,16 @@ class RichardsProblem(Problem.BaseTimeProblem): return r, J @Utils.timeIt - def Jfull(self, m, u=None): - if u is None: - u = self.fields(m) + def Jfull(self, m, f=None): + if f is None: + f = self.fields(m) - nn = len(u)-1 + nn = len(f)-1 Asubs, Adiags, Bs = range(nn), range(nn), range(nn) for ii in range(nn): dt = self.timeSteps[ii] - bc = self.getBoundaryConditions(ii, u[ii]) - Asubs[ii], Adiags[ii], Bs[ii] = self.diagsJacobian(m, u[ii], u[ii+1], dt, bc) + 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]) @@ -251,7 +251,7 @@ class RichardsProblem(Problem.BaseTimeProblem): B = np.array(sp.vstack(Bs).todense()) Ainv = self.Solver(A, **self.solverOpts) - P = self.survey.evalDeriv(u, m) + P = self.survey.evalDeriv(f, m) AinvB = Ainv * B z = np.zeros((self.mesh.nC, B.shape[1])) zAinvB = np.vstack((z, AinvB)) @@ -259,41 +259,41 @@ class RichardsProblem(Problem.BaseTimeProblem): return J @Utils.timeIt - def Jvec(self, m, v, u=None): - if u is None: - u = self.fields(m) + def Jvec(self, m, v, f=None): + if f is None: + f = self.fields(m) - JvC = range(len(u)-1) # Cell to hold each row of the long vector. + JvC = range(len(f)-1) # Cell to hold each row of the long vector. # This is done via forward substitution. - bc = self.getBoundaryConditions(0, u[0]) - temp, Adiag, B = self.diagsJacobian(m, u[0], u[1], self.timeSteps[0], bc) + bc = self.getBoundaryConditions(0, f[0]) + temp, Adiag, B = self.diagsJacobian(m, f[0], f[1], self.timeSteps[0], bc) Adiaginv = self.Solver(Adiag, **self.solverOpts) JvC[0] = Adiaginv * (B*v) - for ii in range(1,len(u)-1): - bc = self.getBoundaryConditions(ii, u[ii]) - Asub, Adiag, B = self.diagsJacobian(m, u[ii], u[ii+1], self.timeSteps[ii], bc) + for ii in range(1,len(f)-1): + bc = self.getBoundaryConditions(ii, f[ii]) + Asub, Adiag, B = self.diagsJacobian(m, f[ii], f[ii+1], self.timeSteps[ii], bc) Adiaginv = self.Solver(Adiag, **self.solverOpts) JvC[ii] = Adiaginv * (B*v - Asub*JvC[ii-1]) - P = self.survey.evalDeriv(u, m) + P = self.survey.evalDeriv(f, m) return P * np.concatenate([np.zeros(self.mesh.nC)] + JvC) @Utils.timeIt - def Jtvec(self, m, v, u=None): - if u is None: - u = self.field(m) + def Jtvec(self, m, v, f=None): + if f is None: + f = self.field(m) - P = self.survey.evalDeriv(u, m) + P = self.survey.evalDeriv(f, m) PTv = P.T*v # This is done via backward substitution. minus = 0 BJtv = 0 - for ii in range(len(u)-1,0,-1): - bc = self.getBoundaryConditions(ii-1, u[ii-1]) - Asub, Adiag, B = self.diagsJacobian(m, u[ii-1], u[ii], self.timeSteps[ii-1], bc) + for ii in range(len(f)-1,0,-1): + bc = self.getBoundaryConditions(ii-1, f[ii-1]) + Asub, Adiag, B = self.diagsJacobian(m, f[ii-1], f[ii], self.timeSteps[ii-1], bc) #select the correct part of v vpart = range((ii)*Adiag.shape[0], (ii+1)*Adiag.shape[0]) AdiaginvT = self.Solver(Adiag.T, **self.solverOpts) diff --git a/SimPEG/Problem.py b/SimPEG/Problem.py index cd8a4aaa..8ed94e97 100644 --- a/SimPEG/Problem.py +++ b/SimPEG/Problem.py @@ -88,28 +88,28 @@ class BaseProblem(object): return self.survey is not None @Utils.timeIt - def Jvec(self, m, v, u=None): - """Jvec(m, v, u=None) + def Jvec(self, m, v, f=None): + """Jvec(m, v, f=None) Effect of J(m) on a vector v. :param numpy.array m: model :param numpy.array v: vector to multiply - :param numpy.array u: fields + :param Fields f: fields :rtype: numpy.array :return: Jv """ raise NotImplementedError('J is not yet implemented.') @Utils.timeIt - def Jtvec(self, m, v, u=None): - """Jtvec(m, v, u=None) + def Jtvec(self, m, v, f=None): + """Jtvec(m, v, f=None) Effect of transpose of J(m) on a vector v. :param numpy.array m: model :param numpy.array v: vector to multiply - :param numpy.array u: fields + :param Fields f: fields :rtype: numpy.array :return: JTv """ @@ -117,28 +117,28 @@ class BaseProblem(object): @Utils.timeIt - def Jvec_approx(self, m, v, u=None): - """Jvec_approx(m, v, u=None) + def Jvec_approx(self, m, v, f=None): + """Jvec_approx(m, v, f=None) Approximate effect of J(m) on a vector v :param numpy.array m: model :param numpy.array v: vector to multiply - :param numpy.array u: fields + :param Fields f: fields :rtype: numpy.array :return: approxJv """ return self.Jvec(m, v, u) @Utils.timeIt - def Jtvec_approx(self, m, v, u=None): - """Jtvec_approx(m, v, u=None) + def Jtvec_approx(self, m, v, f=None): + """Jtvec_approx(m, v, f=None) Approximate effect of transpose of J(m) on a vector v. :param numpy.array m: model :param numpy.array v: vector to multiply - :param numpy.array u: fields + :param Fields f: fields :rtype: numpy.array :return: JTv """ @@ -224,9 +224,9 @@ class LinearProblem(BaseProblem): def fields(self, m): return self.G.dot(m) - def Jvec(self, m, v, u=None): + def Jvec(self, m, v, f=None): return self.G.dot(v) - def Jtvec(self, m, v, u=None): + def Jtvec(self, m, v, f=None): return self.G.T.dot(v) diff --git a/SimPEG/Survey.py b/SimPEG/Survey.py index 37024028..9ddd269e 100644 --- a/SimPEG/Survey.py +++ b/SimPEG/Survey.py @@ -295,21 +295,21 @@ class BaseSurvey(object): @Utils.count @Utils.requires('prob') - def dpred(self, m, u=None): - """dpred(m, u=None) + def dpred(self, m, f=None): + """dpred(m, f=None) Create the projected data from a model. - The field, u, (if provided) will be used for the predicted data + The fields, f, (if provided) will be used for the predicted data instead of recalculating the fields (which may be expensive!). .. math:: - d_\\text{pred} = P(u(m)) + d_\\text{pred} = P(f(m)) Where P is a projection of the fields onto the data space. """ - if u is None: u = self.prob.fields(m) - return Utils.mkvc(self.eval(u)) + if f is None: f = self.prob.fields(m) + return Utils.mkvc(self.eval(f)) @Utils.count @@ -337,11 +337,11 @@ class BaseSurvey(object): raise NotImplemented('eval is not yet implemented.') @Utils.count - def residual(self, m, u=None): - """residual(m, u=None) + def residual(self, m, f=None): + """residual(m, f=None) :param numpy.array m: geophysical model - :param numpy.array u: fields + :param numpy.array f: fields :rtype: numpy.array :return: data residual @@ -352,14 +352,14 @@ class BaseSurvey(object): \mu_\\text{data} = \mathbf{d}_\\text{pred} - \mathbf{d}_\\text{obs} """ - return Utils.mkvc(self.dpred(m, u=u) - self.dobs) + return Utils.mkvc(self.dpred(m, f=f) - self.dobs) @property def isSynthetic(self): "Check if the data is synthetic." return self.mtrue is not None - def makeSyntheticData(self, m, std=0.05, u=None, force=False): + def makeSyntheticData(self, m, std=0.05, f=None, force=False): """ Make synthetic data given a model, and a standard deviation. @@ -372,7 +372,7 @@ class BaseSurvey(object): if getattr(self, 'dobs', None) is not None and not force: raise Exception('Survey already has dobs. You can use force=True to override this exception.') self.mtrue = m - self.dtrue = self.dpred(m, u=u) + self.dtrue = self.dpred(m, f=f) noise = std*abs(self.dtrue)*np.random.randn(*self.dtrue.shape) self.dobs = self.dtrue+noise self.std = self.dobs*0 + std @@ -381,7 +381,7 @@ class BaseSurvey(object): class LinearSurvey(BaseSurvey): def eval(self, u): return u - + @property def nD(self): return self.prob.G.shape[0] diff --git a/tests/flow/test_Richards.py b/tests/flow/test_Richards.py index d63a6210..f67ec71d 100644 --- a/tests/flow/test_Richards.py +++ b/tests/flow/test_Richards.py @@ -116,8 +116,8 @@ class RichardsTests1D(unittest.TestCase): v = np.random.rand(self.survey.nD) z = np.random.rand(self.M.nC) Hs = self.prob.fields(self.Ks) - vJz = v.dot(self.prob.Jvec(self.Ks,z,u=Hs)) - zJv = z.dot(self.prob.Jtvec(self.Ks,v,u=Hs)) + vJz = v.dot(self.prob.Jvec(self.Ks,z,f=Hs)) + zJv = z.dot(self.prob.Jtvec(self.Ks,v,f=Hs)) tol = TOL*(10**int(np.log10(np.abs(zJv)))) passed = np.abs(vJz - zJv) < tol print 'Richards Adjoint Test - PressureHead' @@ -188,8 +188,8 @@ class RichardsTests2D(unittest.TestCase): v = np.random.rand(self.survey.nD) z = np.random.rand(self.M.nC) Hs = self.prob.fields(self.Ks) - vJz = v.dot(self.prob.Jvec(self.Ks,z,u=Hs)) - zJv = z.dot(self.prob.Jtvec(self.Ks,v,u=Hs)) + vJz = v.dot(self.prob.Jvec(self.Ks,z,f=Hs)) + zJv = z.dot(self.prob.Jtvec(self.Ks,v,f=Hs)) tol = TOL*(10**int(np.log10(np.abs(zJv)))) passed = np.abs(vJz - zJv) < tol print '2D: Richards Adjoint Test - PressureHead' @@ -260,8 +260,8 @@ class RichardsTests3D(unittest.TestCase): v = np.random.rand(self.survey.nD) z = np.random.rand(self.M.nC) Hs = self.prob.fields(self.Ks) - vJz = v.dot(self.prob.Jvec(self.Ks,z,u=Hs)) - zJv = z.dot(self.prob.Jtvec(self.Ks,v,u=Hs)) + vJz = v.dot(self.prob.Jvec(self.Ks,z,f=Hs)) + zJv = z.dot(self.prob.Jtvec(self.Ks,v,f=Hs)) tol = TOL*(10**int(np.log10(np.abs(zJv)))) passed = np.abs(vJz - zJv) < tol print '3D: Richards Adjoint Test - PressureHead' From d8d8915f942ef1f5430ba57dd726a00cb747c4ba Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Thu, 31 Mar 2016 09:28:48 -0700 Subject: [PATCH 15/18] f for fields in data misfit, directives etc. Previously, f was used in the InvProblem to be the function value for the objective function --> this has been renamed to phi --- SimPEG/DataMisfit.py | 4 ++-- SimPEG/Directives.py | 4 ++-- SimPEG/EM/FDEM/SurveyFDEM.py | 16 ++++++++-------- SimPEG/EM/TDEM/BaseTDEM.py | 22 +++++++++++----------- SimPEG/InvProblem.py | 26 +++++++++++++------------- SimPEG/MT/BaseMT.py | 26 +++++++++++++------------- SimPEG/MT/SurveyMT.py | 6 +++--- SimPEG/Problem.py | 4 ++-- SimPEG/Survey.py | 14 +++++++------- 9 files changed, 61 insertions(+), 61 deletions(-) diff --git a/SimPEG/DataMisfit.py b/SimPEG/DataMisfit.py index 1fbf7b2d..53728c4e 100644 --- a/SimPEG/DataMisfit.py +++ b/SimPEG/DataMisfit.py @@ -123,5 +123,5 @@ class l2_DataMisfit(BaseDataMisfit): @Utils.timeIt def eval2Deriv(self, m, v, f=None): "eval2Deriv(m, v, f=None)" - if f is None: f = prob.fields(m) - return self.prob.Jtvec_approx(m, self.Wd * (self.Wd * prob.Jvec_approx(m, v, f=f)), f=f) + if f is None: f = self.prob.fields(m) + return self.prob.Jtvec_approx(m, self.Wd * (self.Wd * self.prob.Jvec_approx(m, v, f=f)), f=f) diff --git a/SimPEG/Directives.py b/SimPEG/Directives.py index 2ed27c20..3d726712 100644 --- a/SimPEG/Directives.py +++ b/SimPEG/Directives.py @@ -123,10 +123,10 @@ class BetaEstimate_ByEig(InversionDirective): if self.debug: print 'Calculating the beta0 parameter.' m = self.invProb.curModel - u = self.invProb.getFields(m, store=True, deleteWarmstart=False) + f = self.invProb.getFields(m, store=True, deleteWarmstart=False) x0 = np.random.rand(*m.shape) - t = x0.dot(self.dmisfit.eval2Deriv(m,x0,u=u)) + t = x0.dot(self.dmisfit.eval2Deriv(m,x0,f=f)) b = x0.dot(self.reg.eval2Deriv(m, v=x0)) self.beta0 = self.beta0_ratio*(t/b) diff --git a/SimPEG/EM/FDEM/SurveyFDEM.py b/SimPEG/EM/FDEM/SurveyFDEM.py index 163f6914..1552a12c 100644 --- a/SimPEG/EM/FDEM/SurveyFDEM.py +++ b/SimPEG/EM/FDEM/SurveyFDEM.py @@ -67,7 +67,7 @@ class Rx(SimPEG.Survey.BaseRx): """Grid Location projection (e.g. Ex Fy ...)""" return u._GLoc(self.rxType[0]) + self.knownRxTypes[self.rxType][1] - def eval(self, src, mesh, u): + def eval(self, src, mesh, f): """ Project fields to recievers to get data. @@ -80,27 +80,27 @@ class Rx(SimPEG.Survey.BaseRx): # projGLoc = u._GLoc(self.knownRxTypes[self.rxType][0]) # projGLoc += self.knownRxTypes[self.rxType][1] - P = self.getP(mesh, self.projGLoc(u)) - u_part_complex = u[src, self.projField] + P = self.getP(mesh, self.projGLoc(f)) + f_part_complex = f[src, self.projField] # get the real or imag component real_or_imag = self.projComp - u_part = getattr(u_part_complex, real_or_imag) + f_part = getattr(f_part_complex, real_or_imag) - return P*u_part + return P*f_part - def evalDeriv(self, src, mesh, u, v, adjoint=False): + def evalDeriv(self, src, mesh, f, v, adjoint=False): """ Derivative of projected fields with respect to the inversion model times a vector. :param Source src: FDEM source :param Mesh mesh: mesh used - :param Fields u: fields object + :param Fields f: fields object :param numpy.ndarray v: vector to multiply :rtype: numpy.ndarray :return: fields projected to recievers """ - P = self.getP(mesh, self.projGLoc(u)) + P = self.getP(mesh, self.projGLoc(f)) if not adjoint: Pv_complex = P * v diff --git a/SimPEG/EM/TDEM/BaseTDEM.py b/SimPEG/EM/TDEM/BaseTDEM.py index 0da22072..15fc19e3 100644 --- a/SimPEG/EM/TDEM/BaseTDEM.py +++ b/SimPEG/EM/TDEM/BaseTDEM.py @@ -108,11 +108,11 @@ class BaseTDEMProblem(BaseTimeProblem, BaseEMProblem): Ainv.clean() return F - def Jvec(self, m, v, u=None): + def Jvec(self, m, v, f=None): """ :param numpy.array m: Conductivity model :param numpy.ndarray v: vector (model object) - :param simpegEM.TDEM.FieldsTDEM u: Fields resulting from m + :param simpegEM.TDEM.FieldsTDEM f: Fields resulting from m :rtype: numpy.ndarray :return: w (data object) @@ -125,15 +125,15 @@ class BaseTDEMProblem(BaseTimeProblem, BaseEMProblem): """ if self.verbose: print '%s\nCalculating J(v)\n%s'%('*'*50,'*'*50) self.curModel = m - if u is None: - u = self.fields(m) - p = self.Gvec(m, v, u) + if f is None: + f = self.fields(m) + p = self.Gvec(m, v, f) y = self.solveAh(m, p) - Jv = self.survey.evalDeriv(u, v=y) + Jv = self.survey.evalDeriv(f, v=y) if self.verbose: print '%s\nDone calculating J(v)\n%s'%('*'*50,'*'*50) return - mkvc(Jv) - def Jtvec(self, m, v, u=None): + def Jtvec(self, m, v, f=None): """ :param numpy.array m: Conductivity model :param numpy.ndarray,SimPEG.Survey.Data v: vector (data object) @@ -150,15 +150,15 @@ class BaseTDEMProblem(BaseTimeProblem, BaseEMProblem): """ if self.verbose: print '%s\nCalculating J^T(v)\n%s'%('*'*50,'*'*50) self.curModel = m - if u is None: - u = self.fields(m) + if f is None: + f = self.fields(m) if not isinstance(v, self.dataPair): v = self.dataPair(self.survey, v) - p = self.survey.evalDeriv(u, v=v, adjoint=True) + p = self.survey.evalDeriv(f, v=v, adjoint=True) y = self.solveAht(m, p) - w = self.Gtvec(m, y, u) + w = self.Gtvec(m, y, f) if self.verbose: print '%s\nDone calculating J^T(v)\n%s'%('*'*50,'*'*50) return - mkvc(w) diff --git a/SimPEG/InvProblem.py b/SimPEG/InvProblem.py index 0296bf4b..fd6c48c3 100644 --- a/SimPEG/InvProblem.py +++ b/SimPEG/InvProblem.py @@ -82,23 +82,23 @@ class BaseInvProblem(object): self._warmstart = value def getFields(self, m, store=False, deleteWarmstart=True): - u = None + f = None for mtest, u_ofmtest in self.warmstart: if m is mtest: - u = u_ofmtest + f = u_ofmtest if self.debug: print 'InvProb is Warm Starting!' break - if u is None: - u = self.prob.fields(m) + if f is None: + f = self.prob.fields(m) if deleteWarmstart: self.warmstart = [] if store: - self.warmstart += [(m,u)] + self.warmstart += [(m,f)] - return u + return f @Utils.timeIt def evalFunction(self, m, return_g=True, return_H=True): @@ -109,21 +109,21 @@ class BaseInvProblem(object): gc.collect() # Store fields if doing a line-search - u = self.getFields(m, store=(return_g==False and return_H==False)) + f = self.getFields(m, store=(return_g==False and return_H==False)) - phi_d = self.dmisfit.eval(m, u=u) + phi_d = self.dmisfit.eval(m, f=f) phi_m = self.reg.eval(m) - self.dpred = self.survey.dpred(m, u=u) # This is a cheap matrix vector calculation. + self.dpred = self.survey.dpred(m, f=f) # This is a cheap matrix vector calculation. self.phi_d, self.phi_d_last = phi_d, self.phi_d self.phi_m, self.phi_m_last = phi_m, self.phi_m - f = phi_d + self.beta * phi_m + phi = phi_d + self.beta * phi_m - out = (f,) + out = (phi,) if return_g: - phi_dDeriv = self.dmisfit.evalDeriv(m, u=u) + phi_dDeriv = self.dmisfit.evalDeriv(m, f=f) phi_mDeriv = self.reg.evalDeriv(m) g = phi_dDeriv + self.beta * phi_mDeriv @@ -131,7 +131,7 @@ class BaseInvProblem(object): if return_H: def H_fun(v): - phi_d2Deriv = self.dmisfit.eval2Deriv(m, v, u=u) + phi_d2Deriv = self.dmisfit.eval2Deriv(m, v, f=f) phi_m2Deriv = self.reg.eval2Deriv(m, v=v) return phi_d2Deriv + self.beta * phi_m2Deriv diff --git a/SimPEG/MT/BaseMT.py b/SimPEG/MT/BaseMT.py index 36389430..c201dfb0 100644 --- a/SimPEG/MT/BaseMT.py +++ b/SimPEG/MT/BaseMT.py @@ -27,7 +27,7 @@ class BaseMTProblem(BaseFDEMProblem): # Might need to add more stuff here. ## NEED to clean up the Jvec and Jtvec to use Zero and Identities for None components. - def Jvec(self, m, v, u=None): + def Jvec(self, m, v, f=None): """ Function to calculate the data sensitivities dD/dm times a vector. @@ -39,8 +39,8 @@ class BaseMTProblem(BaseFDEMProblem): """ # Calculate the fields - if u is None: - u = self.fields(m) + if f is None: + f= self.fields(m) # Set current model self.curModel = m # Initiate the Jv object @@ -56,9 +56,9 @@ class BaseMTProblem(BaseFDEMProblem): # We need fDeriv_m = df/du*du/dm + df/dm # Construct du/dm, it requires a solve # NOTE: need to account for the 2 polarizations in the derivatives. - u_src = u[src,:] + f_src = f[src,:] # dA_dm and dRHS_dm should be of size nE,2, so that we can multiply by dA_duI. The 2 columns are each of the polarizations. - dA_dm = self.getADeriv_m(freq, u_src, v) # Size: nE,2 (u_px,u_py) in the columns. + dA_dm = self.getADeriv_m(freq, f_src, v) # Size: nE,2 (u_px,u_py) in the columns. dRHS_dm = self.getRHSDeriv_m(freq, v) # Size: nE,2 (u_px,u_py) in the columns. if dRHS_dm is None: du_dm = dA_duI * ( -dA_dm ) @@ -68,13 +68,13 @@ class BaseMTProblem(BaseFDEMProblem): for rx in src.rxList: # Get the projection derivative # v should be of size 2*nE (for 2 polarizations) - PDeriv_u = lambda t: rx.evalDeriv(src, self.mesh, u, t) # wrt u, we don't have have PDeriv wrt m + PDeriv_u = lambda t: rx.evalDeriv(src, self.mesh, f, t) # wrt u, we don't have have PDeriv wrt m Jv[src, rx] = PDeriv_u(mkvc(du_dm)) dA_duI.clean() # Return the vectorized sensitivities return mkvc(Jv) - def Jtvec(self, m, v, u=None): + def Jtvec(self, m, v, f=None): """ Function to calculate the transpose of the data sensitivities (dD/dm)^T times a vector. @@ -85,8 +85,8 @@ class BaseMTProblem(BaseFDEMProblem): :return: Data sensitivities wrt m """ - if u is None: - u = self.fields(m) + if f is None: + f = self.fields(m) self.curModel = m @@ -103,15 +103,15 @@ class BaseMTProblem(BaseFDEMProblem): for src in self.survey.getSrcByFreq(freq): ftype = self._fieldType + 'Solution' - u_src = u[src, :] + f_src = f[src, :] for rx in src.rxList: # Get the adjoint evalDeriv # PTv needs to be nE, - PTv = rx.evalDeriv(src, self.mesh, u, mkvc(v[src, rx],2), adjoint=True) # wrt u, need possibility wrt m + PTv = rx.evalDeriv(src, self.mesh, f, mkvc(v[src, rx],2), adjoint=True) # wrt u, need possibility wrt m # Get the dA_duIT = ATinv * PTv - dA_dmT = self.getADeriv_m(freq, u_src, mkvc(dA_duIT), adjoint=True) + dA_dmT = self.getADeriv_m(freq, f_src, mkvc(dA_duIT), adjoint=True) dRHS_dmT = self.getRHSDeriv_m(freq, mkvc(dA_duIT), adjoint=True) # Make du_dmT if dRHS_dmT is None: @@ -129,4 +129,4 @@ class BaseMTProblem(BaseFDEMProblem): raise Exception('Must be real or imag') # Clean the factorization, clear memory. ATinv.clean() - return Jtv \ No newline at end of file + return Jtv diff --git a/SimPEG/MT/SurveyMT.py b/SimPEG/MT/SurveyMT.py index 4e4a8688..0ec91a0e 100644 --- a/SimPEG/MT/SurveyMT.py +++ b/SimPEG/MT/SurveyMT.py @@ -427,15 +427,15 @@ class Survey(SimPEGsurvey.BaseSurvey): assert freq in self._freqDict, "The requested frequency is not in this survey." return self._freqDict[freq] - def eval(self, u): + def eval(self, f): data = Data(self) for src in self.srcList: sys.stdout.flush() for rx in src.rxList: - data[src, rx] = rx.eval(src, self.mesh, u) + data[src, rx] = rx.eval(src, self.mesh, f) return data - def evalDeriv(self, u): + def evalDeriv(self, f): raise Exception('Use Transmitters to project fields deriv.') ################# diff --git a/SimPEG/Problem.py b/SimPEG/Problem.py index 8ed94e97..f8520c5c 100644 --- a/SimPEG/Problem.py +++ b/SimPEG/Problem.py @@ -128,7 +128,7 @@ class BaseProblem(object): :rtype: numpy.array :return: approxJv """ - return self.Jvec(m, v, u) + return self.Jvec(m, v, f) @Utils.timeIt def Jtvec_approx(self, m, v, f=None): @@ -142,7 +142,7 @@ class BaseProblem(object): :rtype: numpy.array :return: JTv """ - return self.Jtvec(m, v, u) + return self.Jtvec(m, v, f) def fields(self, m): """ diff --git a/SimPEG/Survey.py b/SimPEG/Survey.py index 9ddd269e..fbc88276 100644 --- a/SimPEG/Survey.py +++ b/SimPEG/Survey.py @@ -313,20 +313,20 @@ class BaseSurvey(object): @Utils.count - def eval(self, u): - """eval(u) + def eval(self, f): + """eval(f) This function projects the fields onto the data space. .. math:: - d_\\text{pred} = \mathbf{P} u(m) + d_\\text{pred} = \mathbf{P} f(m) """ raise NotImplemented('eval is not yet implemented.') @Utils.count - def evalDeriv(self, u): - """evalDeriv(u) + def evalDeriv(self, f): + """evalDeriv(f) This function s the derivative of projects the fields onto the data space. @@ -379,8 +379,8 @@ class BaseSurvey(object): return self.dobs class LinearSurvey(BaseSurvey): - def eval(self, u): - return u + def eval(self, f): + return f @property def nD(self): From c7883673bfc37323e04edfde71c7a731de34fc0a Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Thu, 31 Mar 2016 09:36:55 -0700 Subject: [PATCH 16/18] added the figshare doi link for the example --- SimPEG/Examples/EM_Schenkel_Morrison_Casing.py | 5 +++++ docs/examples/EM_Schenkel_Morrison_Casing.rst | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py index e9d37cfe..0a719ea7 100644 --- a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py +++ b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py @@ -43,6 +43,11 @@ def run(plotIt=True): .. _pymatsolver: https://github.com/rowanc1/pymatsolver + This example is on figshare: https://dx.doi.org/10.6084/m9.figshare.3126961.v1 + + If you would use this example for a code comparison, or build upon it, a + citation would be much appreciated! + """ if plotIt: diff --git a/docs/examples/EM_Schenkel_Morrison_Casing.rst b/docs/examples/EM_Schenkel_Morrison_Casing.rst index 730b8507..77bf1fa2 100644 --- a/docs/examples/EM_Schenkel_Morrison_Casing.rst +++ b/docs/examples/EM_Schenkel_Morrison_Casing.rst @@ -17,9 +17,8 @@ ent inside a steel-cased. The model is based on the Schenkel and ison Casing Model, and the results are used in a 2016 SEG abstract by et al. -chenkel, C.J., and H.F. Morrison, 1990`_, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. +henkel, C.J., and H.F. Morrison, 1990, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. -Schenkel, C.J., and H.F. Morrison, 1990: http://onlinelibrary.wiley.com/store/10.1111/j.1365-2478.1990.tb01868.x/asset/j.1365-2478.1990.tb01868.x.pdf?v=1&t=imdt3o85&s=38248af166c2887ed587d94c8ccafad30b480529 model consists of: r: Conductivity 1e-8 S/m, above z = 0 @@ -42,6 +41,11 @@ eve the CPU time of ~30s is Mumps, which was installed using pymatsolver_ pymatsolver: https://github.com/rowanc1/pymatsolver + example is on figshare: https://dx.doi.org/10.6084/m9.figshare.3126961.v1 + +ou would use this example for a code comparison, or build upon it, a +tion would be much appreciated! + .. plot:: From b531c162a229644f6daaa673ab69cd1e74df0da0 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Thu, 31 Mar 2016 23:50:35 -0700 Subject: [PATCH 17/18] tab so we don't cut off the first characters in the docstring --- .../Examples/EM_Schenkel_Morrison_Casing.py | 52 +++++++++---------- docs/examples/EM_Schenkel_Morrison_Casing.rst | 52 +++++++++---------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py index 0a719ea7..76af4a3d 100644 --- a/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py +++ b/SimPEG/Examples/EM_Schenkel_Morrison_Casing.py @@ -11,42 +11,42 @@ except Exception: def run(plotIt=True): """ - EM: Schenkel and Morrison Casing Model - ====================================== + EM: Schenkel and Morrison Casing Model + ====================================== - Here we create and run a FDEM forward simulation to calculate the vertical - current inside a steel-cased. The model is based on the Schenkel and - Morrison Casing Model, and the results are used in a 2016 SEG abstract by - Yang et al. + Here we create and run a FDEM forward simulation to calculate the vertical + current inside a steel-cased. The model is based on the Schenkel and + Morrison Casing Model, and the results are used in a 2016 SEG abstract by + Yang et al. - - Schenkel, C.J., and H.F. Morrison, 1990, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. + - Schenkel, C.J., and H.F. Morrison, 1990, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. - The model consists of: - - Air: Conductivity 1e-8 S/m, above z = 0 - - Background: conductivity 1e-2 S/m, below z = 0 - - Casing: conductivity 1e6 S/m - - 300m long - - radius of 0.1m - - thickness of 6e-3m + The model consists of: + - Air: Conductivity 1e-8 S/m, above z = 0 + - Background: conductivity 1e-2 S/m, below z = 0 + - Casing: conductivity 1e6 S/m + - 300m long + - radius of 0.1m + - thickness of 6e-3m - Inside the casing, we take the same conductivity as the background. + Inside the casing, we take the same conductivity as the background. - We are using an EM code to simulate DC, so we use frequency low enough - that the skin depth inside the casing is longer than the casing length (f - = 1e-6 Hz). The plot produced is of the current inside the casing. + We are using an EM code to simulate DC, so we use frequency low enough + that the skin depth inside the casing is longer than the casing length (f + = 1e-6 Hz). The plot produced is of the current inside the casing. - These results are shown in the SEG abstract by Yang et al., 2016: 3D DC - resistivity modeling of steel casing for reservoir monitoring using - equivalent resistor network. The solver used to produce these results and - achieve the CPU time of ~30s is Mumps, which was installed using pymatsolver_ + These results are shown in the SEG abstract by Yang et al., 2016: 3D DC + resistivity modeling of steel casing for reservoir monitoring using + equivalent resistor network. The solver used to produce these results and + achieve the CPU time of ~30s is Mumps, which was installed using pymatsolver_ - .. _pymatsolver: https://github.com/rowanc1/pymatsolver + .. _pymatsolver: https://github.com/rowanc1/pymatsolver - This example is on figshare: https://dx.doi.org/10.6084/m9.figshare.3126961.v1 + This example is on figshare: https://dx.doi.org/10.6084/m9.figshare.3126961.v1 - If you would use this example for a code comparison, or build upon it, a - citation would be much appreciated! + If you would use this example for a code comparison, or build upon it, a + citation would be much appreciated! """ diff --git a/docs/examples/EM_Schenkel_Morrison_Casing.rst b/docs/examples/EM_Schenkel_Morrison_Casing.rst index 77bf1fa2..55f00168 100644 --- a/docs/examples/EM_Schenkel_Morrison_Casing.rst +++ b/docs/examples/EM_Schenkel_Morrison_Casing.rst @@ -9,42 +9,42 @@ .. --------------------------------- .. -Schenkel and Morrison Casing Model -================================== +EM: Schenkel and Morrison Casing Model +====================================== - we create and run a FDEM forward simulation to calculate the vertical -ent inside a steel-cased. The model is based on the Schenkel and -ison Casing Model, and the results are used in a 2016 SEG abstract by - et al. +Here we create and run a FDEM forward simulation to calculate the vertical +current inside a steel-cased. The model is based on the Schenkel and +Morrison Casing Model, and the results are used in a 2016 SEG abstract by +Yang et al. -henkel, C.J., and H.F. Morrison, 1990, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. +- Schenkel, C.J., and H.F. Morrison, 1990, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686. -model consists of: -r: Conductivity 1e-8 S/m, above z = 0 -ckground: conductivity 1e-2 S/m, below z = 0 -sing: conductivity 1e6 S/m -- 300m long -- radius of 0.1m -- thickness of 6e-3m +The model consists of: +- Air: Conductivity 1e-8 S/m, above z = 0 +- Background: conductivity 1e-2 S/m, below z = 0 +- Casing: conductivity 1e6 S/m + - 300m long + - radius of 0.1m + - thickness of 6e-3m -de the casing, we take the same conductivity as the background. +Inside the casing, we take the same conductivity as the background. -re using an EM code to simulate DC, so we use frequency low enough - the skin depth inside the casing is longer than the casing length (f --6 Hz). The plot produced is of the current inside the casing. +We are using an EM code to simulate DC, so we use frequency low enough +that the skin depth inside the casing is longer than the casing length (f += 1e-6 Hz). The plot produced is of the current inside the casing. -e results are shown in the SEG abstract by Yang et al., 2016: 3D DC -stivity modeling of steel casing for reservoir monitoring using -valent resistor network. The solver used to produce these results and -eve the CPU time of ~30s is Mumps, which was installed using pymatsolver_ +These results are shown in the SEG abstract by Yang et al., 2016: 3D DC +resistivity modeling of steel casing for reservoir monitoring using +equivalent resistor network. The solver used to produce these results and +achieve the CPU time of ~30s is Mumps, which was installed using pymatsolver_ -pymatsolver: https://github.com/rowanc1/pymatsolver +.. _pymatsolver: https://github.com/rowanc1/pymatsolver - example is on figshare: https://dx.doi.org/10.6084/m9.figshare.3126961.v1 +This example is on figshare: https://dx.doi.org/10.6084/m9.figshare.3126961.v1 -ou would use this example for a code comparison, or build upon it, a -tion would be much appreciated! +If you would use this example for a code comparison, or build upon it, a +citation would be much appreciated! From 5d9d74693234102d6ce593577a2e2532ddea1c16 Mon Sep 17 00:00:00 2001 From: Lindsey Heagy Date: Sun, 3 Apr 2016 10:42:28 -0700 Subject: [PATCH 18/18] kwarg for stepping off bounds in projected gradient --- SimPEG/Optimization.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SimPEG/Optimization.py b/SimPEG/Optimization.py index 54f6c4ff..0a241710 100644 --- a/SimPEG/Optimization.py +++ b/SimPEG/Optimization.py @@ -888,6 +888,8 @@ class ProjectedGNCG(BFGS, Minimize, Remember): maxIterCG = 5 tolCG = 1e-1 + stepOffBoundsFact = 0.1 # perturbation of the inactive set off the bounds + lower = -np.inf upper = np.inf @@ -998,7 +1000,8 @@ class ProjectedGNCG(BFGS, Minimize, Remember): dm_i = max( abs( delx ) ) dm_a = max( abs(rhs_a) ) - delx = delx + rhs_a * dm_i / dm_a /10. + # perturb inactive set off of bounds so that they are included in the step + delx = delx + self.stepOffBoundsFact * (rhs_a * dm_i / dm_a) # Only keep gradients going in the right direction on the active set indx = ((self.xc<=self.lower) & (delx < 0)) | ((self.xc>=self.upper) & (delx > 0))