OOPS
CostJo.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_COSTJO_H_
12 #define OOPS_ASSIMILATION_COSTJO_H_
13 
14 #include <memory>
15 #include <string>
16 #include <utility>
17 #include <vector>
18 
19 #include <boost/noncopyable.hpp>
20 
21 #include "eckit/config/LocalConfiguration.h"
25 #include "oops/base/Departures.h"
26 #include "oops/base/ObsErrors.h"
27 #include "oops/base/Observations.h"
28 #include "oops/base/Observers.h"
30 #include "oops/base/ObsSpaces.h"
31 #include "oops/base/PostBase.h"
32 #include "oops/base/PostBaseTLAD.h"
33 #include "oops/base/QCData.h"
36 #include "oops/interface/State.h"
37 #include "oops/mpi/mpi.h"
38 #include "oops/util/DateTime.h"
39 #include "oops/util/Logger.h"
40 #include "oops/util/missingValues.h"
41 
42 namespace oops {
43 
44 // -----------------------------------------------------------------------------
45 
46 /// Jo Cost Function
47 /*!
48  * The CostJo class encapsulates the Jo term of the cost function.
49  * The Observers to be called during the model integration is managed
50  * inside the CostJo class.
51  */
52 
53 template<typename MODEL, typename OBS> class CostJo : public CostTermBase<MODEL, OBS>,
54  private boost::noncopyable {
68 
69  public:
70  /// Construct \f$ J_o\f$ from \f$ R\f$ and \f$ y_{obs}\f$.
71  CostJo(const eckit::Configuration &, const eckit::mpi::Comm &,
72  const util::DateTime &, const util::DateTime &,
73  const eckit::mpi::Comm & ctime = oops::mpi::myself());
74 
75  /// Constructor added for generic 1d-var under development in ufo
76  CostJo(const eckit::Configuration &, const util::DateTime &, const util::DateTime &,
77  const ObsSpaces_ &);
78 
79  /// Destructor
80  virtual ~CostJo() {}
81 
82  /// Initialize \f$ J_o\f$ before starting the integration of the model.
83  std::shared_ptr<PostBase<State_> > initialize(const CtrlVar_ &,
84  const eckit::Configuration &) override;
85  std::shared_ptr<PostBaseTLAD_> initializeTraj(const CtrlVar_ &,
86  const Geometry_ &,
87  const eckit::Configuration &) override;
88  /// Finalize \f$ J_o\f$ after the integration of the model.
89  double finalize() override;
90  void finalizeTraj() override;
91 
92  /// Initialize \f$ J_o\f$ before starting the TL run.
93  std::shared_ptr<PostBaseTLAD_> setupTL(const CtrlInc_ &) const override;
94 
95  /// Initialize \f$ J_o\f$ before starting the AD run.
96  std::shared_ptr<PostBaseTLAD_> setupAD(
97  std::shared_ptr<const GeneralizedDepartures>, CtrlInc_ &) const override;
98 
99  /// Multiply by \f$ R\f$ and \f$ R^{-1}\f$.
100  std::unique_ptr<GeneralizedDepartures>
101  multiplyCovar(const GeneralizedDepartures &) const override;
102  std::unique_ptr<GeneralizedDepartures>
103  multiplyCoInv(const GeneralizedDepartures &) const override;
104 
105  /// Provide new departure.
106  std::unique_ptr<GeneralizedDepartures> newDualVector() const override;
107 
108  /// Return gradient at first guess ie \f$ R^{-1} {\cal H}(x^t ) - y\f$.
109  std::unique_ptr<GeneralizedDepartures> newGradientFG() const override;
110 
111  /// Reset obs operator trajectory.
112  void resetLinearization() override;
113 
114  /// Print Jo
115  double printJo(const Departures_ &, const Departures_ &) const;
116  const ObsSpaces_ & obspaces() const {return obspace_;}
117 
118  private:
119  eckit::LocalConfiguration obsconf_;
122  std::unique_ptr<ObsErrors_> Rmat_;
123 
124  /// Configuration for current initialize/finalize pair
125  std::unique_ptr<eckit::LocalConfiguration> currentConf_;
126 
127  /// Gradient at first guess : \f$ R^{-1} (H(x_{fg})-y_{obs}) \f$.
128  std::unique_ptr<Departures_> gradFG_;
129 
130  /// Observers passed by \f$ J_o\f$ to the model during integration.
131  mutable std::shared_ptr<Observers_> pobs_;
132 
133  /// Linearized observation operators.
134  std::shared_ptr<ObserversTLAD_> pobstlad_;
135 
136  /// Storage for QC flags and obs error
138 };
139 
140 // =============================================================================
141 
142 template<typename MODEL, typename OBS>
143 CostJo<MODEL, OBS>::CostJo(const eckit::Configuration & joConf, const eckit::mpi::Comm & comm,
144  const util::DateTime & winbgn, const util::DateTime & winend,
145  const eckit::mpi::Comm & ctime)
146  : obsconf_(joConf), obspace_(obsconf_, comm, winbgn, winend, ctime),
147  yobs_(obspace_, "ObsValue"),
148  Rmat_(), currentConf_(), gradFG_(), pobs_(),
149  pobstlad_(), qc_(obspace_)
150 {
151  Log::trace() << "CostJo::CostJo done" << std::endl;
152 }
153 
154 // =============================================================================
155 /// Constructor added for generic 1d-var under development in ufo
156 template<typename MODEL, typename OBS>
157 CostJo<MODEL, OBS>::CostJo(const eckit::Configuration & joConf,
158  const util::DateTime & winbgn, const util::DateTime & winend,
159  const ObsSpaces_ & localobs)
160  : obsconf_(joConf), obspace_(localobs),
161  yobs_(obspace_, "ObsValue"),
162  Rmat_(), currentConf_(), gradFG_(), pobs_(),
163  pobstlad_(), qc_(obspaces)
164 {
165  Log::trace() << "CostJo::CostJo using local obs spaces done" << std::endl;
166 }
167 
168 // -----------------------------------------------------------------------------
169 
170 template<typename MODEL, typename OBS>
171 std::shared_ptr<PostBase<State<MODEL> > >
172 CostJo<MODEL, OBS>::initialize(const CtrlVar_ & xx, const eckit::Configuration & conf) {
173  Log::trace() << "CostJo::initialize start" << std::endl;
174 
175  currentConf_.reset(new eckit::LocalConfiguration(conf));
176  const int iterout = currentConf_->getInt("iteration");
177  obsconf_.set("iteration", iterout);
178  pobs_.reset(new Observers_(obsconf_, obspace_, xx.obsVar(), qc_));
179  Log::trace() << "CostJo::initialize done" << std::endl;
180  return pobs_;
181 }
182 
183 // -----------------------------------------------------------------------------
184 
185 template<typename MODEL, typename OBS>
187  Log::trace() << "CostJo::finalize start" << std::endl;
188  const Observations_ & yeqv = pobs_->hofx();
189  Log::info() << "Jo Observation Equivalent:" << std::endl << yeqv
190  << "End Jo Observation Equivalent" << std::endl;
191  const int iterout = currentConf_->getInt("iteration");
192 
193 // Sace current QC flags and obs error
194  const std::string obsname = "hofx" + std::to_string(iterout);
195  const std::string qcname = "EffectiveQC" + std::to_string(iterout);
196  const std::string errname = "EffectiveError" + std::to_string(iterout);
197  yeqv.save(obsname);
198  for (size_t jj = 0; jj < obspace_.size(); ++jj) {
199  qc_.obsErrors(jj)->mask(*qc_.qcFlags(jj));
200  qc_.qcFlags(jj)->save(qcname);
201  qc_.obsErrors(jj)->save(errname);
202  qc_.obsErrors(jj)->save("EffectiveError"); // Obs error covariance is looking for that for now
203  }
204 
205 // Set observation error covariance
206  Rmat_.reset(new ObsErrors_(obsconf_, obspace_));
207 
208 // Perturb observations according to obs error statistics
209  bool obspert = currentConf_->getBool("obs perturbations", false);
210  if (obspert) {
211  yobs_.perturb(*Rmat_);
212  Log::info() << "Perturbed observations: " << yobs_ << std::endl;
213  }
214 
215 // Compute departures
216  Departures_ ydep(yeqv - yobs_);
217  Log::info() << "Jo Departures:" << std::endl << ydep << "End Jo Departures" << std::endl;
218 
219 // Apply bias correction
220  Departures_ bias(obspace_, "ObsBias", false);
221  ydep += bias;
222  Log::info() << "Jo Bias Corrected Departures:" << std::endl << ydep
223  << "End Jo Bias Corrected Departures" << std::endl;
224 
225 // Compute Jo
226  if (!gradFG_) {
227  gradFG_.reset(new Departures_(ydep));
228  } else {
229  *gradFG_ = ydep;
230  }
231  Rmat_->inverseMultiply(*gradFG_);
232 
233  double zjo = this->printJo(ydep, *gradFG_);
234 
235  if (currentConf_->has("diagnostics.departures")) {
236  const std::string depname = currentConf_->getString("diagnostics.departures");
237  ydep.save(depname);
238  }
239 
240  pobs_.reset();
241  currentConf_.reset();
242  Log::trace() << "CostJo::finalize done" << std::endl;
243  return zjo;
244 }
245 
246 // -----------------------------------------------------------------------------
247 
248 template<typename MODEL, typename OBS>
249 std::shared_ptr<PostBaseTLAD<MODEL> >
251  const eckit::Configuration & conf) {
252  Log::trace() << "CostJo::initializeTraj start" << std::endl;
253  pobstlad_.reset(new ObserversTLAD_(obsconf_, obspace_, xx.obsVar()));
254  Log::trace() << "CostJo::initializeTraj done" << std::endl;
255  return pobstlad_;
256 }
257 
258 // -----------------------------------------------------------------------------
259 
260 template<typename MODEL, typename OBS>
262  Log::trace() << "CostJo::finalizeTraj done" << std::endl;
263 }
264 
265 // -----------------------------------------------------------------------------
266 
267 template<typename MODEL, typename OBS>
268 std::shared_ptr<PostBaseTLAD<MODEL> > CostJo<MODEL, OBS>::setupTL(const CtrlInc_ & dx) const {
269  Log::trace() << "CostJo::setupTL start" << std::endl;
270  ASSERT(pobstlad_);
271  pobstlad_->setupTL(dx.obsVar());
272  Log::trace() << "CostJo::setupTL done" << std::endl;
273  return pobstlad_;
274 }
275 
276 // -----------------------------------------------------------------------------
277 
278 template<typename MODEL, typename OBS>
279 std::shared_ptr<PostBaseTLAD<MODEL> > CostJo<MODEL, OBS>::setupAD(
280  std::shared_ptr<const GeneralizedDepartures> pv,
281  CtrlInc_ & dx) const {
282  Log::trace() << "CostJo::setupAD start" << std::endl;
283  ASSERT(pobstlad_);
284  std::shared_ptr<const Departures_> dy = std::dynamic_pointer_cast<const Departures_>(pv);
285  pobstlad_->setupAD(dy, dx.obsVar());
286  Log::trace() << "CostJo::setupAD done" << std::endl;
287  return pobstlad_;
288 }
289 
290 // -----------------------------------------------------------------------------
291 
292 template<typename MODEL, typename OBS>
293 std::unique_ptr<GeneralizedDepartures>
295  Log::trace() << "CostJo::multiplyCovar start" << std::endl;
296  std::unique_ptr<Departures_> y1(new Departures_(dynamic_cast<const Departures_ &>(v1)));
297  Rmat_->multiply(*y1);
298  return std::move(y1);
299 }
300 
301 // -----------------------------------------------------------------------------
302 
303 template<typename MODEL, typename OBS>
304 std::unique_ptr<GeneralizedDepartures>
306  Log::trace() << "CostJo::multiplyCoInv start" << std::endl;
307  std::unique_ptr<Departures_> y1(new Departures_(dynamic_cast<const Departures_ &>(v1)));
308  Rmat_->inverseMultiply(*y1);
309  return std::move(y1);
310 }
311 
312 // -----------------------------------------------------------------------------
313 
314 template<typename MODEL, typename OBS>
315 std::unique_ptr<GeneralizedDepartures> CostJo<MODEL, OBS>::newDualVector() const {
316  Log::trace() << "CostJo::newDualVector start" << std::endl;
317  std::unique_ptr<Departures_> ydep(new Departures_(obspace_));
318  ydep->zero();
319  Log::trace() << "CostJo::newDualVector done" << std::endl;
320  return std::move(ydep);
321 }
322 
323 // -----------------------------------------------------------------------------
324 
325 template<typename MODEL, typename OBS>
326 std::unique_ptr<GeneralizedDepartures> CostJo<MODEL, OBS>::newGradientFG() const {
327  return std::unique_ptr<Departures_>(new Departures_(*gradFG_));
328 }
329 
330 // -----------------------------------------------------------------------------
331 
332 template<typename MODEL, typename OBS>
334  Log::trace() << "CostJo::resetLinearization start" << std::endl;
335  pobstlad_.reset();
336  Log::trace() << "CostJo::resetLinearization done" << std::endl;
337 }
338 
339 // -----------------------------------------------------------------------------
340 
341 template<typename MODEL, typename OBS>
342 double CostJo<MODEL, OBS>::printJo(const Departures_ & dy, const Departures_ & grad) const {
343  Log::trace() << "CostJo::printJo start" << std::endl;
344  obspace_.printJo(dy, grad);
345 
346  double zjo = 0.0;
347  for (std::size_t jj = 0; jj < dy.size(); ++jj) {
348  const double zz = 0.5 * dot_product(dy[jj], grad[jj]);
349  const unsigned nobs = grad[jj].nobs();
350  if (nobs > 0) {
351  Log::test() << "CostJo : Nonlinear Jo(" << obspace_[jj].obsname() << ") = "
352  << zz << ", nobs = " << nobs << ", Jo/n = " << zz/nobs
353  << ", err = " << (*Rmat_)[jj].getRMSE() << std::endl;
354  } else {
355  Log::test() << "CostJo : Nonlinear Jo(" << obspace_[jj].obsname() << ") = "
356  << zz << " --- No Observations" << std::endl;
357  Log::warning() << "CostJo: No Observations!!!" << std::endl;
358  }
359  zjo += zz;
360  }
361 
362  Log::trace() << "CostJo::printJo done" << std::endl;
363  return zjo;
364 }
365 
366 // -----------------------------------------------------------------------------
367 
368 } // namespace oops
369 
370 #endif // OOPS_ASSIMILATION_COSTJO_H_
oops::CostJo::Departures_
Departures< OBS > Departures_
Definition: CostJo.h:57
oops
The namespace for the main oops code.
Definition: ErrorCovarianceL95.cc:22
oops::GeneralizedDepartures
Abstract base class for quantities.
Definition: GeneralizedDepartures.h:22
oops::CostJo::initializeTraj
std::shared_ptr< PostBaseTLAD_ > initializeTraj(const CtrlVar_ &, const Geometry_ &, const eckit::Configuration &) override
Definition: CostJo.h:250
oops::QCData
container for QC-related things (flags & obserrors)
Definition: QCData.h:24
oops::CostJo::PostBaseTLAD_
PostBaseTLAD< MODEL > PostBaseTLAD_
Definition: CostJo.h:66
oops::ControlVariable::obsVar
ObsAuxCtrls_ & obsVar()
Get augmented observation control variable.
Definition: ControlVariable.h:77
oops::CostJo::newGradientFG
std::unique_ptr< GeneralizedDepartures > newGradientFG() const override
Return gradient at first guess ie .
Definition: CostJo.h:326
PostBaseTLAD.h
oops::CostJo::Geometry_
Geometry< MODEL > Geometry_
Definition: CostJo.h:59
oops::ControlIncrement::obsVar
ObsAuxIncrs_ & obsVar()
Get augmented observation control variable.
Definition: ControlIncrement.h:94
oops::CostTermBase
Base Class for Cost Function Terms.
Definition: CostTermBase.h:37
oops::CostJo::ObsErrors_
ObsErrors< OBS > ObsErrors_
Definition: CostJo.h:62
oops::CostJo::CtrlInc_
ControlIncrement< MODEL, OBS > CtrlInc_
Definition: CostJo.h:56
oops::CostJo::Rmat_
std::unique_ptr< ObsErrors_ > Rmat_
Definition: CostJo.h:122
oops::PostBaseTLAD
Handles post-processing of model fields related to cost function.
Definition: PostBaseTLAD.h:41
oops::CostJo::initialize
std::shared_ptr< PostBase< State_ > > initialize(const CtrlVar_ &, const eckit::Configuration &) override
Initialize before starting the integration of the model.
Definition: CostJo.h:172
QCData.h
oops::ControlVariable
Control variable.
Definition: ControlVariable.h:41
ObsSpaces.h
oops::CostJo::ObserversTLAD_
ObserversTLAD< MODEL, OBS > ObserversTLAD_
Definition: CostJo.h:65
oops::ObserversTLAD
Computes observation equivalent TL and AD to/from increments.
Definition: ObserversTLAD.h:38
mpi.h
oops::Departures::save
void save(const std::string &) const
Save departures values.
Definition: oops/base/Departures.h:226
oops::CostJo::pobs_
std::shared_ptr< Observers_ > pobs_
Observers passed by to the model during integration.
Definition: CostJo.h:131
oops::CostJo::gradFG_
std::unique_ptr< Departures_ > gradFG_
Gradient at first guess : .
Definition: CostJo.h:128
Observers.h
oops::CostJo::State_
State< MODEL > State_
Definition: CostJo.h:60
oops::CostJo::ObsSpaces_
ObsSpaces< OBS > ObsSpaces_
Definition: CostJo.h:63
oops::ObsErrors
\biref Container for ObsErrors for all observation types that are used in DA
Definition: ObsErrors.h:33
oops::CostJo::CostJo
CostJo(const eckit::Configuration &, const eckit::mpi::Comm &, const util::DateTime &, const util::DateTime &, const eckit::mpi::Comm &ctime=oops::mpi::myself())
Construct from and .
Definition: CostJo.h:143
oops::ControlIncrement
Definition: ControlIncrement.h:46
oops::Observers
Computes observation equivalent during model run.
Definition: Observers.h:37
oops::CostJo::CtrlVar_
ControlVariable< MODEL, OBS > CtrlVar_
Definition: CostJo.h:55
oops::CostJo::newDualVector
std::unique_ptr< GeneralizedDepartures > newDualVector() const override
Provide new departure.
Definition: CostJo.h:315
oops::CostJo::Observers_
Observers< MODEL, OBS > Observers_
Definition: CostJo.h:64
Departures.h
oops::mpi::myself
const eckit::mpi::Comm & myself()
Default communicator with each MPI task by itself.
Definition: oops/mpi/mpi.cc:28
CostTermBase.h
oops::CostJo::finalizeTraj
void finalizeTraj() override
Definition: CostJo.h:261
oops::CostJo::qc_
QCData_ qc_
Storage for QC flags and obs error.
Definition: CostJo.h:137
PostBase.h
oops::CostJo::printJo
double printJo(const Departures_ &, const Departures_ &) const
Print Jo.
Definition: CostJo.h:342
oops::CostJo::multiplyCovar
std::unique_ptr< GeneralizedDepartures > multiplyCovar(const GeneralizedDepartures &) const override
Multiply by and .
Definition: CostJo.h:294
Observations.h
oops::CostJo::setupAD
std::shared_ptr< PostBaseTLAD_ > setupAD(std::shared_ptr< const GeneralizedDepartures >, CtrlInc_ &) const override
Initialize before starting the AD run.
Definition: CostJo.h:279
ObsErrors.h
oops::CostJo::finalize
double finalize() override
Finalize after the integration of the model.
Definition: CostJo.h:186
oops::Departures
Difference between two observation vectors.
Definition: oops/base/Departures.h:44
oops::CostJo::obspace_
ObsSpaces_ obspace_
Definition: CostJo.h:120
oops::CostJo::yobs_
Observations_ yobs_
Definition: CostJo.h:121
oops::Departures::size
size_t size() const
Access.
Definition: oops/base/Departures.h:57
oops::CostJo::obspaces
const ObsSpaces_ & obspaces() const
Definition: CostJo.h:116
oops::CostJo::~CostJo
virtual ~CostJo()
Destructor.
Definition: CostJo.h:80
ObserversTLAD.h
oops::Geometry
Geometry class used in oops; subclass of interface class above.
Definition: oops/interface/Geometry.h:189
oops::Departures::nobs
size_t nobs() const
Return number of departures (excluding departures that are masked out)
Definition: oops/base/Departures.h:198
oops::CostJo::QCData_
QCData< OBS > QCData_
Definition: CostJo.h:67
oops::CostJo::multiplyCoInv
std::unique_ptr< GeneralizedDepartures > multiplyCoInv(const GeneralizedDepartures &) const override
Definition: CostJo.h:305
oops::Observations
Observations Class.
Definition: oops/base/Departures.h:30
oops::CostJo::obsconf_
eckit::LocalConfiguration obsconf_
Definition: CostJo.h:119
oops::State
Encapsulates the model state.
Definition: CostJbState.h:28
oops::CostJo::setupTL
std::shared_ptr< PostBaseTLAD_ > setupTL(const CtrlInc_ &) const override
Initialize before starting the TL run.
Definition: CostJo.h:268
oops::CostJo::resetLinearization
void resetLinearization() override
Reset obs operator trajectory.
Definition: CostJo.h:333
State.h
ControlIncrement.h
oops::CostJo::pobstlad_
std::shared_ptr< ObserversTLAD_ > pobstlad_
Linearized observation operators.
Definition: CostJo.h:134
oops::CostJo::Increment_
Increment< MODEL > Increment_
Definition: CostJo.h:61
oops::ObsSpaces
Definition: ObsSpaces.h:41
oops::Increment
Increment Class: Difference between two states.
Definition: CostJbState.h:27
oops::CostJo::currentConf_
std::unique_ptr< eckit::LocalConfiguration > currentConf_
Configuration for current initialize/finalize pair.
Definition: CostJo.h:125
ControlVariable.h
oops::CostJo
Jo Cost Function.
Definition: CostJo.h:54
oops::CostJo::Observations_
Observations< OBS > Observations_
Definition: CostJo.h:58
Geometry.h
Increment.h
oops::Observations::save
void save(const std::string &) const
Save/read observations values.
Definition: Observations.h:153