diff --git a/SimPEG/inverse/BetaSchedule.py b/SimPEG/inverse/BetaSchedule.py index af4d883d..c225c0c0 100644 --- a/SimPEG/inverse/BetaSchedule.py +++ b/SimPEG/inverse/BetaSchedule.py @@ -3,8 +3,8 @@ class Cooling(object): """Simple Beta Schedule""" - beta0 = 1.e6 - beta_coolingFactor = 5. + beta0 = None #: The initial beta value, set to none means that it will be approximated in the first iteration. + beta_coolingFactor = 2. def getBeta(self): if self._beta is None: diff --git a/SimPEG/inverse/Inversion.py b/SimPEG/inverse/Inversion.py index b5e4906f..160678aa 100644 --- a/SimPEG/inverse/Inversion.py +++ b/SimPEG/inverse/Inversion.py @@ -17,6 +17,8 @@ class BaseInversion(object): comment = '' #: Used by some functions to indicate what is going on in the algorithm counter = None #: Set this to a SimPEG.utils.Counter() if you want to count things + beta0 = None #: The initial Beta (regularization parameter) + def __init__(self, prob, reg, opt, **kwargs): setKwargs(self, **kwargs) @@ -77,7 +79,7 @@ class BaseInversion(object): """ self.startup(m0) while True: - self._beta = self.getBeta() + self.doStartIteration() self.m = self.opt.minimize(self.evalFunction, self.m) self.doEndIteration() if self.stoppingCriteria(): break @@ -113,6 +115,26 @@ class BaseInversion(object): self.phi_d_last = np.nan self.phi_m_last = np.nan + def doStartIteration(self): + """ + **doStartIteration** is called at the end of each run iteration. + + If you have things that also need to run at the end of every iteration, you can create a method:: + + def _doStartIteration*(self): + pass + + Where the * can be any string. If present, _doStartIteration* will be called at the start of the default doStartIteration call. + You may also completely overwrite this function. + + :rtype: None + :return: None + """ + callHooks(self,'doStartIteration') + + self._beta = self.getBeta() + + def doEndIteration(self): """ **doEndIteration** is called at the end of each run iteration. @@ -135,15 +157,6 @@ class BaseInversion(object): self.phi_m_last = self.phi_m self._iter += 1 - @property - def beta0(self): - if getattr(self,'_beta0',None) is None: - self._beta0 = self.estimateBeta0() - return self._beta0 - @beta0.setter - def beta0(self, value): - self._beta0 = value - def getBeta(self): return self.beta0 @@ -208,9 +221,14 @@ class BaseInversion(object): """ u = self.prob.field(m) + + if self._iter is 0 and self._beta is None: + self._beta = self.beta0 = self.estimateBeta0(u=u) + phi_d = self.dataObj(m, u) phi_m = self.reg.modelObj(m) + self.dpred = self.prob.dpred(m, u=u) # This is a cheap matrix vector calculation. self.phi_d = phi_d self.phi_m = phi_m diff --git a/SimPEG/inverse/Optimize.py b/SimPEG/inverse/Optimize.py index 5bf3ef4d..7e934e13 100644 --- a/SimPEG/inverse/Optimize.py +++ b/SimPEG/inverse/Optimize.py @@ -142,6 +142,7 @@ class Minimize(object): printInit() while True: + doStartIteration() f, g, H = evalFunction(xc) printIter() if stoppingCriteria(): break @@ -161,11 +162,12 @@ class Minimize(object): self.printInit() while True: + self.doStartIteration() self.f, self.g, self.H = evalFunction(self.xc, return_g=True, return_H=True) self.printIter() if self.stoppingCriteria(): break - p = self.findSearchDirection() - p = self.scaleSearchDirection(p) + self.searchDirection = self.findSearchDirection() + p = self.scaleSearchDirection(self.searchDirection) xt, passLS = self.modifySearchDirection(p) if not passLS: xt, caught = self.modifySearchDirectionBreak(p) @@ -219,6 +221,16 @@ class Minimize(object): self.f_last = np.nan self.x_last = x0 + @count + def doStartIteration(self): + """doStartIteration() + + **doStartIteration** is called at the start of each minimize iteration. + + :rtype: None + :return: None + """ + callHooks(self,'doStartIteration') def printInit(self, inLS=False): """