OOPS
test/interface/Model.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2009-2016 ECMWF.
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  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation nor
8  * does it submit to any jurisdiction.
9  */
10 
11 #ifndef TEST_INTERFACE_MODEL_H_
12 #define TEST_INTERFACE_MODEL_H_
13 
14 #include <cmath>
15 #include <iostream>
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 
24 #include "eckit/config/LocalConfiguration.h"
25 #include "eckit/testing/Test.h"
28 #include "oops/interface/Model.h"
30 #include "oops/interface/State.h"
31 #include "oops/mpi/mpi.h"
32 #include "oops/runs/Test.h"
33 #include "oops/util/DateTime.h"
34 #include "oops/util/Duration.h"
35 #include "test/TestEnvironment.h"
36 
37 namespace test {
38 
39 // =================================================================================================
40 
41 template <typename MODEL> class ModelFixture : private boost::noncopyable {
46 
47  public:
48  static const eckit::Configuration & test() {return *getInstance().test_;}
49  static const Geometry_ & resol() {return *getInstance().resol_;}
50  static const State_ & xref() {return *getInstance().xref_;}
51  static const ModelAux_ & bias() {return *getInstance().bias_;}
52  static const Model_ & model() {return *getInstance().model_;}
53  static void reset() {
54  getInstance().xref_.reset();
55  getInstance().bias_.reset();
56  getInstance().model_.reset();
57  getInstance().resol_.reset();
58  getInstance().test_.reset();
59  }
60 
61  private:
63  static ModelFixture<MODEL> theModelFixture;
64  return theModelFixture;
65  }
66 
68  test_.reset(new eckit::LocalConfiguration(TestEnvironment::config(), "model test"));
69 
70  const eckit::LocalConfiguration resolConfig(TestEnvironment::config(), "geometry");
71  resol_.reset(new Geometry_(resolConfig, oops::mpi::world()));
72 
73  const eckit::LocalConfiguration biasConf(TestEnvironment::config(), "model aux control");
74  bias_.reset(new ModelAux_(*resol_, biasConf));
75 
76  const eckit::LocalConfiguration conf(TestEnvironment::config(), "model");
77  model_.reset(new Model_(*resol_, conf));
78 
79  const eckit::LocalConfiguration iniConf(TestEnvironment::config(), "initial condition");
80  xref_.reset(new State_(*resol_, iniConf));
81  }
82 
83  ~ModelFixture<MODEL>() {}
84 
85  std::unique_ptr<const eckit::LocalConfiguration> test_;
86  std::unique_ptr<const Geometry_> resol_;
87  std::unique_ptr<const State_> xref_;
88  std::unique_ptr<const ModelAux_> bias_;
89  std::unique_ptr<const Model_> model_;
90 };
91 
92 // =================================================================================================
93 
94 template <typename MODEL> void testModelConstructor() {
95  typedef ModelFixture<MODEL> Test_;
96 
97  const util::Duration zero(0);
98  EXPECT(Test_::model().timeResolution() > zero);
99 }
100 
101 // -------------------------------------------------------------------------------------------------
102 
103 template <typename MODEL> void testModelNoForecast() {
104  typedef ModelFixture<MODEL> Test_;
105  typedef oops::State<MODEL> State_;
106 
107  const double ininorm = Test_::xref().norm();
108  State_ xx(Test_::xref());
109  const util::DateTime vt(xx.validTime());
110 
111  const util::Duration zero(0);
113 
114  Test_::model().forecast(xx, Test_::bias(), zero, post);
115 
116  EXPECT(xx.validTime() == vt);
117  EXPECT(xx.norm() == ininorm);
118 
119 // Recomputing initial norm to make sure nothing bad happened
120  EXPECT(Test_::xref().norm() == ininorm);
121 }
122 
123 // -------------------------------------------------------------------------------------------------
124 
125 template <typename MODEL> void testModelForecast() {
126  typedef ModelFixture<MODEL> Test_;
127  typedef oops::State<MODEL> State_;
128 
129  const double fnorm = Test_::test().getDouble("final norm");
130  const double tol = Test_::test().getDouble("tolerance");
131  const util::Duration len(Test_::test().getString("forecast length"));
132 
133  const double ininorm = Test_::xref().norm();
134  State_ xx(Test_::xref());
135  const util::DateTime vt(xx.validTime()+len);
136 
138 
139  Test_::model().forecast(xx, Test_::bias(), len, post);
140 
141  EXPECT(xx.validTime() == vt);
142 
143  oops::Log::debug() << "xx.norm(): " << std::fixed << std::setprecision(8) << xx.norm()
144  << std::endl;
145  oops::Log::debug() << "fnorm: " << std::fixed << std::setprecision(8) << fnorm << std::endl;
146 
147  EXPECT(oops::is_close(xx.norm(), fnorm, tol));
148 
149 // Recomputing initial norm to make sure nothing bad happened
150  EXPECT(Test_::xref().norm() == ininorm);
151 }
152 
153 // -------------------------------------------------------------------------------------------------
154 
155 template <typename MODEL> void testModelReForecast() {
156  typedef ModelFixture<MODEL> Test_;
157  typedef oops::State<MODEL> State_;
158 
159  const bool testreforecast = Test_::test().getBool("test reforecast", true);
160 
161  if (testreforecast) {
162  // Forecast duration
163  const util::Duration len(Test_::test().getString("forecast length"));
164 
165  const double ininorm = Test_::xref().norm();
166 
167  // Initial states
168  State_ xx1(Test_::xref());
169  State_ xx2(Test_::xref());
170 
171  // Time at forecast end
172  const util::DateTime vt(xx1.validTime()+len);
173 
175 
176  // Forecast 1
177  Test_::model().forecast(xx1, Test_::bias(), len, post);
178 
179  // Forecast 2
180  Test_::model().forecast(xx2, Test_::bias(), len, post);
181 
182  // Check forecasts ran to expected time
183  EXPECT(xx1.validTime() == vt);
184  EXPECT(xx2.validTime() == vt);
185 
186  // Print the final norms
187  oops::Log::debug() << "xx1.norm(): " << std::fixed << std::setprecision(8) << xx1.norm()
188  << std::endl;
189  oops::Log::debug() << "xx2.norm(): " << std::fixed << std::setprecision(8) << xx2.norm()
190  << std::endl;
191 
192  // Pass or fail condition
193  EXPECT(xx1.norm() == xx2.norm());
194 
195  // Recomputing initial norm to make sure nothing bad happened
196  EXPECT(Test_::xref().norm() == ininorm);
197  } else {
198  // Dummy test
199  EXPECT(0.0 == 0.0);
200  }
201 }
202 
203 // =================================================================================================
204 
205 template <typename MODEL>
206 class Model : public oops::Test {
207  public:
208  Model() {}
210  private:
211  std::string testid() const override {return "test::Model<" + MODEL::name() + ">";}
212 
213  void register_tests() const override {
214  std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
215 
216  ts.emplace_back(CASE("interface/Model/testModelConstructor")
217  { testModelConstructor<MODEL>(); });
218  ts.emplace_back(CASE("interface/Model/testModelNoForecast")
219  { testModelNoForecast<MODEL>(); });
220  ts.emplace_back(CASE("interface/Model/testModelForecast")
221  { testModelForecast<MODEL>(); });
222  ts.emplace_back(CASE("interface/Model/testModelReForecast")
223  { testModelReForecast<MODEL>(); });
224  }
225 
226  void clear() const override {}
227 };
228 
229 // =================================================================================================
230 
231 } // namespace test
232 
233 #endif // TEST_INTERFACE_MODEL_H_
test::testModelReForecast
void testModelReForecast()
Definition: test/interface/Model.h:155
test::Model::clear
void clear() const override
Definition: test/interface/Model.h:226
test::ModelFixture::resol
static const Geometry_ & resol()
Definition: test/interface/Model.h:49
test::Model::testid
std::string testid() const override
Definition: test/interface/Model.h:211
test::Model
Definition: test/interface/Model.h:206
test::ModelFixture::test_
std::unique_ptr< const eckit::LocalConfiguration > test_
Definition: test/interface/Model.h:85
test::ModelFixture::reset
static void reset()
Definition: test/interface/Model.h:53
test::ModelFixture::State_
oops::State< MODEL > State_
Definition: test/interface/Model.h:45
test::ModelFixture::ModelAux_
oops::ModelAuxControl< MODEL > ModelAux_
Definition: test/interface/Model.h:44
mpi.h
test::ModelFixture::test
static const eckit::Configuration & test()
Definition: test/interface/Model.h:48
oops::ModelAuxControl
Definition: oops/interface/ModelAuxControl.h:35
test::CASE
CASE("test_linearmodelparameterswrapper_valid_name")
Definition: LinearModelFactory.cc:22
test::ModelFixture
Definition: test/interface/Model.h:41
test
Definition: LinearModelFactory.cc:20
test::Model::~Model
virtual ~Model()
Definition: test/interface/Model.h:209
test::ModelFixture::bias_
std::unique_ptr< const ModelAux_ > bias_
Definition: test/interface/Model.h:88
test::ModelFixture::bias
static const ModelAux_ & bias()
Definition: test/interface/Model.h:51
test::testModelForecast
void testModelForecast()
Definition: test/interface/Model.h:125
Test.h
test::TestEnvironment::config
static const eckit::Configuration & config()
Definition: TestEnvironment.h:40
test::ModelFixture::model
static const Model_ & model()
Definition: test/interface/Model.h:52
test::ModelFixture::xref_
std::unique_ptr< const State_ > xref_
Definition: test/interface/Model.h:87
PostProcessor.h
test::ModelFixture::getInstance
static ModelFixture< MODEL > & getInstance()
Definition: test/interface/Model.h:62
test::ModelFixture::Geometry_
oops::Geometry< MODEL > Geometry_
Definition: test/interface/Model.h:42
test::ModelFixture::resol_
std::unique_ptr< const Geometry_ > resol_
Definition: test/interface/Model.h:86
oops::Geometry
Geometry class used in oops; subclass of interface class above.
Definition: oops/interface/Geometry.h:189
Model.h
oops::State::norm
double norm() const
Definition: oops/interface/State.h:201
TestEnvironment.h
test::testModelNoForecast
void testModelNoForecast()
Definition: test/interface/Model.h:103
test::ModelFixture::xref
static const State_ & xref()
Definition: test/interface/Model.h:50
oops::State
Encapsulates the model state.
Definition: CostJbState.h:28
test::Model::Model
Model()
Definition: test/interface/Model.h:208
oops::PostProcessor
Control model post processing.
Definition: PostProcessor.h:30
oops::Test
Definition: Test.h:39
test::testModelConstructor
void testModelConstructor()
Definition: test/interface/Model.h:94
State.h
oops::mpi::world
const eckit::mpi::Comm & world()
Default communicator with all MPI tasks (ie MPI_COMM_WORLD)
Definition: oops/mpi/mpi.cc:22
test::ModelFixture::Model_
oops::Model< MODEL > Model_
Definition: test/interface/Model.h:43
oops::Model
Encapsulates the nonlinear forecast model Note: to see methods that need to be implemented in the for...
Definition: oops/interface/Model.h:54
ModelAuxControl.h
Geometry.h
test::Model::register_tests
void register_tests() const override
Definition: test/interface/Model.h:213
test::ModelFixture::model_
std::unique_ptr< const Model_ > model_
Definition: test/interface/Model.h:89