11 #ifndef OOPS_ASSIMILATION_FULLGMRES_H_    12 #define OOPS_ASSIMILATION_FULLGMRES_H_    20 #include "oops/util/dot_product.h"    21 #include "oops/util/formats.h"    22 #include "oops/util/Logger.h"    66 template <
typename VECTOR, 
typename AMATRIX, 
typename PMATRIX>
    67 double FullGMRES(VECTOR & xx, 
const VECTOR & 
bb, 
const AMATRIX & A,
    68                  const PMATRIX & precond, 
const int maxiter,
    69                  const double tolerance, std::vector<VECTOR> & pqVEC,
    70                  std::vector<VECTOR> & xyVEC) {
    71   std::vector<VECTOR> VV;
    72   std::vector< std::vector<double> > H;
    73   std::vector<double> cs(maxiter+1, 0);
    74   std::vector<double> sn(maxiter+1, 0);
    75   std::vector<double> ss;
    76   std::vector<double> yy(maxiter+1, 0);
    82   double xnrm2 = dot_product(xx, xx);
    88   precond.multiply(rr, zz);
    90   double znrm2 = sqrt(dot_product(zz, zz));
    91   double normReduction = 1.0;
    99   for (
int ii = 0; ii <= maxiter-1; ii++) {
   100     H[ii].resize(maxiter + 1);
   101     for (
int jj = 0; jj <= maxiter; jj++) {
   112   for (jiter = 0; jiter < maxiter; ++jiter) {
   113     Log::info() << 
" FullGMRES Starting Iteration " << jiter+1 << std::endl;
   115     A.multiply(VV[jiter], zz);
   116     precond.multiply(zz, ww);
   118       xyVEC.push_back(VV[jiter]);
   122     double avnrm2 = sqrt(dot_product(ww, ww));
   125     for (
int jj = 0; jj <= jiter; ++jj) {
   126       H[jiter][jj] = dot_product(VV[jj], ww);
   127       ww.axpy(-H[jiter][jj], VV[jj]);
   130     H[jiter][jiter+1] = sqrt(dot_product(ww, ww));
   132     double av2nrm2 = H[jiter][jiter+1];
   135     if (avnrm2 + 0.001*av2nrm2 == avnrm2) {
   136       for (
int jj = 0; jj <= jiter; ++jj) {
   137         double hr = dot_product(VV[jj], ww);
   139         ww.axpy(-hr, VV[jj]);
   141       H[jiter][jiter+1] = sqrt(dot_product(ww, ww));
   145     if (H[jiter][jiter+1] != 0.0) {
   146       ww *= 1/H[jiter][jiter+1];
   153       for (
int jj = 0; jj < jiter; ++jj) {
   154         double temp = cs[jj]*H[jiter][jj] + sn[jj]*H[jiter][jj+1];
   155         H[jiter][jj+1] = -sn[jj]*H[jiter][jj] + cs[jj]*H[jiter][jj+1];
   161     rotmat(H[jiter][jiter], H[jiter][jiter+1], cs[jiter], sn[jiter]);
   163     H[jiter][jiter]   = cs[jiter]*H[jiter][jiter] + sn[jiter]*H[jiter][jiter+1];
   164     H[jiter][jiter+1] = 0.0;
   166     double temp = cs[jiter]*ss[jiter];
   167     ss.push_back(-sn[jiter]*ss[jiter]);
   170     normReduction = std::abs(ss[jiter+1])/znrm2;
   171     Log::info() << 
"FullGMRES end of iteration " << jiter+1 << 
". PNorm reduction= "   172                 << util::full_precision(normReduction) << std::endl << std::endl;
   175       Log::info() << 
"FullGMRES: Achieved required reduction in presidual norm." << std::endl;
   183   for (
int jj = 0; jj < jiter; ++jj) {
   184     xx.axpy(yy[jj], VV[jj]);
   187   return normReduction;
   192 #endif  // OOPS_ASSIMILATION_FULLGMRES_H_ real, dimension(:,:), allocatable, private bb
 
Compute the Givens rotation matrix parameters. 
 
void rotmat(const double &a, const double &b, double &c, double &s)
 
double FullGMRES(VECTOR &xx, const VECTOR &bb, const AMATRIX &A, const PMATRIX &precond, const int maxiter, const double tolerance, std::vector< VECTOR > &pqVEC, std::vector< VECTOR > &xyVEC)
 
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)