FV3 Bundle
RPCGMinimizer.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_RPCGMINIMIZER_H_
12 #define OOPS_ASSIMILATION_RPCGMINIMIZER_H_
13 
14 #include <string>
15 #include <vector>
16 
23 #include "oops/util/dot_product.h"
24 #include "oops/util/formats.h"
25 #include "oops/util/Logger.h"
26 
27 namespace oops {
28 
29 /// RPCG Minimizer
30 /*!
31  * \brief Augmented Restricted Preconditioned Conjugate Gradients.
32  *
33  * This solver is based on the algorithm proposed in Gratton and Tshimanga,
34  * QJRMS, 135: 1573-1585 (2009). It performs minimization in observation space.
35  *
36  * It solves the linear system \f$ (I + R^{-1}HBH^T) lambda = H^T R^{-1}d \f$
37  * with \f$ HBH^T \f$ inner-product in the augmented observation space.
38  *
39  * Note that the traditional \f$ B\f$-preconditioning in model space
40  * corresponds to \f$I\f$ for this algorithm.
41  *
42  * A second-level preconditioner, \f$ G \f$, must be symmetric and
43  * positive definite with respect to \f$ HBH^T \f$ inner-product.
44  * Possible preconditioning is detailed in S. Gurol, PhD Manuscript, 2013.
45  *
46  * On entry:
47  * - vv = starting point, \f$ v_0 \f$.
48  * - vvp = starting point augmented part, \f$ vp_0 \f$
49  * - rr = right hand side.
50  * - dy = \f$ H (xb - xk) \f$
51  * - sigma = \f$ (xb - xk)^T B^{-1} (xb - xk)\f$.
52  * - HBHt = \f$ HBH^T \f$.
53  * - Rinv = \f$ R^{-1} \f$.
54  * - G = preconditioner \f$ G \f$.
55  * - Gt = preconditioner transpose \f$ G^T \f$.
56  *
57  * On exit, vv and vvp will contain the solution \f$ lambda = [vv; vp] \f$
58  *
59  * The return value is the achieved reduction in preconditioned residual norm.
60  *
61  * Iteration will stop if the maximum iteration limit "maxiter" is reached
62  * or if the preconditioned residual norm reduces by a factor of "tolerance".
63  */
64 
65 // -----------------------------------------------------------------------------
66 
67 template<typename MODEL> class RPCGMinimizer : public DualMinimizer<MODEL> {
72 
73  public:
74  const std::string classname() const override {return "RPCGMinimizer";}
75  RPCGMinimizer(const eckit::Configuration &, const CostFct_ & J): DualMinimizer<MODEL>(J) {}
77 
78  private:
79  double solve(Dual_ &, double &, Dual_ &, const HBHt_ &, const Rinv_ &,
80  const int &, const double &, Dual_ &, const double &) override;
81 };
82 
83 // =============================================================================
84 
85 template<typename MODEL>
86 double RPCGMinimizer<MODEL>::solve(Dual_ & vv, double & vvp, Dual_ & rr,
87  const HBHt_ & HBHt, const Rinv_ & Rinv,
88  const int & maxiter, const double & tolerance,
89  Dual_ & dy, const double & sigma) {
90  IdentityMatrix<Dual_> precond;
91  IdentityMatrix<Dual_> precondt;
92 
93  Dual_ zz(vv);
94  Dual_ ww(vv);
95  Dual_ pp(vv);
96  Dual_ tt(vv);
97  Dual_ ll(vv);
98  Dual_ qq(vv);
99  Dual_ w(vv);
100  Dual_ v(vv);
101 
102  // augmented part of the vectors
103  double rrp = 1.0;
104  double llp;
105  double wwp;
106  double zzp;
107  double ppp = 0.0;
108  double ttp = 0.0;
109  double qqp;
110  double vp = 1.0;
111  double wp;
112 
113  std::vector<Dual_> vVEC; // required for re-orthogonalization
114  std::vector<Dual_> wVEC; // required for re-orthogonalization
115  std::vector<double> vpVEC;
116  std::vector<double> wpVEC;
117 
118  // llaug = HBHtaug rraug
119  HBHt.multiply(rr, ll);
120  ll.axpy(rrp, dy);
121  llp = dot_product(dy, rr) + sigma*rrp;
122 
123  // wwaug = Gtaug llaug
124  precondt.multiply(ll, ww); // UPDATE WHEN G IS NOT IDENTITY
125  wwp = llp;
126 
127  // zzaug = Gaug rraug
128  precond.multiply(rr, zz); // UPDATE WHEN G IS NOT IDENTITY
129  zzp = rrp;
130 
131  double dotwr = dot_product(rr, ww) + rrp*wwp;
132  double normReduction = 1.0;
133  double dotw0r0 = dotwr;
134  double dotwr_old = 0.0;
135 
136  v = rr;
137  v *= 1/sqrt(dotwr);
138  vp = rrp;
139  vp *= 1/sqrt(dotwr);
140  w = ww;
141  w *= 1/sqrt(dotwr);
142  wp = wwp;
143  wp *= 1/sqrt(dotwr);
144 
145  vVEC.clear();
146  vpVEC.clear();
147  wVEC.clear();
148  wpVEC.clear();
149 
150  vVEC.push_back(v);
151  vpVEC.push_back(vp);
152  wVEC.push_back(w);
153  wpVEC.push_back(wp);
154 
155  Log::info() << std::endl;
156  for (int jiter = 0; jiter < maxiter; ++jiter) {
157  Log::info() << "RPCG Starting Iteration " << jiter+1 << std::endl;
158 
159  if (jiter > 0) {
160  double beta = dotwr/dotwr_old;
161  Log::debug() << "RPCG beta = " << beta << std::endl;
162 
163  pp *= beta;
164  ppp *= beta;
165 
166  tt *= beta;
167  ttp *= beta;
168  }
169 
170  pp += zz;
171  ppp += zzp; // ppaug = zzaug + beta*ppaug
172 
173  tt += ww;
174  ttp += wwp; // ttaug = wwaug + beta*ttaug
175 
176  // (RinvHBHt + I) pp
177  Rinv.multiply(tt, qq);
178  qq += pp;
179  qqp = ppp; // qqaug = ppaug + Rinv_aug ttaug
180 
181  double alpha = dotwr/(dot_product(qq, tt) + qqp * ttp);
182  Log::debug() << "RPCG alpha = " << alpha << std::endl;
183 
184  vv.axpy(alpha, pp);
185  vvp = vvp + alpha*ppp; // vvaug = vvaug + alpha*ppaug
186 
187  rr.axpy(-alpha, qq);
188  rrp = rrp - alpha*qqp; // rraug = rraug - alpha*qqaug
189 
190  // Re-orthogonalization
191  for (int iiter = 0; iiter < jiter; ++iiter) {
192  double proj = dot_product(rr, wVEC[iiter]) + rrp * wpVEC[iiter];
193  rr.axpy(-proj, vVEC[iiter]);
194  rrp -= proj*vpVEC[iiter];
195  }
196 
197  // llaug = HBHt_aug rraug
198  HBHt.multiply(rr, ll);
199  ll.axpy(rrp, dy);
200  llp = dot_product(dy, rr) + sigma * rrp;
201 
202  // wwaug = Gt_aug llaug
203  precondt.multiply(ll, ww); // UPDATE WHEN G IS NOT IDENTITY
204  wwp = llp;
205 
206  // zzaug = Gaug rraug
207  precond.multiply(rr, zz); // UPDATE WHEN G IS NOT IDENTITY
208  zzp = rrp;
209 
210  dotwr_old = dotwr;
211  dotwr = dot_product(ww, rr) + rrp * wwp;
212 
213  v = rr;
214  v *= 1/sqrt(dotwr);
215  vp = rrp;
216  vp *= 1/sqrt(dotwr);
217  w = ww;
218  w *= 1/sqrt(dotwr);
219  wp = wwp;
220  wp *= 1/sqrt(dotwr);
221 
222  vVEC.push_back(v);
223  vpVEC.push_back(vp);
224  wVEC.push_back(w);
225  wpVEC.push_back(wp);
226 
227  normReduction = sqrt(dotwr/dotw0r0);
228 
229  Log::info() << "RPCG end of iteration " << jiter+1 << ". Norm reduction= "
230  << util::full_precision(normReduction) << std::endl << std::endl;
231 
232  if (normReduction < tolerance) {
233  Log::info() << "RPCG: Achieved required reduction in residual norm." << std::endl;
234  break;
235  }
236  }
237  return normReduction;
238 }
239 
240 // -----------------------------------------------------------------------------
241 
242 } // namespace oops
243 
244 #endif // OOPS_ASSIMILATION_RPCGMINIMIZER_H_
real(fp), parameter ttp
Definition: ufo_aod_mod.F90:28
void multiply(const Dual_ &dx, Dual_ &dy) const
Definition: RinvMatrix.h:36
Container of dual space vectors for all terms of the cost function.
Definition: DualVector.h:34
const std::string classname() const override
Definition: RPCGMinimizer.h:74
Cost Function.
Definition: CostFunction.h:56
integer, parameter sigma
Flags to indicate where climatology pressure levels are pressure or sigma levels. ...
Dual Minimizer.
Definition: DualMinimizer.h:40
The namespace for the main oops code.
RinvMatrix< MODEL > Rinv_
Definition: RPCGMinimizer.h:71
logical debug
Definition: mpp.F90:1297
DualVector< MODEL > Dual_
Definition: RPCGMinimizer.h:69
HBHtMatrix< MODEL > HBHt_
Definition: RPCGMinimizer.h:70
The matrix.
Definition: HBHtMatrix.h:33
double solve(Dual_ &, double &, Dual_ &, const HBHt_ &, const Rinv_ &, const int &, const double &, Dual_ &, const double &) override
Definition: RPCGMinimizer.h:86
subroutine, public info(self)
RPCGMinimizer(const eckit::Configuration &, const CostFct_ &J)
Definition: RPCGMinimizer.h:75
real(fp), parameter, public tolerance
CostFunction< MODEL > CostFct_
Definition: RPCGMinimizer.h:68
void multiply(const VECTOR &a, VECTOR &b) const
Identity matrix.
The matrix.
Definition: RinvMatrix.h:29
void multiply(const Dual_ &dy, Dual_ &dz) const
Definition: HBHtMatrix.h:62
RPCG Minimizer.
Definition: RPCGMinimizer.h:67
void axpy(const double, const DualVector &)
Definition: DualVector.h:213