OOPS
test/interface/ObsOperator.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2017-2018 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_INTERFACE_OBSOPERATOR_H_
9 #define TEST_INTERFACE_OBSOPERATOR_H_
10 
11 #include <memory>
12 #include <string>
13 #include <vector>
14 
15 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
16 
17 #include <boost/noncopyable.hpp>
18 
19 #include "eckit/config/LocalConfiguration.h"
20 #include "eckit/testing/Test.h"
21 #include "oops/base/Variables.h"
22 #include "oops/interface/GeoVaLs.h"
28 #include "oops/runs/Test.h"
30 #include "test/TestEnvironment.h"
31 
32 namespace test {
33 
34 // -----------------------------------------------------------------------------
35 
36 template <typename OBS> void testConstructor() {
37  typedef ObsTestsFixture<OBS> Test_;
38  typedef oops::ObsOperator<OBS> ObsOperator_;
39 
40  std::vector<eckit::LocalConfiguration> conf;
41  TestEnvironment::config().get("observations", conf);
42 
43  for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
44  eckit::LocalConfiguration obsopconf(conf[jj], "obs operator");
45  std::unique_ptr<ObsOperator_> hop(new ObsOperator_(Test_::obspace()[jj], obsopconf));
46  EXPECT(hop.get());
47 
48  hop.reset();
49  EXPECT(!hop.get());
50  }
51 }
52 
53 // -----------------------------------------------------------------------------
54 
55 template <typename OBS> void testSimulateObs() {
56  typedef ObsTestsFixture<OBS> Test_;
57  typedef oops::GeoVaLs<OBS> GeoVaLs_;
58  typedef oops::ObsDiagnostics<OBS> ObsDiags_;
59  typedef oops::ObsAuxControl<OBS> ObsAuxCtrl_;
60  typedef oops::ObsOperator<OBS> ObsOperator_;
61  typedef oops::ObsVector<OBS> ObsVector_;
62 
63  std::vector<eckit::LocalConfiguration> conf;
64  TestEnvironment::config().get("observations", conf);
65 
66  for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
67  // initialize observation operator (set variables requested from the model,
68  // variables simulated by the observation operator, other init)
69  eckit::LocalConfiguration obsopconf(conf[jj], "obs operator");
70  ObsOperator_ hop(Test_::obspace()[jj], obsopconf);
71 
72  // initialize bias correction
73  const ObsAuxCtrl_ ybias(Test_::obspace()[jj], conf[jj]);
74 
75  // read geovals from the file
76  eckit::LocalConfiguration gconf(conf[jj], "geovals");
77  oops::Variables hopvars = hop.requiredVars();
78  hopvars += ybias.requiredVars();
79  const GeoVaLs_ gval(gconf, Test_::obspace()[jj], hopvars);
80 
81  // create obsvector to hold H(x)
82  ObsVector_ hofx(Test_::obspace()[jj]);
83 
84  // create diagnostics to hold HofX diags
85  oops::Variables diagvars;
86  diagvars += ybias.requiredHdiagnostics();
87  ObsDiags_ diags(Test_::obspace()[jj],
88  hop.locations(Test_::obspace()[jj].windowStart(),
89  Test_::obspace()[jj].windowEnd()),
90  diagvars);
91 
92  // call H(x), save result in the output file as @hofx
93  hop.simulateObs(gval, hofx, ybias, diags);
94  hofx.save("hofx");
95 
96  // apply bias correction if it is required
97  if (conf[jj].has("obs bias")) {
98  const ObsVector_ bias(Test_::obspace()[jj], "ObsBias", false);
99  hofx += bias;
100  }
101 
102  const double tol = conf[jj].getDouble("tolerance");
103  if (conf[jj].has("vector ref")) {
104  // if reference h(x) is saved in file as a vector, read from file
105  // and compare the norm of difference to zero
106  ObsVector_ obsref(Test_::obspace()[jj], conf[jj].getString("vector ref"));
107  obsref -= hofx;
108  const double zz = obsref.rms();
109  oops::Log::info() << "Vector difference between reference and computed: " << obsref;
110  EXPECT(zz < 100*tol); // change tol from percent to actual value.
111  // tol used in is_close is relative
112  } else if (conf[jj].has("norm ref")) {
113  // if reference h(x) is saved in file as a vector, read from file
114  // and compare the difference, normalised by the reference values to zero
115  ObsVector_ obsref(Test_::obspace()[jj], conf[jj].getString("norm ref"));
116  obsref -= hofx;
117  obsref /= hofx;
118  const double zz = obsref.rms();
119  oops::Log::info() << "Normalised vector difference between reference and computed: "
120  << obsref;
121  EXPECT(zz < 100*tol); // change tol from percent to actual value.
122  // tol used in is_close is relative
123  } else {
124  // else compare h(x) norm to the norm from the config
125  const double zz = hofx.rms();
126  const double xx = conf[jj].getDouble("rms ref");
127 
128  oops::Log::debug() << "zz: " << std::fixed << std::setprecision(8) << zz << std::endl;
129  oops::Log::debug() << "xx: " << std::fixed << std::setprecision(8) << xx << std::endl;
130 
131  EXPECT(oops::is_close(xx, zz, tol));
132  }
133  }
134 }
135 
136 // -----------------------------------------------------------------------------
137 
138 template <typename OBS>
139 class ObsOperator : public oops::Test {
141  public:
143  virtual ~ObsOperator() {}
144  private:
145  std::string testid() const override {return "test::ObsOperator<" + OBS::name() + ">";}
146 
147  void register_tests() const override {
148  std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
149 
150  ts.emplace_back(CASE("interface/ObsOperator/testConstructor")
151  { testConstructor<OBS>(); });
152  ts.emplace_back(CASE("interface/ObsOperator/testSimulateObs")
153  { testSimulateObs<OBS>(); });
154  }
155 
156  void clear() const override {
157  Test_::reset();
158  }
159 };
160 
161 // =============================================================================
162 
163 } // namespace test
164 
165 #endif // TEST_INTERFACE_OBSOPERATOR_H_
test::ObsTestsFixture
Definition: ObsTestsFixture.h:29
ObsAuxControl.h
test::ObsTestsFixture::reset
static void reset()
Definition: ObsTestsFixture.h:37
test::testSimulateObs
void testSimulateObs()
Definition: test/interface/ObsOperator.h:55
test::ObsOperator::register_tests
void register_tests() const override
Definition: test/interface/ObsOperator.h:147
test::CASE
CASE("test_linearmodelparameterswrapper_valid_name")
Definition: LinearModelFactory.cc:22
test::ObsOperator::clear
void clear() const override
Definition: test/interface/ObsOperator.h:156
ObsOperator.h
test
Definition: LinearModelFactory.cc:20
oops::ObsAuxControl
Definition: oops/interface/ObsAuxControl.h:35
oops::ObsVector
Definition: oops/interface/ObsSpace.h:36
test::ObsOperator::Test_
ObsTestsFixture< OBS > Test_
Definition: test/interface/ObsOperator.h:140
test::ObsOperator
Definition: test/interface/ObsOperator.h:139
ObsDiagnostics.h
oops::ObsOperator
Definition: oops/interface/ObsOperator.h:38
Test.h
test::ObsOperator::~ObsOperator
virtual ~ObsOperator()
Definition: test/interface/ObsOperator.h:143
test::ObsOperator::testid
std::string testid() const override
Definition: test/interface/ObsOperator.h:145
test::TestEnvironment::config
static const eckit::Configuration & config()
Definition: TestEnvironment.h:40
ObsTestsFixture.h
oops::ObsDiagnostics
Definition: ObsDiagnostics.h:33
TestEnvironment.h
test::testConstructor
void testConstructor()
Tests creation and destruction of ObsErrorCovariances.
Definition: test/base/ObsErrorCovariance.h:32
oops_variables_mod::has
logical function has(this, var)
Definition: variables_mod.F90:140
oops::Test
Definition: Test.h:39
oops::Variables
Definition: oops/base/Variables.h:23
ObsVector.h
GeoVaLs.h
ObsDataVector.h
oops::GeoVaLs
Definition: oops/interface/GeoVaLs.h:32
test::ObsOperator::ObsOperator
ObsOperator()
Definition: test/interface/ObsOperator.h:142
Variables.h