Ejemplo n.º 1
0
    def solve_alpha_M_beta_F(self, alpha, beta, b, t):
        """Solve  :code:`alpha * M * u + beta * F(u, t) = b`  with Dirichlet
        conditions.
        """
        matrix = alpha * self.M + beta * self.A

        # See above for float conversion
        right_hand_side = -float(beta) * self.b.copy()
        if b:
            right_hand_side += b

        for bc in self.dirichlet_bcs:
            bc.apply(matrix, right_hand_side)

        # TODO proper preconditioner for convection
        if self.convection:
            # Use HYPRE-Euclid instead of ILU for parallel computation.
            # However, this PC sometimes fails.
            # solver = KrylovSolver('gmres', 'hypre_euclid')
            # Fallback:
            solver = LUSolver()
        else:
            solver = KrylovSolver("gmres", "hypre_amg")
            solver.parameters["relative_tolerance"] = 1.0e-13
            solver.parameters["absolute_tolerance"] = 0.0
            solver.parameters["maximum_iterations"] = 100
            solver.parameters["monitor_convergence"] = True

        solver.set_operator(matrix)

        u = Function(self.Q)
        solver.solve(u.vector(), right_hand_side)
        return u
Ejemplo n.º 2
0
def assert_solves(
    mesh: Mesh,
    diffusion: Coefficient,
    convection: Optional[Coefficient],
    reaction: Optional[Coefficient],
    source: Coefficient,
    exact: Coefficient,
    l2_tol: Optional[float] = 1.0e-8,
    h1_tol: Optional[float] = 1.0e-6,
):
    eafe_matrix = eafe_assemble(mesh, diffusion, convection, reaction)

    pw_linears = FunctionSpace(mesh, "Lagrange", 1)
    test_function = TestFunction(pw_linears)
    rhs_vector = assemble(source * test_function * dx)

    bc = DirichletBC(pw_linears, exact, lambda _, on_bndry: on_bndry)
    bc.apply(eafe_matrix, rhs_vector)

    solution = Function(pw_linears)
    solver = LUSolver(eafe_matrix, "default")
    solver.parameters["symmetric"] = False
    solver.solve(solution.vector(), rhs_vector)

    l2_err: float = errornorm(exact, solution, "l2", 3)
    assert l2_err <= l2_tol, f"L2 error too large: {l2_err} > {l2_tol}"

    h1_err: float = errornorm(exact, solution, "H1", 3)
    assert h1_err <= h1_tol, f"H1 error too large: {h1_err} > {h1_tol}"
Ejemplo n.º 3
0
def direct_solve(A, b, W, which='umfpack'):
    '''inv(A)*b'''
    print 'Solving system of size %d' % A.size(0)
    # NOTE: umfpack sometimes blows up, MUMPS produces crap more often than not
    if isinstance(W, list):
        wh = ii_Function(W)
        LUSolver(which).solve(A, wh.vector(), b)
        print('|b-Ax| from direct solver', (A * wh.vector() - b).norm('linf'))

        return wh

    wh = Function(W)
    LUSolver(which).solve(A, wh.vector(), b)
    print('|b-Ax| from direct solver', (A * wh.vector() - b).norm('linf'))

    if isinstance(
            W.ufl_element(),
        (ufl.VectorElement, ufl.TensorElement)) or W.num_sub_spaces() == 1:
        return ii_Function([W], [wh])

    # Now get components
    Wblock = serialize_mixed_space(W)
    wh = wh.split(deepcopy=True)

    return ii_Function(Wblock, wh)
Ejemplo n.º 4
0
    def _get_constant_pressure(self, W):
        w = TrialFunction(W)
        w_ = TestFunction(W)
        p_ = self.test_functions()["p"]
        A, b = assemble_system(inner(w, w_) * dx, p_ * dx)
        null_fcn = Function(W)
        solver = LUSolver("mumps")
        solver.solve(A, null_fcn.vector(), b)

        return null_fcn
Ejemplo n.º 5
0
    def __init__(self, *args, **kwargs):
        """
        Create solver for
        :py:class:`SemiDecoupled <muflon.functions.discretization.SemiDecoupled>`
        discretization scheme.

        See :py:class:`Solver <muflon.solving.solvers.Solver>` for the list of
        valid initialization arguments.
        """
        super(SemiDecoupled, self).__init__(*args, **kwargs)

        # Extract solution functions
        DS = self.data["model"].discretization_scheme()
        w_ch, w_ns = DS.solution_ctl()

        # Adjust bcs
        bcs_ch = []
        bcs_ns = []
        _bcs = self.data["model"].bcs()
        for bc_v in _bcs.get("v", []):
            assert isinstance(bc_v, tuple)
            assert len(bc_v) == len(w_ns.sub(0))
            bcs_ns += [bc for bc in bc_v if bc is not None]
        bcs_ns += [bc for bc in _bcs.get("p", [])]
        # FIXME: Deal with possible bcs for ``phi`` and ``th``

        # Prepare solver for CH part
        F = self.data["forms"]["nln"]
        J = derivative(F, w_ch)

        # Store solvers and collect other data
        self.data["problem_ch"] = self.CHProblem(F, bcs_ch, J)
        self.data["solver"] = OrderedDict()
        self.data["solver"]["CH"] = OrderedDict()
        self.data["solver"]["CH"]["lin"] = LUSolver("mumps")
        # NOTE: Initialization of nonlinear solver is postponed until setup
        self.data["solver"]["NS"] = LUSolver("mumps")
        self.data["sol_ch"] = w_ch
        self.data["sol_ns"] = w_ns
        self.data["bcs_ns"] = bcs_ns

        # Preparation for tackling singular systems
        if self._flags["fix_p"]:
            null_space, null_fcn = DS.build_pressure_null_space()
            self.data["null_space"] = null_space
            self.data["null_fcn"] = null_fcn

        # Store number of iterations
        self.iters = OrderedDict()
        self.iters["CH"] = [0, 0]  # (total, last solve)
        self.iters["NS"] = [0, 0]  # (total, last solve)
Ejemplo n.º 6
0
 def setUp(self):
     mesh = UnitSquareMesh(5, 5, 'crossed')
     self.V = FunctionSpace(mesh, 'Lagrange', 5)
     self.u = Function(self.V)
     self.uM = Function(self.V)
     self.uMdiag = Function(self.V)
     test = TestFunction(self.V)
     trial = TrialFunction(self.V)
     m = test * trial * dx
     self.M = assemble(m)
     self.solver = LUSolver()
     self.solver.parameters['reuse_factorization'] = True
     self.solver.parameters['symmetric'] = True
     self.solver.set_operator(self.M)
     self.ones = np.ones(self.V.dim())
Ejemplo n.º 7
0
    def __init__(self, *args, **kwargs):
        """
        Create linear solver for :py:class:`FullyDecoupled \
        <muflon.functions.discretization.FullyDecoupled>`
        discretization scheme.

        See :py:class:`Solver <muflon.solving.solvers.Solver>` for the list of
        valid initialization arguments.
        """
        super(FullyDecoupled, self).__init__(*args, **kwargs)

        # Create solvers
        solver = OrderedDict()
        solver["phi"] = LUSolver("mumps")
        solver["chi"] = LUSolver("mumps")
        solver["v"] = LUSolver("mumps")
        solver["p"] = LUSolver("mumps")
        self.data["solver"] = solver

        # Initialize flags
        self._flags["setup"] = False
