FV3 Bundle
DRGMRESRMinimizer.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2009-2016 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation nor
8  * does it submit to any jurisdiction.
9  */
10 
11 #ifndef OOPS_ASSIMILATION_DRGMRESRMINIMIZER_H_
12 #define OOPS_ASSIMILATION_DRGMRESRMINIMIZER_H_
13 
14 #include <cmath>
15 #include <string>
16 #include <vector>
17 
24 #include "oops/util/dot_product.h"
25 #include "oops/util/formats.h"
26 #include "oops/util/Logger.h"
27 
28 namespace oops {
29 
30 /// Derber-Rosati GMRESR Minimizer
31 /*!
32  * \brief Derber-Rosati GMRESR solver for Ax=b.
33  *
34  * DRGMRESR solver for Ax=b. This is a "double" version of GMRESR
35  * (H.A. Van der Vorst and C. Vuik, 1994, Numerical Linear Algebra with
36  * Applications, 1(4), 369-386) following Derber and Rosati (J. Derber and
37  * A. Rosati, 1989, J. Phys. Oceanog. 1333-1347).
38  * It solves Ax=b for the particular case \f$ A=B^{-1}+C\f$, without
39  * requiring the application of \f$ B^{-1}\f$. A must be square, but need
40  * not be symmetric. (For a symmetric matrix, and constant preconditioner,
41  * DRGMRESR is simply Derber-Rosati PCG with full orthogonalisation.)
42  * A preconditioner must be supplied that, given a vector q, returns an
43  * approximate solution of \f$ (AB)^{-1} q\f$. The preconditioner can be
44  * variable. Note that the traditional \f$ B\f$-preconditioning corresponds
45  * to precond=\f$I\f$.
46  *
47  * On entry:
48  * - x = starting point, \f$ X_0 \f$.
49  * - xh = \f$ B^{-1} x_0\f$.
50  * - B = \f$ B \f$.
51  * - C = \f$ C \f$.
52  * - precond = preconditioner matrix \f$ F_k \approx (AB)^{-1} \f$.
53  *
54  * On exit, x will contain the solution \f$ x \f$ and xh will contain
55  * \f$ B^{-1} x\f$.
56  *
57  * Matrices must implement a method:
58  * - void multiply(const VECTOR&, VECTOR&) const
59  *
60  * which applies the matrix to the first argument, and returns the
61  * matrix-vector product in the second. (Note: the const is optional, but
62  * recommended.)
63  *
64  * Iteration will stop if the maximum iteration limit "maxiter" is reached
65  * or if the residual norm reduces by a factor of "tolerance".
66  *
67  * The return value is the achieved reduction in residual norm.
68  */
69 
70 // -----------------------------------------------------------------------------
71 
72 template<typename MODEL> class DRGMRESRMinimizer : public DRMinimizer<MODEL> {
77 
78  public:
79  const std::string classname() const override {return "DRGMRESRMinimizer";}
80  DRGMRESRMinimizer(const eckit::Configuration &, const CostFct_ & J): DRMinimizer<MODEL>(J) {}
82  private:
83  double solve(CtrlInc_ &, CtrlInc_ &, CtrlInc_ &, const Bmat_ &, const HtRinvH_ &,
84  const double, const double, const int, const double) override;
85 };
86 
87 // =============================================================================
88 
89 template<typename MODEL>
91  const Bmat_ & B, const HtRinvH_ & HtRinvH,
92  const double costJ0Jb, const double costJ0JoJc,
93  const int maxiter, const double tolerance) {
95  std::vector<CtrlInc_> c;
96  std::vector<CtrlInc_> u;
97  std::vector<CtrlInc_> uh;
98  CtrlInc_ cc(xh);
99  CtrlInc_ zz(xh);
100  CtrlInc_ zh(xh);
101 
102  double dotRr0 = dot_product(rr, rr);
103  double normReduction = 1.0;
104 
105  Log::info() << std::endl;
106  for (int jiter = 0; jiter < maxiter; ++jiter) {
107  Log::info() << " DRGMRESR Starting Iteration " << jiter+1 << std::endl;
108 
109  precond.multiply(rr, zh); // returns zh as approxmate solve of (BA)zh = r
110  B.multiply(zh, zz); // x=B zh
111  HtRinvH.multiply(zz, cc);
112  cc += zh; // cc = zh+Cz = Az
113 
114  for (int jj = 0; jj < jiter; ++jj) {
115  double alpha = -dot_product(c[jj], cc);
116  cc.axpy(alpha, c[jj]); // cc = cc - <c[jj],cc>*c[jj];
117  zz.axpy(alpha, u[jj]); // zz = zz - <c[jj],cc>*u[jj];
118  zh.axpy(alpha, uh[jj]); // zh = zh - <c[jj],cc>*uh[jj];
119  }
120 
121  double ccnorm = sqrt(dot_product(cc, cc));
122  c.push_back(cc); // c[jiter]=cc
123  c[jiter] *= 1.0/ccnorm;
124  u.push_back(zz); // u[jiter]=z
125  u[jiter] *= 1.0/ccnorm;
126  uh.push_back(zh); // uh[jiter]=zh
127  uh[jiter] *= 1.0/ccnorm;
128 
129  double cdotr = dot_product(c[jiter], rr);
130  xx.axpy(cdotr, u[jiter]);
131  xh.axpy(cdotr, uh[jiter]);
132  rr.axpy(-cdotr, c[jiter]);
133 
134  normReduction = sqrt(dot_product(rr, rr)/dotRr0);
135  Log::info() << "DRGMRESR end of iteration " << jiter+1 << ". Norm reduction= "
136  << util::full_precision(normReduction) << std::endl << std::endl;
137 
138  if (normReduction < tolerance) {
139  Log::info() << "DRGMRESR: Achieved required reduction in residual norm." << std::endl;
140  break;
141  }
142  }
143  return normReduction;
144 }
145 
146 // -----------------------------------------------------------------------------
147 
148 } // namespace oops
149 
150 #endif // OOPS_ASSIMILATION_DRGMRESRMINIMIZER_H_
const std::string classname() const override
real, dimension(:,:,:), allocatable zh
HtRinvHMatrix< MODEL > HtRinvH_
Cost Function.
Definition: CostFunction.h:56
double solve(CtrlInc_ &, CtrlInc_ &, CtrlInc_ &, const Bmat_ &, const HtRinvH_ &, const double, const double, const int, const double) override
The namespace for the main oops code.
void multiply(const CtrlInc_ &dx, CtrlInc_ &dz) const
Definition: HtRinvHMatrix.h:64
subroutine, public info(self)
ControlIncrement< MODEL > CtrlInc_
real(fp), parameter, public tolerance
CostFunction< MODEL > CostFct_
The matrix.
Definition: BMatrix.h:27
void multiply(const VECTOR &a, VECTOR &b) const
Identity matrix.
Derber-Rosati GMRESR Minimizer.
DRGMRESRMinimizer(const eckit::Configuration &, const CostFct_ &J)
DR (Derber and Rosati) Minimizers.
Definition: DRMinimizer.h:44
void axpy(const double, const ControlIncrement &)
void multiply(const CtrlInc_ &x, CtrlInc_ &bx) const
Definition: BMatrix.h:33