OOPS
test/interface/GetValues.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2020 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_GETVALUES_H_
9 #define TEST_INTERFACE_GETVALUES_H_
10 
11 #include <algorithm>
12 #include <cmath>
13 #include <iomanip>
14 #include <iostream>
15 #include <limits>
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
20 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
21 
22 #include <boost/noncopyable.hpp>
23 #include <boost/ptr_container/ptr_vector.hpp>
24 
25 #include "eckit/config/LocalConfiguration.h"
26 #include "eckit/testing/Test.h"
27 #include "oops/base/Variables.h"
30 #include "oops/interface/GeoVaLs.h"
33 #include "oops/interface/State.h"
34 #include "oops/mpi/mpi.h"
35 #include "oops/runs/Test.h"
36 #include "oops/util/DateTime.h"
37 #include "oops/util/dot_product.h"
38 #include "oops/util/Duration.h"
39 #include "test/TestEnvironment.h"
40 
41 namespace test {
42 
43 // =================================================================================================
44 
45 template <typename MODEL, typename OBS> class GetValuesFixture : private boost::noncopyable {
46  typedef eckit::LocalConfiguration LocalConfig_;
52  typedef util::DateTime DateTime_;
53 
54  public:
55  static const DateTime_ & timebeg() {return *getInstance().timebeg_;}
56  static const DateTime_ & timeend() {return *getInstance().timeend_;}
57  static const GeoVaLs_ & geovals() {return *getInstance().geovals_;}
58  static const Geometry_ & resol() {return *getInstance().resol_;}
59  static const GetValues_ & getvalues() {return *getInstance().getvalues_;}
60  static const LocalConfig_ & testconf() {return *getInstance().testconf_;}
61  static const Locations_ & locs() {return *getInstance().locs_;}
62  static const Variables_ & geovalvars() {return *getInstance().geovalvars_;}
63 
64  private:
66  static GetValuesFixture<MODEL, OBS> theGetValuesFixture;
67  return theGetValuesFixture;
68  }
69 
71  testconf_.reset(new LocalConfig_(TestEnvironment::config(), "getvalues test"));
72 
73  // Geometry
74  const LocalConfig_ resolConfig(TestEnvironment::config(), "geometry");
75  resol_.reset(new Geometry_(resolConfig, oops::mpi::world()));
76 
77  // Variables
78  geovalvars_.reset(new Variables_(TestEnvironment::config(), "state variables"));
79 
80  // Locations
81  const LocalConfig_ locsConfig(TestEnvironment::config(), "locations");
82  locs_.reset(new Locations_(locsConfig, oops::mpi::world()));
83 
84  // Window times
85  timebeg_.reset(new DateTime_(locsConfig.getString("window begin")));
86  timeend_.reset(new DateTime_(locsConfig.getString("window end")));
87 
88  // GeoVaLs
89  geovals_.reset(new GeoVaLs_(*locs_, *geovalvars_));
90 
91  // GetValues
92  getvalues_.reset(new GetValues_(*resol_, *locs_));
93  }
94 
95  ~GetValuesFixture<MODEL, OBS>() {}
96 
97  std::unique_ptr<const DateTime_> timebeg_;
98  std::unique_ptr<const DateTime_> timeend_;
99  std::unique_ptr<const GeoVaLs_> geovals_;
100  std::unique_ptr<const Geometry_> resol_;
101  std::unique_ptr<const GetValues_> getvalues_;
102  std::unique_ptr<const LocalConfig_> testconf_;
103  std::unique_ptr<const Locations_> locs_;
104  std::unique_ptr<const Variables_> geovalvars_;
105 };
106 
107 // =================================================================================================
108 
109 template <typename MODEL, typename OBS> void testGetValuesConstructor() {
110  typedef GetValuesFixture<MODEL, OBS> Test_;
111  typedef oops::GetValues<MODEL, OBS> GetValues_;
112 
113  std::unique_ptr<const GetValues_> GetValues(new GetValues_(Test_::resol(), Test_::locs()));
114  EXPECT(GetValues.get());
115 
116  GetValues.reset();
117  EXPECT(!GetValues.get());
118 }
119 
120 // -------------------------------------------------------------------------------------------------
121 
122 template <typename MODEL, typename OBS> void testGetValuesMultiWindow() {
123  typedef GetValuesFixture<MODEL, OBS> Test_;
124  typedef oops::GeoVaLs<OBS> GeoVaLs_;
125  typedef oops::State<MODEL> State_;
126 
127  const util::Duration windowlength = Test_::timeend() - Test_::timebeg();
128  const util::DateTime timemid = Test_::timebeg() + windowlength/2;
129 
130  const eckit::LocalConfiguration confgen(Test_::testconf(), "state generate");
131  const State_ xx(Test_::resol(), confgen);
132 
133  EXPECT(xx.norm() > 0.0);
134 
135  GeoVaLs_ gv1(Test_::locs(), Test_::geovalvars());
136  GeoVaLs_ gv2(Test_::locs(), Test_::geovalvars());
137 
138  // Compute all geovals together
139  Test_::getvalues().fillGeoVaLs(xx, Test_::timebeg(), Test_::timeend(), gv1);
140 
141  // Compute all geovals as two subwindows
142  Test_::getvalues().fillGeoVaLs(xx, Test_::timebeg(), timemid, gv2);
143  Test_::getvalues().fillGeoVaLs(xx, timemid, Test_::timeend(), gv2);
144 
145  EXPECT(gv1.rms() > 0.0);
146  EXPECT(gv2.rms() > 0.0);
147  EXPECT(gv1.rms() == gv2.rms());
148 }
149 
150 // -------------------------------------------------------------------------------------------------
151 
152 /*! \brief Interpolation test
153  *
154  * \details **testGetValuesInterpolation()** tests the creation of an
155  * analytic state for a given model. The conceptual steps are as follows:
156  * 1. Initialize the JEDI State object based on idealized analytic formulae
157  * 2. Interpolate the State variables onto selected "observation" locations
158  * using the getValues() method of the State object. The result is
159  * placed in a JEDI GeoVaLs object
160  * 3. Compute the correct solution by applying the analytic formulae directly
161  * at the observation locations.
162  * 4. Assess the accuracy of the interpolation by comparing the interpolated
163  * values from Step 2 with the exact values from Step 3
164  *
165  * The interpolated state values are compared to the analytic solution for
166  * a series of **locations** which includes values optionally specified by the
167  * user in the "state test" section of the config file in addition to a
168  * randomly-generated list of **nrandom** random locations. nrandom is also
169  * specified by the user in the "state test" section of the config file, as is the
170  * (nondimensional) tolerence level (**interpolation tolerance**) to be used for the tests.
171  *
172  * Relevant parameters in the **State* section of the config file include
173  *
174  * * **norm-gen** Normalization test for the generated State
175  * * **interpolation tolerance** tolerance for the interpolation test
176  *
177  * \date April, 2018: M. Miesch (JCSDA) adapted a preliminary version in the
178  * feature/interp branch
179  *
180  * \warning Since this model compares the interpolated state values to an exact analytic
181  * solution, it requires that the "analytic_init" option be implemented in the model and
182  * selected in the "state.state generate" section of the config file.
183  */
184 
185 template <typename MODEL, typename OBS> void testGetValuesInterpolation() {
186  typedef GetValuesFixture<MODEL, OBS> Test_;
187  typedef oops::AnalyticInit<OBS> AnalyticInit_;
188  typedef oops::State<MODEL> State_;
189  typedef oops::GeoVaLs<OBS> GeoVaLs_;
190 
191  const eckit::LocalConfiguration confgen(Test_::testconf(), "state generate");
192  const State_ xx(Test_::resol(), confgen);
193 
194  // Interpolation tolerance
195  double interp_tol = Test_::testconf().getDouble("interpolation tolerance");
196 
197  // Ceate a GeoVaLs object from locs and vars
198  GeoVaLs_ gval(Test_::locs(), Test_::geovalvars());
199 
200  EXPECT(xx.norm() > 0.0);
201 
202  // Execute the interpolation
203  Test_::getvalues().fillGeoVaLs(xx, Test_::timebeg(), Test_::timeend(), gval);
204 
205  EXPECT(gval.rms() > 0.0);
206  oops::Log::debug() << "RMS GeoVaLs: " << gval.rms() << std::endl;
207 
208  // Now create another GeoVaLs object that contains the exact analytic solutions.
209  GeoVaLs_ ref(gval);
210 
211  AnalyticInit_ init(confgen);
212  init.fillGeoVaLs(Test_::locs(), ref);
213 
214  EXPECT(ref.rms() > 0.0);
215  oops::Log::debug() << "RMS reference GeoVaLs: " << ref.rms() << std::endl;
216 
217  // Compute the difference between the interpolated and exact values
218  gval -= ref;
219 
220  // And check to see if the errors are within specified tolerance
221  oops::Log::test() << "Normalized rms of the difference: " << gval.normalizedrms(ref) << std::endl;
222  EXPECT(gval.normalizedrms(ref) < interp_tol);
223 }
224 
225 // =================================================================================================
226 
227 template <typename MODEL, typename OBS>
228 class GetValues : public oops::Test {
229  public:
231  virtual ~GetValues() {}
232 
233  private:
234  std::string testid() const override {return "test::GetValues<" + MODEL::name() +
235  ", " + OBS::name() + ">";}
236 
237  void register_tests() const override {
238  std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
239 
240  ts.emplace_back(CASE("interface/GeometryIterator/testGetValuesConstructor")
241  { testGetValuesConstructor<MODEL, OBS>(); });
242  ts.emplace_back(CASE("interface/GeometryIterator/testGetValuesMultiWindow")
243  { testGetValuesMultiWindow<MODEL, OBS>(); });
244  ts.emplace_back(CASE("interface/GeometryIterator/testGetValuesInterpolation")
245  { testGetValuesInterpolation<MODEL, OBS>(); });
246  }
247 
248  void clear() const override {}
249 };
250 
251 // =================================================================================================
252 
253 } // namespace test
254 
255 #endif // TEST_INTERFACE_GETVALUES_H_
test::GetValues
Definition: test/interface/GetValues.h:228
test::GetValues::register_tests
void register_tests() const override
Definition: test/interface/GetValues.h:237
test::testGetValuesInterpolation
void testGetValuesInterpolation()
Interpolation test.
Definition: test/interface/GetValues.h:185
GetValues.h
Locations.h
test::GetValuesFixture::geovalvars_
std::unique_ptr< const Variables_ > geovalvars_
Definition: test/interface/GetValues.h:104
mpi.h
test::GetValues::clear
void clear() const override
Definition: test/interface/GetValues.h:248
test::GetValues::testid
std::string testid() const override
Definition: test/interface/GetValues.h:234
test::GetValuesFixture::geovalvars
static const Variables_ & geovalvars()
Definition: test/interface/GetValues.h:62
test::GetValuesFixture::getvalues
static const GetValues_ & getvalues()
Definition: test/interface/GetValues.h:59
test::CASE
CASE("test_linearmodelparameterswrapper_valid_name")
Definition: LinearModelFactory.cc:22
test::GetValuesFixture::DateTime_
util::DateTime DateTime_
Definition: test/interface/GetValues.h:52
test::GetValuesFixture::Locations_
oops::Locations< OBS > Locations_
Definition: test/interface/GetValues.h:50
oops::GetValues
Gets values from model State to observation locations (fills GeoVaLs)
Definition: oops/interface/GetValues.h:32
oops::AnalyticInit
Initializes GeoVaLs with analytic formula.
Definition: src/oops/interface/AnalyticInit.h:24
test
Definition: LinearModelFactory.cc:20
test::testGetValuesMultiWindow
void testGetValuesMultiWindow()
Definition: test/interface/GetValues.h:122
test::GetValuesFixture::testconf
static const LocalConfig_ & testconf()
Definition: test/interface/GetValues.h:60
test::GetValuesFixture::timebeg
static const DateTime_ & timebeg()
Definition: test/interface/GetValues.h:55
test::GetValuesFixture::getInstance
static GetValuesFixture< MODEL, OBS > & getInstance()
Definition: test/interface/GetValues.h:65
Test.h
test::testGetValuesConstructor
void testGetValuesConstructor()
Definition: test/interface/GetValues.h:109
test::GetValuesFixture::geovals_
std::unique_ptr< const GeoVaLs_ > geovals_
Definition: test/interface/GetValues.h:99
test::TestEnvironment::config
static const eckit::Configuration & config()
Definition: TestEnvironment.h:40
test::GetValuesFixture::timeend
static const DateTime_ & timeend()
Definition: test/interface/GetValues.h:56
test::GetValuesFixture::resol_
std::unique_ptr< const Geometry_ > resol_
Definition: test/interface/GetValues.h:100
AnalyticInit.h
test::GetValuesFixture::getvalues_
std::unique_ptr< const GetValues_ > getvalues_
Definition: test/interface/GetValues.h:101
test::GetValuesFixture::testconf_
std::unique_ptr< const LocalConfig_ > testconf_
Definition: test/interface/GetValues.h:102
oops::Geometry
Geometry class used in oops; subclass of interface class above.
Definition: oops/interface/Geometry.h:189
TestEnvironment.h
test::GetValuesFixture::resol
static const Geometry_ & resol()
Definition: test/interface/GetValues.h:58
oops::State
Encapsulates the model state.
Definition: CostJbState.h:28
test::GetValues::GetValues
GetValues()
Definition: test/interface/GetValues.h:230
test::GetValuesFixture::GetValues_
oops::GetValues< MODEL, OBS > GetValues_
Definition: test/interface/GetValues.h:49
test::GetValuesFixture::geovals
static const GeoVaLs_ & geovals()
Definition: test/interface/GetValues.h:57
test::GetValuesFixture
Definition: test/interface/GetValues.h:45
oops::Test
Definition: Test.h:39
test::GetValuesFixture::timebeg_
std::unique_ptr< const DateTime_ > timebeg_
Definition: test/interface/GetValues.h:97
State.h
test::GetValuesFixture::GeoVaLs_
oops::GeoVaLs< OBS > GeoVaLs_
Definition: test/interface/GetValues.h:47
oops::mpi::world
const eckit::mpi::Comm & world()
Default communicator with all MPI tasks (ie MPI_COMM_WORLD)
Definition: oops/mpi/mpi.cc:22
oops::Variables
Definition: oops/base/Variables.h:23
test::GetValuesFixture::Variables_
oops::Variables Variables_
Definition: test/interface/GetValues.h:51
oops::Locations
Locations of observations for observation operator.
Definition: oops/interface/Locations.h:36
GeoVaLs.h
test::GetValuesFixture::timeend_
std::unique_ptr< const DateTime_ > timeend_
Definition: test/interface/GetValues.h:98
test::GetValuesFixture::LocalConfig_
eckit::LocalConfiguration LocalConfig_
Definition: test/interface/GetValues.h:46
test::GetValuesFixture::locs
static const Locations_ & locs()
Definition: test/interface/GetValues.h:61
test::GetValues::~GetValues
virtual ~GetValues()
Definition: test/interface/GetValues.h:231
oops::GeoVaLs
Definition: oops/interface/GeoVaLs.h:32
test::GetValuesFixture::locs_
std::unique_ptr< const Locations_ > locs_
Definition: test/interface/GetValues.h:103
Variables.h
test::GetValuesFixture::Geometry_
oops::Geometry< MODEL > Geometry_
Definition: test/interface/GetValues.h:48
Geometry.h