UFO
test/ufo/ObsDiagnostics.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2019 UCAR
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  */
7 
8 #ifndef TEST_UFO_OBSDIAGNOSTICS_H_
9 #define TEST_UFO_OBSDIAGNOSTICS_H_
10 
11 #include <memory>
12 #include <string>
13 #include <vector>
14 
15 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
16 
17 #include "eckit/config/LocalConfiguration.h"
18 #include "eckit/testing/Test.h"
19 #include "ioda/ObsSpace.h"
20 #include "ioda/ObsVector.h"
21 #include "oops/base/Variables.h"
22 #include "oops/mpi/mpi.h"
23 #include "oops/runs/Test.h"
24 #include "test/TestEnvironment.h"
25 #include "ufo/GeoVaLs.h"
26 #include "ufo/Locations.h"
27 #include "ufo/ObsBias.h"
28 #include "ufo/ObsDiagnostics.h"
29 #include "ufo/ObsOperator.h"
30 
31 namespace ufo {
32 namespace test {
33 
34 // -----------------------------------------------------------------------------
35 
37  const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
38 
39  // Setup ObsSpace
40  util::DateTime bgn(conf.getString("window begin"));
41  util::DateTime end(conf.getString("window end"));
42  const eckit::LocalConfiguration obsconf(conf, "obs space");
43  ioda::ObsSpace ospace(obsconf, oops::mpi::world(), bgn, end, oops::mpi::myself());
44  const size_t nlocs = ospace.nlocs();
45 
46  // initialize observation operator (set variables requested from the model,
47  // variables simulated by the observation operator, other init)
48  eckit::LocalConfiguration obsopconf(conf, "obs operator");
49  ObsOperator hop(ospace, obsopconf);
50 
51  // read geovals from the file
52  eckit::LocalConfiguration gconf(conf, "geovals");
53  const GeoVaLs gval(gconf, ospace, hop.requiredVars());
54 
55  // initialize bias correction
56  const ObsBias ybias(ospace, conf);
57 
58  // create obsvector to hold H(x)
59  ioda::ObsVector hofx(ospace);
60 
61  // create diagnostics to hold HofX diags
62  eckit::LocalConfiguration diagconf(conf, "obs diagnostics");
63  oops::Variables diagvars(diagconf, "variables");
64  EXPECT(diagvars.size() > 0);
65  std::unique_ptr<Locations> locs(hop.locations(bgn, end));
66  ObsDiagnostics diags(ospace, *(locs.get()), diagvars);
67 
68  // call H(x) to compute diagnostics
69  hop.simulateObs(gval, hofx, ybias, diags);
70 
71  // read tolerance and reference Diagnostics
72  const double tol = conf.getDouble("tolerance");
73  eckit::LocalConfiguration diagrefconf(conf, "reference obs diagnostics");
74  ObsDiagnostics diagref(diagrefconf, ospace, diagvars);
75 
76  // loop over all diag variables and levels and compare with reference
77  for (size_t ivar = 0; ivar < diagvars.size(); ivar++) {
78  const size_t nlevs = diags.nlevs(diagvars[ivar]);
79  EXPECT(nlevs == diagref.nlevs(diagvars[ivar]));
80  for (size_t ilev = 0; ilev < nlevs; ilev++) {
81  std::vector<float> ref(nlocs);
82  std::vector<float> computed(nlocs);
83  diags.get(computed, diagvars[ivar], ilev+1);
84  diagref.get(ref, diagvars[ivar], ilev+1);
85 
86  float rms = 0.0;
87  for (size_t iloc = 0; iloc < nlocs; iloc++) {
88  ref[iloc] -= computed[iloc];
89  rms += ref[iloc] * ref[iloc];
90  }
91  rms = sqrt(rms / nlocs);
92 
93  EXPECT(rms < 100*tol);
94  oops::Log::info() << diagvars[ivar] << ", level " << ilev <<
95  ": difference between reference and computed: " << ref << std::endl;
96  }
97  }
98 }
99 
100 // -----------------------------------------------------------------------------
101 
102 class ObsDiagnostics : public oops::Test {
103  public:
105  virtual ~ObsDiagnostics() {}
106  private:
107  std::string testid() const override {return "ufo::test::ObsDiagnostics";}
108 
109  void register_tests() const override {
110  std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
111 
112  ts.emplace_back(CASE("ufo/ObsDiagnostics/testObsDiagnostics")
113  { testObsDiagnostics(); });
114  }
115 
116  void clear() const override {}
117 };
118 
119 // -----------------------------------------------------------------------------
120 
121 } // namespace test
122 } // namespace ufo
123 
124 #endif // TEST_UFO_OBSDIAGNOSTICS_H_
ufo::test::testObsDiagnostics
void testObsDiagnostics()
Definition: test/ufo/ObsDiagnostics.h:36
ufo::test::GeoVaLs
Definition: test/ufo/GeoVaLs.h:168
ObsBias.h
ufo::test::CASE
CASE("ufo/MetOfficeBuddyPairFinder/" "Duplicates, constraints on buddy counts, legacy pair collector")
Definition: test/ufo/MetOfficeBuddyPairFinder.h:171
ufo::ObsOperator
Definition: ObsOperator.h:46
ObsOperator.h
ufo::test::ObsDiagnostics::clear
void clear() const override
Definition: test/ufo/ObsDiagnostics.h:116
ufo
Definition: RunCRTM.h:27
ufo::ObsOperator::locations
std::unique_ptr< Locations > locations(const util::DateTime &, const util::DateTime &) const
Operator locations.
Definition: ObsOperator.cc:58
ufo::ObsBias
Class to handle observation bias parameters.
Definition: ObsBias.h:44
ufo::test::ObsDiagnostics::testid
std::string testid() const override
Definition: test/ufo/ObsDiagnostics.h:107
ufo::test::ObsDiagnostics::ObsDiagnostics
ObsDiagnostics()
Definition: test/ufo/ObsDiagnostics.h:104
ufo::ObsOperator::simulateObs
void simulateObs(const GeoVaLs &, ioda::ObsVector &, const ObsBias &, ObsDiagnostics &) const
Obs Operator.
Definition: ObsOperator.cc:40
ufo::test::ObsDiagnostics::register_tests
void register_tests() const override
Definition: test/ufo/ObsDiagnostics.h:109
ufo::ObsOperator::requiredVars
const oops::Variables & requiredVars() const
Operator input required from Model.
Definition: ObsOperator.cc:52
ufo::test::ObsDiagnostics::~ObsDiagnostics
virtual ~ObsDiagnostics()
Definition: test/ufo/ObsDiagnostics.h:105
ufo::test::ObsDiagnostics
Definition: test/ufo/ObsDiagnostics.h:102
conf
Definition: conf.py:1