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::instantiateLinearModelFactory<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;
168 const util::DateTime vt(Test_::time());
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"));
201 const util::DateTime t1(Test_::time());
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"));
231 const util::DateTime t1(Test_::time());
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"));
266 const util::DateTime t1(Test_::time());
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");
284 if (Test_::test().
has(
"first multiplier 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);
305 oops::Log::test() <<
"TL error = " << std::setprecision(16) << err
306 <<
", relative error = " << errnorm / difnorm << std::endl;
311 const double approx = *std::min_element(errors.begin(), errors.end());
312 oops::Log::test() <<
"Test TL min error = " << approx << std::endl;
313 const double tol = Test_::test().getDouble(
"tolerance TL");
314 EXPECT(approx < tol);
324 const util::Duration len(Test_::test().getString(
"forecast length"));
325 const util::DateTime t1(Test_::time());
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>
365 std::string
testid()
const override {
return "test::LinearModel<" + MODEL::name() +
">";}
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.
Abstract linear forecast model used by high level algorithms and applications.
Auxiliary state related to model (could be e.g. model bias), not used at the moment.
Auxiliary Increment related to model, not used at the moment.
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("test_linearmodelparameterswrapper_valid_name")
void testLinearModelLinearity()