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 <numeric> //std::iota
10 #include <stdexcept>
11 
12 #include <adios2.h>
13 
14 #include <gtest/gtest.h>
15 
16 #include "../SmallTestData.h"
17 
18 std::string engineName; // comes from command line
19 
20 class BPWriteReadBlockInfo : public ::testing::Test
21 {
22 public:
23     BPWriteReadBlockInfo() = default;
24 
25     SmallTestData m_TestData;
26 };
27 
28 namespace
29 {
30 
31 template <class T>
CheckAllStepsBlockInfo1D(const std::vector<std::vector<typename adios2::Variable<T>::Info>> & allStepsBlocksInfo,const size_t NSteps,const size_t Nx)32 void CheckAllStepsBlockInfo1D(
33     const std::vector<std::vector<typename adios2::Variable<T>::Info>>
34         &allStepsBlocksInfo,
35     const size_t NSteps, const size_t Nx)
36 {
37     EXPECT_EQ(allStepsBlocksInfo.size(), NSteps);
38 
39     for (size_t s = 0; s < allStepsBlocksInfo.size(); ++s)
40     {
41         for (size_t b = 0; b < allStepsBlocksInfo[s].size(); ++b)
42         {
43             EXPECT_EQ(allStepsBlocksInfo[s][b].BlockID, b);
44             EXPECT_EQ(allStepsBlocksInfo[s][b].Start[0], b * Nx);
45             EXPECT_EQ(allStepsBlocksInfo[s][b].Count[0], Nx);
46             EXPECT_EQ(allStepsBlocksInfo[s][b].Step, s);
47             EXPECT_EQ(allStepsBlocksInfo[s][b].WriterID, b);
48             EXPECT_FALSE(allStepsBlocksInfo[s][b].IsReverseDims);
49         }
50     }
51 }
52 
53 template <class T>
CheckAllStepsBlockInfo2D(const std::vector<std::vector<typename adios2::Variable<T>::Info>> & allStepsBlocksInfo,const size_t NSteps,const size_t Nx,const size_t Ny)54 void CheckAllStepsBlockInfo2D(
55     const std::vector<std::vector<typename adios2::Variable<T>::Info>>
56         &allStepsBlocksInfo,
57     const size_t NSteps, const size_t Nx, const size_t Ny)
58 {
59     EXPECT_EQ(allStepsBlocksInfo.size(), NSteps);
60 
61     for (size_t s = 0; s < allStepsBlocksInfo.size(); ++s)
62     {
63         for (size_t b = 0; b < allStepsBlocksInfo[s].size(); ++b)
64         {
65             EXPECT_EQ(allStepsBlocksInfo[s][b].BlockID, b);
66             EXPECT_EQ(allStepsBlocksInfo[s][b].Start[0], 0);
67             EXPECT_EQ(allStepsBlocksInfo[s][b].Start[1], b * Nx);
68             EXPECT_EQ(allStepsBlocksInfo[s][b].Count[0], Ny);
69             EXPECT_EQ(allStepsBlocksInfo[s][b].Count[1], Nx);
70             EXPECT_EQ(allStepsBlocksInfo[s][b].Step, s);
71             EXPECT_EQ(allStepsBlocksInfo[s][b].WriterID, b);
72             EXPECT_FALSE(allStepsBlocksInfo[s][b].IsReverseDims);
73         }
74     }
75 }
76 }
77 
TEST_F(BPWriteReadBlockInfo,BPWriteReadBlockInfo1D8)78 TEST_F(BPWriteReadBlockInfo, BPWriteReadBlockInfo1D8)
79 {
80     // Each process would write a 1x8 array and all processes would
81     // form a mpiSize * Nx 1D array
82     const std::string fname("BPWriteReadblockInfo1D8.bp");
83 
84     int mpiRank = 0, mpiSize = 1;
85     // Number of rows
86     const size_t Nx = 8;
87 
88     // Number of steps
89     const size_t NSteps = 3;
90 
91 #if ADIOS2_USE_MPI
92     MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
93     MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
94 #endif
95 
96     // Write test data using BP
97 
98 #if ADIOS2_USE_MPI
99     adios2::ADIOS adios(MPI_COMM_WORLD);
100 #else
101     adios2::ADIOS adios;
102 #endif
103     {
104         adios2::IO io = adios.DeclareIO("TestIO");
105 
106         const adios2::Dims shape{static_cast<size_t>(Nx * mpiSize)};
107         const adios2::Dims start{static_cast<size_t>(Nx * mpiRank)};
108         const adios2::Dims count{Nx};
109 
110         auto var_local =
111             io.DefineVariable<int32_t>("local", {adios2::LocalValueDim});
112         auto var_localStr =
113             io.DefineVariable<std::string>("localStr", {adios2::LocalValueDim});
114 
115         auto var_iString = io.DefineVariable<std::string>("iString");
116         auto var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count);
117         auto var_i16 = io.DefineVariable<int16_t>("i16", shape, start, count);
118         auto var_i32 = io.DefineVariable<int32_t>("i32", shape, start, count);
119         auto var_i64 = io.DefineVariable<int64_t>("i64", shape, start, count);
120         auto var_u8 = io.DefineVariable<uint8_t>("u8", shape, start, count);
121         auto var_u16 = io.DefineVariable<uint16_t>("u16", shape, start, count);
122         auto var_u32 = io.DefineVariable<uint32_t>("u32", shape, start, count);
123         auto var_u64 = io.DefineVariable<uint64_t>("u64", shape, start, count);
124         auto var_r32 = io.DefineVariable<float>("r32", shape, start, count);
125         auto var_r64 = io.DefineVariable<double>("r64", shape, start, count);
126         auto var_cr32 =
127             io.DefineVariable<std::complex<float>>("cr32", shape, start, count);
128         auto var_cr64 = io.DefineVariable<std::complex<double>>("cr64", shape,
129                                                                 start, count);
130 
131         if (!engineName.empty())
132         {
133             io.SetEngine(engineName);
134         }
135         else
136         {
137             // Create the BP Engine
138             io.SetEngine("BPFile");
139         }
140         io.SetParameter("AggregatorRatio", "1");
141 
142         adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write);
143 
144         for (size_t step = 0; step < NSteps; ++step)
145         {
146             // Generate test data for each process uniquely
147             SmallTestData currentTestData = generateNewSmallTestData(
148                 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
149 
150             bpWriter.BeginStep();
151 
152             const int32_t localNumber = static_cast<int32_t>(mpiRank + step);
153             bpWriter.Put(var_local, localNumber);
154             bpWriter.Put(var_localStr, std::to_string(localNumber));
155 
156             bpWriter.Put(var_iString, currentTestData.S1);
157             bpWriter.Put(var_i8, currentTestData.I8.data());
158             bpWriter.Put(var_i16, currentTestData.I16.data());
159             bpWriter.Put(var_i32, currentTestData.I32.data());
160             bpWriter.Put(var_i64, currentTestData.I64.data());
161             bpWriter.Put(var_u8, currentTestData.U8.data());
162             bpWriter.Put(var_u16, currentTestData.U16.data());
163             bpWriter.Put(var_u32, currentTestData.U32.data());
164             bpWriter.Put(var_u64, currentTestData.U64.data());
165             bpWriter.Put(var_r32, currentTestData.R32.data());
166             bpWriter.Put(var_r64, currentTestData.R64.data());
167             bpWriter.Put(var_cr32, currentTestData.CR32.data());
168             bpWriter.Put(var_cr64, currentTestData.CR64.data());
169             bpWriter.EndStep();
170         }
171 
172         bpWriter.Close();
173     }
174 
175     {
176         adios2::IO io = adios.DeclareIO("ReadIO");
177         if (!engineName.empty())
178         {
179             io.SetEngine(engineName);
180         }
181         else
182         {
183             io.SetEngine("BPFile");
184         }
185         adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read);
186 
187         auto var_local = io.InquireVariable<int32_t>("local");
188         auto var_localStr = io.InquireVariable<std::string>("localStr");
189 
190         auto var_iString = io.InquireVariable<std::string>("iString");
191         auto var_i8 = io.InquireVariable<int8_t>("i8");
192         auto var_i16 = io.InquireVariable<int16_t>("i16");
193         auto var_i32 = io.InquireVariable<int32_t>("i32");
194         auto var_i64 = io.InquireVariable<int64_t>("i64");
195         auto var_u8 = io.InquireVariable<uint8_t>("u8");
196         auto var_u16 = io.InquireVariable<uint16_t>("u16");
197         auto var_u32 = io.InquireVariable<uint32_t>("u32");
198         auto var_u64 = io.InquireVariable<uint64_t>("u64");
199         auto var_r32 = io.InquireVariable<float>("r32");
200         auto var_r64 = io.InquireVariable<double>("r64");
201         auto var_cr32 = io.InquireVariable<std::complex<float>>("cr32");
202         auto var_cr64 = io.InquireVariable<std::complex<double>>("cr64");
203 
204         const std::vector<std::vector<adios2::Variable<int8_t>::Info>>
205             allStepsBlocksInfoI8 = var_i8.AllStepsBlocksInfo();
206         const std::vector<std::vector<adios2::Variable<int16_t>::Info>>
207             allStepsBlocksInfoI16 = var_i16.AllStepsBlocksInfo();
208         const std::vector<std::vector<adios2::Variable<int32_t>::Info>>
209             allStepsBlocksInfoI32 = var_i32.AllStepsBlocksInfo();
210         const std::vector<std::vector<adios2::Variable<int64_t>::Info>>
211             allStepsBlocksInfoI64 = var_i64.AllStepsBlocksInfo();
212         const std::vector<std::vector<adios2::Variable<uint8_t>::Info>>
213             allStepsBlocksInfoU8 = var_u8.AllStepsBlocksInfo();
214         const std::vector<std::vector<adios2::Variable<uint16_t>::Info>>
215             allStepsBlocksInfoU16 = var_u16.AllStepsBlocksInfo();
216         const std::vector<std::vector<adios2::Variable<uint32_t>::Info>>
217             allStepsBlocksInfoU32 = var_u32.AllStepsBlocksInfo();
218         const std::vector<std::vector<adios2::Variable<uint64_t>::Info>>
219             allStepsBlocksInfoU64 = var_u64.AllStepsBlocksInfo();
220 
221         const std::vector<std::vector<adios2::Variable<float>::Info>>
222             allStepsBlocksInfoR32 = var_r32.AllStepsBlocksInfo();
223         const std::vector<std::vector<adios2::Variable<double>::Info>>
224             allStepsBlocksInfoR64 = var_r64.AllStepsBlocksInfo();
225 
226         const std::vector<
227             std::vector<adios2::Variable<std::complex<float>>::Info>>
228             allStepsBlocksInfoCR32 = var_cr32.AllStepsBlocksInfo();
229         const std::vector<
230             std::vector<adios2::Variable<std::complex<double>>::Info>>
231             allStepsBlocksInfoCR64 = var_cr64.AllStepsBlocksInfo();
232 
233         EXPECT_EQ(allStepsBlocksInfoI8.size(), NSteps);
234         EXPECT_EQ(allStepsBlocksInfoI16.size(), NSteps);
235         EXPECT_EQ(allStepsBlocksInfoI32.size(), NSteps);
236         EXPECT_EQ(allStepsBlocksInfoI64.size(), NSteps);
237         EXPECT_EQ(allStepsBlocksInfoU8.size(), NSteps);
238         EXPECT_EQ(allStepsBlocksInfoU16.size(), NSteps);
239         EXPECT_EQ(allStepsBlocksInfoU32.size(), NSteps);
240         EXPECT_EQ(allStepsBlocksInfoU64.size(), NSteps);
241         EXPECT_EQ(allStepsBlocksInfoR32.size(), NSteps);
242         EXPECT_EQ(allStepsBlocksInfoR64.size(), NSteps);
243         EXPECT_EQ(allStepsBlocksInfoCR32.size(), NSteps);
244         EXPECT_EQ(allStepsBlocksInfoCR64.size(), NSteps);
245 
246         CheckAllStepsBlockInfo1D<int8_t>(allStepsBlocksInfoI8, NSteps, Nx);
247         CheckAllStepsBlockInfo1D<int16_t>(allStepsBlocksInfoI16, NSteps, Nx);
248         CheckAllStepsBlockInfo1D<int32_t>(allStepsBlocksInfoI32, NSteps, Nx);
249         CheckAllStepsBlockInfo1D<int64_t>(allStepsBlocksInfoI64, NSteps, Nx);
250         CheckAllStepsBlockInfo1D<uint8_t>(allStepsBlocksInfoU8, NSteps, Nx);
251         CheckAllStepsBlockInfo1D<uint16_t>(allStepsBlocksInfoU16, NSteps, Nx);
252         CheckAllStepsBlockInfo1D<uint32_t>(allStepsBlocksInfoU32, NSteps, Nx);
253         CheckAllStepsBlockInfo1D<uint64_t>(allStepsBlocksInfoU64, NSteps, Nx);
254         CheckAllStepsBlockInfo1D<float>(allStepsBlocksInfoR32, NSteps, Nx);
255         CheckAllStepsBlockInfo1D<double>(allStepsBlocksInfoR64, NSteps, Nx);
256         CheckAllStepsBlockInfo1D<std::complex<float>>(allStepsBlocksInfoCR32,
257                                                       NSteps, Nx);
258         CheckAllStepsBlockInfo1D<std::complex<double>>(allStepsBlocksInfoCR64,
259                                                        NSteps, Nx);
260 
261         // TODO: other types
262 
263         SmallTestData testData;
264 
265         std::string IString;
266         std::array<int8_t, Nx> I8;
267         std::array<int16_t, Nx> I16;
268         std::array<int32_t, Nx> I32;
269         std::array<int64_t, Nx> I64;
270         std::array<uint8_t, Nx> U8;
271         std::array<uint16_t, Nx> U16;
272         std::array<uint32_t, Nx> U32;
273         std::array<uint64_t, Nx> U64;
274         std::array<float, Nx> R32;
275         std::array<double, Nx> R64;
276         std::array<std::complex<float>, Nx> CR32;
277         std::array<std::complex<double>, Nx> CR64;
278 
279         const size_t blockRank = static_cast<size_t>(mpiRank);
280         var_i8.SetBlockSelection(blockRank);
281         var_i16.SetBlockSelection(blockRank);
282         var_i32.SetBlockSelection(blockRank);
283         var_i64.SetBlockSelection(blockRank);
284 
285         var_u8.SetBlockSelection(blockRank);
286         var_u16.SetBlockSelection(blockRank);
287         var_u32.SetBlockSelection(blockRank);
288         var_u64.SetBlockSelection(blockRank);
289 
290         var_r32.SetBlockSelection(blockRank);
291         var_r64.SetBlockSelection(blockRank);
292 
293         var_cr32.SetBlockSelection(blockRank);
294         var_cr64.SetBlockSelection(blockRank);
295 
296         for (size_t t = 0; t < NSteps; ++t)
297         {
298             var_local.SetStepSelection({t, 1});
299             var_localStr.SetStepSelection({t, 1});
300 
301             var_i8.SetStepSelection({t, 1});
302             var_i16.SetStepSelection({t, 1});
303             var_i32.SetStepSelection({t, 1});
304             var_i64.SetStepSelection({t, 1});
305 
306             var_u8.SetStepSelection({t, 1});
307             var_u16.SetStepSelection({t, 1});
308             var_u32.SetStepSelection({t, 1});
309             var_u64.SetStepSelection({t, 1});
310 
311             var_r32.SetStepSelection({t, 1});
312             var_r64.SetStepSelection({t, 1});
313             var_cr32.SetStepSelection({t, 1});
314             var_cr64.SetStepSelection({t, 1});
315 
316             // Generate test data for each rank uniquely
317             SmallTestData currentTestData = generateNewSmallTestData(
318                 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
319 
320             bpReader.Get(var_iString, IString);
321 
322             bpReader.Get(var_i8, I8.data());
323             bpReader.Get(var_i16, I16.data());
324             bpReader.Get(var_i32, I32.data());
325             bpReader.Get(var_i64, I64.data());
326 
327             bpReader.Get(var_u8, U8.data());
328             bpReader.Get(var_u16, U16.data());
329             bpReader.Get(var_u32, U32.data());
330             bpReader.Get(var_u64, U64.data());
331 
332             bpReader.Get(var_r32, R32.data());
333             bpReader.Get(var_r64, R64.data());
334             bpReader.Get(var_cr32, CR32.data());
335             bpReader.Get(var_cr64, CR64.data());
336 
337             bpReader.PerformGets();
338 
339             EXPECT_EQ(IString, currentTestData.S1);
340 
341             for (size_t i = 0; i < Nx; ++i)
342             {
343                 std::stringstream ss;
344                 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
345                 std::string msg = ss.str();
346 
347                 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
348                 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
349                 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
350                 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
351                 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
352                 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
353                 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
354                 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
355                 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
356                 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
357                 EXPECT_EQ(CR32[i], currentTestData.CR32[i]) << msg;
358                 EXPECT_EQ(CR64[i], currentTestData.CR64[i]) << msg;
359             }
360 
361             const size_t domainSize = static_cast<size_t>(mpiSize);
362             for (size_t i = 0; i < domainSize; ++i)
363             {
364                 std::vector<int32_t> ILocal;
365                 std::vector<std::string> ILocalStr;
366 
367                 var_local.SetSelection({{i}, {domainSize - i}});
368                 var_localStr.SetSelection({{i}, {domainSize - i}});
369 
370                 bpReader.Get(var_local, ILocal);
371                 bpReader.Get(var_localStr, ILocalStr);
372                 bpReader.PerformGets();
373 
374                 /*std::cout << "rank=" << mpiRank << " local["
375                           << std::to_string(i) << ":"
376                           << std::to_string(domainSize) << "] = {";
377                 for (size_t j = i; j < domainSize; ++j)
378                 {
379                     std::cout << std::to_string(ILocal[j - i]) << " ";
380                 }
381                 std::cout << "]" << std::endl;*/
382 
383                 for (size_t j = i; j < domainSize; ++j)
384                 {
385                     std::stringstream ss;
386                     ss << "t=" << t << " i=" << i << " j=" << j;
387                     std::string msg = ss.str();
388 
389                     /*std::cout << "rank=" << mpiRank << " t=" << t << " i=" <<
390                        i
391                               << " j=" << j
392                               << " data=" << std::to_string(ILocal[j - i])
393                               << " expect = " << std::to_string(j + t)
394                               << std::endl;*/
395 
396                     EXPECT_EQ(ILocal[j - i], j + t) << msg;
397                     EXPECT_EQ(ILocalStr[j - i], std::to_string(j + t)) << msg;
398                 }
399             }
400         }
401         bpReader.Close();
402     }
403 }
404 
TEST_F(BPWriteReadBlockInfo,BPWriteReadBlockInfo2D2x4)405 TEST_F(BPWriteReadBlockInfo, BPWriteReadBlockInfo2D2x4)
406 {
407     const std::string fname("BPWriteReadBlockInfo2D2x4.bp");
408 
409     int mpiRank = 0, mpiSize = 1;
410     // Number of rows
411     const std::size_t Nx = 4;
412 
413     // Number of rows
414     const std::size_t Ny = 2;
415 
416     // Number of steps
417     const std::size_t NSteps = 3;
418 
419 #if ADIOS2_USE_MPI
420     MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
421     MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
422 #endif
423 
424     // Write test data using ADIOS2
425 
426 #if ADIOS2_USE_MPI
427     adios2::ADIOS adios(MPI_COMM_WORLD);
428 #else
429     adios2::ADIOS adios;
430 #endif
431     {
432         adios2::IO io = adios.DeclareIO("TestIO");
433 
434         const adios2::Dims shape{Ny, static_cast<size_t>(Nx * mpiSize)};
435         const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
436         const adios2::Dims count{Ny, Nx};
437 
438         auto var_iString = io.DefineVariable<std::string>("iString");
439         auto var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count);
440         auto var_i16 = io.DefineVariable<int16_t>("i16", shape, start, count);
441         auto var_i32 = io.DefineVariable<int32_t>("i32", shape, start, count);
442         auto var_i64 = io.DefineVariable<int64_t>("i64", shape, start, count);
443         auto var_u8 = io.DefineVariable<uint8_t>("u8", shape, start, count);
444         auto var_u16 = io.DefineVariable<uint16_t>("u16", shape, start, count);
445         auto var_u32 = io.DefineVariable<uint32_t>("u32", shape, start, count);
446         auto var_u64 = io.DefineVariable<uint64_t>("u64", shape, start, count);
447         auto var_r32 = io.DefineVariable<float>("r32", shape, start, count);
448         auto var_r64 = io.DefineVariable<double>("r64", shape, start, count);
449         auto var_cr32 =
450             io.DefineVariable<std::complex<float>>("cr32", shape, start, count);
451         auto var_cr64 = io.DefineVariable<std::complex<double>>("cr64", shape,
452                                                                 start, count);
453 
454         if (!engineName.empty())
455         {
456             io.SetEngine(engineName);
457         }
458         else
459         {
460             // Create the BP Engine
461             io.SetEngine("BPFile");
462         }
463         io.SetParameter("AggregatorRatio", "1");
464 
465         adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write);
466 
467         for (size_t step = 0; step < NSteps; ++step)
468         {
469             // Generate test data for each process uniquely
470             SmallTestData currentTestData = generateNewSmallTestData(
471                 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
472 
473             bpWriter.BeginStep();
474             bpWriter.Put(var_iString, currentTestData.S1);
475             bpWriter.Put(var_i8, currentTestData.I8.data());
476             bpWriter.Put(var_i16, currentTestData.I16.data());
477             bpWriter.Put(var_i32, currentTestData.I32.data());
478             bpWriter.Put(var_i64, currentTestData.I64.data());
479             bpWriter.Put(var_u8, currentTestData.U8.data());
480             bpWriter.Put(var_u16, currentTestData.U16.data());
481             bpWriter.Put(var_u32, currentTestData.U32.data());
482             bpWriter.Put(var_u64, currentTestData.U64.data());
483             bpWriter.Put(var_r32, currentTestData.R32.data());
484             bpWriter.Put(var_r64, currentTestData.R64.data());
485             bpWriter.Put(var_cr32, currentTestData.CR32.data());
486             bpWriter.Put(var_cr64, currentTestData.CR64.data());
487             bpWriter.EndStep();
488         }
489 
490         // Close the file
491         bpWriter.Close();
492     }
493 
494     {
495         adios2::IO io = adios.DeclareIO("ReadIO");
496         if (!engineName.empty())
497         {
498             io.SetEngine(engineName);
499         }
500         else
501         {
502             // Create the BP Engine
503             io.SetEngine("BPFile");
504         }
505         adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read);
506 
507         auto var_iString = io.InquireVariable<std::string>("iString");
508         auto var_i8 = io.InquireVariable<int8_t>("i8");
509         auto var_i16 = io.InquireVariable<int16_t>("i16");
510         auto var_i32 = io.InquireVariable<int32_t>("i32");
511         auto var_i64 = io.InquireVariable<int64_t>("i64");
512         auto var_u8 = io.InquireVariable<uint8_t>("u8");
513         auto var_u16 = io.InquireVariable<uint16_t>("u16");
514         auto var_u32 = io.InquireVariable<uint32_t>("u32");
515         auto var_u64 = io.InquireVariable<uint64_t>("u64");
516         auto var_r32 = io.InquireVariable<float>("r32");
517         auto var_r64 = io.InquireVariable<double>("r64");
518         auto var_cr32 = io.InquireVariable<std::complex<float>>("cr32");
519         auto var_cr64 = io.InquireVariable<std::complex<double>>("cr64");
520 
521         const std::vector<std::vector<adios2::Variable<int8_t>::Info>>
522             allStepsBlocksInfoI8 = var_i8.AllStepsBlocksInfo();
523         const std::vector<std::vector<adios2::Variable<int16_t>::Info>>
524             allStepsBlocksInfoI16 = var_i16.AllStepsBlocksInfo();
525         const std::vector<std::vector<adios2::Variable<int32_t>::Info>>
526             allStepsBlocksInfoI32 = var_i32.AllStepsBlocksInfo();
527         const std::vector<std::vector<adios2::Variable<int64_t>::Info>>
528             allStepsBlocksInfoI64 = var_i64.AllStepsBlocksInfo();
529         const std::vector<std::vector<adios2::Variable<uint8_t>::Info>>
530             allStepsBlocksInfoU8 = var_u8.AllStepsBlocksInfo();
531         const std::vector<std::vector<adios2::Variable<uint16_t>::Info>>
532             allStepsBlocksInfoU16 = var_u16.AllStepsBlocksInfo();
533         const std::vector<std::vector<adios2::Variable<uint32_t>::Info>>
534             allStepsBlocksInfoU32 = var_u32.AllStepsBlocksInfo();
535         const std::vector<std::vector<adios2::Variable<uint64_t>::Info>>
536             allStepsBlocksInfoU64 = var_u64.AllStepsBlocksInfo();
537         const std::vector<std::vector<adios2::Variable<float>::Info>>
538             allStepsBlocksInfoR32 = var_r32.AllStepsBlocksInfo();
539         const std::vector<std::vector<adios2::Variable<double>::Info>>
540             allStepsBlocksInfoR64 = var_r64.AllStepsBlocksInfo();
541         const std::vector<
542             std::vector<adios2::Variable<std::complex<float>>::Info>>
543             allStepsBlocksInfoCR32 = var_cr32.AllStepsBlocksInfo();
544         const std::vector<
545             std::vector<adios2::Variable<std::complex<double>>::Info>>
546             allStepsBlocksInfoCR64 = var_cr64.AllStepsBlocksInfo();
547 
548         EXPECT_EQ(allStepsBlocksInfoI8.size(), NSteps);
549         EXPECT_EQ(allStepsBlocksInfoI16.size(), NSteps);
550         EXPECT_EQ(allStepsBlocksInfoI32.size(), NSteps);
551         EXPECT_EQ(allStepsBlocksInfoI64.size(), NSteps);
552         EXPECT_EQ(allStepsBlocksInfoU8.size(), NSteps);
553         EXPECT_EQ(allStepsBlocksInfoU16.size(), NSteps);
554         EXPECT_EQ(allStepsBlocksInfoU32.size(), NSteps);
555         EXPECT_EQ(allStepsBlocksInfoU64.size(), NSteps);
556         EXPECT_EQ(allStepsBlocksInfoR32.size(), NSteps);
557         EXPECT_EQ(allStepsBlocksInfoR64.size(), NSteps);
558         EXPECT_EQ(allStepsBlocksInfoCR32.size(), NSteps);
559         EXPECT_EQ(allStepsBlocksInfoCR64.size(), NSteps);
560 
561         CheckAllStepsBlockInfo2D<int8_t>(allStepsBlocksInfoI8, NSteps, Nx, Ny);
562         CheckAllStepsBlockInfo2D<int16_t>(allStepsBlocksInfoI16, NSteps, Nx,
563                                           Ny);
564         CheckAllStepsBlockInfo2D<int32_t>(allStepsBlocksInfoI32, NSteps, Nx,
565                                           Ny);
566         CheckAllStepsBlockInfo2D<int64_t>(allStepsBlocksInfoI64, NSteps, Nx,
567                                           Ny);
568         CheckAllStepsBlockInfo2D<uint8_t>(allStepsBlocksInfoU8, NSteps, Nx, Ny);
569         CheckAllStepsBlockInfo2D<uint16_t>(allStepsBlocksInfoU16, NSteps, Nx,
570                                            Ny);
571         CheckAllStepsBlockInfo2D<uint32_t>(allStepsBlocksInfoU32, NSteps, Nx,
572                                            Ny);
573         CheckAllStepsBlockInfo2D<uint64_t>(allStepsBlocksInfoU64, NSteps, Nx,
574                                            Ny);
575         CheckAllStepsBlockInfo2D<float>(allStepsBlocksInfoR32, NSteps, Nx, Ny);
576         CheckAllStepsBlockInfo2D<double>(allStepsBlocksInfoR64, NSteps, Nx, Ny);
577         CheckAllStepsBlockInfo2D<std::complex<float>>(allStepsBlocksInfoCR32,
578                                                       NSteps, Nx, Ny);
579         CheckAllStepsBlockInfo2D<std::complex<double>>(allStepsBlocksInfoCR64,
580                                                        NSteps, Nx, Ny);
581 
582         std::string IString;
583         std::array<int8_t, Nx * Ny> I8;
584         std::array<int16_t, Nx * Ny> I16;
585         std::array<int32_t, Nx * Ny> I32;
586         std::array<int64_t, Nx * Ny> I64;
587         std::array<uint8_t, Nx * Ny> U8;
588         std::array<uint16_t, Nx * Ny> U16;
589         std::array<uint32_t, Nx * Ny> U32;
590         std::array<uint64_t, Nx * Ny> U64;
591         std::array<float, Nx * Ny> R32;
592         std::array<double, Nx * Ny> R64;
593         std::array<std::complex<float>, Nx * Ny> CR32;
594         std::array<std::complex<double>, Nx * Ny> CR64;
595 
596         const size_t blockRank = static_cast<size_t>(mpiRank);
597         var_i8.SetBlockSelection(blockRank);
598         var_i16.SetBlockSelection(blockRank);
599         var_i32.SetBlockSelection(blockRank);
600         var_i64.SetBlockSelection(blockRank);
601 
602         var_u8.SetBlockSelection(blockRank);
603         var_u16.SetBlockSelection(blockRank);
604         var_u32.SetBlockSelection(blockRank);
605         var_u64.SetBlockSelection(blockRank);
606 
607         var_r32.SetBlockSelection(blockRank);
608         var_r64.SetBlockSelection(blockRank);
609         var_cr32.SetBlockSelection(blockRank);
610         var_cr64.SetBlockSelection(blockRank);
611 
612         for (size_t t = 0; t < NSteps; ++t)
613         {
614             var_i8.SetStepSelection({t, 1});
615             var_i16.SetStepSelection({t, 1});
616             var_i32.SetStepSelection({t, 1});
617             var_i64.SetStepSelection({t, 1});
618 
619             var_u8.SetStepSelection({t, 1});
620             var_u16.SetStepSelection({t, 1});
621             var_u32.SetStepSelection({t, 1});
622             var_u64.SetStepSelection({t, 1});
623 
624             var_r32.SetStepSelection({t, 1});
625             var_r64.SetStepSelection({t, 1});
626             var_cr32.SetStepSelection({t, 1});
627             var_cr64.SetStepSelection({t, 1});
628 
629             bpReader.Get(var_iString, IString);
630 
631             bpReader.Get(var_i8, I8.data());
632             bpReader.Get(var_i16, I16.data());
633             bpReader.Get(var_i32, I32.data());
634             bpReader.Get(var_i64, I64.data());
635 
636             bpReader.Get(var_u8, U8.data());
637             bpReader.Get(var_u16, U16.data());
638             bpReader.Get(var_u32, U32.data());
639             bpReader.Get(var_u64, U64.data());
640 
641             bpReader.Get(var_r32, R32.data());
642             bpReader.Get(var_r64, R64.data());
643             bpReader.Get(var_cr32, CR32.data());
644             bpReader.Get(var_cr64, CR64.data());
645 
646             bpReader.PerformGets();
647 
648             // Generate test data for each rank uniquely
649             SmallTestData currentTestData = generateNewSmallTestData(
650                 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
651 
652             EXPECT_EQ(IString, currentTestData.S1);
653 
654             for (size_t i = 0; i < Nx * Ny; ++i)
655             {
656                 std::stringstream ss;
657                 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
658                 std::string msg = ss.str();
659 
660                 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
661                 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
662                 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
663                 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
664                 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
665                 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
666                 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
667                 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
668                 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
669                 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
670                 EXPECT_EQ(CR32[i], currentTestData.CR32[i]) << msg;
671                 EXPECT_EQ(CR64[i], currentTestData.CR64[i]) << msg;
672             }
673         }
674         bpReader.Close();
675     }
676 }
677 
main(int argc,char ** argv)678 int main(int argc, char **argv)
679 {
680 #if ADIOS2_USE_MPI
681     MPI_Init(nullptr, nullptr);
682 #endif
683 
684     int result;
685     ::testing::InitGoogleTest(&argc, argv);
686 
687     if (argc > 1)
688     {
689         engineName = std::string(argv[1]);
690     }
691     result = RUN_ALL_TESTS();
692 
693 #if ADIOS2_USE_MPI
694     MPI_Finalize();
695 #endif
696 
697     return result;
698 }
699