OOPS
test/interface/ErrorCovariance.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_ERRORCOVARIANCE_H_
12 #define TEST_INTERFACE_ERRORCOVARIANCE_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/Configuration.h"
25 #include "eckit/testing/Test.h"
28 #include "oops/base/Variables.h"
31 #include "oops/interface/State.h"
32 #include "oops/mpi/mpi.h"
33 #include "oops/runs/Test.h"
34 #include "oops/util/DateTime.h"
35 #include "oops/util/dot_product.h"
36 #include "oops/util/Expect.h"
37 #include "oops/util/Logger.h"
38 #include "test/TestEnvironment.h"
39 
40 namespace test {
41 
42 // =============================================================================
43 
44 template <typename MODEL> class ErrorCovarianceFixture : private boost::noncopyable {
47 
48  public:
49  static const eckit::Configuration & test() {return *getInstance().test_;}
50  static const Geometry_ & resol() {return *getInstance().resol_;}
51  static const oops::Variables & ctlvars() {return *getInstance().ctlvars_;}
52  static const util::DateTime & time() {return *getInstance().time_;}
53  static const Covariance_ & covariance() {return *getInstance().B_;}
54 
55  private:
57  static ErrorCovarianceFixture<MODEL> theErrorCovarianceFixture;
58  return theErrorCovarianceFixture;
59  }
60 
62  oops::instantiateCovarFactory<MODEL>();
63 
64  test_.reset(new eckit::LocalConfiguration(TestEnvironment::config(), "covariance test"));
65 
66  const eckit::LocalConfiguration resolConfig(TestEnvironment::config(), "geometry");
67  resol_.reset(new Geometry_(resolConfig, oops::mpi::world()));
68 
69  ctlvars_.reset(new oops::Variables(TestEnvironment::config(), "analysis variables"));
70 
71  const eckit::LocalConfiguration fgconf(TestEnvironment::config(), "background");
72  oops::State<MODEL> xx(*resol_, fgconf);
73 
74  time_.reset(new util::DateTime(xx.validTime()));
75 
76 // Setup the B matrix
77  const eckit::LocalConfiguration covar(TestEnvironment::config(), "background error");
78  B_.reset(oops::CovarianceFactory<MODEL>::create(covar, *resol_, *ctlvars_, xx, xx));
79  }
80 
81  ~ErrorCovarianceFixture<MODEL>() {}
82 
83  std::unique_ptr<const eckit::LocalConfiguration> test_;
84  std::unique_ptr<const Geometry_> resol_;
85  std::unique_ptr<const oops::Variables> ctlvars_;
86  std::unique_ptr<const util::DateTime> time_;
87  std::unique_ptr<Covariance_> B_;
88 };
89 
90 // =============================================================================
91 
92 template <typename MODEL> void testErrorCovarianceZero() {
93  typedef ErrorCovarianceFixture<MODEL> Test_;
94  typedef oops::Increment<MODEL> Increment_;
95 
96  Increment_ dx1(Test_::resol(), Test_::ctlvars(), Test_::time());
97  Increment_ dx2(Test_::resol(), Test_::ctlvars(), Test_::time());
98 
99  Test_::covariance().randomize(dx2);
100  oops::Log::info() << "dx2.norm()=" << dx2.norm() << std::endl;
101 
102  EXPECT(dx1.norm() == 0.0);
103  EXPECT(dx2.norm() > 0.0);
104 
105  Test_::covariance().multiply(dx1, dx2);
106  EXPECT(dx2.norm() == 0.0);
107 
108  const bool testinverse = Test_::test().getBool("testinverse", true);
109  if (testinverse)
110  {
111  oops::Log::info() << "Doing zero test for inverse" << std::endl;
112  dx1.zero();
113  Test_::covariance().randomize(dx2);
114  EXPECT(dx1.norm() == 0.0);
115  EXPECT(dx2.norm() > 0.0);
116  Test_::covariance().inverseMultiply(dx1, dx2);
117  EXPECT(dx2.norm() == 0.0);
118  } else {
119  oops::Log::info() << "Not doing zero test for inverse" << std::endl;
120  }
121 }
122 
123 // -----------------------------------------------------------------------------
124 
125 template <typename MODEL> void testErrorCovarianceInverse() {
126  typedef ErrorCovarianceFixture<MODEL> Test_;
127  typedef oops::Increment<MODEL> Increment_;
128 
129  const bool testinverse = Test_::test().getBool("testinverse", true);
130  if (testinverse)
131  {
132  Increment_ dx1(Test_::resol(), Test_::ctlvars(), Test_::time());
133  Increment_ dx2(Test_::resol(), Test_::ctlvars(), Test_::time());
134  Increment_ dx3(Test_::resol(), Test_::ctlvars(), Test_::time());
135  Test_::covariance().randomize(dx1);
136  EXPECT(dx1.norm() > 0.0);
137 
138  Test_::covariance().multiply(dx1, dx2);
139  Test_::covariance().inverseMultiply(dx2, dx3);
140 
141  EXPECT(dx2.norm() > 0.0);
142  EXPECT(dx3.norm() > 0.0);
143  dx3 -= dx1;
144  const double tol = Test_::test().getDouble("tolerance");
145  EXPECT(dx3.norm()/dx1.norm() < tol);
146  } else {
147  return;
148  }
149 }
150 
151 // -----------------------------------------------------------------------------
152 
153 template <typename MODEL> void testErrorCovarianceSym() {
154  typedef ErrorCovarianceFixture<MODEL> Test_;
155  typedef oops::Increment<MODEL> Increment_;
156 
157  Increment_ dx(Test_::resol(), Test_::ctlvars(), Test_::time());
158  Increment_ Bdx(Test_::resol(), Test_::ctlvars(), Test_::time());
159  Increment_ dy(Test_::resol(), Test_::ctlvars(), Test_::time());
160  Increment_ Bdy(Test_::resol(), Test_::ctlvars(), Test_::time());
161 
162  dx.random();
163  dy.random();
164 
165  Test_::covariance().multiply(dx, Bdx);
166  Test_::covariance().multiply(dy, Bdy);
167  const double zz1 = dot_product(dx, Bdy);
168  const double zz2 = dot_product(Bdx, dy);
169  oops::Log::info() << "<dx,Bdy>-<Bdx,dy>/<dx,Bdy>="
170  << (zz1-zz2)/zz1 << std::endl;
171  oops::Log::info() << "<dx,Bdy>-<Bdx,dy>/<Bdx,dy>="
172  << (zz1-zz2)/zz2 << std::endl;
173  const double tol = Test_::test().getDouble("tolerance");
174  EXPECT(oops::is_close(zz1, zz2, tol));
175 }
176 
177 // -----------------------------------------------------------------------------
178 
179 template <typename MODEL> void testCovarianceParametersWrapperValidName() {
180  eckit::LocalConfiguration config(TestEnvironment::config(), "background error");
182  EXPECT_NO_THROW(parameters.validateAndDeserialize(config));
183 }
184 
185 // -----------------------------------------------------------------------------
186 
187 template <typename MODEL> void testCovarianceParametersWrapperInvalidName() {
188  eckit::LocalConfiguration config;
189  config.set("covariance model", "###INVALID###");
191  if (oops::Parameters::isValidationSupported())
192  EXPECT_THROWS_MSG(parameters.validate(config), "unrecognized enum value");
193  EXPECT_THROWS_MSG(parameters.deserialize(config),
194  "does not exist in CovarianceFactory");
195 }
196 
197 // -----------------------------------------------------------------------------
198 
199 template <typename MODEL> void testCovarianceFactoryGetMakerNames() {
200  eckit::LocalConfiguration config(TestEnvironment::config(), "background error");
201  const std::string validName = config.getString("covariance model");
202  const std::vector<std::string> registeredNames =
204  const bool found = std::find(registeredNames.begin(), registeredNames.end(), validName) !=
205  registeredNames.end();
206  EXPECT(found);
207 }
208 
209 // =============================================================================
210 
211 template <typename MODEL>
212 class ErrorCovariance : public oops::Test {
213  public:
215  virtual ~ErrorCovariance() {}
216 
217  private:
218  std::string testid() const override {return "test::ErrorCovariance<" + MODEL::name() + ">";}
219 
220  void register_tests() const override {
221  std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
222 
223  ts.emplace_back(CASE("interface/ErrorCovariance/testErrorCovarianceZero")
224  { testErrorCovarianceZero<MODEL>(); });
225  ts.emplace_back(CASE("interface/ErrorCovariance/testErrorCovarianceInverse")
226  { testErrorCovarianceInverse<MODEL>(); });
227  ts.emplace_back(CASE("interface/ErrorCovariance/testErrorCovarianceSym")
228  { testErrorCovarianceSym<MODEL>(); });
229  ts.emplace_back(CASE("interface/ErrorCovariance/testCovarianceParametersWrapperValidName")
230  { testCovarianceParametersWrapperValidName<MODEL>(); });
231  ts.emplace_back(CASE("interface/ErrorCovariance/testCovarianceParametersWrapperInvalidName")
232  { testCovarianceParametersWrapperInvalidName<MODEL>(); });
233  ts.emplace_back(CASE("interface/ErrorCovariance/testCovarianceFactoryGetMakerNames")
234  { testCovarianceFactoryGetMakerNames<MODEL>(); });
235  }
236 
237  void clear() const override {}
238 };
239 
240 // =============================================================================
241 
242 } // namespace test
243 
244 #endif // TEST_INTERFACE_ERRORCOVARIANCE_H_
test::ErrorCovarianceFixture::getInstance
static ErrorCovarianceFixture< MODEL > & getInstance()
Definition: test/interface/ErrorCovariance.h:56
test::ErrorCovarianceFixture::ctlvars_
std::unique_ptr< const oops::Variables > ctlvars_
Definition: test/interface/ErrorCovariance.h:85
test::ErrorCovarianceFixture::Covariance_
oops::ModelSpaceCovarianceBase< MODEL > Covariance_
Definition: test/interface/ErrorCovariance.h:45
ModelSpaceCovarianceBase.h
oops::CovarianceFactory
Covariance Factory.
Definition: ModelSpaceCovarianceBase.h:93
test::ErrorCovarianceFixture::resol
static const Geometry_ & resol()
Definition: test/interface/ErrorCovariance.h:50
mpi.h
test::testErrorCovarianceInverse
void testErrorCovarianceInverse()
Definition: test/interface/ErrorCovariance.h:125
test::testErrorCovarianceSym
void testErrorCovarianceSym()
Definition: test/interface/ErrorCovariance.h:153
test::CASE
CASE("test_linearmodelparameterswrapper_valid_name")
Definition: LinearModelFactory.cc:22
test
Definition: LinearModelFactory.cc:20
test::ErrorCovarianceFixture::time_
std::unique_ptr< const util::DateTime > time_
Definition: test/interface/ErrorCovariance.h:86
test::ErrorCovarianceFixture::time
static const util::DateTime & time()
Definition: test/interface/ErrorCovariance.h:52
test::ErrorCovarianceFixture::B_
std::unique_ptr< Covariance_ > B_
Definition: test/interface/ErrorCovariance.h:87
test::ErrorCovariance::ErrorCovariance
ErrorCovariance()
Definition: test/interface/ErrorCovariance.h:214
Test.h
test::testCovarianceParametersWrapperInvalidName
void testCovarianceParametersWrapperInvalidName()
Definition: test/interface/ErrorCovariance.h:187
test::TestEnvironment::config
static const eckit::Configuration & config()
Definition: TestEnvironment.h:40
test::testCovarianceFactoryGetMakerNames
void testCovarianceFactoryGetMakerNames()
Definition: test/interface/ErrorCovariance.h:199
oops::ModelSpaceCovarianceParametersWrapper
Contains a polymorphic parameter holding an instance of a subclass of ModelSpaceCovarianceParametersB...
Definition: ModelSpaceCovarianceBase.h:120
test::ErrorCovariance
Definition: test/interface/ErrorCovariance.h:212
test::ErrorCovarianceFixture::ctlvars
static const oops::Variables & ctlvars()
Definition: test/interface/ErrorCovariance.h:51
test::ErrorCovarianceFixture::resol_
std::unique_ptr< const Geometry_ > resol_
Definition: test/interface/ErrorCovariance.h:84
test::testErrorCovarianceZero
void testErrorCovarianceZero()
Definition: test/interface/ErrorCovariance.h:92
test::ErrorCovarianceFixture
Definition: test/interface/ErrorCovariance.h:44
test::ErrorCovarianceFixture::Geometry_
oops::Geometry< MODEL > Geometry_
Definition: test/interface/ErrorCovariance.h:46
test::testCovarianceParametersWrapperValidName
void testCovarianceParametersWrapperValidName()
Definition: test/interface/ErrorCovariance.h:179
test::ErrorCovariance::~ErrorCovariance
virtual ~ErrorCovariance()
Definition: test/interface/ErrorCovariance.h:215
oops::Geometry
Geometry class used in oops; subclass of interface class above.
Definition: oops/interface/Geometry.h:189
instantiateCovarFactory.h
TestEnvironment.h
test::ErrorCovarianceFixture::test
static const eckit::Configuration & test()
Definition: test/interface/ErrorCovariance.h:49
oops::CovarianceFactory::getMakerNames
static std::vector< std::string > getMakerNames()
Return the names of all covariance models that can be created by one of the registered makers.
Definition: ModelSpaceCovarianceBase.h:163
test::ErrorCovarianceFixture::test_
std::unique_ptr< const eckit::LocalConfiguration > test_
Definition: test/interface/ErrorCovariance.h:83
test::ErrorCovariance::testid
std::string testid() const override
Definition: test/interface/ErrorCovariance.h:218
oops::State
Encapsulates the model state.
Definition: CostJbState.h:28
test::ErrorCovarianceFixture::covariance
static const Covariance_ & covariance()
Definition: test/interface/ErrorCovariance.h:53
oops::Test
Definition: Test.h:39
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
oops::Variables
Definition: oops/base/Variables.h:23
oops::ModelSpaceCovarianceBase
Definition: ModelSpaceCovarianceBase.h:61
oops::Increment
Increment Class: Difference between two states.
Definition: CostJbState.h:27
test::ErrorCovariance::clear
void clear() const override
Definition: test/interface/ErrorCovariance.h:237
test::ErrorCovariance::register_tests
void register_tests() const override
Definition: test/interface/ErrorCovariance.h:220
Variables.h
Geometry.h
Increment.h