OOPS
ModelSpaceCovarianceBase.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_BASE_MODELSPACECOVARIANCEBASE_H_
12 #define OOPS_BASE_MODELSPACECOVARIANCEBASE_H_
13 
14 #include <map>
15 #include <memory>
16 #include <string>
17 #include <vector>
18 
19 #include <boost/make_unique.hpp>
20 #include <boost/noncopyable.hpp>
21 #include <boost/ptr_container/ptr_vector.hpp>
22 #include <boost/range/adaptor/reversed.hpp>
23 
24 #include "eckit/config/LocalConfiguration.h"
25 #include "eckit/exception/Exceptions.h"
28 #include "oops/base/Variables.h"
31 #include "oops/interface/State.h"
32 #include "oops/util/AssociativeContainers.h"
33 #include "oops/util/Logger.h"
34 #include "oops/util/parameters/ConfigurationParameter.h"
35 #include "oops/util/parameters/HasParameters_.h"
36 #include "oops/util/parameters/OptionalParameter.h"
37 #include "oops/util/parameters/Parameters.h"
38 #include "oops/util/parameters/RequiredPolymorphicParameter.h"
39 
40 namespace util {
41  class DateTime;
42 }
43 
44 namespace oops {
45 
46 // -----------------------------------------------------------------------------
47 
48 // Should this be one with the ErrorCovariance class in the interface directory? YT
49 
50 /// Abstract base class for model space error covariances.
51 ///
52 /// Note: subclasses can opt to extract their settings either from a Configuration object or from a
53 /// subclass of Parameters.
54 ///
55 /// In the former case, they should provide a constructor taking a const reference to an
56 /// eckit::Configuration object. In the latter case, the implementer should first define a subclass
57 /// of Parameters holding the settings of the model-space covariance change in question. The latter
58 /// should then typedef `Parameters_` to the name of that subclass and provide a constructor taking
59 /// a const reference to an instance of that subclass.
60 template <typename MODEL>
66  typedef typename boost::ptr_vector<LinearVariableChangeBase_> ChvarVec_;
67  typedef typename ChvarVec_::iterator iter_;
68  typedef typename ChvarVec_::const_iterator icst_;
69  typedef typename ChvarVec_::const_reverse_iterator ircst_;
70 
71  public:
72  ModelSpaceCovarianceBase(const State_ &, const State_ &,
74  ModelSpaceCovarianceBase(const State_ &, const State_ &,
75  const Geometry_ &, const eckit::Configuration &);
77 
78  void randomize(Increment_ &) const;
79  void multiply(const Increment_ &, Increment_ &) const;
80  void inverseMultiply(const Increment_ &, Increment_ &) const;
81 
82  private:
83  virtual void doRandomize(Increment_ &) const = 0;
84  virtual void doMultiply(const Increment_ &, Increment_ &) const = 0;
85  virtual void doInverseMultiply(const Increment_ &, Increment_ &) const = 0;
86 
88 };
89 
90 // =============================================================================
91 
92 template <typename MODEL>
94 
95 // -----------------------------------------------------------------------------
96 
97 /// \brief A subclass of ModelSpaceCovarianceParametersBase storing the values of all options in a
98 /// single Configuration object.
99 ///
100 /// This object can be accessed by calling the value() method of the \p config member variable.
101 ///
102 /// The ConfigurationParameter class does not perform any parameter validation; models using
103 /// GenericModelSpaceCovarianceParameters should therefore ideally be refactored, replacing this
104 /// class with a dedicated subclass of ModelSpaceCovarianceParametersBase storing each parameter in
105 /// a separate (Optional/Required)Parameter object.
106 ///
107 template <typename MODEL>
109  OOPS_CONCRETE_PARAMETERS(GenericModelSpaceCovarianceParameters,
111  public:
112  ConfigurationParameter config{this};
113 };
114 
115 // -----------------------------------------------------------------------------
116 
117 /// \brief Contains a polymorphic parameter holding an instance of a subclass of
118 /// ModelSpaceCovarianceParametersBase.
119 template <typename MODEL>
120 class ModelSpaceCovarianceParametersWrapper : public Parameters {
121  OOPS_CONCRETE_PARAMETERS(ModelSpaceCovarianceParametersWrapper, Parameters)
122  public:
123  /// After deserialization, holds an instance of a subclass of ModelSpaceCovarianceParametersBase
124  /// controlling the behavior of a covariance model. The type of the subclass is determined by
125  /// the value of the "name" key in the Configuration object from which this object is
126  /// deserialized.
127  RequiredPolymorphicParameter<ModelSpaceCovarianceParametersBase<MODEL>, CovarianceFactory<MODEL>>
128  covarianceParameters{"covariance model", this};
129 };
130 
131 // =============================================================================
132 
133 /// Covariance Factory
134 template <typename MODEL>
135 class CovarianceFactory {
138 
139  public:
140  /// \brief Create and return a new covariance model.
141  ///
142  /// The covariance model is determined by the \c covarianceModel attribute of \p parameters.
143  /// \p parameters must be an instance of the subclass of ModelSpaceCovarianceParametersBase
144  /// associated with that covariance model, otherwise an exception will be thrown.
146  const Geometry_ &, const Variables &,
147  const State_ &, const State_ &);
148 
149  /// \brief Create and return a new covariance model.
150  ///
151  /// Deprecated overload taking a Configuration instead of a ModelSpaceCovarianceParametersBase.
152  static ModelSpaceCovarianceBase<MODEL> * create(const eckit::Configuration &,
153  const Geometry_ &, const Variables &,
154  const State_ &, const State_ &);
155 
156  /// \brief Create and return an instance of the subclass of ModelSpaceCovarianceParametersBase
157  /// storing parameters of the specified covariance model.
158  static std::unique_ptr<ModelSpaceCovarianceParametersBase<MODEL>> createParameters(
159  const std::string &covarianceModel);
160 
161  /// \brief Return the names of all covariance models that can be created by one of the
162  /// registered makers.
163  static std::vector<std::string> getMakerNames() {
164  return keys(getMakers());
165  }
166 
167  virtual ~CovarianceFactory() = default;
168 
169  protected:
170  /// \brief Register a maker able to create covariance models of type \p name.
171  explicit CovarianceFactory(const std::string &name);
172 
173  private:
175  const Geometry_ &, const Variables &,
176  const State_ &, const State_ &) = 0;
177 
178  virtual std::unique_ptr<ModelSpaceCovarianceParametersBase<MODEL>> makeParameters() const = 0;
179 
180  static std::map < std::string, CovarianceFactory<MODEL> * > & getMakers() {
181  static std::map < std::string, CovarianceFactory<MODEL> * > makers_;
182  return makers_;
183  }
184 };
185 
186 // -----------------------------------------------------------------------------
187 
188 template<class MODEL, class COVAR>
189 class CovarMaker : public CovarianceFactory<MODEL> {
190  /// Defined as T::Parameters_ if COVAR defines a Parameters_ type; otherwise as
191  /// GenericModelSpaceCovarianceParameters<MODEL>.
192  typedef TParameters_IfAvailableElseFallbackType_t<
194 
197 
200  const Geometry_ & resol, const Variables & vars,
201  const State_ & xb, const State_ & fg) override {
202  const auto &stronglyTypedParams = dynamic_cast<const Parameters_&>(params);
203  return new COVAR(resol, vars,
204  parametersOrConfiguration<HasParameters_<COVAR>::value>(stronglyTypedParams),
205  xb, fg);
206  }
207 
208  std::unique_ptr<ModelSpaceCovarianceParametersBase<MODEL>> makeParameters() const override {
209  return boost::make_unique<Parameters_>();
210  }
211 
212  public:
213  explicit CovarMaker(const std::string & name) : CovarianceFactory<MODEL>(name) {}
214 };
215 
216 // =============================================================================
217 
218 template <typename MODEL>
220  if (getMakers().find(name) != getMakers().end()) {
221  throw std::runtime_error(name + " already registered in covariance factory.");
222  }
223  getMakers()[name] = this;
224 }
225 
226 // -----------------------------------------------------------------------------
227 
228 template <typename MODEL>
231  const Geometry_ & resol,
232  const Variables & vars,
233  const State_ & xb, const State_ & fg) {
234  const std::string id = parameters.covarianceModel.value().value();
235  Log::trace() << "ModelSpaceCovarianceBase type = " << id << std::endl;
236  typename std::map<std::string, CovarianceFactory<MODEL>*>::iterator jcov = getMakers().find(id);
237  if (jcov == getMakers().end()) {
238  Log::error() << id << " does not exist in CovarianceFactory." << std::endl;
239  Log::error() << "CovarianceFactory has " << getMakers().size() << " elements:" << std::endl;
240  for (typename std::map<std::string, CovarianceFactory<MODEL>*>::const_iterator
241  jj = getMakers().begin(); jj != getMakers().end(); ++jj) {
242  Log::error() << "A " << jj->first << " B" << std::endl;
243  }
244  throw std::runtime_error(id + " does not exist in covariance factory.");
245  }
246  Variables vars_in(vars);
247  Variables vars_out;
248  for (const LinearVariableChangeParametersWrapper<MODEL> &variableChange :
249  boost::adaptors::reverse(parameters.variableChanges.value())) {
250  const LinearVariableChangeParametersBase &variableChangeParameters =
251  variableChange.variableChangeParameters;
252  if (variableChangeParameters.inputVariables.value() != boost::none &&
253  variableChangeParameters.outputVariables.value() != boost::none) {
254  vars_out = *variableChangeParameters.outputVariables.value();
255  if (!(vars_in == vars_out)) {
256  Log::error() << "Input variables: " << vars_in << std::endl;
257  Log::error() << "Output variables: " << vars_out << std::endl;
258  throw eckit::BadParameter("Sequence of variable changes is not consistent");
259  }
260  vars_in = *variableChangeParameters.inputVariables.value();
261  }
262  }
263  return (*jcov).second->make(parameters, resol, vars_in, xb, fg);
264 }
265 
266 // -----------------------------------------------------------------------------
267 
268 template <typename MODEL>
270  const eckit::Configuration & conf,
271  const Geometry_ & resol,
272  const Variables & vars,
273  const State_ & xb, const State_ & fg) {
275  parameters.validateAndDeserialize(conf);
276  return create(parameters.covarianceParameters, resol, vars, xb, fg);
277 }
278 
279 // -----------------------------------------------------------------------------
280 
281 template <typename MODEL>
282 std::unique_ptr<ModelSpaceCovarianceParametersBase<MODEL>>
284  const std::string &name) {
285  typename std::map<std::string, CovarianceFactory<MODEL>*>::iterator it =
286  getMakers().find(name);
287  if (it == getMakers().end()) {
288  throw std::runtime_error(name + " does not exist in CovarianceFactory");
289  }
290  return it->second->makeParameters();
291 }
292 
293 // =============================================================================
294 
295 template <typename MODEL>
297  const State_ & bg, const State_ & fg,
298  const Geometry_ & resol,
299  const ModelSpaceCovarianceParametersBase<MODEL> & parameters) {
300  for (const LinearVariableChangeParametersWrapper<MODEL> &variableChange :
301  parameters.variableChanges.value()) {
303  bg, fg, resol, variableChange.variableChangeParameters));
304  }
305 }
306 
307 // -----------------------------------------------------------------------------
308 
309 template <typename MODEL>
311  const State_ & bg, const State_ & fg,
312  const Geometry_ & resol,
313  const eckit::Configuration & conf)
315  bg, fg, resol, validateAndDeserialize<GenericModelSpaceCovarianceParameters<MODEL>>(conf))
316 {}
317 
318 // -----------------------------------------------------------------------------
319 
320 template <typename MODEL>
322  // TODO(notguillaume): Generalize to non-square change of variable
323  if (chvars_.size()) {
324  this->doRandomize(dx); // dx = C^1/2 dx
325  // K_N K_N-1 ... K_1
326  for (icst_ it = chvars_.begin(); it != chvars_.end(); ++it) {
327  dx = it->multiply(dx); // dx = K_i dx
328  }
329  } else {
330  this->doRandomize(dx);
331  }
332 }
333 
334 // -----------------------------------------------------------------------------
335 
336 template <typename MODEL>
338  Increment_ & dxo) const {
339  if (chvars_.size()) {
340  // K_1^T K_2^T .. K_N^T
341  std::unique_ptr<Increment_> dxchvarin(new Increment_(dxi));
342  for (ircst_ it = chvars_.rbegin(); it != chvars_.rend(); ++it) {
343  Increment_ dxchvarout = it->multiplyAD(*dxchvarin);
344  dxchvarin.reset(new Increment_(dxchvarout));
345  }
346  Increment_ dxchvarout(*dxchvarin, false);
347 
348  this->doMultiply(*dxchvarin, dxchvarout);
349 
350  // K_N K_N-1 ... K_1
351  dxchvarin.reset(new Increment_(dxchvarout));
352  for (icst_ it = chvars_.begin(); it != chvars_.end(); ++it) {
353  Increment_ dxchvarout = it->multiply(*dxchvarin);
354  dxchvarin.reset(new Increment_(dxchvarout));
355  }
356  dxo = *dxchvarin;
357  } else {
358  this->doMultiply(dxi, dxo);
359  }
360 }
361 
362 // -----------------------------------------------------------------------------
363 
364 template <typename MODEL>
366  Increment_ & dxo) const {
367  if (chvars_.size()) {
368  // K_1^{-1} K_2^{-1} .. K_N^{-1}
369  std::unique_ptr<Increment_> dxchvarin(new Increment_(dxi));
370  for (ircst_ it = chvars_.rbegin(); it != chvars_.rend(); ++it) {
371  Increment_ dxchvarout = it->multiplyInverse(*dxchvarin);
372  dxchvarin.reset(new Increment_(dxchvarout));
373  }
374  Increment_ dxchvarout(*dxchvarin, false);
375 
376  this->doInverseMultiply(*dxchvarin, dxchvarout);
377 
378  // K_N^T^{-1} K_N-1^T^{-1} ... K_1^T^{-1}
379  dxchvarin.reset(new Increment_(dxchvarout));
380  for (icst_ it = chvars_.begin(); it != chvars_.end(); ++it) {
381  Increment_ dxchvarout = it->multiplyInverseAD(*dxchvarin);
382  dxchvarin.reset(new Increment_(dxchvarout));
383  }
384  dxo = *dxchvarin;
385  } else {
386  this->doInverseMultiply(dxi, dxo);
387  }
388 }
389 
390 // -----------------------------------------------------------------------------
391 
392 } // namespace oops
393 
394 #endif // OOPS_BASE_MODELSPACECOVARIANCEBASE_H_
oops::ModelSpaceCovarianceBase::ChvarVec_
boost::ptr_vector< LinearVariableChangeBase_ > ChvarVec_
Definition: ModelSpaceCovarianceBase.h:66
oops::GenericModelSpaceCovarianceParameters
A subclass of ModelSpaceCovarianceParametersBase storing the values of all options in a single Config...
Definition: ModelSpaceCovarianceBase.h:108
oops
The namespace for the main oops code.
Definition: ErrorCovarianceL95.cc:22
oops::ModelSpaceCovarianceBase::iter_
ChvarVec_::iterator iter_
Definition: ModelSpaceCovarianceBase.h:67
oops::ModelSpaceCovarianceParametersBase::variableChanges
Parameter< std::vector< LinearVariableChangeParametersWrapper< MODEL > > > variableChanges
Definition: ModelSpaceCovarianceParametersBase.h:38
oops::LinearVariableChangeFactory
LinearVariableChange factory.
Definition: LinearVariableChangeBase.h:85
oops::CovarianceFactory::makeParameters
virtual std::unique_ptr< ModelSpaceCovarianceParametersBase< MODEL > > makeParameters() const =0
oops::CovarianceFactory
Covariance Factory.
Definition: ModelSpaceCovarianceBase.h:93
oops::CovarianceFactory::createParameters
static std::unique_ptr< ModelSpaceCovarianceParametersBase< MODEL > > createParameters(const std::string &covarianceModel)
Create and return an instance of the subclass of ModelSpaceCovarianceParametersBase storing parameter...
Definition: ModelSpaceCovarianceBase.h:283
oops::CovarMaker
Definition: ModelSpaceCovarianceBase.h:189
oops::LinearVariableChangeParametersBase::inputVariables
OptionalParameter< Variables > inputVariables
Definition: LinearVariableChangeParametersBase.h:35
oops::CovarMaker::make
ModelSpaceCovarianceBase< MODEL > * make(const ModelSpaceCovarianceParametersBase< MODEL > &params, const Geometry_ &resol, const Variables &vars, const State_ &xb, const State_ &fg) override
Definition: ModelSpaceCovarianceBase.h:198
oops::ModelSpaceCovarianceBase::chvars_
ChvarVec_ chvars_
Definition: ModelSpaceCovarianceBase.h:87
oops::CovarianceFactory::getMakers
static std::map< std::string, CovarianceFactory< MODEL > * > & getMakers()
Definition: ModelSpaceCovarianceBase.h:180
oops::CovarMaker::CovarMaker
CovarMaker(const std::string &name)
Definition: ModelSpaceCovarianceBase.h:213
oops::ModelSpaceCovarianceBase::ModelSpaceCovarianceBase
ModelSpaceCovarianceBase(const State_ &, const State_ &, const Geometry_ &, const ModelSpaceCovarianceParametersBase< MODEL > &)
Definition: ModelSpaceCovarianceBase.h:296
oops::CovarianceFactory::Geometry_
Geometry< MODEL > Geometry_
Definition: ModelSpaceCovarianceBase.h:136
oops::ModelSpaceCovarianceBase::doMultiply
virtual void doMultiply(const Increment_ &, Increment_ &) const =0
oops::CovarianceFactory::make
virtual ModelSpaceCovarianceBase< MODEL > * make(const ModelSpaceCovarianceParametersBase< MODEL > &, const Geometry_ &, const Variables &, const State_ &, const State_ &)=0
oops::ModelSpaceCovarianceBase::ircst_
ChvarVec_::const_reverse_iterator ircst_
Definition: ModelSpaceCovarianceBase.h:69
oops::LinearVariableChangeParametersWrapper
Contains a polymorphic parameter holding an instance of a subclass of LinearVariableChangeParametersB...
Definition: LinearVariableChangeBase.h:110
oops::ModelSpaceCovarianceBase::Increment_
Increment< MODEL > Increment_
Definition: ModelSpaceCovarianceBase.h:64
oops::ModelSpaceCovarianceBase::multiply
void multiply(const Increment_ &, Increment_ &) const
Definition: ModelSpaceCovarianceBase.h:337
oops::LinearVariableChangeParametersBase
Base class of classes storing parameters controlling specific linear variable changes.
Definition: LinearVariableChangeParametersBase.h:21
oops::CovarMaker::Geometry_
Geometry< MODEL > Geometry_
Definition: ModelSpaceCovarianceBase.h:195
oops::LinearVariableChangeBase
Definition: LinearVariableChangeBase.h:53
oops::CovarMaker::State_
State< MODEL > State_
Definition: ModelSpaceCovarianceBase.h:196
oops::CovarMaker::makeParameters
std::unique_ptr< ModelSpaceCovarianceParametersBase< MODEL > > makeParameters() const override
Definition: ModelSpaceCovarianceBase.h:208
oops::ModelSpaceCovarianceParametersBase::covarianceModel
OptionalParameter< std::string > covarianceModel
Covariance model name.
Definition: ModelSpaceCovarianceParametersBase.h:36
oops::LinearVariableChangeParametersBase::outputVariables
OptionalParameter< Variables > outputVariables
Definition: LinearVariableChangeParametersBase.h:36
oops::ModelSpaceCovarianceBase::~ModelSpaceCovarianceBase
virtual ~ModelSpaceCovarianceBase()
Definition: ModelSpaceCovarianceBase.h:76
oops::ModelSpaceCovarianceParametersWrapper
Contains a polymorphic parameter holding an instance of a subclass of ModelSpaceCovarianceParametersB...
Definition: ModelSpaceCovarianceBase.h:120
oops::ModelSpaceCovarianceBase::State_
State< MODEL > State_
Definition: ModelSpaceCovarianceBase.h:63
oops::ModelSpaceCovarianceBase::randomize
void randomize(Increment_ &) const
Definition: ModelSpaceCovarianceBase.h:321
oops::Geometry
Geometry class used in oops; subclass of interface class above.
Definition: oops/interface/Geometry.h:189
oops::ModelSpaceCovarianceParametersWrapper::covarianceParameters
RequiredPolymorphicParameter< ModelSpaceCovarianceParametersBase< MODEL >, CovarianceFactory< MODEL > > covarianceParameters
Definition: ModelSpaceCovarianceBase.h:128
oops::ModelSpaceCovarianceBase::doInverseMultiply
virtual void doInverseMultiply(const Increment_ &, Increment_ &) const =0
oops::CovarianceFactory::getMakerNames
static std::vector< std::string > getMakerNames()
Return the names of all covariance models that can be created by one of the registered makers.
Definition: ModelSpaceCovarianceBase.h:163
oops::CovarianceFactory::create
static ModelSpaceCovarianceBase< MODEL > * create(const ModelSpaceCovarianceParametersBase< MODEL > &, const Geometry_ &, const Variables &, const State_ &, const State_ &)
Create and return a new covariance model.
Definition: ModelSpaceCovarianceBase.h:229
oops::State
Encapsulates the model state.
Definition: CostJbState.h:28
oops::ModelSpaceCovarianceBase::Geometry_
Geometry< MODEL > Geometry_
Definition: ModelSpaceCovarianceBase.h:62
oops::CovarianceFactory::State_
State< MODEL > State_
Definition: ModelSpaceCovarianceBase.h:137
oops::ModelSpaceCovarianceParametersBase
Base class for classes storing parameters of a particular model-space error covariance implementation...
Definition: ModelSpaceCovarianceParametersBase.h:25
oops::ModelSpaceCovarianceBase::inverseMultiply
void inverseMultiply(const Increment_ &, Increment_ &) const
Definition: ModelSpaceCovarianceBase.h:365
State.h
ModelSpaceCovarianceParametersBase.h
oops::Variables
Definition: oops/base/Variables.h:23
compare.error
int error
Definition: compare.py:168
oops::ModelSpaceCovarianceBase::doRandomize
virtual void doRandomize(Increment_ &) const =0
oops::ModelSpaceCovarianceBase::LinearVariableChangeBase_
LinearVariableChangeBase< MODEL > LinearVariableChangeBase_
Definition: ModelSpaceCovarianceBase.h:65
oops::ModelSpaceCovarianceBase
Definition: ModelSpaceCovarianceBase.h:61
oops::CovarMaker::Parameters_
TParameters_IfAvailableElseFallbackType_t< COVAR, GenericModelSpaceCovarianceParameters< MODEL > > Parameters_
Definition: ModelSpaceCovarianceBase.h:193
oops::Increment
Increment Class: Difference between two states.
Definition: CostJbState.h:27
oops::CovarianceFactory::~CovarianceFactory
virtual ~CovarianceFactory()=default
oops::ModelSpaceCovarianceBase::icst_
ChvarVec_::const_iterator icst_
Definition: ModelSpaceCovarianceBase.h:68
util
Definition: ObservationL95.h:32
oops::CovarianceFactory::CovarianceFactory
CovarianceFactory(const std::string &name)
Register a maker able to create covariance models of type name.
Definition: ModelSpaceCovarianceBase.h:219
LinearVariableChangeBase.h
Variables.h
Geometry.h
Increment.h