diff --git a/.gitignore b/.gitignore index abbec73c..5c39733b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.pyc -SimPEG.sublime-project -SimPEG.sublime-workspace +*.so +*.sublime-project +*.sublime-workspace docs/_build/ myNotebooks/* diff --git a/SimPEG/forward/DCProblem.py b/SimPEG/forward/DCProblem.py index 132966a8..9ddb5332 100644 --- a/SimPEG/forward/DCProblem.py +++ b/SimPEG/forward/DCProblem.py @@ -16,7 +16,7 @@ class DCProblem(ModelTransforms.LogModel, Problem): """ def __init__(self, mesh): - super(DCProblem, self).__init__(mesh) + Problem.__init__(self, mesh) self.mesh.setCellGradBC('neumann') def reshapeFields(self, u): diff --git a/SimPEG/forward/LinearProblem.py b/SimPEG/forward/LinearProblem.py index d30a5b4d..ef92957b 100644 --- a/SimPEG/forward/LinearProblem.py +++ b/SimPEG/forward/LinearProblem.py @@ -13,13 +13,13 @@ class LinearProblem(Problem): return self.G.dot(m) def J(self, m, v, u=None): - return G.dot(v) + return self.G.dot(v) def Jt(self, m, v, u=None): - return G.T.dot(v) + return self.G.T.dot(v) -if __name__ == '__main__': - N = 100 + +def example(N): h = np.ones(N)/N M = TensorMesh([h]) @@ -28,8 +28,6 @@ if __name__ == '__main__': p = -0.25 q = 0.25 - - g = lambda k: np.exp(p*jk[k]*M.vectorCCx)*np.cos(2*np.pi*q*jk[k]*M.vectorCCx) G = np.empty((nk, M.nC)) @@ -38,12 +36,6 @@ if __name__ == '__main__': G[i,:] = g(i) - - plt.figure(1) - for i in range(nk): - plt.plot(G[i,:]) - - m_true = np.zeros(M.nC) m_true[M.vectorCCx > 0.3] = 1. m_true[M.vectorCCx > 0.45] = -0.5 @@ -55,29 +47,29 @@ if __name__ == '__main__': d_obs = d_true + noise - # plt.figure(3) - # plt.plot(d_true,'-o') - # plt.plot(d_obs,'r-o') - - - - - prob = LinearProblem(M) prob.G = G prob.dobs = d_obs prob.std = np.ones_like(d_obs)*0.1 + return prob, m_true + + +if __name__ == '__main__': + + prob, m_true = example(100) + M = prob.mesh + reg = Regularization(M) - opt = InexactGaussNewton(maxIter=20) - inv = Inversion(prob,reg,opt,beta0=1e-4) - m0 = np.zeros_like(m_true) mrec = inv.run(m0) + plt.figure(1) + for i in range(prob.G.shape[0]): + plt.plot(prob.G[i,:]) plt.figure(2) diff --git a/SimPEG/forward/Problem.py b/SimPEG/forward/Problem.py index 2e6831f7..cf22baae 100644 --- a/SimPEG/forward/Problem.py +++ b/SimPEG/forward/Problem.py @@ -140,7 +140,7 @@ class Problem(object): This can often be computed given a vector (i.e. J(v)) rather than stored, as J is a large dense matrix. """ - pass + raise NotImplementedError('J is not yet implemented.') def Jt(self, m, v, u=None): """ @@ -152,7 +152,7 @@ class Problem(object): Effect of transpose of J on a vector v. """ - pass + raise NotImplementedError('Jt is not yet implemented.') def J_approx(self, m, v, u=None): diff --git a/SimPEG/inverse/BetaSchedule.py b/SimPEG/inverse/BetaSchedule.py index fe197340..af4d883d 100644 --- a/SimPEG/inverse/BetaSchedule.py +++ b/SimPEG/inverse/BetaSchedule.py @@ -8,5 +8,5 @@ class Cooling(object): def getBeta(self): if self._beta is None: - return beta0 - return self._beta / beta_coolingFactor + return self.beta0 + return self._beta / self.beta_coolingFactor diff --git a/SimPEG/inverse/Inversion.py b/SimPEG/inverse/Inversion.py index 3aa8ce58..e3d500b1 100644 --- a/SimPEG/inverse/Inversion.py +++ b/SimPEG/inverse/Inversion.py @@ -1,35 +1,33 @@ import numpy as np import scipy.sparse as sp -from SimPEG.utils import sdiag, mkvc +import SimPEG +from SimPEG.utils import sdiag, mkvc, setKwargs, checkStoppers, printStoppers +from Optimize import Remember +from BetaSchedule import Cooling -class Inversion(object): - """docstring for Inversion""" +class BaseInversion(object): + """docstring for BaseInversion""" - maxIter = 10 - name = 'SimPEG Inversion' + maxIter = 1 + name = 'BaseInversion' + debug = False + beta0 = 1e4 def __init__(self, prob, reg, opt, **kwargs): + setKwargs(self, **kwargs) self.prob = prob self.reg = reg self.opt = opt self.opt.parent = self - self.setKwargs(**kwargs) - def setKwargs(self, **kwargs): - """Sets key word arguments (kwargs) that are present in the object, throw an error if they don't exist.""" - for attr in kwargs: - if hasattr(self, attr): - setattr(self, attr, kwargs[attr]) - else: - raise Exception('%s attr is not recognized' % attr) + self.stoppers = [SimPEG.inverse.StoppingCriteria.iteration, SimPEG.inverse.StoppingCriteria.phi_d_target_Inversion] - def printInit(self): - print "%s %s %s" % ('='*22, self.name, '='*22) - print " # beta phi_d phi_m f norm(dJ) #LS" - print "%s" % '-'*62 - - def printIter(self): - print "%3d %1.2e %1.2e %1.2e %1.2e %1.2e %3d" % (self.opt._iter, self._beta, self._phi_d_last, self._phi_m_last, self.opt.f, np.linalg.norm(self.opt.g), self.opt._iterLS) + # Check if we have inserted printers into the optimization + if not np.any([p is SimPEG.inverse.IterationPrinters.phi_d for p in self.opt.printers]): + self.opt.printers.insert(1,SimPEG.inverse.IterationPrinters.beta) + self.opt.printers.insert(2,SimPEG.inverse.IterationPrinters.phi_d) + self.opt.printers.insert(3,SimPEG.inverse.IterationPrinters.phi_m) + self.opt.stoppers.append(SimPEG.inverse.StoppingCriteria.phi_d_target_Minimize) @property def Wd(self): @@ -53,34 +51,85 @@ class Inversion(object): if getattr(self, '_phi_d_target', None) is None: return self.prob.dobs.size # return self._phi_d_target + @phi_d_target.setter def phi_d_target(self, value): self._phi_d_target = value def run(self, m0): - m = m0 - self._iter = 0 - self._beta = None + self.startup(m0) while True: self._beta = self.getBeta() - m = self.opt.minimize(self.evalFunction,m) + self.m = self.opt.minimize(self.evalFunction, self.m) + self.doEndIteration() if self.stoppingCriteria(): break - self._iter += 1 - return m - beta0 = 1.e2 - beta_coolingFactor = 5. + self.printDone() + return self.m + + def startup(self, m0): + """ + **startup** is called at the start of any new run call. + + If you have things that also need to run on startup, you can create a method:: + + def _startup*(self, x0): + pass + + Where the * can be any string. If present, _startup* will be called at the start of the default startup call. + You may also completely overwrite this function. + + :param numpy.ndarray x0: initial x + :rtype: None + :return: None + """ + for method in [posible for posible in dir(self) if '_startup' in posible]: + if self.debug: print 'startup is calling self.'+method + getattr(self,method)(m0) + + self.m = m0 + self._iter = 0 + self._beta = None + + def doEndIteration(self): + """ + **doEndIteration** 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 _doEndIteration*(self, xt): + pass + + Where the * can be any string. If present, _doEndIteration* will be called at the start of the default doEndIteration call. + You may also completely overwrite this function. + + :param numpy.ndarray xt: tested new iterate that ensures a descent direction. + :rtype: None + :return: None + """ + for method in [posible for posible in dir(self) if '_doEndIteration' in posible]: + if self.debug: print 'doEndIteration is calling self.'+method + getattr(self,method)() + + # store old values + self.phi_d_last = self.phi_d + self.phi_m_last = self.phi_m + self._iter += 1 def getBeta(self): - if self._beta is None: - return self.beta0 - return self._beta / self.beta_coolingFactor + return self.beta0 def stoppingCriteria(self): - self._STOP = np.zeros(2,dtype=bool) - self._STOP[0] = self._iter >= self.maxIter - self._STOP[1] = self._phi_d_last <= self.phi_d_target - return np.any(self._STOP) + if self.debug: print 'checking stoppingCriteria' + return checkStoppers(self, self.stoppers) + + + def printDone(self): + """ + **printDone** is called at the end of the inversion routine. + + """ + printStoppers(self, self.stoppers) def evalFunction(self, m, return_g=True, return_H=True): @@ -89,8 +138,8 @@ class Inversion(object): phi_d = self.dataObj(m, u) phi_m = self.reg.modelObj(m) - self._phi_d_last = phi_d - self._phi_m_last = phi_m + self.phi_d = phi_d + self.phi_m = phi_m f = phi_d + self._beta * phi_m @@ -111,7 +160,7 @@ class Inversion(object): operator = sp.linalg.LinearOperator( (m.size, m.size), H_fun, dtype=float ) out += (operator,) - return out + return out if len(out) > 1 else out[0] def dataObj(self, m, u=None): @@ -219,3 +268,10 @@ class Inversion(object): return dmisfit +class Inversion(Cooling, Remember, BaseInversion): + + maxIter = 10 + name = "SimPEG Inversion" + + def __init__(self, prob, reg, opt, **kwargs): + BaseInversion.__init__(self, prob, reg, opt, **kwargs) diff --git a/SimPEG/inverse/Optimize.py b/SimPEG/inverse/Optimize.py index 6221246f..37c8b296 100644 --- a/SimPEG/inverse/Optimize.py +++ b/SimPEG/inverse/Optimize.py @@ -1,6 +1,6 @@ import numpy as np import matplotlib.pyplot as plt -from SimPEG.utils import mkvc, sdiag +from SimPEG.utils import mkvc, sdiag, setKwargs, printTitles, printLine, printStoppers, checkStoppers norm = np.linalg.norm import scipy.sparse as sp from SimPEG import Solver @@ -12,6 +12,75 @@ except Exception, e: print 'Warning: you may not have the required pubsub installed, use pypubsub. You will not be able to listen to events.' doPub = False +class StoppingCriteria(object): + """docstring for StoppingCriteria""" + + iteration = { "str": "%d : maxIter = %3d <= iter = %3d", + "left": lambda M: M.maxIter, "right": lambda M: M._iter, + "stopType": "critical"} + + iterationLS = { "str": "%d : maxIterLS = %3d <= iterLS = %3d", + "left": lambda M: M.maxIterLS, "right": lambda M: M._iterLS, + "stopType": "critical"} + + armijoGoldstein = { "str": "%d : ft = %1.4e <= alp*descent = %1.4e", + "left": lambda M: M._LS_ft, "right": lambda M: M.f + M.LSreduction * M._LS_descent, + "stopType": "optimal"} + + tolerance_f = { "str": "%d : |fc-fOld| = %1.4e <= tolF*(1+|f0|) = %1.4e", + "left": lambda M: 1 if M._iter==0 else abs(M.f-M.f_last), "right": lambda M: 0 if M._iter==0 else M.tolF*(1+abs(M.f0)), + "stopType": "optimal"} + + moving_x = { "str": "%d : |xc-x_last| = %1.4e <= tolX*(1+|x0|) = %1.4e", + "left": lambda M: 1 if M._iter==0 else norm(M.xc-M.x_last), "right": lambda M: 0 if M._iter==0 else M.tolX*(1+norm(M.x0)), + "stopType": "optimal"} + + tolerance_g = { "str": "%d : |proj(x-g)-x| = %1.4e <= tolG = %1.4e", + "left": lambda M: norm(M.projection(M.xc - M.g) - M.xc), "right": lambda M: M.tolG, + "stopType": "optimal"} + + norm_g = { "str": "%d : |proj(x-g)-x| = %1.4e <= 1e3*eps = %1.4e", + "left": lambda M: norm(M.projection(M.xc - M.g) - M.xc), "right": lambda M: 1e3*M.eps, + "stopType": "critical"} + + bindingSet = { "str": "%d : probSize = %3d <= bindingSet = %3d", + "left": lambda M: M.xc.size, "right": lambda M: np.sum(M.bindingSet(M.xc)), + "stopType": "critical"} + + bindingSet_LS = { "str": "%d : probSize = %3d <= bindingSet = %3d", + "left": lambda M: M._LS_xt.size, "right": lambda M: np.sum(M.bindingSet(M._LS_xt)), + "stopType": "critical"} + + phi_d_target_Minimize = { "str": "%d : phi_d = %1.4e <= phi_d_target = %1.4e ", + "left": lambda M: M.parent.phi_d, "right": lambda M: M.parent.phi_d_target, + "stopType": "critical"} + + phi_d_target_Inversion = { "str": "%d : phi_d = %1.4e <= phi_d_target = %1.4e ", + "left": lambda I: I.phi_d, "right": lambda I: I.phi_d_target, + "stopType": "critical"} + + +class IterationPrinters(object): + """docstring for IterationPrinters""" + + iteration = {"title": "#", "value": lambda M: M._iter, "width": 5, "format": "%3d"} + f = {"title": "f", "value": lambda M: M.f, "width": 10, "format": "%1.2e"} + norm_g = {"title": "|proj(x-g)-x|", "value": lambda M: norm(M.projection(M.xc - M.g) - M.xc), "width": 15, "format": "%1.2e"} + totalLS = {"title": "LS", "value": lambda M: M._iterLS, "width": 5, "format": "%d"} + + iterationLS = {"title": "#", "value": lambda M: (M._iter, M._iterLS), "width": 5, "format": "%3d.%d"} + LS_ft = {"title": "ft", "value": lambda M: M._LS_ft, "width": 10, "format": "%1.2e"} + LS_t = {"title": "t", "value": lambda M: M._LS_t, "width": 10, "format": "%0.5f"} + LS_armijoGoldstein = {"title": "f + alp*g.T*p", "value": lambda M: M.f + M.LSreduction*M._LS_descent, "width": 16, "format": "%1.2e"} + + itType = {"title": "itType", "value": lambda M: M._itType, "width": 8, "format": "%s"} + aSet = {"title": "aSet", "value": lambda M: np.sum(M.activeSet(M.xc)), "width": 8, "format": "%d"} + bSet = {"title": "bSet", "value": lambda M: np.sum(M.bindingSet(M.xc)), "width": 8, "format": "%d"} + comment = {"title": "Comment", "value": lambda M: M.projComment, "width": 7, "format": "%s"} + + beta = {"title": "beta", "value": lambda M: M.parent._beta, "width": 10, "format": "%1.2e"} + phi_d = {"title": "phi_d", "value": lambda M: M.parent.phi_d, "width": 10, "format": "%1.2e"} + phi_m = {"title": "phi_m", "value": lambda M: M.parent.phi_m, "width": 10, "format": "%1.2e"} class Minimize(object): @@ -22,7 +91,7 @@ class Minimize(object): """ - name = "GeneralOptimizationAlgorithm" + name = "General Optimization Algorithm" maxIter = 20 maxIterLS = 10 @@ -34,17 +103,18 @@ class Minimize(object): tolG = 1e-1 eps = 1e-5 + debug = False + debugLS = False + def __init__(self, **kwargs): self._id = int(np.random.rand()*1e6) # create a unique identifier to this program to be used in pubsub - self.setKwargs(**kwargs) + self.stoppers = [StoppingCriteria.tolerance_f, StoppingCriteria.moving_x, StoppingCriteria.tolerance_g, StoppingCriteria.norm_g, StoppingCriteria.iteration] + self.stoppersLS = [StoppingCriteria.armijoGoldstein, StoppingCriteria.iterationLS] - def setKwargs(self, **kwargs): - """Sets key word arguments (kwargs) that are present in the object, throw an error if they don't exist.""" - for attr in kwargs: - if hasattr(self, attr): - setattr(self, attr, kwargs[attr]) - else: - raise Exception('%s attr is not recognized' % attr) + self.printers = [IterationPrinters.iteration, IterationPrinters.f, IterationPrinters.norm_g, IterationPrinters.totalLS] + self.printersLS = [IterationPrinters.iterationLS, IterationPrinters.LS_ft, IterationPrinters.LS_t, IterationPrinters.LS_armijoGoldstein] + + setKwargs(self, **kwargs) def minimize(self, evalFunction, x0): """ @@ -59,6 +129,14 @@ class Minimize(object): (f[, g][, H]) = evalFunction(x, return_g=False, return_H=False ) + def evalFunction(x, return_g=False, return_H=False): + out = (f,) + if return_g: + out += (g,) + if return_H: + out += (H,) + return out if len(out) > 1 else out[0] + Events are fired with the following inputs via pypubsub:: @@ -146,19 +224,33 @@ class Minimize(object): xc = x0 _iter = _iterLS = 0 + If you have things that also need to run on startup, you can create a method:: + + def _startup*(self, x0): + pass + + Where the * can be any string. If present, _startup* will be called at the start of the default startup call. + You may also completely overwrite this function. + :param numpy.ndarray x0: initial x :rtype: None :return: None """ + for method in [posible for posible in dir(self) if '_startup' in posible]: + if self.debug: print 'startup is calling self.'+method + getattr(self,method)(x0) + self._iter = 0 self._iterLS = 0 - self._STOP = np.zeros((5,1),dtype=bool) + x0 = self.projection(x0) # ensure that we start of feasible. self.x0 = x0 self.xc = x0 - self.xOld = x0 + self.f_last = np.nan + self.x_last = x0 - def printInit(self): + + def printInit(self, inLS=False): """ **printInit** is called at the beginning of the optimization routine. @@ -166,15 +258,12 @@ class Minimize(object): parent.printInit function and call that. """ - if doPub: pub.sendMessage('Minimize.printInit', minimize=self) - if self.parent is not None and hasattr(self.parent, 'printInit'): - self.parent.printInit() - return - print "%s %s %s" % ('='*22, self.name, '='*22) - print "iter\tJc\t\tnorm(dJ)\tLS" - print "%s" % '-'*57 + if doPub and not inLS: pub.sendMessage('Minimize.printInit', minimize=self) + pad = ' '*10 if inLS else '' + name = self.name if not inLS else self.nameLS + printTitles(self, self.printers if not inLS else self.printersLS, name, pad) - def printIter(self): + def printIter(self, inLS=False): """ **printIter** is called directly after function evaluations. @@ -182,13 +271,11 @@ class Minimize(object): parent.printIter function and call that. """ - if doPub: pub.sendMessage('Minimize.printIter', minimize=self) - if self.parent is not None and hasattr(self.parent, 'printIter'): - self.parent.printIter() - return - print "%3d\t%1.2e\t%1.2e\t%d" % (self._iter, self.f, norm(self.g), self._iterLS) + if doPub and not inLS: pub.sendMessage('Minimize.printIter', minimize=self) + pad = ' '*10 if inLS else '' + printLine(self, self.printers if not inLS else self.printersLS, pad=pad) - def printDone(self): + def printDone(self, inLS=False): """ **printDone** is called at the end of the optimization routine. @@ -196,31 +283,19 @@ class Minimize(object): parent.printDone function and call that. """ - if doPub: pub.sendMessage('Minimize.printDone', minimize=self) - if self.parent is not None and hasattr(self.parent, 'printDone'): - self.parent.printDone() - return - print "%s STOP! %s" % ('-'*25,'-'*25) - # TODO: put controls on gradient value, min model update, and function value - if self._iter > 0: - print "%d : |fc-fOld| = %1.4e <= tolF*(1+|fStop|) = %1.4e" % (self._STOP[0], abs(self.f-self.fOld), self.tolF*(1+abs(self.fStop))) - print "%d : |xc-xOld| = %1.4e <= tolX*(1+|x0|) = %1.4e" % (self._STOP[1], norm(self.xc-self.xOld), self.tolX*(1+norm(self.x0))) - print "%d : |g| = %1.4e <= tolG*(1+|fStop|) = %1.4e" % (self._STOP[2], norm(self.g), self.tolG*(1+abs(self.fStop))) - print "%d : |g| = %1.4e <= 1e3*eps = %1.4e" % (self._STOP[3], norm(self.g), 1e3*self.eps) - print "%d : iter = %3d\t <= maxIter\t = %3d" % (self._STOP[4], self._iter, self.maxIter) - print "%s DONE! %s\n" % ('='*25,'='*25) + if doPub and not inLS: pub.sendMessage('Minimize.printDone', minimize=self) + pad = ' '*10 if inLS else '' + stop, done = (' STOP! ', ' DONE! ') if not inLS else ('----------------', ' End Linesearch ') + stoppers = self.stoppers if not inLS else self.stoppersLS + printStoppers(self, stoppers, pad='', stop=stop, done=done) - def stoppingCriteria(self): + + def stoppingCriteria(self, inLS=False): if self._iter == 0: - self.fStop = self.f # Save this for stopping criteria + self.f0 = self.f + self.g0 = self.g + return checkStoppers(self, self.stoppers if not inLS else self.stoppersLS) - # check stopping rules - self._STOP[0] = self._iter > 0 and (abs(self.f-self.fOld) <= self.tolF*(1+abs(self.fStop))) - self._STOP[1] = self._iter > 0 and (norm(self.xc-self.xOld) <= self.tolX*(1+norm(self.x0))) - self._STOP[2] = norm(self.g) <= self.tolG*(1+abs(self.fStop)) - self._STOP[3] = norm(self.g) <= 1e3*self.eps - self._STOP[4] = self._iter >= self.maxIter - return all(self._STOP[0:3]) | any(self._STOP[3:]) def projection(self, p): """ @@ -278,6 +353,8 @@ class Minimize(object): p = self.maxStep*p/np.abs(p.max()) return p + nameLS = "Armijo linesearch" + def modifySearchDirection(self, p): """ **modifySearchDirection** changes the search direction based on some sort of linesearch or trust-region criteria. @@ -296,20 +373,23 @@ class Minimize(object): :rtype: numpy.ndarray,bool :return: (xt, passLS) """ - # Armijo linesearch - descent = np.inner(self.g, p) - t = 1 - iterLS = 0 - while iterLS < self.maxIterLS: - xt = self.projection(self.xc + t*p) - ft = self.evalFunction(xt, return_g=False, return_H=False) - if ft < self.f + t*self.LSreduction*descent: - break - iterLS += 1 - t = self.LSshorten*t + # Projected Armijo linesearch + self._LS_t = 1 + self._iterLS = 0 + while self._iterLS < self.maxIterLS: + self._LS_xt = self.projection(self.xc + self._LS_t*p) + self._LS_ft = self.evalFunction(self._LS_xt, return_g=False, return_H=False) + self._LS_descent = np.inner(self.g, self._LS_xt - self.xc) # this takes into account multiplying by t, but is important for projection. + if self.stoppingCriteria(inLS=True): break + self._iterLS += 1 + self._LS_t = self.LSshorten*self._LS_t + if self.debugLS: + if self._iterLS == 1: self.printInit(inLS=True) + self.printIter(inLS=True) - self._iterLS = iterLS - return xt, iterLS < self.maxIterLS + if self.debugLS and self._iterLS > 0: self.printDone(inLS=True) + + return self._LS_xt, self._iterLS < self.maxIterLS def modifySearchDirectionBreak(self, p): """ @@ -327,35 +407,227 @@ class Minimize(object): :rtype: numpy.ndarray,bool :return: (xt, breakCaught) """ + self.printDone(inLS=True) print 'The linesearch got broken. Boo.' return p, False def doEndIteration(self, xt): """ - **doEndIteration** is called at the end of each minimize iteration. + **doEndIteration** is called at the end of each minimize iteration. - By default, function values and x locations are shuffled to store 1 past iteration in memory. + By default, function values and x locations are shuffled to store 1 past iteration in memory. - self.xc must be updated in this code. + self.xc must be updated in this code. - :param numpy.ndarray xt: tested new iterate that ensures a descent direction. - :rtype: None - :return: None + + If you have things that also need to run at the end of every iteration, you can create a method:: + + def _doEndIteration*(self, xt): + pass + + Where the * can be any string. If present, _doEndIteration* will be called at the start of the default doEndIteration call. + You may also completely overwrite this function. + + :param numpy.ndarray xt: tested new iterate that ensures a descent direction. + :rtype: None + :return: None """ + for method in [posible for posible in dir(self) if '_doEndIteration' in posible]: + if self.debug: print 'doEndIteration is calling self.'+method + getattr(self,method)(xt) + # store old values - self.fOld = self.f - self.xOld, self.xc = self.xc, xt + self.f_last = self.f + self.x_last, self.xc = self.xc, xt self._iter += 1 + if self.debug: self.printDone() -class GaussNewton(Minimize): - name = 'GaussNewton' + +class Remember(object): + """ + This mixin remembers all the things you tend to forget. + + You can remember parameters directly, naming the str in Minimize, + or pass a tuple with the name and the function that takes Minimize. + + For Example:: + + opt.remember('f',('norm_g', lambda M: np.linalg.norm(M.g))) + + opt.minimize(evalFunction, x0) + + opt.recall('f') + + The param name (str) can also be located in the parent (if no conflicts), + and it will be looked up by default. + """ + + _rememberThese = [] + + def remember(self, *args): + self._rememberThese = args + + def recall(self, param): + assert param in self._rememberList, "You didn't tell me to remember "+param+", you gotta tell me what to remember!" + return self._rememberList[param] + + def _startupRemember(self, x0): + self._rememberList = {} + for param in self._rememberThese: + if type(param) is str: + self._rememberList[param] = [] + elif type(param) is tuple: + self._rememberList[param[0]] = [] + + def _doEndIterationRemember(self, *args): + for param in self._rememberThese: + if type(param) is str: + if self.debug: print 'Remember is remembering: ' + param + val = getattr(self, param, None) + if val is None and getattr(self, 'parent', None) is not None: + # Look to the parent for the param if not found here. + val = getattr(self.parent, param, None) + self._rememberList[param].append( val ) + elif type(param) is tuple: + if self.debug: print 'Remember is remembering: ' + param[0] + self._rememberList[param[0]].append( param[1](self) ) + + + +class ProjectedGradient(Minimize, Remember): + name = 'Projected Gradient' + + maxIterCG = 10 + tolCG = 1e-3 + + lower = -np.inf + upper = np.inf + + def __init__(self,**kwargs): + super(ProjectedGradient, self).__init__(**kwargs) + + self.stoppers.append(StoppingCriteria.bindingSet) + self.stoppersLS.append(StoppingCriteria.bindingSet_LS) + + self.printers.extend([ IterationPrinters.itType, IterationPrinters.aSet, IterationPrinters.bSet, IterationPrinters.comment ]) + + + def _startup(self, x0): + # ensure bound vectors are the same size as the model + if type(self.lower) is not np.ndarray: + self.lower = np.ones_like(x0)*self.lower + if type(self.upper) is not np.ndarray: + self.upper = np.ones_like(x0)*self.upper + + self.explorePG = True + self.exploreCG = False + self.stopDoingPG = False + + self._itType = 'SD' + self.projComment = '' + + self.aSet_prev = self.activeSet(x0) + + def projection(self, x): + """Make sure we are feasible.""" + return np.median(np.c_[self.lower,x,self.upper],axis=1) + + def activeSet(self, x): + """If we are on a bound""" + return np.logical_or(x == self.lower, x == self.upper) + + def inactiveSet(self, x): + """The free variables.""" + return np.logical_not(self.activeSet(x)) + + def bindingSet(self, x): + """ + If we are on a bound and the negative gradient points away from the feasible set. + + Optimality condition. (Satisfies Kuhn-Tucker) MoreToraldo91 + + """ + bind_up = np.logical_and(x == self.lower, self.g >= 0) + bind_low = np.logical_and(x == self.upper, self.g <= 0) + return np.logical_or(bind_up, bind_low) + + def findSearchDirection(self): + self.aSet_prev = self.activeSet(self.xc) + allBoundsAreActive = sum(self.aSet_prev) == self.xc.size + + if self.debug: print 'findSearchDirection: stopDoingPG: ', self.stopDoingPG + if self.debug: print 'findSearchDirection: explorePG: ', self.explorePG + if self.debug: print 'findSearchDirection: exploreCG: ', self.exploreCG + if self.debug: print 'findSearchDirection: aSet', np.sum(self.activeSet(self.xc)) + if self.debug: print 'findSearchDirection: bSet', np.sum(self.bindingSet(self.xc)) + if self.debug: print 'findSearchDirection: allBoundsAreActive: ', allBoundsAreActive + + if self.explorePG or not self.exploreCG or allBoundsAreActive: + if self.debug: print 'findSearchDirection.PG: doingPG' + self._itType = 'SD' + p = -self.g + else: + if self.debug: print 'findSearchDirection.CG: doingCG' + # Reset the max decrease each time you do a CG iteration + self.f_decrease_max = -np.inf + + self._itType = '.CG.' + + iSet = self.inactiveSet(self.xc) # The inactive set (free variables) + bSet = self.bindingSet(self.xc) + shape = (self.xc.size, np.sum(iSet)) + v = np.ones(shape[1]) + i = np.where(iSet)[0] + j = np.arange(shape[1]) + if self.debug: print 'findSearchDirection.CG: Z.shape', shape + Z = sp.csr_matrix((v, (i, j)), shape=shape) + + def reduceHess(v): + # Z is tall and skinny + return Z.T*(self.H*(Z*v)) + operator = sp.linalg.LinearOperator( (shape[1], shape[1]), reduceHess, dtype=float ) + p, info = sp.linalg.cg(operator, -Z.T*self.g, tol=self.tolCG, maxiter=self.maxIterCG) + p = Z*p # bring up to full size + # aSet_after = self.activeSet(self.xc+p) + return p + + def _doEndIteration_ProjectedGradient(self, xt): + aSet = self.activeSet(xt) + bSet = self.bindingSet(xt) + + self.explorePG = not np.all(aSet == self.aSet_prev) # explore proximal gradient + self.exploreCG = np.all(aSet == bSet) # explore conjugate gradient + + f_current_decrease = self.f_last - self.f + self.projComment = '' + if self._iter < 1: + # Note that this is reset on every CG iteration. + self.f_decrease_max = -np.inf + else: + self.f_decrease_max = max(self.f_decrease_max, f_current_decrease) + self.stopDoingPG = f_current_decrease < 0.25 * self.f_decrease_max + if self.stopDoingPG: + self.projComment = 'Stop SD' + self.explorePG = False + self.exploreCG = True + # implement 3.8, MoreToraldo91 + #self.eta_2 * max_decrease where max decrease + # if true go to CG + # don't do too many steps of PG in a row. + + if self.debug: print 'doEndIteration.ProjGrad, f_current_decrease: ', f_current_decrease + if self.debug: print 'doEndIteration.ProjGrad, f_decrease_max: ', self.f_decrease_max + if self.debug: print 'doEndIteration.ProjGrad, stopDoingSD: ', self.stopDoingSD + +class GaussNewton(Minimize, Remember): + name = 'Gauss Newton' def findSearchDirection(self): return Solver(self.H).solve(-self.g) -class InexactGaussNewton(Minimize): - name = 'InexactGaussNewton' +class InexactGaussNewton(Minimize, Remember): + name = 'Inexact Gauss Newton' maxIterCG = 10 tolCG = 1e-5 @@ -366,8 +638,8 @@ class InexactGaussNewton(Minimize): return p -class SteepestDescent(Minimize): - name = 'SteepestDescent' +class SteepestDescent(Minimize, Remember): + name = 'Steepest Descent' def findSearchDirection(self): return -self.g @@ -377,9 +649,9 @@ if __name__ == '__main__': x0 = np.array([2.6, 3.7]) checkDerivative(Rosenbrock, x0, plotIt=False) - def listener1(minimize,p): - print 'hi: ', p - if doPub: pub.subscribe(listener1, 'Minimize.searchDirection') + # def listener1(minimize,p): + # print 'hi: ', p + # if doPub: pub.subscribe(listener1, 'Minimize.searchDirection') xOpt = GaussNewton(maxIter=20,tolF=1e-10,tolX=1e-10,tolG=1e-10).minimize(Rosenbrock,x0) print "xOpt=[%f, %f]" % (xOpt[0], xOpt[1]) diff --git a/SimPEG/tests/TestUtils.py b/SimPEG/tests/TestUtils.py index 140b56fa..1cc2bbae 100644 --- a/SimPEG/tests/TestUtils.py +++ b/SimPEG/tests/TestUtils.py @@ -5,11 +5,17 @@ from SimPEG.utils import mkvc, sdiag from SimPEG import utils from SimPEG.mesh import TensorMesh, LogicallyOrthogonalMesh import numpy as np +import scipy.sparse as sp import unittest import inspect -happiness = ['The test be workin!', 'You get a gold star!', 'Yay passed!', 'Happy little convergence test!', 'That was easy!', 'Testing is important.', 'You are awesome.', 'Go Test Go!', 'Once upon a time, a happy little test passed.', 'And then everyone was happy.'] -sadness = ['No gold star for you.','Try again soon.','Thankfully, persistence is a great substitute for talent.','It might be easier to call this a feature...','Coffee break?', 'Boooooooo :(', 'Testing is important. Do it again.'] +try: + import getpass + name = getpass.getuser()[0].upper() + getpass.getuser()[1:] +except Exception, e: + name = 'You' +happiness = ['The test be workin!', 'You get a gold star!', 'Yay passed!', 'Happy little convergence test!', 'That was easy!', 'Testing is important.', 'You are awesome.', 'Go Test Go!', 'Once upon a time, a happy little test passed.', 'And then everyone was happy.','Not just a pretty face '+name,'You deserve a pat on the back!','Well done '+name+'!', 'Awesome, '+name+', just awesome.'] +sadness = ['No gold star for you.','Try again soon.','Thankfully, persistence is a great substitute for talent.','It might be easier to call this a feature...','Coffee break?', 'Boooooooo :(', 'Testing is important. Do it again.',"Did you put your clever trousers on today?",'Just think about a dancing dinosaur and life will get better!','You had so much promise '+name+', oh well...', name.upper()+' ERROR!','Get on it '+name+'!', 'You break it, you fix it.'] class OrderTest(unittest.TestCase): """ @@ -174,14 +180,14 @@ def Rosenbrock(x, return_g=True, return_H=True): f = 100*(x[1]-x[0]**2)**2+(1-x[0])**2 g = np.array([2*(200*x[0]**3-200*x[0]*x[1]+x[0]-1), 200*(x[1]-x[0]**2)]) - H = np.array([[-400*x[1]+1200*x[0]**2+2, -400*x[0]], [-400*x[0], 200]]) + H = sp.csr_matrix(np.array([[-400*x[1]+1200*x[0]**2+2, -400*x[0]], [-400*x[0], 200]])) out = (f,) if return_g: out += (g,) if return_H: out += (H,) - return out + return out if len(out) > 1 else out[0] def checkDerivative(fctn, x0, num=7, plotIt=True, dx=None): """ @@ -269,6 +275,28 @@ def checkDerivative(fctn, x0, num=7, plotIt=True, dx=None): return passTest + +def getQuadratic(A, b): + """ + Given A and b, this returns a quadratic, Q + + .. math:: + + \mathbf{Q( x ) = 0.5 x A x + b x} + """ + def Quadratic(x, return_g=True, return_H=True): + f = 0.5 * x.dot( A.dot(x)) + b.dot( x ) + out = (f,) + if return_g: + g = A.dot(x) + b + out += (g,) + if return_H: + H = A + out += (H,) + return out if len(out) > 1 else out[0] + return Quadratic + + if __name__ == '__main__': def simplePass(x): diff --git a/SimPEG/tests/__init__.py b/SimPEG/tests/__init__.py index f896cfd0..d082562d 100644 --- a/SimPEG/tests/__init__.py +++ b/SimPEG/tests/__init__.py @@ -1,2 +1,2 @@ import TestUtils -from TestUtils import checkDerivative, Rosenbrock, OrderTest +from TestUtils import checkDerivative, Rosenbrock, OrderTest, getQuadratic diff --git a/SimPEG/tests/test_optimizers.py b/SimPEG/tests/test_optimizers.py new file mode 100644 index 00000000..6fff75d3 --- /dev/null +++ b/SimPEG/tests/test_optimizers.py @@ -0,0 +1,54 @@ +import unittest +from SimPEG import Solver +from SimPEG.mesh import TensorMesh +from SimPEG.utils import sdiag +import numpy as np +import scipy.sparse as sp +from SimPEG import inverse +from SimPEG.tests import getQuadratic, Rosenbrock + +TOL = 1e-2 + +class TestOptimizers(unittest.TestCase): + + def setUp(self): + self.A = sp.identity(2).tocsr() + self.b = np.array([-5,-5]) + + def test_GN_Rosenbrock(self): + GN = inverse.GaussNewton() + xopt = GN.minimize(Rosenbrock,np.array([0,0])) + x_true = np.array([1.,1.]) + print 'xopt: ', xopt + print 'x_true: ', x_true + self.assertTrue(np.linalg.norm(xopt-x_true,2) < TOL, True) + + def test_GN_quadratic(self): + GN = inverse.GaussNewton() + xopt = GN.minimize(getQuadratic(self.A,self.b),np.array([0,0])) + x_true = np.array([5.,5.]) + print 'xopt: ', xopt + print 'x_true: ', x_true + self.assertTrue(np.linalg.norm(xopt-x_true,2) < TOL, True) + + def test_ProjGradient_quadraticBounded(self): + PG = inverse.ProjectedGradient() + PG.lower, PG.upper = -2, 2 + xopt = PG.minimize(getQuadratic(self.A,self.b),np.array([0,0])) + x_true = np.array([2.,2.]) + print 'xopt: ', xopt + print 'x_true: ', x_true + self.assertTrue(np.linalg.norm(xopt-x_true,2) < TOL, True) + + def test_ProjGradient_quadratic1Bound(self): + myB = np.array([-5,1]) + PG = inverse.ProjectedGradient() + PG.lower, PG.upper = -2, 2 + xopt = PG.minimize(getQuadratic(self.A,myB),np.array([0,0])) + x_true = np.array([2.,-1.]) + print 'xopt: ', xopt + print 'x_true: ', x_true + self.assertTrue(np.linalg.norm(xopt-x_true,2) < TOL, True) + +if __name__ == '__main__': + unittest.main() diff --git a/SimPEG/utils/Solver.py b/SimPEG/utils/Solver.py index 3efaf10b..a1194487 100644 --- a/SimPEG/utils/Solver.py +++ b/SimPEG/utils/Solver.py @@ -93,7 +93,7 @@ class Solver(object): :rtype: numpy.ndarray :return: x """ - if backend is None: backend = DEFAULTS['scipy'] + if backend is None: backend = DEFAULTS['direct'] assert np.shape(self.A)[1] == np.shape(b)[0], 'Dimension mismatch' diff --git a/SimPEG/utils/__init__.py b/SimPEG/utils/__init__.py index d3955170..3f82ba6d 100644 --- a/SimPEG/utils/__init__.py +++ b/SimPEG/utils/__init__.py @@ -7,5 +7,55 @@ from matutils import getSubArray, mkvc, ndgrid, ind2sub, sub2ind from sputils import spzeros, kron3, speye, sdiag from lomutils import volTetra, faceInfo, inv2X2BlockDiagonal, inv3X3BlockDiagonal, indexCube, exampleLomGird from interputils import interpmat +from ipythonUtils import easyAnimate as animate import Solver from Solver import Solver + +def setKwargs(obj, **kwargs): + """Sets key word arguments (kwargs) that are present in the object, throw an error if they don't exist.""" + for attr in kwargs: + if hasattr(obj, attr): + setattr(obj, attr, kwargs[attr]) + else: + raise Exception('%s attr is not recognized' % attr) + +def printTitles(obj, printers, name='Print Titles', pad=''): + titles = '' + widths = 0 + for printer in printers: + titles += ('{:^%i}'%printer['width']).format(printer['title']) + '' + widths += printer['width'] + print pad + "{0} {1} {0}".format('='*((widths-1-len(name))/2), name) + print pad + titles + print pad + "%s" % '-'*widths + +def printLine(obj, printers, pad=''): + values = '' + for printer in printers: + values += ('{:^%i}'%printer['width']).format(printer['format'] % printer['value'](obj)) + print pad + values + +def checkStoppers(obj, stoppers): + # check stopping rules + optimal = [] + critical = [] + for stopper in stoppers: + l = stopper['left'](obj) + r = stopper['right'](obj) + if stopper['stopType'] == 'optimal': + optimal.append(l <= r) + if stopper['stopType'] == 'critical': + critical.append(l <= r) + + if obj.debug: print 'checkStoppers.optimal: ', optimal + if obj.debug: print 'checkStoppers.critical: ', critical + + return (len(optimal)>0 and all(optimal)) | (len(critical)>0 and any(critical)) + +def printStoppers(obj, stoppers, pad='', stop='STOP!', done='DONE!'): + print pad + "%s%s%s" % ('-'*25,stop,'-'*25) + for stopper in stoppers: + l = stopper['left'](obj) + r = stopper['right'](obj) + print pad + stopper['str'] % (l<=r,l,r) + print pad + "%s%s%s" % ('-'*25,done,'-'*25) diff --git a/SimPEG/utils/ipythonUtils.py b/SimPEG/utils/ipythonUtils.py new file mode 100644 index 00000000..aa1eefdd --- /dev/null +++ b/SimPEG/utils/ipythonUtils.py @@ -0,0 +1,29 @@ +from tempfile import NamedTemporaryFile +import matplotlib.pyplot as plt +from matplotlib import animation +from IPython.display import HTML + +# http://jakevdp.github.io/blog/2013/05/12/embedding-matplotlib-animations/ +# http://www.renevolution.com/how-to-install-ffmpeg-on-mac-os-x/ + +VIDEO_TAG = """""" + +def anim_to_html(anim): + if not hasattr(anim, '_encoded_video'): + with NamedTemporaryFile(suffix='.mp4') as f: + anim.save(f.name, fps=20, extra_args=['-vcodec', 'libx264', '-pix_fmt', 'yuv420p']) + video = open(f.name, "rb").read() + anim._encoded_video = video.encode("base64") + + return VIDEO_TAG.format(anim._encoded_video) + +def display_animation(anim): + plt.close(anim._fig) + return anim_to_html(anim) + +animation.Animation._repr_html_ = display_animation + +easyAnimate = animation.FuncAnimation diff --git a/docs/api_TestResults.rst b/docs/api_TestResults.rst index 7b276006..8c16f36e 100644 --- a/docs/api_TestResults.rst +++ b/docs/api_TestResults.rst @@ -185,9 +185,9 @@ Test Results -->
-

Start Time: 2013-11-05 16:10:07

-

Duration: 0:00:31.280082

-

Status: Pass 99

+

Start Time: 2013-11-12 11:29:23

+

Duration: 0:00:32.452108

+

Status: Pass 107

SimPEG Test Report was automatically generated.

@@ -377,15 +377,15 @@ Test Results pt3.2: ==================== checkDerivative ==================== iter h |J0-Jt| |J0+h*dJ'*dx-Jt| Order --------------------------------------------------------- - 0 1.00e-01 3.555e+01 3.750e+01 nan - 1 1.00e-02 1.711e-01 3.662e-01 2.010 - 2 1.00e-03 1.586e-02 3.653e-03 2.001 - 3 1.00e-04 1.915e-03 3.652e-05 2.000 - 4 1.00e-05 1.948e-04 3.652e-07 2.000 - 5 1.00e-06 1.951e-05 3.662e-09 1.999 - 6 1.00e-07 1.951e-06 3.158e-11 2.064 + 0 1.00e-01 2.025e+01 2.686e+01 nan + 1 1.00e-02 3.953e-01 2.660e-01 2.004 + 2 1.00e-03 6.347e-02 2.657e-03 2.000 + 3 1.00e-04 6.587e-03 2.657e-05 2.000 + 4 1.00e-05 6.610e-04 2.657e-07 2.000 + 5 1.00e-06 6.613e-05 2.657e-09 2.000 + 6 1.00e-07 6.613e-06 2.700e-11 1.993 ========================= PASS! ========================= - Testing is important. + You deserve a pat on the back! @@ -414,15 +414,15 @@ Test Results pt3.3: ==================== checkDerivative ==================== iter h |J0-Jt| |J0+h*dJ'*dx-Jt| Order --------------------------------------------------------- - 0 1.00e-01 5.409e-02 4.593e-03 nan - 1 1.00e-02 5.429e-03 4.574e-05 2.002 - 2 1.00e-03 5.431e-04 4.570e-07 2.000 - 3 1.00e-04 5.431e-05 4.570e-09 2.000 - 4 1.00e-05 5.431e-06 4.570e-11 2.000 - 5 1.00e-06 5.431e-07 4.553e-13 2.002 - 6 1.00e-07 5.431e-08 4.751e-15 1.982 + 0 1.00e-01 5.087e-02 5.479e-03 nan + 1 1.00e-02 5.240e-03 5.471e-05 2.001 + 2 1.00e-03 5.256e-04 5.468e-07 2.000 + 3 1.00e-04 5.258e-05 5.467e-09 2.000 + 4 1.00e-05 5.258e-06 5.467e-11 2.000 + 5 1.00e-06 5.258e-07 5.467e-13 2.000 + 6 1.00e-07 5.258e-08 5.672e-15 1.984 ========================= PASS! ========================= - That was easy! + Testing is important. @@ -451,15 +451,15 @@ Test Results pt3.4: ==================== checkDerivative ==================== iter h |J0-Jt| |J0+h*dJ'*dx-Jt| Order --------------------------------------------------------- - 0 1.00e-01 8.756e+00 7.946e+00 nan - 1 1.00e-02 1.605e-01 7.946e-02 2.000 - 2 1.00e-03 8.894e-03 7.946e-04 2.000 - 3 1.00e-04 8.179e-04 7.946e-06 2.000 - 4 1.00e-05 8.108e-05 7.946e-08 2.000 - 5 1.00e-06 8.100e-06 7.946e-10 2.000 - 6 1.00e-07 8.100e-07 7.947e-12 2.000 + 0 1.00e-01 6.461e+00 7.059e+00 nan + 1 1.00e-02 1.073e-02 7.059e-02 2.000 + 2 1.00e-03 5.280e-03 7.059e-04 2.000 + 3 1.00e-04 5.915e-04 7.059e-06 2.000 + 4 1.00e-05 5.979e-05 7.059e-08 2.000 + 5 1.00e-06 5.985e-06 7.059e-10 2.000 + 6 1.00e-07 5.986e-07 7.059e-12 2.000 ========================= PASS! ========================= - The test be workin! + That was easy! @@ -498,15 +498,15 @@ Test Results ==================== checkDerivative ==================== iter h |J0-Jt| |J0+h*dJ'*dx-Jt| Order --------------------------------------------------------- - 0 1.00e-01 1.309e-01 4.745e-17 nan - 1 1.00e-02 1.309e-02 4.825e-17 -0.007 - 2 1.00e-03 1.309e-03 5.993e-17 -0.094 - 3 1.00e-04 1.309e-04 6.648e-17 -0.045 - 4 1.00e-05 1.309e-05 6.931e-17 -0.018 - 5 1.00e-06 1.309e-06 6.247e-17 0.045 - 6 1.00e-07 1.309e-07 5.708e-17 0.039 + 0 1.00e-01 3.421e-01 3.925e-17 nan + 1 1.00e-02 3.421e-02 2.357e-17 0.222 + 2 1.00e-03 3.421e-03 4.849e-17 -0.313 + 3 1.00e-04 3.421e-04 5.925e-17 -0.087 + 4 1.00e-05 3.421e-05 6.316e-17 -0.028 + 5 1.00e-06 3.421e-06 4.061e-17 0.192 + 6 1.00e-07 3.421e-07 6.370e-17 -0.196 ========================= PASS! ========================= - You are awesome. + You get a gold star! @@ -535,15 +535,15 @@ Test Results pt4.2: ==================== checkDerivative ==================== iter h |J0-Jt| |J0+h*dJ'*dx-Jt| Order --------------------------------------------------------- - 0 1.00e-01 3.133e-01 3.168e-02 nan - 1 1.00e-02 3.418e-02 3.168e-04 2.000 - 2 1.00e-03 3.447e-03 3.168e-06 2.000 - 3 1.00e-04 3.449e-04 3.168e-08 2.000 - 4 1.00e-05 3.450e-05 3.168e-10 2.000 - 5 1.00e-06 3.450e-06 3.169e-12 2.000 - 6 1.00e-07 3.450e-07 3.481e-14 1.959 + 0 1.00e-01 2.565e+00 1.802e-01 nan + 1 1.00e-02 2.727e-01 1.802e-03 2.000 + 2 1.00e-03 2.743e-02 1.802e-05 2.000 + 3 1.00e-04 2.745e-03 1.802e-07 2.000 + 4 1.00e-05 2.745e-04 1.802e-09 2.000 + 5 1.00e-06 2.745e-05 1.802e-11 2.000 + 6 1.00e-07 2.745e-06 1.800e-13 2.000 ========================= PASS! ========================= - That was easy! + Yay passed! @@ -583,22 +583,22 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 2.76e-01 | - 16 | 6.10e-02 | 4.5221 | 2.1770 - 32 | 1.44e-02 | 4.2290 | 2.0803 + 8 | 2.58e-01 | + 16 | 6.41e-02 | 4.0278 | 2.0100 + 32 | 1.77e-02 | 3.6279 | 1.8591 --------------------------------------------- - Happy little convergence test! + That was easy! randomTensorMesh: Interpolation 1D: CC _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 2.46e-01 | - 16 | 1.11e-01 | 2.2066 | 0.9651 - 32 | 4.07e-02 | 2.7360 | 3.1871 + 8 | 4.97e-01 | + 16 | 1.59e-01 | 3.1240 | 1.6281 + 32 | 4.04e-02 | 3.9430 | 2.3561 --------------------------------------------- - Testing is important. + Happy little convergence test! @@ -629,22 +629,22 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 2.39e-01 | - 16 | 6.89e-02 | 3.4636 | 1.7923 - 32 | 1.78e-02 | 3.8797 | 1.9559 + 8 | 3.09e-01 | + 16 | 7.89e-02 | 3.9199 | 1.9708 + 32 | 1.83e-02 | 4.3119 | 2.1083 --------------------------------------------- - You get a gold star! + Well done Rowan! randomTensorMesh: Interpolation 1D: N _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 5.97e-01 | - 16 | 1.38e-01 | 4.3354 | 1.7681 - 32 | 3.33e-02 | 4.1339 | 2.1579 + 8 | 4.76e-01 | + 16 | 1.11e-01 | 4.2662 | 1.9952 + 32 | 4.59e-02 | 2.4283 | 1.2771 --------------------------------------------- - Yay passed! + Once upon a time, a happy little test passed. @@ -684,24 +684,24 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.06e-02 | - 16 | 1.78e-02 | 3.9781 | 1.9921 - 32 | 4.72e-03 | 3.7595 | 1.9106 - 64 | 1.18e-03 | 3.9981 | 1.9993 + 8 | 7.60e-02 | + 16 | 1.91e-02 | 3.9815 | 1.9933 + 32 | 4.72e-03 | 4.0446 | 2.0160 + 64 | 1.18e-03 | 4.0053 | 2.0019 --------------------------------------------- - The test be workin! + Happy little convergence test! randomTensorMesh: Interpolation 2D: CC _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 9.16e-02 | - 16 | 3.39e-02 | 2.7044 | 1.6128 - 32 | 9.31e-03 | 3.6391 | 1.9612 - 64 | 4.10e-03 | 2.2687 | 1.5130 + 8 | 1.75e-01 | + 16 | 2.69e-02 | 6.5233 | 2.3005 + 32 | 1.12e-02 | 2.4031 | 1.2481 + 64 | 3.53e-03 | 3.1726 | 1.8392 --------------------------------------------- - Testing is important. + You are awesome. @@ -732,24 +732,24 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.04e-02 | - 16 | 1.88e-02 | 3.7329 | 1.9003 - 32 | 4.77e-03 | 3.9517 | 1.9825 - 64 | 1.19e-03 | 4.0081 | 2.0029 + 8 | 7.01e-02 | + 16 | 1.88e-02 | 3.7205 | 1.8955 + 32 | 4.59e-03 | 4.1006 | 2.0358 + 64 | 1.16e-03 | 3.9440 | 1.9797 --------------------------------------------- - Testing is important. + Well done Rowan! randomTensorMesh: Interpolation 2D: Ex _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 1.96e-01 | - 16 | 4.30e-02 | 4.5625 | 2.7996 - 32 | 2.01e-02 | 2.1406 | 1.0860 - 64 | 3.32e-03 | 6.0522 | 2.4217 + 8 | 1.12e-01 | + 16 | 8.66e-02 | 1.2909 | 0.8416 + 32 | 2.00e-02 | 4.3264 | 1.8545 + 64 | 2.47e-03 | 8.1124 | 2.6759 --------------------------------------------- - You get a gold star! + You deserve a pat on the back! @@ -780,10 +780,10 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.01e-02 | - 16 | 1.88e-02 | 3.7175 | 1.8943 - 32 | 4.59e-03 | 4.1014 | 2.0361 - 64 | 1.19e-03 | 3.8653 | 1.9506 + 8 | 6.84e-02 | + 16 | 1.60e-02 | 4.2800 | 2.0976 + 32 | 4.79e-03 | 3.3359 | 1.7381 + 64 | 1.20e-03 | 3.9828 | 1.9938 --------------------------------------------- The test be workin! @@ -792,12 +792,12 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 1.92e-01 | - 16 | 5.13e-02 | 3.7457 | 2.6593 - 32 | 1.09e-02 | 4.7164 | 2.0227 - 64 | 4.07e-03 | 2.6707 | 1.4891 + 8 | 6.00e-02 | + 16 | 4.16e-02 | 1.4412 | 0.4902 + 32 | 7.60e-03 | 5.4787 | 2.8421 + 64 | 2.60e-03 | 2.9195 | 1.2969 --------------------------------------------- - Go Test Go! + Not just a pretty face Rowan @@ -828,24 +828,24 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.06e-02 | - 16 | 1.78e-02 | 3.9781 | 1.9921 - 32 | 4.72e-03 | 3.7595 | 1.9106 - 64 | 1.18e-03 | 3.9981 | 1.9993 + 8 | 7.60e-02 | + 16 | 1.91e-02 | 3.9815 | 1.9933 + 32 | 4.72e-03 | 4.0446 | 2.0160 + 64 | 1.18e-03 | 4.0053 | 2.0019 --------------------------------------------- - Yay passed! + Happy little convergence test! randomTensorMesh: Interpolation 2D: Fx _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 9.82e-02 | - 16 | 5.58e-02 | 1.7592 | 6.6696 - 32 | 6.57e-03 | 8.4887 | 2.2061 - 64 | 4.28e-03 | 1.5342 | 0.6081 + 8 | 7.56e-02 | + 16 | 3.64e-02 | 2.0777 | 0.8083 + 32 | 1.07e-02 | 3.3892 | 1.8786 + 64 | 3.58e-03 | 3.0004 | 1.6103 --------------------------------------------- - The test be workin! + Go Test Go! @@ -876,10 +876,10 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.57e-02 | - 16 | 1.88e-02 | 4.0222 | 2.0080 - 32 | 4.72e-03 | 3.9905 | 1.9966 - 64 | 1.18e-03 | 4.0110 | 2.0040 + 8 | 7.49e-02 | + 16 | 1.80e-02 | 4.1557 | 2.0551 + 32 | 4.00e-03 | 4.5049 | 2.1715 + 64 | 1.20e-03 | 3.3419 | 1.7407 --------------------------------------------- That was easy! @@ -888,12 +888,12 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 6.72e-02 | - 16 | 3.28e-02 | 2.0482 | 1.6433 - 32 | 1.13e-02 | 2.9135 | 2.1786 - 64 | 3.35e-03 | 3.3628 | 1.6438 + 8 | 9.96e-02 | + 16 | 5.79e-02 | 1.7215 | 0.5101 + 32 | 1.21e-02 | 4.7877 | 2.1054 + 64 | 2.60e-03 | 4.6488 | 2.4950 --------------------------------------------- - Yay passed! + Happy little convergence test! @@ -924,10 +924,10 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.04e-02 | - 16 | 1.88e-02 | 3.7329 | 1.9003 - 32 | 4.77e-03 | 3.9517 | 1.9825 - 64 | 1.19e-03 | 4.0081 | 2.0029 + 8 | 7.01e-02 | + 16 | 1.88e-02 | 3.7205 | 1.8955 + 32 | 4.59e-03 | 4.1006 | 2.0358 + 64 | 1.16e-03 | 3.9440 | 1.9797 --------------------------------------------- Once upon a time, a happy little test passed. @@ -936,12 +936,12 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 1.24e-01 | - 16 | 6.30e-02 | 1.9636 | 1.2918 - 32 | 2.15e-02 | 2.9310 | 1.6864 - 64 | 4.96e-03 | 4.3359 | 1.9158 + 8 | 1.13e-01 | + 16 | 4.02e-02 | 2.8137 | 1.7733 + 32 | 1.12e-02 | 3.5726 | 1.4513 + 64 | 3.25e-03 | 3.4586 | 1.4744 --------------------------------------------- - Happy little convergence test! + You get a gold star! @@ -981,24 +981,24 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.36e-02 | - 16 | 1.74e-02 | 4.2291 | 2.0803 - 32 | 4.16e-03 | 4.1900 | 2.0669 - 64 | 9.48e-04 | 4.3858 | 2.1328 + 8 | 7.59e-02 | + 16 | 1.90e-02 | 3.9963 | 1.9987 + 32 | 4.69e-03 | 4.0474 | 2.0170 + 64 | 1.18e-03 | 3.9935 | 1.9977 --------------------------------------------- - That was easy! + Once upon a time, a happy little test passed. randomTensorMesh: Interpolation CC _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 2.30e-01 | - 16 | 1.70e-02 | 13.5276 | 3.5152 - 32 | 6.70e-03 | 2.5405 | 1.2651 - 64 | 1.88e-03 | 3.5689 | 1.8184 + 8 | 7.88e-02 | + 16 | 2.49e-02 | 3.1639 | 2.5664 + 32 | 1.40e-02 | 1.7739 | 0.8582 + 64 | 2.03e-03 | 6.9317 | 2.8790 --------------------------------------------- - That was easy! + And then everyone was happy. @@ -1029,24 +1029,24 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 6.98e-02 | - 16 | 1.79e-02 | 3.8902 | 1.9598 - 32 | 4.41e-03 | 4.0681 | 2.0244 - 64 | 1.18e-03 | 3.7418 | 1.9037 + 8 | 7.03e-02 | + 16 | 1.88e-02 | 3.7326 | 1.9002 + 32 | 4.77e-03 | 3.9468 | 1.9807 + 64 | 1.12e-03 | 4.2670 | 2.0932 --------------------------------------------- - Happy little convergence test! + You are awesome. randomTensorMesh: Interpolation Ex _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 2.92e-01 | - 16 | 8.20e-02 | 3.5597 | 4.3217 - 32 | 9.49e-03 | 8.6460 | 1.9353 - 64 | 2.89e-03 | 3.2854 | 1.7236 + 8 | 9.15e-02 | + 16 | 7.21e-02 | 1.2700 | 0.5458 + 32 | 1.22e-02 | 5.9140 | 2.6646 + 64 | 2.75e-03 | 4.4260 | 1.8486 --------------------------------------------- - Testing is important. + That was easy! @@ -1077,24 +1077,24 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.04e-02 | - 16 | 1.87e-02 | 3.7726 | 1.9155 - 32 | 4.61e-03 | 4.0477 | 2.0171 - 64 | 1.09e-03 | 4.2392 | 2.0838 + 8 | 7.03e-02 | + 16 | 1.88e-02 | 3.7324 | 1.9001 + 32 | 4.32e-03 | 4.3577 | 2.1236 + 64 | 1.19e-03 | 3.6424 | 1.8649 --------------------------------------------- - You are awesome. + You get a gold star! randomTensorMesh: Interpolation Ey _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 1.30e-01 | - 16 | 4.52e-02 | 2.8770 | 1.4488 - 32 | 1.36e-02 | 3.3196 | 2.2159 - 64 | 2.81e-03 | 4.8481 | 1.8199 + 8 | 1.53e-01 | + 16 | 6.69e-02 | 2.2859 | 1.4178 + 32 | 2.05e-02 | 3.2684 | 2.0771 + 64 | 2.74e-03 | 7.4881 | 2.3296 --------------------------------------------- - You are awesome. + Testing is important. @@ -1125,24 +1125,24 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.04e-02 | - 16 | 1.87e-02 | 3.7711 | 1.9150 - 32 | 4.61e-03 | 4.0489 | 2.0175 - 64 | 1.15e-03 | 4.0151 | 2.0054 + 8 | 7.03e-02 | + 16 | 1.88e-02 | 3.7376 | 1.9021 + 32 | 4.57e-03 | 4.1226 | 2.0435 + 64 | 1.16e-03 | 3.9523 | 1.9827 --------------------------------------------- - Yay passed! + You are awesome. randomTensorMesh: Interpolation Ez _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 3.81e-01 | - 16 | 3.89e-02 | 9.7974 | 2.2747 - 32 | 2.09e-02 | 1.8614 | 2.2906 - 64 | 3.97e-03 | 5.2691 | 1.7820 + 8 | 1.48e-01 | + 16 | 9.32e-02 | 1.5867 | 0.4554 + 32 | 2.27e-02 | 4.1106 | 1.5265 + 64 | 2.68e-03 | 8.4640 | 3.0885 --------------------------------------------- - Once upon a time, a happy little test passed. + Testing is important. @@ -1173,24 +1173,24 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.36e-02 | - 16 | 1.74e-02 | 4.2291 | 2.0803 - 32 | 4.16e-03 | 4.1900 | 2.0669 - 64 | 9.48e-04 | 4.3858 | 2.1328 + 8 | 7.59e-02 | + 16 | 1.90e-02 | 3.9963 | 1.9987 + 32 | 4.69e-03 | 4.0474 | 2.0170 + 64 | 1.18e-03 | 3.9935 | 1.9977 --------------------------------------------- - Once upon a time, a happy little test passed. + You deserve a pat on the back! randomTensorMesh: Interpolation Fx _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 1.59e-01 | - 16 | 7.66e-02 | 2.0691 | 1.2662 - 32 | 1.01e-02 | 7.5592 | 3.0198 - 64 | 1.82e-03 | 5.5842 | 2.5778 + 8 | 8.49e-02 | + 16 | 2.72e-02 | 3.1225 | 1.2154 + 32 | 1.12e-02 | 2.4354 | 1.9171 + 64 | 3.67e-03 | 3.0455 | 1.3837 --------------------------------------------- - That was easy! + You deserve a pat on the back! @@ -1221,24 +1221,24 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.61e-02 | - 16 | 1.92e-02 | 3.9682 | 1.9885 - 32 | 4.77e-03 | 4.0172 | 2.0062 - 64 | 1.16e-03 | 4.1081 | 2.0385 + 8 | 7.60e-02 | + 16 | 1.91e-02 | 3.9765 | 1.9915 + 32 | 4.72e-03 | 4.0514 | 2.0184 + 64 | 1.18e-03 | 4.0055 | 2.0020 --------------------------------------------- - Once upon a time, a happy little test passed. + Happy little convergence test! randomTensorMesh: Interpolation Fy _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 1.45e-01 | - 16 | 5.01e-02 | 2.8858 | 1.2456 - 32 | 8.71e-03 | 5.7525 | 3.4043 - 64 | 1.85e-03 | 4.7102 | 1.9579 + 8 | 7.84e-02 | + 16 | 2.69e-02 | 2.9183 | 1.3569 + 32 | 1.20e-02 | 2.2396 | 1.1828 + 64 | 2.31e-03 | 5.1989 | 2.2465 --------------------------------------------- - The test be workin! + You get a gold star! @@ -1269,24 +1269,24 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.41e-02 | - 16 | 1.78e-02 | 4.1730 | 2.0611 - 32 | 4.55e-03 | 3.9004 | 1.9636 - 64 | 1.11e-03 | 4.0930 | 2.0332 + 8 | 7.61e-02 | + 16 | 1.92e-02 | 3.9650 | 1.9873 + 32 | 4.79e-03 | 4.0044 | 2.0016 + 64 | 1.18e-03 | 4.0544 | 2.0195 --------------------------------------------- - And then everyone was happy. + Testing is important. randomTensorMesh: Interpolation Fz _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 7.63e-02 | - 16 | 4.19e-02 | 1.8225 | 1.1195 - 32 | 9.07e-03 | 4.6176 | 1.4900 - 64 | 2.70e-03 | 3.3657 | 2.0946 + 8 | 2.11e-01 | + 16 | 3.01e-02 | 7.0210 | 2.8286 + 32 | 1.37e-02 | 2.1966 | 1.3516 + 64 | 2.88e-03 | 4.7606 | 1.9822 --------------------------------------------- - Go Test Go! + Not just a pretty face Rowan @@ -1317,24 +1317,24 @@ Test Results _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 6.98e-02 | - 16 | 1.79e-02 | 3.8902 | 1.9598 - 32 | 4.41e-03 | 4.0681 | 2.0244 - 64 | 1.18e-03 | 3.7418 | 1.9037 + 8 | 7.03e-02 | + 16 | 1.88e-02 | 3.7326 | 1.9002 + 32 | 4.77e-03 | 3.9468 | 1.9807 + 64 | 1.12e-03 | 4.2670 | 2.0932 --------------------------------------------- - You are awesome. + Yay passed! randomTensorMesh: Interpolation N _____________________________________________ h | error | e(i-1)/e(i) | order ~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~~~~|~~~~~~~~~~ - 8 | 2.76e-01 | - 16 | 4.47e-02 | 6.1758 | 2.9429 - 32 | 1.13e-02 | 3.9576 | 1.7499 - 64 | 4.59e-03 | 2.4595 | 2.1993 + 8 | 4.98e-02 | + 16 | 3.64e-02 | 1.3674 | 0.3550 + 32 | 1.19e-02 | 3.0611 | 2.4683 + 64 | 3.98e-03 | 2.9868 | 1.4933 --------------------------------------------- - And then everyone was happy. + Yay passed! @@ -1426,7 +1426,7 @@ Test Results 16 | 2.42e-03 | 32 | 6.06e-04 | 4.0001 | 2.0000 --------------------------------------------- - Once upon a time, a happy little test passed. + That was easy! uniformLOM: Edge Inner Product - Isotropic @@ -1446,7 +1446,7 @@ Test Results 16 | 2.81e-03 | 32 | 7.11e-04 | 3.9432 | 1.9794 --------------------------------------------- - The test be workin! + Testing is important. @@ -1480,7 +1480,7 @@ Test Results 16 | 6.29e-04 | 32 | 1.57e-04 | 3.9978 | 1.9992 --------------------------------------------- - You are awesome. + Yay passed! uniformLOM: Face Inner Product - Isotropic @@ -1490,7 +1490,7 @@ Test Results 16 | 6.29e-04 | 32 | 1.57e-04 | 3.9978 | 1.9992 --------------------------------------------- - Yay passed! + Once upon a time, a happy little test passed. rotateLOM: Face Inner Product - Isotropic @@ -1500,7 +1500,7 @@ Test Results 16 | 3.08e-04 | 32 | 7.07e-05 | 4.3564 | 2.1231 --------------------------------------------- - And then everyone was happy. + The test be workin! @@ -1534,7 +1534,7 @@ Test Results 16 | 6.99e-03 | 32 | 1.75e-03 | 3.9996 | 1.9998 --------------------------------------------- - Yay passed! + Awesome, Rowan, just awesome. uniformLOM: Edge Inner Product - Anisotropic @@ -1544,7 +1544,7 @@ Test Results 16 | 6.99e-03 | 32 | 1.75e-03 | 3.9996 | 1.9998 --------------------------------------------- - Happy little convergence test! + You deserve a pat on the back! rotateLOM: Edge Inner Product - Anisotropic @@ -1588,7 +1588,7 @@ Test Results 16 | 2.68e-03 | 32 | 6.69e-04 | 3.9982 | 1.9993 --------------------------------------------- - You are awesome. + Go Test Go! uniformLOM: Face Inner Product - Anisotropic @@ -1598,7 +1598,7 @@ Test Results 16 | 2.68e-03 | 32 | 6.69e-04 | 3.9982 | 1.9993 --------------------------------------------- - Testing is important. + Yay passed! rotateLOM: Face Inner Product - Anisotropic @@ -1608,7 +1608,7 @@ Test Results 16 | 2.15e-03 | 32 | 5.25e-04 | 4.0845 | 2.0302 --------------------------------------------- - The test be workin! + That was easy! @@ -1642,7 +1642,7 @@ Test Results 16 | 6.79e-03 | 32 | 1.70e-03 | 3.9996 | 1.9998 --------------------------------------------- - And then everyone was happy. + Not just a pretty face Rowan uniformLOM: Edge Inner Product - Full Tensor @@ -1652,7 +1652,7 @@ Test Results 16 | 6.79e-03 | 32 | 1.70e-03 | 3.9996 | 1.9998 --------------------------------------------- - You get a gold star! + Yay passed! rotateLOM: Edge Inner Product - Full Tensor @@ -1662,7 +1662,7 @@ Test Results 16 | 7.49e-03 | 32 | 1.89e-03 | 3.9617 | 1.9861 --------------------------------------------- - The test be workin! + That was easy! @@ -1696,7 +1696,7 @@ Test Results 16 | 3.10e-03 | 32 | 7.74e-04 | 3.9981 | 1.9993 --------------------------------------------- - Testing is important. + That was easy! uniformLOM: Face Inner Product - Full Tensor @@ -1706,7 +1706,7 @@ Test Results 16 | 3.10e-03 | 32 | 7.74e-04 | 3.9981 | 1.9993 --------------------------------------------- - Go Test Go! + Once upon a time, a happy little test passed. rotateLOM: Face Inner Product - Full Tensor @@ -1716,7 +1716,7 @@ Test Results 16 | 2.54e-03 | 32 | 6.23e-04 | 4.0741 | 2.0265 --------------------------------------------- - You are awesome. + Go Test Go! @@ -1763,7 +1763,7 @@ Test Results 64 | 2.18e-02 | 4.0001 | 2.0000 128 | 5.46e-03 | 4.0000 | 2.0000 --------------------------------------------- - Go Test Go! + Once upon a time, a happy little test passed. uniformLOM: 2D Edge Inner Product - Isotropic @@ -1777,7 +1777,7 @@ Test Results 64 | 2.18e-02 | 4.0001 | 2.0000 128 | 5.46e-03 | 4.0000 | 2.0000 --------------------------------------------- - And then everyone was happy. + Yay passed! rotateLOM: 2D Edge Inner Product - Isotropic @@ -1791,7 +1791,7 @@ Test Results 64 | 2.00e-02 | 4.0155 | 2.0056 128 | 5.00e-03 | 4.0038 | 2.0014 --------------------------------------------- - You get a gold star! + You are awesome. @@ -1829,7 +1829,7 @@ Test Results 64 | 2.53e-02 | 4.0000 | 2.0000 128 | 6.32e-03 | 4.0000 | 2.0000 --------------------------------------------- - And then everyone was happy. + Not just a pretty face Rowan uniformLOM: 2D Face Inner Product - Isotropic @@ -1843,7 +1843,7 @@ Test Results 64 | 2.53e-02 | 4.0000 | 2.0000 128 | 6.32e-03 | 4.0000 | 2.0000 --------------------------------------------- - Yay passed! + Happy little convergence test! rotateLOM: 2D Face Inner Product - Isotropic @@ -1857,7 +1857,7 @@ Test Results 64 | 2.30e-02 | 4.0132 | 2.0048 128 | 5.74e-03 | 4.0009 | 2.0003 --------------------------------------------- - And then everyone was happy. + Happy little convergence test! @@ -1895,7 +1895,7 @@ Test Results 64 | 1.30e-01 | 4.0000 | 2.0000 128 | 3.24e-02 | 4.0000 | 2.0000 --------------------------------------------- - You are awesome. + And then everyone was happy. uniformLOM: 2D Face Inner Product - Anisotropic @@ -1909,7 +1909,7 @@ Test Results 64 | 1.30e-01 | 4.0000 | 2.0000 128 | 3.24e-02 | 4.0000 | 2.0000 --------------------------------------------- - And then everyone was happy. + Yay passed! rotateLOM: 2D Face Inner Product - Anisotropic @@ -1923,7 +1923,7 @@ Test Results 64 | 1.28e-01 | 4.0007 | 2.0003 128 | 3.19e-02 | 3.9975 | 1.9991 --------------------------------------------- - And then everyone was happy. + You get a gold star! @@ -1961,7 +1961,7 @@ Test Results 64 | 3.66e-02 | 4.0000 | 2.0000 128 | 9.14e-03 | 4.0000 | 2.0000 --------------------------------------------- - And then everyone was happy. + Not just a pretty face Rowan uniformLOM: 2D Edge Inner Product - Anisotropic @@ -2027,7 +2027,7 @@ Test Results 64 | 1.52e-01 | 4.0000 | 2.0000 128 | 3.80e-02 | 4.0000 | 2.0000 --------------------------------------------- - Yay passed! + You get a gold star! uniformLOM: 2D Face Inner Product - Full Tensor @@ -2041,7 +2041,7 @@ Test Results 64 | 1.52e-01 | 4.0000 | 2.0000 128 | 3.80e-02 | 4.0000 | 2.0000 --------------------------------------------- - Once upon a time, a happy little test passed. + Go Test Go! rotateLOM: 2D Face Inner Product - Full Tensor @@ -2055,7 +2055,7 @@ Test Results 64 | 1.45e-01 | 4.0074 | 2.0027 128 | 3.62e-02 | 3.9984 | 1.9994 --------------------------------------------- - And then everyone was happy. + You get a gold star! @@ -2093,7 +2093,7 @@ Test Results 64 | 3.78e-03 | 4.0001 | 2.0000 128 | 9.46e-04 | 4.0000 | 2.0000 --------------------------------------------- - You get a gold star! + The test be workin! uniformLOM: 2D Edge Inner Product - Full Tensor @@ -2107,7 +2107,7 @@ Test Results 64 | 3.78e-03 | 4.0001 | 2.0000 128 | 9.46e-04 | 4.0000 | 2.0000 --------------------------------------------- - Testing is important. + That was easy! rotateLOM: 2D Edge Inner Product - Full Tensor @@ -2121,7 +2121,7 @@ Test Results 64 | 1.98e-02 | 3.8708 | 1.9526 128 | 5.03e-03 | 3.9418 | 1.9789 --------------------------------------------- - Testing is important. + You are awesome. @@ -2166,7 +2166,7 @@ Test Results 16 | 3.95e-02 | 3.7462 | 1.9054 32 | 1.00e-02 | 3.9364 | 1.9769 --------------------------------------------- - You are awesome. + And then everyone was happy. uniformLOM: Curl @@ -2178,7 +2178,7 @@ Test Results 16 | 3.95e-02 | 3.7462 | 1.9054 32 | 1.00e-02 | 3.9364 | 1.9769 --------------------------------------------- - The test be workin! + Happy little convergence test! rotateLOM: Curl @@ -2190,7 +2190,7 @@ Test Results 16 | 1.70e-02 | 5.2040 | 2.3796 32 | 3.77e-03 | 4.5126 | 2.1740 --------------------------------------------- - Happy little convergence test! + Go Test Go! @@ -2234,7 +2234,7 @@ Test Results 16 | 1.19e-01 | 3.7462 | 1.9054 32 | 3.01e-02 | 3.9364 | 1.9769 --------------------------------------------- - That was easy! + Go Test Go! uniformLOM: Face Divergence @@ -2245,7 +2245,7 @@ Test Results 16 | 1.19e-01 | 3.7462 | 1.9054 32 | 3.01e-02 | 3.9364 | 1.9769 --------------------------------------------- - Once upon a time, a happy little test passed. + Well done Rowan! rotateLOM: Face Divergence @@ -2256,7 +2256,7 @@ Test Results 16 | 9.53e-04 | 9.5374 | 3.2536 32 | 2.75e-04 | 3.4594 | 1.7905 --------------------------------------------- - That was easy! + Testing is important. @@ -2313,7 +2313,7 @@ Test Results 32 | 2.01e-02 | 3.9364 | 1.9769 64 | 5.04e-03 | 3.9841 | 1.9943 --------------------------------------------- - The test be workin! + Go Test Go! rotateLOM: Face Divergence 2D @@ -2325,7 +2325,7 @@ Test Results 32 | 2.01e-02 | 3.9364 | 1.9769 64 | 5.57e-03 | 3.6062 | 1.8505 --------------------------------------------- - Go Test Go! + And then everyone was happy. @@ -2370,7 +2370,7 @@ Test Results 16 | 1.34e-04 | 3.9116 | 1.9678 32 | 3.39e-05 | 3.9578 | 1.9847 --------------------------------------------- - Yay passed! + The test be workin! uniformLOM: Nodal Gradient @@ -2382,7 +2382,7 @@ Test Results 16 | 1.34e-04 | 3.9116 | 1.9678 32 | 3.39e-05 | 3.9578 | 1.9847 --------------------------------------------- - You get a gold star! + Happy little convergence test! rotateLOM: Nodal Gradient @@ -2394,7 +2394,7 @@ Test Results 16 | 1.80e-04 | 3.6283 | 1.8593 32 | 4.66e-05 | 3.8703 | 1.9525 --------------------------------------------- - You get a gold star! + The test be workin! @@ -2439,7 +2439,7 @@ Test Results 16 | 1.34e-04 | 3.9116 | 1.9678 32 | 3.39e-05 | 3.9578 | 1.9847 --------------------------------------------- - Go Test Go! + Awesome, Rowan, just awesome. uniformLOM: Nodal Gradient 2D @@ -2451,7 +2451,7 @@ Test Results 16 | 1.34e-04 | 3.9116 | 1.9678 32 | 3.39e-05 | 3.9578 | 1.9847 --------------------------------------------- - You are awesome. + You get a gold star! rotateLOM: Nodal Gradient 2D @@ -2463,10 +2463,183 @@ Test Results 16 | 1.80e-04 | 3.6343 | 1.8617 32 | 4.64e-05 | 3.8804 | 1.9562 --------------------------------------------- - Go Test Go! + You deserve a pat on the back! + + + + + + + + + test_optimizers.TestOptimizers + 4 + 4 + 0 + 0 + Detail + + + +
test_GN_Rosenbrock
+ + + + + pass + + + + + + + + +
test_GN_quadratic
+ + + + + pass + + + + + + + + +
test_ProjGradient_quadratic1Bound
+ + + + + pass + + + + + + + + +
test_ProjGradient_quadraticBounded
+ + + + + pass + + @@ -2476,60 +2649,80 @@ Test Results test_Solver.TestSolver - 10 - 10 + 14 + 14 0 0 - Detail + Detail - +
test_directDiagonal_1
pass - +
test_directDiagonal_M
pass - +
test_directFactored_1
pass - +
test_directFactored_M
pass - -
test_directLower_1
+ +
test_directLower_1_fortran
pass - -
test_directLower_M
+ +
test_directLower_1_python
pass - + +
test_directLower_M_fortran
+ pass + + + +
test_directLower_M_python
+ pass + + +
test_directSpsolve_1
pass - +
test_directSpsolve_M
pass - -
test_directUpper_1
+ +
test_directUpper_1_fortran
pass - -
test_directUpper_M
+ +
test_directUpper_1_python
+ pass + + + +
test_directUpper_M_fortran
+ pass + + + +
test_directUpper_M_python
pass @@ -2539,40 +2732,40 @@ Test Results 7 0 0 - Detail + Detail - +
test_area_3D
pass - +
test_edge_2D
pass - +
test_edge_3D
pass - +
test_vectorCC_2D
pass - +
test_vectorN_2D
pass - +
test_vol_2D
pass - +
test_vol_3D
pass @@ -2583,25 +2776,25 @@ Test Results 2 0 0 - Detail + Detail - +
test_orderBackward
- + pass -