8 #ifndef TEST_IODA_OBSSPACE_H_
9 #define TEST_IODA_OBSSPACE_H_
16 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
18 #include <boost/noncopyable.hpp>
19 #include <boost/shared_ptr.hpp>
21 #include "eckit/config/LocalConfiguration.h"
22 #include "eckit/testing/Test.h"
24 #include "oops/mpi/mpi.h"
25 #include "oops/runs/Test.h"
26 #include "oops/test/TestEnvironment.h"
28 #include "ioda/distribution/Accumulator.h"
29 #include "ioda/distribution/DistributionUtils.h"
30 #include "ioda/IodaTrait.h"
46 for (
auto &space : spaces) {
55 return theObsSpaceTestFixture;
59 util::DateTime bgn(::test::TestEnvironment::config().getString(
"window begin"));
60 util::DateTime end(::test::TestEnvironment::config().getString(
"window end"));
62 std::vector<eckit::LocalConfiguration> conf;
63 ::test::TestEnvironment::config().get(
"observations", conf);
65 for (std::size_t jj = 0; jj < conf.size(); ++jj) {
66 eckit::LocalConfiguration obsconf(conf[jj],
"obs space");
67 std::string distname = obsconf.getString(
"distribution",
"RoundRobin");
68 boost::shared_ptr<ioda::ObsSpace> tmp(
new ioda::ObsSpace(obsconf, oops::mpi::world(),
69 bgn, end, oops::mpi::myself()));
76 std::vector<boost::shared_ptr<ioda::ObsSpace> >
ospaces_;
84 std::vector<eckit::LocalConfiguration> conf;
85 ::test::TestEnvironment::config().get(
"observations", conf);
87 for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
89 eckit::LocalConfiguration obsConfig;
90 eckit::LocalConfiguration testConfig;
91 conf[jj].get(
"obs space", obsConfig);
92 conf[jj].get(
"test data", testConfig);
94 std::string DistMethod = obsConfig.getString(
"distribution",
"RoundRobin");
96 const ObsSpace &odb = Test_::obspace(jj);
99 std::size_t GlobalNlocs = odb.globalNumLocs();
100 std::size_t
Nlocs = odb.nlocs();
101 std::size_t Nvars = odb.nvars();
104 int obsPertSeed = odb.params().obsPertSeed();
107 std::size_t ExpectedGlobalNlocs = testConfig.getUnsigned(
"nlocs");
108 std::size_t ExpectedNvars = testConfig.getUnsigned(
"nvars");
111 int ExpectedObsPertSeed = testConfig.getUnsigned(
"obs perturbations seed");
114 std::vector<std::string> ObsGroupVars = odb.obs_group_vars();
115 std::string ObsSortVar = odb.obs_sort_var();
116 std::string ObsSortOrder = odb.obs_sort_order();
119 std::vector<std::string> ExpectedObsGroupVars =
120 testConfig.getStringVector(
"expected group variables");
121 std::string ExpectedObsSortVar = testConfig.getString(
"expected sort variable");
122 std::string ExpectedObsSortOrder = testConfig.getString(
"expected sort order");
124 oops::Log::debug() <<
"GlobalNlocs, ExpectedGlobalNlocs: " << GlobalNlocs <<
", "
125 << ExpectedGlobalNlocs << std::endl;
126 oops::Log::debug() <<
"Nvars, ExpectedNvars: " << Nvars <<
", "
127 << ExpectedNvars << std::endl;
131 if (DistMethod !=
"Halo") {
132 std::size_t NRecs = 0;
133 std::set<std::size_t> recIndices;
134 auto accumulator = odb.distribution()->createAccumulator<std::size_t>();
135 for (std::size_t loc = 0; loc <
Nlocs; ++loc) {
136 if (
bool isNewRecord = recIndices.insert(odb.recnum()[loc]).second) {
137 accumulator->addTerm(loc, 1);
141 std::size_t ExpectedNRecs = odb.nrecs();
142 EXPECT_EQUAL(NRecs, ExpectedNRecs);
145 std::size_t GlobalNRecs = accumulator->computeResult();
146 std::size_t ExpectedGlobalNrecs = testConfig.getUnsigned(
"nrecs");
147 EXPECT_EQUAL(GlobalNRecs, ExpectedGlobalNrecs);
150 oops::Log::debug() <<
"ObsGroupVars, ExpectedObsGroupVars: " << ObsGroupVars <<
", "
151 << ExpectedObsGroupVars << std::endl;
152 oops::Log::debug() <<
"ObsSortVar, ExpectedObsSortVar: " << ObsSortVar <<
", "
153 << ExpectedObsSortVar << std::endl;
154 oops::Log::debug() <<
"ObsSortOrder, ExpectedObsSortOrder: " << ObsSortOrder <<
", "
155 << ExpectedObsSortOrder << std::endl;
161 EXPECT(GlobalNlocs == ExpectedGlobalNlocs);
162 EXPECT(Nvars == ExpectedNvars);
164 EXPECT(obsPertSeed == ExpectedObsPertSeed);
166 EXPECT(ObsGroupVars == ExpectedObsGroupVars);
167 EXPECT(ObsSortVar == ExpectedObsSortVar);
168 EXPECT(ObsSortOrder == ExpectedObsSortOrder);
170 EXPECT(nlocsName ==
"nlocs");
171 EXPECT(nchansName ==
"nchans");
183 std::vector<eckit::LocalConfiguration> conf;
184 ::test::TestEnvironment::config().get(
"observations", conf);
186 for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
188 eckit::LocalConfiguration obsConfig;
189 eckit::LocalConfiguration testConfig;
190 conf[jj].get(
"obs space", obsConfig);
191 conf[jj].get(
"test data", testConfig);
193 std::string DistMethod = obsConfig.getString(
"distribution",
"RoundRobin");
200 std::vector<eckit::LocalConfiguration> varconf =
201 testConfig.getSubConfigurations(
"variables");
202 double Tol = testConfig.getDouble(
"tolerance");
203 for (std::size_t i = 0; i < varconf.size(); ++i) {
205 std::string VarName = varconf[i].getString(
"name");
206 std::string GroupName = varconf[i].getString(
"group");
207 std::string VarType = varconf[i].getString(
"type");
210 if (VarType ==
"float") {
217 std::vector<double> TestVec(
Nlocs);
218 Odb->
get_db(GroupName, VarName, TestVec);
221 double ExpectedVnorm = varconf[i].getDouble(
"norm");
225 EXPECT(oops::is_close(Vnorm, ExpectedVnorm, Tol));
226 }
else if (VarType ==
"integer") {
232 std::vector<int> TestVec(
Nlocs);
233 Odb->
get_db(GroupName, VarName, TestVec);
236 double ExpectedVnorm = varconf[i].getDouble(
"norm");
240 EXPECT(oops::is_close(Vnorm, ExpectedVnorm, Tol));
241 }
else if (VarType ==
"string") {
247 std::string ExpectedFirstValue = varconf[i].getString(
"first value");
248 std::string ExpectedLastValue = varconf[i].getString(
"last value");
249 std::vector<std::string> TestVec(
Nlocs);
250 Odb->
get_db(GroupName, VarName, TestVec);
251 EXPECT(TestVec[0] == ExpectedFirstValue);
252 EXPECT(TestVec[
Nlocs-1] == ExpectedLastValue);
263 std::string VarName(
"DummyVar");
265 for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
273 std::vector<double> TestVec(
Nlocs);
274 std::vector<double> ExpectedVec(
Nlocs);
276 for (std::size_t i = 0; i <
Nlocs; ++i) {
277 ExpectedVec[i] =
static_cast<double>(i);
282 Odb->
put_db(
"MetaData", VarName, ExpectedVec);
283 Odb->
get_db(
"MetaData", VarName, TestVec);
285 bool VecMatch =
true;
286 for (std::size_t i = 0; i <
Nlocs; ++i) {
287 VecMatch = VecMatch && (
static_cast<int>(ExpectedVec[i]) ==
static_cast<int>(TestVec[i]));
299 std::string VarName(
"DummyVar");
301 for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
309 std::vector<double> TestVec(
Nlocs);
310 std::vector<double> ExpectedVec(
Nlocs);
312 for (std::size_t i = 0; i <
Nlocs; ++i) {
313 ExpectedVec[i] =
static_cast<double>(i);
318 Odb->
put_db(
"TestGroup", VarName, ExpectedVec);
319 Odb->
get_db(
"TestGroup", VarName, TestVec);
321 bool VecMatch =
true;
322 for (std::size_t i = 0; i <
Nlocs; ++i) {
323 VecMatch = VecMatch && (
static_cast<int>(ExpectedVec[i]) ==
static_cast<int>(TestVec[i]));
328 for (std::size_t i = 0; i <
Nlocs; ++i) {
329 ExpectedVec[i] = ExpectedVec[i] * 2;
332 Odb->
put_db(
"TestGroup", VarName, ExpectedVec);
333 Odb->
get_db(
"TestGroup", VarName, TestVec);
336 for (std::size_t i = 0; i <
Nlocs; ++i) {
337 VecMatch = VecMatch && (
static_cast<int>(ExpectedVec[i]) ==
static_cast<int>(TestVec[i]));
348 for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
361 std::vector<int> TestValues;
362 std::vector<int> ExpectedValues;
363 std::vector<std::string> dimList;
365 int numElements =
Nlocs;
373 TestValues.resize(numElements);
374 ExpectedValues.resize(numElements);
376 for (std::size_t i = 0; i < numElements; ++i) {
377 ExpectedValues[i] = testValue;
383 Odb->
put_db(
"MultiDimData",
"DummyVar", ExpectedValues, dimList);
384 Odb->
get_db(
"MultiDimData",
"DummyVar", TestValues, {} );
385 EXPECT(TestValues == ExpectedValues);
387 const int numOddChannels =
Nchans/2;
388 if (numOddChannels > 0) {
394 std::vector<int> chanSelect;
395 for (
int i = 0; i < numOddChannels; ++i) {
396 const std::size_t channelIndex = 1 + 2 * i;
397 chanSelect.push_back(
channels[channelIndex]);
400 ExpectedValues.clear();
401 for (std::size_t loc = 0; loc <
Nlocs; ++loc) {
402 for (
int i = 0; i < numOddChannels; ++i) {
403 const std::size_t channelIndex = 1 + 2 * i;
404 ExpectedValues.push_back(loc *
Nchans + channelIndex);
408 Odb->
get_db(
"MultiDimData",
"DummyVar", TestValues, chanSelect);
409 EXPECT_EQUAL(TestValues, ExpectedValues);
412 if (numOddChannels > 0) {
417 const int channelIndex = 1;
418 const int channelNumber =
channels[channelIndex];
420 ExpectedValues.clear();
421 for (std::size_t loc = 0; loc <
Nlocs; ++loc)
422 ExpectedValues.push_back(loc *
Nchans + channelIndex);
424 Odb->
get_db(
"MultiDimData",
"DummyVar_" + std::to_string(channelNumber), TestValues);
425 EXPECT_EQUAL(TestValues, ExpectedValues);
448 std::string
testid()
const override {
return "test::ObsSpace<ioda::IodaTrait>";}
451 std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
453 ts.emplace_back(
CASE(
"ioda/ObsSpace/testConstructor")
455 ts.emplace_back(
CASE(
"ioda/ObsSpace/testGetDb")
457 ts.emplace_back(
CASE(
"ioda/ObsSpace/testPutDb")
459 ts.emplace_back(
CASE(
"ioda/ObsSpace/testWriteableGroup")
461 ts.emplace_back(
CASE(
"ioda/ObsSpace/testMultiDimTransfer")
463 ts.emplace_back(
CASE(
"ioda/ObsSpace/testCleanup")
Observation data class for IODA.
ObsDtype dtype(const std::string &group, const std::string &name) const
return data type for group/variable
void put_db(const std::string &group, const std::string &name, const std::vector< int > &vdata, const std::vector< std::string > &dimList={ "nlocs" })
transfer data from vdata to the obs container
size_t nchans() const
return the number of channels in the container. If this is not a radiance obs type,...
std::string get_dim_name(const ObsDimensionId dimId) const
return the standard dimension name for the given dimension id
std::shared_ptr< const Distribution > distribution() const
return MPI distribution object
size_t nlocs() const
return the number of locations in the obs space. Note that nlocs may be smaller than global unique nl...
void get_db(const std::string &group, const std::string &name, std::vector< int > &vdata, const std::vector< int > &chanSelect={ }) const
transfer data from the obs container to vdata
const oops::Variables & obsvariables() const
return oops variables object (simulated variables)
std::string testid() const override
void register_tests() const override
void clear() const override
std::vector< boost::shared_ptr< ioda::ObsSpace > > ospaces_
static ioda::ObsSpace & obspace(const std::size_t ii)
static ObsSpaceTestFixture & getInstance()
static std::size_t size()
void testWriteableGroup()
void testMultiDimTransfer()
CASE("Derived variable and unit conversion methods")
double dotProduct(const Distribution &dist, std::size_t numVariables, const std::vector< double > &v1, const std::vector< double > &v2)