Files
simpeg/SimPEG/InvProblem.py
T
2014-05-17 00:14:22 -07:00

91 lines
2.8 KiB
Python

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]