1 /*
2 * Distributed under the OSI-approved Apache License, Version 2.0. See
3 * accompanying file Copyright.txt for details.
4 */
5 #include <cstdint>
6 #include <cstring>
7
8 #include <iostream>
9 #include <stdexcept>
10
11 #include <adios2.h>
12
13 #include <gtest/gtest.h>
14
15 #include "../SmallTestData.h"
16
17 class HDF5WriteReadAsStreamTestADIOS2 : public ::testing::Test
18 {
19 public:
20 HDF5WriteReadAsStreamTestADIOS2() = default;
21
22 SmallTestData m_TestData;
23 };
24
TEST_F(HDF5WriteReadAsStreamTestADIOS2,ADIOS2HDF5WriteRead1D8)25 TEST_F(HDF5WriteReadAsStreamTestADIOS2, ADIOS2HDF5WriteRead1D8)
26 {
27 // Each process would write a 1x8 array and all processes would
28 // form a mpiSize * Nx 1D array
29 const std::string fname("ADIOS2HDF5WriteReadAsStream1D8.h5");
30
31 int mpiRank = 0, mpiSize = 1;
32 // Number of rows
33 const size_t Nx = 8;
34
35 // Number of steps
36 const size_t NSteps = 5;
37
38 #ifdef TEST_HDF5_MPI
39 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
40 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
41 #endif
42
43 // Write test data using HDF5
44
45 #ifdef TEST_HDF5_MPI
46 adios2::ADIOS adios(MPI_COMM_WORLD);
47 #else
48 adios2::ADIOS adios;
49 #endif
50 {
51 adios2::IO io = adios.DeclareIO("TestIO");
52 io.SetEngine("HDF5");
53
54 // Declare 1D variables (NumOfProcesses * Nx)
55 // The local process' part (start, count) can be defined now or later
56 // before Write().
57 {
58 const adios2::Dims shape{static_cast<size_t>(Nx * mpiSize)};
59 const adios2::Dims start{static_cast<size_t>(Nx * mpiRank)};
60 const adios2::Dims count{Nx};
61
62 io.DefineVariable<std::string>("iString");
63
64 io.DefineVariable<int8_t>("i8", shape, start, count,
65 adios2::ConstantDims);
66 io.DefineVariable<int16_t>("i16", shape, start, count,
67 adios2::ConstantDims);
68
69 io.DefineVariable<int32_t>("i32", shape, start, count,
70 adios2::ConstantDims);
71
72 io.DefineVariable<int64_t>("i64", shape, start, count,
73 adios2::ConstantDims);
74
75 io.DefineVariable<uint8_t>("u8", shape, start, count,
76 adios2::ConstantDims);
77
78 io.DefineVariable<uint16_t>("u16", shape, start, count,
79 adios2::ConstantDims);
80 io.DefineVariable<uint32_t>("u32", shape, start, count,
81 adios2::ConstantDims);
82 io.DefineVariable<uint64_t>("u64", shape, start, count,
83 adios2::ConstantDims);
84
85 io.DefineVariable<float>("r32", shape, start, count,
86 adios2::ConstantDims);
87 io.DefineVariable<double>("r64", shape, start, count,
88 adios2::ConstantDims);
89
90 io.DefineVariable<std::complex<float>>("cr32", shape, start, count,
91 adios2::ConstantDims);
92 io.DefineVariable<std::complex<double>>("cr64", shape, start, count,
93 adios2::ConstantDims);
94 }
95
96 adios2::Engine h5Writer = io.Open(fname, adios2::Mode::Write);
97
98 for (size_t step = 0; step < NSteps; ++step)
99 {
100 SmallTestData currentTestData = generateNewSmallTestData(
101 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
102
103 // EXPECT_EQ(h5Writer.CurrentStep(), step);
104
105 h5Writer.BeginStep();
106
107 if (step == 0)
108 {
109 h5Writer.Put<std::string>("iString", currentTestData.S1);
110 }
111
112 if (step % 2 == 0)
113 {
114 h5Writer.Put<int8_t>("i8", currentTestData.I8.data());
115 h5Writer.Put<int16_t>("i16", currentTestData.I16.data());
116 h5Writer.Put<int32_t>("i32", currentTestData.I32.data());
117 h5Writer.Put<int64_t>("i64", currentTestData.I64.data());
118 }
119 if (step % 2 == 1)
120 {
121 h5Writer.Put<uint8_t>("u8", currentTestData.U8.data());
122 h5Writer.Put<uint16_t>("u16", currentTestData.U16.data());
123 h5Writer.Put<uint32_t>("u32", currentTestData.U32.data());
124 h5Writer.Put<uint64_t>("u64", currentTestData.U64.data());
125 }
126
127 if (step < NSteps - 1) // all but the last
128 {
129 h5Writer.Put<float>("r32", currentTestData.R32.data());
130 h5Writer.Put<double>("r64", currentTestData.R64.data());
131 }
132
133 h5Writer.Put<std::complex<float>>("cr32",
134 currentTestData.CR32.data());
135 h5Writer.Put<std::complex<double>>("cr64",
136 currentTestData.CR64.data());
137
138 h5Writer.EndStep();
139 }
140
141 h5Writer.Close();
142 }
143
144 // if (false)
145 {
146 adios2::IO io = adios.DeclareIO("ReadIO");
147 io.SetEngine("HDF5");
148
149 adios2::Engine h5Reader = io.Open(fname, adios2::Mode::Read);
150
151 std::string IString;
152 std::array<int8_t, Nx> I8;
153 std::array<int16_t, Nx> I16;
154 std::array<int32_t, Nx> I32;
155 std::array<int64_t, Nx> I64;
156 std::array<uint8_t, Nx> U8;
157 std::array<uint16_t, Nx> U16;
158 std::array<uint32_t, Nx> U32;
159 std::array<uint64_t, Nx> U64;
160 std::array<float, Nx> R32;
161 std::array<double, Nx> R64;
162 std::array<std::complex<float>, Nx> CR32;
163 std::array<std::complex<double>, Nx> CR64;
164
165 const adios2::Dims start{mpiRank * Nx};
166 const adios2::Dims count{Nx};
167
168 const adios2::Box<adios2::Dims> sel(start, count);
169
170 size_t t = 0;
171
172 while (h5Reader.BeginStep() == adios2::StepStatus::OK)
173 {
174 const size_t currentStep = h5Reader.CurrentStep();
175 EXPECT_EQ(currentStep, static_cast<size_t>(t));
176
177 SmallTestData currentTestData = generateNewSmallTestData(
178 m_TestData, static_cast<int>(currentStep), mpiRank, mpiSize);
179
180 auto var_iString = io.InquireVariable<std::string>("iString");
181 auto var_i8 = io.InquireVariable<int8_t>("i8");
182 auto var_i16 = io.InquireVariable<int16_t>("i16");
183 auto var_i32 = io.InquireVariable<int32_t>("i32");
184 auto var_i64 = io.InquireVariable<int64_t>("i64");
185 auto var_u8 = io.InquireVariable<uint8_t>("u8");
186 auto var_u16 = io.InquireVariable<uint16_t>("u16");
187 auto var_u32 = io.InquireVariable<uint32_t>("u32");
188 auto var_u64 = io.InquireVariable<uint64_t>("u64");
189 auto var_r32 = io.InquireVariable<float>("r32");
190 auto var_r64 = io.InquireVariable<double>("r64");
191 auto var_cr32 = io.InquireVariable<std::complex<float>>("cr32");
192 auto var_cr64 = io.InquireVariable<std::complex<double>>("cr64");
193
194 if (currentStep == 0)
195 {
196 EXPECT_TRUE(var_iString);
197 EXPECT_TRUE(var_iString);
198 ASSERT_EQ(var_iString.Shape().size(), 0);
199 ASSERT_EQ(var_iString.Steps(), 1);
200 }
201 else
202 {
203 EXPECT_FALSE(var_iString);
204 }
205
206 if (currentStep % 2 == 0)
207 {
208 EXPECT_TRUE(var_i8);
209 EXPECT_TRUE(var_i16);
210 EXPECT_TRUE(var_i32);
211 EXPECT_TRUE(var_i64);
212 EXPECT_FALSE(var_u8);
213 EXPECT_FALSE(var_u16);
214 EXPECT_FALSE(var_u32);
215 EXPECT_FALSE(var_u64);
216
217 ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
218 ASSERT_EQ(var_i8.Steps(), NSteps / 2 + NSteps % 2);
219 ASSERT_EQ(var_i8.Shape()[0], static_cast<size_t>(mpiSize * Nx));
220
221 ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
222 ASSERT_EQ(var_i16.Steps(), NSteps / 2 + NSteps % 2);
223 ASSERT_EQ(var_i16.Shape()[0],
224 static_cast<size_t>(mpiSize * Nx));
225
226 ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
227 ASSERT_EQ(var_i32.Steps(), NSteps / 2 + NSteps % 2);
228 ASSERT_EQ(var_i32.Shape()[0],
229 static_cast<size_t>(mpiSize * Nx));
230
231 ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
232 ASSERT_EQ(var_i64.Steps(), NSteps / 2 + NSteps % 2);
233 ASSERT_EQ(var_i64.Shape()[0],
234 static_cast<size_t>(mpiSize * Nx));
235
236 var_i8.SetSelection(sel);
237 var_i16.SetSelection(sel);
238 var_i32.SetSelection(sel);
239 var_i64.SetSelection(sel);
240
241 h5Reader.Get(var_i8, I8.data());
242 h5Reader.Get(var_i16, I16.data());
243 h5Reader.Get(var_i32, I32.data());
244 h5Reader.Get(var_i64, I64.data());
245 }
246
247 if (currentStep % 2 == 1)
248 {
249 EXPECT_FALSE(var_i8);
250 EXPECT_FALSE(var_i16);
251 EXPECT_FALSE(var_i32);
252 EXPECT_FALSE(var_i64);
253 EXPECT_TRUE(var_u8);
254 EXPECT_TRUE(var_u16);
255 EXPECT_TRUE(var_u32);
256 EXPECT_TRUE(var_u64);
257
258 ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
259 ASSERT_EQ(var_u8.Steps(), NSteps / 2);
260 ASSERT_EQ(var_u8.Shape()[0], mpiSize * Nx);
261
262 ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
263 ASSERT_EQ(var_u16.Steps(), NSteps / 2);
264 ASSERT_EQ(var_u16.Shape()[0], mpiSize * Nx);
265
266 ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
267 ASSERT_EQ(var_u32.Steps(), NSteps / 2);
268 ASSERT_EQ(var_u32.Shape()[0], mpiSize * Nx);
269
270 ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
271 ASSERT_EQ(var_u64.Steps(), NSteps / 2);
272 ASSERT_EQ(var_u64.Shape()[0], mpiSize * Nx);
273
274 var_u8.SetSelection(sel);
275 var_u16.SetSelection(sel);
276 var_u32.SetSelection(sel);
277 var_u64.SetSelection(sel);
278
279 h5Reader.Get(var_u8, U8.data());
280 h5Reader.Get(var_u16, U16.data());
281 h5Reader.Get(var_u32, U32.data());
282 h5Reader.Get(var_u64, U64.data());
283 }
284
285 if (currentStep == NSteps - 1)
286 {
287 EXPECT_FALSE(var_r32);
288 EXPECT_FALSE(var_r64);
289 }
290 else
291 {
292 EXPECT_TRUE(var_r32);
293 EXPECT_TRUE(var_r64);
294
295 ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
296 ASSERT_EQ(var_r32.Steps(), NSteps - 1);
297 ASSERT_EQ(var_r32.Shape()[0], mpiSize * Nx);
298
299 ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
300 ASSERT_EQ(var_r64.Steps(), NSteps - 1);
301 ASSERT_EQ(var_r64.Shape()[0], mpiSize * Nx);
302
303 var_r32.SetSelection(sel);
304 var_r64.SetSelection(sel);
305
306 h5Reader.Get(var_r32, R32.data());
307 h5Reader.Get(var_r64, R64.data());
308 }
309
310 EXPECT_TRUE(var_cr32);
311 EXPECT_TRUE(var_cr64);
312
313 ASSERT_EQ(var_cr32.ShapeID(), adios2::ShapeID::GlobalArray);
314 ASSERT_EQ(var_cr32.Steps(), NSteps);
315 ASSERT_EQ(var_cr32.Shape()[0], mpiSize * Nx);
316
317 ASSERT_EQ(var_cr64.ShapeID(), adios2::ShapeID::GlobalArray);
318 ASSERT_EQ(var_cr64.Steps(), NSteps);
319 ASSERT_EQ(var_cr64.Shape()[0], mpiSize * Nx);
320
321 var_cr32.SetSelection(sel);
322 var_cr64.SetSelection(sel);
323
324 h5Reader.Get(var_cr32, CR32.data());
325 h5Reader.Get(var_cr64, CR64.data());
326
327 h5Reader.EndStep();
328
329 for (size_t i = 0; i < Nx; ++i)
330 {
331 std::stringstream ss;
332 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
333 std::string msg = ss.str();
334
335 if (var_i8)
336 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
337 if (var_i16)
338 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
339 if (var_i32)
340 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
341 if (var_i64)
342 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
343
344 if (var_u8)
345 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
346 if (var_u16)
347 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
348 if (var_u32)
349 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
350 if (var_u64)
351 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
352 if (var_r32)
353 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
354 if (var_r64)
355 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
356
357 if (var_cr32)
358 EXPECT_EQ(CR32[i], currentTestData.CR32[i]) << msg;
359 if (var_cr64)
360 EXPECT_EQ(CR64[i], currentTestData.CR64[i]) << msg;
361 }
362 ++t;
363 }
364
365 EXPECT_EQ(t, NSteps);
366
367 h5Reader.Close();
368 }
369 }
370
TEST_F(HDF5WriteReadAsStreamTestADIOS2,ADIOS2HDF5WriteRead2D2x4)371 TEST_F(HDF5WriteReadAsStreamTestADIOS2, ADIOS2HDF5WriteRead2D2x4)
372 {
373 // Each process would write a 2x4 array and all processes would
374 // form a 2D 2 * (numberOfProcess*Nx) matrix where Nx is 4 here
375 const std::string fname("ADIOS2HDF5WriteReadAsStream2D2x4Test.h5");
376
377 int mpiRank = 0, mpiSize = 1;
378 // Number of rows
379 const std::size_t Nx = 4;
380
381 // Number of rows
382 const std::size_t Ny = 2;
383
384 // Number of steps
385 const std::size_t NSteps = 3;
386
387 #ifdef TEST_HDF5_MPI
388 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
389 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
390 #endif
391
392 // Write test data using ADIOS2
393
394 #ifdef TEST_HDF5_MPI
395 adios2::ADIOS adios(MPI_COMM_WORLD);
396 #else
397 adios2::ADIOS adios;
398 #endif
399 {
400 adios2::IO io = adios.DeclareIO("TestIO");
401
402 // Create the HDF5 Engine
403 io.SetEngine("HDF5");
404
405 // Declare 2D variables (Ny * (NumOfProcesses * Nx))
406 // The local process' part (start, count) can be defined now or later
407 // before Write().
408 {
409 const adios2::Dims shape{Ny, static_cast<size_t>(Nx * mpiSize)};
410 const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
411 const adios2::Dims count{Ny, Nx};
412
413 io.DefineVariable<int8_t>("i8", shape, start, count,
414 adios2::ConstantDims);
415 io.DefineVariable<int16_t>("i16", shape, start, count,
416 adios2::ConstantDims);
417 io.DefineVariable<int32_t>("i32", shape, start, count,
418 adios2::ConstantDims);
419 io.DefineVariable<int64_t>("i64", shape, start, count,
420 adios2::ConstantDims);
421
422 io.DefineVariable<uint8_t>("u8", shape, start, count,
423 adios2::ConstantDims);
424
425 io.DefineVariable<uint16_t>("u16", shape, start, count,
426 adios2::ConstantDims);
427 io.DefineVariable<uint32_t>("u32", shape, start, count,
428 adios2::ConstantDims);
429 io.DefineVariable<uint64_t>("u64", shape, start, count,
430 adios2::ConstantDims);
431
432 io.DefineVariable<float>("r32", shape, start, count,
433 adios2::ConstantDims);
434 io.DefineVariable<double>("r64", shape, start, count,
435 adios2::ConstantDims);
436 }
437
438 adios2::Engine h5Writer = io.Open(fname, adios2::Mode::Write);
439
440 for (size_t step = 0; step < NSteps; ++step)
441 {
442 SmallTestData currentTestData = generateNewSmallTestData(
443 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
444
445 // EXPECT_EQ(h5Writer.CurrentStep(), step);
446
447 h5Writer.BeginStep();
448 h5Writer.Put<int8_t>("i8", currentTestData.I8.data());
449 h5Writer.Put<int16_t>("i16", currentTestData.I16.data());
450 h5Writer.Put<int32_t>("i32", currentTestData.I32.data());
451 h5Writer.Put<int64_t>("i64", currentTestData.I64.data());
452 h5Writer.Put<uint8_t>("u8", currentTestData.U8.data());
453 h5Writer.Put<uint16_t>("u16", currentTestData.U16.data());
454 h5Writer.Put<uint32_t>("u32", currentTestData.U32.data());
455 h5Writer.Put<uint64_t>("u64", currentTestData.U64.data());
456 h5Writer.Put<float>("r32", currentTestData.R32.data());
457 h5Writer.Put<double>("r64", currentTestData.R64.data());
458 h5Writer.EndStep();
459 }
460
461 h5Writer.Close();
462 }
463
464 {
465 adios2::IO io = adios.DeclareIO("ReadIO");
466 io.SetEngine("HDF5");
467
468 adios2::Engine h5Reader = io.Open(fname, adios2::Mode::Read);
469
470 size_t t = 0;
471
472 while (h5Reader.BeginStep() == adios2::StepStatus::OK)
473 {
474 auto var_i8 = io.InquireVariable<int8_t>("i8");
475 EXPECT_TRUE(var_i8);
476 ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
477 ASSERT_EQ(var_i8.Steps(), NSteps);
478 ASSERT_EQ(var_i8.Shape()[0], Ny);
479 ASSERT_EQ(var_i8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
480
481 auto var_i16 = io.InquireVariable<int16_t>("i16");
482 EXPECT_TRUE(var_i16);
483 ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
484 ASSERT_EQ(var_i16.Steps(), NSteps);
485 ASSERT_EQ(var_i16.Shape()[0], Ny);
486 ASSERT_EQ(var_i16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
487
488 auto var_i32 = io.InquireVariable<int32_t>("i32");
489 EXPECT_TRUE(var_i32);
490 ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
491 ASSERT_EQ(var_i32.Steps(), NSteps);
492 ASSERT_EQ(var_i32.Shape()[0], Ny);
493 ASSERT_EQ(var_i32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
494
495 auto var_i64 = io.InquireVariable<int64_t>("i64");
496 EXPECT_TRUE(var_i64);
497 ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
498 ASSERT_EQ(var_i64.Steps(), NSteps);
499 ASSERT_EQ(var_i64.Shape()[0], Ny);
500 ASSERT_EQ(var_i64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
501
502 auto var_u8 = io.InquireVariable<uint8_t>("u8");
503 EXPECT_TRUE(var_u8);
504 ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
505 ASSERT_EQ(var_u8.Steps(), NSteps);
506 ASSERT_EQ(var_u8.Shape()[0], Ny);
507 ASSERT_EQ(var_u8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
508
509 auto var_u16 = io.InquireVariable<uint16_t>("u16");
510 EXPECT_TRUE(var_u16);
511 ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
512 ASSERT_EQ(var_u16.Steps(), NSteps);
513 ASSERT_EQ(var_u16.Shape()[0], Ny);
514 ASSERT_EQ(var_u16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
515
516 auto var_u32 = io.InquireVariable<uint32_t>("u32");
517 EXPECT_TRUE(var_u32);
518 ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
519 ASSERT_EQ(var_u32.Steps(), NSteps);
520 ASSERT_EQ(var_u32.Shape()[0], Ny);
521 ASSERT_EQ(var_u32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
522
523 auto var_u64 = io.InquireVariable<uint64_t>("u64");
524 EXPECT_TRUE(var_u64);
525 ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
526 ASSERT_EQ(var_u64.Steps(), NSteps);
527 ASSERT_EQ(var_u64.Shape()[0], Ny);
528 ASSERT_EQ(var_u64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
529
530 auto var_r32 = io.InquireVariable<float>("r32");
531 EXPECT_TRUE(var_r32);
532 ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
533 ASSERT_EQ(var_r32.Steps(), NSteps);
534 ASSERT_EQ(var_r32.Shape()[0], Ny);
535 ASSERT_EQ(var_r32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
536
537 auto var_r64 = io.InquireVariable<double>("r64");
538 EXPECT_TRUE(var_r64);
539 ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
540 ASSERT_EQ(var_r64.Steps(), NSteps);
541 ASSERT_EQ(var_r64.Shape()[0], Ny);
542 ASSERT_EQ(var_r64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
543
544 std::array<int8_t, Nx * Ny> I8;
545 std::array<int16_t, Nx * Ny> I16;
546 std::array<int32_t, Nx * Ny> I32;
547 std::array<int64_t, Nx * Ny> I64;
548 std::array<uint8_t, Nx * Ny> U8;
549 std::array<uint16_t, Nx * Ny> U16;
550 std::array<uint32_t, Nx * Ny> U32;
551 std::array<uint64_t, Nx * Ny> U64;
552 std::array<float, Nx * Ny> R32;
553 std::array<double, Nx * Ny> R64;
554
555 const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
556 const adios2::Dims count{Ny, Nx};
557
558 const adios2::Box<adios2::Dims> sel(start, count);
559
560 var_i8.SetSelection(sel);
561 var_i16.SetSelection(sel);
562 var_i32.SetSelection(sel);
563 var_i64.SetSelection(sel);
564
565 var_u8.SetSelection(sel);
566 var_u16.SetSelection(sel);
567 var_u32.SetSelection(sel);
568 var_u64.SetSelection(sel);
569
570 var_r32.SetSelection(sel);
571 var_r64.SetSelection(sel);
572
573 const size_t currentStep = h5Reader.CurrentStep();
574 EXPECT_EQ(currentStep, static_cast<size_t>(t));
575
576 SmallTestData currentTestData = generateNewSmallTestData(
577 m_TestData, static_cast<int>(currentStep), mpiRank, mpiSize);
578
579 h5Reader.Get(var_i8, I8.data());
580 h5Reader.Get(var_i16, I16.data());
581 h5Reader.Get(var_i32, I32.data());
582 h5Reader.Get(var_i64, I64.data());
583
584 h5Reader.Get(var_u8, U8.data());
585 h5Reader.Get(var_u16, U16.data());
586 h5Reader.Get(var_u32, U32.data());
587 h5Reader.Get(var_u64, U64.data());
588
589 h5Reader.Get(var_r32, R32.data());
590 h5Reader.Get(var_r64, R64.data());
591
592 h5Reader.PerformGets();
593 h5Reader.EndStep();
594
595 for (size_t i = 0; i < Nx * Ny; ++i)
596 {
597 std::stringstream ss;
598 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
599 std::string msg = ss.str();
600
601 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
602 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
603 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
604 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
605 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
606 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
607 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
608 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
609 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
610 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
611 }
612 ++t;
613 }
614 EXPECT_EQ(t, NSteps);
615
616 h5Reader.Close();
617 }
618 }
619
TEST_F(HDF5WriteReadAsStreamTestADIOS2,ADIOS2HDF5WriteRead2D4x2)620 TEST_F(HDF5WriteReadAsStreamTestADIOS2, ADIOS2HDF5WriteRead2D4x2)
621 {
622 // Each process would write a 4x2 array and all processes would
623 // form a 2D 4 * (NumberOfProcess * Nx) matrix where Nx is 2 here
624 const std::string fname("ADIOS2HDF5WriteReadAsStream2D4x2Test.h5");
625
626 int mpiRank = 0, mpiSize = 1;
627 // Number of rows
628 const std::size_t Nx = 2;
629 // Number of cols
630 const std::size_t Ny = 4;
631
632 // Number of steps
633 const std::size_t NSteps = 3;
634
635 #ifdef TEST_HDF5_MPI
636 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
637 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
638 #endif
639
640 // Write test data using ADIOS2
641
642 #ifdef TEST_HDF5_MPI
643 adios2::ADIOS adios(MPI_COMM_WORLD);
644 #else
645 adios2::ADIOS adios;
646 #endif
647 {
648 adios2::IO io = adios.DeclareIO("TestIO");
649 io.SetEngine("HDF5");
650
651 // Declare 2D variables (4 * (NumberOfProcess * Nx))
652 // The local process' part (start, count) can be defined now or later
653 // before Write().
654 {
655 adios2::Dims shape{static_cast<unsigned int>(Ny),
656 static_cast<unsigned int>(mpiSize * Nx)};
657 adios2::Dims start{static_cast<unsigned int>(0),
658 static_cast<unsigned int>(mpiRank * Nx)};
659 adios2::Dims count{static_cast<unsigned int>(Ny),
660 static_cast<unsigned int>(Nx)};
661
662 io.DefineVariable<int8_t>("i8", shape, start, count,
663 adios2::ConstantDims);
664 io.DefineVariable<int16_t>("i16", shape, start, count,
665 adios2::ConstantDims);
666 io.DefineVariable<int32_t>("i32", shape, start, count,
667 adios2::ConstantDims);
668 io.DefineVariable<int64_t>("i64", shape, start, count,
669 adios2::ConstantDims);
670
671 io.DefineVariable<uint8_t>("u8", shape, start, count,
672 adios2::ConstantDims);
673
674 io.DefineVariable<uint16_t>("u16", shape, start, count,
675 adios2::ConstantDims);
676 io.DefineVariable<uint32_t>("u32", shape, start, count,
677 adios2::ConstantDims);
678 io.DefineVariable<uint64_t>("u64", shape, start, count,
679 adios2::ConstantDims);
680
681 io.DefineVariable<float>("r32", shape, start, count,
682 adios2::ConstantDims);
683 io.DefineVariable<double>("r64", shape, start, count,
684 adios2::ConstantDims);
685 }
686
687 adios2::Engine h5Writer = io.Open(fname, adios2::Mode::Write);
688
689 for (size_t step = 0; step < NSteps; ++step)
690 {
691 SmallTestData currentTestData = generateNewSmallTestData(
692 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
693
694 // EXPECT_EQ(h5Writer.CurrentStep(), step);
695
696 h5Writer.BeginStep();
697 h5Writer.Put<int8_t>("i8", currentTestData.I8.data());
698 h5Writer.Put<int16_t>("i16", currentTestData.I16.data());
699 h5Writer.Put<int32_t>("i32", currentTestData.I32.data());
700 h5Writer.Put<int64_t>("i64", currentTestData.I64.data());
701 h5Writer.Put<uint8_t>("u8", currentTestData.U8.data());
702 h5Writer.Put<uint16_t>("u16", currentTestData.U16.data());
703 h5Writer.Put<uint32_t>("u32", currentTestData.U32.data());
704 h5Writer.Put<uint64_t>("u64", currentTestData.U64.data());
705 h5Writer.Put<float>("r32", currentTestData.R32.data());
706 h5Writer.Put<double>("r64", currentTestData.R64.data());
707 h5Writer.EndStep();
708 }
709
710 h5Writer.Close();
711 }
712
713 {
714 adios2::IO io = adios.DeclareIO("ReadIO");
715 io.SetEngine("HDF5");
716
717 adios2::Engine h5Reader = io.Open(fname, adios2::Mode::Read);
718
719 size_t t = 0;
720
721 while (h5Reader.BeginStep() == adios2::StepStatus::OK)
722 {
723
724 auto var_i8 = io.InquireVariable<int8_t>("i8");
725 EXPECT_TRUE(var_i8);
726 ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
727 ASSERT_EQ(var_i8.Steps(), NSteps);
728 ASSERT_EQ(var_i8.Shape()[0], Ny);
729 ASSERT_EQ(var_i8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
730
731 auto var_i16 = io.InquireVariable<int16_t>("i16");
732 EXPECT_TRUE(var_i16);
733 ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
734 ASSERT_EQ(var_i16.Steps(), NSteps);
735 ASSERT_EQ(var_i16.Shape()[0], Ny);
736 ASSERT_EQ(var_i16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
737
738 auto var_i32 = io.InquireVariable<int32_t>("i32");
739 EXPECT_TRUE(var_i32);
740 ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
741 ASSERT_EQ(var_i32.Steps(), NSteps);
742 ASSERT_EQ(var_i32.Shape()[0], Ny);
743 ASSERT_EQ(var_i32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
744
745 auto var_i64 = io.InquireVariable<int64_t>("i64");
746 EXPECT_TRUE(var_i64);
747 ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
748 ASSERT_EQ(var_i64.Steps(), NSteps);
749 ASSERT_EQ(var_i64.Shape()[0], Ny);
750 ASSERT_EQ(var_i64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
751
752 auto var_u8 = io.InquireVariable<uint8_t>("u8");
753 EXPECT_TRUE(var_u8);
754 ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
755 ASSERT_EQ(var_u8.Steps(), NSteps);
756 ASSERT_EQ(var_u8.Shape()[0], Ny);
757 ASSERT_EQ(var_u8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
758
759 auto var_u16 = io.InquireVariable<uint16_t>("u16");
760 EXPECT_TRUE(var_u16);
761 ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
762 ASSERT_EQ(var_u16.Steps(), NSteps);
763 ASSERT_EQ(var_u16.Shape()[0], Ny);
764 ASSERT_EQ(var_u16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
765
766 auto var_u32 = io.InquireVariable<uint32_t>("u32");
767 EXPECT_TRUE(var_u32);
768 ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
769 ASSERT_EQ(var_u32.Steps(), NSteps);
770 ASSERT_EQ(var_u32.Shape()[0], Ny);
771 ASSERT_EQ(var_u32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
772
773 auto var_u64 = io.InquireVariable<uint64_t>("u64");
774 EXPECT_TRUE(var_u64);
775 ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
776 ASSERT_EQ(var_u64.Steps(), NSteps);
777 ASSERT_EQ(var_u64.Shape()[0], Ny);
778 ASSERT_EQ(var_u64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
779
780 auto var_r32 = io.InquireVariable<float>("r32");
781 EXPECT_TRUE(var_r32);
782 ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
783 ASSERT_EQ(var_r32.Steps(), NSteps);
784 ASSERT_EQ(var_r32.Shape()[0], Ny);
785 ASSERT_EQ(var_r32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
786
787 auto var_r64 = io.InquireVariable<double>("r64");
788 EXPECT_TRUE(var_r64);
789 ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
790 ASSERT_EQ(var_r64.Steps(), NSteps);
791 ASSERT_EQ(var_r64.Shape()[0], Ny);
792 ASSERT_EQ(var_r64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
793
794 // If the size of the array is smaller than the data
795 // the result is weird... double and uint64_t would get
796 // completely garbage data
797 std::array<int8_t, Nx * Ny> I8;
798 std::array<int16_t, Nx * Ny> I16;
799 std::array<int32_t, Nx * Ny> I32;
800 std::array<int64_t, Nx * Ny> I64;
801 std::array<uint8_t, Nx * Ny> U8;
802 std::array<uint16_t, Nx * Ny> U16;
803 std::array<uint32_t, Nx * Ny> U32;
804 std::array<uint64_t, Nx * Ny> U64;
805 std::array<float, Nx * Ny> R32;
806 std::array<double, Nx * Ny> R64;
807
808 const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
809 const adios2::Dims count{Ny, Nx};
810
811 const adios2::Box<adios2::Dims> sel(start, count);
812
813 var_i8.SetSelection(sel);
814 var_i16.SetSelection(sel);
815 var_i32.SetSelection(sel);
816 var_i64.SetSelection(sel);
817
818 var_u8.SetSelection(sel);
819 var_u16.SetSelection(sel);
820 var_u32.SetSelection(sel);
821 var_u64.SetSelection(sel);
822
823 var_r32.SetSelection(sel);
824 var_r64.SetSelection(sel);
825
826 const size_t currentStep = h5Reader.CurrentStep();
827 EXPECT_EQ(currentStep, static_cast<size_t>(t));
828
829 SmallTestData currentTestData = generateNewSmallTestData(
830 m_TestData, static_cast<int>(currentStep), mpiRank, mpiSize);
831
832 h5Reader.Get(var_i8, I8.data());
833 h5Reader.Get(var_i16, I16.data());
834 h5Reader.Get(var_i32, I32.data());
835 h5Reader.Get(var_i64, I64.data());
836
837 h5Reader.Get(var_u8, U8.data());
838 h5Reader.Get(var_u16, U16.data());
839 h5Reader.Get(var_u32, U32.data());
840 h5Reader.Get(var_u64, U64.data());
841
842 h5Reader.Get(var_r32, R32.data());
843 h5Reader.Get(var_r64, R64.data());
844
845 h5Reader.PerformGets();
846
847 h5Reader.EndStep();
848
849 for (size_t i = 0; i < Nx * Ny; ++i)
850 {
851 std::stringstream ss;
852 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
853 std::string msg = ss.str();
854
855 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
856 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
857 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
858 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
859 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
860 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
861 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
862 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
863 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
864 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
865 }
866 ++t;
867 }
868 EXPECT_EQ(t, NSteps);
869 h5Reader.Close();
870 }
871 }
872
TEST_F(HDF5WriteReadAsStreamTestADIOS2,ReaderWriterDefineVariable)873 TEST_F(HDF5WriteReadAsStreamTestADIOS2, ReaderWriterDefineVariable)
874 {
875 const std::string fnameFloat("HDF5ReaderWriterDefineVariable_float.h5");
876 const std::string fname("HDF5ReaderWriterDefineVariable_all.h5");
877
878 int mpiRank = 0, mpiSize = 1;
879 // Number of rows
880 const std::size_t Nx = 2;
881 // Number of cols
882 const std::size_t Ny = 4;
883
884 // Number of steps
885 const std::size_t NSteps = 3;
886
887 #ifdef TEST_HDF5_MPI
888 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
889 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
890 #endif
891
892 // Write test data using ADIOS2
893
894 #ifdef TEST_HDF5_MPI
895 adios2::ADIOS adios(MPI_COMM_WORLD);
896 #else
897 adios2::ADIOS adios;
898 #endif
899
900 const adios2::Dims shape{Ny, static_cast<size_t>(Nx * mpiSize)};
901 const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
902 const adios2::Dims count{Ny, Nx};
903 // simple writer to generate content
904 {
905 adios2::IO io = adios.DeclareIO("Writer");
906 io.SetEngine("HDF5");
907
908 io.DefineVariable<float>("r32", shape, start, count,
909 adios2::ConstantDims);
910
911 adios2::Engine h5Writer = io.Open(fnameFloat, adios2::Mode::Write);
912
913 for (size_t step = 0; step < NSteps; ++step)
914 {
915 SmallTestData currentTestData = generateNewSmallTestData(
916 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
917 h5Writer.BeginStep();
918 h5Writer.Put<float>("r32", currentTestData.R32.data());
919 h5Writer.EndStep();
920 }
921
922 h5Writer.Close();
923 }
924 #ifdef TEST_HDF5_MPI
925 MPI_Barrier(MPI_COMM_WORLD);
926 #endif
927 {
928 adios2::IO io = adios.DeclareIO("ReaderWriter");
929 io.SetEngine("HDF5");
930
931 adios2::Engine reader = io.Open(fnameFloat, adios2::Mode::Read);
932 adios2::Engine writer = io.Open(fname, adios2::Mode::Write);
933 for (size_t step = 0; step < NSteps; ++step)
934 {
935 reader.BeginStep();
936 adios2::Variable<float> varR32 = io.InquireVariable<float>("r32");
937 EXPECT_TRUE(varR32);
938 reader.EndStep();
939
940 if (step == 0)
941 {
942 adios2::Variable<double> varR64 = io.DefineVariable<double>(
943 "r64", shape, start, count, adios2::ConstantDims);
944 EXPECT_TRUE(varR64);
945 }
946 SmallTestData currentTestData = generateNewSmallTestData(
947 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
948 writer.BeginStep();
949 writer.Put<float>("r32", currentTestData.R32.data());
950 writer.Put<double>("r64", currentTestData.R64.data());
951 writer.EndStep();
952 }
953
954 writer.Close();
955 reader.Close();
956 }
957 #ifdef TEST_HDF5_MPI
958 MPI_Barrier(MPI_COMM_WORLD);
959 #endif
960 {
961 adios2::IO io = adios.DeclareIO("Reader");
962 io.SetEngine("HDF5");
963 adios2::Engine reader = io.Open(fname, adios2::Mode::Read);
964 while (reader.BeginStep() == adios2::StepStatus::OK)
965 {
966 adios2::Variable<float> varR32 = io.InquireVariable<float>("r32");
967 EXPECT_TRUE(varR32);
968 adios2::Variable<double> varR64 = io.InquireVariable<double>("r64");
969 EXPECT_TRUE(varR32);
970 reader.EndStep();
971 }
972 reader.Close();
973 }
974 }
975
main(int argc,char ** argv)976 int main(int argc, char **argv)
977 {
978 #ifdef TEST_HDF5_MPI
979 MPI_Init(nullptr, nullptr);
980 #endif
981
982 int result;
983 ::testing::InitGoogleTest(&argc, argv);
984 result = RUN_ALL_TESTS();
985
986 #ifdef TEST_HDF5_MPI
987 MPI_Finalize();
988 #endif
989
990 return result;
991 }
992