"""Preconditioned conjugate gradient method for the EGSZ application""" from spuq.utils.type_check import takes, optional, returns, tuple_of from spuq.linalg.operator import Operator from spuq.linalg.vector import Vector, inner from spuq.utils.forgetful_vector import ForgetfulVector __all__ = ["pcg"] import logging logger = logging.getLogger(__name__) @takes(Operator, Vector, Operator, Vector, optional(float), optional(int)) def pcg(A, f, P, w0, eps=1e-4, maxiter=100): # for most quantities in PCG (except zeta) only the most recent # values needs to be kept in memory w = ForgetfulVector(1) rho = ForgetfulVector(1) s = ForgetfulVector(1) v = ForgetfulVector(1) z = ForgetfulVector(1) alpha = ForgetfulVector(1) zeta = ForgetfulVector(2) w[0] = w0 rho[0] = f - A * w[0] s[0] = P * rho[0] v[0] = s[0] zeta[0] = inner(rho[0], s[0]) for i in xrange(1, maxiter):
DEFAULT_BC = object() @takes((Expression, Function), FunctionSpace) def poisson_bilinear_form(coeff_func, V): """Assemble the discrete problem (i.e. the stiffness matrix).""" # setup problem, assemble and apply boundary conditions u = TrialFunction(V) v = TestFunction(V) a = inner(coeff_func * nabla_grad(u), nabla_grad(v)) * dx return a @takes(anything, (DirichletBC, NoneType, object), optional(FunctionSpace)) def apply_bc(fenics_obj, bc=DEFAULT_BC, V=None): if bc is not None: if bc is DEFAULT_BC: if V is None: V = fenics_obj.function_space() bc = homogeneous_dirichlet_bc(V) bc.apply(fenics_obj) return fenics_obj @takes(GenericMatrix, (DirichletBC, sequence_of(DirichletBC))) def _remove_boundary_entries(A, bcs): if not isinstance(bcs, DirichletBC): for bc in bcs: remove_boundary_entries(A, bc)
import collections from abc import ABCMeta, abstractmethod default_Dirichlet_boundary = lambda x, on_boundary: on_boundary CoefficientFunction = (dolfin.Expression, dolfin.GenericFunction, ufl.expr.Expr, tuple_of((dolfin.Expression, dolfin.GenericFunction, ufl.expr.Expr, float, int))) FormFunction = (dolfin.Argument, dolfin.Function) LoadingFunction = (dolfin.Coefficient) BoundaryType = (anything) BoundaryFunction = (dolfin.Coefficient) ################################################### # Helper functions ################################################### @takes(anything, optional(int)) def make_list(x, length=None): """Make a sequence type out of some item if it not already is one""" if not isinstance(x, collections.Sequence): x = [x] if length is not None: if len(x) == 1: x = x * length assert len(x) == length return x @takes(dolfin.FunctionSpaceBase) def zero_function(V): if V.num_sub_spaces(): d = V.mesh().geometry().dim()