IODA
test/ioda/ObsVector.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_IODA_OBSVECTOR_H_
12 #define TEST_IODA_OBSVECTOR_H_
13 
14 #include <memory>
15 #include <string>
16 #include <vector>
17 
18 #include <boost/shared_ptr.hpp>
19 
20 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
21 
22 #include "eckit/config/LocalConfiguration.h"
23 #include "eckit/testing/Test.h"
24 
25 #include "oops/mpi/mpi.h"
26 #include "oops/runs/Test.h"
27 #include "oops/test/TestEnvironment.h"
28 #include "oops/util/dot_product.h"
29 #include "oops/util/Logger.h"
30 
31 #include "ioda/IodaTrait.h"
32 #include "ioda/ObsSpace.h"
33 #include "ioda/ObsVector.h"
34 
35 namespace ioda {
36 namespace test {
37 
38 // -----------------------------------------------------------------------------
39 
40 class ObsVecTestFixture : private boost::noncopyable {
42 
43  public:
44  static std::vector<boost::shared_ptr<ObsSpace_> > & obspace() {return getInstance().ospaces_;}
45 
46  private:
48  static ObsVecTestFixture theObsVecTestFixture;
49  return theObsVecTestFixture;
50  }
51 
53  util::DateTime bgn((::test::TestEnvironment::config().getString("window begin")));
54  util::DateTime end((::test::TestEnvironment::config().getString("window end")));
55 
56  std::vector<eckit::LocalConfiguration> conf;
57  ::test::TestEnvironment::config().get("observations", conf);
58 
59  for (std::size_t jj = 0; jj < conf.size(); ++jj) {
60  eckit::LocalConfiguration obsconf(conf[jj], "obs space");
61  boost::shared_ptr<ObsSpace_> tmp(new ObsSpace_(obsconf, oops::mpi::world(),
62  bgn, end, oops::mpi::myself()));
63  ospaces_.push_back(tmp);
64  eckit::LocalConfiguration ObsDataInConf;
65  obsconf.get("obsdatain", ObsDataInConf);
66  }
67  }
68 
70 
71  std::vector<boost::shared_ptr<ObsSpace_> > ospaces_;
72 };
73 
74 // -----------------------------------------------------------------------------
75 
76 void testConstructor() {
77  typedef ObsVecTestFixture Test_;
78  typedef ioda::ObsVector ObsVector_;
79 
80  for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
81  std::unique_ptr<ObsVector_> ov(new ObsVector_(*Test_::obspace()[jj]));
82  EXPECT(ov.get());
83 
84  ov.reset();
85  EXPECT(!ov.get());
86  }
87 }
88 
89 // -----------------------------------------------------------------------------
90 
92  typedef ObsVecTestFixture Test_;
93  typedef ioda::ObsVector ObsVector_;
94 
95  for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
96  std::unique_ptr<ObsVector_> ov(new ObsVector_(*Test_::obspace()[jj]));
97 
98  std::unique_ptr<ObsVector_> other(new ObsVector_(*ov));
99  EXPECT(other.get());
100 
101  other.reset();
102  EXPECT(!other.get());
103 
104  EXPECT(ov.get());
105  }
106 }
107 
108 // -----------------------------------------------------------------------------
109 
110 void testNotZero() {
111  typedef ObsVecTestFixture Test_;
112  typedef ioda::ObsVector ObsVector_;
113  const double zero = 0.0;
114 
115  for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
116  ObsVector_ ov(*Test_::obspace()[jj]);
117 
118  ov.random();
119 
120  const double ovov2 = dot_product(ov, ov);
121  EXPECT(ovov2 > zero);
122 
123  ov.zero();
124 
125  const double zz = dot_product(ov, ov);
126  EXPECT(zz == zero);
127  }
128 }
129 
130 // -----------------------------------------------------------------------------
131 
132 void testRead() {
133  typedef ObsVecTestFixture Test_;
134  typedef ioda::ObsVector ObsVector_;
135 
136  std::vector<eckit::LocalConfiguration> conf;
137  ::test::TestEnvironment::config().get("observations", conf);
138 
139  for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
140  ioda::ObsSpace * Odb = Test_::obspace()[jj].get();
141 
142  // Grab the expected RMS value and tolerance from the obsdb_ configuration.
143  double ExpectedRms = conf[jj].getDouble("obs space.obsdatain.rms ref");
144  double Tol = conf[jj].getDouble("obs space.obsdatain.tolerance");
145 
146  // Read in a vector and check contents with norm function.
147  std::unique_ptr<ObsVector_> ov(new ObsVector_(*Odb, "ObsValue"));
148  double Rms = ov->rms();
149 
150  EXPECT(oops::is_close(Rms, ExpectedRms, Tol));
151  }
152 }
153 
154 // -----------------------------------------------------------------------------
155 
156 void testSave() {
157  typedef ObsVecTestFixture Test_;
158  typedef ioda::ObsVector ObsVector_;
159 
160  ioda::ObsSpace * Odb;
161  double Rms;
162  double ExpectedRms;
163 
164  for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
165  Odb = Test_::obspace()[jj].get();
166 
167  // Read in a vector and save the rms value. Then write the vector into a
168  // test group, read it out of the test group and compare the rms of the
169  // vector read out of the test group with that of the original.
170  std::unique_ptr<ObsVector_> ov_orig(new ObsVector_(*Odb, "ObsValue"));
171  ExpectedRms = ov_orig->rms();
172  ov_orig->save("ObsTest");
173 
174  std::unique_ptr<ObsVector_> ov_test(new ObsVector_(*Odb, "ObsTest"));
175  Rms = ov_test->rms();
176 
177  EXPECT(oops::is_close(Rms, ExpectedRms, 1.0e-12));
178  }
179 }
180 
181 // -----------------------------------------------------------------------------
182 
184  typedef ioda::ObsVector ObsVector_;
185  typedef ioda::ObsSpace ObsSpace_;
186  typedef std::vector< std::shared_ptr< ObsVector_> > ObsVectors_;
187 
188  // Some of the ObsVector math routines require global communications,
189  // and so are performed differently for different distributions. But the
190  // answers should always be the same regardless of distribution.
191 
192  // get the list of distributions to test with
193  std::vector<std::string> dist_names =
194  ::test::TestEnvironment::config().getStringVector("distributions");
195  for (std::size_t ii = 0; ii < dist_names.size(); ++ii) {
196  oops::Log::debug() << "using distribution: " << dist_names[ii] << std::endl;
197  }
198 
199  // Get some config information that is the same regardless of distribution
200  util::DateTime bgn((::test::TestEnvironment::config().getString("window begin")));
201  util::DateTime end((::test::TestEnvironment::config().getString("window end")));
202  std::vector<eckit::LocalConfiguration> conf;
203  ::test::TestEnvironment::config().get("observations", conf);
204 
205  // for each distribution, create the set of obs vectors
206  std::vector< ObsVectors_ > dist_obsvecs;
207  std::vector< std::shared_ptr<ObsSpace_> > dist_obsdbs;
208  for (std::size_t dd = 0; dd < dist_names.size(); ++dd) {
209  ObsVectors_ obsvecs;
210  for (std::size_t jj = 0; jj < conf.size(); ++jj) {
211  eckit::LocalConfiguration obsconf(conf[jj], "obs space");
212  obsconf.set("distribution", dist_names[dd]);
213  std::shared_ptr<ObsSpace_> obsdb(new ObsSpace(obsconf, oops::mpi::world(),
214  bgn, end, oops::mpi::myself()));
215  std::shared_ptr<ObsVector_> obsvec(new ObsVector_(*obsdb, "ObsValue"));
216  oops::Log::debug() << dist_names[dd] << ": " << *obsvec << std::endl;
217  dist_obsdbs.push_back(obsdb);
218  obsvecs.push_back(obsvec);
219  }
220  dist_obsvecs.push_back(obsvecs);
221  }
222 
223  // For each ObsVector make sure the math is the same regardless of distribution.
224  // Test rms(), nobs(), dot_product_with()
225  for (std::size_t ii = 0; ii < conf.size(); ++ii) {
226  // get the values for the first distribution
227  int nobs = dist_obsvecs[0][ii]->nobs();
228  double rms = dist_obsvecs[0][ii]->rms();
229  double dot = dist_obsvecs[0][ii]->dot_product_with(*dist_obsvecs[0][ii]);
230 
231  // make sure the values are the same for all the other distributions
232  for (std::size_t jj = 1; jj < dist_obsvecs.size(); ++jj) {
233  int nobs2 = dist_obsvecs[jj][ii]->nobs();
234  double rms2 = dist_obsvecs[jj][ii]->rms();
235  double dot2 = dist_obsvecs[jj][ii]->dot_product_with(*dist_obsvecs[jj][ii]);
236 
237  EXPECT(nobs == nobs2);
238  EXPECT(oops::is_close(rms, rms2, 1.0e-12));
239  EXPECT(oops::is_close(dot, dot2, 1.0e-12));
240  }
241  }
242 }
243 
244 // -----------------------------------------------------------------------------
245 
246 class ObsVector : public oops::Test {
247  public:
249  virtual ~ObsVector() {}
250 
251  private:
252  std::string testid() const override {return "test::ObsVector<ioda::IodaTrait>";}
253 
254  void register_tests() const override {
255  std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
256 
257  ts.emplace_back(CASE("ioda/ObsVector/testConstructor")
258  { testConstructor(); });
259  ts.emplace_back(CASE("ioda/ObsVector/testCopyConstructor")
260  { testCopyConstructor(); });
261  ts.emplace_back(CASE("ioda/ObsVector/testNotZero")
262  { testNotZero(); });
263  ts.emplace_back(CASE("ioda/ObsVector/testRead")
264  { testRead(); });
265  ts.emplace_back(CASE("ioda/ObsVector/testSave")
266  { testSave(); });
267  ts.emplace_back(CASE("ioda/ObsVector/testDistributedMath")
268  { testDistributedMath(); });
269  }
270 
271  void clear() const override {}
272 };
273 
274 // =============================================================================
275 
276 } // namespace test
277 } // namespace ioda
278 
279 #endif // TEST_IODA_OBSVECTOR_H_
ioda::test::testCopyConstructor
void testCopyConstructor()
Definition: test/ioda/ObsVector.h:91
ioda::test::ObsVector::~ObsVector
virtual ~ObsVector()
Definition: test/ioda/ObsVector.h:249
ioda::test::ObsVecTestFixture::ObsVecTestFixture
ObsVecTestFixture()
Definition: test/ioda/ObsVector.h:52
ObsSpace.h
ioda::test::testDistributedMath
void testDistributedMath()
Definition: test/ioda/ObsVector.h:183
ioda::test::ObsVecTestFixture::ospaces_
std::vector< boost::shared_ptr< ObsSpace_ > > ospaces_
Definition: test/ioda/ObsVector.h:71
ioda::test::testNotZero
void testNotZero()
Definition: test/ioda/ObsVector.h:110
ioda::test::ObsVecTestFixture::obspace
static std::vector< boost::shared_ptr< ObsSpace_ > > & obspace()
Definition: test/ioda/ObsVector.h:44
ioda::test::ObsVector::ObsVector
ObsVector()
Definition: test/ioda/ObsVector.h:248
ioda
Definition: IodaUtils.cc:13
ioda::ObsVector
ObsVector class to handle vectors in observation space for IODA.
Definition: src/ObsVector.h:34
ioda::test::testRead
void testRead()
Definition: test/ioda/ObsVector.h:132
ioda::test::testConstructor
void testConstructor()
Definition: test/core/ObsSpaceContainer.h:76
ioda::test::ObsVector::register_tests
void register_tests() const override
Definition: test/ioda/ObsVector.h:254
ioda::test::testSave
void testSave()
Definition: test/ioda/ObsVector.h:156
ioda::test::ObsVecTestFixture::ObsSpace_
ioda::ObsSpace ObsSpace_
Definition: test/ioda/ObsVector.h:41
ioda::test::ObsSpace
Definition: test/ioda/ObsSpace.h:309
ioda::test::ObsVecTestFixture::getInstance
static ObsVecTestFixture & getInstance()
Definition: test/ioda/ObsVector.h:47
ioda::test::ObsVector::testid
std::string testid() const override
Definition: test/ioda/ObsVector.h:252
ioda::test::ObsVecTestFixture::~ObsVecTestFixture
~ObsVecTestFixture()
Definition: test/ioda/ObsVector.h:69
ioda::test::ObsVector::clear
void clear() const override
Definition: test/ioda/ObsVector.h:271
ObsVector.h
ioda::test::ObsVecTestFixture
Definition: test/ioda/ObsVector.h:40
ioda::ObsSpace
Observation Space View.
Definition: src/ObsSpace.h:35
ioda::test::ObsVector
Definition: test/ioda/ObsVector.h:246