FV3 Bundle
test/lorenz95/ObsBiasCorrection.cc
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 #include <fstream>
12 #include <iostream>
13 
14 #include <boost/lexical_cast.hpp>
15 #include <boost/scoped_ptr.hpp>
16 #include <boost/test/unit_test.hpp>
17 
18 #include "./TestConfig.h"
19 #include "eckit/config/LocalConfiguration.h"
20 #include "lorenz95/ObsBias.h"
22 #include "test/TestFixture.h"
23 
24 namespace test {
25 
26 // -----------------------------------------------------------------------------
27 class ObsBiasTestFixture : TestFixture {
28  public:
30  off_.reset(new eckit::LocalConfiguration());
31  conf_.reset(new eckit::LocalConfiguration(TestConfig::config(), "ObsBiasCovariance"));
32  eckit::LocalConfiguration bconf(TestConfig::config(), "ObsBias");
33  obias_.reset(new lorenz95::ObsBias(bconf));
34  bias1_ = bconf.getDouble("bias");
35  bias2_ = 3.5 * bias1_;
36  fact_ = 1.234;
37  }
39  boost::scoped_ptr<const eckit::LocalConfiguration> off_;
40  boost::scoped_ptr<const eckit::LocalConfiguration> conf_;
41  double bias1_;
42  double bias2_;
43  double fact_;
44  boost::scoped_ptr<lorenz95::ObsBias> obias_;
45 };
46 
47 // -----------------------------------------------------------------------------
48 BOOST_FIXTURE_TEST_SUITE(test_obsBiasCorrection, ObsBiasTestFixture)
49 // -----------------------------------------------------------------------------
50  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_constructor_active) {
51  lorenz95::ObsBiasCorrection dob(*conf_);
52  BOOST_CHECK_EQUAL(dob.value(), 0.0);
53  }
54 // -----------------------------------------------------------------------------
55  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_constructor_inactive) {
56  lorenz95::ObsBiasCorrection dob(*off_);
57  BOOST_CHECK_EQUAL(dob.value(), 0.0);
58  }
59 // -----------------------------------------------------------------------------
60  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_copy_ctor_active_copy) {
61  lorenz95::ObsBiasCorrection dob1(*conf_);
62  dob1.value() = bias1_;
63 
64  lorenz95::ObsBiasCorrection dob2(dob1, true);
65 
66  BOOST_CHECK_EQUAL(dob2.value(), bias1_);
67  }
68 // -----------------------------------------------------------------------------
69  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_copy_ctor_active_no_copy) {
70  lorenz95::ObsBiasCorrection dob1(*conf_);
71  dob1.value() = bias1_;
72 
73  lorenz95::ObsBiasCorrection dob2(dob1, false);
74 
75  // because the copy is false,
76  // the active_ flag is true and the bias1_ value is 0.0
77  BOOST_CHECK_EQUAL(dob2.value(), 0.0);
78  }
79 // -----------------------------------------------------------------------------
80  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_copy_ctor_inactive_copy) {
81  lorenz95::ObsBiasCorrection dob1(*off_);
82  dob1.value() = bias1_;
83 
84  lorenz95::ObsBiasCorrection dob2(dob1, true);
85 
86  // because the cfg is empty when used,
87  // the active_ flag is false and the bias1_ value is 0.0
88  BOOST_CHECK_EQUAL(dob2.value(), 0.0);
89  }
90 // -----------------------------------------------------------------------------
91  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_copy_ctor_inactive_no_copy) {
92  lorenz95::ObsBiasCorrection dob1(*off_);
93  dob1.value() = bias1_;
94 
95  lorenz95::ObsBiasCorrection dob2(dob1, false);
96 
97  // because the cfg is empty when used and the copy flag is false,
98  // the active_ flag is false and the bias1_ value is 0.0
99  BOOST_CHECK_EQUAL(dob2.value(), 0.0);
100  }
101 // -----------------------------------------------------------------------------
102  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_copy_constructor_config) {
103  lorenz95::ObsBiasCorrection dob1(*conf_);
104  dob1.value() = bias1_;
105 
106  lorenz95::ObsBiasCorrection dob2(dob1, *conf_);
107 
108  BOOST_CHECK_EQUAL(dob2.value(), bias1_);
109  }
110 // -----------------------------------------------------------------------------
111  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_copy_constructor_no_config) {
112  lorenz95::ObsBiasCorrection dob1(*off_);
113  dob1.value() = bias1_;
114 
115  lorenz95::ObsBiasCorrection dob2(dob1, eckit::LocalConfiguration());
116 
117  // because the covarCfg is empty when used (regardless of the cfg),
118  // the active_ flag is false and the bias1_ value is 0.0
119  BOOST_CHECK_EQUAL(dob2.value(), 0.0);
120  }
121 // -----------------------------------------------------------------------------
122  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_diff_active) {
123  lorenz95::ObsBias obias2(*conf_);
124  obias2.value() = bias2_;
125 
126  lorenz95::ObsBiasCorrection dob(*conf_);
127 
128  dob.diff(*obias_, obias2);
129 
130  BOOST_CHECK_EQUAL(dob.value(), bias1_ - bias2_);
131  }
132 // -----------------------------------------------------------------------------
133  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_diff_inactive) {
134  lorenz95::ObsBias obias2(*conf_);
135  obias2.value() = bias2_;
136 
137  // construct the dob object with empty config
138  lorenz95::ObsBiasCorrection dob(*off_);
139 
140  dob.diff(*obias_, obias2);
141 
142  // because the OBC has empty config the active_flag is false and
143  // the diff will not be performed, leaving the OBC value unchanged
144  BOOST_CHECK_EQUAL(dob.value(), 0.0);
145  }
146 // -----------------------------------------------------------------------------
147  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_zero) {
148  lorenz95::ObsBiasCorrection dob(*conf_);
149  dob.value() = bias1_;
150 
151  dob.zero();
152 
153  BOOST_CHECK_EQUAL(dob.value(), 0.0);
154  }
155 // -----------------------------------------------------------------------------
156  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_assignment_active) {
157  lorenz95::ObsBiasCorrection dob1(*conf_);
158  dob1.value() = bias1_;
159  lorenz95::ObsBiasCorrection dob2(dob1);
160  dob2.value() = bias2_;
161 
162  dob1 = dob2;
163 
164  BOOST_CHECK_EQUAL(dob1.value(), bias2_);
165  }
166 // -----------------------------------------------------------------------------
167  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_assignment_inactive) {
168  lorenz95::ObsBiasCorrection dob1(*off_);
169  dob1.value() = bias1_;
170  lorenz95::ObsBiasCorrection dob2(dob1);
171  dob2.value() = bias2_;
172 
173  dob1 = dob2;
174 
175  // because the OBC has empty config the active_ flag is false
176  BOOST_CHECK_EQUAL(dob1.value(), 0.0);
177  }
178 // -----------------------------------------------------------------------------
179  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_assignment_add_active) {
180  lorenz95::ObsBiasCorrection dob1(*conf_);
181  dob1.value() = bias1_;
182  lorenz95::ObsBiasCorrection dob2(dob1);
183  dob2.value() = bias2_;
184 
185  dob1 += dob2;
186 
187  BOOST_CHECK_EQUAL(dob1.value(), bias1_ + bias2_);
188  }
189 // -----------------------------------------------------------------------------
190  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_assign_add_inactive) {
191  lorenz95::ObsBiasCorrection dob1(*off_);
192  dob1.value() = bias1_;
193  lorenz95::ObsBiasCorrection dob2(dob1);
194  dob2.value() = bias2_;
195 
196  dob1 += dob2;
197 
198  // because the OBC has empty config, the bias value is unchanged
199  BOOST_CHECK_EQUAL(dob1.value(), bias1_);
200  }
201 // -----------------------------------------------------------------------------
202  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_assignment_subtract_active) {
203  lorenz95::ObsBiasCorrection dob1(*conf_);
204  dob1.value() = bias1_;
205  lorenz95::ObsBiasCorrection dob2(dob1);
206  dob2.value() = bias2_;
207 
208  dob1 -= dob2;
209 
210  BOOST_CHECK_EQUAL(dob1.value(), bias1_ - bias2_);
211  }
212 // -----------------------------------------------------------------------------
213  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_assignment_subtract_inactive) {
214  lorenz95::ObsBiasCorrection dob1(*off_);
215  dob1.value() = bias1_;
216  lorenz95::ObsBiasCorrection dob2(dob1);
217  dob2.value() = bias2_;
218 
219  dob1 -= dob2;
220 
221  // because the OBC has empty config, the bias value is unchanged
222  BOOST_CHECK_EQUAL(dob1.value(), bias1_);
223  }
224 // -----------------------------------------------------------------------------
225  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_assignment_multiply_active) {
226  lorenz95::ObsBiasCorrection dob(*conf_);
227  dob.value() = bias1_;
228 
229  dob *= fact_;
230 
231  BOOST_CHECK_EQUAL(dob.value(), bias1_ * fact_);
232  }
233 // -----------------------------------------------------------------------------
234  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_assignment_multiply_inactive) {
235  lorenz95::ObsBiasCorrection dob(*off_);
236  dob.value() = bias1_;
237 
238  dob *= fact_;
239 
240  // because the OBC has empty config, the bias value is unchanged
241  BOOST_CHECK_EQUAL(dob.value(), bias1_);
242  }
243 // -----------------------------------------------------------------------------
244  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_axpy_active) {
245  lorenz95::ObsBiasCorrection dob1(*conf_);
246  dob1.value() = bias1_;
247  lorenz95::ObsBiasCorrection dob2(dob1);
248  dob2.value() = bias2_;
249 
250  dob1.axpy(fact_, dob2);
251 
252  BOOST_CHECK_EQUAL(dob1.value(), bias1_ + (fact_ * bias2_));
253  }
254 // -----------------------------------------------------------------------------
255  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_axpy_inactive) {
256  lorenz95::ObsBiasCorrection dob1(*off_);
257  dob1.value() = bias1_;
258  lorenz95::ObsBiasCorrection dob2(dob1);
259  dob2.value() = bias2_;
260 
261  dob1.axpy(fact_, dob2);
262 
263  // because the OBC has empty config, the bias value is unchanged
264  BOOST_CHECK_EQUAL(dob1.value(), bias1_);
265  }
266 // -----------------------------------------------------------------------------
267  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_dot_product_with_active) {
268  lorenz95::ObsBiasCorrection dob1(*conf_);
269  dob1.value() = bias1_;
270  lorenz95::ObsBiasCorrection dob2(dob1);
271  dob2.value() = bias2_;
272 
273  double dpwResult = dob1.dot_product_with(dob2);
274 
275  BOOST_CHECK_EQUAL(dpwResult, bias1_ * bias2_);
276  }
277 // -----------------------------------------------------------------------------
278  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_dot_product_with_inactive) {
279  lorenz95::ObsBiasCorrection dob1(*off_);
280  dob1.value() = bias1_;
281  lorenz95::ObsBiasCorrection dob2(dob1);
282  dob2.value() = bias2_;
283 
284  double dpwResult = dob1.dot_product_with(dob2);
285 
286  // because the OBC has empty config, the result is 0
287  BOOST_CHECK_EQUAL(dpwResult, 0.0);
288  }
289 // -----------------------------------------------------------------------------
290  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_read) {
291  // not yet implemented
292  }
293 // -----------------------------------------------------------------------------
294  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_write) {
295  // not yet implemented
296  }
297 // -----------------------------------------------------------------------------
298  BOOST_AUTO_TEST_CASE(test_obsBiasCorrection_stream_output) {
299  lorenz95::ObsBiasCorrection dob(*conf_);
300  dob.value() = bias1_;
301 
302  // use the operator<< method to write the value to a file
303  std::filebuf fb;
304  std::string filename("ObsBiasCorrectionTest.txt");
305  fb.open(filename.c_str(), std::ios::out);
306  std::ostream os(&fb);
307  os << dob;
308  fb.close();
309 
310  // then read the value that was written to the file
311  std::string inputString;
312  std::string inputBias;
313  double bias = 0.0;
314  int biasStartPos = 20; // length of "ObsBiasCorrection = " is 20
315  std::ifstream inputFile(filename.c_str());
316  if (inputFile.is_open()) {
317  getline(inputFile, inputString); // ignore first (blank) line
318  getline(inputFile, inputString);
319 
320  inputBias = inputString.substr(biasStartPos);
321 
322  try {
323  bias = boost::lexical_cast<double>(inputBias);
324  }
325  catch(boost::bad_lexical_cast const&) {
326  BOOST_ERROR("operator<< incorrectly output a non-double");
327  }
328 
329  BOOST_CHECK_CLOSE(bias1_, bias, 0.0001);
330  } else {
331  // if we can't open the file then we can't
332  // verify that the value was correctly written
333  BOOST_ERROR("operator<< functionality cannot be determined");
334  }
335  inputFile.close();
336  }
337 // -----------------------------------------------------------------------------
338 
339 BOOST_AUTO_TEST_SUITE_END()
340 } // namespace test
boost::scoped_ptr< const eckit::LocalConfiguration > conf_
Class to handle observation bias parameters.
boost::scoped_ptr< const eckit::LocalConfiguration > off_
double dot_product_with(const ObsBiasCorrection &) const
boost::scoped_ptr< lorenz95::ObsBias > obias_
void axpy(const double, const ObsBiasCorrection &)
void diff(const ObsBias &, const ObsBias &)
Linear algebra operators.
BOOST_AUTO_TEST_CASE(test_GomL95_constructor)
static const eckit::Configuration & config()
Definition: TestConfig.h:30
const double & value() const