11 #ifndef OOPS_BASE_MODELSPACECOVARIANCEBASE_H_
12 #define OOPS_BASE_MODELSPACECOVARIANCEBASE_H_
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>
24 #include "eckit/config/LocalConfiguration.h"
25 #include "eckit/exception/Exceptions.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"
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_;
75 const Geometry_ &,
const eckit::Configuration &);
92 template <
typename MODEL>
107 template <
typename MODEL>
112 ConfigurationParameter config{
this};
119 template <
typename MODEL>
134 template <
typename MODEL>
135 class CovarianceFactory {
158 static std::unique_ptr<ModelSpaceCovarianceParametersBase<MODEL>>
createParameters(
159 const std::string &covarianceModel);
178 virtual std::unique_ptr<ModelSpaceCovarianceParametersBase<MODEL>>
makeParameters()
const = 0;
180 static std::map < std::string, CovarianceFactory<MODEL> * > &
getMakers() {
181 static std::map < std::string, CovarianceFactory<MODEL> * > makers_;
188 template<
class MODEL,
class COVAR>
192 typedef TParameters_IfAvailableElseFallbackType_t<
202 const auto &stronglyTypedParams =
dynamic_cast<const Parameters_&
>(params);
203 return new COVAR(resol, vars,
204 parametersOrConfiguration<HasParameters_<COVAR>::value>(stronglyTypedParams),
208 std::unique_ptr<ModelSpaceCovarianceParametersBase<MODEL>>
makeParameters()
const override {
209 return boost::make_unique<Parameters_>();
218 template <
typename MODEL>
220 if (getMakers().find(name) != getMakers().end()) {
221 throw std::runtime_error(name +
" already registered in covariance factory.");
223 getMakers()[name] =
this;
228 template <
typename MODEL>
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;
241 jj = getMakers().begin(); jj != getMakers().end(); ++jj) {
242 Log::error() <<
"A " << jj->first <<
" B" << std::endl;
244 throw std::runtime_error(
id +
" does not exist in covariance factory.");
251 variableChange.variableChangeParameters;
252 if (variableChangeParameters.
inputVariables.value() != boost::none &&
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");
263 return (*jcov).second->make(parameters, resol, vars_in, xb, fg);
268 template <
typename MODEL>
270 const eckit::Configuration & conf,
275 parameters.validateAndDeserialize(conf);
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");
290 return it->second->makeParameters();
295 template <
typename MODEL>
303 bg, fg, resol, variableChange.variableChangeParameters));
309 template <
typename MODEL>
313 const eckit::Configuration & conf)
320 template <
typename MODEL>
323 if (chvars_.size()) {
324 this->doRandomize(dx);
326 for (
icst_ it = chvars_.begin(); it != chvars_.end(); ++it) {
327 dx = it->multiply(dx);
330 this->doRandomize(dx);
336 template <
typename MODEL>
339 if (chvars_.size()) {
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);
348 this->doMultiply(*dxchvarin, dxchvarout);
352 for (
icst_ it = chvars_.begin(); it != chvars_.end(); ++it) {
353 Increment_ dxchvarout = it->multiply(*dxchvarin);
358 this->doMultiply(dxi, dxo);
364 template <
typename MODEL>
367 if (chvars_.size()) {
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);
376 this->doInverseMultiply(*dxchvarin, dxchvarout);
380 for (
icst_ it = chvars_.begin(); it != chvars_.end(); ++it) {
381 Increment_ dxchvarout = it->multiplyInverseAD(*dxchvarin);
386 this->doInverseMultiply(dxi, dxo);
394 #endif // OOPS_BASE_MODELSPACECOVARIANCEBASE_H_