11 #ifndef TEST_INTERFACE_LINEARVARIABLECHANGE_H_
12 #define TEST_INTERFACE_LINEARVARIABLECHANGE_H_
20 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
22 #include <boost/noncopyable.hpp>
24 #include "eckit/config/Configuration.h"
25 #include "eckit/testing/Test.h"
34 #include "oops/util/DateTime.h"
35 #include "oops/util/dot_product.h"
36 #include "oops/util/Expect.h"
37 #include "oops/util/Logger.h"
58 return theLinearVariableChangeFixture;
62 oops::instantiateVariableChangeFactory<MODEL>();
70 time_.reset(
new util::DateTime(
xx_->validTime()));
75 ~LinearVariableChangeFixture<MODEL>() {}
77 std::vector<eckit::LocalConfiguration>
confs_;
78 std::unique_ptr<const State_ >
xx_;
79 std::unique_ptr<const Geometry_>
resol_;
80 std::unique_ptr<const util::DateTime>
time_;
91 for (std::size_t jj = 0; jj < Test_::confs().size(); ++jj) {
95 std::unique_ptr<LinearVariableChange_> changevar(LinearVariableChangeFactory_::create(
96 Test_::xx(), Test_::xx(),
97 Test_::resol(), Test_::confs()[jj]));
99 Increment_ dxinTlIAd(Test_::resol(), varin, Test_::time());
100 Increment_ dxinAdInv(Test_::resol(), varout, Test_::time());
101 Increment_ dxoutTlIAd(Test_::resol(), varout, Test_::time());
102 Increment_ dxoutAdInv(Test_::resol(), varin, Test_::time());
106 dxoutTlIAd = changevar->multiply(dxinTlIAd);
107 EXPECT(dxoutTlIAd.norm() == 0.0);
111 dxoutAdInv = changevar->multiplyAD(dxinAdInv);
112 EXPECT(dxoutAdInv.norm() == 0.0);
114 const bool testinverse = Test_::confs()[jj].getBool(
"test inverse",
true);
117 oops::Log::info() <<
"Doing zero test for inverse" << std::endl;
119 dxoutTlIAd = changevar->multiplyInverseAD(dxinTlIAd);
120 EXPECT(dxoutTlIAd.norm() == 0.0);
123 dxoutAdInv = changevar->multiplyInverse(dxinAdInv);
124 EXPECT(dxoutAdInv.norm() == 0.0);
126 oops::Log::info() <<
"Not doing zero test for inverse" << std::endl;
138 for (std::size_t jj = 0; jj < Test_::confs().size(); ++jj) {
142 std::unique_ptr<LinearVariableChange_> changevar(LinearVariableChangeFactory_::create(
143 Test_::xx(), Test_::xx(),
144 Test_::resol(), Test_::confs()[jj]));
146 Increment_ dxinAdInv(Test_::resol(), varout, Test_::time());
147 Increment_ dxinTlIAd(Test_::resol(), varin, Test_::time());
148 Increment_ dxoutAdInv(Test_::resol(), varin, Test_::time());
149 Increment_ dxoutTlIAd(Test_::resol(), varout, Test_::time());
154 Increment_ dxinAdInv0(dxinAdInv);
155 Increment_ dxinTlIAd0(dxinTlIAd);
157 dxoutTlIAd = changevar->multiply(dxinTlIAd);
158 dxoutAdInv = changevar->multiplyAD(dxinAdInv);
161 double zz1 = dot_product(dxoutTlIAd, dxinAdInv0);
163 double zz2 = dot_product(dxinTlIAd0, dxoutAdInv);
165 oops::Log::info() <<
"<dxout,KTdxin>-<Kdxout,dxin>/<dxout,KTdxin>="
166 << (zz1-zz2)/zz1 << std::endl;
167 oops::Log::info() <<
"<dxout,KTdxin>-<Kdxout,dxin>/<Kdxout,dxin>="
168 << (zz1-zz2)/zz2 << std::endl;
169 const double tol = 1e-10;
170 EXPECT(oops::is_close(zz1, zz2, tol));
171 const bool testinverse = Test_::confs()[jj].getBool(
"test inverse",
true);
174 oops::Log::info() <<
"Doing adjoint test for inverse" << std::endl;
179 dxinAdInv0 = dxinAdInv;
180 dxinTlIAd0 = dxinTlIAd;
181 dxoutTlIAd = changevar->multiplyInverseAD(dxinTlIAd);
182 dxoutAdInv = changevar->multiplyInverse(dxinAdInv);
183 zz1 = dot_product(dxoutTlIAd, dxinAdInv0);
184 zz2 = dot_product(dxinTlIAd0, dxoutAdInv);
185 oops::Log::info() <<
"<dxout,KinvTdxin>-<Kinvdxout,dxin>/<dxout,KinvTdxin>="
186 << (zz1-zz2)/zz1 << std::endl;
187 oops::Log::info() <<
"<dxout,KinvTdxin>-<Kinvdxout,dxin>/<Kinvdxout,dxin>="
188 << (zz1-zz2)/zz2 << std::endl;
189 EXPECT(oops::is_close(zz1, zz2, tol));
191 oops::Log::info() <<
"Not doing adjoint test for inverse" << std::endl;
204 for (std::size_t jj = 0; jj < Test_::confs().size(); ++jj) {
208 const double tol = Test_::confs()[jj].getDouble(
"tolerance inverse");
210 const bool testinverse = Test_::confs()[jj].getBool(
"test inverse",
false);
213 oops::Log::info() <<
"Testing multiplyInverse" << std::endl;
214 std::unique_ptr<LinearVariableChange_> changevar(LinearVariableChangeFactory_::create(
215 Test_::xx(), Test_::xx(),
216 Test_::resol(), Test_::confs()[jj]));
218 Increment_ dxinInv(Test_::resol(), varout, Test_::time());
219 Increment_ dxoutInv(Test_::resol(), varin, Test_::time());
220 Increment_ dxout(Test_::resol(), varout, Test_::time());
224 dxoutInv = changevar->multiplyInverse(dxinInv);
225 dxout = changevar->multiply(dxoutInv);
227 const double zz1 = dxinInv.norm();
228 const double zz2 = dxout.norm();
230 oops::Log::info() <<
"<x>, <KK^{-1}x>=" << zz1 <<
" " << zz2 << std::endl;
231 oops::Log::info() <<
"<x>-<KK^{-1}x>=" << zz1-zz2 << std::endl;
233 EXPECT((zz1-zz2) < tol);
235 oops::Log::info() <<
"multiplyInverse test not executed" << std::endl;
245 for (
const eckit::Configuration &config : Test_::confs()) {
247 EXPECT_NO_THROW(parameters.validateAndDeserialize(config));
254 eckit::LocalConfiguration config;
255 config.set(
"variable change",
"###INVALID###");
257 if (oops::Parameters::isValidationSupported())
258 EXPECT_THROWS_MSG(parameters.validate(config),
"unrecognized enum value");
259 EXPECT_THROWS_MSG(parameters.deserialize(config),
260 "does not exist in LinearVariableChangeFactory");
267 const std::vector<std::string> registeredNames =
269 for (
const eckit::Configuration &config : Test_::confs()) {
270 const std::string validName = config.getString(
"variable change");
271 const bool found = std::find(registeredNames.begin(), registeredNames.end(), validName) !=
272 registeredNames.end();
279 template <
typename MODEL>
286 std::string
testid()
const override {
return "test::LinearVariableChange<" + MODEL::name() +
">";}
289 std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
291 ts.emplace_back(
CASE(
"interface/LinearVariableChange/testLinearVariableChangeZero")
292 { testLinearVariableChangeZero<MODEL>(); });
293 ts.emplace_back(
CASE(
"interface/LinearVariableChange/testLinearVariableChangeAdjoint")
294 { testLinearVariableChangeAdjoint<MODEL>(); });
295 ts.emplace_back(
CASE(
"interface/LinearVariableChange/testLinearVariableChangeInverse")
296 { testLinearVariableChangeInverse<MODEL>(); });
297 ts.emplace_back(
CASE(
"interface/LinearVariableChange/"
298 "testLinearVariableChangeParametersWrapperValidName")
299 { testLinearVariableChangeParametersWrapperValidName<MODEL>(); });
300 ts.emplace_back(
CASE(
"interface/LinearVariableChange/"
301 "testLinearVariableChangeParametersWrapperInvalidName")
302 { testLinearVariableChangeParametersWrapperInvalidName<MODEL>(); });
303 ts.emplace_back(
CASE(
"interface/LinearVariableChange/"
304 "testLinearVariableChangeFactoryGetMakerNames")
305 { testLinearVariableChangeFactoryGetMakerNames<MODEL>(); });
315 #endif // TEST_INTERFACE_LINEARVARIABLECHANGE_H_