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)