def __init__(self, Vh, gamma, delta, locations, m_true, Theta=None, pen=1e1, order=2, rel_tol=1e-12, max_iter=1000): """ Construct the Prior model. Input: - Vh: the finite element space for the parameter - gamma and delta: the coefficient in the PDE - locations: the points x_i at which we assume to know the true value of the parameter - m_true: the true model - Theta: the s.p.d. tensor for anisotropic diffusion of the pde - pen: a penalization parameter for the mollifier """ assert delta != 0. or pen != 0, "Intrinsic Gaussian Prior are not supported" self.Vh = Vh trial = dl.TrialFunction(Vh) test = dl.TestFunction(Vh) if Theta == None: varfL = dl.inner(dl.nabla_grad(trial), dl.nabla_grad(test)) * dl.dx else: varfL = dl.inner(Theta * dl.grad(trial), dl.grad(test)) * dl.dx varfM = dl.inner(trial, test) * dl.dx self.M = dl.assemble(varfM) self.Msolver = dl.PETScKrylovSolver("cg", "jacobi") self.Msolver.set_operator(self.M) self.Msolver.parameters["maximum_iterations"] = max_iter self.Msolver.parameters["relative_tolerance"] = rel_tol self.Msolver.parameters["error_on_nonconvergence"] = True self.Msolver.parameters["nonzero_initial_guess"] = False #mfun = Mollifier(gamma/delta, dl.inv(Theta), order, locations) mfun = dl.Expression(code_Mollifier, degree=Vh.ufl_element().degree() + 2) mfun.l = gamma / delta mfun.o = order mfun.theta0 = 1. / Theta.theta0 mfun.theta1 = 1. / Theta.theta1 mfun.alpha = Theta.alpha for ii in range(locations.shape[0]): mfun.addLocation(locations[ii, 0], locations[ii, 1]) varfmo = mfun * dl.inner(trial, test) * dl.dx MO = dl.assemble(pen * varfmo) self.A = dl.assemble(gamma * varfL + delta * varfM + pen * varfmo) self.Asolver = dl.PETScKrylovSolver("cg", amg_method()) self.Asolver.set_operator(self.A) self.Asolver.parameters["maximum_iterations"] = max_iter self.Asolver.parameters["relative_tolerance"] = rel_tol self.Asolver.parameters["error_on_nonconvergence"] = True self.Asolver.parameters["nonzero_initial_guess"] = False old_qr = dl.parameters["form_compiler"]["quadrature_degree"] dl.parameters["form_compiler"]["quadrature_degree"] = -1 qdegree = 2 * Vh._ufl_element.degree() metadata = {"quadrature_degree": qdegree} if dlversion() == (2017, 1, 0): representation_old = dl.parameters["form_compiler"][ "representation"] dl.parameters["form_compiler"]["representation"] = "quadrature" if dlversion() <= (1, 6, 0): Qh = dl.FunctionSpace(Vh.mesh(), 'Quadrature', qdegree) else: element = dl.FiniteElement("Quadrature", Vh.mesh().ufl_cell(), qdegree, quad_scheme="default") Qh = dl.FunctionSpace(Vh.mesh(), element) ph = dl.TrialFunction(Qh) qh = dl.TestFunction(Qh) Mqh = dl.assemble(ph * qh * dl.dx(metadata=metadata)) ones = dl.interpolate(dl.Constant(1.), Qh).vector() dMqh = Mqh * ones Mqh.zero() dMqh.set_local(ones.array() / np.sqrt(dMqh.array())) Mqh.set_diagonal(dMqh) MixedM = dl.assemble(ph * test * dl.dx(metadata=metadata)) self.sqrtM = MatMatMult(MixedM, Mqh) dl.parameters["form_compiler"]["quadrature_degree"] = old_qr if dlversion() == (2017, 1, 0): dl.parameters["form_compiler"][ "representation"] = representation_old self.R = _BilaplacianR(self.A, self.Msolver) self.Rsolver = _BilaplacianRsolver(self.Asolver, self.M) rhs = dl.Vector() self.mean = dl.Vector() self.init_vector(rhs, 0) self.init_vector(self.mean, 0) MO.mult(m_true, rhs) self.Asolver.solve(self.mean, rhs)
class MollifiedBiLaplacianPrior(_Prior): """ This class implement a Prior model with covariance matrix C = ( (\delta + pen \sum_i m(x - x_i) ) I + \gamma \div Theta \grad) ^ {-2}, where - Theta is a s.p.d tensor that models anisotropy in the covariance kernel - x_i (i=1,...,n) are points were we assume to know exactly the value of the parameter (i.e. m(x_i) = m_true( x_i) for i=1,...,n). - m is the mollifier function: m(x - x_i) = exp( - [\frac{\gamma}{\delta}|| x - x_i ||_Theta^{-1}]^order ). - pen is a penalization paramter The magnitude of \delta\gamma governs the variance of the samples, while the ratio \frac{\gamma}{\delta} governs the correlation lenght. The prior mean is computed by solving ( (\delta + \sum_i m(x - x_i) ) I + \gamma \div Theta \grad ) m = \sum_i m(x - x_i) m_true. """ def __init__(self, Vh, gamma, delta, locations, m_true, Theta=None, pen=1e1, order=2, rel_tol=1e-12, max_iter=1000): """ Construct the Prior model. Input: - Vh: the finite element space for the parameter - gamma and delta: the coefficient in the PDE - locations: the points x_i at which we assume to know the true value of the parameter - m_true: the true model - Theta: the s.p.d. tensor for anisotropic diffusion of the pde - pen: a penalization parameter for the mollifier """ assert delta != 0. or pen != 0, "Intrinsic Gaussian Prior are not supported" self.Vh = Vh trial = dl.TrialFunction(Vh) test = dl.TestFunction(Vh) if Theta == None: varfL = dl.inner(dl.nabla_grad(trial), dl.nabla_grad(test)) * dl.dx else: varfL = dl.inner(Theta * dl.grad(trial), dl.grad(test)) * dl.dx varfM = dl.inner(trial, test) * dl.dx self.M = dl.assemble(varfM) self.Msolver = dl.PETScKrylovSolver("cg", "jacobi") self.Msolver.set_operator(self.M) self.Msolver.parameters["maximum_iterations"] = max_iter self.Msolver.parameters["relative_tolerance"] = rel_tol self.Msolver.parameters["error_on_nonconvergence"] = True self.Msolver.parameters["nonzero_initial_guess"] = False #mfun = Mollifier(gamma/delta, dl.inv(Theta), order, locations) mfun = dl.Expression(code_Mollifier, degree=Vh.ufl_element().degree() + 2) mfun.l = gamma / delta mfun.o = order mfun.theta0 = 1. / Theta.theta0 mfun.theta1 = 1. / Theta.theta1 mfun.alpha = Theta.alpha for ii in range(locations.shape[0]): mfun.addLocation(locations[ii, 0], locations[ii, 1]) varfmo = mfun * dl.inner(trial, test) * dl.dx MO = dl.assemble(pen * varfmo) self.A = dl.assemble(gamma * varfL + delta * varfM + pen * varfmo) self.Asolver = dl.PETScKrylovSolver("cg", amg_method()) self.Asolver.set_operator(self.A) self.Asolver.parameters["maximum_iterations"] = max_iter self.Asolver.parameters["relative_tolerance"] = rel_tol self.Asolver.parameters["error_on_nonconvergence"] = True self.Asolver.parameters["nonzero_initial_guess"] = False old_qr = dl.parameters["form_compiler"]["quadrature_degree"] dl.parameters["form_compiler"]["quadrature_degree"] = -1 qdegree = 2 * Vh._ufl_element.degree() metadata = {"quadrature_degree": qdegree} if dlversion() == (2017, 1, 0): representation_old = dl.parameters["form_compiler"][ "representation"] dl.parameters["form_compiler"]["representation"] = "quadrature" if dlversion() <= (1, 6, 0): Qh = dl.FunctionSpace(Vh.mesh(), 'Quadrature', qdegree) else: element = dl.FiniteElement("Quadrature", Vh.mesh().ufl_cell(), qdegree, quad_scheme="default") Qh = dl.FunctionSpace(Vh.mesh(), element) ph = dl.TrialFunction(Qh) qh = dl.TestFunction(Qh) Mqh = dl.assemble(ph * qh * dl.dx(metadata=metadata)) ones = dl.interpolate(dl.Constant(1.), Qh).vector() dMqh = Mqh * ones Mqh.zero() dMqh.set_local(ones.array() / np.sqrt(dMqh.array())) Mqh.set_diagonal(dMqh) MixedM = dl.assemble(ph * test * dl.dx(metadata=metadata)) self.sqrtM = MatMatMult(MixedM, Mqh) dl.parameters["form_compiler"]["quadrature_degree"] = old_qr if dlversion() == (2017, 1, 0): dl.parameters["form_compiler"][ "representation"] = representation_old self.R = _BilaplacianR(self.A, self.Msolver) self.Rsolver = _BilaplacianRsolver(self.Asolver, self.M) rhs = dl.Vector() self.mean = dl.Vector() self.init_vector(rhs, 0) self.init_vector(self.mean, 0) MO.mult(m_true, rhs) self.Asolver.solve(self.mean, rhs) def init_vector(self, x, dim): """ Inizialize a vector x to be compatible with the range/domain of R. If dim == "noise" inizialize x to be compatible with the size of white noise used for sampling. """ if dim == "noise": self.sqrtM.init_vector(x, 1) else: self.A.init_vector(x, dim) def sample(self, noise, s, add_mean=True): """ Given a noise ~ N(0, I) compute a sample s from the prior. If add_mean=True add the prior mean value to s. """ rhs = self.sqrtM * noise self.Asolver.solve(s, rhs) if add_mean: s.axpy(1., self.mean)
def __init__(self, Vh, gamma, delta, Theta=None, mean=None, rel_tol=1e-12, max_iter=1000): """ Construct the Prior model. Input: - Vh: the finite element space for the parameter - gamma and delta: the coefficient in the PDE - Theta: the s.p.d. tensor for anisotropic diffusion of the pde - mean: the prior mean """ assert delta != 0., "Intrinsic Gaussian Prior are not supported" self.Vh = Vh trial = dl.TrialFunction(Vh) test = dl.TestFunction(Vh) if Theta == None: varfL = dl.inner(dl.nabla_grad(trial), dl.nabla_grad(test)) * dl.dx else: varfL = dl.inner(Theta * dl.grad(trial), dl.grad(test)) * dl.dx varfM = dl.inner(trial, test) * dl.dx self.M = dl.assemble(varfM) self.Msolver = dl.PETScKrylovSolver("cg", "jacobi") self.Msolver.set_operator(self.M) self.Msolver.parameters["maximum_iterations"] = max_iter self.Msolver.parameters["relative_tolerance"] = rel_tol self.Msolver.parameters["error_on_nonconvergence"] = True self.Msolver.parameters["nonzero_initial_guess"] = False self.A = dl.assemble(gamma * varfL + delta * varfM) self.Asolver = dl.PETScKrylovSolver("cg", amg_method()) self.Asolver.set_operator(self.A) self.Asolver.parameters["maximum_iterations"] = max_iter self.Asolver.parameters["relative_tolerance"] = rel_tol self.Asolver.parameters["error_on_nonconvergence"] = True self.Asolver.parameters["nonzero_initial_guess"] = False old_qr = dl.parameters["form_compiler"]["quadrature_degree"] dl.parameters["form_compiler"]["quadrature_degree"] = -1 qdegree = 2 * Vh._ufl_element.degree() metadata = {"quadrature_degree": qdegree} if dlversion() == (2017, 1, 0): representation_old = dl.parameters["form_compiler"][ "representation"] dl.parameters["form_compiler"]["representation"] = "quadrature" if dlversion() <= (1, 6, 0): Qh = dl.FunctionSpace(Vh.mesh(), 'Quadrature', qdegree) else: #element = dl.FiniteElement("Quadrature", Vh.mesh().ufl_cell(), qdegree, quad_scheme="default") element = dl.VectorElement("Quadrature", Vh.mesh().ufl_cell(), qdegree, quad_scheme="default") Qh = dl.FunctionSpace(Vh.mesh(), element) ph = dl.TrialFunction(Qh) qh = dl.TestFunction(Qh) #Mqh = dl.assemble(ph*qh*dl.dx(metadata=metadata)) Mqh = dl.assemble(dl.inner(ph, qh) * dl.dx(metadata=metadata)) #ones = dl.interpolate(dl.Constant(1., 1., 1.), Qh).vector() ones = dl.Vector() Mqh.init_vector(ones, 0) ones.set_local(np.ones(ones.array().shape, dtype=ones.array().dtype)) dMqh = Mqh * ones Mqh.zero() dMqh.set_local(ones.array() / np.sqrt(dMqh.array())) Mqh.set_diagonal(dMqh) #MixedM = dl.assemble(ph*test*dl.dx(metadata=metadata)) MixedM = dl.assemble(dl.inner(ph, test) * dl.dx(metadata=metadata)) self.sqrtM = MatMatMult(MixedM, Mqh) dl.parameters["form_compiler"]["quadrature_degree"] = old_qr if dlversion() == (2017, 1, 0): dl.parameters["form_compiler"][ "representation"] = representation_old self.R = _BilaplacianR(self.A, self.Msolver) self.Rsolver = _BilaplacianRsolver(self.Asolver, self.M) self.mean = mean if self.mean is None: self.mean = dl.Vector() self.init_vector(self.mean, 0)
class BiLaplacianPrior(_Prior): """ This class implement a Prior model with covariance matrix C = (\delta I + \gamma \div Theta \grad) ^ {-2}. The magnitude of \delta\gamma governs the variance of the samples, while the ratio \frac{\gamma}{\delta} governs the correlation lenght. Here Theta is a s.p.d tensor that models anisotropy in the covariance kernel. """ def __init__(self, Vh, gamma, delta, Theta=None, mean=None, rel_tol=1e-12, max_iter=1000): """ Construct the Prior model. Input: - Vh: the finite element space for the parameter - gamma and delta: the coefficient in the PDE - Theta: the s.p.d. tensor for anisotropic diffusion of the pde - mean: the prior mean """ assert delta != 0., "Intrinsic Gaussian Prior are not supported" self.Vh = Vh trial = dl.TrialFunction(Vh) test = dl.TestFunction(Vh) if Theta == None: varfL = dl.inner(dl.nabla_grad(trial), dl.nabla_grad(test)) * dl.dx else: varfL = dl.inner(Theta * dl.grad(trial), dl.grad(test)) * dl.dx varfM = dl.inner(trial, test) * dl.dx self.M = dl.assemble(varfM) self.Msolver = dl.PETScKrylovSolver("cg", "jacobi") self.Msolver.set_operator(self.M) self.Msolver.parameters["maximum_iterations"] = max_iter self.Msolver.parameters["relative_tolerance"] = rel_tol self.Msolver.parameters["error_on_nonconvergence"] = True self.Msolver.parameters["nonzero_initial_guess"] = False self.A = dl.assemble(gamma * varfL + delta * varfM) self.Asolver = dl.PETScKrylovSolver("cg", amg_method()) self.Asolver.set_operator(self.A) self.Asolver.parameters["maximum_iterations"] = max_iter self.Asolver.parameters["relative_tolerance"] = rel_tol self.Asolver.parameters["error_on_nonconvergence"] = True self.Asolver.parameters["nonzero_initial_guess"] = False old_qr = dl.parameters["form_compiler"]["quadrature_degree"] dl.parameters["form_compiler"]["quadrature_degree"] = -1 qdegree = 2 * Vh._ufl_element.degree() metadata = {"quadrature_degree": qdegree} if dlversion() == (2017, 1, 0): representation_old = dl.parameters["form_compiler"][ "representation"] dl.parameters["form_compiler"]["representation"] = "quadrature" if dlversion() <= (1, 6, 0): Qh = dl.FunctionSpace(Vh.mesh(), 'Quadrature', qdegree) else: #element = dl.FiniteElement("Quadrature", Vh.mesh().ufl_cell(), qdegree, quad_scheme="default") element = dl.VectorElement("Quadrature", Vh.mesh().ufl_cell(), qdegree, quad_scheme="default") Qh = dl.FunctionSpace(Vh.mesh(), element) ph = dl.TrialFunction(Qh) qh = dl.TestFunction(Qh) #Mqh = dl.assemble(ph*qh*dl.dx(metadata=metadata)) Mqh = dl.assemble(dl.inner(ph, qh) * dl.dx(metadata=metadata)) #ones = dl.interpolate(dl.Constant(1., 1., 1.), Qh).vector() ones = dl.Vector() Mqh.init_vector(ones, 0) ones.set_local(np.ones(ones.array().shape, dtype=ones.array().dtype)) dMqh = Mqh * ones Mqh.zero() dMqh.set_local(ones.array() / np.sqrt(dMqh.array())) Mqh.set_diagonal(dMqh) #MixedM = dl.assemble(ph*test*dl.dx(metadata=metadata)) MixedM = dl.assemble(dl.inner(ph, test) * dl.dx(metadata=metadata)) self.sqrtM = MatMatMult(MixedM, Mqh) dl.parameters["form_compiler"]["quadrature_degree"] = old_qr if dlversion() == (2017, 1, 0): dl.parameters["form_compiler"][ "representation"] = representation_old self.R = _BilaplacianR(self.A, self.Msolver) self.Rsolver = _BilaplacianRsolver(self.Asolver, self.M) self.mean = mean if self.mean is None: self.mean = dl.Vector() self.init_vector(self.mean, 0) def init_vector(self, x, dim): """ Inizialize a vector x to be compatible with the range/domain of R. If dim == "noise" inizialize x to be compatible with the size of white noise used for sampling. """ if dim == "noise": self.sqrtM.init_vector(x, 1) else: self.A.init_vector(x, dim) def sample(self, noise, s, add_mean=True): """ Given a noise ~ N(0, I) compute a sample s from the prior. If add_mean=True add the prior mean value to s. """ rhs = self.sqrtM * noise self.Asolver.solve(s, rhs) if add_mean: s.axpy(1., self.mean)
def __init__(self, Vh, gamma, delta, mean=None, rel_tol=1e-12, max_iter=100): """ Construct the Prior model. Input: - Vh: the finite element space for the parameter - gamma and delta: the coefficient in the PDE - Theta: the s.p.d. tensor for anisotropic diffusion of the pde - mean: the prior mean """ assert delta != 0., "Intrinsic Gaussian Prior are not supported" self.Vh = Vh trial = dl.TrialFunction(Vh) test = dl.TestFunction(Vh) varfL = dl.inner(dl.nabla_grad(trial), dl.nabla_grad(test)) * dl.dx varfM = dl.inner(trial, test) * dl.dx self.M = dl.assemble(varfM) self.R = dl.assemble(gamma * varfL + delta * varfM) self.Rsolver = dl.PETScKrylovSolver("cg", amg_method()) self.Rsolver.set_operator(self.R) self.Rsolver.parameters["maximum_iterations"] = max_iter self.Rsolver.parameters["relative_tolerance"] = rel_tol self.Rsolver.parameters["error_on_nonconvergence"] = True self.Rsolver.parameters["nonzero_initial_guess"] = False self.Msolver = dl.PETScKrylovSolver("cg", "jacobi") self.Msolver.set_operator(self.M) self.Msolver.parameters["maximum_iterations"] = max_iter self.Msolver.parameters["relative_tolerance"] = rel_tol self.Msolver.parameters["error_on_nonconvergence"] = True self.Msolver.parameters["nonzero_initial_guess"] = False ndim = Vh.mesh().geometry().dim() qdegree = 2 * Vh._ufl_element.degree() metadata = {"quadrature_degree": qdegree} if dlversion() <= (1, 6, 0): Qh = dl.VectorFunctionSpace(Vh.mesh(), 'Quadrature', qdegree, dim=(ndim + 1)) else: element = dl.VectorElement("Quadrature", Vh.mesh().ufl_cell(), qdegree, dim=(ndim + 1), quad_scheme="default") Qh = dl.FunctionSpace(Vh.mesh(), element) ph = dl.TrialFunction(Qh) qh = dl.TestFunction(Qh) pph = dl.split(ph) Mqh = dl.assemble(dl.inner(ph, qh) * dl.dx(metadata=metadata)) ones = dl.Vector() Mqh.init_vector(ones, 0) ones.set_local(np.ones(ones.array().shape, dtype=ones.array().dtype)) dMqh = Mqh * ones dMqh.set_local(ones.array() / np.sqrt(dMqh.array())) Mqh.zero() Mqh.set_diagonal(dMqh) sqrtdelta = math.sqrt(delta) sqrtgamma = math.sqrt(gamma) varfGG = sqrtdelta * pph[0] * test * dl.dx(metadata=metadata) for i in range(ndim): varfGG = varfGG + sqrtgamma * pph[i + 1] * test.dx(i) * dl.dx( metadata=metadata) GG = dl.assemble(varfGG) self.sqrtR = MatMatMult(GG, Mqh) self.mean = mean if self.mean is None: self.mean = dl.Vector() self.init_vector(self.mean, 0)
class LaplacianPrior(_Prior): """ This class implements a Prior model with covariance matrix C = (\delta I + \gamma \Delta) ^ {-1}. The magnitude of \gamma governs the variance of the samples, while the ratio \frac{\gamma}{\delta} governs the correlation lenght. Note that C is a trace class operator only in 1D while it is not a valid prior in 2D and 3D. """ def __init__(self, Vh, gamma, delta, mean=None, rel_tol=1e-12, max_iter=100): """ Construct the Prior model. Input: - Vh: the finite element space for the parameter - gamma and delta: the coefficient in the PDE - Theta: the s.p.d. tensor for anisotropic diffusion of the pde - mean: the prior mean """ assert delta != 0., "Intrinsic Gaussian Prior are not supported" self.Vh = Vh trial = dl.TrialFunction(Vh) test = dl.TestFunction(Vh) varfL = dl.inner(dl.nabla_grad(trial), dl.nabla_grad(test)) * dl.dx varfM = dl.inner(trial, test) * dl.dx self.M = dl.assemble(varfM) self.R = dl.assemble(gamma * varfL + delta * varfM) self.Rsolver = dl.PETScKrylovSolver("cg", amg_method()) self.Rsolver.set_operator(self.R) self.Rsolver.parameters["maximum_iterations"] = max_iter self.Rsolver.parameters["relative_tolerance"] = rel_tol self.Rsolver.parameters["error_on_nonconvergence"] = True self.Rsolver.parameters["nonzero_initial_guess"] = False self.Msolver = dl.PETScKrylovSolver("cg", "jacobi") self.Msolver.set_operator(self.M) self.Msolver.parameters["maximum_iterations"] = max_iter self.Msolver.parameters["relative_tolerance"] = rel_tol self.Msolver.parameters["error_on_nonconvergence"] = True self.Msolver.parameters["nonzero_initial_guess"] = False ndim = Vh.mesh().geometry().dim() qdegree = 2 * Vh._ufl_element.degree() metadata = {"quadrature_degree": qdegree} if dlversion() <= (1, 6, 0): Qh = dl.VectorFunctionSpace(Vh.mesh(), 'Quadrature', qdegree, dim=(ndim + 1)) else: element = dl.VectorElement("Quadrature", Vh.mesh().ufl_cell(), qdegree, dim=(ndim + 1), quad_scheme="default") Qh = dl.FunctionSpace(Vh.mesh(), element) ph = dl.TrialFunction(Qh) qh = dl.TestFunction(Qh) pph = dl.split(ph) Mqh = dl.assemble(dl.inner(ph, qh) * dl.dx(metadata=metadata)) ones = dl.Vector() Mqh.init_vector(ones, 0) ones.set_local(np.ones(ones.array().shape, dtype=ones.array().dtype)) dMqh = Mqh * ones dMqh.set_local(ones.array() / np.sqrt(dMqh.array())) Mqh.zero() Mqh.set_diagonal(dMqh) sqrtdelta = math.sqrt(delta) sqrtgamma = math.sqrt(gamma) varfGG = sqrtdelta * pph[0] * test * dl.dx(metadata=metadata) for i in range(ndim): varfGG = varfGG + sqrtgamma * pph[i + 1] * test.dx(i) * dl.dx( metadata=metadata) GG = dl.assemble(varfGG) self.sqrtR = MatMatMult(GG, Mqh) self.mean = mean if self.mean is None: self.mean = dl.Vector() self.init_vector(self.mean, 0) def init_vector(self, x, dim): """ Inizialize a vector x to be compatible with the range/domain of R. If dim == "noise" inizialize x to be compatible with the size of white noise used for sampling. """ if dim == "noise": self.sqrtR.init_vector(x, 1) else: self.R.init_vector(x, dim) def sample(self, noise, s, add_mean=True): """ Given a noise ~ N(0, I) compute a sample s from the prior. If add_mean=True add the prior mean value to s. """ rhs = self.sqrtR * noise self.Rsolver.solve(s, rhs) if add_mean: s.axpy(1., self.mean)