8 #ifndef TEST_INTERFACE_LINEARGETVALUES_H_
9 #define TEST_INTERFACE_LINEARGETVALUES_H_
20 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
22 #include <boost/noncopyable.hpp>
23 #include <boost/ptr_container/ptr_vector.hpp>
25 #include "eckit/config/LocalConfiguration.h"
26 #include "eckit/testing/Test.h"
37 #include "oops/util/DateTime.h"
38 #include "oops/util/dot_product.h"
39 #include "oops/util/Duration.h"
74 return theLinearGetValuesFixture;
117 ~LinearGetValuesFixture<MODEL, OBS>() {}
119 std::unique_ptr<const DateTime_>
time_;
127 std::unique_ptr<const Locations_>
locs_;
139 std::unique_ptr<const LinearGetValues_> lineargetvalues(
new LinearGetValues_(Test_::resol(),
141 EXPECT(lineargetvalues.get());
143 lineargetvalues.reset();
144 EXPECT(!lineargetvalues.get());
154 Increment_ dx(Test_::resol(), Test_::statevars(), Test_::time());
157 GeoVaLs_ gv(Test_::locs(), Test_::geovalvars());
159 EXPECT(dx.norm() == 0.0);
161 Test_::lineargetvalues().fillGeoVaLsTL(dx, Test_::timebeg(), Test_::timeend(), gv);
163 EXPECT(dx.norm() == 0.0);
164 EXPECT(gv.rms() == 0.0);
166 Test_::lineargetvalues().fillGeoVaLsAD(dx, Test_::timebeg(), Test_::timeend(), gv);
168 EXPECT(dx.norm() == 0.0);
169 EXPECT(gv.rms() == 0.0);
179 const double zz = 3.1415;
181 Increment_ dx1(Test_::resol(), Test_::statevars(), Test_::time());
185 EXPECT(dx1.norm() > 0.0);
186 EXPECT(dx2.norm() > 0.0);
188 GeoVaLs_ gv1(Test_::locs(), Test_::geovalvars());
189 GeoVaLs_ gv2(Test_::locs(), Test_::geovalvars());
192 Test_::lineargetvalues().fillGeoVaLsTL(dx1, Test_::timebeg(), Test_::timeend(), gv1);
198 Test_::lineargetvalues().fillGeoVaLsTL(dx2, Test_::timebeg(), Test_::timeend(), gv2);
200 const double tol = Test_::testconf().getDouble(
"tolerance linearity", 1.0e-11);
201 EXPECT(oops::is_close(gv1.rms(), gv2.rms(), tol));
212 const unsigned int ntest = Test_::testconf().getInt(
"iterations TL", 10);
213 double zz = Test_::testconf().getDouble(
"first multiplier TL", 1.0e-2);
216 State_ xx0(Test_::state());
217 GeoVaLs_ gv0(Test_::locs(), Test_::geovalvars());
218 Test_::getvalues().fillGeoVaLs(xx0, Test_::timebeg(), Test_::timeend(), gv0);
221 Increment_ dx0(Test_::resol(), Test_::statevars(), Test_::time());
224 std::vector<double> errors;
225 for (
unsigned int jtest = 0; jtest < ntest; ++jtest) {
228 GeoVaLs_ gv(Test_::locs(), Test_::geovalvars());
229 GeoVaLs_ dgv(Test_::locs(), Test_::geovalvars());
234 Test_::getvalues().fillGeoVaLs(xx, Test_::timebeg(), Test_::timeend(), gv);
237 Test_::lineargetvalues().fillGeoVaLsTL(dxx, Test_::timebeg(), Test_::timeend(), dgv);
243 const double nlnorm = gvdiff.rms();
244 const double tlnorm = dgv.rms();
249 double testdot = dot_product(gvdiff, gvdiff);
250 errors.push_back(testdot);
252 oops::Log::test() <<
" ||g(x+dx) - g(x)|| = " << std::setprecision(16) << nlnorm << std::endl;
253 oops::Log::test() <<
" ||Gdx|| = " << std::setprecision(16) << tlnorm << std::endl;
254 oops::Log::test() <<
"||g(x+dx)-g(x)-Gdx|| = " << std::setprecision(16) << testdot << std::endl;
260 const double approx = *std::min_element(errors.begin(), errors.end());
261 oops::Log::test() <<
"Test LinearGetValuesTL min error = " << approx << std::endl;
262 const double tol = Test_::testconf().getDouble(
"tolerance TL", 1.0e-11);
263 EXPECT(approx < tol);
273 Increment_ dx_in(Test_::resol(), Test_::statevars(), Test_::time());
274 Increment_ dx_ou(Test_::resol(), Test_::statevars(), Test_::time());
276 GeoVaLs_ gv_ou(Test_::locs(), Test_::geovalvars());
280 EXPECT(dx_in.norm() > 0.0);
281 Test_::lineargetvalues().fillGeoVaLsTL(dx_in, Test_::timebeg(), Test_::timeend(), gv_ou);
282 EXPECT(gv_ou.rms() > 0.0);
285 GeoVaLs_ gv_in(gv_ou);
287 EXPECT(gv_in.rms() > 0.0);
289 Test_::lineargetvalues().fillGeoVaLsAD(dx_ou, Test_::timebeg(), Test_::timeend(), gv_in);
290 EXPECT(dx_ou.norm() > 0.0);
293 const double dot1 = dot_product(dx_in, dx_ou);
294 const double dot2 = dot_product(gv_in, gv_ou);
295 const double tol = Test_::testconf().getDouble(
"tolerance AD", 1.0e-11);
296 EXPECT(oops::is_close(dot1, dot2, tol));
298 oops::Log::test() <<
"Dot Product <dx, M^Tgv> = " << std::setprecision(16) << dot1 << std::endl;
299 oops::Log::test() <<
"Dot Product <gv, M dx> = " << std::setprecision(16) << dot2 << std::endl;
300 oops::Log::test() <<
"Relative diff: " << std::setprecision(16) << (dot1-dot2)/dot1 << std::endl;
305 template <
typename MODEL,
typename OBS>
312 std::string
testid()
const override {
return "test::LinearGetValues<" + MODEL::name() +
", "
313 + OBS::name() +
">";}
316 std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
318 ts.emplace_back(
CASE(
"interface/GeometryIterator/testLinearGetValuesConstructor")
319 { testLinearGetValuesConstructor<MODEL, OBS>(); });
320 ts.emplace_back(
CASE(
"interface/GeometryIterator/testLinearGetValuesZeroPert")
321 { testLinearGetValuesZeroPert<MODEL, OBS>(); });
322 ts.emplace_back(
CASE(
"interface/GeometryIterator/testLinearGetValuesLinearity")
323 { testLinearGetValuesLinearity<MODEL, OBS>(); });
324 ts.emplace_back(
CASE(
"interface/GeometryIterator/testLinearGetValuesLinearApproximation")
325 { testLinearGetValuesLinearApproximation<MODEL, OBS>(); });
326 ts.emplace_back(
CASE(
"interface/GeometryIterator/testLinearGetValuesAdjoint")
327 { testLinearGetValuesAdjoint<MODEL, OBS>(); });
337 #endif // TEST_INTERFACE_LINEARGETVALUES_H_