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_;
156 const util::Duration zero(0);
157 EXPECT(Test_::tlm().timeResolution() > zero);
158 oops::Log::test() <<
"Testing LinearModel: " << Test_::tlm() << std::endl;
169 const util::Duration zero(0);
171 Increment_ dxref(Test_::resol(), Test_::ctlvars(), vt);
172 Test_::covariance().randomize(dxref);
173 ModelAuxIncr_ daux(Test_::dbias());
174 const double ininorm = dxref.norm();
175 EXPECT(ininorm > 0.0);
177 Increment_ dx(Test_::resol(), Test_::ctlvars(), vt);
178 Increment_ dxm(Test_::resol(), Test_::tlm().variables(), vt);
180 Test_::tlm().forecastTL(dxm, daux, zero);
182 EXPECT(dx.validTime() == vt);
183 EXPECT(dx.norm() == ininorm);
187 Test_::tlm().forecastAD(dxm, daux, zero);
189 EXPECT(dx.validTime() == vt);
190 EXPECT(dx.norm() == ininorm);
200 const util::Duration len(
Test_::test().getString(
"forecast length"));
202 const util::DateTime t2(t1 + len);
205 Increment_ dx(Test_::resol(), Test_::tlm().variables(), t1);
206 ModelAuxIncr_ daux(Test_::dbias());
210 EXPECT(dx.norm() == 0.0);
211 Test_::tlm().forecastTL(dx, daux, len);
212 EXPECT(dx.validTime() == t2);
213 EXPECT(dx.norm() == 0.0);
217 EXPECT(dx.norm() == 0.0);
218 Test_::tlm().forecastAD(dx, daux, len);
219 EXPECT(dx.validTime() == t1);
220 EXPECT(dx.norm() == 0.0);
230 const util::Duration len(
Test_::test().getString(
"forecast length"));
232 const util::DateTime t2(t1 + len);
234 const double zz = 3.1415;
236 Increment_ dx1(Test_::resol(), Test_::tlm().variables(), t1);
237 Test_::covariance().randomize(dx1);
238 ModelAuxIncr_ daux1(Test_::dbias());
239 EXPECT(dx1.norm() > 0.0);
242 ModelAuxIncr_ daux2(daux1);
244 Test_::tlm().forecastTL(dx1, daux1, len);
245 EXPECT(dx1.validTime() == t2);
251 Test_::tlm().forecastTL(dx2, daux2, len);
252 EXPECT(dx2.validTime() == t2);
254 const double tol =
Test_::test().getDouble(
"tolerance AD");
255 EXPECT(oops::is_close(dx1.norm(), dx2.norm(), tol));
265 const util::Duration len(
Test_::test().getString(
"forecast length"));
267 const util::DateTime t2(t1 + len);
270 Increment_ dx0(Test_::resol(), Test_::tlm().variables(), t1);
271 Test_::covariance().randomize(dx0);
272 EXPECT(dx0.norm() > 0.0);
275 Test_::tlm().forecastTL(dx, Test_::dbias(), len);
276 const double dxnorm = dx.norm();
279 State_ xx0(Test_::xref());
280 Test_::model().forecast(xx0, Test_::bias(), len, post);
282 const unsigned int ntest =
Test_::test().getInt(
"iterations TL");
285 zz =
Test_::test().getDouble(
"first multiplier TL");
288 std::vector<double> errors;
289 for (
unsigned int jtest = 0; jtest < ntest; ++jtest) {
290 State_ xx(Test_::xref());
291 Increment_ pert(dx0);
294 Test_::model().forecast(xx, Test_::bias(), len, post);
296 Increment_ diff(Test_::resol(), Test_::tlm().variables(), t2);
298 const double difnorm = diff.norm();
299 const double err = zz * dxnorm / difnorm;
303 const double errnorm = derr.norm();
304 errors.push_back(errnorm / difnorm);
306 <<
", relative error = " << errnorm / difnorm << std::endl;
311 const double approx = *std::min_element(errors.begin(), errors.end());
313 const double tol =
Test_::test().getDouble(
"tolerance TL");
314 EXPECT(approx < tol);
324 const util::Duration len(
Test_::test().getString(
"forecast length"));
326 const util::DateTime t2(t1 + len);
329 Increment_ dx11(Test_::resol(), Test_::tlm().variables(), t1);
330 Test_::covariance().randomize(dx11);
331 ModelAuxIncr_ daux1(Test_::dbias());
332 EXPECT(dx11.norm() > 0.0);
333 Increment_ dx12(dx11);
334 Test_::tlm().forecastTL(dx12, daux1, len);
335 EXPECT(dx12.norm() > 0.0);
336 Increment_ dx22(Test_::resol(), Test_::tlm().variables(), t2);
337 Test_::covariance().randomize(dx22);
338 ModelAuxIncr_ daux2(Test_::dbias());
339 EXPECT(dx22.norm() > 0.0);
340 Increment_ dx21(dx22);
341 Test_::tlm().forecastAD(dx21, daux2, len);
342 EXPECT(dx21.norm() > 0.0);
344 EXPECT(dx11.norm() != dx22.norm());
345 EXPECT(dx11.validTime() == t1);
346 EXPECT(dx21.validTime() == t1);
347 EXPECT(dx12.validTime() == t2);
348 EXPECT(dx22.validTime() == t2);
350 const double dot1 = dot_product(dx11, dx21);
351 const double dot2 = dot_product(dx12, dx22);
352 const double tol =
Test_::test().getDouble(
"tolerance AD");
353 EXPECT(oops::is_close(dot1, dot2, tol));
358 template <
typename MODEL>
368 std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
370 ts.emplace_back(
CASE(
"interface/LinearModel/testLinearModelConstructor")
371 { testLinearModelConstructor<MODEL>(); });
372 ts.emplace_back(
CASE(
"interface/LinearModel/testLinearModelZeroLength")
373 { testLinearModelZeroLength<MODEL>(); });
374 ts.emplace_back(
CASE(
"interface/LinearModel/testLinearModelZeroPert")
375 { testLinearModelZeroPert<MODEL>(); });
376 ts.emplace_back(
CASE(
"interface/LinearModel/testLinearModelLinearity")
377 { testLinearModelLinearity<MODEL>(); });
378 ts.emplace_back(
CASE(
"interface/LinearModel/testLinearApproximation")
379 { testLinearApproximation<MODEL>(); });
380 ts.emplace_back(
CASE(
"interface/LinearModel/testLinearModelAdjoint")
381 { testLinearModelAdjoint<MODEL>(); });
Geometry class used in oops; subclass of interface class interface::Geometry.
Increment class used in oops.
Encapsulates the linear forecast model.
Abstract nonlinear forecast model used by high level algorithms and applications.
Control model post processing.
void enrollProcessor(PostBase_ *pp)
Control model post processing.
State class used in oops; subclass of interface class interface::State.
Save trajectory during forecast run.
static const eckit::Configuration & test()
std::unique_ptr< const ModelAuxIncr_ > dbias_
std::unique_ptr< const ModelAux_ > bias_
oops::ModelSpaceCovarianceBase< MODEL > Covariance_
static const Covariance_ & covariance()
oops::ModelAuxControl< MODEL > ModelAux_
oops::Model< MODEL > Model_
std::unique_ptr< const util::DateTime > time_
oops::Geometry< MODEL > Geometry_
static const util::DateTime & time()
static const Model_ & model()
std::unique_ptr< const Covariance_ > B_
std::shared_ptr< LinearModel_ > tlm_
static LinearModelFixture< MODEL > & getInstance()
static const oops::Variables & ctlvars()
std::unique_ptr< const eckit::LocalConfiguration > test_
static const Geometry_ & resol()
oops::State< MODEL > State_
static const State_ & xref()
static const ModelAuxIncr_ & dbias()
std::unique_ptr< const State_ > xref_
std::unique_ptr< const eckit::LocalConfiguration > tlConf_
static const LinearModel_ & tlm()
std::unique_ptr< const oops::Variables > ctlvars_
oops::LinearModel< MODEL > LinearModel_
oops::ModelAuxIncrement< MODEL > ModelAuxIncr_
std::unique_ptr< const Model_ > model_
std::unique_ptr< const Geometry_ > resol_
static const ModelAux_ & bias()
oops::Increment< MODEL > Increment_
void clear() const override
void register_tests() const override
std::string testid() const override
static const eckit::Configuration & config()
const eckit::mpi::Comm & world()
Default communicator with all MPI tasks (ie MPI_COMM_WORLD)
logical function has(this, var)
void testLinearModelConstructor()
tests constructor, timeResolution() method and print method
void testLinearModelAdjoint()
void testLinearModelZeroLength()
void testLinearModelZeroPert()
void testLinearApproximation()
CASE("assimilation/FullGMRES/FullGMRES")
void testLinearModelLinearity()