Ejemplo n.º 8
0
 def _assemble(self):
     # Get input:
     self.gamma = self.Parameters['gamma']
     if self.Parameters.has_key('beta'): self.beta = self.Parameters['beta']
     else: self.beta = 0.0
     self.Vm = self.Parameters['Vm']
     if self.Parameters.has_key('m0'):
         self.m0 = self.Parameters['m0'].copy(deepcopy=True)
         isFunction(self.m0)
     else:
         self.m0 = Function(self.Vm)
     self.mtrial = TrialFunction(self.Vm)
     self.mtest = TestFunction(self.Vm)
     self.mysample = Function(self.Vm)
     self.draw = Function(self.Vm)
     # Assemble:
     self.R = assemble(inner(nabla_grad(self.mtrial), \
     nabla_grad(self.mtest))*dx)
     self.M = PETScMatrix()
     assemble(inner(self.mtrial, self.mtest) * dx, tensor=self.M)
     # preconditioner is Gamma^{-1}:
     if self.beta > 1e-16:
         self.precond = self.gamma * self.R + self.beta * self.M
     else:
         self.precond = self.gamma * self.R + (1e-14) * self.M
     # Discrete operator K:
     self.K = self.gamma * self.R + self.beta * self.M
     # Get eigenvalues for M:
     self.eigsolM = SLEPcEigenSolver(self.M)
     self.eigsolM.solve()
     # Solver for M^{-1}:
     self.solverM = LUSolver()
     self.solverM.parameters['reuse_factorization'] = True
     self.solverM.parameters['symmetric'] = True
     self.solverM.set_operator(self.M)
     # Solver for K^{-1}:
     self.solverK = LUSolver()
     self.solverK.parameters['reuse_factorization'] = True
     self.solverK.parameters['symmetric'] = True
     self.solverK.set_operator(self.K)
Ejemplo n.º 9
0
    def _set_fluid_default_parameters(self):
        fluid = df.Parameters(Physics.FLUID.value)
        fluid.add("dt", 1e-3)
        fluid.add("dummy_parameter", False)

        # Add default parameters from both LU and Krylov solvers
        fluid.add(LUSolver.default_parameters())
        fluid.add(PETScKrylovSolver.default_parameters())

        # Add solver parameters
        fluid.add(df.Parameters("Solver"))
        fluid["Solver"].add("dummy_parameter", False)

        self.add(fluid)
Ejemplo n.º 10
0
    def _set_porous_default_parameters(self):
        porous = df.Parameters(Physics.POROUS.value)
        porous.add("dt", 1e-3)
        porous.add("dummy_parameter", False)

        # Add default parameters from both LU and Krylov solvers
        porous.add(LUSolver.default_parameters())
        porous.add(PETScKrylovSolver.default_parameters())

        # Add solver parameters
        porous.add(df.Parameters("Solver"))
        porous["Solver"].add("dummy_parameter", False)

        self.add(porous)
Ejemplo n.º 11
0
 def _assemble(self):
     # Get input:
     self.gamma = self.Parameters['gamma']
     if self.Parameters.has_key('beta'): self.beta = self.Parameters['beta']
     else:   self.beta = 0.0
     self.Vm = self.Parameters['Vm']
     if self.Parameters.has_key('m0'):   
         self.m0 = self.Parameters['m0'].copy(deepcopy=True)
         isFunction(self.m0)
     else:   self.m0 = Function(self.Vm)
     self.mtrial = TrialFunction(self.Vm)
     self.mtest = TestFunction(self.Vm)
     self.mysample = Function(self.Vm)
     self.draw = Function(self.Vm)
     # Assemble:
     self.R = assemble(inner(nabla_grad(self.mtrial), \
     nabla_grad(self.mtest))*dx)
     self.M = PETScMatrix()
     assemble(inner(self.mtrial, self.mtest)*dx, tensor=self.M)
     # preconditioner is Gamma^{-1}:
     if self.beta > 1e-16: self.precond = self.gamma*self.R + self.beta*self.M
     else:   self.precond = self.gamma*self.R + (1e-14)*self.M
     # Discrete operator K:
     self.K = self.gamma*self.R + self.beta*self.M
     # Get eigenvalues for M:
     self.eigsolM = SLEPcEigenSolver(self.M)
     self.eigsolM.solve()
     # Solver for M^{-1}:
     self.solverM = LUSolver()
     self.solverM.parameters['reuse_factorization'] = True
     self.solverM.parameters['symmetric'] = True
     self.solverM.set_operator(self.M)
     # Solver for K^{-1}:
     self.solverK = LUSolver()
     self.solverK.parameters['reuse_factorization'] = True
     self.solverK.parameters['symmetric'] = True
     self.solverK.set_operator(self.K)
Ejemplo n.º 12
0
 def setUp(self):
     mesh = UnitSquareMesh(5, 5, 'crossed')
     self.V = FunctionSpace(mesh, 'Lagrange', 5)
     self.u = Function(self.V)
     self.uM = Function(self.V)
     self.uMdiag = Function(self.V)
     test = TestFunction(self.V)
     trial = TrialFunction(self.V)
     m = test*trial*dx
     self.M = assemble(m)
     self.solver = LUSolver()
     self.solver.parameters['reuse_factorization'] = True
     self.solver.parameters['symmetric'] = True
     self.solver.set_operator(self.M)
     self.ones = np.ones(self.V.dim())
Ejemplo n.º 13
0
    def _set_solid_default_parameters(self):
        solid = df.Parameters(Physics.SOLID.value)
        solid.add("dt", 1e-3)
        solid.add("dummy_parameter", False)

        # Add boundary condtion parameters
        solid.add(df.Parameters("BoundaryConditions"))
        solid["BoundaryConditions"].add("base_bc", "fixed")
        solid["BoundaryConditions"].add("lv_pressure", 10.0)
        solid["BoundaryConditions"].add("rv_pressure", 0.0)
        solid["BoundaryConditions"].add("pericardium_spring", 0.0)
        solid["BoundaryConditions"].add("base_spring", 0.0)

        # Add default parameters from both LU and Krylov solvers
        solid.add(NonlinearVariationalSolver.default_parameters())
        solid.add(LUSolver.default_parameters())
        solid.add(PETScKrylovSolver.default_parameters())

        # Add solver parameters
        solid.add(df.Parameters("Solver"))
        solid["Solver"].add("dummy_parameter", False)

        self.add(solid)
Ejemplo n.º 14
0
Archivo: heat.py Proyecto: nschloe/flow
    def solve_alpha_M_beta_F(self, alpha, beta, b, t):
        '''Solve  alpha * M * u + beta * F(u, t) = b  for u.
        '''
        A = alpha * self.M + beta * self.A

        # See above for float conversion
        right_hand_side = - float(beta) * self.b.copy()
        if b:
            right_hand_side += b

        for bc in self.bcs:
            bc.apply(A, b)

        # The Krylov solver doesn't converge
        solver = LUSolver()
        solver.set_operator(A)

        u = Function(self.V)
        solver.solve(u.vector(), b)
        return u
