11 #ifndef OOPS_ASSIMILATION_GMRESR_H_
12 #define OOPS_ASSIMILATION_GMRESR_H_
17 #include "oops/util/dot_product.h"
18 #include "oops/util/formats.h"
19 #include "oops/util/Logger.h"
62 template <
typename VECTOR,
typename AMATRIX,
typename PMATRIX>
63 double GMRESR(VECTOR & xx,
const VECTOR & bb,
64 const AMATRIX & A,
const PMATRIX & precond,
65 const int maxiter,
const double tolerance) {
66 const double stagthresh = 1.0e-3;
67 const double smallres = 1.0e-6;
69 std::vector<VECTOR> cvecs;
70 std::vector<VECTOR> zvecs;
78 double normReduction = 1.0;
79 double rrnorm = sqrt(dot_product(rr, rr));
80 double cdotr = rrnorm;
81 const double rrnorm0 = rrnorm;
83 if (rrnorm > smallres) {
84 Log::info() << std::endl;
85 for (
int jiter = 0; jiter < maxiter; ++jiter) {
86 Log::info() <<
" GMRESR Starting Iteration " << jiter+1 << std::endl;
89 if (std::abs(cdotr) < stagthresh*rrnorm) {
90 Log::info() <<
"GMRESR stagnated. Doing an LSQR step." << std::endl;
93 precond.multiply(rr, zz);
98 for (
int jj = 0; jj < jiter; ++jj) {
99 double alpha = -dot_product(cvecs[jj], cc);
100 cc.axpy(alpha, cvecs[jj]);
101 zz.axpy(alpha, zvecs[jj]);
104 double ccnorm = sqrt(dot_product(cc, cc));
106 cvecs[jiter] *= 1.0/ccnorm;
108 zvecs[jiter] *= 1.0/ccnorm;
110 cdotr = dot_product(cvecs[jiter], rr);
111 rr.axpy(-cdotr, cvecs[jiter]);
112 xx.axpy(cdotr, zvecs[jiter]);
114 rrnorm = sqrt(dot_product(rr, rr));
115 normReduction = rrnorm/rrnorm0;
116 Log::info() <<
"GMRESR end of iteration " << jiter+1 <<
". Norm reduction= "
117 << util::full_precision(normReduction) << std::endl << std::endl;
119 if (normReduction < tolerance) {
120 Log::info() <<
"GMRESR: Achieved required reduction in residual norm." << std::endl;
126 return normReduction;
131 #endif // OOPS_ASSIMILATION_GMRESR_H_