IODA Bundle
LinearModelBase.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_LINEARMODELBASE_H_
12 #define OOPS_BASE_LINEARMODELBASE_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 
22 #include "oops/base/Geometry.h"
23 #include "oops/base/Increment.h"
24 #include "oops/base/State.h"
27 #include "oops/util/AssociativeContainers.h"
28 #include "oops/util/Duration.h"
29 #include "oops/util/Logger.h"
30 #include "oops/util/ObjectCounter.h"
31 #include "oops/util/parameters/ConfigurationParameter.h"
32 #include "oops/util/parameters/HasParameters_.h"
33 #include "oops/util/parameters/OptionalParameter.h"
34 #include "oops/util/parameters/Parameters.h"
35 #include "oops/util/parameters/RequiredPolymorphicParameter.h"
36 #include "oops/util/Printable.h"
37 
38 namespace eckit {
39  class Configuration;
40 }
41 
42 namespace oops {
43 
44 /// Base class for encapsulation of the linear forecast model.
45 /*!
46  * Defines the interfaces for the linear model.
47  */
48 
49 // -----------------------------------------------------------------------------
50 
51 template <typename MODEL>
52 class LinearModelBase : public util::Printable,
53  private boost::noncopyable {
59 
60  public:
61  static const std::string classname() {return "oops::LinearModelBase";}
62 
64  virtual ~LinearModelBase() {}
65 
66 // Set the linearization trajectory
67  void setTrajectory(const State_ &, State_ &, const ModelAux_ &);
68 
69 // Run the TL forecast
70  void initializeTL(Increment_ &) const;
71  void stepTL(Increment_ &, const ModelAuxIncr_ &) const;
72  void finalizeTL(Increment_ &) const;
73 
74 // Run the AD forecast
75  void initializeAD(Increment_ &) const;
76  void stepAD(Increment_ &, ModelAuxIncr_ &) const;
77  void finalizeAD(Increment_ &) const;
78 
79 // Information and diagnostics
80  virtual const util::Duration & timeResolution() const = 0;
81  virtual const oops::Variables & variables() const = 0;
82 
83  protected:
84 // Set the linearization trajectory
85  virtual void setTrajectory(const typename MODEL::State &, typename MODEL::State &,
86  const typename MODEL::ModelAuxControl &) = 0;
87 
88 // Run the TL forecast
89  virtual void initializeTL(typename MODEL::Increment &) const = 0;
90  virtual void stepTL(typename MODEL::Increment &,
91  const typename MODEL::ModelAuxIncrement &) const = 0;
92  virtual void finalizeTL(typename MODEL::Increment &) const = 0;
93 
94 // Run the AD forecast
95  virtual void initializeAD(typename MODEL::Increment &) const = 0;
96  virtual void stepAD(typename MODEL::Increment &, typename MODEL::ModelAuxIncrement &) const = 0;
97  virtual void finalizeAD(typename MODEL::Increment &) const = 0;
98 
99 // Information and diagnostics
100  virtual void print(std::ostream &) const = 0;
101 };
102 
103 // =============================================================================
104 
105 template <typename MODEL>
106 class LinearModelFactory;
107 
108 // -----------------------------------------------------------------------------
109 
110 /// \brief Base class for classes storing model-specific parameters.
111 class LinearModelParametersBase : public Parameters {
112  OOPS_ABSTRACT_PARAMETERS(LinearModelParametersBase, Parameters)
113  public:
114  /// \brief Model name.
115  ///
116  /// \note This parameter is marked as optional because it is only required in certain
117  /// circumstances (e.g. when model parameters are deserialized into a
118  /// LinearModelParametersWrapper and used by LinearModelFactory to instantiate a tangent linear
119  /// model whose type is determined at runtime), but not others (e.g. in tests written with a
120  /// particular model in mind). LinearModelParametersWrapper will throw an exception if this
121  /// parameter is not provided.
122  OptionalParameter<std::string> name{"name", this};
123 };
124 
125 // -----------------------------------------------------------------------------
126 
127 /// \brief A subclass of LinearModelParametersBase storing the values of all options in a
128 /// single Configuration object.
129 ///
130 /// This object can be accessed by calling the value() method of the \p config member variable.
131 ///
132 /// The ConfigurationParameter class does not perform any parameter validation; models using
133 /// GenericLinearModelParameters should therefore ideally be refactored, replacing this class with a
134 /// dedicated subclass of LinearModelParametersBase storing each parameter in a separate
135 /// (Optional/Required)Parameter object.
138  public:
139  ConfigurationParameter config{this};
140 };
141 
142 // -----------------------------------------------------------------------------
143 
144 /// \brief Contains a polymorphic parameter holding an instance of a subclass of
145 /// LinearModelParametersBase.
146 template <typename MODEL>
147 class LinearModelParametersWrapper : public Parameters {
148  OOPS_CONCRETE_PARAMETERS(LinearModelParametersWrapper, Parameters)
149  public:
150  /// After deserialization, holds an instance of a subclass of LinearModelParametersBase
151  /// controlling the behavior of a tangent linear model. The type of the subclass is determined by
152  /// the value of the "name" key in the Configuration object from which this object is
153  /// deserialized.
154  RequiredPolymorphicParameter<LinearModelParametersBase, LinearModelFactory<MODEL>>
155  modelParameters{"name", this};
156 };
157 
158 // =============================================================================
159 
160 /// \brief Tangent linear model factory.
161 template <typename MODEL>
164 
165  public:
166  /// \brief Create and return a new tangent linear model.
167  ///
168  /// The model's type is determined by the \c name attribute of \p parameters.
169  /// \p parameters must be an instance of the subclass of LinearModelParametersBase
170  /// associated with that model type, otherwise an exception will be thrown.
171  static LinearModelBase<MODEL> * create(const Geometry_ &,
172  const LinearModelParametersBase & parameters);
173 
174  /// \brief Create and return an instance of the subclass of LinearModelParametersBase
175  /// storing parameters of tangent linear models of the specified type.
176  static std::unique_ptr<LinearModelParametersBase> createParameters(const std::string &name);
177 
178  /// \brief Return the names of all tangent linear models that can be created by one of the
179  /// registered makers.
180  static std::vector<std::string> getMakerNames() {
181  return keys(getMakers());
182  }
183 
184  virtual ~LinearModelFactory() = default;
185 
186  protected:
187  /// \brief Register a maker able to create tangent linear models of type \p name.
188  explicit LinearModelFactory(const std::string &name);
189 
190  private:
192 
193  virtual std::unique_ptr<LinearModelParametersBase> makeParameters() const = 0;
194 
195  static std::map < std::string, LinearModelFactory<MODEL> * > & getMakers() {
196  static std::map < std::string, LinearModelFactory<MODEL> * > makers_;
197  return makers_;
198  }
199 };
200 
201 // -----------------------------------------------------------------------------
202 
203 template<class MODEL, class T>
204 class LinearModelMaker : public LinearModelFactory<MODEL> {
205  private:
206  /// Defined as T::Parameters_ if T defines a Parameters_ type; otherwise as
207  /// GenericLinearModelParameters.
208  typedef TParameters_IfAvailableElseFallbackType_t<T, GenericLinearModelParameters> Parameters_;
209 
211 
213  const LinearModelParametersBase & parameters) override {
214  const auto &stronglyTypedParameters = dynamic_cast<const Parameters_&>(parameters);
215  return new T(geom.geometry(),
216  parametersOrConfiguration<HasParameters_<T>::value>(stronglyTypedParameters));
217  }
218 
219  std::unique_ptr<LinearModelParametersBase> makeParameters() const override {
220  return boost::make_unique<Parameters_>();
221  }
222 
223  public:
224  explicit LinearModelMaker(const std::string & name) : LinearModelFactory<MODEL>(name) {}
225 };
226 
227 // -----------------------------------------------------------------------------
228 
229 template <typename MODEL>
231  if (getMakers().find(name) != getMakers().end()) {
232  throw std::runtime_error(name + " already registered in tangent linear model factory.");
233  }
234  getMakers()[name] = this;
235 }
236 
237 // -----------------------------------------------------------------------------
238 
239 template <typename MODEL>
241  const Geometry_ & geom, const LinearModelParametersBase & parameters) {
242  Log::trace() << "LinearModelBase<MODEL>::create starting" << std::endl;
243  const std::string &id = parameters.name.value().value();
244  typename std::map<std::string, LinearModelFactory<MODEL>*>::iterator
245  jerr = getMakers().find(id);
246  if (jerr == getMakers().end()) {
247  Log::error() << id << " does not exist in the tangent linear model factory." << std::endl;
248  Log::error() << "Factory contains " << getMakers().size() << " elements:" << std::endl;
249  for (typename std::map<std::string, LinearModelFactory<MODEL>*>::const_iterator
250  jj = getMakers().begin(); jj != getMakers().end(); ++jj) {
251  Log::error() << "A " << jj->first << " linear model" << std::endl;
252  }
253  throw std::runtime_error(id + " does not exist in tangent linear model factory.");
254  }
255  LinearModelBase<MODEL> * ptr = jerr->second->make(geom, parameters);
256  Log::trace() << "LinearModelBase<MODEL>::create done" << std::endl;
257  return ptr;
258 }
259 
260 // -----------------------------------------------------------------------------
261 
262 template <typename MODEL>
263 std::unique_ptr<LinearModelParametersBase> LinearModelFactory<MODEL>::createParameters(
264  const std::string &name) {
265  typename std::map<std::string, LinearModelFactory<MODEL>*>::iterator it = getMakers().find(name);
266  if (it == getMakers().end()) {
267  throw std::runtime_error(name + " does not exist in the tangent linear model factory");
268  }
269  return it->second->makeParameters();
270 }
271 
272 // =============================================================================
273 
274 template<typename MODEL>
276  const ModelAux_ & maux) {
277  Log::trace() << "LinearModelBase<MODEL>::setTrajectory starting" << std::endl;
278  this->setTrajectory(xx.state(), xlr.state(), maux.modelauxcontrol());
279  Log::trace() << "LinearModelBase<MODEL>::setTrajectory done" << std::endl;
280 }
281 
282 // -----------------------------------------------------------------------------
283 
284 template<typename MODEL>
286  Log::trace() << "LinearModelBase<MODEL>::initializeTL starting" << std::endl;
287  this->initializeTL(dx.increment());
288  Log::trace() << "LinearModelBase<MODEL>::initializeTL done" << std::endl;
289 }
290 
291 // -----------------------------------------------------------------------------
292 
293 template<typename MODEL>
295  Log::trace() << "LinearModelBase<MODEL>::stepTL starting" << std::endl;
296  this->stepTL(dx.increment(), merr.modelauxincrement());
297  Log::trace() << "LinearModelBase<MODEL>::stepTL done" << std::endl;
298 }
299 
300 // -----------------------------------------------------------------------------
301 
302 template<typename MODEL>
304  Log::trace() << "LinearModelBase<MODEL>::finalizeTL starting" << std::endl;
305  this->finalizeTL(dx.increment());
306  Log::trace() << "LinearModelBase<MODEL>::finalizeTL done" << std::endl;
307 }
308 
309 // -----------------------------------------------------------------------------
310 
311 template<typename MODEL>
313  Log::trace() << "LinearModelBase<MODEL>::initializeAD starting" << std::endl;
314  this->initializeAD(dx.increment());
315  Log::trace() << "LinearModelBase<MODEL>::initializeAD done" << std::endl;
316 }
317 
318 // -----------------------------------------------------------------------------
319 
320 template<typename MODEL>
322  Log::trace() << "LinearModelBase<MODEL>::stepAD starting" << std::endl;
323  this->stepAD(dx.increment(), merr.modelauxincrement());
324  Log::trace() << "LinearModelBase<MODEL>::stepAD done" << std::endl;
325 }
326 
327 // -----------------------------------------------------------------------------
328 
329 template<typename MODEL>
331  Log::trace() << "LinearModelBase<MODEL>::finalizeAD starting" << std::endl;
332  this->finalizeAD(dx.increment());
333  Log::trace() << "LinearModelBase<MODEL>::finalizeAD done" << std::endl;
334 }
335 
336 // -----------------------------------------------------------------------------
337 
338 } // namespace oops
339 
340 #endif // OOPS_BASE_LINEARMODELBASE_H_
A subclass of LinearModelParametersBase storing the values of all options in a single Configuration o...
Geometry class used in oops; subclass of interface class interface::Geometry.
Increment class used in oops.
Base class for encapsulation of the linear forecast model.
virtual void print(std::ostream &) const =0
virtual void stepTL(typename MODEL::Increment &, const typename MODEL::ModelAuxIncrement &) const =0
void initializeTL(Increment_ &) const
virtual void stepAD(typename MODEL::Increment &, typename MODEL::ModelAuxIncrement &) const =0
virtual const oops::Variables & variables() const =0
void stepTL(Increment_ &, const ModelAuxIncr_ &) const
ModelAuxControl< MODEL > ModelAux_
virtual void initializeTL(typename MODEL::Increment &) const =0
ModelAuxIncrement< MODEL > ModelAuxIncr_
virtual void finalizeAD(typename MODEL::Increment &) const =0
Increment< MODEL > Increment_
void finalizeTL(Increment_ &) const
Geometry< MODEL > Geometry_
virtual void finalizeTL(typename MODEL::Increment &) const =0
State< MODEL > State_
void stepAD(Increment_ &, ModelAuxIncr_ &) const
void finalizeAD(Increment_ &) const
virtual void initializeAD(typename MODEL::Increment &) const =0
virtual const util::Duration & timeResolution() const =0
void setTrajectory(const State_ &, State_ &, const ModelAux_ &)
static const std::string classname()
void initializeAD(Increment_ &) const
virtual void setTrajectory(const typename MODEL::State &, typename MODEL::State &, const typename MODEL::ModelAuxControl &)=0
Tangent linear model factory.
LinearModelFactory(const std::string &name)
Register a maker able to create tangent linear models of type name.
virtual ~LinearModelFactory()=default
Geometry< MODEL > Geometry_
static LinearModelBase< MODEL > * create(const Geometry_ &, const LinearModelParametersBase &parameters)
Create and return a new tangent linear model.
virtual std::unique_ptr< LinearModelParametersBase > makeParameters() const =0
static std::vector< std::string > getMakerNames()
Return the names of all tangent linear models that can be created by one of the registered makers.
static std::map< std::string, LinearModelFactory< MODEL > * > & getMakers()
virtual LinearModelBase< MODEL > * make(const Geometry_ &, const LinearModelParametersBase &)=0
static std::unique_ptr< LinearModelParametersBase > createParameters(const std::string &name)
Create and return an instance of the subclass of LinearModelParametersBase storing parameters of tang...
std::unique_ptr< LinearModelParametersBase > makeParameters() const override
LinearModelMaker(const std::string &name)
Geometry< MODEL > Geometry_
TParameters_IfAvailableElseFallbackType_t< T, GenericLinearModelParameters > Parameters_
LinearModelBase< MODEL > * make(const Geometry_ &geom, const LinearModelParametersBase &parameters) override
Base class for classes storing model-specific parameters.
OptionalParameter< std::string > name
Model name.
Contains a polymorphic parameter holding an instance of a subclass of LinearModelParametersBase.
RequiredPolymorphicParameter< LinearModelParametersBase, LinearModelFactory< MODEL > > modelParameters
const ModelAuxControl_ & modelauxcontrol() const
Interfacing.
const ModelAuxIncrement_ & modelauxincrement() const
Interfacing.
State class used in oops; subclass of interface class interface::State.
const Geometry_ & geometry() const
const Increment_ & increment() const
State_ & state()
Accessor.
The namespace for the main oops code.