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"
34 #include "oops/util/AssociativeContainers.h"
35 #include "oops/util/Logger.h"
36 #include "oops/util/parameters/ConfigurationParameter.h"
37 #include "oops/util/parameters/HasParameters_.h"
38 #include "oops/util/parameters/OptionalParameter.h"
39 #include "oops/util/parameters/Parameters.h"
40 #include "oops/util/parameters/RequiredPolymorphicParameter.h"
41 #include "oops/util/Random.h"
63 template <
typename MODEL>
69 typedef typename boost::ptr_vector<LinearVariableChangeBase_>
ChvarVec_;
70 typedef typename ChvarVec_::iterator
iter_;
71 typedef typename ChvarVec_::const_iterator
icst_;
72 typedef typename ChvarVec_::const_reverse_iterator
ircst_;
78 const Geometry_ &,
const eckit::Configuration &);
100 template <
typename MODEL>
115 template <
typename MODEL>
120 ConfigurationParameter config{
this};
127 template <
typename MODEL>
142 template <
typename MODEL>
166 static std::unique_ptr<ModelSpaceCovarianceParametersBase<MODEL>>
createParameters(
167 const std::string &covarianceModel);
186 virtual std::unique_ptr<ModelSpaceCovarianceParametersBase<MODEL>>
makeParameters()
const = 0;
188 static std::map < std::string, CovarianceFactory<MODEL> * > &
getMakers() {
189 static std::map < std::string, CovarianceFactory<MODEL> * > makers_;
196 template<
class MODEL,
class COVAR>
200 typedef TParameters_IfAvailableElseFallbackType_t<
210 const auto &stronglyTypedParams =
dynamic_cast<const Parameters_&
>(params);
211 return new COVAR(resol, vars,
212 parametersOrConfiguration<HasParameters_<COVAR>::value>(stronglyTypedParams),
216 std::unique_ptr<ModelSpaceCovarianceParametersBase<MODEL>>
makeParameters()
const override {
217 return boost::make_unique<Parameters_>();
226 template <
typename MODEL>
228 if (getMakers().find(name) != getMakers().end()) {
229 throw std::runtime_error(name +
" already registered in covariance factory.");
231 getMakers()[name] =
this;
236 template <
typename MODEL>
243 Log::trace() <<
"ModelSpaceCovarianceBase type = " <<
id << std::endl;
244 typename std::map<std::string, CovarianceFactory<MODEL>*>::iterator jcov = getMakers().find(
id);
245 if (jcov == getMakers().end()) {
246 Log::error() <<
id <<
" does not exist in CovarianceFactory." << std::endl;
247 Log::error() <<
"CovarianceFactory has " << getMakers().size() <<
" elements:" << std::endl;
249 jj = getMakers().begin(); jj != getMakers().end(); ++jj) {
250 Log::error() <<
"A " << jj->first <<
" B" << std::endl;
252 throw std::runtime_error(
id +
" does not exist in covariance factory.");
259 variableChange.variableChangeParameters;
260 if (variableChangeParameters.
inputVariables.value() != boost::none &&
263 if (!(vars_in == vars_out)) {
264 Log::error() <<
"Input variables: " << vars_in << std::endl;
265 Log::error() <<
"Output variables: " << vars_out << std::endl;
266 throw eckit::BadParameter(
"Sequence of variable changes is not consistent");
271 return (*jcov).second->make(parameters, resol, vars_in, xb, fg);
276 template <
typename MODEL>
278 const eckit::Configuration & conf,
283 parameters.validateAndDeserialize(conf);
289 template <
typename MODEL>
290 std::unique_ptr<ModelSpaceCovarianceParametersBase<MODEL>>
292 const std::string &name) {
293 typename std::map<std::string, CovarianceFactory<MODEL>*>::iterator it =
294 getMakers().find(name);
295 if (it == getMakers().end()) {
296 throw std::runtime_error(name +
" does not exist in CovarianceFactory");
298 return it->second->makeParameters();
303 template <
typename MODEL>
311 bg, fg, resol, variableChange.variableChangeParameters));
321 template <
typename MODEL>
325 const eckit::Configuration & conf)
332 template <
typename MODEL>
335 if (chvars_.size()) {
336 this->doRandomize(dx);
338 for (
icst_ it = chvars_.begin(); it != chvars_.end(); ++it) {
339 dx = it->multiply(dx);
342 this->doRandomize(dx);
348 template <
typename MODEL>
351 if (chvars_.size()) {
353 std::unique_ptr<Increment_> dxchvarin(
new Increment_(dxi));
354 for (
ircst_ it = chvars_.rbegin(); it != chvars_.rend(); ++it) {
355 Increment_ dxchvarout = it->multiplyAD(*dxchvarin);
360 this->doMultiply(*dxchvarin, dxchvarout);
364 for (
icst_ it = chvars_.begin(); it != chvars_.end(); ++it) {
365 Increment_ dxchvarout = it->multiply(*dxchvarin);
370 this->doMultiply(dxi, dxo);
376 template <
typename MODEL>
383 GMRESR(dxo, dxi, *
this, Id, fullInverseIterations_, fullInverseAccuracy_);
385 if (chvars_.size()) {
387 std::unique_ptr<Increment_> dxchvarin(
new Increment_(dxi));
388 for (
ircst_ it = chvars_.rbegin(); it != chvars_.rend(); ++it) {
389 Increment_ dxchvarout = it->multiplyInverse(*dxchvarin);
394 this->doInverseMultiply(*dxchvarin, dxchvarout);
398 for (
icst_ it = chvars_.begin(); it != chvars_.end(); ++it) {
399 Increment_ dxchvarout = it->multiplyInverseAD(*dxchvarin);
404 this->doInverseMultiply(dxi, dxo);
411 template <
typename MODEL>
418 for (
size_t ie = 0; ie < randomizationSize_; ++ie) {
423 double rk_var =
static_cast<double>(ie)/
static_cast<double>(ie+1);
424 double rk_mean = 1.0/
static_cast<double>(ie+1);
425 variance.
axpy(rk_var, dxsq,
false);
426 mean.
axpy(rk_mean, dx,
false);
428 double rk_norm = 1.0/
static_cast<double>(randomizationSize_-1);
Geometry< MODEL > Geometry_
CovarMaker(const std::string &name)
ModelSpaceCovarianceBase< MODEL > * make(const ModelSpaceCovarianceParametersBase< MODEL > ¶ms, const Geometry_ &resol, const Variables &vars, const State_ &xb, const State_ &fg) override
TParameters_IfAvailableElseFallbackType_t< COVAR, GenericModelSpaceCovarianceParameters< MODEL > > Parameters_
std::unique_ptr< ModelSpaceCovarianceParametersBase< MODEL > > makeParameters() const override
virtual std::unique_ptr< ModelSpaceCovarianceParametersBase< MODEL > > makeParameters() const =0
Geometry< MODEL > Geometry_
static std::vector< std::string > getMakerNames()
Return the names of all covariance models that can be created by one of the registered makers.
CovarianceFactory(const std::string &name)
Register a maker able to create covariance models of type name.
virtual ModelSpaceCovarianceBase< MODEL > * make(const ModelSpaceCovarianceParametersBase< MODEL > &, const Geometry_ &, const Variables &, const State_ &, const State_ &)=0
virtual ~CovarianceFactory()=default
static std::unique_ptr< ModelSpaceCovarianceParametersBase< MODEL > > createParameters(const std::string &covarianceModel)
Create and return an instance of the subclass of ModelSpaceCovarianceParametersBase storing parameter...
static ModelSpaceCovarianceBase< MODEL > * create(const ModelSpaceCovarianceParametersBase< MODEL > &, const Geometry_ &, const Variables &, const State_ &, const State_ &)
Create and return a new covariance model.
static std::map< std::string, CovarianceFactory< MODEL > * > & getMakers()
A subclass of ModelSpaceCovarianceParametersBase storing the values of all options in a single Config...
Geometry class used in oops; subclass of interface class interface::Geometry.
Increment class used in oops.
LinearVariableChange factory.
Base class of classes storing parameters controlling specific linear variable changes.
OptionalParameter< Variables > outputVariables
OptionalParameter< Variables > inputVariables
Contains a polymorphic parameter holding an instance of a subclass of LinearVariableChangeParametersB...
ChvarVec_::const_reverse_iterator ircst_
Increment< MODEL > Increment_
virtual ~ModelSpaceCovarianceBase()
LinearVariableChangeBase< MODEL > LinearVariableChangeBase_
double fullInverseAccuracy_
virtual void doMultiply(const Increment_ &, Increment_ &) const =0
boost::ptr_vector< LinearVariableChangeBase_ > ChvarVec_
void getVariance(Increment_ &) const
Geometry< MODEL > Geometry_
ModelSpaceCovarianceBase(const State_ &, const State_ &, const Geometry_ &, const ModelSpaceCovarianceParametersBase< MODEL > &)
ChvarVec_::const_iterator icst_
void randomize(Increment_ &) const
virtual void doInverseMultiply(const Increment_ &, Increment_ &) const =0
void inverseMultiply(const Increment_ &, Increment_ &) const
ChvarVec_::iterator iter_
virtual void doRandomize(Increment_ &) const =0
size_t randomizationSize_
void multiply(const Increment_ &, Increment_ &) const
int fullInverseIterations_
Base class for classes storing parameters of a particular model-space error covariance implementation...
Parameter< bool > fullInverse
Parameter< int > fullInverseIterations
Parameter< std::vector< LinearVariableChangeParametersWrapper< MODEL > > > variableChanges
Parameter< double > fullInverseAccuracy
OptionalParameter< std::string > covarianceModel
Covariance model name.
Parameter< size_t > randomizationSize
Contains a polymorphic parameter holding an instance of a subclass of ModelSpaceCovarianceParametersB...
RequiredPolymorphicParameter< ModelSpaceCovarianceParametersBase< MODEL >, CovarianceFactory< MODEL > > covarianceParameters
State class used in oops; subclass of interface class interface::State.
void axpy(const double &w, const Increment &dx, const bool check=true)
void schur_product_with(const Increment &other)
Compute Schur product of this Increment with other, assign to this Increment.
void zero()
Zero out this Increment.
The namespace for the main oops code.
double GMRESR(VECTOR &xx, const VECTOR &bb, const AMATRIX &A, const PMATRIX &precond, const int maxiter, const double tolerance)