OOPS
VariableChangeBase.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2018 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_VARIABLECHANGEBASE_H_
9 #define OOPS_BASE_VARIABLECHANGEBASE_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 
20 #include "oops/base/Variables.h"
21 #include "oops/interface/State.h"
22 #include "oops/util/AssociativeContainers.h"
23 #include "oops/util/parameters/ConfigurationParameter.h"
24 #include "oops/util/parameters/HasParameters_.h"
25 #include "oops/util/parameters/Parameters.h"
26 #include "oops/util/parameters/PolymorphicParameter.h"
27 #include "oops/util/Printable.h"
28 
29 namespace eckit {
30  class Configuration;
31 }
32 
33 namespace oops {
34 
35 // -------------------------------------------------------------------------------------------------
36 
37 /// Base class for generic variable transform
38 ///
39 /// Note: subclasses can opt to extract their settings either from a Configuration object or from a
40 /// subclass of Parameters.
41 ///
42 /// In the former case, they should provide a constructor taking a const reference to an
43 /// eckit::Configuration object. In the latter case, the implementer should first define a subclass
44 /// of Parameters holding the settings of the variable change in question. The latter should
45 /// then typedef `Parameters_` to the name of that subclass and provide a constructor taking a
46 /// const reference to an instance of that subclass.
47 template <typename MODEL>
48 class VariableChangeBase : public util::Printable,
49  private boost::noncopyable {
51 
52  public:
54  explicit VariableChangeBase(const eckit::Configuration &);
55  virtual ~VariableChangeBase() {}
56 
57  void setInputVariables(const Variables & vars) { varin_.reset(new Variables(vars)); }
58  void setOutputVariables(const Variables & vars) { varout_.reset(new Variables(vars)); }
59 
60  virtual void changeVar(const State_ &, State_ &) const = 0;
61  virtual void changeVarInverse(const State_ &, State_ &) const = 0;
62 
63  State_ changeVar(const State_ &) const;
64  State_ changeVarInverse(const State_ &) const;
65 
66  private:
67  virtual void print(std::ostream &) const = 0;
68  std::unique_ptr<Variables> varin_;
69  std::unique_ptr<Variables> varout_;
70 };
71 
72 // =============================================================================
73 
74 template <typename MODEL>
76 
77 // -----------------------------------------------------------------------------
78 
79 /// \brief A subclass of VariableChangeParametersBase storing the values of all options in a
80 /// single Configuration object.
81 ///
82 /// This object can be accessed by calling the value() method of the \p config member variable.
83 ///
84 /// The ConfigurationParameter class does not perform any parameter validation; models using
85 /// GenericVariableChangeParameters should therefore ideally be refactored, replacing this
86 /// class with a dedicated subclass of VariableChangeParametersBase storing each parameter in
87 /// a separate (Optional/Required)Parameter object.
89  OOPS_CONCRETE_PARAMETERS(GenericVariableChangeParameters,
91  public:
92  ConfigurationParameter config{this};
93 };
94 
95 // -----------------------------------------------------------------------------
96 
97 /// \brief Contains a polymorphic parameter holding an instance of a subclass of
98 /// VariableChangeParametersBase.
99 template <typename MODEL>
100 class VariableChangeParametersWrapper : public Parameters {
101  OOPS_CONCRETE_PARAMETERS(VariableChangeParametersWrapper, Parameters)
102  public:
103  /// After deserialization, holds an instance of a subclass of VariableChangeParametersBase
104  /// controlling the behavior of a variable change. The type of the subclass is determined
105  /// by the value of the "variable change" key in the Configuration object from which this object
106  /// is deserialized.
107  PolymorphicParameter<VariableChangeParametersBase, VariableChangeFactory<MODEL>>
108  variableChangeParameters{"variable change", "Identity", this};
109 };
110 
111 // =============================================================================
112 
113 /// VariableChange factory
114 template <typename MODEL>
115 class VariableChangeFactory {
117 
118  public:
119  /// \brief Create and return a new variable change.
120  ///
121  /// The type of the variable change is determined by the `variable change` attribute of \p
122  /// parameters. \p parameters must be an instance of the subclass of
123  /// VariableChangeParametersBase associated with that variable change type, otherwise an
124  /// exception will be thrown.
126  const Geometry_ &);
127 
128  /// \brief Create and return a new variable change.
129  ///
130  /// Deprecated overload taking a Configuration instead of a VariableChangeParametersBase.
131  static VariableChangeBase<MODEL> * create(const eckit::Configuration &, const Geometry_ &);
132 
133  /// \brief Create and return an instance of the subclass of VariableChangeParametersBase
134  /// storing parameters of variable changes of the specified type.
135  static std::unique_ptr<VariableChangeParametersBase> createParameters(const std::string &name);
136 
137  /// \brief Return the names of all variable changes that can be created by one of the
138  /// registered makers.
139  static std::vector<std::string> getMakerNames() {
140  return keys(getMakers());
141  }
142 
143  virtual ~VariableChangeFactory() = default;
144 
145  protected:
146  /// \brief Register a maker able to create variable changes of type \p name.
147  explicit VariableChangeFactory(const std::string &);
148 
149  private:
151  const Geometry_ &) = 0;
152 
153  virtual std::unique_ptr<VariableChangeParametersBase> makeParameters() const = 0;
154 
155  static std::map < std::string, VariableChangeFactory<MODEL> * > & getMakers() {
156  static std::map < std::string, VariableChangeFactory<MODEL> * > makers_;
157  return makers_;
158  }
159 };
160 
161 // -------------------------------------------------------------------------------------------------
162 
163 template<class MODEL, class T>
165  /// Defined as T::Parameters_ if T defines a Parameters_ type; otherwise as
166  /// GenericVariableChangeParameters.
167  typedef TParameters_IfAvailableElseFallbackType_t<T, GenericVariableChangeParameters> Parameters_;
168 
170 
172  const Geometry_ & resol) override {
173  const auto &stronglyTypedParams = dynamic_cast<const Parameters_&>(params);
174  return new T(resol,
175  parametersOrConfiguration<HasParameters_<T>::value>(stronglyTypedParams));
176  }
177 
178  std::unique_ptr<VariableChangeParametersBase> makeParameters() const override {
179  return boost::make_unique<Parameters_>();
180  }
181 
182  public:
183  explicit VariableChangeMaker(const std::string & name)
184  : VariableChangeFactory<MODEL>(name) {}
185 };
186 
187 // -------------------------------------------------------------------------------------------------
188 
189 template <typename MODEL>
191  if (getMakers().find(name) != getMakers().end()) {
192  throw std::runtime_error(name + " already registered in the variable change factory.");
193  }
194  getMakers()[name] = this;
195 }
196 
197 // -------------------------------------------------------------------------------------------------
198 
199 template <typename MODEL>
201  const VariableChangeParametersBase & params, const Geometry_ & resol)
202 {
203  Log::trace() << "VariableChangeBase<MODEL>::create starting" << std::endl;
204 // Not good: should not create anything if no variable change required. YT
205  const std::string &id = params.variableChange.value().value();
206  typename std::map<std::string, VariableChangeFactory<MODEL>*>::iterator
207  jerr = getMakers().find(id);
208  if (jerr == getMakers().end()) {
209  throw std::runtime_error(id + " does not exist in variable change factory.");
210  }
211  VariableChangeBase<MODEL> * ptr = jerr->second->make(params, resol);
212  Log::trace() << "VariableChangeBase<MODEL>::create done" << std::endl;
213  return ptr;
214 }
215 
216 // -------------------------------------------------------------------------------------------------
217 
218 template <typename MODEL>
220  const Geometry_ & resol) {
222  parameters.validateAndDeserialize(conf);
223  return create(parameters.variableChangeParameters, resol);
224 }
225 
226 // -----------------------------------------------------------------------------
227 
228 template <typename MODEL>
229 std::unique_ptr<VariableChangeParametersBase> VariableChangeFactory<MODEL>::createParameters(
230  const std::string &name) {
231  typename std::map<std::string, VariableChangeFactory<MODEL>*>::iterator it =
232  getMakers().find(name);
233  if (it == getMakers().end()) {
234  throw std::runtime_error(name + " does not exist in VariableChangeFactory");
235  }
236  return it->second->makeParameters();
237 }
238 
239 // =================================================================================================
240 
241 template<typename MODEL>
243  : varin_(), varout_()
244 {
245  if (params.inputVariables.value() != boost::none) {
246  varin_.reset(new Variables(*params.inputVariables.value()));
247  Log::trace() << "VariableChangeBase<MODEL>::VariableChangeBase input variables: "
248  << *varin_ << std::endl;
249  }
250  if (params.outputVariables.value() != boost::none) {
251  varout_.reset(new Variables(*params.outputVariables.value()));
252  Log::trace() << "VariableChangeBase<MODEL>::VariableChangeBase output variables: "
253  << *varout_ << std::endl;
254  }
255 }
256 
257 // -------------------------------------------------------------------------------------------------
258 
259 template<typename MODEL>
260 VariableChangeBase<MODEL>::VariableChangeBase(const eckit::Configuration & conf)
261  : VariableChangeBase(validateAndDeserialize<GenericVariableChangeParameters>(conf))
262 {}
263 
264 // -------------------------------------------------------------------------------------------------
265 
266 template<typename MODEL>
268  Log::trace() << "VariableChangeBase<MODEL>::changeVar starting" << std::endl;
269  ASSERT(varout_);
270  State_ xout(xin.geometry(), *varout_, xin.validTime());
271  this->changeVar(xin, xout);
272  Log::trace() << "VariableChangeBase<MODEL>::changeVar done" << std::endl;
273  return xout;
274 }
275 
276 // -------------------------------------------------------------------------------------------------
277 
278 template<typename MODEL>
280  Log::trace() << "VariableChangeBase<MODEL>::changeVarInverse starting" << std::endl;
281  ASSERT(varin_);
282  State_ xout(xin.geometry(), *varin_, xin.validTime());
283  this->changeVarInverse(xin, xout);
284  Log::trace() << "VariableChangeBase<MODEL>::changeVarInverse done" << std::endl;
285  return xout;
286 }
287 
288 // -------------------------------------------------------------------------------------------------
289 
290 } // namespace oops
291 
292 #endif // OOPS_BASE_VARIABLECHANGEBASE_H_
oops::State::validTime
const util::DateTime validTime() const
Time.
Definition: oops/interface/State.h:60
oops::GenericVariableChangeParameters
A subclass of VariableChangeParametersBase storing the values of all options in a single Configuratio...
Definition: VariableChangeBase.h:88
oops
The namespace for the main oops code.
Definition: ErrorCovarianceL95.cc:22
oops::VariableChangeBase
Definition: VariableChangeBase.h:49
oops::VariableChangeBase::setOutputVariables
void setOutputVariables(const Variables &vars)
Definition: VariableChangeBase.h:58
oops::VariableChangeFactory::VariableChangeFactory
VariableChangeFactory(const std::string &)
Register a maker able to create variable changes of type name.
Definition: VariableChangeBase.h:190
oops::VariableChangeMaker::makeParameters
std::unique_ptr< VariableChangeParametersBase > makeParameters() const override
Definition: VariableChangeBase.h:178
oops::VariableChangeBase::print
virtual void print(std::ostream &) const =0
oops::VariableChangeFactory::create
static VariableChangeBase< MODEL > * create(const VariableChangeParametersBase &, const Geometry_ &)
Create and return a new variable change.
Definition: VariableChangeBase.h:200
oops::VariableChangeFactory::getMakers
static std::map< std::string, VariableChangeFactory< MODEL > * > & getMakers()
Definition: VariableChangeBase.h:155
oops::VariableChangeFactory::~VariableChangeFactory
virtual ~VariableChangeFactory()=default
oops::VariableChangeFactory::Geometry_
Geometry< MODEL > Geometry_
Definition: VariableChangeBase.h:116
oops::VariableChangeBase::changeVar
virtual void changeVar(const State_ &, State_ &) const =0
oops::VariableChangeParametersWrapper
Contains a polymorphic parameter holding an instance of a subclass of VariableChangeParametersBase.
Definition: VariableChangeBase.h:100
oops::VariableChangeParametersWrapper::variableChangeParameters
PolymorphicParameter< VariableChangeParametersBase, VariableChangeFactory< MODEL > > variableChangeParameters
Definition: VariableChangeBase.h:108
oops::VariableChangeFactory
VariableChange factory.
Definition: VariableChangeBase.h:75
oops::VariableChangeBase::VariableChangeBase
VariableChangeBase(const VariableChangeParametersBase &)
Definition: VariableChangeBase.h:242
oops::VariableChangeBase::~VariableChangeBase
virtual ~VariableChangeBase()
Definition: VariableChangeBase.h:55
oops::VariableChangeParametersBase::outputVariables
OptionalParameter< Variables > outputVariables
Definition: VariableChangeParametersBase.h:35
eckit
Definition: FieldL95.h:22
oops::VariableChangeFactory::createParameters
static std::unique_ptr< VariableChangeParametersBase > createParameters(const std::string &name)
Create and return an instance of the subclass of VariableChangeParametersBase storing parameters of v...
Definition: VariableChangeBase.h:229
VariableChangeParametersBase.h
oops::VariableChangeParametersBase
Base class of classes storing parameters controlling specific variable changes.
Definition: VariableChangeParametersBase.h:21
oops::VariableChangeMaker::make
VariableChangeBase< MODEL > * make(const VariableChangeParametersBase &params, const Geometry_ &resol) override
Definition: VariableChangeBase.h:171
oops::VariableChangeFactory::makeParameters
virtual std::unique_ptr< VariableChangeParametersBase > makeParameters() const =0
oops::VariableChangeBase::State_
State< MODEL > State_
Definition: VariableChangeBase.h:50
oops::VariableChangeFactory::make
virtual VariableChangeBase< MODEL > * make(const VariableChangeParametersBase &, const Geometry_ &)=0
oops::VariableChangeParametersBase::inputVariables
OptionalParameter< Variables > inputVariables
Definition: VariableChangeParametersBase.h:34
oops::Geometry
Geometry class used in oops; subclass of interface class above.
Definition: oops/interface/Geometry.h:189
oops::VariableChangeBase::changeVarInverse
virtual void changeVarInverse(const State_ &, State_ &) const =0
oops::VariableChangeBase::varout_
std::unique_ptr< Variables > varout_
Definition: VariableChangeBase.h:69
oops::State::geometry
Geometry_ geometry() const
Definition: oops/interface/State.h:215
oops::State
Encapsulates the model state.
Definition: CostJbState.h:28
oops::VariableChangeMaker::VariableChangeMaker
VariableChangeMaker(const std::string &name)
Definition: VariableChangeBase.h:183
oops::VariableChangeMaker
Definition: VariableChangeBase.h:164
oops::VariableChangeMaker::Parameters_
TParameters_IfAvailableElseFallbackType_t< T, GenericVariableChangeParameters > Parameters_
Definition: VariableChangeBase.h:167
oops::VariableChangeFactory::getMakerNames
static std::vector< std::string > getMakerNames()
Return the names of all variable changes that can be created by one of the registered makers.
Definition: VariableChangeBase.h:139
State.h
oops::Variables
Definition: oops/base/Variables.h:23
oops::VariableChangeBase::setInputVariables
void setInputVariables(const Variables &vars)
Definition: VariableChangeBase.h:57
oops::VariableChangeMaker::Geometry_
Geometry< MODEL > Geometry_
Definition: VariableChangeBase.h:169
Variables.h
oops::VariableChangeBase::varin_
std::unique_ptr< Variables > varin_
Definition: VariableChangeBase.h:68
oops::VariableChangeParametersBase::variableChange
OptionalParameter< std::string > variableChange
Variable change type.
Definition: VariableChangeParametersBase.h:32