def solve(self, x, b): if not isinstance(x, (function.Function, vector.Vector)): raise TypeError("Provided solution is a '%s', not a Function or Vector" % type(x).__name__) if isinstance(b, vector.Vector): b = b.function if not isinstance(b, function.Function): raise TypeError("Provided RHS is a '%s', not a Function" % type(b).__name__) if len(self.trial_space) > 1 and self.nullspace is not None: self.nullspace._apply(self.trial_space.dof_dset.field_ises) if len(self.test_space) > 1 and self.transpose_nullspace is not None: self.transpose_nullspace._apply(self.test_space.dof_dset.field_ises, transpose=True) if len(self.trial_space) > 1 and self.near_nullspace is not None: self.near_nullspace._apply(self.trial_space.dof_dset.field_ises, near=True) if self.A.has_bcs: b = self._lifted(b) if self.ksp.getInitialGuessNonzero(): acc = x.dat.vec else: acc = x.dat.vec_wo with self.inserted_options(), b.dat.vec_ro as rhs, acc as solution, dmhooks.add_hooks(self.ksp.dm, self): self.ksp.solve(rhs, solution) r = self.ksp.getConvergedReason() if r < 0: raise ConvergenceError("LinearSolver failed to converge after %d iterations with reason: %s", self.ksp.getIterationNumber(), solving_utils.KSPReasons[r])
def solve(self, x, b): if not isinstance(x, (function.Function, vector.Vector)): raise TypeError("Provided solution is a '%s', not a Function or Vector" % type(x).__name__) if not isinstance(b, function.Function): raise TypeError("Provided RHS is a '%s', not a Function" % type(b).__name__) if len(self._W) > 1 and self.nullspace is not None: self.nullspace._apply(self._W.dof_dset.field_ises) if len(self._W) > 1 and self.transpose_nullspace is not None: self.transpose_nullspace._apply(self._W.dof_dset.field_ises, transpose=True) if len(self._W) > 1 and self.near_nullspace is not None: self.near_nullspace._apply(self._W.dof_dset.field_ises, near=True) 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 self.inserted_options(): 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 ConvergenceError("LinearSolver failed to converge after %d iterations with reason: %s", self.ksp.getIterationNumber(), solving_utils.KSPReasons[r])
def check_ts_convergence(ts): r = ts.getConvergedReason() # TODO: submit PR to petsc4py to add the following reasons # TSFORWARD_DIVERGED_LINEAR_SOLVE = -3, # TSADJOINT_DIVERGED_LINEAR_SOLVE = -4 if r == -3: raise ConvergenceError( f"TS solve failed to converge. Reason: TSFORWARD_DIVERGED_LINEAR_SOLVE" ) if r == -4: raise ConvergenceError( f"TS solve failed to converge. Reason: TSADJOINT_DIVERGED_LINEAR_SOLVE" ) reason = TSReasons[r] if r < 0: raise ConvergenceError( f"TS solve failed to converge after {ts.getStepNumber()} iterations. Reason: {reason}" )
def check_snes_convergence(snes): r = snes.getConvergedReason() try: reason = SNESReasons[r] inner = False except KeyError: r = snes.getKSP().getConvergedReason() try: inner = True reason = KSPReasons[r] except KeyError: reason = "unknown reason (petsc4py enum incomplete?), try with -snes_converged_reason and -ksp_converged_reason" if r < 0: if inner: msg = "Inner linear solve failed to converge after %d iterations with reason: %s" % \ (snes.getKSP().getIterationNumber(), reason) else: msg = reason raise ConvergenceError(r"""Nonlinear solve failed to converge after %d nonlinear iterations. Reason: %s""" % (snes.getIterationNumber(), msg))