class LowRankHessian: """ Operator that represents the action of the low rank approximation 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(U[0].mpi_comm()) self.init_vector(self.help, 0) self.help1 = Vector(U[0].mpi_comm()) 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.help.mpi_comm()) 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 LowRankHessian: """ Operator that represents the action of the low rank approximation 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(U[0].mpi_comm()) self.init_vector(self.help, 0) self.help1 = Vector(U[0].mpi_comm()) 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.help.mpi_comm()) 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)
def trace(A): """ Compute the trace of a sparse matrix A. """ v = Vector() A.init_vector(v) mpi_comm = v.mpi_comm() nprocs = MPI.size(mpi_comm) if nprocs > 1: raise Exception("trace is only serial") n = A.size(0) tr = 0. for i in range(0, n): [j, val] = A.getrow(i) tr += val[j == i] return tr
def to_dense(A): """ Convert a sparse matrix A to dense. For debugging only. """ v = Vector() A.init_vector(v) mpi_comm = v.mpi_comm() nprocs = MPI.size(mpi_comm) if nprocs > 1: raise Exception("to_dense is only serial") if hasattr(A, "getrow"): n = A.size(0) m = A.size(1) B = np.zeros((n, m), dtype=np.float64) for i in range(0, n): [j, val] = A.getrow(i) B[i, j] = val return B else: x = Vector() Ax = Vector() A.init_vector(x, 1) A.init_vector(Ax, 0) n = Ax.array().shape[0] m = x.array().shape[0] B = np.zeros((n, m), dtype=np.float64) for i in range(0, m): i_ind = np.array([i], dtype=np.intc) x.set_local(np.ones(i_ind.shape), i_ind) x.apply("sum_values") A.mult(x, Ax) B[:, i] = Ax.array() x.set_local(np.zeros(i_ind.shape), i_ind) x.apply("sum_values") return B