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"
47 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
48 const eckit::LocalConfiguration & conf = Test_::config(jj);
50 std::string confname =
"obs operator";
51 if (conf.has(
"linear obs operator")) confname =
"linear obs operator";
52 eckit::LocalConfiguration linobsopconf(conf, confname);
55 std::unique_ptr<LinearObsOperator_> linobsop(
56 new LinearObsOperator_(Test_::obspace()[jj], linobsopconf));
57 EXPECT(linobsop.get());
58 oops::Log::test() <<
"Testing LinearObsOperator: " << *linobsop << std::endl;
60 EXPECT(!linobsop.get());
64 EXPECT_THROWS_MSG(LinearObsOperator_(Test_::obspace()[jj], linobsopconf),
65 expectedMessage.c_str());
82 const double zero = 0.0;
83 const double coef = 3.14;
84 const double tol = 1.0e-11;
86 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
87 const eckit::LocalConfiguration & conf = Test_::config(jj);
96 eckit::LocalConfiguration obsopconf(conf,
"obs operator");
97 ObsOperator_ hop(Test_::obspace()[jj], obsopconf);
101 std::string confname =
"obs operator";
102 if (conf.has(
"linear obs operator")) confname =
"linear obs operator";
103 eckit::LocalConfiguration linobsopconf(conf, confname);
104 LinearObsOperator_ hoptl(Test_::obspace()[jj], linobsopconf);
107 eckit::LocalConfiguration biasconf = conf.getSubConfiguration(
"obs bias");
108 typename ObsAuxCtrl_::Parameters_ biasparams;
109 biasparams.validateAndDeserialize(biasconf);
110 const ObsAuxCtrl_ ybias(Test_::obspace()[jj], biasparams);
111 ObsAuxIncr_ ybinc(Test_::obspace()[jj], biasparams);
114 const eckit::LocalConfiguration gconf(conf,
"geovals");
116 hopvars += ybias.requiredVars();
117 const GeoVaLs_ gval(gconf, Test_::obspace()[jj], hopvars);
120 const ObsAuxCov_ Bobsbias(Test_::obspace()[jj], biasparams);
123 hoptl.setTrajectory(gval, ybias);
126 ObsVector_ dy1(Test_::obspace()[jj]);
129 GeoVaLs_ dx(gconf, Test_::obspace()[jj], hoptl.requiredVars());
134 hoptl.simulateObsTL(dx, dy1, ybinc);
135 EXPECT(dy1.rms() == zero);
139 Bobsbias.randomize(ybinc);
140 hoptl.simulateObsTL(dx, dy1, ybinc);
141 EXPECT(dy1.rms() > zero);
147 ObsVector_ dy2(Test_::obspace()[jj]);
148 hoptl.simulateObsTL(dx, dy2, ybinc);
151 EXPECT(dy2.rms() / dy1.rms() < tol);
167 const double zero = 0.0;
169 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
170 const eckit::LocalConfiguration & conf = Test_::config(jj);
180 eckit::LocalConfiguration obsopconf(conf,
"obs operator");
181 ObsOperator_ hop(Test_::obspace()[jj], obsopconf);
185 std::string confname =
"obs operator";
186 if (conf.has(
"linear obs operator")) confname =
"linear obs operator";
187 eckit::LocalConfiguration linobsopconf(conf, confname);
188 LinearObsOperator_ hoptl(Test_::obspace()[jj], linobsopconf);
190 const double tol = conf.getDouble(
"linear obs operator test.tolerance AD");
192 eckit::LocalConfiguration biasconf = conf.getSubConfiguration(
"obs bias");
193 typename ObsAuxCtrl_::Parameters_ biasparams;
194 biasparams.validateAndDeserialize(biasconf);
195 const ObsAuxCtrl_ ybias(Test_::obspace()[jj], biasparams);
196 ObsAuxIncr_ ybinc1(Test_::obspace()[jj], biasparams);
197 ObsAuxIncr_ ybinc2(Test_::obspace()[jj], biasparams);
200 const ObsAuxCov_ Bobsbias(Test_::obspace()[jj], biasparams);
203 eckit::LocalConfiguration gconf(conf,
"geovals");
205 hopvars += ybias.requiredVars();
206 const GeoVaLs_ gval(gconf, Test_::obspace()[jj], hopvars);
209 hoptl.setTrajectory(gval, ybias);
211 ObsVector_ dy1(Test_::obspace()[jj]);
212 ObsVector_ dy2(Test_::obspace()[jj]);
213 GeoVaLs_ dx1(gconf, Test_::obspace()[jj], hoptl.requiredVars());
214 GeoVaLs_ dx2(gconf, Test_::obspace()[jj], hoptl.requiredVars());
218 EXPECT(dot_product(dx1, dx1) > zero);
219 Bobsbias.randomize(ybinc1);
220 hoptl.simulateObsTL(dx1, dy1, ybinc1);
221 EXPECT(dot_product(dy1, dy1) > zero);
225 EXPECT(dot_product(dy2, dy2) > zero);
228 hoptl.simulateObsAD(dx2, dy2, ybinc2);
229 EXPECT(dot_product(dx2, dx2) > zero);
231 const double zz1 = dot_product(dx1, dx2) + dot_product(ybinc1, ybinc2);
232 const double zz2 = dot_product(dy1, dy2);
235 << (zz1-zz2)/zz2 << std::endl;
239 EXPECT(oops::is_close(zz1, zz2, tol));
257 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
258 const eckit::LocalConfiguration & conf = Test_::config(jj);
267 eckit::LocalConfiguration obsopconf(conf,
"obs operator");
268 ObsOperator_ hop(Test_::obspace()[jj], obsopconf);
272 std::string confname =
"obs operator";
273 if (conf.has(
"linear obs operator")) confname =
"linear obs operator";
274 eckit::LocalConfiguration linobsopconf(conf, confname);
275 LinearObsOperator_ hoptl(Test_::obspace()[jj], linobsopconf);
277 const double tol = conf.getDouble(
"linear obs operator test.tolerance TL");
278 const double alpha = conf.getDouble(
"linear obs operator test.coef TL", 0.1);
279 const int iter = conf.getInt(
"linear obs operator test.iterations TL", 1);
282 eckit::LocalConfiguration biasconf = conf.getSubConfiguration(
"obs bias");
283 typename ObsAuxCtrl_::Parameters_ biasparams;
284 biasparams.validateAndDeserialize(biasconf);
285 const ObsAuxCtrl_ ybias0(Test_::obspace()[jj], biasparams);
286 ObsAuxCtrl_ ybias(Test_::obspace()[jj], biasparams);
289 const ObsAuxCov_ Bobsbias(Test_::obspace()[jj], biasparams);
292 const eckit::LocalConfiguration gconf(conf,
"geovals");
294 hopvars += ybias0.requiredVars();
295 const GeoVaLs_ x0(gconf, Test_::obspace()[jj], hopvars);
296 GeoVaLs_ x(gconf, Test_::obspace()[jj], hopvars);
299 hoptl.setTrajectory(x0, ybias0);
302 ObsVector_ y1(Test_::obspace()[jj]);
303 ObsVector_ y2(Test_::obspace()[jj]);
304 ObsVector_ y3(Test_::obspace()[jj]);
308 diagvars += ybias0.requiredHdiagnostics();
309 ObsDiags_ ydiag(Test_::obspace()[jj], hop.locations(), diagvars);
312 hop.simulateObs(x0, y1, ybias0, ydiag);
315 GeoVaLs_ dx(gconf, Test_::obspace()[jj], hoptl.requiredVars());
317 ObsAuxIncr_ ybinc(Test_::obspace()[jj], biasparams);
318 Bobsbias.randomize(ybinc);
323 for (
int jter = 0; jter < iter; ++jter) {
334 hop.simulateObs(x, y2, ybias, ydiag);
337 hoptl.simulateObsTL(dx, y3, ybinc);
340 double test_norm = y2.rms();
341 oops::Log::test() <<
"Iter:" << jter <<
" ||(h(x+alpha*dx)-h(x)-h'*(alpha*dx))||="
342 << test_norm << std::endl;
344 EXPECT(y2.rms() < tol);
360 for (std::size_t jj = 0; jj < Test_::obspace().size(); ++jj) {
361 const eckit::LocalConfiguration & conf = Test_::config(jj);
366 eckit::LocalConfiguration obsopconf(conf,
"obs operator");
367 ObsOperator_ hop(Test_::obspace()[jj], obsopconf);
368 std::string confname =
"obs operator";
369 if (conf.has(
"linear obs operator")) confname =
"linear obs operator";
370 eckit::LocalConfiguration linobsopconf(conf, confname);
371 LinearObsOperator_ hoptl(Test_::obspace()[jj], linobsopconf);
372 eckit::LocalConfiguration biasconf = conf.getSubConfiguration(
"obs bias");
373 typename ObsAuxCtrl_::Parameters_ biasparams;
374 biasparams.validateAndDeserialize(biasconf);
375 const ObsAuxCtrl_ ybias(Test_::obspace()[jj], biasparams);
376 ObsAuxIncr_ ybinc(Test_::obspace()[jj], biasparams);
377 const ObsAuxCov_ Bobsbias(Test_::obspace()[jj], biasparams);
378 eckit::LocalConfiguration gconf(conf,
"geovals");
380 hopvars += ybias.requiredVars();
381 const GeoVaLs_ gval(gconf, Test_::obspace()[jj], hopvars);
383 diagvars += ybias.requiredHdiagnostics();
388 const std::string expectedMessage =
390 EXPECT_THROWS_MSG(hoptl.setTrajectory(gval, ybias),
391 expectedMessage.c_str());
398 hoptl.setTrajectory(gval, ybias);
399 ObsVector_ dy1(Test_::obspace()[jj]);
400 GeoVaLs_ dx1(gconf, Test_::obspace()[jj], hoptl.requiredVars());
402 Bobsbias.randomize(ybinc);
405 const std::string expectedMessage =
407 EXPECT_THROWS_MSG(hoptl.simulateObsTL(dx1, dy1, ybinc),
408 expectedMessage.c_str());
412 hoptl.setTrajectory(gval, ybias);
413 ObsVector_ dy2(Test_::obspace()[jj]);
414 GeoVaLs_ dx2(gconf, Test_::obspace()[jj], hoptl.requiredVars());
415 Bobsbias.randomize(ybinc);
421 const std::string expectedMessage =
423 EXPECT_THROWS_MSG(hoptl.simulateObsAD(dx2, dy2, ybinc),
424 expectedMessage.c_str());
431 template <
typename OBS>
440 std::string
testid()
const override {
return "test::LinearObsOperator<" +
OBS::name() +
">";}
443 std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
445 ts.emplace_back(
CASE(
"interface/LinearObsOperator/testConstructor")
446 { testConstructor<OBS>(); });
447 ts.emplace_back(
CASE(
"interface/LinearObsOperator/testLinearity")
448 { testLinearity<OBS>(); });
449 ts.emplace_back(
CASE(
"interface/LinearObsOperator/testTangentLinear")
450 { testTangentLinear<OBS>(); });
451 ts.emplace_back(
CASE(
"interface/LinearObsOperator/testAdjoint")
452 { testAdjoint<OBS>(); });
453 ts.emplace_back(
CASE(
"interface/LinearObsOperator/testException")
454 { testException<OBS>(); });
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("assimilation/FullGMRES/FullGMRES")
void testConstructor()
Tests creation and destruction of ObsErrorCovariances.