Ejemplo n.º 15
0
class ObjectiveFunctional(LinearOperator):
    """
    Provides data misfit, gradient and Hessian information for the data misfit
    part of a time-independent symmetric inverse problem.
    """
    __metaclass__ = abc.ABCMeta

    # Instantiation
    def __init__(self, V, Vm, bc, bcadj, \
    RHSinput=[], ObsOp=[], UD=[], Regul=[], Data=[], plot=False, \
    mycomm=None):
        # Define test, trial and all other functions
        self.trial = TrialFunction(V)
        self.test = TestFunction(V)
        self.mtrial = TrialFunction(Vm)
        self.mtest = TestFunction(Vm)
        self.rhs = Function(V)
        self.m = Function(Vm)
        self.mcopy = Function(Vm)
        self.srchdir = Function(Vm)
        self.delta_m = Function(Vm)
        self.MG = Function(Vm)
        self.Grad = Function(Vm)
        self.Gradnorm = 0.0
        self.lenm = len(self.m.vector().array())
        self.u = Function(V)
        self.ud = Function(V)
        self.diff = Function(V)
        self.p = Function(V)
        # Define weak forms to assemble A, C and E
        self._wkforma()
        self._wkformc()
        self._wkforme()
        # Store other info:
        self.ObsOp = ObsOp
        self.UD = UD
        self.reset()    # Initialize U, C and E to []
        self.Data = Data
        self.GN = 1.0   # GN = 0.0 => GN Hessian; = 1.0 => full Hessian
        # Operators and bc
        LinearOperator.__init__(self, self.delta_m.vector(), \
        self.delta_m.vector()) 
        self.bc = bc
        self.bcadj = bcadj
        self._assemble_solverM(Vm)
        self.assemble_A()
        self.assemble_RHS(RHSinput)
        self.Regul = Regul
        # Counters, tolerances and others
        self.nbPDEsolves = 0    # Updated when solve_A called
        self.nbfwdsolves = 0    # Counter for plots
        self.nbadjsolves = 0    # Counter for plots
        self._set_plots(plot)
        # MPI:
        self.mycomm = mycomm
        try:
            self.myrank = MPI.rank(self.mycomm)
        except:
            self.myrank = 0

    def copy(self):
        """Define a copy method"""
        V = self.trial.function_space()
        Vm = self.mtrial.function_space()
        newobj = self.__class__(V, Vm, self.bc, self.bcadj, [], self.ObsOp, \
        self.UD, self.Regul, self.Data, False)
        newobj.RHS = self.RHS
        newobj.update_m(self.m)
        return newobj

    def mult(self, mhat, y):
        """mult(self, mhat, y): do y = Hessian * mhat
        member self.GN sets full Hessian (=1.0) or GN Hessian (=0.0)"""
        N = self.Nbsrc # Number of sources
        y[:] = np.zeros(self.lenm)
        for C, E in zip(self.C, self.E):
            # Solve for uhat
            C.transpmult(mhat, self.rhs.vector())
            self.bcadj.apply(self.rhs.vector())
            self.solve_A(self.u.vector(), -self.rhs.vector())
            # Solve for phat
            E.transpmult(mhat, self.rhs.vector())
            Etmhat = self.rhs.vector().array()
            self.rhs.vector().axpy(1.0, self.ObsOp.incradj(self.u))
            self.bcadj.apply(self.rhs.vector())
            self.solve_A(self.p.vector(), -self.rhs.vector())
            # Compute Hessian*x:
            y.axpy(1.0/N, C * self.p.vector())
            y.axpy(self.GN/N, E * self.u.vector())
        y.axpy(1.0, self.Regul.hessian(mhat))

    # Getters
    def getm(self): return self.m
    def getmarray(self):    return self.m.vector().array()
    def getmcopyarray(self):    return self.mcopy.vector().array()
    def getVm(self):    return self.mtrial.function_space()
    def getMGarray(self):   return self.MG.vector().array()
    def getMGvec(self):   return self.MG.vector()
    def getGradarray(self):   return self.Grad.vector().array()
    def getGradnorm(self):  return self.Gradnorm
    def getsrchdirarray(self):    return self.srchdir.vector().array()
    def getsrchdirvec(self):    return self.srchdir.vector()
    def getsrchdirnorm(self):
        return np.sqrt((self.MM*self.getsrchdirvec()).inner(self.getsrchdirvec()))
    def getgradxdir(self): return self.gradxdir
    def getcost(self):  return self.cost, self.misfit, self.regul
    def getprecond(self):
        Prec = PETScKrylovSolver("richardson", "amg")
        Prec.parameters["maximum_iterations"] = 1
        Prec.parameters["error_on_nonconvergence"] = False
        Prec.parameters["nonzero_initial_guess"] = False
        Prec.set_operator(self.Regul.get_precond())
        return Prec
    def getMass(self):    return self.MM

    # Setters
    def setsrchdir(self, arr):  self.srchdir.vector()[:] = arr
    def setgradxdir(self, valueloc):   
        """Sum all local results for Grad . Srch_dir"""
        try:
            valueglob = MPI.sum(self.mycomm, valueloc)
        except:
            valueglob = valueloc
        self.gradxdir = valueglob

    # Solve
    def solvefwd(self, cost=False):
        """Solve fwd operators for given RHS"""
        self.nbfwdsolves += 1
        if self.ObsOp.noise:    self.noise = 0.0
        if self.plot:
            self.plotu = PlotFenics(self.plotoutdir)
            self.plotu.set_varname('u{0}'.format(self.nbfwdsolves))
        if cost:    self.misfit = 0.0
        for ii, rhs in enumerate(self.RHS):
            self.solve_A(self.u.vector(), rhs)
            if self.plot:   self.plotu.plot_vtk(self.u, ii)
            u_obs, noiselevel = self.ObsOp.obs(self.u)
            self.U.append(u_obs)
            if self.ObsOp.noise:    self.noise += noiselevel
            if cost:
                self.misfit += self.ObsOp.costfct(u_obs, self.UD[ii])
            self.C.append(assemble(self.c))
        if cost:
            self.misfit /= len(self.U)
            self.regul = self.Regul.cost(self.m)
            self.cost = self.misfit + self.regul
        if self.ObsOp.noise and self.myrank == 0:
            print 'Total noise in data misfit={:.5e}\n'.\
            format(self.noise*.5/len(self.U))
            self.ObsOp.noise = False    # Safety
        if self.plot:   self.plotu.gather_vtkplots()

    def solvefwd_cost(self):
        """Solve fwd operators for given RHS and compute cost fct"""
        self.solvefwd(True)

    def solveadj(self, grad=False):
        """Solve adj operators"""
        self.nbadjsolves += 1
        if self.plot:
            self.plotp = PlotFenics(self.plotoutdir)
            self.plotp.set_varname('p{0}'.format(self.nbadjsolves))
        self.Nbsrc = len(self.UD)
        if grad:    self.MG.vector()[:] = np.zeros(self.lenm)
        for ii, C in enumerate(self.C):
            self.ObsOp.assemble_rhsadj(self.U[ii], self.UD[ii], \
            self.rhs, self.bcadj)
            self.solve_A(self.p.vector(), self.rhs.vector())
            if self.plot:   self.plotp.plot_vtk(self.p, ii)
            self.E.append(assemble(self.e))
            if grad:    self.MG.vector().axpy(1.0/self.Nbsrc, \
                        C * self.p.vector())
        if grad:
            self.MG.vector().axpy(1.0, self.Regul.grad(self.m))
            self.solverM.solve(self.Grad.vector(), self.MG.vector())
            self.Gradnorm = np.sqrt(self.Grad.vector().inner(self.MG.vector()))
        if self.plot:   self.plotp.gather_vtkplots()

    def solveadj_constructgrad(self):
        """Solve adj operators and assemble gradient"""
        self.solveadj(True)

    # Assembler
    def assemble_A(self):
        """Assemble operator A(m)"""
        self.A = assemble(self.a)
        self.bc.apply(self.A)
        self.set_solver()

    def solve_A(self, b, f):
        """Solve system of the form A.b = f, 
        with b and f in form to be used in solver."""
        self.solver.solve(b, f)
        self.nbPDEsolves += 1

    def assemble_RHS(self, RHSin):
        """Assemble RHS for fwd solve"""
        if RHSin == []: self.RHS = None
        else:
            self.RHS = []
            for rhs in RHSin:
                if isinstance(rhs, Expression):
                    L = rhs*self.test*dx
                    b = assemble(L)
                    self.bc.apply(b)
                    self.RHS.append(b)
                else:   raise WrongInstanceError("rhs should be Expression")

    def _assemble_solverM(self, Vm):
        self.MM = assemble(inner(self.mtrial, self.mtest)*dx)
        self.solverM = LUSolver()
        self.solverM.parameters['reuse_factorization'] = True
        self.solverM.parameters['symmetric'] = True
        self.solverM.set_operator(self.MM)

    def _set_plots(self, plot):
        self.plot = plot
        if self.plot:
            filename, ext = splitext(sys.argv[0])
            self.plotoutdir = filename + '/Plots/'
            self.plotvarm = PlotFenics(self.plotoutdir)
            self.plotvarm.set_varname('m')

    def plotm(self, index):
        if self.plot:   self.plotvarm.plot_vtk(self.m, index)

    def gatherm(self):
        if self.plot:   self.plotvarm.gather_vtkplots()

    # Update param
    def update_Data(self, Data):
        """Update Data member"""
        self.Data = Data
        self.assemble_A()
        self.reset()

    def update_m(self, m):
        """Update values of parameter m"""
        if isinstance(m, np.ndarray):
            self.m.vector()[:] = m
        elif isinstance(m, Function):
            self.m.assign(m)
        elif isinstance(m, float):
            self.m.vector()[:] = m
        elif isinstance(m, int):
            self.m.vector()[:] = float(m)
        else:   raise WrongInstanceError('Format for m not accepted')
        self.assemble_A()
        self.reset()

    def backup_m(self):
        self.mcopy.assign(self.m)

    def restore_m(self):
        self.update_m(self.mcopy)

    def reset(self):
        """Reset U, C and E"""
        self.U = []
        self.C = []
        self.E = []

    def set_solver(self):
        """Reset solver for fwd operator"""
        self.solver = LUSolver()
        self.solver.parameters['reuse_factorization'] = True
        self.solver.set_operator(self.A)

    def addPDEcount(self, increment=1):
        """Increase 'nbPDEsolves' by 'increment'"""
        self.nbPDEsolves += increment

    def resetPDEsolves(self):
        self.nbPDEsolves = 0

    # Additional methods for compatibility with CG solver:
    def init_vector(self, x, dim):
        """Initialize vector x to be compatible with parameter
         Does not work in dolfin 1.3.0"""
        self.MM.init_vector(x, 0)

    def init_vector130(self):
        """Initialize vector x to be compatible with parameter"""
        return Vector(Function(self.mcopy.function_space()).vector())

    # Abstract methods
    @abc.abstractmethod
    def _wkforma(self): self.a = []

    @abc.abstractmethod
    def _wkformc(self): self.c = []

    @abc.abstractmethod
    def _wkforme(self): self.e = []
