FV3 Bundle
test/interface/Increment.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_INCREMENT_H_
12 #define TEST_INTERFACE_INCREMENT_H_
13 
14 #include <cmath>
15 #include <iostream>
16 #include <string>
17 
18 #define BOOST_TEST_NO_MAIN
19 #define BOOST_TEST_ALTERNATIVE_INIT_API
20 
21 #define BOOST_TEST_DYN_LINK
22 #include <boost/test/unit_test.hpp>
23 
24 #include <boost/noncopyable.hpp>
25 #include <boost/scoped_ptr.hpp>
26 
27 #include "eckit/config/LocalConfiguration.h"
28 #include "oops/base/Variables.h"
32 #include "oops/interface/State.h"
33 #include "oops/runs/Test.h"
34 #include "oops/util/DateTime.h"
35 #include "oops/util/dot_product.h"
36 #include "test/TestEnvironment.h"
37 
38 namespace test {
39 
40 // =============================================================================
41 
42 template <typename MODEL> class IncrementFixture : private boost::noncopyable {
44 
45  public:
46  static const Geometry_ & resol() {return *getInstance().resol_;}
47  static const oops::Variables & ctlvars() {return *getInstance().ctlvars_;}
48  static const util::DateTime & time() {return *getInstance().time_;}
49 
50  private:
52  static IncrementFixture<MODEL> theIncrementFixture;
53  return theIncrementFixture;
54  }
55 
57 // Setup a geometry
58  const eckit::LocalConfiguration resolConfig(TestEnvironment::config(), "Geometry");
59  resol_.reset(new Geometry_(resolConfig));
60 
61  const eckit::LocalConfiguration varConfig(TestEnvironment::config(), "Variables");
62  ctlvars_.reset(new oops::Variables(varConfig));
63 
64  time_.reset(new util::DateTime(TestEnvironment::config().getString("TestDate")));
65  }
66 
68 
69  boost::scoped_ptr<Geometry_> resol_;
70  boost::scoped_ptr<oops::Variables> ctlvars_;
71  boost::scoped_ptr<util::DateTime> time_;
72 };
73 
74 // =============================================================================
75 
76 template <typename MODEL> void testIncrementConstructor() {
77  typedef IncrementFixture<MODEL> Test_;
78  typedef oops::Increment<MODEL> Increment_;
79 
80  Increment_ dx(Test_::resol(), Test_::ctlvars(), Test_::time());
81 
82  BOOST_CHECK_EQUAL(dx.norm(), 0.0);
83 }
84 
85 // -----------------------------------------------------------------------------
86 
87 template <typename MODEL> void testIncrementCopyConstructor() {
88  typedef IncrementFixture<MODEL> Test_;
89  typedef oops::Increment<MODEL> Increment_;
90 
91  Increment_ dx1(Test_::resol(), Test_::ctlvars(), Test_::time());
92  dx1.random();
93  BOOST_CHECK(dx1.norm() > 0.0);
94 
95  Increment_ dx2(dx1);
96  BOOST_CHECK(dx2.norm() > 0.0);
97 
98 // Check that the copy is equal to the original
99  dx2 -= dx1;
100  BOOST_CHECK_EQUAL(dx2.norm(), 0.0);
101 }
102 
103 // -----------------------------------------------------------------------------
104 
105 template <typename MODEL> void testIncrementTriangle() {
106  typedef IncrementFixture<MODEL> Test_;
107  typedef oops::Increment<MODEL> Increment_;
108 
109  Increment_ dx1(Test_::resol(), Test_::ctlvars(), Test_::time());
110  dx1.random();
111  Increment_ dx2(Test_::resol(), Test_::ctlvars(), Test_::time());
112  dx2.random();
113 
114 // test triangle inequality
115  double dot1 = dx1.norm();
116  BOOST_CHECK(dot1 > 0.0);
117 
118  double dot2 = dx2.norm();
119  BOOST_CHECK(dot2 > 0.0);
120 
121  dx2 += dx1;
122  double dot3 = dx2.norm();
123  BOOST_CHECK(dot3 > 0.0);
124 
125  BOOST_CHECK(dot3 <= dot1 + dot2);
126 }
127 
128 // -----------------------------------------------------------------------------
129 
130 template <typename MODEL> void testIncrementOpPlusEq() {
131  typedef IncrementFixture<MODEL> Test_;
132  typedef oops::Increment<MODEL> Increment_;
133 
134  Increment_ dx1(Test_::resol(), Test_::ctlvars(), Test_::time());
135  dx1.random();
136  Increment_ dx2(dx1);
137 
138 // test *= and +=
139  dx2 += dx1;
140  dx1 *= 2.0;
141 
142  dx2 -= dx1;
143  BOOST_CHECK_SMALL(dx2.norm(), 1e-8);
144 }
145 
146 // -----------------------------------------------------------------------------
147 
148 template <typename MODEL> void testIncrementDotProduct() {
149  typedef IncrementFixture<MODEL> Test_;
150  typedef oops::Increment<MODEL> Increment_;
151 
152  Increment_ dx1(Test_::resol(), Test_::ctlvars(), Test_::time());
153  dx1.random();
154  Increment_ dx2(Test_::resol(), Test_::ctlvars(), Test_::time());
155  dx2.random();
156 
157 // test symmetry of dot product
158  double zz1 = dot_product(dx1, dx2);
159  double zz2 = dot_product(dx2, dx1);
160 
161  BOOST_CHECK_EQUAL(zz1, zz2);
162 }
163 
164 // -----------------------------------------------------------------------------
165 
166 template <typename MODEL> void testIncrementZero() {
167  typedef IncrementFixture<MODEL> Test_;
168  typedef oops::Increment<MODEL> Increment_;
169 
170  Increment_ dx(Test_::resol(), Test_::ctlvars(), Test_::time());
171  dx.random();
172  BOOST_CHECK(dx.norm() > 0.0);
173 
174 // test zero
175  dx->zero();
176  BOOST_CHECK_EQUAL(dx.norm(), 0.0);
177 }
178 
179 // -----------------------------------------------------------------------------
180 
181 template <typename MODEL> void testIncrementAxpy() {
182  typedef IncrementFixture<MODEL> Test_;
183  typedef oops::Increment<MODEL> Increment_;
184 
185  Increment_ dx1(Test_::resol(), Test_::ctlvars(), Test_::time());
186  dx1.random();
187 
188 // test axpy
189  Increment_ dx2(dx1);
190  dx2.axpy(2.0, dx1);
191 
192  dx2 -= dx1;
193  dx2 -= dx1;
194  dx2 -= dx1;
195 
196  BOOST_CHECK_SMALL(dx2.norm(), 1e-8);
197 }
198 
199 // -----------------------------------------------------------------------------
200 
201 template <typename MODEL> void testIncrementInterpAD() {
202  typedef IncrementFixture<MODEL> Test_;
203  typedef oops::Increment<MODEL> Increment_;
204  typedef oops::Locations<MODEL> Locations_;
205  typedef oops::GeoVaLs<MODEL> GeoVaLs_;
206  typedef oops::InterpolatorTraj<MODEL> InterpolatorTraj_;
207  typedef oops::State<MODEL> State_;
208  typedef eckit::LocalConfiguration LocalConf_;
209 
210  // Check if "InterpTest" is present
211  if (!TestEnvironment::config().has("InterpTest")) {
212  oops::Log::warning() << "Bypassing test for adjoint of interpolation";
213  return;
214  }
215 
216  // Create Background
217  const LocalConf_ confstate(TestEnvironment::config(), "State");
218  const State_ xx(Test_::resol(), Test_::ctlvars(), confstate);
219 
220  // Locations from config
221  const LocalConf_ configlocs(TestEnvironment::config(), "InterpTest.Locations");
222  const Locations_ locs(configlocs);
223 
224  // Variables from config
225  const LocalConf_ configvars(TestEnvironment::config(), "InterpTest.GeoVaLs");
226  const oops::Variables vars(configvars);
227 
228  // Setup Increments
229  Increment_ dx(Test_::resol(), Test_::ctlvars(), Test_::time());
230  Increment_ Htdg(dx);
231  Htdg.zero();
232 
233  // Get tolerance of dot product test
234  const double tol = TestEnvironment::config().getDouble("InterpTest.tolerance");
235 
236  // Call NL getvalues to setup and initialize trajectory
237  InterpolatorTraj_ traj;
238  GeoVaLs_ hofx(locs, vars);
239  xx.getValues(locs, vars, hofx, traj);
240 
241  // Randomize increments
242  dx.random();
243 
244  // Create geovals from locs and vars
245  GeoVaLs_ Hdx(locs, vars);
246 
247  // Forward getValues (state to geovals)
248  dx.getValuesTL(locs, vars, Hdx, traj);
249 
250  // Setup and randomize geoval increments
251  GeoVaLs_ dg(Hdx);
252  dg.zero();
253  dg.random();
254 
255  // Backward getValues (geovals to state)
256  Htdg.getValuesAD(locs, vars, dg, traj);
257 
258  // Check adjoint: <Htdg,dx>=<dg,Hdx>
259  double zz1 = dot_product(Htdg, dx);
260  double zz2 = dot_product(dg, Hdx);
261 
262  oops::Log::debug() << "Adjoint test result: (<HTdg,dx>-<dg,Hdx>) = "
263  << zz1-zz2 << std::endl;
264 
265  BOOST_CHECK(zz1 != 0.0);
266  BOOST_CHECK(zz2 != 0.0);
267  BOOST_CHECK_CLOSE(zz1, zz2, tol);
268 }
269 
270 // =============================================================================
271 
272 template <typename MODEL> class Increment : public oops::Test {
273  public:
275  virtual ~Increment() {}
276  private:
277  std::string testid() const {return "test::Increment<" + MODEL::name() + ">";}
278 
279  void register_tests() const {
280  boost::unit_test::test_suite * ts = BOOST_TEST_SUITE("interface/Increment");
281 
282  ts->add(BOOST_TEST_CASE(&testIncrementConstructor<MODEL>));
283  ts->add(BOOST_TEST_CASE(&testIncrementCopyConstructor<MODEL>));
284  ts->add(BOOST_TEST_CASE(&testIncrementTriangle<MODEL>));
285  ts->add(BOOST_TEST_CASE(&testIncrementOpPlusEq<MODEL>));
286  ts->add(BOOST_TEST_CASE(&testIncrementDotProduct<MODEL>));
287  ts->add(BOOST_TEST_CASE(&testIncrementAxpy<MODEL>));
288  ts->add(BOOST_TEST_CASE(&testIncrementInterpAD<MODEL>));
289 
290  boost::unit_test::framework::master_test_suite().add(ts);
291  }
292 };
293 
294 // =============================================================================
295 
296 } // namespace test
297 
298 #endif // TEST_INTERFACE_INCREMENT_H_
oops::Geometry< MODEL > Geometry_
boost::scoped_ptr< util::DateTime > time_
integer, parameter, public warning
void testIncrementInterpAD()
static const oops::Variables & ctlvars()
static const util::DateTime & time()
void testIncrementTriangle()
static const Geometry_ & resol()
Encapsulates the model state.
void testIncrementAxpy()
boost::scoped_ptr< Geometry_ > resol_
static const eckit::Configuration & config()
character(len=32) name
void testIncrementZero()
void testIncrementCopyConstructor()
real(fp), parameter, public e
logical debug
Definition: mpp.F90:1297
void testIncrementOpPlusEq()
Increment Class: Difference between two states.
void testIncrementConstructor()
boost::scoped_ptr< oops::Variables > ctlvars_
static IncrementFixture< MODEL > & getInstance()
void testIncrementDotProduct()
std::string testid() const