IODA Bundle
ObsErrorCovariance.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 TEST_BASE_OBSERRORCOVARIANCE_H_
12 #define TEST_BASE_OBSERRORCOVARIANCE_H_
13 
14 #include <memory>
15 #include <string>
16 #include <vector>
17 
18 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
19 
20 #include "eckit/testing/Test.h"
21 #include "oops/base/ObsError.h"
24 #include "oops/runs/Test.h"
26 #include "test/TestEnvironment.h"
27 
28 namespace test {
29 
30 // -----------------------------------------------------------------------------
31 /// Tests creation and destruction of ObsErrorCovariances
32 template <typename OBS> void testConstructor() {
33  typedef ObsTestsFixture<OBS> Test_;
34  typedef oops::ObsError<OBS> Covar_;
35 
36  oops::instantiateObsErrorFactory<OBS>();
37 
38  std::vector<eckit::LocalConfiguration> conf;
39  TestEnvironment::config().get("observations", conf);
40 
41  for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
42  const eckit::LocalConfiguration rconf(conf[jj], "obs error");
43  std::unique_ptr<Covar_> R = std::make_unique<Covar_>(rconf, Test_::obspace()[jj]);
44  EXPECT(R.get());
45  oops::Log::test() << "Testing ObsError: " << *R << std::endl;
46  R.reset();
47  EXPECT(!R.get());
48  }
49 }
50 
51 // -----------------------------------------------------------------------------
52 /// Tests that \f$R*R^{-1}*dy = dy\f$ and \f$R^{-1}*R*dy = dy\f$
53 template <typename OBS> void testMultiplies() {
54  typedef ObsTestsFixture<OBS> Test_;
55  typedef oops::ObsError<OBS> Covar_;
56  typedef oops::ObsVector<OBS> ObsVector_;
57 
58  oops::instantiateObsErrorFactory<OBS>();
59 
60  std::vector<eckit::LocalConfiguration> conf;
61  TestEnvironment::config().get("observations", conf);
62 
63  for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
64  ObsVector_ obserr(Test_::obspace()[jj], "ObsError");
65 
66  const eckit::LocalConfiguration rconf(conf[jj], "obs error");
67  Covar_ R(rconf, Test_::obspace()[jj]);
68 
69  // RMSE should be equal to the rms that was read from the file
70  EXPECT(oops::is_close(R.getRMSE(), obserr.rms(), 1.e-10));
71 
72  // create random vector dy and its copies dy1, dy2
73  ObsVector_ dy(Test_::obspace()[jj]);
74  R.randomize(dy);
75  ObsVector_ dy1(dy);
76  ObsVector_ dy2(dy);
77  oops::Log::test() << "Random vector dy: " << dy << std::endl;
78 
79  R.multiply(dy1);
80  oops::Log::test() << "R*dy: " << dy1 << std::endl;
81  R.inverseMultiply(dy1);
82  // dy1 = R^{-1}*R*dy
83  oops::Log::test() << "R^{-1}*R*dy: " << dy1 << std::endl;
84  EXPECT(oops::is_close(dy1.rms(), dy.rms(), 1.e-10));
85 
86  R.inverseMultiply(dy2);
87  oops::Log::test() << "R^{-1}*dy: " << dy2 << std::endl;
88  R.multiply(dy2);
89  // dy2 = R*R^P-1}*dy
90  oops::Log::test() << "R*R^{-1}*dy: " << dy2 << std::endl;
91  EXPECT(oops::is_close(dy2.rms(), dy.rms(), 1.e-10));
92  }
93 }
94 
95 // -----------------------------------------------------------------------------
96 /// Tests that the methods obserrors(), inverseVariance update() and save()
97 /// do what is expected.
98 template <typename OBS> void testAccessors() {
99  typedef ObsTestsFixture<OBS> Test_;
100  typedef oops::ObsError<OBS> Covar_;
101  typedef oops::ObsVector<OBS> ObsVector_;
102 
103  oops::instantiateObsErrorFactory<OBS>();
104 
105  std::vector<eckit::LocalConfiguration> conf;
106  TestEnvironment::config().get("observations", conf);
107 
108  for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
109  ObsVector_ obserr(Test_::obspace()[jj], "ObsError");
110 
111  const eckit::LocalConfiguration rconf(conf[jj], "obs error");
112  Covar_ R(rconf, Test_::obspace()[jj]);
113 
114  ObsVector_ dy(R.obserrors());
115  oops::Log::test() << "ObsError: " << dy << std::endl;
116  EXPECT(oops::is_close(dy.rms(), obserr.rms(), 1.e-10));
117 
118  ObsVector_ dy1(R.inverseVariance());
119  oops::Log::test() << "inverseVariance: " << dy1 << std::endl;
120  dy *= dy;
121  dy.invert();
122  EXPECT(oops::is_close(dy.rms(), dy1.rms(), 1.e-10));
123 
124  dy.ones();
125  R.update(dy);
126  oops::Log::test() << "R filled with ones: " << R.obserrors() << std::endl;
127  EXPECT(oops::is_close(R.obserrors().rms(), R.inverseVariance().rms(), 1.e-10));
128  EXPECT(oops::is_close(R.obserrors().rms(), dy.rms(), 1.e-10));
129 
130  R.save("Ones");
131  ObsVector_ testOnes(Test_::obspace()[jj], "Ones");
132  EXPECT(oops::is_close(dy.rms(), testOnes.rms(), 1.e-10));
133  }
134 }
135 
136 // -----------------------------------------------------------------------------
137 
138 template <typename OBS>
141  public:
143  virtual ~ObsErrorCovariance() {}
144  private:
145  std::string testid() const override {return "test::ObsErrorCovariance<" + OBS::name() + ">";}
146 
147  void register_tests() const override {
148  std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
149 
150  ts.emplace_back(CASE("interface/ObsErrorCovariance/testConstructor")
151  { testConstructor<OBS>(); });
152  ts.emplace_back(CASE("interface/ObsErrorCovariance/testMultiplies")
153  { testMultiplies<OBS>(); });
154  ts.emplace_back(CASE("interface/ObsErrorCovariance/testAccessors")
155  { testAccessors<OBS>(); });
156  }
157 
158  void clear() const override {
159  Test_::reset();
160  }
161 };
162 
163 // -----------------------------------------------------------------------------
164 
165 } // namespace test
166 
167 #endif // TEST_BASE_OBSERRORCOVARIANCE_H_
program test
Observation error covariance matrix of observations from a single ObsSpace.
Definition: ObsError.h:29
void register_tests() const override
ObsTestsFixture< OBS > Test_
void clear() const override
std::string testid() const override
static const eckit::Configuration & config()
void testAccessors()
void testMultiplies()
Tests that and .
CASE("assimilation/FullGMRES/FullGMRES")
void testConstructor()
Tests creation and destruction of ObsErrorCovariances.