8 #ifndef TEST_INTERFACE_LINEAROBSOPERATOR_H_
9 #define TEST_INTERFACE_LINEAROBSOPERATOR_H_
15 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
18 #include "eckit/testing/Test.h"
27 #include "oops/util/dot_product.h"
28 #include "oops/util/Expect.h"
29 #include "oops/util/Logger.h"
46 typedef typename LinearObsOperator_::Parameters_ LinearObsOperatorParameters_;
48 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
49 const eckit::LocalConfiguration & conf = Test_::config(jj);
51 std::string confname =
"obs operator";
52 if (conf.has(
"linear obs operator")) confname =
"linear obs operator";
53 eckit::LocalConfiguration linobsopconf(conf, confname);
54 LinearObsOperatorParameters_ linobsopparams;
55 linobsopparams.validateAndDeserialize(linobsopconf);
58 std::unique_ptr<LinearObsOperator_> linobsop(
59 new LinearObsOperator_(Test_::obspace()[jj], linobsopparams));
60 EXPECT(linobsop.get());
61 oops::Log::test() <<
"Testing LinearObsOperator: " << *linobsop << std::endl;
63 EXPECT(!linobsop.get());
67 EXPECT_THROWS_MSG(LinearObsOperator_(Test_::obspace()[jj], linobsopparams),
68 expectedMessage.c_str());
82 typedef typename ObsOperator_::Parameters_ ObsOperatorParameters_;
84 typedef typename LinearObsOperator_::Parameters_ LinearObsOperatorParameters_;
87 const double zero = 0.0;
88 const double coef = 3.14;
89 const double tol = 1.0e-11;
91 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
92 const eckit::LocalConfiguration & conf = Test_::config(jj);
101 eckit::LocalConfiguration obsopconf(conf,
"obs operator");
102 ObsOperatorParameters_ obsopparams;
103 obsopparams.validateAndDeserialize(obsopconf);
104 ObsOperator_ hop(Test_::obspace()[jj], obsopparams);
108 std::string confname =
"obs operator";
109 if (conf.has(
"linear obs operator")) confname =
"linear obs operator";
110 eckit::LocalConfiguration linobsopconf(conf, confname);
111 LinearObsOperatorParameters_ linobsopparams;
112 linobsopparams.validateAndDeserialize(linobsopconf);
113 LinearObsOperator_ hoptl(Test_::obspace()[jj], linobsopparams);
116 eckit::LocalConfiguration biasconf = conf.getSubConfiguration(
"obs bias");
117 typename ObsAuxCtrl_::Parameters_ biasparams;
118 biasparams.validateAndDeserialize(biasconf);
119 const ObsAuxCtrl_ ybias(Test_::obspace()[jj], biasparams);
120 ObsAuxIncr_ ybinc(Test_::obspace()[jj], biasparams);
123 const eckit::LocalConfiguration gconf(conf,
"geovals");
125 hopvars += ybias.requiredVars();
126 const GeoVaLs_ gval(gconf, Test_::obspace()[jj], hopvars);
129 const ObsAuxCov_ Bobsbias(Test_::obspace()[jj], biasparams);
132 hoptl.setTrajectory(gval, ybias);
135 ObsVector_ dy1(Test_::obspace()[jj]);
138 GeoVaLs_ dx(gconf, Test_::obspace()[jj], hoptl.requiredVars());
143 hoptl.simulateObsTL(dx, dy1, ybinc);
144 EXPECT(dy1.rms() == zero);
148 Bobsbias.randomize(ybinc);
149 hoptl.simulateObsTL(dx, dy1, ybinc);
150 EXPECT(dy1.rms() > zero);
156 ObsVector_ dy2(Test_::obspace()[jj]);
157 hoptl.simulateObsTL(dx, dy2, ybinc);
160 EXPECT(dy2.rms() / dy1.rms() < tol);
170 typedef typename ObsOperator_::Parameters_ ObsOperatorParameters_;
172 typedef typename LinearObsOperator_::Parameters_ LinearObsOperatorParameters_;
178 const double zero = 0.0;
180 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
181 const eckit::LocalConfiguration & conf = Test_::config(jj);
191 eckit::LocalConfiguration obsopconf(conf,
"obs operator");
192 ObsOperatorParameters_ obsopparams;
193 obsopparams.validateAndDeserialize(obsopconf);
194 ObsOperator_ hop(Test_::obspace()[jj], obsopparams);
198 std::string confname =
"obs operator";
199 if (conf.has(
"linear obs operator")) confname =
"linear obs operator";
200 eckit::LocalConfiguration linobsopconf(conf, confname);
201 LinearObsOperatorParameters_ linobsopparams;
202 linobsopparams.validateAndDeserialize(linobsopconf);
203 LinearObsOperator_ hoptl(Test_::obspace()[jj], linobsopparams);
205 const double tol = conf.getDouble(
"linear obs operator test.tolerance AD");
207 eckit::LocalConfiguration biasconf = conf.getSubConfiguration(
"obs bias");
208 typename ObsAuxCtrl_::Parameters_ biasparams;
209 biasparams.validateAndDeserialize(biasconf);
210 const ObsAuxCtrl_ ybias(Test_::obspace()[jj], biasparams);
211 ObsAuxIncr_ ybinc1(Test_::obspace()[jj], biasparams);
212 ObsAuxIncr_ ybinc2(Test_::obspace()[jj], biasparams);
215 const ObsAuxCov_ Bobsbias(Test_::obspace()[jj], biasparams);
218 eckit::LocalConfiguration gconf(conf,
"geovals");
220 hopvars += ybias.requiredVars();
221 const GeoVaLs_ gval(gconf, Test_::obspace()[jj], hopvars);
224 hoptl.setTrajectory(gval, ybias);
226 ObsVector_ dy1(Test_::obspace()[jj]);
227 ObsVector_ dy2(Test_::obspace()[jj]);
228 GeoVaLs_ dx1(gconf, Test_::obspace()[jj], hoptl.requiredVars());
229 GeoVaLs_ dx2(gconf, Test_::obspace()[jj], hoptl.requiredVars());
233 EXPECT(dot_product(dx1, dx1) > zero);
234 Bobsbias.randomize(ybinc1);
235 hoptl.simulateObsTL(dx1, dy1, ybinc1);
236 EXPECT(dot_product(dy1, dy1) > zero);
240 EXPECT(dot_product(dy2, dy2) > zero);
243 hoptl.simulateObsAD(dx2, dy2, ybinc2);
244 EXPECT(dot_product(dx2, dx2) > zero);
246 const double zz1 = dot_product(dx1, dx2) + dot_product(ybinc1, ybinc2);
247 const double zz2 = dot_product(dy1, dy2);
249 oops::Log::test() <<
"Adjoint test result: (<x,HTy>-<Hx,y>)/<Hx,y> = "
250 << (zz1-zz2)/zz2 << std::endl;
254 EXPECT(oops::is_close(zz1, zz2, tol));
269 typedef typename ObsOperator_::Parameters_ ObsOperatorParameters_;
271 typedef typename LinearObsOperator_::Parameters_ LinearObsOperatorParameters_;
274 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
275 const eckit::LocalConfiguration & conf = Test_::config(jj);
284 eckit::LocalConfiguration obsopconf(conf,
"obs operator");
285 ObsOperatorParameters_ obsopparams;
286 obsopparams.validateAndDeserialize(obsopconf);
287 ObsOperator_ hop(Test_::obspace()[jj], obsopparams);
291 std::string confname =
"obs operator";
292 if (conf.has(
"linear obs operator")) confname =
"linear obs operator";
293 eckit::LocalConfiguration linobsopconf(conf, confname);
294 LinearObsOperatorParameters_ linobsopparams;
295 linobsopparams.validateAndDeserialize(linobsopconf);
296 LinearObsOperator_ hoptl(Test_::obspace()[jj], linobsopparams);
298 const double tol = conf.getDouble(
"linear obs operator test.tolerance TL");
299 const double alpha = conf.getDouble(
"linear obs operator test.coef TL", 0.1);
300 const int iter = conf.getInt(
"linear obs operator test.iterations TL", 1);
303 eckit::LocalConfiguration biasconf = conf.getSubConfiguration(
"obs bias");
304 typename ObsAuxCtrl_::Parameters_ biasparams;
305 biasparams.validateAndDeserialize(biasconf);
306 const ObsAuxCtrl_ ybias0(Test_::obspace()[jj], biasparams);
307 ObsAuxCtrl_ ybias(Test_::obspace()[jj], biasparams);
310 const ObsAuxCov_ Bobsbias(Test_::obspace()[jj], biasparams);
313 const eckit::LocalConfiguration gconf(conf,
"geovals");
315 hopvars += ybias0.requiredVars();
316 const GeoVaLs_ x0(gconf, Test_::obspace()[jj], hopvars);
317 GeoVaLs_ x(gconf, Test_::obspace()[jj], hopvars);
320 hoptl.setTrajectory(x0, ybias0);
323 ObsVector_ y1(Test_::obspace()[jj]);
324 ObsVector_ y2(Test_::obspace()[jj]);
325 ObsVector_ y3(Test_::obspace()[jj]);
326 ObsVector_ bias(Test_::obspace()[jj]);
331 diagvars += ybias0.requiredHdiagnostics();
332 ObsDiags_ ydiag(Test_::obspace()[jj], hop.locations(), diagvars);
335 hop.simulateObs(x0, y1, ybias0, bias, ydiag);
338 GeoVaLs_ dx(gconf, Test_::obspace()[jj], hoptl.requiredVars());
340 ObsAuxIncr_ ybinc(Test_::obspace()[jj], biasparams);
341 Bobsbias.randomize(ybinc);
346 for (
int jter = 0; jter < iter; ++jter) {
358 hop.simulateObs(x, y2, ybias, bias, ydiag);
361 hoptl.simulateObsTL(dx, y3, ybinc);
364 double test_norm = y2.rms();
365 oops::Log::test() <<
"Iter:" << jter <<
" ||(h(x+alpha*dx)-h(x)-h'*(alpha*dx))||="
366 << test_norm << std::endl;
368 EXPECT(y2.rms() < tol);
378 typedef typename ObsOperator_::Parameters_ ObsOperatorParameters_;
380 typedef typename LinearObsOperator_::Parameters_ LinearObsOperatorParameters_;
386 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
387 const eckit::LocalConfiguration & conf = Test_::config(jj);
392 eckit::LocalConfiguration obsopconf(conf,
"obs operator");
393 ObsOperatorParameters_ obsopparams;
394 obsopparams.validateAndDeserialize(obsopconf);
395 ObsOperator_ hop(Test_::obspace()[jj], obsopparams);
396 std::string confname =
"obs operator";
397 if (conf.has(
"linear obs operator")) confname =
"linear obs operator";
398 eckit::LocalConfiguration linobsopconf(conf, confname);
399 LinearObsOperatorParameters_ linobsopparams;
400 linobsopparams.validateAndDeserialize(linobsopconf);
401 LinearObsOperator_ hoptl(Test_::obspace()[jj], linobsopparams);
402 eckit::LocalConfiguration biasconf = conf.getSubConfiguration(
"obs bias");
403 typename ObsAuxCtrl_::Parameters_ biasparams;
404 biasparams.validateAndDeserialize(biasconf);
405 const ObsAuxCtrl_ ybias(Test_::obspace()[jj], biasparams);
406 ObsAuxIncr_ ybinc(Test_::obspace()[jj], biasparams);
407 const ObsAuxCov_ Bobsbias(Test_::obspace()[jj], biasparams);
408 eckit::LocalConfiguration gconf(conf,
"geovals");
410 hopvars += ybias.requiredVars();
411 const GeoVaLs_ gval(gconf, Test_::obspace()[jj], hopvars);
413 diagvars += ybias.requiredHdiagnostics();
418 const std::string expectedMessage =
420 EXPECT_THROWS_MSG(hoptl.setTrajectory(gval, ybias),
421 expectedMessage.c_str());
428 hoptl.setTrajectory(gval, ybias);
429 ObsVector_ dy1(Test_::obspace()[jj]);
430 GeoVaLs_ dx1(gconf, Test_::obspace()[jj], hoptl.requiredVars());
432 Bobsbias.randomize(ybinc);
435 const std::string expectedMessage =
437 EXPECT_THROWS_MSG(hoptl.simulateObsTL(dx1, dy1, ybinc),
438 expectedMessage.c_str());
442 hoptl.setTrajectory(gval, ybias);
443 ObsVector_ dy2(Test_::obspace()[jj]);
444 GeoVaLs_ dx2(gconf, Test_::obspace()[jj], hoptl.requiredVars());
445 Bobsbias.randomize(ybinc);
451 const std::string expectedMessage =
453 EXPECT_THROWS_MSG(hoptl.simulateObsAD(dx2, dy2, ybinc),
454 expectedMessage.c_str());
461 template <
typename OBS>
470 std::string
testid()
const override {
return "test::LinearObsOperator<" + OBS::name() +
">";}
473 std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
475 ts.emplace_back(
CASE(
"interface/LinearObsOperator/testConstructor")
476 { testConstructor<OBS>(); });
477 ts.emplace_back(
CASE(
"interface/LinearObsOperator/testLinearity")
478 { testLinearity<OBS>(); });
479 ts.emplace_back(
CASE(
"interface/LinearObsOperator/testTangentLinear")
480 { testTangentLinear<OBS>(); });
481 ts.emplace_back(
CASE(
"interface/LinearObsOperator/testAdjoint")
482 { testAdjoint<OBS>(); });
483 ts.emplace_back(
CASE(
"interface/LinearObsOperator/testException")
484 { testException<OBS>(); });
MODEL-agnostic part of tangent-linear and adjoint of the nonlinear observation (forward) operator Obs...
Auxiliary state related to observations, templated on <OBS>
Auxiliary error covariance related to observations, templated on <OBS>
Auxiliary increment related to observations, templated on <OBS>
MODEL-agnostic part of nonlinear observation (forward) operator. The full nonlinear observation opera...
ObsVector class used in oops; subclass of interface class interface::ObsVector.
void clear() const override
virtual ~LinearObsOperator()
void register_tests() const override
std::string testid() const override
ObsTestsFixture< OBS > Test_
logical function has(this, var)
const char * expectConstructorToThrow
const char * expectSimulateObsTLToThrow
const char * expectSetTrajectoryToThrow
const char * expectSimulateObsToThrow
const char * expectSimulateObsADToThrow
CASE("test_linearmodelparameterswrapper_valid_name")
void testConstructor()
Tests creation and destruction of ObsErrorCovariances.