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