From b33ec1828cb9fe17625e5bf3807568602ccb48f5 Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Sat, 17 May 2014 00:14:22 -0700 Subject: [PATCH] Rearrange Framework --- SimPEG/DataMisfit.py | 140 +++++++++++++++++++++++ SimPEG/Directives.py | 22 ++-- SimPEG/Examples/Linear.py | 6 +- SimPEG/InvProblem.py | 90 +++++++++++++++ SimPEG/Inversion.py | 26 ++--- SimPEG/ObjFunction.py | 220 ------------------------------------ SimPEG/Optimization.py | 30 +---- SimPEG/Survey.py | 39 ------- SimPEG/Utils/SolverUtils.py | 33 ++++++ SimPEG/__init__.py | 3 +- docs/api_DataMisfit.rst | 52 +++++++++ docs/conf.py | 3 + docs/index.rst | 3 +- docs/simpeg-framework.png | Bin 19442 -> 45712 bytes 14 files changed, 351 insertions(+), 316 deletions(-) create mode 100644 SimPEG/DataMisfit.py create mode 100644 SimPEG/InvProblem.py delete mode 100644 SimPEG/ObjFunction.py create mode 100644 docs/api_DataMisfit.rst diff --git a/SimPEG/DataMisfit.py b/SimPEG/DataMisfit.py new file mode 100644 index 00000000..870b5880 --- /dev/null +++ b/SimPEG/DataMisfit.py @@ -0,0 +1,140 @@ +import Utils, Survey, Problem, numpy as np, scipy.sparse as sp, gc + + +def _splitForward(forward): + assert forward.ispaired, 'The problem and survey must be paired.' + if isinstance(forward, Survey.BaseSurvey): + survey = forward + prob = forward.prob + elif isinstance(forward, Problem.BaseProblem): + prob = forward + survey = forward.survey + else: + raise Exception('The forward simulation must either be a problem or a survey.') + + return prob, survey + + +class BaseDataMisfit(object): + """BaseDataMisfit + + .. note:: + + You should inherit from this class to create your own data misfit term. + """ + + __metaclass__ = Utils.SimPEGMetaClass + + debug = False #: Print debugging information + counter = None #: Set this to a SimPEG.Utils.Counter() if you want to count things + + def __init__(self): + pass + + def splitForward(self, forward): + """splitForward(forward) + + Split the forward simulation into a problem and a survey + + :param Problem,Survey forward: forward simulation + :rtype: Problem,Survey + :return: (prob, survey) + + """ + prob, survey = _splitForward(forward) + return prob, survey + + @Utils.timeIt + def dataObj(self, forward, m, u=None): + """dataObj(forward, m, u=None) + + :param Problem,Survey forward: forward simulation + :param numpy.array m: geophysical model + :param numpy.array u: fields + :rtype: float + :return: data misfit + + """ + raise NotImplementedError('This method should be overwritten.') + + @Utils.timeIt + def dataObjDeriv(self, forward, m, u=None): + """dataObjDeriv(forward, m, u=None) + + :param Problem,Survey forward: forward simulation + :param numpy.array m: geophysical model + :param numpy.array u: fields + :rtype: numpy.array + :return: data misfit derivative + + """ + raise NotImplementedError('This method should be overwritten.') + + + @Utils.timeIt + def dataObj2Deriv(self, forward, m, v, u=None): + """dataObj2Deriv(forward, m, v, u=None) + + :param Problem,Survey forward: forward simulation + :param numpy.array m: geophysical model + :param numpy.array v: vector to multiply + :param numpy.array u: fields + :rtype: numpy.array + :return: data misfit derivative + + """ + raise NotImplementedError('This method should be overwritten.') + + +class l2_DataMisfit(object): + """ + + The data misfit with an l_2 norm: + + .. math:: + + \mu_\\text{data} = {1\over 2}\left| \mathbf{W}_d (\mathbf{d}_\\text{pred} - \mathbf{d}_\\text{obs}) \\right|_2^2 + + """ + + def __init__(self, **kwargs): + pass + + def getWd(self, survey): + """getWd(survey) + + Get the data weighting matrix. + + This is based on the norm of the data plus a noise floor. + + :param Survey survey: geophysical survey + :rtype: scipy.sparse.csr_matrix + :return: Wd + + """ + eps = np.linalg.norm(Utils.mkvc(survey.dobs),2)*1e-5 + return Utils.sdiag(1/(abs(survey.dobs)*survey.std+eps)) + + @Utils.timeIt + def dataObj(self, forward, m, u=None): + "dataObj2Deriv(forward, m, u=None)" + prob, survey = _splitForward(forward) + Wd = self.getWd(survey) + R = Wd * survey.residual(m, u=u) + return 0.5*np.vdot(R, R) + + @Utils.timeIt + def dataObjDeriv(self, forward, m, u=None): + "dataObj2Deriv(forward, m, u=None)" + prob, survey = _splitForward(forward) + if u is None: u = prob.fields(m) + Wd = self.getWd(survey) + return prob.Jtvec(m, Wd * (Wd * survey.residual(m, u=u)), u=u) + + @Utils.timeIt + def dataObj2Deriv(self, forward, m, v, u=None): + "dataObj2Deriv(forward, m, v, u=None)" + prob, survey = _splitForward(forward) + if u is None: u = prob.fields(m) + Wd = self.getWd(survey) + return prob.Jtvec_approx(m, Wd * (Wd * prob.Jvec_approx(m, v, u=u)), u=u) diff --git a/SimPEG/Directives.py b/SimPEG/Directives.py index cff073ac..0334e0e4 100644 --- a/SimPEG/Directives.py +++ b/SimPEG/Directives.py @@ -21,15 +21,17 @@ class InversionDirective(object): self._inversion = i @property - def objFunc(self): return self.inversion.objFunc + def invProb(self): return self.inversion.invProb @property def opt(self): return self.inversion.opt @property - def reg(self): return self.inversion.objFunc.reg + def reg(self): return self.invProb.reg @property - def survey(self): return self.inversion.objFunc.survey + def dmisfit(self): return self.invProb.dmisfit @property - def prob(self): return self.inversion.objFunc.prob + def survey(self): return self.invProb.survey + @property + def prob(self): return self.invProb.prob def initialize(self): pass @@ -122,15 +124,15 @@ class BetaEstimate_ByEig(InversionDirective): if self.debug: print 'Calculating the beta0 parameter.' - m = self.objFunc.m_current - u = self.objFunc.u_current or self.prob.fields(m) + m = self.invProb.m_current + u = self.invProb.u_current or self.prob.fields(m) x0 = np.random.rand(*m.shape) - t = x0.dot(self.objFunc.dataObj2Deriv(m,x0,u=u)) + t = x0.dot(self.dmisfit.dataObj2Deriv(self.prob,m,x0,u=u)) b = x0.dot(self.reg.modelObj2Deriv(m, v=x0)) self.beta0 = self.beta0_ratio*(t/b) - self.objFunc.beta = self.beta0 + self.invProb.beta = self.beta0 class BetaSchedule(InversionDirective): @@ -142,7 +144,7 @@ class BetaSchedule(InversionDirective): def endIter(self): if self.opt.iter > 0 and self.opt.iter % self.coolingRate == 0: if self.debug: print 'BetaSchedule is cooling Beta. Iteration: %d' % self.opt.iter - self.objFunc.beta /= self.coolingFactor + self.invProb.beta /= self.coolingFactor # class UpdateReferenceModel(Parameter): @@ -154,5 +156,5 @@ class BetaSchedule(InversionDirective): # if mref is None: # if self.debug: print 'UpdateReferenceModel is using mref0' # mref = self.mref0 -# self.m_prev = self.objFunc.m_current +# self.m_prev = self.invProb.m_current # return mref diff --git a/SimPEG/Examples/Linear.py b/SimPEG/Examples/Linear.py index 3fa02c11..1a36e541 100644 --- a/SimPEG/Examples/Linear.py +++ b/SimPEG/Examples/Linear.py @@ -51,12 +51,12 @@ def run(N, plotIt=True): M = prob.mesh reg = Regularization.Tikhonov(mesh) - objFunc = ObjFunction.BaseObjFunction(survey, reg) + dmis = DataMisfit.l2_DataMisfit() opt = Optimization.InexactGaussNewton(maxIter=20) - inv = Inversion.BaseInversion(objFunc, opt) + invProb = InvProblem.BaseInvProblem(prob, reg, dmis, opt) beta = Directives.BetaSchedule() betaest = Directives.BetaEstimate_ByEig() - inv.ruleList = Directives.DirectiveList(betaest, beta) + inv = Inversion.BaseInversion(invProb, directiveList=[beta, betaest]) m0 = np.zeros_like(survey.mtrue) mrec = inv.run(m0) diff --git a/SimPEG/InvProblem.py b/SimPEG/InvProblem.py new file mode 100644 index 00000000..b982c7c7 --- /dev/null +++ b/SimPEG/InvProblem.py @@ -0,0 +1,90 @@ +import Utils, Survey, Problem, numpy as np, scipy.sparse as sp, gc +from Utils.SolverUtils import * +from DataMisfit import _splitForward + +class BaseInvProblem(object): + """BaseInvProblem(forward, reg, **kwargs)""" + + __metaclass__ = Utils.SimPEGMetaClass + + beta = 1.0 #: Trade-off parameter + + debug = False #: Print debugging information + counter = None #: Set this to a SimPEG.Utils.Counter() if you want to count things + + reg = None #: Regularization + dmisfit = None #: DataMisfit + opt = None #: Optimization program + + u_current = None #: The most current evaluated field + m_current = None #: The most current model + + + def __init__(self, forward, reg, dmisfit, opt, **kwargs): + Utils.setKwargs(self, **kwargs) + self.prob, self.survey = _splitForward(forward) + self.reg = reg + self.dmisfit = dmisfit + self.opt = opt + + @Utils.callHooks('startup') + def startup(self, m0): + """startup(m0) + + Called when inversion is first starting. + """ + if self.debug: print 'Calling InvProblem.startup' + + if self.reg.mref is None: + print 'Regularization has not set mref. SimPEG.InvProblem will set it to m0.' + self.reg.mref = m0 + + self.phi_d = np.nan + self.phi_m = np.nan + + self.m_current = m0 + + print 'Setting bfgsH0 to the inverse of the modelObj2Deriv. Done using direct methods.' + self.opt.bfgsH0 = Solver(self.reg.modelObj2Deriv(self.m_current)) + + @Utils.timeIt + def evalFunction(self, m, return_g=True, return_H=True): + """evalFunction(m, return_g=True, return_H=True) + """ + + self.u_current = None + self.m_current = m + forward = self.prob + gc.collect() + + u = self.prob.fields(m) + self.u_current = u + + phi_d = self.dmisfit.dataObj(forward, m, u=u) + phi_m = self.reg.modelObj(m) + + self.dpred = self.survey.dpred(m, u=u) # 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 + + out = (f,) + if return_g: + phi_dDeriv = self.dmisfit.dataObjDeriv(forward, m, u=u) + phi_mDeriv = self.reg.modelObjDeriv(m) + + g = phi_dDeriv + self.beta * phi_mDeriv + out += (g,) + + if return_H: + def H_fun(v): + phi_d2Deriv = self.dmisfit.dataObj2Deriv(forward, m, v, u=u) + phi_m2Deriv = self.reg.modelObj2Deriv(m, v=v) + + return phi_d2Deriv + self.beta * phi_m2Deriv + + H = sp.linalg.LinearOperator( (m.size, m.size), H_fun, dtype=m.dtype ) + out += (H,) + return out if len(out) > 1 else out[0] diff --git a/SimPEG/Inversion.py b/SimPEG/Inversion.py index 62772476..b380b3df 100644 --- a/SimPEG/Inversion.py +++ b/SimPEG/Inversion.py @@ -5,7 +5,7 @@ import Directives class BaseInversion(object): - """BaseInversion(objFunc, opt, **kwargs) + """BaseInversion(invProb, opt, **kwargs) """ __metaclass__ = Utils.SimPEGMetaClass @@ -30,23 +30,21 @@ class BaseInversion(object): self._directiveList = value self._directiveList.inversion = self - def __init__(self, objFunc, opt, **kwargs): + def __init__(self, invProb, **kwargs): Utils.setKwargs(self, **kwargs) - self.objFunc = objFunc - self.objFunc.parent = self + self.invProb = invProb - self.opt = opt - opt.callback = self._optCallback - self.opt.parent = self + self.opt = invProb.opt + self.opt.callback = self._optCallback self.stoppers = [StoppingCriteria.iteration] - # Check if we have inserted printers into the optimization - if IterationPrinters.phi_d not in self.opt.printers: - self.opt.printers.insert(1,IterationPrinters.beta) - self.opt.printers.insert(2,IterationPrinters.phi_d) - self.opt.printers.insert(3,IterationPrinters.phi_m) + # # Check if we have inserted printers into the optimization + # if IterationPrinters.phi_d not in self.opt.printers: + # self.opt.printers.insert(1,IterationPrinters.beta) + # self.opt.printers.insert(2,IterationPrinters.phi_d) + # self.opt.printers.insert(3,IterationPrinters.phi_m) @Utils.timeIt def run(self, m0): @@ -55,9 +53,9 @@ class BaseInversion(object): Runs the inversion! """ - self.objFunc.startup(m0) + self.invProb.startup(m0) self.directiveList.call('initialize') - self.m = self.opt.minimize(self.objFunc.evalFunction, m0) + self.m = self.opt.minimize(self.invProb.evalFunction, m0) self.directiveList.call('finish') return self.m diff --git a/SimPEG/ObjFunction.py b/SimPEG/ObjFunction.py deleted file mode 100644 index a5332921..00000000 --- a/SimPEG/ObjFunction.py +++ /dev/null @@ -1,220 +0,0 @@ -import Utils, Survey, Problem, numpy as np, scipy.sparse as sp, gc - -class BaseObjFunction(object): - """BaseObjFunction(forward, reg, **kwargs)""" - - __metaclass__ = Utils.SimPEGMetaClass - - beta = 1.0 #: Regularization trade-off parameter - - debug = False #: Print debugging information - counter = None #: Set this to a SimPEG.Utils.Counter() if you want to count things - - surveyPair = Survey.BaseSurvey - problemPair = Problem.BaseProblem - - name = 'Base Objective Function' #: Name of the objective function - - u_current = None #: The most current evaluated field - m_current = None #: The most current model - - @property - def parent(self): - """This is the parent of the objective function.""" - return getattr(self,'_parent',None) - @parent.setter - def parent(self, p): - if getattr(self,'_parent',None) is not None: - print 'Objective function has switched to a new parent!' - self._parent = p - - @property - def inv(self): return self.parent - @property - def objFunc(self): return self - @property - def opt(self): return getattr(self.parent,'opt',None) - - - def __init__(self, forward, reg, **kwargs): - Utils.setKwargs(self, **kwargs) - - assert forward.ispaired, 'The forward problem and survey must be paired.' - if isinstance(forward, self.surveyPair): - self.survey = forward - self.prob = forward.prob - elif isinstance(forward, self.problemPair): - self.prob = forward - self.survey = forward.survey - - - self.reg = reg - self.reg.parent = self - - - @Utils.callHooks('startup') - def startup(self, m0): - """startup(m0) - - Called when inversion is first starting. - """ - if self.debug: print 'Calling ObjFunction.startup' - - if self.reg.mref is None: - print 'Regularization has not set mref. SimPEG.ObjFunction will set it to m0.' - self.reg.mref = m0 - - self.phi_d = np.nan - self.phi_m = np.nan - - self.m_current = m0 - - @Utils.timeIt - def evalFunction(self, m, return_g=True, return_H=True): - """evalFunction(m, return_g=True, return_H=True) - """ - - self.u_current = None - self.m_current = m - gc.collect() - - u = self.prob.fields(m) - self.u_current = u - - phi_d = self.dataObj(m, u=u) - phi_m = self.reg.modelObj(m) - - self.dpred = self.survey.dpred(m, u=u) # 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 - - out = (f,) - if return_g: - phi_dDeriv = self.dataObjDeriv(m, u=u) - phi_mDeriv = self.reg.modelObjDeriv(m) - - g = phi_dDeriv + self.beta * phi_mDeriv - out += (g,) - - if return_H: - def H_fun(v): - phi_d2Deriv = self.dataObj2Deriv(m, v, u=u) - phi_m2Deriv = self.reg.modelObj2Deriv(m, v=v) - - return phi_d2Deriv + self.beta * phi_m2Deriv - - operator = sp.linalg.LinearOperator( (m.size, m.size), H_fun, dtype=m.dtype ) - out += (operator,) - return out if len(out) > 1 else out[0] - - @Utils.timeIt - def dataObj(self, m, u=None): - """dataObj(m, u=None) - - :param numpy.array m: geophysical model - :param numpy.array u: fields - :rtype: float - :return: data misfit - - The data misfit using an l_2 norm is: - - .. math:: - - \mu_\\text{data} = {1\over 2}\left| \mathbf{W} \circ (\mathbf{d}_\\text{pred} - \mathbf{d}_\\text{obs}) \\right|_2^2 - - Where P is a projection matrix that brings the field on the full domain to the data measurement locations; - u is the field of interest; d_obs is the observed data; and W is the weighting matrix. - """ - # TODO: ensure that this is a data is vector and Wd is a matrix. - R = self.survey.residualWeighted(m, u=u) - return 0.5*np.vdot(R, R) - - @Utils.timeIt - def dataObjDeriv(self, m, u=None): - """dataObjDeriv(m, u=None) - - :param numpy.array m: geophysical model - :param numpy.array u: fields - :rtype: numpy.array - :return: data misfit derivative - - The data misfit using an l_2 norm is: - - .. math:: - - \mu_\\text{data} = {1\over 2}\left| \mathbf{W} \circ (\mathbf{d}_\\text{pred} - \mathbf{d}_\\text{obs}) \\right|_2^2 - - If the field, u, is provided, the calculation of the data is fast: - - .. math:: - - \mathbf{d}_\\text{pred} = \mathbf{Pu(m)} - - \mathbf{R} = \mathbf{W} \circ (\mathbf{d}_\\text{pred} - \mathbf{d}_\\text{obs}) - - Where P is a projection matrix that brings the field on the full domain to the data measurement locations; - u is the field of interest; d_obs is the observed data; and W is the weighting matrix. - - The derivative of this, with respect to the model, is: - - .. math:: - - \\frac{\partial \mu_\\text{data}}{\partial \mathbf{m}} = \mathbf{J}^\\top \mathbf{W \circ R} - - """ - if u is None: u = self.prob.fields(m) - - R = self.survey.residualWeighted(m, u=u) - - dmisfit = self.prob.Jtvec(m, self.survey.Wd * R, u=u) - - return dmisfit - - @Utils.timeIt - def dataObj2Deriv(self, m, v, u=None): - """dataObj2Deriv(m, v, u=None) - - :param numpy.array m: geophysical model - :param numpy.array v: vector to multiply - :param numpy.array u: fields - :rtype: numpy.array - :return: data misfit derivative - - The data misfit using an l_2 norm is: - - .. math:: - - \mu_\\text{data} = {1\over 2}\left| \mathbf{W} \circ (\mathbf{d}_\\text{pred} - \mathbf{d}_\\text{obs}) \\right|_2^2 - - If the field, u, is provided, the calculation of the data is fast: - - .. math:: - - \mathbf{d}_\\text{pred} = \mathbf{Pu(m)} - - \mathbf{R} = \mathbf{W} \circ (\mathbf{d}_\\text{pred} - \mathbf{d}_\\text{obs}) - - Where P is a projection matrix that brings the field on the full domain to the data measurement locations; - u is the field of interest; d_obs is the observed data; and W is the weighting matrix. - - The derivative of this, with respect to the model, is: - - .. math:: - - \\frac{\partial \mu_\\text{data}}{\partial \mathbf{m}} = \mathbf{J}^\\top \mathbf{W \circ R} - - \\frac{\partial^2 \mu_\\text{data}}{\partial^2 \mathbf{m}} = \mathbf{J}^\\top \mathbf{W \circ W J} - - """ - if u is None: u = self.prob.fields(m) - - R = self.survey.residualWeighted(m, u=u) - - # TODO: abstract to different norms a little cleaner. - # \/ it goes here. in l2 it is the identity. - dmisfit = self.prob.Jtvec_approx(m, self.survey.Wd * self.survey.Wd * self.prob.Jvec_approx(m, v, u=u), u=u) - - return dmisfit diff --git a/SimPEG/Optimization.py b/SimPEG/Optimization.py index c8314af5..e63a5fe2 100644 --- a/SimPEG/Optimization.py +++ b/SimPEG/Optimization.py @@ -1,5 +1,5 @@ import Utils, numpy as np, scipy.sparse as sp -from Utils.SolverUtils import Solver, SolverCG +from Utils.SolverUtils import * norm = np.linalg.norm @@ -663,13 +663,7 @@ class BFGS(Minimize, Remember): Must be a SimPEG.Solver """ if getattr(self,'_bfgsH0',None) is None: - # Check if it has been set by the user and the default is not being used. - if self.parent is None: - self._bfgsH0 = Solver(sp.identity(self.xc.size).tocsc(), flag='D') - else: - print 'Setting bfgsH0 to the inverse of the modelObj2Deriv. Done using direct methods.' - objFunc = self.parent.objFunc - self._bfgsH0 = Solver(objFunc.reg.modelObj2Deriv(objFunc.m_current)) + self._bfgsH0 = SolverDiag(sp.identity(self.xc.size)) return self._bfgsH0 @bfgsH0.setter @@ -878,23 +872,3 @@ class NewtonRoot(object): break return x - - - -if __name__ == '__main__': - from SimPEG.Tests import Rosenbrock, checkDerivative - import matplotlib.pyplot as plt - x0 = np.array([2.6, 3.7]) - checkDerivative(Rosenbrock, x0, plotIt=False) - - xOpt = GaussNewton(maxIter=20,tolF=1e-10,tolX=1e-10,tolG=1e-10).minimize(Rosenbrock,x0) - print "xOpt=[%f, %f]" % (xOpt[0], xOpt[1]) - xOpt = SteepestDescent(maxIter=30, maxIterLS=15,tolF=1e-10,tolX=1e-10,tolG=1e-10).minimize(Rosenbrock, x0) - print "xOpt=[%f, %f]" % (xOpt[0], xOpt[1]) - - - print 'test the newtonRoot finding.' - fun = lambda x, return_g=True: np.sin(x) if not return_g else ( np.sin(x), Utils.sdiag( np.cos(x) ) ) - x = np.array([np.pi-0.3, np.pi+0.1, 0]) - pnt = NewtonRoot(comments=True).root(fun,x) - print pnt diff --git a/SimPEG/Survey.py b/SimPEG/Survey.py index 206c8be3..5d0da5c4 100644 --- a/SimPEG/Survey.py +++ b/SimPEG/Survey.py @@ -597,45 +597,6 @@ class BaseSurvey(object): """ return Utils.mkvc(self.dpred(m, u=u) - self.dobs) - - @property - def Wd(self): - """ - Data weighting matrix. This is a covariance matrix used in:: - - def residualWeighted(m,u=None): - return self.Wd*self.residual(m, u=u) - - By default, this is based on the norm of the data plus a noise floor. - - """ - if getattr(self,'_Wd',None) is None: - print 'SimPEG is making Survey.Wd to be norm of the data plus a floor.' - eps = np.linalg.norm(Utils.mkvc(self.dobs),2)*1e-5 - self._Wd = 1/(abs(self.dobs)*self.std+eps) - return self._Wd - @Wd.setter - def Wd(self, value): - self._Wd = value - - def residualWeighted(self, m, u=None): - """residualWeighted(m, u=None) - - :param numpy.array m: geophysical model - :param numpy.array u: fields - :rtype: numpy.array - :return: weighted data residual - - The weighted data residual: - - .. math:: - - \mu_\\text{data}^{\\text{weighted}} = \mathbf{W}_d(\mathbf{d}_\\text{pred} - \mathbf{d}_\\text{obs}) - - Where \\\\(W_d\\\\) is a covariance matrix that weights the data residual. - """ - return Utils.mkvc(self.Wd*self.residual(m, u=u)) - @property def isSynthetic(self): "Check if the data is synthetic." diff --git a/SimPEG/Utils/SolverUtils.py b/SimPEG/Utils/SolverUtils.py index 50317b63..386a3f98 100644 --- a/SimPEG/Utils/SolverUtils.py +++ b/SimPEG/Utils/SolverUtils.py @@ -114,3 +114,36 @@ def SolverWrapI(fun, checkAccuracy=True, accuracyTol=1e-5): Solver = SolverWrapD(sp.linalg.spsolve, factorize=False) SolverLU = SolverWrapD(sp.linalg.splu, factorize=True) SolverCG = SolverWrapI(sp.linalg.cg) + + +class SolverDiag(object): + """docstring for SolverDiag""" + def __init__(self, A): + self.A = A + self._diagonal = A.diagonal() + + def __mul__(self, rhs): + n = self.A.shape[0] + assert rhs.size % n == 0, 'Incorrect shape of rhs.' + nrhs = rhs.size // n + + if len(rhs.shape) == 1 or rhs.shape[1] == 1: + x = self._solve1(rhs) + else: + x = self._solveM(rhs) + + if nrhs == 1: + return x.flatten() + elif nrhs > 1: + return x.reshape((n,nrhs), order='F') + + def _solve1(self, rhs): + return rhs.flatten()/self._diagonal + + def _solveM(self, rhs): + n = self.A.shape[0] + nrhs = rhs.size // n + return rhs/self._diagonal.repeat(nrhs).reshape((n,nrhs)) + + def clean(self): + pass diff --git a/SimPEG/__init__.py b/SimPEG/__init__.py index 7d894e65..5ba6ea55 100644 --- a/SimPEG/__init__.py +++ b/SimPEG/__init__.py @@ -7,7 +7,8 @@ import Maps import Problem import Survey import Regularization -import ObjFunction +import DataMisfit +import InvProblem import Optimization import Directives import Inversion diff --git a/docs/api_DataMisfit.rst b/docs/api_DataMisfit.rst new file mode 100644 index 00000000..3033acce --- /dev/null +++ b/docs/api_DataMisfit.rst @@ -0,0 +1,52 @@ +.. _api_DataMisfit: + + +Data Misfit +*********** + +The data misfit using an l_2 norm is: + +.. math:: + + \mu_\text{data} = {1\over 2}\left| \mathbf{W}_d (\mathbf{d}_\text{pred} - \mathbf{d}_\text{obs}) \right|_2^2 + +If the field, u, is provided, the calculation of the data is fast: + +.. math:: + + \mathbf{d}_\text{pred} = \mathbf{Pu(m)} + + \mathbf{R} = \mathbf{W}_d (\mathbf{d}_\text{pred} - \mathbf{d}_\text{obs}) + +Where P is a projection matrix that brings the field on the full domain to the data measurement locations; +u is the field of interest; d_obs is the observed data; and \\\(\\mathbf{W}_d\\\) is the weighting matrix. + +The derivative of this, with respect to the model, is: + +.. math:: + + \frac{\partial \mu_\text{data}}{\partial \mathbf{m}} = \mathbf{J}^\top \mathbf{W}_d \mathbf{R} + +The second derivative is: + +.. math:: + + \frac{\partial^2 \mu_\text{data}}{\partial^2 \mathbf{m}} = \mathbf{J}^\top \mathbf{W}_d \mathbf{W}_d \mathbf{J} + + +The API +======= + +.. autoclass:: SimPEG.DataMisfit.BaseDataMisfit + :members: + :undoc-members: + +Common Data Misfits +=================== + +l2 norm +------- + +.. autoclass:: SimPEG.DataMisfit.l2_DataMisfit + :members: + :undoc-members: diff --git a/docs/conf.py b/docs/conf.py index 86aacce4..f2ab0db1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,6 +20,7 @@ import sys, os sys.path.append('../') + # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. @@ -242,3 +243,5 @@ texinfo_documents = [ # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' + +autodoc_member_order = 'bysource' diff --git a/docs/index.rst b/docs/index.rst index 4a45f25f..7b5f91e1 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -47,8 +47,9 @@ Inversion ********* .. toctree:: - :maxdepth: 2 + :maxdepth: 3 + api_DataMisfit api_Inverse api_Parameters diff --git a/docs/simpeg-framework.png b/docs/simpeg-framework.png index 0d020d6320e8cf28b01ff6ba0ca9f388770a93ab..158ea8853f20c3d07c100543d42ad5d7fca86aee 100644 GIT binary patch literal 45712 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 z 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 JmCf~E{{#3cUMK(n literal 19442 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