8 #ifndef TEST_UFO_GEOVALS_H_
9 #define TEST_UFO_GEOVALS_H_
18 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
20 #include "eckit/config/LocalConfiguration.h"
21 #include "eckit/testing/Test.h"
22 #include "ioda/ObsSpace.h"
23 #include "oops/mpi/mpi.h"
24 #include "oops/runs/Test.h"
25 #include "oops/util/FloatCompare.h"
26 #include "oops/util/Logger.h"
27 #include "test/TestEnvironment.h"
28 #include "ufo/GeoVaLs.h"
29 #include "ufo/Locations.h"
38 const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
39 util::DateTime bgn(conf.getString(
"window begin"));
40 util::DateTime end(conf.getString(
"window end"));
42 std::vector<eckit::LocalConfiguration> confs;
43 conf.get(
"geovals test", confs);
44 for (
size_t jconf = 0; jconf < confs.size(); ++jconf) {
46 const eckit::LocalConfiguration obsconf(confs[jconf],
"obs space");
47 ioda::ObsTopLevelParameters obsparams;
48 obsparams.validateAndDeserialize(obsconf);
49 ioda::ObsSpace ospace(obsparams, oops::mpi::world(), bgn, end, oops::mpi::myself());
52 const eckit::LocalConfiguration gconf(confs[jconf],
"geovals");
53 const oops::Variables ingeovars(gconf,
"state variables");
54 const GeoVaLs gval(gconf, ospace, ingeovars);
56 const double tol = gconf.getDouble(
"tolerance");
60 "GeoVaLs default constructor - does not allocate fields" << std::endl;
61 GeoVaLs gv_temp(ospace.distribution(), ingeovars);
64 if (gconf.has(
"one location check")) {
65 oops::Log::trace() <<
"Check that GeoVaLs constructor for one location works" << std::endl;
66 const eckit::LocalConfiguration gconfone(gconf,
"one location check");
67 const std::string var = gconfone.getString(
"variable");
68 const std::vector<int> ind = gconfone.getIntVector(
"indices");
69 const std::vector<float> values = gconfone.getFloatVector(
"values");
70 const float oneloctol = gconfone.getFloat(
"tolerance");
73 oops::TestVerbosity verbosity = oops::TestVerbosity::LOG_SUCCESS_AND_FAILURE;
74 for (std::size_t i = 0; i < ind.size(); ++i) {
76 std::vector<float> gv_val(1);
77 gv_one.getAtLevel(gv_val, var, 0);
78 EXPECT(oops::is_close_absolute(gv_val[0], values[i], oneloctol, 0, verbosity));
81 oops::Log::trace() <<
"Test just the constructor for a one location GeoVaLs" << std::endl;
87 if (gconf.has(
"reorderzdir check")) {
88 const eckit::LocalConfiguration gconfchk(gconf,
"reorderzdir check");
89 const std::string flipto = gconfchk.getString(
"direction");
90 std::string flipback = (flipto ==
"bottom2top") ?
"top2bottom" :
"bottom2top";
91 std::size_t nobs = ospace.nlocs();
92 gv.reorderzdir(
"air_pressure_levels", flipto);
93 std::vector<float> gvar(nobs);
94 std::vector<float> gvarref(nobs);
96 for (
size_t i = 0; i < ingeovars.size(); ++i) {
97 size_t nlevs = gv.nlevs(ingeovars[i]);
99 for (
size_t k = 0; k < nlevs; ++k) {
100 size_t kk = nlevs - k - 1;
101 gv.getAtLevel(gvar, ingeovars[i], k);
102 gval.getAtLevel(gvarref, ingeovars[i], kk);
103 for (
size_t j = 0; j < nobs; ++j) {
104 gvar[j] = gvar[j] - gvarref[j];
105 sum += sum + gvar[j];
109 gv.reorderzdir(
"air_pressure_levels", flipback);
110 const double tol = gconfchk.getDouble(
"tolerance");
111 EXPECT(
abs(sum) < tol);
115 oops::Log::trace() <<
116 "GeoVaLs merge followed by a split gives back the original geovals" << std::endl;
118 double dp_gval = gval.dot_product_with(gval);
119 oops::Log::debug()<<
"initial gval dot product with itself " << dp_gval << std::endl;
122 gv.merge(gval, gval);
124 double dp_gv_merged = gv.dot_product_with(gv);
125 oops::Log::debug()<<
"gv dot product with itself after merge " << dp_gv_merged << std::endl;
126 EXPECT(
abs(dp_gv_merged - 2.0 * dp_gval)/dp_gv_merged < tol);
128 GeoVaLs gv1(ospace.distribution(), gv.getVars());
129 GeoVaLs gv2(ospace.distribution(), gv.getVars());
132 double dp_gv1_split = gv1.dot_product_with(gv1);
133 double dp_gv2_split = gv2.dot_product_with(gv2);
136 << dp_gv1_split <<
" " << dp_gv2_split << std::endl;
138 EXPECT(gv1.rms() == gv2.rms());
139 EXPECT(gv1.rms() == gval.rms());
140 EXPECT(
abs(dp_gv1_split - dp_gv2_split)/dp_gv1_split < tol);
141 EXPECT(
abs(dp_gv1_split - dp_gval)/dp_gv1_split < tol);
143 oops::Log::trace() <<
144 "GeoVaLs merge followed by a split test succeeded" << std::endl;
147 oops::Log::trace() <<
148 "Check that GeoVaLs & operator *= (const std::vector<float>);" << std::endl;
150 std::size_t
nlocs = ospace.nlocs();
152 std::vector<float> tw(
nlocs, 1.0f);
154 EXPECT(gv1.rms() == gval.rms());
157 std::vector<float> tw(
nlocs, 2.0f);
161 rms2 = 2.0 * gval.rms();
163 EXPECT(rms1 == rms2);
165 oops::Log::trace() <<
166 "GeoVaLs & operator *= (const std::vector<float>); test succeeded" << std::endl;
174 const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
175 const eckit::LocalConfiguration testconf(conf,
"geovals get test");
178 const std::string var1 =
"variable1";
179 const std::string var2 =
"variable2";
180 const oops::Variables testvars({var1, var2});
183 const Locations locs(testconf, oops::mpi::world());
185 oops::Log::test() <<
"GeoVals allocate test: created empty GeoVaLs with " << testvars <<
186 " variables and nlocs=" << gval.nlocs() << std::endl;
187 EXPECT_EQUAL(gval.nlevs(var1), 0);
188 EXPECT_EQUAL(gval.nlevs(var2), 0);
191 const oops::Variables testvar1({var1});
192 const int nlevs1 = 10;
193 gval.allocate(nlevs1, testvar1);
194 oops::Log::test() <<
"Allocated " << var1 <<
"; nlevs(var1) = " << gval.nlevs(var1) <<
195 "; nlevs(var2) = " << gval.nlevs(var2) << std::endl;
196 EXPECT_EQUAL(gval.nlevs(var1), nlevs1);
197 EXPECT_EQUAL(gval.nlevs(var2), 0);
200 const oops::Variables testvar2({var2});
201 const int nlevs2 = 1;
202 gval.allocate(nlevs2, testvar2);
203 oops::Log::test() <<
"Allocated " << var2 <<
"; nlevs(var1) = " << gval.nlevs(var1) <<
204 "; nlevs(var2) = " << gval.nlevs(var2) << std::endl;
205 EXPECT_EQUAL(gval.nlevs(var1), nlevs1);
206 EXPECT_EQUAL(gval.nlevs(var2), nlevs2);
212 const double fillvalue_double = 3.01234567890123;
213 oops::Log::test() <<
"Put(double) fill value: " << fillvalue_double << std::endl;
214 const std::vector<double> refvalues_double(gval.nlocs(), fillvalue_double);
215 gval.putAtLevel(refvalues_double, var2, 0);
216 std::vector<double> testvalues_double(gval.nlocs(), 0);
217 gval.get(testvalues_double, var2);
218 oops::Log::test() <<
"Get(double) result: " << testvalues_double << std::endl;
219 EXPECT_EQUAL(testvalues_double, refvalues_double);
221 const float fillvalue_float = 4.1f;
222 oops::Log::test() <<
"Put(float) fill value: " << fillvalue_float << std::endl;
223 const std::vector<float> refvalues_float(gval.nlocs(), fillvalue_float);
224 gval.putAtLevel(refvalues_float, var2, 0);
225 std::vector<float> testvalues_float(gval.nlocs(), 0);
226 gval.get(testvalues_float, var2);
227 oops::Log::test() <<
"Get(float) result: " << testvalues_float << std::endl;
228 EXPECT_EQUAL(testvalues_float, refvalues_float);
230 const int fillvalue_int = 5;
231 oops::Log::test() <<
"Put(int) fill value: " << fillvalue_int << std::endl;
232 const std::vector<int> refvalues_int(gval.nlocs(), fillvalue_int);
233 gval.putAtLevel(refvalues_int, var2, 0);
234 std::vector<int> testvalues_int(gval.nlocs(), 0);
235 gval.get(testvalues_int, var2);
236 oops::Log::test() <<
"Get(int) result: " << testvalues_int << std::endl;
237 EXPECT_EQUAL(testvalues_int, refvalues_int);
241 for (
size_t jlev = 0; jlev < nlevs1; ++jlev) {
242 std::vector<double> refvalues_loc_double(gval.nlocs());
243 std::iota(refvalues_loc_double.begin(), refvalues_loc_double.end(), jlev);
244 gval.putAtLevel(refvalues_loc_double, var1, jlev);
246 for (
size_t jloc = 0; jloc < gval.nlocs(); ++jloc) {
248 std::vector<double> testvalues_loc_double(gval.nlevs(var1));
249 gval.getAtLocation(testvalues_loc_double, var1, jloc);
251 std::vector<double> refvalues_loc_double(gval.nlevs(var1));
252 std::iota(refvalues_loc_double.begin(), refvalues_loc_double.end(), jloc);
254 EXPECT_EQUAL(testvalues_loc_double, refvalues_loc_double);
256 std::vector<float> testvalues_loc_float(gval.nlevs(var1));
257 gval.getAtLocation(testvalues_loc_float, var1, jloc);
258 std::vector<float> refvalues_loc_float(refvalues_loc_double.begin(),
259 refvalues_loc_double.end());
260 EXPECT_EQUAL(testvalues_loc_float, refvalues_loc_float);
262 std::vector<int> testvalues_loc_int(gval.nlevs(var1));
263 gval.getAtLocation(testvalues_loc_int, var1, jloc);
264 std::vector<int> refvalues_loc_int(refvalues_loc_double.begin(),
265 refvalues_loc_double.end());
266 EXPECT_EQUAL(testvalues_loc_int, refvalues_loc_int);
275 oops::Log::test() <<
"putAtLoction with doubles" << std::endl;
276 for (
size_t jloc = 0; jloc < gval.nlocs(); ++jloc) {
277 std::vector<double> refvalues_double(gval.nlevs(var1));
278 std::iota(refvalues_double.begin(), refvalues_double.end(), jloc);
279 gval.putAtLocation(refvalues_double, var1, jloc);
281 oops::Log::test() <<
"testing putAtLoction with doubles" << std::endl;
282 for (
size_t jlev = 0; jlev < gval.nlevs(var1); ++jlev) {
284 std::vector <double> testvalues_double(gval.nlocs());
285 gval.getAtLevel(testvalues_double, var1, jlev);
287 std::vector <double> refvalues_double(gval.nlocs());
288 std::iota(refvalues_double.begin(), refvalues_double.end(), jlev);
290 EXPECT_EQUAL(testvalues_double, refvalues_double);
294 oops::Log::test() <<
"putAtLoction with floats" << std::endl;
295 for (
size_t jloc = 0; jloc < gval.nlocs(); ++jloc) {
296 std::vector<float> refvalues_float(gval.nlevs(var1));
297 std::iota(refvalues_float.begin(), refvalues_float.end(), jloc + 1);
298 gval.putAtLocation(refvalues_float, var1, jloc);
300 oops::Log::test() <<
"testing putAtLoction with floats" << std::endl;
301 for (
size_t jlev = 0; jlev < gval.nlevs(var1); ++jlev) {
303 std::vector <float> testvalues_float(gval.nlocs());
304 gval.getAtLevel(testvalues_float, var1, jlev);
306 std::vector <float> refvalues_float(gval.nlocs());
307 std::iota(refvalues_float.begin(), refvalues_float.end(), jlev + 1);
309 EXPECT_EQUAL(testvalues_float, refvalues_float);
313 oops::Log::test() <<
"putAtLoction with ints" << std::endl;
314 for (
size_t jloc = 0; jloc < gval.nlocs(); ++jloc) {
315 std::vector<int> refvalues_int(gval.nlevs(var1));
316 std::iota(refvalues_int.begin(), refvalues_int.end(), jloc + 2);
317 gval.putAtLocation(refvalues_int, var1, jloc);
319 oops::Log::test() <<
"testing putAtLoction with ints" << std::endl;
320 for (
size_t jlev = 0; jlev < gval.nlevs(var1); ++jlev) {
322 std::vector <int> testvalues_int(gval.nlocs());
323 gval.getAtLevel(testvalues_int, var1, jlev);
325 std::vector <int> refvalues_int(gval.nlocs());
326 std::iota(refvalues_int.begin(), refvalues_int.end(), jlev + 2);
328 EXPECT_EQUAL(testvalues_int, refvalues_int);
332 std::vector<double> testvalues_loc_wrongsize(gval.nlevs(var1) + 1, 0.0);
333 EXPECT_THROWS(gval.getAtLocation(testvalues_loc_wrongsize, var1, 1));
334 std::vector<double> testvalues_loc(gval.nlevs(var1), 0.0);
335 EXPECT_THROWS(gval.getAtLocation(testvalues_loc, var1, -1));
336 EXPECT_THROWS(gval.getAtLocation(testvalues_loc, var1, gval.nlocs()));
339 EXPECT_THROWS(gval.putAtLocation(testvalues_loc_wrongsize, var1, 1));
340 EXPECT_THROWS(gval.putAtLocation(testvalues_loc, var1, -1));
341 EXPECT_THROWS(gval.putAtLocation(testvalues_loc, var1, gval.nlocs()));
344 for (
size_t jlev = 0; jlev < nlevs1; ++jlev) {
345 const float fillvalue = 3.0*(jlev+1);
346 const std::vector<double> refvalues(gval.nlocs(), fillvalue);
347 gval.putAtLevel(refvalues, var1, jlev);
348 oops::Log::test() << jlev <<
" level: put fill value: " << fillvalue << std::endl;
349 std::vector<double> testvalues(gval.nlocs(), 0);
350 gval.getAtLevel(testvalues, var1, jlev);
351 oops::Log::test() << jlev <<
" level: get result: " << testvalues << std::endl;
352 EXPECT_EQUAL(testvalues, refvalues);
360 const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
361 const eckit::LocalConfiguration testconf(conf,
"geovals get test");
363 const std::string var1 =
"variable1";
364 const std::string var2 =
"variable2";
365 const oops::Variables testvars({var1, var2});
368 const Locations locs(testconf, oops::mpi::world());
369 const std::vector<size_t> testnlevs({10, 1});
370 GeoVaLs gval(locs, testvars, testnlevs);
371 oops::Log::test() <<
"Created and allocated GeoVaLs: " << var1 <<
"; nlevs(var1) = " <<
372 gval.nlevs(var1) <<
", " << var2 <<
"; nlevs(var2) = " <<
373 gval.nlevs(var2) << std::endl;
374 EXPECT_EQUAL(gval.nlevs(var1), 10);
375 EXPECT_EQUAL(gval.nlevs(var2), 1);
377 const std::vector<double> refvalues(gval.nlocs(), 0.0);
378 const std::vector<float> refvalues_float(gval.nlocs(), 0.0);
379 const std::vector<int> refvalues_int(gval.nlocs(), 0);
382 std::vector<double> testvalues(gval.nlocs(), 1.0);
383 gval.get(testvalues, var2);
384 oops::Log::test() <<
"Get result: " << testvalues << std::endl;
385 EXPECT_EQUAL(testvalues, refvalues);
386 std::vector<float> testvalues_float(gval.nlocs(), 1.0);
387 gval.get(testvalues_float, var2);
388 oops::Log::test() <<
"Get(float) result: " << testvalues_float << std::endl;
389 EXPECT_EQUAL(testvalues_float, refvalues_float);
390 std::vector<int> testvalues_int(gval.nlocs(), 1);
391 gval.get(testvalues_int, var2);
392 oops::Log::test() <<
"Get(int) result: " << testvalues_int << std::endl;
393 EXPECT_EQUAL(testvalues_int, refvalues_int);
404 std::string
testid()
const override {
return "ufo::test::GeoVaLs";}
407 std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
409 ts.emplace_back(
CASE(
"ufo/GeoVaLs/testGeoVaLs")
411 ts.emplace_back(
CASE(
"ufo/GeoVaLs/testGeoVaLsAllocatePutGet")
413 ts.emplace_back(
CASE(
"ufo/GeoVaLs/testGeoVaLsConstructor")
void clear() const override
void register_tests() const override
virtual ~GeoVaLs()=default
std::string testid() const override
void testGeoVaLsConstructor()
Tests GeoVaLs(const Locations &, const Variables &, const std::vector<size_t> &) constructor....
void testGeoVaLsAllocatePutGet()
Tests GeoVaLs::allocate, GeoVals::put, GeoVaLs::get, GeoVaLs::putAtLevel, GeoVaLs::getAtLevel,...
CASE("ufo/DataExtractor/bilinearinterp/float_linear")
integer function nlocs(this)
Return the number of observational locations in this Locations object.
util::Duration abs(const util::Duration &duration)