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)