Ejemplo n.º 16
0
class BilaplacianPrior(GaussianPrior):
    """Gaussian prior
    Parameters must be a dictionary containing:
        gamma = multiplicative factor applied to <Grad u, Grad v> term
        beta = multiplicative factor applied to <u,v> term (default=0.0)
        m0 = mean (or reference parameter when used as regularization)
        Vm = function space for parameter
    cost = 1/2 * (m-m0)^T.R.(m-m0)"""
    def _assemble(self):
        # Get input:
        self.gamma = self.Parameters['gamma']
        if self.Parameters.has_key('beta'): self.beta = self.Parameters['beta']
        else: self.beta = 0.0
        self.Vm = self.Parameters['Vm']
        if self.Parameters.has_key('m0'):
            self.m0 = self.Parameters['m0'].copy(deepcopy=True)
            isFunction(self.m0)
        else:
            self.m0 = Function(self.Vm)
        self.mtrial = TrialFunction(self.Vm)
        self.mtest = TestFunction(self.Vm)
        self.mysample = Function(self.Vm)
        self.draw = Function(self.Vm)
        # Assemble:
        self.R = assemble(inner(nabla_grad(self.mtrial), \
        nabla_grad(self.mtest))*dx)
        self.M = PETScMatrix()
        assemble(inner(self.mtrial, self.mtest) * dx, tensor=self.M)
        # preconditioner is Gamma^{-1}:
        if self.beta > 1e-16:
            self.precond = self.gamma * self.R + self.beta * self.M
        else:
            self.precond = self.gamma * self.R + (1e-14) * self.M
        # Discrete operator K:
        self.K = self.gamma * self.R + self.beta * self.M
        # Get eigenvalues for M:
        self.eigsolM = SLEPcEigenSolver(self.M)
        self.eigsolM.solve()
        # Solver for M^{-1}:
        self.solverM = LUSolver()
        self.solverM.parameters['reuse_factorization'] = True
        self.solverM.parameters['symmetric'] = True
        self.solverM.set_operator(self.M)
        # Solver for K^{-1}:
        self.solverK = LUSolver()
        self.solverK.parameters['reuse_factorization'] = True
        self.solverK.parameters['symmetric'] = True
        self.solverK.set_operator(self.K)

    def Minvpriordot(self, vect):
        """Here M.Gamma^{-1} = K M^{-1} K"""
        mhat = Function(self.Vm)
        self.solverM.solve(mhat.vector(), self.K * vect)
        return self.K * mhat.vector()

    def apply_sqrtM(self, vect):
        """Compute M^{1/2}.vect from Vector() vect"""
        sqrtMv = Function(self.Vm)
        for ii in range(self.Vm.dim()):
            r, c, rx, cx = self.eigsolM.get_eigenpair(ii)
            RX = Vector(rx)
            sqrtMv.vector().axpy(
                np.sqrt(r) * np.dot(rx.array(), vect.array()), RX)
        return sqrtMv.vector()

    def Ldot(self, vect):
        """Here L = K^{-1} M^{1/2}"""
        Lb = Function(self.Vm)
        self.solverK.solve(Lb.vector(), self.apply_sqrtM(vect))
        return Lb.vector()
