OOPS
ModelBase.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2018-2020 UCAR
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  */
7 
8 #ifndef OOPS_BASE_MODELBASE_H_
9 #define OOPS_BASE_MODELBASE_H_
10 
11 #include <map>
12 #include <memory>
13 #include <string>
14 #include <vector>
15 
16 #include <boost/make_unique.hpp>
17 #include <boost/noncopyable.hpp>
18 
21 #include "oops/interface/State.h"
22 #include "oops/util/AssociativeContainers.h"
23 #include "oops/util/Duration.h"
24 #include "oops/util/Logger.h"
25 #include "oops/util/parameters/ConfigurationParameter.h"
26 #include "oops/util/parameters/HasParameters_.h"
27 #include "oops/util/parameters/OptionalParameter.h"
28 #include "oops/util/parameters/Parameters.h"
29 #include "oops/util/parameters/ParametersOrConfiguration.h"
30 #include "oops/util/parameters/RequiredPolymorphicParameter.h"
31 #include "oops/util/Printable.h"
32 
33 namespace eckit {
34  class Configuration;
35 }
36 
37 namespace oops {
38 
39 // -----------------------------------------------------------------------------
40 
41 /// \brief Base class for the forecasting model
42 /// Defines the interfaces for a forecast model.
43 template <typename MODEL>
44 class ModelBase : public util::Printable,
45  private boost::noncopyable {
46  typedef typename MODEL::ModelAuxControl ModelAux_;
47  typedef typename MODEL::State State_;
48 
49  public:
50  static const std::string classname() {return "oops::ModelBase";}
51 
52  ModelBase() = default;
53  virtual ~ModelBase() = default;
54 
55  /// \brief Forecast initialization, called before every forecast run
56  virtual void initialize(State_ &) const = 0;
57  /// \brief Forecast "step", called during forecast run; updates state to the next time
58  virtual void step(State_ &, const ModelAux_ &) const = 0;
59  /// \brief Forecast finalization; called after each forecast run
60  virtual void finalize(State_ &) const = 0;
61 
62  /// \brief Time step for running Model's forecast in oops (frequency with which the
63  /// State will be updated)
64  virtual const util::Duration & timeResolution() const = 0;
65  /// \brief Model variables (only used in 4DVar)
66  virtual const oops::Variables & variables() const = 0;
67 
68  private:
69  /// \brief Print; used for logging
70  virtual void print(std::ostream &) const = 0;
71 };
72 
73 // =============================================================================
74 
75 template <typename MODEL>
77 
78 // -----------------------------------------------------------------------------
79 
80 /// \brief Base class for classes storing model-specific parameters.
81 class ModelParametersBase : public Parameters {
82  OOPS_ABSTRACT_PARAMETERS(ModelParametersBase, Parameters)
83  public:
84  /// \brief Model name.
85  ///
86  /// \note This parameter is marked as optional because it is only required in certain
87  /// circumstances (e.g. when model parameters are deserialized into a ModelParametersWrapper
88  /// and used by ModelFactory to instantiate a model whose type is determined at runtime), but
89  /// not others (e.g. in tests written with a particular model in mind). ModelParametersWrapper
90  /// will throw an exception if this parameter is not provided.
91  OptionalParameter<std::string> name{"name", this};
92 };
93 
94 // -----------------------------------------------------------------------------
95 
96 /// \brief A subclass of ModelParametersBase storing the values of all options in a
97 /// single Configuration object.
98 ///
99 /// This object can be accessed by calling the value() method of the \p config member variable.
100 ///
101 /// The ConfigurationParameter class does not perform any parameter validation; models using
102 /// GenericModelParameters should therefore ideally be refactored, replacing this class with a
103 /// dedicated subclass of ModelParametersBase storing each parameter in a separate
104 /// (Optional/Required)Parameter object.
106  OOPS_CONCRETE_PARAMETERS(GenericModelParameters, ModelParametersBase)
107  public:
108  ConfigurationParameter config{this};
109 };
110 
111 // -----------------------------------------------------------------------------
112 
113 /// \brief Contains a polymorphic parameter holding an instance of a subclass of
114 /// ModelParametersBase.
115 template <typename MODEL>
116 class ModelParametersWrapper : public Parameters {
117  OOPS_CONCRETE_PARAMETERS(ModelParametersWrapper, Parameters)
118  public:
119  /// After deserializtion, holds an instance of a subclass of ModelParametersBase controlling
120  /// the behavior of a model. The type of the subclass is determined by the value of the "name"
121  /// key in the Configuration object from which this object is deserialized.
122  RequiredPolymorphicParameter<ModelParametersBase, ModelFactory<MODEL>>
123  modelParameters{"name", this};
124 };
125 
126 // =============================================================================
127 
128 /// Model factory
129 template <typename MODEL>
130 class ModelFactory {
132 
133  public:
134  /// \brief Create and return a new model.
135  ///
136  /// The model's type is determined by the \c name attribute of \p parameters.
137  /// \p parameters must be an instance of the subclass of ModelParametersBase
138  /// associated with that model type, otherwise an exception will be thrown.
139  static ModelBase<MODEL> * create(const Geometry_ &, const ModelParametersBase & parameters);
140 
141  /// \brief Create and return an instance of the subclass of ModelParametersBase
142  /// storing parameters of models of the specified type.
143  static std::unique_ptr<ModelParametersBase> createParameters(const std::string &name);
144 
145  /// \brief Return the names of all models that can be created by one of the registered makers.
146  static std::vector<std::string> getMakerNames() {
147  return keys(getMakers());
148  }
149 
150  virtual ~ModelFactory() = default;
151 
152  protected:
153  /// \brief Register a maker able to create models of type \p name.
154  explicit ModelFactory(const std::string & name);
155 
156  private:
157  virtual ModelBase<MODEL> * make(const Geometry_ &, const ModelParametersBase &) = 0;
158 
159  virtual std::unique_ptr<ModelParametersBase> makeParameters() const = 0;
160 
161  static std::map < std::string, ModelFactory<MODEL> * > & getMakers() {
162  static std::map < std::string, ModelFactory<MODEL> * > makers_;
163  return makers_;
164  }
165 };
166 
167 // -----------------------------------------------------------------------------
168 
169 /// \brief A subclass of ModelFactory able to create instances of T (a concrete subclass of
170 /// ModelBase<MODEL>).
171 template<class MODEL, class T>
172 class ModelMaker : public ModelFactory<MODEL> {
173  private:
174  /// Defined as T::Parameters_ if T defines a Parameters_ type; otherwise as
175  /// GenericModelParameters.
176  typedef TParameters_IfAvailableElseFallbackType_t<T, GenericModelParameters> Parameters_;
177 
178  public:
180 
181  explicit ModelMaker(const std::string & name) : ModelFactory<MODEL>(name) {}
182 
183  ModelBase<MODEL> * make(const Geometry_ & geom, const ModelParametersBase & parameters) override {
184  Log::trace() << "ModelBase<MODEL>::make starting" << std::endl;
185  const auto &stronglyTypedParameters = dynamic_cast<const Parameters_&>(parameters);
186  return new T(geom.geometry(),
187  parametersOrConfiguration<HasParameters_<T>::value>(stronglyTypedParameters));
188  }
189 
190  std::unique_ptr<ModelParametersBase> makeParameters() const override {
191  return boost::make_unique<Parameters_>();
192  }
193 };
194 
195 // -----------------------------------------------------------------------------
196 
197 template <typename MODEL>
198 ModelFactory<MODEL>::ModelFactory(const std::string & name) {
199  Log::trace() << "ModelFactory<MODEL>::ModelFactory starting" << std::endl;
200  if (getMakers().find(name) != getMakers().end()) {
201  throw std::runtime_error(name + " already registered in the model factory.");
202  }
203  getMakers()[name] = this;
204  Log::trace() << "ModelFactory<MODEL>::ModelFactory done" << std::endl;
205 }
206 
207 // -----------------------------------------------------------------------------
208 
209 template <typename MODEL>
211  const ModelParametersBase & parameters) {
212  Log::trace() << "ModelFactory<MODEL>::create starting" << std::endl;
213  const std::string &id = parameters.name.value().value();
214  typename std::map<std::string, ModelFactory<MODEL>*>::iterator
215  jerr = getMakers().find(id);
216  if (jerr == getMakers().end()) {
217  throw std::runtime_error(id + " does not exist in the model factory");
218  }
219  ModelBase<MODEL> * ptr = jerr->second->make(geom, parameters);
220  Log::trace() << "ModelFactory<MODEL>::create done" << std::endl;
221  return ptr;
222 }
223 
224 // -----------------------------------------------------------------------------
225 
226 template <typename MODEL>
227 std::unique_ptr<ModelParametersBase> ModelFactory<MODEL>::createParameters(
228  const std::string &name) {
229  Log::trace() << "ModelFactory<MODEL>::createParameters starting" << std::endl;
230  typename std::map<std::string, ModelFactory<MODEL>*>::iterator it = getMakers().find(name);
231  if (it == getMakers().end()) {
232  throw std::runtime_error(name + " does not exist in the model factory");
233  }
234  return it->second->makeParameters();
235 }
236 
237 // -----------------------------------------------------------------------------
238 
239 } // namespace oops
240 
241 #endif // OOPS_BASE_MODELBASE_H_
oops::ModelBase
Base class for the forecasting model Defines the interfaces for a forecast model.
Definition: ModelBase.h:45
oops::ModelFactory::make
virtual ModelBase< MODEL > * make(const Geometry_ &, const ModelParametersBase &)=0
oops
The namespace for the main oops code.
Definition: ErrorCovarianceL95.cc:22
oops::ModelParametersBase::name
OptionalParameter< std::string > name
Model name.
Definition: ModelBase.h:91
oops::ModelFactory::getMakerNames
static std::vector< std::string > getMakerNames()
Return the names of all models that can be created by one of the registered makers.
Definition: ModelBase.h:146
oops::ModelFactory::Geometry_
Geometry< MODEL > Geometry_
Definition: ModelBase.h:131
oops::ModelBase::initialize
virtual void initialize(State_ &) const =0
Forecast initialization, called before every forecast run.
oops::ModelMaker::make
ModelBase< MODEL > * make(const Geometry_ &geom, const ModelParametersBase &parameters) override
Definition: ModelBase.h:183
oops::ModelBase::variables
virtual const oops::Variables & variables() const =0
Model variables (only used in 4DVar)
oops::ModelMaker::ModelMaker
ModelMaker(const std::string &name)
Definition: ModelBase.h:181
oops::ModelBase::print
virtual void print(std::ostream &) const =0
Print; used for logging.
oops::ModelMaker
A subclass of ModelFactory able to create instances of T (a concrete subclass of ModelBase<MODEL>).
Definition: ModelBase.h:172
oops::ModelMaker::Geometry_
Geometry< MODEL > Geometry_
Definition: ModelBase.h:179
oops::ModelMaker::makeParameters
std::unique_ptr< ModelParametersBase > makeParameters() const override
Definition: ModelBase.h:190
oops::ModelMaker::Parameters_
TParameters_IfAvailableElseFallbackType_t< T, GenericModelParameters > Parameters_
Definition: ModelBase.h:176
oops::ModelBase::ModelBase
ModelBase()=default
eckit
Definition: FieldL95.h:22
oops::ModelBase::State_
MODEL::State State_
Definition: ModelBase.h:47
oops::GenericModelParameters
A subclass of ModelParametersBase storing the values of all options in a single Configuration object.
Definition: ModelBase.h:105
oops::ModelBase::ModelAux_
MODEL::ModelAuxControl ModelAux_
Definition: ModelBase.h:46
oops::ModelBase::classname
static const std::string classname()
Definition: ModelBase.h:50
oops::ModelBase::~ModelBase
virtual ~ModelBase()=default
oops::ModelFactory::createParameters
static std::unique_ptr< ModelParametersBase > createParameters(const std::string &name)
Create and return an instance of the subclass of ModelParametersBase storing parameters of models of ...
Definition: ModelBase.h:227
oops::ModelFactory::~ModelFactory
virtual ~ModelFactory()=default
oops::ModelFactory::getMakers
static std::map< std::string, ModelFactory< MODEL > * > & getMakers()
Definition: ModelBase.h:161
oops::Geometry
Geometry class used in oops; subclass of interface class above.
Definition: oops/interface/Geometry.h:189
oops::ModelParametersWrapper
Contains a polymorphic parameter holding an instance of a subclass of ModelParametersBase.
Definition: ModelBase.h:116
oops::ModelParametersBase
Base class for classes storing model-specific parameters.
Definition: ModelBase.h:81
oops::ModelParametersWrapper::modelParameters
RequiredPolymorphicParameter< ModelParametersBase, ModelFactory< MODEL > > modelParameters
Definition: ModelBase.h:123
oops::ModelBase::timeResolution
virtual const util::Duration & timeResolution() const =0
Time step for running Model's forecast in oops (frequency with which the State will be updated)
oops::ModelFactory::create
static ModelBase< MODEL > * create(const Geometry_ &, const ModelParametersBase &parameters)
Create and return a new model.
Definition: ModelBase.h:210
State.h
oops::Variables
Definition: oops/base/Variables.h:23
oops::ModelBase::finalize
virtual void finalize(State_ &) const =0
Forecast finalization; called after each forecast run.
oops::ModelFactory
Model factory.
Definition: ModelBase.h:76
oops::GenericModelParameters::config
ConfigurationParameter config
Definition: ModelBase.h:108
oops::ModelFactory::makeParameters
virtual std::unique_ptr< ModelParametersBase > makeParameters() const =0
oops::ModelBase::step
virtual void step(State_ &, const ModelAux_ &) const =0
Forecast "step", called during forecast run; updates state to the next time.
oops::ModelFactory::ModelFactory
ModelFactory(const std::string &name)
Register a maker able to create models of type name.
Definition: ModelBase.h:198
ModelAuxControl.h
Geometry.h
oops::Geometry::geometry
const Geometry_ & geometry() const
Interfacing with other oops classes.
Definition: oops/interface/Geometry.h:206