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");
69 std::string distname = obsconf.getString(
"distribution",
"RoundRobin");
70 boost::shared_ptr<ObsSpace_> tmp(
new ObsSpace_(obsconf, oops::mpi::world(),
71 bgn, end, oops::mpi::myself()));
73 eckit::LocalConfiguration ObsDataInConf;
74 obsconf.get(
"obsdatain", ObsDataInConf);
80 std::vector<boost::shared_ptr<ObsSpace_> >
ospaces_;
89 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
90 std::unique_ptr<ObsVector_> ov(
new ObsVector_(*Test_::obspace()[jj]));
104 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
105 std::unique_ptr<ObsVector_> ov(
new ObsVector_(*Test_::obspace()[jj]));
107 std::unique_ptr<ObsVector_> other(
new ObsVector_(*ov));
111 EXPECT(!other.get());
122 const double zero = 0.0;
124 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
125 ObsVector_ ov(*Test_::obspace()[jj]);
129 const double ovov2 = dot_product(ov, ov);
130 EXPECT(ovov2 > zero);
134 const double zz = dot_product(ov, ov);
142 typedef ObsVecTestFixture Test_;
145 std::vector<eckit::LocalConfiguration> conf;
146 ::test::TestEnvironment::config().get(
"observations", conf);
148 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
153 eckit::LocalConfiguration testConfig;
154 conf[jj].get(
"test data", testConfig);
155 double ExpectedRms = testConfig.getDouble(
"rms ref");
156 double Tol = testConfig.getDouble(
"tolerance");
159 std::unique_ptr<ObsVector_> ov(
new ObsVector_(*Odb,
"ObsValue"));
160 double Rms = ov->rms();
162 EXPECT(oops::is_close(Rms, ExpectedRms, Tol));
176 std::vector<eckit::LocalConfiguration> conf;
177 ::test::TestEnvironment::config().get(
"observations", conf);
179 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
180 Odb = Test_::obspace()[jj].get();
181 bool read_obs_from_separate_file =
182 conf[jj].getBool(
"obs space.read obs from separate file",
false);
187 std::unique_ptr<ObsVector_> ov_orig(
new ObsVector_(*Odb,
"ObsValue"));
188 ExpectedRms = ov_orig->rms();
190 if (!read_obs_from_separate_file)
191 ov_orig->save(
"ObsTest");
193 std::unique_ptr<ObsVector_> ov_test(
new ObsVector_(*Odb,
"ObsTest"));
194 Rms = ov_test->rms();
196 EXPECT(oops::is_close(Rms, ExpectedRms, 1.0e-12));
212 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
214 ObsVector_ vec1(obspace);
218 ObsVector_ vec2(vec1);
219 vec2.axpy(2.0, vec1);
220 ObsVector_ vec3(vec1);
221 std::vector<double> beta(obspace.
obsvariables().size(), 2.0);
222 vec3.axpy(beta, vec1);
223 oops::Log::test() <<
"Testing ObsVector::axpy" << std::endl;
224 oops::Log::test() <<
"x = " << vec1 << std::endl;
225 oops::Log::test() <<
"x.axpy(2, x) = " << vec2 << std::endl;
226 oops::Log::test() <<
"x.axpy(vector of 2, x) = " << vec3 << std::endl;
227 EXPECT(oops::is_close(vec2.rms(), vec3.rms(), 1.0e-8));
230 std::vector<double> beta1(obspace.
obsvariables().size());
231 std::vector<double> beta2(obspace.
obsvariables().size());
232 for (
size_t jj = 0; jj < beta1.size(); ++jj) {
233 beta1[jj] =
static_cast<double>(jj)/beta1.size();
234 beta2[jj] = 2.0 - beta1[jj];
236 oops::Log::test() <<
"beta1 = " << beta1 <<
", beta2 = " << beta2 << std::endl;
237 ObsVector_ vec4(vec1);
238 vec4.axpy(beta1, vec1);
239 oops::Log::test() <<
"x.axpy(beta1, x) = " << vec4 << std::endl;
240 vec4.axpy(beta2, vec1);
241 oops::Log::test() <<
"x.axpy(beta2, x) = " << vec4 << std::endl;
242 EXPECT(oops::is_close(vec4.rms(), vec3.rms(), 1.0e-8));
254 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
256 ObsVector_ vec1(obspace);
258 ObsVector_ vec2(obspace);
261 double dp1 = vec1.dot_product_with(vec2);
262 std::vector<double> dp2 = vec1.multivar_dot_product_with(vec2);
263 oops::Log::test() <<
"Testing ObsVector::dot_product" << std::endl;
264 oops::Log::test() <<
"x1 = " << vec1 << std::endl;
265 oops::Log::test() <<
"x2 = " << vec2 << std::endl;
266 oops::Log::test() <<
"x1.dot_product_with(x2) = " << dp1 << std::endl;
267 oops::Log::test() <<
"x1.multivar_dot_product_with(x2) = " << dp2 << std::endl;
270 EXPECT_EQUAL(dp2.size(), vec1.nvars());
273 EXPECT(oops::is_close(dp1, std::accumulate(dp2.begin(), dp2.end(), 0.0), 1.0e-12));
282 typedef std::vector< std::shared_ptr< ObsVector_> > ObsVectors_;
289 std::vector<std::string> dist_names =
290 ::test::TestEnvironment::config().getStringVector(
"distributions");
291 for (std::size_t ii = 0; ii < dist_names.size(); ++ii) {
292 oops::Log::debug() <<
"using distribution: " << dist_names[ii] << std::endl;
296 util::DateTime bgn((::test::TestEnvironment::config().getString(
"window begin")));
297 util::DateTime end((::test::TestEnvironment::config().getString(
"window end")));
298 std::vector<eckit::LocalConfiguration> conf;
299 ::test::TestEnvironment::config().get(
"observations", conf);
302 std::vector< ObsVectors_ > dist_obsvecs;
303 std::vector< std::shared_ptr<ObsSpace_> > dist_obsdbs;
304 for (std::size_t dd = 0; dd < dist_names.size(); ++dd) {
306 for (std::size_t jj = 0; jj < conf.size(); ++jj) {
325 eckit::LocalConfiguration obsconf(conf[jj],
"obs space");
326 obsconf.set(
"distribution", dist_names[dd]);
327 if (obsconf.has(
"obsdataout.obsfile")) {
328 std::string fileName = obsconf.getString(
"obsdataout.obsfile");
329 std::string fileTag = std::string(
"_Dist_") + dist_names[dd];
330 std::size_t pos = fileName.find_last_of(
".");
331 if (pos != std::string::npos) {
333 fileName.insert(pos, fileTag);
338 obsconf.set(
"obsdataout.obsfile", fileName);
342 std::shared_ptr<ObsSpace_> obsdb(
new ObsSpace(obsconf, oops::mpi::world(),
343 bgn, end, oops::mpi::myself()));
344 std::shared_ptr<ObsVector_> obsvec(
new ObsVector_(*obsdb,
"ObsValue"));
345 oops::Log::debug() << dist_names[dd] <<
": " << *obsvec << std::endl;
346 dist_obsdbs.push_back(obsdb);
347 obsvecs.push_back(obsvec);
349 dist_obsvecs.push_back(obsvecs);
354 for (std::size_t ii = 0; ii < conf.size(); ++ii) {
356 int nobs = dist_obsvecs[0][ii]->nobs();
357 double rms = dist_obsvecs[0][ii]->rms();
358 double dot = dist_obsvecs[0][ii]->dot_product_with(*dist_obsvecs[0][ii]);
361 for (std::size_t jj = 1; jj < dist_obsvecs.size(); ++jj) {
362 int nobs2 = dist_obsvecs[jj][ii]->nobs();
363 double rms2 = dist_obsvecs[jj][ii]->rms();
364 double dot2 = dist_obsvecs[jj][ii]->dot_product_with(*dist_obsvecs[jj][ii]);
366 EXPECT(nobs == nobs2);
367 EXPECT(oops::is_close(rms, rms2, 1.0e-12));
368 EXPECT(oops::is_close(dot, dot2, 1.0e-12));
378 typedef ObsVecTestFixture Test_;
391 std::string
testid()
const override {
return "test::ObsVector<ioda::IodaTrait>";}
394 std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
396 ts.emplace_back(
CASE(
"ioda/ObsVector/testConstructor")
398 ts.emplace_back(
CASE(
"ioda/ObsVector/testCopyConstructor")
400 ts.emplace_back(
CASE(
"ioda/ObsVector/testNotZero")
402 ts.emplace_back(
CASE(
"ioda/ObsVector/testRead")
404 ts.emplace_back(
CASE(
"ioda/ObsVector/testSave")
406 ts.emplace_back(
CASE(
"ioda/ObsVector/testAxpy")
408 ts.emplace_back(
CASE(
"ioda/ObsVector/testDotProduct")
410 ts.emplace_back(
CASE(
"ioda/ObsVector/testDistributedMath")
412 ts.emplace_back(
CASE(
"ioda/ObsVector/testCleanup")
Observation data class for IODA.
const oops::Variables & obsvariables() const
return oops variables object (simulated variables)
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
void testAxpy()
tests ObsVector::axpy methods
void testCopyConstructor()
void testDotProduct()
tests ObsVector::dot_product methods
CASE("Derived variable and unit conversion methods")
void testDistributedMath()