11 #ifndef OOPS_ASSIMILATION_FGMRES_H_ 12 #define OOPS_ASSIMILATION_FGMRES_H_ 20 #include "oops/util/dot_product.h" 21 #include "oops/util/formats.h" 22 #include "oops/util/Logger.h" 67 template <
typename VECTOR,
typename AMATRIX,
typename PMATRIX>
68 double FGMRES(VECTOR & x,
const VECTOR &
b,
69 const AMATRIX & A,
const PMATRIX & precond,
70 const int maxiter,
const double tolerance) {
71 std::vector<VECTOR> V;
72 std::vector<VECTOR> Z;
73 std::vector< std::vector<double> > H;
74 std::vector<double> cs(maxiter+1, 0);
75 std::vector<double> sn(maxiter+1, 0);
76 std::vector<double> s;
77 std::vector<double> y(maxiter+1, 0);
87 double xnrm2 = dot_product(x, x);
93 double bnrm2 = sqrt(dot_product(
b,
b));
94 double rnrm2 = sqrt(dot_product(r, r));
95 double normReduction = rnrm2 / bnrm2;
99 for (
int ii = 0; ii <= maxiter-1; ii++) {
100 H[ii].resize(maxiter + 1);
101 for (
int jj = 0; jj <= maxiter; jj++) {
113 for (jiter = 0; jiter < maxiter; ++jiter) {
114 Log::info() <<
" FGMRES Starting Iteration " << jiter+1 << std::endl;
116 precond.multiply(V[jiter], z);
120 double avnrm2 = sqrt(dot_product(w, w));
123 for (
int jj = 0; jj <= jiter; ++jj) {
124 H[jiter][jj] = dot_product(V[jj], w);
125 w.axpy(-H[jiter][jj], V[jj]);
127 H[jiter][jiter+1] = sqrt(dot_product(w, w));
128 double av2nrm2 = H[jiter][jiter+1];
131 if (avnrm2 + 0.001*av2nrm2 == avnrm2) {
132 for (
int jj = 0; jj <= jiter; ++jj) {
133 double hr = dot_product(V[jj], w);
137 H[jiter][jiter+1] = sqrt(dot_product(w, w));
141 if (H[jiter][jiter+1] != 0) {
142 w *= 1/H[jiter][jiter+1];
148 for (
int jj = 0; jj < jiter; ++jj) {
149 double temp = cs[jj]*H[jiter][jj] + sn[jj]*H[jiter][jj+1];
150 H[jiter][jj+1] = -sn[jj]*H[jiter][jj] + cs[jj]*H[jiter][jj+1];
156 rotmat(H[jiter][jiter], H[jiter][jiter+1], cs[jiter], sn[jiter]);
158 H[jiter][jiter] = cs[jiter]*H[jiter][jiter] + sn[jiter]*H[jiter][jiter+1];
159 H[jiter][jiter+1] = 0.0;
161 double temp = cs[jiter]*s[jiter];
162 s.push_back(-sn[jiter]*s[jiter]);
168 for (
int jj = 0; jj < jiter+1; ++jj) {
169 x.axpy(y[jj], Z[jj]);
172 normReduction = std::abs(s[jiter+1])/bnrm2;
173 Log::info() <<
"FGMRES end of iteration " << jiter+1 <<
". PNorm reduction= " 174 << util::full_precision(normReduction) << std::endl << std::endl;
177 Log::info() <<
"FGMRES: Achieved required reduction in residual norm." << std::endl;
186 for (
int jj = 0; jj < jiter; ++jj) {
187 x.axpy(y[jj], Z[jj]);
190 Log::info() <<
"FGMRES: end" << std::endl;
192 return normReduction;
197 #endif // OOPS_ASSIMILATION_FGMRES_H_ Compute the Givens rotation matrix parameters.
void rotmat(const double &a, const double &b, double &c, double &s)
double FGMRES(VECTOR &x, const VECTOR &b, const AMATRIX &A, const PMATRIX &precond, const int maxiter, const double tolerance)
Solves the upper triangular system sol = H \ rhs.
The namespace for the main oops code.
subroutine, public info(self)
real(fp), parameter, public tolerance
void UpTriSolve(const std::vector< std::vector< double > > &H, const std::vector< double > &rhs, std::vector< double > &sol, const int &dim)