Esempio n. 1
0
    def solve(self):
        dm = self.snes.getDM()
        dm.setAppCtx(weakref.proxy(self._ctx))
        dm.setCreateMatrix(self._ctx.create_matrix)

        # Apply the boundary conditions to the initial guess.
        for bc in self._problem.bcs:
            bc.apply(self._problem.u)

        # User might have updated parameters dict before calling
        # solve, ensure these are passed through to the snes.
        solving_utils.update_parameters(self, self.snes)

        with self._problem.u.dat.vec as v:
            self.snes.solve(None, v)

        solving_utils.check_snes_convergence(self.snes)
Esempio n. 2
0
    def __init__(self, *args, **kwargs):
        """
        :arg problem: A :class:`LinearVariationalProblem` to solve.
        :kwarg solver_parameters: Solver parameters to pass to PETSc.
            This should be a dict mapping PETSc options to values.
        :kwarg nullspace: an optional :class:`.VectorSpaceBasis` (or
               :class:`.MixedVectorSpaceBasis`) spanning the null
               space of the operator.
        :kwarg options_prefix: an optional prefix used to distinguish
               PETSc options.  If not provided a unique prefix will be
               created.  Use this option if you want to pass options
               to the solver from the command line in addition to
               through the :data:`solver_parameters` dict.
        """
        super(LinearVariationalSolver, self).__init__(*args, **kwargs)

        self.parameters.setdefault('snes_type', 'ksponly')
        self.parameters.setdefault('ksp_rtol', 1.0e-7)
        solving_utils.update_parameters(self, self.snes)
Esempio n. 3
0
    def __init__(self, *args, **kwargs):
        """
        :arg problem: A :class:`LinearVariationalProblem` to solve.
        :kwarg solver_parameters: Solver parameters to pass to PETSc.
            This should be a dict mapping PETSc options to values.
        :kwarg nullspace: an optional :class:`.VectorSpaceBasis` (or
               :class:`.MixedVectorSpaceBasis`) spanning the null
               space of the operator.

        .. warning ::

            Since this object contains a circular reference and a
            custom ``__del__`` attribute, you *must* call :meth:`.destroy`
            on it when you are done, otherwise it will never be
            garbage collected.
        """
        super(LinearVariationalSolver, self).__init__(*args, **kwargs)

        self.parameters.setdefault('snes_type', 'ksponly')
        self.parameters.setdefault('ksp_rtol', 1.0e-7)
        solving_utils.update_parameters(self, self.snes)
Esempio n. 4
0
    def solve(self, x, b):
        if len(self._W) > 1 and self.nullspace is not None:
            self.nullspace._apply(self._W.dof_dset.field_ises)
        # User may have updated parameters
        solving_utils.update_parameters(self, self.ksp)
        if self.A.has_bcs:
            b_bc = self._b
            # rhs = b - action(A, zero_function_with_bcs_applied)
            b_bc.assign(b - self._Abcs)
            # Now we need to apply the boundary conditions to the "RHS"
            for bc in self.A.bcs:
                bc.apply(b_bc)
            # don't want to write into b itself, because that would confuse user
            b = b_bc
        with b.dat.vec_ro as rhs:
            with x.dat.vec as solution:
                self.ksp.solve(rhs, solution)

        r = self.ksp.getConvergedReason()
        if r < 0:
            raise RuntimeError("LinearSolver failed to converge after %d iterations with reason: %s", self.ksp.getIterationNumber(), solving_utils.KSPReasons[r])
Esempio n. 5
0
    def solve(self):
        # Apply the boundary conditions to the initial guess.
        for bc in self._problem.bcs:
            bc.apply(self._problem.u_ufl)

        # User might have updated parameters dict before calling
        # solve, ensure these are passed through to the snes.
        solving_utils.update_parameters(self, self.snes)

        with self._problem.u_ufl.dat.vec as v:
            self.snes.solve(None, v)

        reasons = self.snes.ConvergedReason()
        reasons = dict([(getattr(reasons, r), r)
                        for r in dir(reasons) if not r.startswith('_')])
        r = self.snes.getConvergedReason()
        try:
            reason = reasons[r]
            inner = False
        except KeyError:
            kspreasons = self.snes.getKSP().ConvergedReason()
            kspreasons = dict([(getattr(kspreasons, kr), kr)
                               for kr in dir(kspreasons) if not kr.startswith('_')])
            r = self.snes.getKSP().getConvergedReason()
            try:
                reason = kspreasons[r]
                inner = True
            except KeyError:
                reason = 'unknown reason (petsc4py enum incomplete?)'
        if r < 0:
            if inner:
                msg = "Inner linear solve failed to converge after %d iterations with reason: %s" % \
                      (self.snes.getKSP().getIterationNumber(), reason)
            else:
                msg = reason
            raise RuntimeError("""Nonlinear solve failed to converge after %d nonlinear iterations.
Reason:
   %s""" % (self.snes.getIterationNumber(), msg))
Esempio n. 6
0
    def solve(self, x, b):
        # User may have updated parameters
        solving_utils.update_parameters(self, self.ksp)
        if self.A.has_bcs:
            b_bc = function.Function(b.function_space())
            for bc in self.A.bcs:
                bc.apply(b_bc)
            # rhs = b - action(A, b_bc)
            b_bc.assign(b - self.A._form_action(b_bc))
            # Now we need to apply the boundary conditions to the "RHS"
            for bc in self.A.bcs:
                bc.apply(b_bc)
            # don't want to write into b itself, because that would confuse user
            b = b_bc
        with b.dat.vec_ro as rhs:
            with x.dat.vec as solution:
                self.ksp.solve(rhs, solution)

        r = self.ksp.getConvergedReason()
        if r < 0:
            reasons = self.ksp.ConvergedReason()
            reasons = dict([(getattr(reasons, reason), reason)
                            for reason in dir(reasons) if not reason.startswith('_')])
            raise RuntimeError("LinearSolver failed to converge after %d iterations with reason: %s", self.ksp.getIterationNumber(), reasons[r])
Esempio n. 7
0
 def parameters(self, val):
     assert isinstance(val, dict), 'Must pass a dict to set parameters'
     self._parameters = val
     solving_utils.update_parameters(self, self.snes)