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)
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)
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)
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])
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))
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])
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)