IODA Bundle
generic/ObsErrorBase.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_GENERIC_OBSERRORBASE_H_
12 #define OOPS_GENERIC_OBSERRORBASE_H_
13 
14 #include <map>
15 #include <memory>
16 #include <string>
17 
18 #include <boost/noncopyable.hpp>
19 #include "eckit/config/Configuration.h"
20 
23 #include "oops/util/abor1_cpp.h"
24 #include "oops/util/Logger.h"
25 #include "oops/util/Printable.h"
26 
27 namespace oops {
28 
29 // -----------------------------------------------------------------------------
30 /// \brief Base class for generic implementations of observation error covariance matrices.
31 ///
32 /// Use this class as a base class for generic implementations,
33 /// and interface::ObsErrorBase as a base class for OBS-specific implementations.
34 ///
35 /// Note: generic implementations need to provide a constructor with the following signature:
36 ///
37 /// ObsErrorBase(const eckit::Configuration &config, ObsSpace<OBS> &obsspace);
38 template<typename OBS>
39 class ObsErrorBase : public util::Printable,
40  private boost::noncopyable {
43 
44  public:
45  ObsErrorBase() = default;
46  virtual ~ObsErrorBase() = default;
47 
48 /// Multiply a Departure \p dy by \f$R\f$.
49  virtual void multiply(ObsVector_ & dy) const = 0;
50 /// Multiply a Departure \p dy by \f$R^{-1}\f$.
51  virtual void inverseMultiply(ObsVector_ & dy) const = 0;
52 
53 /// Generate random perturbation in \p dy.
54  virtual void randomize(ObsVector_ & dy) const = 0;
55 
56 /// Save obs errors to the group \p name.
57  virtual void save(const std::string &name) const = 0;
58 
59 /// Return a copy of obs error std. dev. If this ObsVector_ is modified (e.g. by obs filters),
60 /// it should be passed back to update() to ensure the covariance matrix stays consistent.
61  virtual ObsVector_ obserrors() const = 0;
62 
63 /// Set the diagonal of the covariance matrix to \p stddev squared.
64  virtual void update(const ObsVector_ &stddev) = 0;
65 
66 /// Return the vector of inverse obs error variances.
67  virtual ObsVector_ inverseVariance() const = 0;
68 
69 /// Get mean error for Jo table.
70  virtual double getRMSE() const = 0;
71 
72  private:
73  virtual void print(std::ostream &) const = 0;
74 };
75 
76 // =============================================================================
77 
78 /// A factory creating instances of concrete subclasses of ObsErrorBase.
79 template <typename OBS>
83  public:
84  static std::unique_ptr<ObsErrorBase_> create(const eckit::Configuration &,
85  const ObsSpace_ &);
86  virtual ~ObsErrorFactory() = default;
87  protected:
88  explicit ObsErrorFactory(const std::string &);
89  private:
90  virtual std::unique_ptr<ObsErrorBase_> make(const eckit::Configuration &, const ObsSpace_ &) = 0;
91  static std::map < std::string, ObsErrorFactory<OBS> * > & getMakers() {
92  static std::map < std::string, ObsErrorFactory<OBS> * > makers_;
93  return makers_;
94  }
95 };
96 
97 // -----------------------------------------------------------------------------
98 
99 /// \brief A subclass of ObsErrorFactory able to create instances of T (a concrete subclass of
100 /// ObsErrorBase<OBS>). Passes ObsSpace<OBS> to the constructor of T.
101 template<class OBS, class T>
102 class ObsErrorMaker : public ObsErrorFactory<OBS> {
105  std::unique_ptr<ObsErrorBase_> make(const eckit::Configuration & conf,
106  const ObsSpace_ & obs) override
107  { return std::make_unique<T>(conf, obs); }
108  public:
109  explicit ObsErrorMaker(const std::string & name) : ObsErrorFactory<OBS>(name) {}
110 };
111 
112 // =============================================================================
113 
114 template <typename OBS>
116  if (getMakers().find(name) != getMakers().end()) {
117  throw std::runtime_error(name + " already registered in obs error factory.");
118  }
119  getMakers()[name] = this;
120 }
121 
122 // -----------------------------------------------------------------------------
123 
124 template <typename OBS>
125 std::unique_ptr<ObsErrorBase<OBS>>
126 ObsErrorFactory<OBS>::create(const eckit::Configuration & conf, const ObsSpace_ & obs) {
127  Log::trace() << "ObsErrorFactory<OBS>::create starting" << std::endl;
128  const std::string id = conf.getString("covariance model", "diagonal");
129  Log::trace() << "ObsError matrix type is: " << id << std::endl;
130  typename std::map<std::string, ObsErrorFactory<OBS>*>::iterator
131  jerr = getMakers().find(id);
132  if (jerr == getMakers().end()) {
133  throw std::runtime_error(id + " does not exist in obs error factory.");
134  }
135  std::unique_ptr<ObsErrorBase<OBS>> ptr(jerr->second->make(conf, obs));
136  Log::trace() << "ObsErrorFactory<OBS>::create done" << std::endl;
137  return ptr;
138 }
139 
140 // -----------------------------------------------------------------------------
141 
142 } // namespace oops
143 
144 #endif // OOPS_GENERIC_OBSERRORBASE_H_
Base class for generic implementations of observation error covariance matrices.
virtual void update(const ObsVector_ &stddev)=0
Set the diagonal of the covariance matrix to stddev squared.
ObsErrorBase()=default
virtual void multiply(ObsVector_ &dy) const =0
Multiply a Departure dy by .
ObsVector< OBS > ObsVector_
virtual void print(std::ostream &) const =0
virtual double getRMSE() const =0
Get mean error for Jo table.
ObsSpace< OBS > ObsSpace_
virtual ObsVector_ obserrors() const =0
virtual ~ObsErrorBase()=default
virtual void randomize(ObsVector_ &dy) const =0
Generate random perturbation in dy.
virtual void save(const std::string &name) const =0
Save obs errors to the group name.
virtual void inverseMultiply(ObsVector_ &dy) const =0
Multiply a Departure dy by .
virtual ObsVector_ inverseVariance() const =0
Return the vector of inverse obs error variances.
A factory creating instances of concrete subclasses of ObsErrorBase.
virtual std::unique_ptr< ObsErrorBase_ > make(const eckit::Configuration &, const ObsSpace_ &)=0
virtual ~ObsErrorFactory()=default
ObsErrorBase< OBS > ObsErrorBase_
static std::unique_ptr< ObsErrorBase_ > create(const eckit::Configuration &, const ObsSpace_ &)
static std::map< std::string, ObsErrorFactory< OBS > * > & getMakers()
ObsErrorFactory(const std::string &)
A subclass of ObsErrorFactory able to create instances of T (a concrete subclass of ObsErrorBase<OBS>...
std::unique_ptr< ObsErrorBase_ > make(const eckit::Configuration &conf, const ObsSpace_ &obs) override
ObsErrorBase< OBS > ObsErrorBase_
ObsErrorMaker(const std::string &name)
The namespace for the main oops code.