11 #ifndef TEST_INTERFACE_LINEARMODEL_H_
12 #define TEST_INTERFACE_LINEARMODEL_H_
23 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
25 #include <boost/noncopyable.hpp>
27 #include "eckit/config/LocalConfiguration.h"
28 #include "eckit/testing/Test.h"
45 #include "oops/util/DateTime.h"
46 #include "oops/util/dot_product.h"
47 #include "oops/util/Duration.h"
91 return theLinearModelFixture;
96 const util::Duration len(
test_->getString(
"forecast length"));
106 const eckit::LocalConfiguration dbiasConf =
115 time_.reset(
new util::DateTime(
xref_->validTime()));
118 oops::instantiateCovarFactory<MODEL>();
126 oops::instantiateTlmFactory<MODEL>();
135 ~LinearModelFixture<MODEL>() {}
137 std::unique_ptr<const eckit::LocalConfiguration>
test_;
138 std::unique_ptr<const eckit::LocalConfiguration>
tlConf_;
140 std::unique_ptr<const util::DateTime>
time_;
142 std::unique_ptr<const State_>
xref_;
144 std::unique_ptr<const ModelAux_>
bias_;
145 std::unique_ptr<const ModelAuxIncr_>
dbias_;
146 std::unique_ptr<const Covariance_>
B_;
147 std::shared_ptr<LinearModel_>
tlm_;
155 const util::Duration zero(0);
156 EXPECT(Test_::tlm().timeResolution() > zero);
166 const util::DateTime vt(Test_::time());
167 const util::Duration zero(0);
169 Increment_ dxref(Test_::resol(), Test_::ctlvars(), vt);
170 Test_::covariance().randomize(dxref);
171 ModelAuxIncr_ daux(Test_::dbias());
172 const double ininorm = dxref.norm();
173 EXPECT(ininorm > 0.0);
175 Increment_ dx(Test_::resol(), Test_::ctlvars(), vt);
176 Increment_ dxm(Test_::resol(), Test_::tlm().variables(), vt);
178 Test_::tlm().forecastTL(dxm, daux, zero);
180 EXPECT(dx.validTime() == vt);
181 EXPECT(dx.norm() == ininorm);
185 Test_::tlm().forecastAD(dxm, daux, zero);
187 EXPECT(dx.validTime() == vt);
188 EXPECT(dx.norm() == ininorm);
198 const util::Duration len(Test_::test().getString(
"forecast length"));
199 const util::DateTime t1(Test_::time());
200 const util::DateTime t2(t1 + len);
203 Increment_ dx(Test_::resol(), Test_::tlm().variables(), t1);
204 ModelAuxIncr_ daux(Test_::dbias());
208 EXPECT(dx.norm() == 0.0);
209 Test_::tlm().forecastTL(dx, daux, len);
210 EXPECT(dx.validTime() == t2);
211 EXPECT(dx.norm() == 0.0);
215 EXPECT(dx.norm() == 0.0);
216 Test_::tlm().forecastAD(dx, daux, len);
217 EXPECT(dx.validTime() == t1);
218 EXPECT(dx.norm() == 0.0);
228 const util::Duration len(Test_::test().getString(
"forecast length"));
229 const util::DateTime t1(Test_::time());
230 const util::DateTime t2(t1 + len);
232 const double zz = 3.1415;
234 Increment_ dx1(Test_::resol(), Test_::tlm().variables(), t1);
235 Test_::covariance().randomize(dx1);
236 ModelAuxIncr_ daux1(Test_::dbias());
237 EXPECT(dx1.norm() > 0.0);
240 ModelAuxIncr_ daux2(daux1);
242 Test_::tlm().forecastTL(dx1, daux1, len);
243 EXPECT(dx1.validTime() == t2);
249 Test_::tlm().forecastTL(dx2, daux2, len);
250 EXPECT(dx2.validTime() == t2);
252 const double tol = Test_::test().getDouble(
"tolerance AD");
253 EXPECT(oops::is_close(dx1.norm(), dx2.norm(), tol));
263 const util::Duration len(Test_::test().getString(
"forecast length"));
264 const util::DateTime t1(Test_::time());
265 const util::DateTime t2(t1 + len);
268 Increment_ dx0(Test_::resol(), Test_::tlm().variables(), t1);
269 Test_::covariance().randomize(dx0);
270 EXPECT(dx0.norm() > 0.0);
273 Test_::tlm().forecastTL(dx, Test_::dbias(), len);
274 const double dxnorm = dx.norm();
277 State_ xx0(Test_::xref());
278 Test_::model().forecast(xx0, Test_::bias(), len, post);
280 const unsigned int ntest = Test_::test().getInt(
"iterations TL");
282 if (Test_::test().
has(
"first multiplier TL")) {
283 zz = Test_::test().getDouble(
"first multiplier TL");
286 std::vector<double> errors;
287 for (
unsigned int jtest = 0; jtest < ntest; ++jtest) {
288 State_ xx(Test_::xref());
289 Increment_ pert(dx0);
292 Test_::model().forecast(xx, Test_::bias(), len, post);
294 Increment_ diff(Test_::resol(), Test_::tlm().variables(), t2);
296 const double difnorm = diff.norm();
297 const double err = zz * dxnorm / difnorm;
301 const double errnorm = derr.norm();
302 errors.push_back(errnorm / difnorm);
303 oops::Log::test() <<
"TL error = " << std::setprecision(16) << err
304 <<
", relative error = " << errnorm / difnorm << std::endl;
309 const double approx = *std::min_element(errors.begin(), errors.end());
310 oops::Log::test() <<
"Test TL min error = " << approx << std::endl;
311 const double tol = Test_::test().getDouble(
"tolerance TL");
312 EXPECT(approx < tol);
322 const util::Duration len(Test_::test().getString(
"forecast length"));
323 const util::DateTime t1(Test_::time());
324 const util::DateTime t2(t1 + len);
327 Increment_ dx11(Test_::resol(), Test_::tlm().variables(), t1);
328 Test_::covariance().randomize(dx11);
329 ModelAuxIncr_ daux1(Test_::dbias());
330 EXPECT(dx11.norm() > 0.0);
331 Increment_ dx12(dx11);
332 Test_::tlm().forecastTL(dx12, daux1, len);
333 EXPECT(dx12.norm() > 0.0);
334 Increment_ dx22(Test_::resol(), Test_::tlm().variables(), t2);
335 Test_::covariance().randomize(dx22);
336 ModelAuxIncr_ daux2(Test_::dbias());
337 EXPECT(dx22.norm() > 0.0);
338 Increment_ dx21(dx22);
339 Test_::tlm().forecastAD(dx21, daux2, len);
340 EXPECT(dx21.norm() > 0.0);
342 EXPECT(dx11.norm() != dx22.norm());
343 EXPECT(dx11.validTime() == t1);
344 EXPECT(dx21.validTime() == t1);
345 EXPECT(dx12.validTime() == t2);
346 EXPECT(dx22.validTime() == t2);
348 const double dot1 = dot_product(dx11, dx21);
349 const double dot2 = dot_product(dx12, dx22);
350 const double tol = Test_::test().getDouble(
"tolerance AD");
351 EXPECT(oops::is_close(dot1, dot2, tol));
356 template <
typename MODEL>
363 std::string
testid()
const override {
return "test::LinearModel<" + MODEL::name() +
">";}
366 std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
368 ts.emplace_back(
CASE(
"interface/GeometryIterator/testLinearModelConstructor")
369 { testLinearModelConstructor<MODEL>(); });
370 ts.emplace_back(
CASE(
"interface/GeometryIterator/testLinearModelZeroLength")
371 { testLinearModelZeroLength<MODEL>(); });
372 ts.emplace_back(
CASE(
"interface/GeometryIterator/testLinearModelZeroPert")
373 { testLinearModelZeroPert<MODEL>(); });
374 ts.emplace_back(
CASE(
"interface/GeometryIterator/testLinearModelLinearity")
375 { testLinearModelLinearity<MODEL>(); });
376 ts.emplace_back(
CASE(
"interface/GeometryIterator/testLinearApproximation")
377 { testLinearApproximation<MODEL>(); });
378 ts.emplace_back(
CASE(
"interface/GeometryIterator/testLinearModelAdjoint")
379 { testLinearModelAdjoint<MODEL>(); });
389 #endif // TEST_INTERFACE_LINEARMODEL_H_