class LowRankHessian: """ Operator that represents the action of the low rank approx of the Hessian and of its inverse. """ def __init__(self, prior, d, U): self.prior = prior self.LowRankH = LowRankOperator(d, U) dsolve = d / (np.ones(d.shape, dtype=d.dtype) + d) self.LowRankHinv = LowRankOperator(dsolve, U) self.help = Vector() self.init_vector(self.help, 0) self.help1 = Vector() self.init_vector(self.help1, 0) def init_vector(self, x, dim): self.prior.init_vector(x, dim) def inner(self, x, y): Hx = Vector() self.init_vector(Hx, 0) self.mult(x, Hx) return Hx.inner(y) def mult(self, x, y): self.prior.R.mult(x, y) self.LowRankH.mult(y, self.help) self.prior.R.mult(self.help, self.help1) y.axpy(1, self.help1) def solve(self, sol, rhs): self.prior.Rsolver.solve(sol, rhs) self.LowRankHinv.mult(rhs, self.help) sol.axpy(-1, self.help)
class LowRankPosteriorSampler: """ Object to sample from the low-rank approximation of the posterior. y = ( I - U S U^TR) x, where S = I - (I + D)^{-1/2}, x ~ N(0, R^{-1}) """ def __init__(self, prior, d, U): self.prior = prior ones = np.ones(d.shape, dtype=d.dtype) self.d = ones - np.power(ones + d, -.5) self.lrsqrt = LowRankOperator(self.d, U) self.help = Vector() self.init_vector(self.help, 0) def init_vector(self, x, dim): self.prior.init_vector(x, dim) def sample(self, noise, s): self.prior.R.mult(noise, self.help) self.lrsqrt.mult(self.help, s) s.axpy(-1, noise) s *= -1.0
class LowRankHessianMisfit: """ Operator that represents the action of the low rank approx of the Hessian misfit and of its inverse. """ def __init__(self, prior, d, U): self.prior = prior self.LowRankH = LowRankOperator(d, U) self.help = Vector() self.init_vector(self.help, 0) def init_vector(self, x, dim): self.prior.init_vector(x, dim) def inner(self, x, y): Hx = Vector() self.init_vector(Hx, 0) self.mult(x, Hx) return Hx.inner(y) def mult(self, x, y): self.prior.R.mult(x, y) self.LowRankH.mult(y, self.help) self.prior.R.mult(self.help, y)