def CheckResidual(self, residual): self.iterations += 1 self.residuals.append(residual) if len(self.residuals) == 1: if self.tol is None: self._final_residual = self.atol else: self._final_residual = residual * self.tol if self.atol is not None: self._final_residual = max(self._final_residual, self.atol) else: if self.callback is not None: self.callback(self.iterations, residual) if self.callback_sol is not None: self.callback_sol(self.sol) if self.residuals[0] != 0: logerrstop = log(self._final_residual) logerrfirst = log(self.residuals[0]) _SetThreadPercentage(100. * max(self.iterations / self.maxiter, (log(residual) - logerrfirst) / (logerrstop - logerrfirst))) if self.printrates: print("{} iteration {}, residual = {}".format( self.name, self.iterations, residual), end="\n" if isinstance(self.printrates, bool) else self.printrates) if self.iterations == self.maxiter and residual >= self._final_residual: print("WARNING: {} did not converge to TOL".format(self.name)) is_converged = self.iterations == self.maxiter or residual < self._final_residual if is_converged and self.printrates == "\r": print("{} {}converged in {} iterations to residual {}".format( self.name, "NOT " if residual >= self._final_residual else "", self.iterations, residual)) return is_converged
def Solve(self, rhs: BaseVector, sol: Optional[BaseVector] = None, initialize: bool = True) -> BaseVector: old_status = _GetStatus() _PushStatus(self.name + " Solve") _SetThreadPercentage(0) if sol is None: sol = rhs.CreateVector() initialize = True if initialize: sol[:] = 0 self.sol = sol self._SolveImpl(rhs=rhs, sol=sol) if old_status[0] != "idle": _PushStatus(old_status[0]) _SetThreadPercentage(old_status[1]) return sol
def Solve(self, rhs: BaseVector, sol: Optional[BaseVector] = None, initialize: bool = True) -> None: old_status = _GetStatus() _PushStatus("CG Solve") _SetThreadPercentage(0) self.sol = sol if sol is not None else self.mat.CreateRowVector() d, w, s = self._tmp_vecs u, mat, pre, conjugate, tol, maxsteps, callback = self.sol, self.mat, self.pre, self.conjugate, \ self.tol, self.maxsteps, self.callback if initialize: u[:] = 0 d.data = rhs - mat * u w.data = pre * d if pre else d s.data = w wdn = w.InnerProduct(d, conjugate=conjugate) err0 = sqrt(abs(wdn)) self.errors = [err0] if wdn == err0: return u lwstart = log(err0) errstop = err0 * tol if self.abstol is not None: errstop = max(errstop, self.abstol) logerrstop = log(errstop) for it in range(maxsteps): self.iterations = it + 1 w.data = mat * s wd = wdn as_s = s.InnerProduct(w, conjugate=conjugate) alpha = wd / as_s u.data += alpha * s d.data += (-alpha) * w w.data = pre * d if pre else d wdn = w.InnerProduct(d, conjugate=conjugate) beta = wdn / wd s *= beta s.data += w err = sqrt(abs(wd)) self.errors.append(err) self.logger.info("iteration " + str(it) + " error = " + str(err)) if callback is not None: callback(it, err) _SetThreadPercentage( 100. * max(it / maxsteps, (log(err) - lwstart) / (logerrstop - lwstart))) if err < errstop: break else: self.logger.warning("CG did not converge to tol") if old_status[0] != "idle": _PushStatus(old_status[0]) _SetThreadPercentage(old_status[1])