Ejemplo n.º 17
0
class ObjectiveAcoustic(LinearOperator):
    """
    Computes data misfit, gradient and Hessian evaluation for the seismic
    inverse problem using acoustic wave data
    """
    #TODO: add support for multiple sources

    # CONSTRUCTORS:
    def __init__(self, acousticwavePDE, regularization=None):
        """ 
        Input:
            acousticwavePDE should be an instantiation from class AcousticWave
        """
        self.PDE = acousticwavePDE
        self.PDE.exact = None
        self.fwdsource = self.PDE.ftime
        self.MG = Function(self.PDE.Vl)
        self.MGv = self.MG.vector()
        self.Grad = Function(self.PDE.Vl)
        self.Gradv = self.Grad.vector()
        self.srchdir = Function(self.PDE.Vl)
        self.delta_m = Function(self.PDE.Vl)
        LinearOperator.__init__(self, self.MG.vector(), self.MG.vector())
        self.obsop = None   # Observation operator
        self.dd = None  # observations
        if regularization == None:  self.regularization = ZeroRegularization()
        else:   self.regularization = regularization
        self.alpha_reg = 1.0
        # gradient
        self.lamtest, self.lamtrial = TestFunction(self.PDE.Vl), TrialFunction(self.PDE.Vl)
        self.p, self.v = Function(self.PDE.V), Function(self.PDE.V)
        self.wkformgrad = inner(self.lamtest*nabla_grad(self.p), nabla_grad(self.v))*dx
        # incremental rhs
        self.lamhat = Function(self.PDE.Vl)
        self.ptrial, self.ptest = TrialFunction(self.PDE.V), TestFunction(self.PDE.V)
        self.wkformrhsincr = inner(self.lamhat*nabla_grad(self.ptrial), nabla_grad(self.ptest))*dx
        # Hessian
        self.phat, self.vhat = Function(self.PDE.V), Function(self.PDE.V)
        self.wkformhess = inner(self.lamtest*nabla_grad(self.phat), nabla_grad(self.v))*dx \
        + inner(self.lamtest*nabla_grad(self.p), nabla_grad(self.vhat))*dx
        # Mass matrix:
        weak_m =  inner(self.lamtrial,self.lamtest)*dx
        Mass = assemble(weak_m)
        self.solverM = LUSolver()
        self.solverM.parameters['reuse_factorization'] = True
        self.solverM.parameters['symmetric'] = True
        self.solverM.set_operator(Mass)
        # Time-integration factors
        self.factors = np.ones(self.PDE.times.size)
        self.factors[0], self.factors[-1] = 0.5, 0.5
        self.factors *= self.PDE.Dt
        self.invDt = 1./self.PDE.Dt
        # Absorbing BCs
        if self.PDE.abc:
            #TODO: should probably be tested in other situations
            if self.PDE.lumpD:
                print '*** Warning: Damping matrix D is lumped. ',\
                'Make sure gradient is consistent.'
            self.vD, self.pD, self.p1D, self.p2D = Function(self.PDE.V), \
            Function(self.PDE.V), Function(self.PDE.V), Function(self.PDE.V)
            self.wkformgradD = inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\
            *self.pD, self.vD*self.lamtest)*self.PDE.ds(1)
            self.wkformDprime = inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\
            *self.lamhat*self.ptrial, self.ptest)*self.PDE.ds(1)
            self.dp, self.dph, self.vhatD = Function(self.PDE.V), \
            Function(self.PDE.V), Function(self.PDE.V)
            self.p1hatD, self.p2hatD = Function(self.PDE.V), Function(self.PDE.V)
            self.wkformhessD = inner(-0.25*sqrt(self.PDE.rho)/(self.PDE.lam*sqrt(self.PDE.lam))\
            *self.lamhat*self.dp, self.vD*self.lamtest)*self.PDE.ds(1) \
            + inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\
            *self.dph, self.vD*self.lamtest)*self.PDE.ds(1)\
            + inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\
            *self.dp, self.vhatD*self.lamtest)*self.PDE.ds(1)


    def copy(self):
        """(hard) copy constructor"""
        newobj = self.__class__(self.PDE.copy())
        setfct(newobj.MG, self.MG)
        setfct(newobj.srchdir, self.srchdir)
        newobj.obsop = self.obsop
        return newobj


    # FORWARD PROBLEM + COST:
    def solvefwd(self, cost=False):
        self.PDE.set_fwd()
        self.PDE.ftime = self.fwdsource
        self.solfwd,_ = self.PDE.solve()
        # observations:
        self.Bp = np.zeros((len(self.obsop.PtwiseObs.Points),len(self.solfwd)))
        for index, sol in enumerate(self.solfwd):
            setfct(self.p, sol[0])
            self.Bp[:,index] = self.obsop.obs(self.p)
        if cost:
            assert not self.dd == None, "Provide observations"
            self.misfit = self.obsop.costfct(self.Bp, self.dd, self.PDE.times)
            self.cost_reg = self.regularization.cost(self.PDE.lam)
            self.cost = self.misfit + self.alpha_reg*self.cost_reg

    def solvefwd_cost(self):    self.solvefwd(True)


    # ADJOINT PROBLEM + GRAD:
    #@profile
    def solveadj(self, grad=False):
        self.PDE.set_adj()
        self.obsop.assemble_rhsadj(self.Bp, self.dd, self.PDE.times, self.PDE.bc)
        self.PDE.ftime = self.obsop.ftimeadj
        self.soladj,_ = self.PDE.solve()
        if grad:
            self.MGv.zero()
            if self.PDE.abc:
                self.vD.vector().zero(); self.pD.vector().zero();
                self.p1D.vector().zero(); self.p2D.vector().zero();
            index = 0
            for fwd, adj, fact in \
            zip(self.solfwd, reversed(self.soladj), self.factors):
                ttf, tta = fwd[1], adj[1]
                assert isequal(ttf, tta, 1e-16), \
                'tfwd={}, tadj={}, reldiff={}'.format(ttf, tta, abs(ttf-tta)/ttf)
                setfct(self.p, fwd[0])
                setfct(self.v, adj[0])
                self.MGv.axpy(fact, assemble(self.wkformgrad))
