|
@@ -15,7 +15,7 @@ template <class Real> class ParallelSolver {
|
|
|
|
|
|
ParallelSolver(const Comm& comm = Comm::Self(), bool verbose = true) : comm_(comm), verbose_(verbose) {}
|
|
|
|
|
|
- void operator()(Vector<Real>* x, const ParallelOp& A, const Vector<Real>& b, Real tol, Integer max_iter = -1);
|
|
|
+ void operator()(Vector<Real>* x, const ParallelOp& A, const Vector<Real>& b, Real tol, Integer max_iter = -1, bool use_abs_tol = false);
|
|
|
|
|
|
private:
|
|
|
Comm comm_;
|
|
@@ -62,7 +62,7 @@ template <class Real> int ParallelSolverMatVec(Mat M_, Vec x_, Vec Mx_) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-template <class Real> inline void ParallelSolver<Real>::operator()(Vector<Real>* x, const ParallelOp& A, const Vector<Real>& b, Real tol, Integer max_iter) {
|
|
|
+template <class Real> inline void ParallelSolver<Real>::operator()(Vector<Real>* x, const ParallelOp& A, const Vector<Real>& b, Real tol, Integer max_iter, bool use_abs_tol) {
|
|
|
PetscInt N = b.Dim();
|
|
|
if (max_iter < 0) max_iter = N;
|
|
|
MPI_Comm comm = comm_.GetMPI_Comm();
|
|
@@ -100,7 +100,8 @@ template <class Real> inline void ParallelSolver<Real>::operator()(Vector<Real>*
|
|
|
// Set runtime options
|
|
|
KSPSetType(ksp, KSPGMRES);
|
|
|
KSPSetNormType(ksp, KSP_NORM_UNPRECONDITIONED);
|
|
|
- KSPSetTolerances(ksp, tol, PETSC_DEFAULT, PETSC_DEFAULT, max_iter);
|
|
|
+ if (use_abs_tol) KSPSetTolerances(ksp, PETSC_DEFAULT, tol, PETSC_DEFAULT, max_iter);
|
|
|
+ else KSPSetTolerances(ksp, tol, PETSC_DEFAULT, PETSC_DEFAULT, max_iter);
|
|
|
KSPGMRESSetOrthogonalization(ksp, KSPGMRESModifiedGramSchmidtOrthogonalization);
|
|
|
//if (verbose_) KSPMonitorSet(ksp, KSPMonitorDefault, nullptr, nullptr); // Doesn't work for some versions of PETSc!! WTH!!
|
|
|
KSPGMRESSetRestart(ksp, max_iter);
|
|
@@ -158,7 +159,7 @@ template <class Real> static Real inner_prod(const Vector<Real>& x, const Vector
|
|
|
return x_dot_y_glb;
|
|
|
}
|
|
|
|
|
|
-template <class Real> inline void ParallelSolver<Real>::operator()(Vector<Real>* x, const ParallelOp& A, const Vector<Real>& b, Real tol, Integer max_iter) {
|
|
|
+template <class Real> inline void ParallelSolver<Real>::operator()(Vector<Real>* x, const ParallelOp& A, const Vector<Real>& b, Real tol, Integer max_iter, bool use_abs_tol) {
|
|
|
Long N = b.Dim();
|
|
|
if (max_iter < 0) max_iter = N;
|
|
|
|
|
@@ -181,10 +182,11 @@ template <class Real> inline void ParallelSolver<Real>::operator()(Vector<Real>*
|
|
|
|
|
|
Matrix<Real> H_;
|
|
|
Vector<Real> Aq(N), y, h, r = b;
|
|
|
+ Real abs_tol = tol * (use_abs_tol ? 1 : b_norm);
|
|
|
while (1) {
|
|
|
Real r_norm = sqrt(inner_prod(r, r, comm_));
|
|
|
if (verbose_ && !comm_.Rank()) printf("%3lld KSP Residual norm %.12e\n", (long long)H.Dim(), r_norm);
|
|
|
- if (r_norm < tol * b_norm || H.Dim() == max_iter) break;
|
|
|
+ if (r_norm < abs_tol || H.Dim() == max_iter) break;
|
|
|
|
|
|
A(&Aq, q);
|
|
|
q = Aq;
|