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" 
   36   template <> 
struct VectorPrintSelector<float> { 
typedef VectorPrintSimple selector; };
 
   49   static const eckit::LocalConfiguration & 
config(
const std::size_t ii) {
 
   55     for (
auto &space : spaces) {
 
   64     return theObsSpaceTestFixture;
 
   68     util::DateTime bgn(::test::TestEnvironment::config().getString(
"window begin"));
 
   69     util::DateTime end(::test::TestEnvironment::config().getString(
"window end"));
 
   71     ::test::TestEnvironment::config().get(
"observations", 
configs_);
 
   73     for (std::size_t jj = 0; jj < 
configs_.size(); ++jj) {
 
   74       eckit::LocalConfiguration obsconf(
configs_[jj], 
"obs space");
 
   76       obsparams.validateAndDeserialize(obsconf);
 
   77       boost::shared_ptr<ioda::ObsSpace> tmp(
new ioda::ObsSpace(obsparams, oops::mpi::world(),
 
   78                                                                bgn, end, oops::mpi::myself()));
 
   85   std::vector<eckit::LocalConfiguration> 
configs_;
 
   86   std::vector<boost::shared_ptr<ioda::ObsSpace> > 
ospaces_;
 
   94   std::vector<eckit::LocalConfiguration> conf;
 
   95   ::test::TestEnvironment::config().get(
"observations", conf);
 
   97   for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
 
   99     eckit::LocalConfiguration obsConfig;
 
  100     eckit::LocalConfiguration testConfig;
 
  101     conf[jj].get(
"obs space", obsConfig);
 
  102     conf[jj].get(
"test data", testConfig);
 
  104     std::string DistMethod = obsConfig.getString(
"distribution", 
"RoundRobin");
 
  106     const ObsSpace &odb = Test_::obspace(jj);
 
  109     std::size_t GlobalNlocs = odb.globalNumLocs();
 
  110     std::size_t 
Nlocs = odb.nlocs();
 
  111     std::size_t Nvars = odb.nvars();
 
  114     int obsPertSeed = odb.params().obsPertSeed();
 
  117     std::size_t ExpectedGlobalNlocs = testConfig.getUnsigned(
"nlocs");
 
  118     std::size_t ExpectedNvars = testConfig.getUnsigned(
"nvars");
 
  121     int ExpectedObsPertSeed = testConfig.getUnsigned(
"obs perturbations seed");
 
  124     std::vector<std::string> ObsGroupVars = odb.obs_group_vars();
 
  125     std::string ObsSortVar = odb.obs_sort_var();
 
  126     std::string ObsSortOrder = odb.obs_sort_order();
 
  129     std::vector<std::string> ExpectedObsGroupVars =
 
  130       testConfig.getStringVector(
"expected group variables");
 
  131     std::string ExpectedObsSortVar = testConfig.getString(
"expected sort variable");
 
  132     std::string ExpectedObsSortOrder = testConfig.getString(
"expected sort order");
 
  134     oops::Log::debug() << 
"GlobalNlocs, ExpectedGlobalNlocs: " << GlobalNlocs << 
", " 
  135                        << ExpectedGlobalNlocs << std::endl;
 
  136     oops::Log::debug() << 
"Nvars, ExpectedNvars: " << Nvars << 
", " 
  137                        << ExpectedNvars << std::endl;
 
  141     if (DistMethod != 
"Halo") {
 
  142       std::size_t NRecs = 0;
 
  143       std::set<std::size_t> recIndices;
 
  144       auto accumulator = odb.distribution()->createAccumulator<std::size_t>();
 
  145       for (std::size_t loc = 0; loc < 
Nlocs; ++loc) {
 
  146         if (
bool isNewRecord = recIndices.insert(odb.recnum()[loc]).second) {
 
  147           accumulator->addTerm(loc, 1);
 
  151       std::size_t ExpectedNRecs = odb.nrecs();
 
  152       EXPECT_EQUAL(NRecs, ExpectedNRecs);
 
  155       std::size_t GlobalNRecs = accumulator->computeResult();
 
  156       std::size_t ExpectedGlobalNrecs = testConfig.getUnsigned(
"nrecs");
 
  157       EXPECT_EQUAL(GlobalNRecs, ExpectedGlobalNrecs);
 
  160     oops::Log::debug() << 
"ObsGroupVars, ExpectedObsGroupVars: " << ObsGroupVars << 
", " 
  161                        << ExpectedObsGroupVars << std::endl;
 
  162     oops::Log::debug() << 
"ObsSortVar, ExpectedObsSortVar: " << ObsSortVar << 
", " 
  163                        << ExpectedObsSortVar << std::endl;
 
  164     oops::Log::debug() << 
"ObsSortOrder, ExpectedObsSortOrder: " << ObsSortOrder << 
", " 
  165                        << ExpectedObsSortOrder << std::endl;
 
  171     EXPECT(GlobalNlocs == ExpectedGlobalNlocs);
 
  172     EXPECT(Nvars == ExpectedNvars);
 
  174     EXPECT(obsPertSeed == ExpectedObsPertSeed);
 
  176     EXPECT(ObsGroupVars == ExpectedObsGroupVars);
 
  177     EXPECT(ObsSortVar == ExpectedObsSortVar);
 
  178     EXPECT(ObsSortOrder == ExpectedObsSortOrder);
 
  180     EXPECT(nlocsName == 
"nlocs");
 
  181     EXPECT(nchansName == 
"nchans");
 
  193   std::vector<eckit::LocalConfiguration> conf;
 
  194   ::test::TestEnvironment::config().get(
"observations", conf);
 
  196   for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
 
  198     eckit::LocalConfiguration obsConfig;
 
  199     eckit::LocalConfiguration testConfig;
 
  200     conf[jj].get(
"obs space", obsConfig);
 
  201     conf[jj].get(
"test data", testConfig);
 
  208     std::vector<eckit::LocalConfiguration> varconf =
 
  209                             testConfig.getSubConfigurations(
"variables for get test");
 
  210     double Tol = testConfig.getDouble(
"tolerance");
 
  211     for (std::size_t i = 0; i < varconf.size(); ++i) {
 
  213       std::string VarName = varconf[i].getString(
"name");
 
  214       std::string GroupName = varconf[i].getString(
"group");
 
  215       std::string VarType = varconf[i].getString(
"type");
 
  216       bool SkipDerived = varconf[i].getBool(
"skip derived", 
false);
 
  219       if (VarType == 
"float") {
 
  221         EXPECT(Odb->has(GroupName, VarName, SkipDerived));
 
  224         ObsDtype VarDataType = Odb->dtype(GroupName, VarName, SkipDerived);
 
  229         std::vector<double> TestVec(
Nlocs);
 
  230         Odb->get_db(GroupName, VarName, TestVec, {}, SkipDerived);
 
  233         double ExpectedVnorm = varconf[i].getDouble(
"norm");
 
  234         double Vnorm = 
dotProduct(*Odb->distribution(), 1, TestVec, TestVec);
 
  237         EXPECT(oops::is_close(Vnorm, ExpectedVnorm, Tol));
 
  238       } 
else if (VarType == 
"integer") {
 
  240         EXPECT(Odb->has(GroupName, VarName, SkipDerived));
 
  243         ObsDtype VarDataType = Odb->dtype(GroupName, VarName, SkipDerived);
 
  247         std::vector<int> TestVec(
Nlocs);
 
  248         Odb->get_db(GroupName, VarName, TestVec, {}, SkipDerived);
 
  251         double ExpectedVnorm = varconf[i].getDouble(
"norm");
 
  252         double Vnorm = 
dotProduct(*Odb->distribution(), 1, TestVec, TestVec);
 
  255         EXPECT(oops::is_close(Vnorm, ExpectedVnorm, Tol));
 
  256       } 
else if (VarType == 
"string") {
 
  258         EXPECT(Odb->has(GroupName, VarName, SkipDerived));
 
  261         ObsDtype VarDataType = Odb->dtype(GroupName, VarName, SkipDerived);
 
  265         std::string ExpectedFirstValue = varconf[i].getString(
"first value");
 
  266         std::string ExpectedLastValue = varconf[i].getString(
"last value");
 
  267         std::vector<std::string> TestVec(
Nlocs);
 
  268         Odb->get_db(GroupName, VarName, TestVec, {}, SkipDerived);
 
  269         EXPECT(TestVec[0] == ExpectedFirstValue);
 
  270         EXPECT(TestVec[
Nlocs-1] == ExpectedLastValue);
 
  271       } 
else if (VarType == 
"none") {
 
  273         EXPECT_NOT(Odb->has(GroupName, VarName, SkipDerived));
 
  276         ObsDtype VarDataType = Odb->dtype(GroupName, VarName, SkipDerived);
 
  281           std::vector<float> TestVec(
Nlocs);
 
  282           EXPECT_THROWS(Odb->get_db(GroupName, VarName, TestVec, {}, SkipDerived));
 
  285           std::vector<int> TestVec(
Nlocs);
 
  286           EXPECT_THROWS(Odb->get_db(GroupName, VarName, TestVec, {}, SkipDerived));
 
  289           std::vector<std::string> TestVec(
Nlocs);
 
  290           EXPECT_THROWS(Odb->get_db(GroupName, VarName, TestVec, {}, SkipDerived));
 
  302   std::string VarName(
"DummyVar");
 
  304   for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
 
  312     std::vector<double> TestVec(
Nlocs);
 
  313     std::vector<double> ExpectedVec(
Nlocs);
 
  315     for (std::size_t i = 0; i < 
Nlocs; ++i) {
 
  316       ExpectedVec[i] = 
static_cast<double>(i);
 
  321     Odb->put_db(
"MetaData", VarName, ExpectedVec);
 
  322     Odb->get_db(
"MetaData", VarName, TestVec);
 
  324     bool VecMatch = 
true;
 
  325     for (std::size_t i = 0; i < 
Nlocs; ++i) {
 
  326       VecMatch = VecMatch && (
static_cast<int>(ExpectedVec[i]) == 
static_cast<int>(TestVec[i]));
 
  338   std::vector<eckit::LocalConfiguration> conf;
 
  339   ::test::TestEnvironment::config().get(
"observations", conf);
 
  341   for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
 
  343     eckit::LocalConfiguration obsConfig;
 
  344     eckit::LocalConfiguration testConfig;
 
  345     conf[jj].get(
"obs space", obsConfig);
 
  346     conf[jj].get(
"test data", testConfig);
 
  353     std::vector<eckit::LocalConfiguration> varconf =
 
  354                             testConfig.getSubConfigurations(
"variables for putget test");
 
  355     for (std::size_t i = 0; i < varconf.size(); ++i) {
 
  359       std::string VarName = varconf[i].getString(
"name");
 
  360       std::string GroupName = varconf[i].getString(
"group");
 
  361       std::vector<int> Channels = varconf[i].getIntVector(
"channels", { });
 
  362       oops::Log::debug() << 
"Reading: " << GroupName << 
", " << VarName << 
", " 
  363                          << Channels << std::endl;
 
  366       EXPECT(Odb->has(GroupName, VarName));
 
  369       ObsDtype VarDataType = Odb->dtype(GroupName, VarName);
 
  373       std::vector<float> OrigVec(
Nlocs);
 
  374       Odb->get_db(GroupName, VarName, OrigVec, Channels);
 
  377       std::string TestGroupName = GroupName + 
"_Test";
 
  378       std::string PutDbVarName = VarName;
 
  379       std::vector<std::string> DimList = { 
"nlocs" };
 
  380       if (!Channels.empty()) {
 
  381         PutDbVarName += 
"_" + std::to_string(Channels[0]);
 
  382         DimList.push_back(
"nchans");
 
  384       oops::Log::debug() << 
"Writing: " << TestGroupName << 
", " << PutDbVarName << 
", " 
  385                          << DimList << std::endl;
 
  387       Odb->put_db(TestGroupName, PutDbVarName, OrigVec, DimList);
 
  390       std::vector<float> TestVec(
Nlocs);
 
  391       Odb->get_db(TestGroupName, VarName, TestVec, Channels);
 
  393       EXPECT(TestVec == OrigVec);
 
  403   std::string VarName(
"DummyVar");
 
  405   for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
 
  413     std::vector<double> TestVec(
Nlocs);
 
  414     std::vector<double> ExpectedVec(
Nlocs);
 
  416     for (std::size_t i = 0; i < 
Nlocs; ++i) {
 
  417       ExpectedVec[i] = 
static_cast<double>(i);
 
  422     Odb->put_db(
"TestGroup", VarName, ExpectedVec);
 
  423     Odb->get_db(
"TestGroup", VarName, TestVec);
 
  425     bool VecMatch = 
true;
 
  426     for (std::size_t i = 0; i < 
Nlocs; ++i) {
 
  427       VecMatch = VecMatch && (
static_cast<int>(ExpectedVec[i]) == 
static_cast<int>(TestVec[i]));
 
  432     for (std::size_t i = 0; i < 
Nlocs; ++i) {
 
  433       ExpectedVec[i] = ExpectedVec[i] * 2;
 
  436     Odb->put_db(
"TestGroup", VarName, ExpectedVec);
 
  437     Odb->get_db(
"TestGroup", VarName, TestVec);
 
  440     for (std::size_t i = 0; i < 
Nlocs; ++i) {
 
  441       VecMatch = VecMatch && (
static_cast<int>(ExpectedVec[i]) == 
static_cast<int>(TestVec[i]));
 
  452   for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
 
  463     std::size_t 
Nchans = Odb->nchans();
 
  465     std::vector<int> TestValues;
 
  466     std::vector<int> ExpectedValues;
 
  467     std::vector<std::string> dimList;
 
  469     int numElements = 
Nlocs;
 
  477     TestValues.resize(numElements);
 
  478     ExpectedValues.resize(numElements);
 
  480     for (std::size_t i = 0; i < numElements; ++i) {
 
  481       ExpectedValues[i] = testValue;
 
  487     Odb->put_db(
"MultiDimData", 
"DummyVar", ExpectedValues, dimList);
 
  488     Odb->get_db(
"MultiDimData", 
"DummyVar", TestValues, {} );
 
  489     EXPECT(TestValues == ExpectedValues);
 
  491     const int numOddChannels = 
Nchans/2;
 
  492     if (numOddChannels > 0) {
 
  495       const std::vector<int>& 
channels = Odb->obsvariables().channels();
 
  498       std::vector<int> chanSelect;
 
  499       for (
int i = 0; i < numOddChannels; ++i) {
 
  500         const std::size_t channelIndex = 1 + 2 * i;
 
  501         chanSelect.push_back(
channels[channelIndex]);
 
  504       ExpectedValues.clear();
 
  505       for (std::size_t loc = 0; loc < 
Nlocs; ++loc) {
 
  506         for (
int i = 0; i < numOddChannels; ++i) {
 
  507           const std::size_t channelIndex = 1 + 2 * i;
 
  508           ExpectedValues.push_back(loc * 
Nchans + channelIndex);
 
  512       Odb->get_db(
"MultiDimData", 
"DummyVar", TestValues, chanSelect);
 
  513       EXPECT_EQUAL(TestValues, ExpectedValues);
 
  516     if (numOddChannels > 0) {
 
  520       const std::vector<int>& 
channels = Odb->obsvariables().channels();
 
  521       const int channelIndex = 1;
 
  522       const int channelNumber = 
channels[channelIndex];
 
  524       ExpectedValues.clear();
 
  525       for (std::size_t loc = 0; loc < 
Nlocs; ++loc)
 
  526         ExpectedValues.push_back(loc * 
Nchans + channelIndex);
 
  528       Odb->get_db(
"MultiDimData", 
"DummyVar_" + std::to_string(channelNumber), TestValues);
 
  529       EXPECT_EQUAL(TestValues, ExpectedValues);
 
  540   for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
 
  544     obsparams.validateAndDeserialize(Test_::config(jj));
 
  546     const oops::Variables & allSimVars = Odb.obsvariables();
 
  547     const oops::Variables & initialSimVars = Odb.initial_obsvariables();
 
  548     const oops::Variables & derivedSimVars = Odb.derived_obsvariables();
 
  550     EXPECT_EQUAL(initialSimVars, obsparams.
simVars);
 
  552     EXPECT_EQUAL(allSimVars.size(), initialSimVars.size() + derivedSimVars.size());
 
  563   for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
 
  566     const oops::Variables & derivedSimVars = Odb.derived_obsvariables();
 
  567     for (
size_t i = 0; i < derivedSimVars.size(); ++i) {
 
  568       EXPECT(Odb.has(
"ObsError", derivedSimVars[i]));
 
  569       std::vector<float> values(Odb.
nlocs());
 
  570       Odb.get_db(
"ObsError", derivedSimVars[i], values);
 
  572       std::vector<float> expectedValues(Odb.
nlocs(), util::missingValue(
float()));
 
  573       EXPECT_EQUAL(values, expectedValues);
 
  596   std::string 
testid()
 const override {
return "test::ObsSpace<ioda::IodaTrait>";}
 
  599     std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
 
  601     ts.emplace_back(
CASE(
"ioda/ObsSpace/testConstructor")
 
  603     ts.emplace_back(
CASE(
"ioda/ObsSpace/testGetDb")
 
  605     ts.emplace_back(
CASE(
"ioda/ObsSpace/testPutDb")
 
  607     ts.emplace_back(
CASE(
"ioda/ObsSpace/testPutGetChanSelect")
 
  609     ts.emplace_back(
CASE(
"ioda/ObsSpace/testWriteableGroup")
 
  611     ts.emplace_back(
CASE(
"ioda/ObsSpace/testMultiDimTransfer")
 
  613     ts.emplace_back(
CASE(
"ioda/ObsSpace/testCleanup")
 
oops::RequiredParameter< oops::Variables > simVars
simulated variables
 
oops::Parameter< oops::Variables > derivedSimVars
 
std::string testid() const override
 
void register_tests() const override
 
void clear() const override
 
std::vector< boost::shared_ptr< ioda::ObsSpace > > ospaces_
 
static const eckit::LocalConfiguration & config(const std::size_t ii)
 
std::vector< eckit::LocalConfiguration > configs_
 
static ioda::ObsSpace & obspace(const std::size_t ii)
 
static ObsSpaceTestFixture & getInstance()
 
static std::size_t size()
 
void testWriteableGroup()
 
CASE("Derived variable, unit conversion, and exception checking methods")
 
void testDerivedObsError()
 
void testMultiDimTransfer()
 
void testPutGetChanSelect()
 
double dotProduct(const Distribution &dist, std::size_t numVariables, const std::vector< double > &v1, const std::vector< double > &v2)