#                self.MGv.axpy(fact, assemble(self.wkformgrad, \
#                form_compiler_parameters={'optimize':True,\
#                'representation':'quadrature'}))
                if self.PDE.abc:
                    if index%2 == 0:
                        self.p2D.vector().axpy(1.0, self.p.vector())
                        setfct(self.pD, self.p2D)
                        #self.MGv.axpy(1.0*0.5*self.invDt, assemble(self.wkformgradD))
                        self.MGv.axpy(fact*0.5*self.invDt, assemble(self.wkformgradD))
                        setfct(self.p2D, -1.0*self.p.vector())
                        setfct(self.vD, self.v)
                    else:
                        self.p1D.vector().axpy(1.0, self.p.vector())
                        setfct(self.pD, self.p1D)
                        #self.MGv.axpy(1.0*0.5*self.invDt, assemble(self.wkformgradD))
                        self.MGv.axpy(fact*0.5*self.invDt, assemble(self.wkformgradD))
                        setfct(self.p1D, -1.0*self.p.vector())
                        setfct(self.vD, self.v)
                index += 1
            self.MGv.axpy(self.alpha_reg, self.regularization.grad(self.PDE.lam))
            self.solverM.solve(self.Gradv, self.MGv)

    def solveadj_constructgrad(self):   self.solveadj(True)


    # HESSIAN:
    def ftimeincrfwd(self, tt):
        """ Compute rhs for incremental forward at time tt """
        try:
            index = int(np.where(isequal(self.PDE.times, tt, 1e-14))[0])
        except:
            print 'Error in ftimeincrfwd at time {}'.format(tt)
            print np.min(np.abs(self.PDE.times-tt))
            sys.exit(0)
        # lamhat * grad(p).grad(vtilde)
        assert isequal(tt, self.solfwd[index][1], 1e-16)
        setfct(self.p, self.solfwd[index][0])
        setfct(self.v, self.C*self.p.vector())
        # D'.dot(p)
        if self.PDE.abc and index > 0:
                setfct(self.p, \
                self.solfwd[index+1][0] - self.solfwd[index-1][0])
                self.v.vector().axpy(.5*self.invDt, self.Dp*self.p.vector())
        return -1.0*self.v.vector().array()

    def ftimeincradj(self, tt):
        """ Compute rhs for incremental adjoint at time tt """
        try:
            indexf = int(np.where(isequal(self.PDE.times, tt, 1e-14))[0])
            indexa = int(np.where(isequal(self.PDE.times[::-1], tt, 1e-14))[0])
        except:
            print 'Error in ftimeincradj at time {}'.format(tt)
            print np.min(np.abs(self.PDE.times-tt))
            sys.exit(0)
        # lamhat * grad(ptilde).grad(v)
        assert isequal(tt, self.soladj[indexa][1], 1e-16)
        setfct(self.v, self.soladj[indexa][0])
        setfct(self.vhat, self.C*self.v.vector())
        # B* B phat
        assert isequal(tt, self.solincrfwd[indexf][1], 1e-16)
        setfct(self.phat, self.solincrfwd[indexf][0])
        self.vhat.vector().axpy(1.0, self.obsop.incradj(self.phat, tt))
        # D'.dot(v)
        if self.PDE.abc and indexa > 0:
                setfct(self.v, \
                self.soladj[indexa-1][0] - self.soladj[indexa+1][0])
                self.vhat.vector().axpy(-.5*self.invDt, self.Dp*self.v.vector())
        return -1.0*self.vhat.vector().array()
        
    def mult(self, lamhat, y):
        """
        mult(self, lamhat, y): return y = Hessian * lamhat
        inputs:
            y, lamhat = Function(V).vector()
        """
        self.regularization.assemble_hessian(lamhat)
        setfct(self.lamhat, lamhat)
        self.C = assemble(self.wkformrhsincr)
        if self.PDE.abc:    self.Dp = assemble(self.wkformDprime)
        # solve for phat
        self.PDE.set_fwd()
        self.PDE.ftime = self.ftimeincrfwd
        self.solincrfwd,_ = self.PDE.solve()
        # solve for vhat
        self.PDE.set_adj()
        self.PDE.ftime = self.ftimeincradj
        self.solincradj,_ = self.PDE.solve()
        # Compute Hessian*lamhat
        y.zero()
        index = 0
        if self.PDE.abc:
            self.vD.vector().zero(); self.vhatD.vector().zero(); 
            self.p1D.vector().zero(); self.p2D.vector().zero();
            self.p1hatD.vector().zero(); self.p2hatD.vector().zero();
        for fwd, adj, incrfwd, incradj, fact in \
        zip(self.solfwd, reversed(self.soladj), \
        self.solincrfwd, reversed(self.solincradj), self.factors):
            ttf, tta, ttf2 = incrfwd[1], incradj[1], fwd[1]
            assert isequal(ttf, tta, 1e-16), 'tfwd={}, tadj={}, reldiff={}'.\
            format(ttf, tta, abs(ttf-tta)/ttf)
            assert isequal(ttf, ttf2, 1e-16), 'tfwd={}, tadj={}, reldiff={}'.\
            format(ttf, ttf2, abs(ttf-ttf2)/ttf)
            setfct(self.p, fwd[0])
            setfct(self.v, adj[0])
            setfct(self.phat, incrfwd[0])
            setfct(self.vhat, incradj[0])
            y.axpy(fact, assemble(self.wkformhess))
            if self.PDE.abc:
                if index%2 == 0:
                    self.p2D.vector().axpy(1.0, self.p.vector())
                    self.p2hatD.vector().axpy(1.0, self.phat.vector())
                    setfct(self.dp, self.p2D)
                    setfct(self.dph, self.p2hatD)
                    y.axpy(1.0*0.5*self.invDt, assemble(self.wkformhessD))
                    setfct(self.p2D, -1.0*self.p.vector())
                    setfct(self.p2hatD, -1.0*self.phat.vector())
                else:
                    self.p1D.vector().axpy(1.0, self.p.vector())
                    self.p1hatD.vector().axpy(1.0, self.phat.vector())
                    setfct(self.dp, self.p1D)
                    setfct(self.dph, self.p1hatD)
                    y.axpy(1.0*0.5*self.invDt, assemble(self.wkformhessD))
                    setfct(self.p1D, -1.0*self.p.vector())
                    setfct(self.p1hatD, -1.0*self.phat.vector())
                setfct(self.vD, self.v)
                setfct(self.vhatD, self.vhat)
            index += 1
        # add regularization term
        y.axpy(self.alpha_reg, self.regularization.hessian(lamhat))


    # SETTERS + UPDATE:
    def update_PDE(self, parameters): self.PDE.update(parameters)
    def update_m(self, lam):    self.update_PDE({'lambda':lam})
    def set_abc(self, mesh, class_bc_abc, lumpD):  
        self.PDE.set_abc(mesh, class_bc_abc, lumpD)
    def backup_m(self): self.lam_bkup = self.getmarray()
    def restore_m(self):    self.update_m(self.lam_bkup)
    def setsrcterm(self, ftime):    self.PDE.ftime = ftime


    # GETTERS:
    def getmcopyarray(self):    return self.lam_bkup
    def getmarray(self):    return self.PDE.lam.vector().array()
    def getMGarray(self):   return self.MGv.array()
Ejemplo n.º 18
0
 def __init__(self, acousticwavePDE, regularization=None):
     """ 
     Input:
         acousticwavePDE should be an instantiation from class AcousticWave
     """
     self.PDE = acousticwavePDE
     self.PDE.exact = None
     self.fwdsource = self.PDE.ftime
     self.MG = Function(self.PDE.Vl)
     self.MGv = self.MG.vector()
     self.Grad = Function(self.PDE.Vl)
     self.Gradv = self.Grad.vector()
     self.srchdir = Function(self.PDE.Vl)
     self.delta_m = Function(self.PDE.Vl)
     LinearOperator.__init__(self, self.MG.vector(), self.MG.vector())
     self.obsop = None   # Observation operator
     self.dd = None  # observations
     if regularization == None:  self.regularization = ZeroRegularization()
     else:   self.regularization = regularization
     self.alpha_reg = 1.0
     # gradient
     self.lamtest, self.lamtrial = TestFunction(self.PDE.Vl), TrialFunction(self.PDE.Vl)
     self.p, self.v = Function(self.PDE.V), Function(self.PDE.V)
     self.wkformgrad = inner(self.lamtest*nabla_grad(self.p), nabla_grad(self.v))*dx
     # incremental rhs
     self.lamhat = Function(self.PDE.Vl)
     self.ptrial, self.ptest = TrialFunction(self.PDE.V), TestFunction(self.PDE.V)
     self.wkformrhsincr = inner(self.lamhat*nabla_grad(self.ptrial), nabla_grad(self.ptest))*dx
     # Hessian
     self.phat, self.vhat = Function(self.PDE.V), Function(self.PDE.V)
     self.wkformhess = inner(self.lamtest*nabla_grad(self.phat), nabla_grad(self.v))*dx \
     + inner(self.lamtest*nabla_grad(self.p), nabla_grad(self.vhat))*dx
     # Mass matrix:
     weak_m =  inner(self.lamtrial,self.lamtest)*dx
     Mass = assemble(weak_m)
     self.solverM = LUSolver()
     self.solverM.parameters['reuse_factorization'] = True
     self.solverM.parameters['symmetric'] = True
     self.solverM.set_operator(Mass)
     # Time-integration factors
     self.factors = np.ones(self.PDE.times.size)
     self.factors[0], self.factors[-1] = 0.5, 0.5
     self.factors *= self.PDE.Dt
     self.invDt = 1./self.PDE.Dt
     # Absorbing BCs
     if self.PDE.abc:
         #TODO: should probably be tested in other situations
         if self.PDE.lumpD:
             print '*** Warning: Damping matrix D is lumped. ',\
             'Make sure gradient is consistent.'
         self.vD, self.pD, self.p1D, self.p2D = Function(self.PDE.V), \
         Function(self.PDE.V), Function(self.PDE.V), Function(self.PDE.V)
         self.wkformgradD = inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\
         *self.pD, self.vD*self.lamtest)*self.PDE.ds(1)
         self.wkformDprime = inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\
         *self.lamhat*self.ptrial, self.ptest)*self.PDE.ds(1)
         self.dp, self.dph, self.vhatD = Function(self.PDE.V), \
         Function(self.PDE.V), Function(self.PDE.V)
         self.p1hatD, self.p2hatD = Function(self.PDE.V), Function(self.PDE.V)
         self.wkformhessD = inner(-0.25*sqrt(self.PDE.rho)/(self.PDE.lam*sqrt(self.PDE.lam))\
         *self.lamhat*self.dp, self.vD*self.lamtest)*self.PDE.ds(1) \
         + inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\
         *self.dph, self.vD*self.lamtest)*self.PDE.ds(1)\
         + inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\
         *self.dp, self.vhatD*self.lamtest)*self.PDE.ds(1)
Ejemplo n.º 19
0
 def _assemble_solverM(self, Vm):
     self.MM = assemble(inner(self.mtrial, self.mtest)*dx)
     self.solverM = LUSolver()
     self.solverM.parameters['reuse_factorization'] = True
     self.solverM.parameters['symmetric'] = True
     self.solverM.set_operator(self.MM)
