FV3 Bundle
DRMinimizer.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_DRMINIMIZER_H_
12 #define OOPS_ASSIMILATION_DRMINIMIZER_H_
13 
14 #include <string>
15 #include <vector>
16 
17 #include <boost/scoped_ptr.hpp>
18 
19 #include "eckit/config/Configuration.h"
25 
26 #include "oops/util/dot_product.h"
27 #include "oops/util/formats.h"
28 #include "oops/util/Logger.h"
29 
30 namespace oops {
31 
32 /// DR (Derber and Rosati) Minimizers
33 /*!
34  * DRMinimizer is the base class for all minimizers that use \f$ B\f$ to
35  * precondition the variational minimisation problem and use the auxiliary
36  * variable \f$ \hat{x}=B^{-1}x\f$ and to update it in parallel to \f$ x\f$
37  * based on Derber and Rosati, 1989, J. Phys. Oceanog. 1333-1347.
38  * \f$ J_b\f$ is then computed as \f$ x^T\hat{x}\f$ eliminating the need for
39  * \f$ B^{-1}\f$ or \f$ B^{1/2}\f$.
40  */
41 
42 // -----------------------------------------------------------------------------
43 
44 template<typename MODEL> class DRMinimizer : public Minimizer<MODEL> {
50 
51  public:
52  explicit DRMinimizer(const CostFct_ & J): Minimizer_(J), J_(J), gradJb_(0), costJ0Jb_(0) {}
54  const std::string classname() const override = 0;
55 
56  private:
57  CtrlInc_ * doMinimize(const eckit::Configuration &) override;
58  virtual double solve(CtrlInc_ &, CtrlInc_ &, CtrlInc_ &,
59  const Bmat_ &, const HtRinvH_ &,
60  const double, const double,
61  const int, const double) = 0;
62 
63  const CostFct_ & J_;
64  boost::scoped_ptr<CtrlInc_> gradJb_;
65  std::vector<CtrlInc_> dxh_;
66  double costJ0Jb_;
67 };
68 
69 // =============================================================================
70 
71 template<typename MODEL>
72 ControlIncrement<MODEL> * DRMinimizer<MODEL>::doMinimize(const eckit::Configuration & config) {
73  int ninner = config.getInt("ninner");
74  double gnreduc = config.getDouble("gradient_norm_reduction");
75 
76  bool runOnlineAdjTest = false;
77  if (config.has("onlineDiagnostics")) {
78  const eckit::LocalConfiguration onlineDiag(config, "onlineDiagnostics");
79  runOnlineAdjTest = onlineDiag.getBool("onlineAdjTest");
80  }
81 
82  if (gradJb_ == 0) {
83  gradJb_.reset(new CtrlInc_(J_.jb()));
84  } else {
85  gradJb_.reset(new CtrlInc_(J_.jb().resolution(), *gradJb_));
86  }
87 
88  Log::info() << std::endl;
89  Log::info() << classname() << ": max iter = " << ninner
90  << ", requested norm reduction = " << gnreduc << std::endl;
91 
92 // Define the matrices
93  const Bmat_ B(J_);
94  const HtRinvH_ HtRinvH(J_, runOnlineAdjTest);
95 
96 // Compute RHS (sum B^{-1} dx_{i}) + H^T R^{-1} d
97 // dx_i = x_i - x_{i-1}; dx_1 = x_1 - x_b
98  CtrlInc_ rhs(J_.jb());
99  J_.computeGradientFG(rhs);
100  J_.jb().addGradientFG(rhs, *gradJb_);
101  rhs *= -1.0;
102  Log::info() << classname() << " rhs" << rhs << std::endl;
103 
104 // Define minimisation starting point
105  // dx
106  CtrlInc_ * dx = new CtrlInc_(J_.jb());
107  // dxh = B^{-1} dx
108  CtrlInc_ dxh(J_.jb());
109 
110 // Set J[0] = 0.5 (x_i - x_b)^T B^{-1} (x_i - x_b) + 0.5 d^T R^{-1} d
111  const double costJ0Jb = costJ0Jb_;
112  const double costJ0JoJc = J_.getCostJoJc();
113 
114 // Solve the linear system
115  double reduc = this->solve(*dx, dxh, rhs, B, HtRinvH, costJ0Jb, costJ0JoJc, ninner, gnreduc);
116 
117  Log::test() << classname() << ": reduction in residual norm = " << reduc << std::endl;
118  Log::info() << classname() << " output increment:" << *dx << std::endl;
119 
120 // Update gradient Jb
121  *gradJb_ += dxh;
122  dxh_.push_back(dxh);
123 
124 // Update Jb component of J[0]: 0.5 (x_i - x_b)^T B^-1 (x_i - x_b)
125  costJ0Jb_ += 0.5 * dot_product(*dx, dxh);
126  for (unsigned int jouter = 1; jouter < dxh_.size(); ++jouter) {
127  CtrlInc_ dxhtmp(dx->geometry(), dxh_[jouter-1]);
128  costJ0Jb_ += dot_product(*dx, dxhtmp);
129  }
130 
131  return dx;
132 }
133 
134 // -----------------------------------------------------------------------------
135 
136 } // namespace oops
137 
138 #endif // OOPS_ASSIMILATION_DRMINIMIZER_H_
HtRinvHMatrix< MODEL > HtRinvH_
Definition: DRMinimizer.h:48
const CostFct_ & J_
Definition: DRMinimizer.h:63
Geometry_ geometry() const
Get geometry.
const std::string classname() const override=0
std::vector< CtrlInc_ > dxh_
Definition: DRMinimizer.h:65
Cost Function.
Definition: CostFunction.h:56
ControlIncrement< MODEL > CtrlInc_
Definition: DRMinimizer.h:47
program test
The namespace for the main oops code.
subroutine, public info(self)
Minimizer< MODEL > Minimizer_
Definition: DRMinimizer.h:49
DRMinimizer(const CostFct_ &J)
Definition: DRMinimizer.h:52
virtual double solve(CtrlInc_ &, CtrlInc_ &, CtrlInc_ &, const Bmat_ &, const HtRinvH_ &, const double, const double, const int, const double)=0
The matrix.
Definition: BMatrix.h:27
CtrlInc_ * doMinimize(const eckit::Configuration &) override
Definition: DRMinimizer.h:72
A Minimizer knows how to minimize a cost function.
Definition: Minimizer.h:39
BMatrix< MODEL > Bmat_
Definition: DRMinimizer.h:45
CostFunction< MODEL > CostFct_
Definition: DRMinimizer.h:46
DR (Derber and Rosati) Minimizers.
Definition: DRMinimizer.h:44
boost::scoped_ptr< CtrlInc_ > gradJb_
Definition: DRMinimizer.h:64