11 #ifndef TEST_IODA_OBSVECTOR_H_
12 #define TEST_IODA_OBSVECTOR_H_
18 #include <boost/shared_ptr.hpp>
20 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
22 #include "eckit/config/LocalConfiguration.h"
23 #include "eckit/testing/Test.h"
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"
31 #include "ioda/IodaTrait.h"
48 for (
auto &space : spaces) {
57 return theObsVecTestFixture;
61 util::DateTime bgn((::test::TestEnvironment::config().getString(
"window begin")));
62 util::DateTime end((::test::TestEnvironment::config().getString(
"window end")));
64 std::vector<eckit::LocalConfiguration> conf;
65 ::test::TestEnvironment::config().get(
"observations", conf);
67 for (std::size_t jj = 0; jj < conf.size(); ++jj) {
68 eckit::LocalConfiguration obsconf(conf[jj],
"obs space");
70 obsparams.validateAndDeserialize(obsconf);
71 boost::shared_ptr<ObsSpace_> tmp(
new ObsSpace_(obsparams, oops::mpi::world(),
72 bgn, end, oops::mpi::myself()));
79 std::vector<boost::shared_ptr<ObsSpace_> >
ospaces_;
88 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
89 std::unique_ptr<ObsVector_> ov(
new ObsVector_(*Test_::obspace()[jj]));
103 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
104 std::unique_ptr<ObsVector_> ov(
new ObsVector_(*Test_::obspace()[jj]));
106 std::unique_ptr<ObsVector_> other(
new ObsVector_(*ov));
110 EXPECT(!other.get());
121 const double zero = 0.0;
123 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
124 ObsVector_ ov(*Test_::obspace()[jj]);
128 const double ovov2 = dot_product(ov, ov);
129 EXPECT(ovov2 > zero);
133 const double zz = dot_product(ov, ov);
141 typedef ObsVecTestFixture Test_;
144 std::vector<eckit::LocalConfiguration> conf;
145 ::test::TestEnvironment::config().get(
"observations", conf);
147 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
152 eckit::LocalConfiguration testConfig;
153 conf[jj].get(
"test data", testConfig);
154 double ExpectedRms = testConfig.getDouble(
"rms ref");
155 double Tol = testConfig.getDouble(
"tolerance");
158 std::unique_ptr<ObsVector_> ov(
new ObsVector_(*Odb,
"ObsValue"));
159 double Rms = ov->rms();
161 EXPECT(oops::is_close(Rms, ExpectedRms, Tol));
175 std::vector<eckit::LocalConfiguration> conf;
176 ::test::TestEnvironment::config().get(
"observations", conf);
178 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
179 Odb = Test_::obspace()[jj].get();
180 bool read_obs_from_separate_file =
181 conf[jj].getBool(
"obs space.read obs from separate file",
false);
186 std::unique_ptr<ObsVector_> ov_orig(
new ObsVector_(*Odb,
"ObsValue"));
187 ExpectedRms = ov_orig->rms();
189 if (!read_obs_from_separate_file)
190 ov_orig->save(
"ObsTest");
192 std::unique_ptr<ObsVector_> ov_test(
new ObsVector_(*Odb,
"ObsTest"));
193 Rms = ov_test->rms();
195 EXPECT(oops::is_close(Rms, ExpectedRms, 1.0e-12));
211 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
213 ObsVector_ vec1(obspace);
217 ObsVector_ vec2(vec1);
218 vec2.axpy(2.0, vec1);
219 ObsVector_ vec3(vec1);
220 std::vector<double> beta(obspace.obsvariables().size(), 2.0);
221 vec3.axpy(beta, vec1);
222 oops::Log::test() <<
"Testing ObsVector::axpy" << std::endl;
223 oops::Log::test() <<
"x = " << vec1 << std::endl;
224 oops::Log::test() <<
"x.axpy(2, x) = " << vec2 << std::endl;
225 oops::Log::test() <<
"x.axpy(vector of 2, x) = " << vec3 << std::endl;
226 EXPECT(oops::is_close(vec2.rms(), vec3.rms(), 1.0e-8));
229 std::vector<double> beta1(obspace.obsvariables().size());
230 std::vector<double> beta2(obspace.obsvariables().size());
231 for (
size_t jj = 0; jj < beta1.size(); ++jj) {
232 beta1[jj] =
static_cast<double>(jj)/beta1.size();
233 beta2[jj] = 2.0 - beta1[jj];
235 oops::Log::test() <<
"beta1 = " << beta1 <<
", beta2 = " << beta2 << std::endl;
236 ObsVector_ vec4(vec1);
237 vec4.axpy(beta1, vec1);
238 oops::Log::test() <<
"x.axpy(beta1, x) = " << vec4 << std::endl;
239 vec4.axpy(beta2, vec1);
240 oops::Log::test() <<
"x.axpy(beta2, x) = " << vec4 << std::endl;
241 EXPECT(oops::is_close(vec4.rms(), vec3.rms(), 1.0e-8));
253 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
255 ObsVector_ vec1(obspace);
257 ObsVector_ vec2(obspace);
260 double dp1 = vec1.dot_product_with(vec2);
261 std::vector<double> dp2 = vec1.multivar_dot_product_with(vec2);
262 oops::Log::test() <<
"Testing ObsVector::dot_product" << std::endl;
263 oops::Log::test() <<
"x1 = " << vec1 << std::endl;
264 oops::Log::test() <<
"x2 = " << vec2 << std::endl;
265 oops::Log::test() <<
"x1.dot_product_with(x2) = " << dp1 << std::endl;
266 oops::Log::test() <<
"x1.multivar_dot_product_with(x2) = " << dp2 << std::endl;
269 EXPECT_EQUAL(dp2.size(), vec1.nvars());
272 EXPECT(oops::is_close(dp1, std::accumulate(dp2.begin(), dp2.end(), 0.0), 1.0e-12));
281 typedef std::vector< std::shared_ptr< ObsVector_> > ObsVectors_;
288 std::vector<std::string> dist_names =
289 ::test::TestEnvironment::config().getStringVector(
"distributions");
290 for (std::size_t ii = 0; ii < dist_names.size(); ++ii) {
291 oops::Log::debug() <<
"using distribution: " << dist_names[ii] << std::endl;
295 util::DateTime bgn((::test::TestEnvironment::config().getString(
"window begin")));
296 util::DateTime end((::test::TestEnvironment::config().getString(
"window end")));
297 std::vector<eckit::LocalConfiguration> conf;
298 ::test::TestEnvironment::config().get(
"observations", conf);
301 std::vector< ObsVectors_ > dist_obsvecs;
302 std::vector< std::shared_ptr<ObsSpace_> > dist_obsdbs;
303 for (std::size_t dd = 0; dd < dist_names.size(); ++dd) {
305 for (std::size_t jj = 0; jj < conf.size(); ++jj) {
324 eckit::LocalConfiguration obsconf(conf[jj],
"obs space");
325 obsconf.set(
"distribution", dist_names[dd]);
326 if (obsconf.has(
"obsdataout.obsfile")) {
327 std::string fileName = obsconf.getString(
"obsdataout.obsfile");
328 std::string fileTag = std::string(
"_Dist_") + dist_names[dd];
329 std::size_t pos = fileName.find_last_of(
".");
330 if (pos != std::string::npos) {
332 fileName.insert(pos, fileTag);
337 obsconf.set(
"obsdataout.obsfile", fileName);
341 obsparams.validateAndDeserialize(obsconf);
344 std::shared_ptr<ObsSpace_> obsdb(
new ObsSpace(obsparams, oops::mpi::world(),
345 bgn, end, oops::mpi::myself()));
346 std::shared_ptr<ObsVector_> obsvec(
new ObsVector_(*obsdb,
"ObsValue"));
347 oops::Log::debug() << dist_names[dd] <<
": " << *obsvec << std::endl;
348 dist_obsdbs.push_back(obsdb);
349 obsvecs.push_back(obsvec);
351 dist_obsvecs.push_back(obsvecs);
356 for (std::size_t ii = 0; ii < conf.size(); ++ii) {
358 int nobs = dist_obsvecs[0][ii]->nobs();
359 double rms = dist_obsvecs[0][ii]->rms();
360 double dot = dist_obsvecs[0][ii]->dot_product_with(*dist_obsvecs[0][ii]);
363 for (std::size_t jj = 1; jj < dist_obsvecs.size(); ++jj) {
364 int nobs2 = dist_obsvecs[jj][ii]->nobs();
365 double rms2 = dist_obsvecs[jj][ii]->rms();
366 double dot2 = dist_obsvecs[jj][ii]->dot_product_with(*dist_obsvecs[jj][ii]);
368 EXPECT(nobs == nobs2);
369 EXPECT(oops::is_close(rms, rms2, 1.0e-12));
370 EXPECT(oops::is_close(dot, dot2, 1.0e-12));
380 typedef ObsVecTestFixture Test_;
393 std::string
testid()
const override {
return "test::ObsVector<ioda::IodaTrait>";}
396 std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
398 ts.emplace_back(
CASE(
"ioda/ObsVector/testConstructor")
400 ts.emplace_back(
CASE(
"ioda/ObsVector/testCopyConstructor")
402 ts.emplace_back(
CASE(
"ioda/ObsVector/testNotZero")
404 ts.emplace_back(
CASE(
"ioda/ObsVector/testRead")
406 ts.emplace_back(
CASE(
"ioda/ObsVector/testSave")
408 ts.emplace_back(
CASE(
"ioda/ObsVector/testAxpy")
410 ts.emplace_back(
CASE(
"ioda/ObsVector/testDotProduct")
412 ts.emplace_back(
CASE(
"ioda/ObsVector/testDistributedMath")
414 ts.emplace_back(
CASE(
"ioda/ObsVector/testCleanup")
ObsVector class to handle vectors in observation space for IODA.
static ObsVecTestFixture & getInstance()
std::vector< boost::shared_ptr< ObsSpace_ > > ospaces_
static std::vector< boost::shared_ptr< ObsSpace_ > > & obspace()
std::string testid() const override
void clear() const override
void register_tests() const override
CASE("Derived variable, unit conversion, and exception checking methods")
void testAxpy()
tests ObsVector::axpy methods
void testCopyConstructor()
void testDotProduct()
tests ObsVector::dot_product methods
void testDistributedMath()