Ejemplo n.º 20
0
 def set_solver(self):
     """Reset solver for fwd operator"""
     self.solver = LUSolver()
     self.solver.parameters['reuse_factorization'] = True
     self.solver.set_operator(self.A)
Ejemplo n.º 21
0
class BilaplacianPrior(GaussianPrior):
    """Gaussian prior
    Parameters must be a dictionary containing:
        gamma = multiplicative factor applied to <Grad u, Grad v> term
        beta = multiplicative factor applied to <u,v> term (default=0.0)
        m0 = mean (or reference parameter when used as regularization)
        Vm = function space for parameter
    cost = 1/2 * (m-m0)^T.R.(m-m0)"""
    def _assemble(self):
        # Get input:
        self.gamma = self.Parameters['gamma']
        if self.Parameters.has_key('beta'): self.beta = self.Parameters['beta']
        else:   self.beta = 0.0
        self.Vm = self.Parameters['Vm']
        if self.Parameters.has_key('m0'):   
            self.m0 = self.Parameters['m0'].copy(deepcopy=True)
            isFunction(self.m0)
        else:   self.m0 = Function(self.Vm)
        self.mtrial = TrialFunction(self.Vm)
        self.mtest = TestFunction(self.Vm)
        self.mysample = Function(self.Vm)
        self.draw = Function(self.Vm)
        # Assemble:
        self.R = assemble(inner(nabla_grad(self.mtrial), \
        nabla_grad(self.mtest))*dx)
        self.M = PETScMatrix()
        assemble(inner(self.mtrial, self.mtest)*dx, tensor=self.M)
        # preconditioner is Gamma^{-1}:
        if self.beta > 1e-16: self.precond = self.gamma*self.R + self.beta*self.M
        else:   self.precond = self.gamma*self.R + (1e-14)*self.M
        # Discrete operator K:
        self.K = self.gamma*self.R + self.beta*self.M
        # Get eigenvalues for M:
        self.eigsolM = SLEPcEigenSolver(self.M)
        self.eigsolM.solve()
        # Solver for M^{-1}:
        self.solverM = LUSolver()
        self.solverM.parameters['reuse_factorization'] = True
        self.solverM.parameters['symmetric'] = True
        self.solverM.set_operator(self.M)
        # Solver for K^{-1}:
        self.solverK = LUSolver()
        self.solverK.parameters['reuse_factorization'] = True
        self.solverK.parameters['symmetric'] = True
        self.solverK.set_operator(self.K)

    def Minvpriordot(self, vect):
        """Here M.Gamma^{-1} = K M^{-1} K"""
        mhat = Function(self.Vm)
        self.solverM.solve(mhat.vector(), self.K*vect)
        return self.K * mhat.vector()

    def apply_sqrtM(self, vect):
        """Compute M^{1/2}.vect from Vector() vect"""
        sqrtMv = Function(self.Vm)
        for ii in range(self.Vm.dim()):
            r, c, rx, cx = self.eigsolM.get_eigenpair(ii)
            RX = Vector(rx)
            sqrtMv.vector().axpy(np.sqrt(r)*np.dot(rx.array(), vect.array()), RX)
        return sqrtMv.vector()

    def Ldot(self, vect):   
        """Here L = K^{-1} M^{1/2}"""
        Lb = Function(self.Vm)
        self.solverK.solve(Lb.vector(), self.apply_sqrtM(vect))
        return Lb.vector()
Ejemplo n.º 22
0
def main(module_name, ncases, params, petsc_params):
    '''
    Run the test case in module with ncases. Optionally store results
    in savedir. For some modules there are multiple (which) choices of 
    preconditioners.
    '''

    # Unpack
    for k, v in params.items():
        exec(k + '=v', locals())

    RED = '\033[1;37;31m%s\033[0m'
    print RED % ('\tRunning %s' % module_name)

    module = __import__(module_name)  # no importlib in python2.7

    # Setup the MMS case
    u_true, rhs_data = module.setup_mms(eps)

    # Setup the convergence monitor
    if log:
        params = [('solver', solver), ('precond', str(precond)),
                  ('eps', str(eps))]

        path = '_'.join([module_name] + ['%s=%s' % pv for pv in params])
        path = os.path.join(save_dir if save_dir else '.', path)
        path = '.'.join([path, 'txt'])
    else:
        path = ''

    memory, residuals = [], []
    monitor = module.setup_error_monitor(u_true, memory, path=path)

    # Sometimes it is usedful to transform the solution before computing
    # the error. e.g. consider subdomains
    if hasattr(module, 'setup_transform'):
        # NOTE: transform take two args for case and the current computed
        # solution
        transform = module.setup_transform
    else:
        transform = lambda i, x: x

    print '=' * 79
    print '\t\t\tProblem eps = %g' % eps
    print '=' * 79
    for i in ncases:
        a, L, W = module.setup_problem(i, rhs_data, eps=eps)

        # Assemble blocks
        t = Timer('assembly')
        t.start()
        AA, bb = map(ii_assemble, (a, L))
        print '\tAssembled blocks in %g s' % t.stop()

        wh = ii_Function(W)

        if solver == 'direct':
            # Turn into a (monolithic) PETScMatrix/Vector
            t = Timer('conversion')
            t.start()
            AAm, bbm = map(ii_convert, (AA, bb))
            print '\tConversion to PETScMatrix/Vector took %g s' % t.stop()

            t = Timer('solve')
            t.start()
            LUSolver('umfpack').solve(AAm, wh.vector(), bbm)
            print '\tSolver took %g s' % t.stop()

            niters = 1
        else:
            # Here we define a Krylov solver using PETSc
            BB = module.setup_preconditioner(W, precond, eps=eps)
            ## AA and BB as block_mat
            ksp = PETSc.KSP().create()

            # Default is minres
            if '-ksp_type' not in petsc_params:
                petsc_params['-ksp_type'] = 'minres'

            opts = PETSc.Options()
            for key, value in petsc_params.iteritems():
                opts.setValue(key, None if value == 'none' else value)

            ksp.setOperators(ii_PETScOperator(AA))

            ksp.setNormType(PETSc.KSP.NormType.NORM_PRECONDITIONED)
            # ksp.setTolerances(rtol=1E-6, atol=None, divtol=None, max_it=300)
            ksp.setConvergenceHistory()
            # We attach the wrapped preconditioner defined by the module
            ksp.setPC(ii_PETScPreconditioner(BB, ksp))

            ksp.setFromOptions()

            print ksp.getTolerances()

            # Want the iterations to start from random
            wh.block_vec().randomize()
            # Solve, note the past object must be PETSc.Vec
            t = Timer('solve')
            t.start()
            ksp.solve(as_petsc_nest(bb), wh.petsc_vec())
            print '\tSolver took %g s' % t.stop()

            niters = ksp.getIterationNumber()

            residuals.append(ksp.getConvergenceHistory())

        # Let's check the final size of the residual
        r_norm = (bb - AA * wh.block_vec()).norm()

        # Convergence?
        monitor.send((transform(i, wh), niters, r_norm))

    # Only send the final
    if save_dir:
        path = os.path.join(save_dir, module_name)
        for i, wh_i in enumerate(wh):
            # Renaming to make it easier to save state in Visit/Pareview
            wh_i.rename('u', str(i))

            File('%s_%d.pvd' % (path, i)) << wh_i

    # Plot relative residual norm
    if plot:
        plt.figure()
        [
            plt.semilogy(res / res[0], label=str(i))
            for i, res in enumerate(residuals, 1)
        ]
        plt.legend(loc='best')
        plt.show()
Ejemplo n.º 23
0
class TestLumpedMass(unittest.TestCase):

    def setUp(self):
        mesh = UnitSquareMesh(5, 5, 'crossed')
        self.V = FunctionSpace(mesh, 'Lagrange', 5)
        self.u = Function(self.V)
        self.uM = Function(self.V)
        self.uMdiag = Function(self.V)
        test = TestFunction(self.V)
        trial = TrialFunction(self.V)
        m = test*trial*dx
        self.M = assemble(m)
        self.solver = LUSolver()
        self.solver.parameters['reuse_factorization'] = True
        self.solver.parameters['symmetric'] = True
        self.solver.set_operator(self.M)
        self.ones = np.ones(self.V.dim())
        

    def test00(self):
        """ Create a lumped solver """
        myobj = LumpedMatrixSolver(self.V)

    def test01_set(self):
        """ Set operator """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)

    def test01_entries(self):
        """ Lump matrix """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for index, ii in enumerate(self.M.array()):
            err += abs(ii.sum() - myobj.Mdiag[index])
        self.assertTrue(err < index*1e-16)


    def test02(self):
        """ Invert lumped matrix """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for ii in range(len(myobj.Mdiag.array())):
            err += abs(1./myobj.Mdiag[ii] - myobj.invMdiag[ii])
        self.assertTrue(err < ii*1e-16)


    def test03_basic(self):
        """ solve """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        myobj.solve(self.uMdiag.vector(), myobj.Mdiag)
        diff = (myobj.one - self.uMdiag.vector()).array()
        self.assertTrue(np.linalg.norm(diff)/np.linalg.norm(myobj.one.array()) < 1e-14)


    def test04_mult(self):
        """ overloaded * operator """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        self.uMdiag.vector().axpy(1.0, myobj*myobj.one)
        diff = (myobj.Mdiag - self.uMdiag.vector()).array()
        self.assertTrue(np.linalg.norm(diff)/np.linalg.norm(myobj.Mdiag.array()) < 1e-14)


    def test10(self):
        """ Create a lumped solver """
        myobj = LumpedMatrixSolverS(self.V)

    def test11_set(self):
        """ Set operator """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)

    def test11_entries(self):
        """ Lump matrix """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        Msum = np.dot(self.ones, self.M.array().dot(self.ones))
        err = abs(myobj.Mdiag.array().dot(self.ones) - \
        Msum) / Msum
        self.assertTrue(err < 1e-14, err)


    def test12(self):
        """ Invert lumped matrix """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for ii in range(len(myobj.Mdiag.array())):
            err += abs(1./myobj.Mdiag[ii] - myobj.invMdiag[ii])
        self.assertTrue(err < ii*1e-16)


    def test13_basic(self):
        """ solve """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        myobj.solve(self.uMdiag.vector(), myobj.Mdiag)
        diff = myobj.one.array() - self.uMdiag.vector().array()
        self.assertTrue(np.linalg.norm(diff)/np.linalg.norm(myobj.one.array()) < 1e-14)


    def test14_mult(self):
        """ overloaded * operator """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        self.uMdiag.vector().axpy(1.0, myobj*myobj.one)
        diff = (myobj.Mdiag - self.uMdiag.vector()).array()
        self.assertTrue(np.linalg.norm(diff)/np.linalg.norm(myobj.Mdiag.array()) < 1e-14)
Ejemplo n.º 24
0
class TestLumpedMass(unittest.TestCase):
    def setUp(self):
        mesh = UnitSquareMesh(5, 5, 'crossed')
        self.V = FunctionSpace(mesh, 'Lagrange', 5)
        self.u = Function(self.V)
        self.uM = Function(self.V)
        self.uMdiag = Function(self.V)
        test = TestFunction(self.V)
        trial = TrialFunction(self.V)
        m = test * trial * dx
        self.M = assemble(m)
        self.solver = LUSolver()
        self.solver.parameters['reuse_factorization'] = True
        self.solver.parameters['symmetric'] = True
        self.solver.set_operator(self.M)
        self.ones = np.ones(self.V.dim())

    def test00(self):
        """ Create a lumped solver """
        myobj = LumpedMatrixSolver(self.V)

    def test01_set(self):
        """ Set operator """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)

    def test01_entries(self):
        """ Lump matrix """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for index, ii in enumerate(self.M.array()):
            err += abs(ii.sum() - myobj.Mdiag[index])
        self.assertTrue(err < index * 1e-16)

    def test02(self):
        """ Invert lumped matrix """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for ii in range(len(myobj.Mdiag.array())):
            err += abs(1. / myobj.Mdiag[ii] - myobj.invMdiag[ii])
        self.assertTrue(err < ii * 1e-16)

    def test03_basic(self):
        """ solve """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        myobj.solve(self.uMdiag.vector(), myobj.Mdiag)
        diff = (myobj.one - self.uMdiag.vector()).array()
        self.assertTrue(
            np.linalg.norm(diff) / np.linalg.norm(myobj.one.array()) < 1e-14)

    def test04_mult(self):
        """ overloaded * operator """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        self.uMdiag.vector().axpy(1.0, myobj * myobj.one)
        diff = (myobj.Mdiag - self.uMdiag.vector()).array()
        self.assertTrue(
            np.linalg.norm(diff) / np.linalg.norm(myobj.Mdiag.array()) < 1e-14)

    def test10(self):
        """ Create a lumped solver """
        myobj = LumpedMatrixSolverS(self.V)

    def test11_set(self):
        """ Set operator """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)

    def test11_entries(self):
        """ Lump matrix """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        Msum = np.dot(self.ones, self.M.array().dot(self.ones))
        err = abs(myobj.Mdiag.array().dot(self.ones) - \
        Msum) / Msum
        self.assertTrue(err < 1e-14, err)

    def test12(self):
        """ Invert lumped matrix """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for ii in range(len(myobj.Mdiag.array())):
            err += abs(1. / myobj.Mdiag[ii] - myobj.invMdiag[ii])
        self.assertTrue(err < ii * 1e-16)

    def test13_basic(self):
        """ solve """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        myobj.solve(self.uMdiag.vector(), myobj.Mdiag)
        diff = myobj.one.array() - self.uMdiag.vector().array()
        self.assertTrue(
            np.linalg.norm(diff) / np.linalg.norm(myobj.one.array()) < 1e-14)

    def test14_mult(self):
        """ overloaded * operator """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        self.uMdiag.vector().axpy(1.0, myobj * myobj.one)
        diff = (myobj.Mdiag - self.uMdiag.vector()).array()
        self.assertTrue(
            np.linalg.norm(diff) / np.linalg.norm(myobj.Mdiag.array()) < 1e-14)
Ejemplo n.º 25
0
    def solve_alpha_M_beta_F(self, alpha, beta, b, t):
        """Solve  :code:`alpha * M * u + beta * F(u, t) = b`  with Dirichlet
        conditions.
        """
        matrix = alpha * self.M + beta * self.A

        # See above for float conversion
        right_hand_side = -float(beta) * self.b.copy()
        if b:
            right_hand_side += b

        for bc in self.dirichlet_bcs:
            bc.apply(matrix, right_hand_side)

        # TODO proper preconditioner for convection
        if self.convection:
            # Use HYPRE-Euclid instead of ILU for parallel computation.
            # However, this PC sometimes fails.
            # solver = KrylovSolver('gmres', 'hypre_euclid')
            # Fallback:
            solver = LUSolver()
        else:
            solver = KrylovSolver("gmres", "hypre_amg")
            solver.parameters["relative_tolerance"] = 1.0e-13
            solver.parameters["absolute_tolerance"] = 0.0
            solver.parameters["maximum_iterations"] = 100
            solver.parameters["monitor_convergence"] = True

        solver.set_operator(matrix)

        u = Function(self.Q)
        solver.solve(u.vector(), right_hand_side)
        return u