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 BPWriteReadTestADIOS2 : public ::testing::Test
21 {
22 public:
23     BPWriteReadTestADIOS2() = default;
24 
25     SmallTestData m_TestData;
26 };
27 
28 //******************************************************************************
29 // 1D 1x8 test data
30 //******************************************************************************
31 
32 // ADIOS2 BP write, native ADIOS1 read
TEST_F(BPWriteReadTestADIOS2,ADIOS2BPWriteRead1D8)33 TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8)
34 {
35     // Each process would write a 1x8 array and all processes would
36     // form a mpiSize * Nx 1D array
37     const std::string fname("ADIOS2BPWriteRead1D8.bp");
38 
39     int mpiRank = 0, mpiSize = 1;
40     // Number of rows
41     const size_t Nx = 8;
42 
43     // Number of steps
44     const size_t NSteps = 3;
45 
46 #if ADIOS2_USE_MPI
47     MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
48     MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
49 #endif
50 
51     // Write test data using BP
52 
53 #if ADIOS2_USE_MPI
54     adios2::ADIOS adios(MPI_COMM_WORLD);
55 #else
56     adios2::ADIOS adios;
57 #endif
58     {
59         adios2::IO io = adios.DeclareIO("TestIO");
60 
61         // Test setting parameters
62         {
63             io.SetParameter("ProfileUnits", "Microseconds");
64             io.SetParameters("Threads=2, CollectiveMetadata = OFF");
65             adios2::Params parameters = io.Parameters();
66 
67             auto ProfileUnits = parameters.find("ProfileUnits");
68             EXPECT_NE(ProfileUnits, parameters.end());
69             EXPECT_EQ(ProfileUnits->second, "Microseconds");
70 
71             auto Threads = parameters.find("Threads");
72             EXPECT_NE(Threads, parameters.end());
73             EXPECT_EQ(Threads->second, "2");
74 
75             auto CollectiveMetadata = parameters.find("CollectiveMetadata");
76             EXPECT_NE(CollectiveMetadata, parameters.end());
77             EXPECT_EQ(CollectiveMetadata->second, "OFF");
78 
79             io.ClearParameters();
80 
81             // should not find parameters anymore
82             parameters = io.Parameters();
83             CollectiveMetadata = parameters.find("CollectiveMetadata");
84             EXPECT_EQ(CollectiveMetadata, parameters.end());
85         }
86 
87         // Declare 1D variables (NumOfProcesses * Nx)
88         // The local process' part (start, count) can be defined now or later
89         // before Write().
90         {
91             const adios2::Dims shape{static_cast<size_t>(Nx * mpiSize)};
92             const adios2::Dims start{static_cast<size_t>(Nx * mpiRank)};
93             const adios2::Dims count{Nx};
94 
95             auto var_iString = io.DefineVariable<std::string>("iString");
96             auto var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count);
97             auto var_i16 =
98                 io.DefineVariable<int16_t>("i16", shape, start, count);
99             auto var_i32 =
100                 io.DefineVariable<int32_t>("i32", shape, start, count);
101             auto var_i64 =
102                 io.DefineVariable<int64_t>("i64", shape, start, count);
103             auto var_u8 = io.DefineVariable<uint8_t>("u8", shape, start, count);
104             auto var_u16 =
105                 io.DefineVariable<uint16_t>("u16", shape, start, count);
106             auto var_u32 =
107                 io.DefineVariable<uint32_t>("u32", shape, start, count);
108             auto var_u64 =
109                 io.DefineVariable<uint64_t>("u64", shape, start, count);
110             auto var_r32 = io.DefineVariable<float>("r32", shape, start, count);
111             auto var_r64 =
112                 io.DefineVariable<double>("r64", shape, start, count);
113         }
114 
115         if (!engineName.empty())
116         {
117             io.SetEngine(engineName);
118         }
119         else
120         {
121             // Create the BP Engine
122             io.SetEngine("BPFile");
123         }
124 
125         io.SetParameter("AsyncThreads", "0");
126         io.AddTransport("file");
127 
128         // QUESTION: It seems that BPFilterWriter cannot overwrite existing
129         // files
130         // Ex. if you tune Nx and NSteps, the test would fail. But if you clear
131         // the cache in
132         // ${adios2Build}/testing/adios2/engine/bp/ADIOS2BPWriteADIOS1Read1D8.bp.dir,
133         // then it works
134         adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write);
135 
136         for (size_t step = 0; step < NSteps; ++step)
137         {
138             // Generate test data for each process uniquely
139             SmallTestData currentTestData = generateNewSmallTestData(
140                 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
141 
142             // Retrieve the variables that previously went out of scope
143             auto var_iString = io.InquireVariable<std::string>("iString");
144             auto var_i8 = io.InquireVariable<int8_t>("i8");
145             auto var_i16 = io.InquireVariable<int16_t>("i16");
146             auto var_i32 = io.InquireVariable<int32_t>("i32");
147             auto var_i64 = io.InquireVariable<int64_t>("i64");
148             auto var_u8 = io.InquireVariable<uint8_t>("u8");
149             auto var_u16 = io.InquireVariable<uint16_t>("u16");
150             auto var_u32 = io.InquireVariable<uint32_t>("u32");
151             auto var_u64 = io.InquireVariable<uint64_t>("u64");
152             auto var_r32 = io.InquireVariable<float>("r32");
153             auto var_r64 = io.InquireVariable<double>("r64");
154 
155             // Make a 1D selection to describe the local dimensions of the
156             // variable we write and its offsets in the global spaces
157             adios2::Box<adios2::Dims> sel({mpiRank * Nx}, {Nx});
158 
159             EXPECT_THROW(var_iString.SetSelection(sel), std::invalid_argument);
160             var_i8.SetSelection(sel);
161             var_i16.SetSelection(sel);
162             var_i32.SetSelection(sel);
163             var_i64.SetSelection(sel);
164             var_u8.SetSelection(sel);
165             var_u16.SetSelection(sel);
166             var_u32.SetSelection(sel);
167             var_u64.SetSelection(sel);
168             var_r32.SetSelection(sel);
169             var_r64.SetSelection(sel);
170 
171             // Write each one
172             // fill in the variable with values from starting index to
173             // starting index + count
174             bpWriter.BeginStep();
175 
176             bpWriter.Put(var_iString, currentTestData.S1);
177             bpWriter.Put(var_i8, currentTestData.I8.data());
178             bpWriter.Put(var_i16, currentTestData.I16.data());
179             bpWriter.Put(var_i32, currentTestData.I32.data());
180             bpWriter.Put(var_i64, currentTestData.I64.data());
181             bpWriter.Put(var_u8, currentTestData.U8.data());
182             bpWriter.Put(var_u16, currentTestData.U16.data());
183             bpWriter.Put(var_u32, currentTestData.U32.data());
184             bpWriter.Put(var_u64, currentTestData.U64.data());
185             bpWriter.Put(var_r32, currentTestData.R32.data());
186             bpWriter.Put(var_r64, currentTestData.R64.data());
187             bpWriter.PerformPuts();
188 
189             bpWriter.EndStep();
190         }
191 
192         // Close the file
193         bpWriter.Close();
194     }
195 
196     {
197         adios2::IO io = adios.DeclareIO("ReadIO");
198 
199         if (!engineName.empty())
200         {
201             io.SetEngine(engineName);
202         }
203 
204         adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read);
205 
206         EXPECT_EQ(bpReader.Steps(), NSteps);
207 
208         auto var_iString = io.InquireVariable<std::string>("iString");
209         EXPECT_TRUE(var_iString);
210         ASSERT_EQ(var_iString.Shape().size(), 0);
211         ASSERT_EQ(var_iString.Steps(), NSteps);
212 
213         auto var_i8 = io.InquireVariable<int8_t>("i8");
214         EXPECT_TRUE(var_i8);
215         ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
216         ASSERT_EQ(var_i8.Steps(), NSteps);
217         ASSERT_EQ(var_i8.Shape()[0], mpiSize * Nx);
218 
219         auto var_i16 = io.InquireVariable<int16_t>("i16");
220         EXPECT_TRUE(var_i16);
221         ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
222         ASSERT_EQ(var_i16.Steps(), NSteps);
223         ASSERT_EQ(var_i16.Shape()[0], mpiSize * Nx);
224 
225         auto var_i32 = io.InquireVariable<int32_t>("i32");
226         EXPECT_TRUE(var_i32);
227         ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
228         ASSERT_EQ(var_i32.Steps(), NSteps);
229         ASSERT_EQ(var_i32.Shape()[0], mpiSize * Nx);
230 
231         auto var_i64 = io.InquireVariable<int64_t>("i64");
232         EXPECT_TRUE(var_i64);
233         ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
234         ASSERT_EQ(var_i64.Steps(), NSteps);
235         ASSERT_EQ(var_i64.Shape()[0], mpiSize * Nx);
236 
237         auto var_u8 = io.InquireVariable<uint8_t>("u8");
238         EXPECT_TRUE(var_u8);
239         ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
240         ASSERT_EQ(var_u8.Steps(), NSteps);
241         ASSERT_EQ(var_u8.Shape()[0], mpiSize * Nx);
242 
243         auto var_u16 = io.InquireVariable<uint16_t>("u16");
244         EXPECT_TRUE(var_u16);
245         ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
246         ASSERT_EQ(var_u16.Steps(), NSteps);
247         ASSERT_EQ(var_u16.Shape()[0], mpiSize * Nx);
248 
249         auto var_u32 = io.InquireVariable<uint32_t>("u32");
250         EXPECT_TRUE(var_u32);
251         ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
252         ASSERT_EQ(var_u32.Steps(), NSteps);
253         ASSERT_EQ(var_u32.Shape()[0], mpiSize * Nx);
254 
255         auto var_u64 = io.InquireVariable<uint64_t>("u64");
256         EXPECT_TRUE(var_u64);
257         ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
258         ASSERT_EQ(var_u64.Steps(), NSteps);
259         ASSERT_EQ(var_u64.Shape()[0], mpiSize * Nx);
260 
261         auto var_r32 = io.InquireVariable<float>("r32");
262         EXPECT_TRUE(var_r32);
263         ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
264         ASSERT_EQ(var_r32.Steps(), NSteps);
265         ASSERT_EQ(var_r32.Shape()[0], mpiSize * Nx);
266 
267         auto var_r64 = io.InquireVariable<double>("r64");
268         EXPECT_TRUE(var_r64);
269         ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
270         ASSERT_EQ(var_r64.Steps(), NSteps);
271         ASSERT_EQ(var_r64.Shape()[0], mpiSize * Nx);
272 
273         // TODO: other types
274 
275         SmallTestData testData;
276 
277         std::string IString;
278         std::array<int8_t, Nx> I8;
279         std::array<int16_t, Nx> I16;
280         std::array<int32_t, Nx> I32;
281         std::array<int64_t, Nx> I64;
282         std::array<uint8_t, Nx> U8;
283         std::array<uint16_t, Nx> U16;
284         std::array<uint32_t, Nx> U32;
285         std::array<uint64_t, Nx> U64;
286         std::array<float, Nx> R32;
287         std::array<double, Nx> R64;
288 
289         const adios2::Dims start{mpiRank * Nx};
290         const adios2::Dims count{Nx};
291 
292         const adios2::Box<adios2::Dims> sel(start, count);
293 
294         var_i8.SetSelection(sel);
295         var_i16.SetSelection(sel);
296         var_i32.SetSelection(sel);
297         var_i64.SetSelection(sel);
298 
299         var_u8.SetSelection(sel);
300         var_u16.SetSelection(sel);
301         var_u32.SetSelection(sel);
302         var_u64.SetSelection(sel);
303 
304         var_r32.SetSelection(sel);
305         var_r64.SetSelection(sel);
306 
307         for (size_t t = 0; t < NSteps; ++t)
308         {
309             var_i8.SetStepSelection({t, 1});
310             var_i16.SetStepSelection({t, 1});
311             var_i32.SetStepSelection({t, 1});
312             var_i64.SetStepSelection({t, 1});
313 
314             var_u8.SetStepSelection({t, 1});
315             var_u16.SetStepSelection({t, 1});
316             var_u32.SetStepSelection({t, 1});
317             var_u64.SetStepSelection({t, 1});
318 
319             var_r32.SetStepSelection({t, 1});
320             var_r64.SetStepSelection({t, 1});
321 
322             // Generate test data for each rank uniquely
323             SmallTestData currentTestData = generateNewSmallTestData(
324                 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
325 
326             bpReader.Get(var_iString, IString);
327 
328             bpReader.Get(var_i8, I8.data());
329             bpReader.Get(var_i16, I16.data());
330             bpReader.Get(var_i32, I32.data());
331             bpReader.Get(var_i64, I64.data());
332 
333             bpReader.Get(var_u8, U8.data());
334             bpReader.Get(var_u16, U16.data());
335             bpReader.Get(var_u32, U32.data());
336             bpReader.Get(var_u64, U64.data());
337 
338             bpReader.Get(var_r32, R32.data());
339             bpReader.Get(var_r64, R64.data());
340 
341             bpReader.PerformGets();
342 
343             EXPECT_EQ(IString, currentTestData.S1);
344 
345             for (size_t i = 0; i < Nx; ++i)
346             {
347                 std::stringstream ss;
348                 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
349                 std::string msg = ss.str();
350 
351                 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
352                 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
353                 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
354                 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
355                 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
356                 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
357                 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
358                 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
359                 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
360                 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
361             }
362         }
363         bpReader.Close();
364     }
365 }
366 
367 //******************************************************************************
368 // 2D 2x4 test data
369 //******************************************************************************
370 
371 // ADIOS2 BP write, native ADIOS1 read
TEST_F(BPWriteReadTestADIOS2,ADIOS2BPWriteRead2D2x4)372 TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead2D2x4)
373 {
374     // Each process would write a 2x4 array and all processes would
375     // form a 2D 2 * (numberOfProcess*Nx) matrix where Nx is 4 here
376     const std::string fname("ADIOS2BPWriteRead2D2x4Test.bp");
377 
378     int mpiRank = 0, mpiSize = 1;
379     // Number of rows
380     const std::size_t Nx = 4;
381 
382     // Number of rows
383     const std::size_t Ny = 2;
384 
385     // Number of steps
386     const std::size_t NSteps = 3;
387 
388 #if ADIOS2_USE_MPI
389     MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
390     MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
391 #endif
392 
393     // Write test data using ADIOS2
394 
395 #if ADIOS2_USE_MPI
396     adios2::ADIOS adios(MPI_COMM_WORLD);
397 #else
398     adios2::ADIOS adios;
399 #endif
400     {
401         adios2::IO io = adios.DeclareIO("TestIO");
402 
403         // Declare 2D variables (Ny * (NumOfProcesses * Nx))
404         // The local process' part (start, count) can be defined now or later
405         // before Write().
406         {
407             const adios2::Dims shape{Ny, static_cast<size_t>(Nx * mpiSize)};
408             const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
409             const adios2::Dims count{Ny, Nx};
410 
411             auto var_iString = io.DefineVariable<std::string>("iString");
412             auto var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count);
413             auto var_i16 =
414                 io.DefineVariable<int16_t>("i16", shape, start, count);
415             auto var_i32 =
416                 io.DefineVariable<int32_t>("i32", shape, start, count);
417             auto var_i64 =
418                 io.DefineVariable<int64_t>("i64", shape, start, count);
419             auto var_u8 = io.DefineVariable<uint8_t>("u8", shape, start, count);
420             auto var_u16 =
421                 io.DefineVariable<uint16_t>("u16", shape, start, count);
422             auto var_u32 =
423                 io.DefineVariable<uint32_t>("u32", shape, start, count);
424             auto var_u64 =
425                 io.DefineVariable<uint64_t>("u64", shape, start, count);
426             auto var_r32 = io.DefineVariable<float>("r32", shape, start, count);
427             auto var_r64 =
428                 io.DefineVariable<double>("r64", shape, start, count);
429         }
430 
431         if (!engineName.empty())
432         {
433             io.SetEngine(engineName);
434         }
435         else
436         {
437             // Create the BP Engine
438             io.SetEngine("BPFile");
439         }
440         io.AddTransport("file");
441 
442         adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write);
443 
444         for (size_t step = 0; step < NSteps; ++step)
445         {
446             // Generate test data for each process uniquely
447             SmallTestData currentTestData = generateNewSmallTestData(
448                 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
449 
450             // Retrieve the variables that previously went out of scope
451             auto var_iString = io.InquireVariable<std::string>("iString");
452             auto var_i8 = io.InquireVariable<int8_t>("i8");
453             auto var_i16 = io.InquireVariable<int16_t>("i16");
454             auto var_i32 = io.InquireVariable<int32_t>("i32");
455             auto var_i64 = io.InquireVariable<int64_t>("i64");
456             auto var_u8 = io.InquireVariable<uint8_t>("u8");
457             auto var_u16 = io.InquireVariable<uint16_t>("u16");
458             auto var_u32 = io.InquireVariable<uint32_t>("u32");
459             auto var_u64 = io.InquireVariable<uint64_t>("u64");
460             auto var_r32 = io.InquireVariable<float>("r32");
461             auto var_r64 = io.InquireVariable<double>("r64");
462 
463             // Make a 2D selection to describe the local dimensions of the
464             // variable we write and its offsets in the global spaces
465             adios2::Box<adios2::Dims> sel(
466                 {0, static_cast<size_t>(mpiRank * Nx)}, {Ny, Nx});
467             var_i8.SetSelection(sel);
468             var_i16.SetSelection(sel);
469             var_i32.SetSelection(sel);
470             var_i64.SetSelection(sel);
471             var_u8.SetSelection(sel);
472             var_u16.SetSelection(sel);
473             var_u32.SetSelection(sel);
474             var_u64.SetSelection(sel);
475             var_r32.SetSelection(sel);
476             var_r64.SetSelection(sel);
477 
478             // Write each one
479             // fill in the variable with values from starting index to
480             // starting index + count
481             bpWriter.BeginStep();
482             bpWriter.Put(var_iString, currentTestData.S1);
483             bpWriter.Put(var_i8, currentTestData.I8.data());
484             bpWriter.Put(var_i16, currentTestData.I16.data());
485             bpWriter.Put(var_i32, currentTestData.I32.data());
486             bpWriter.Put(var_i64, currentTestData.I64.data());
487             bpWriter.Put(var_u8, currentTestData.U8.data());
488             bpWriter.Put(var_u16, currentTestData.U16.data());
489             bpWriter.Put(var_u32, currentTestData.U32.data());
490             bpWriter.Put(var_u64, currentTestData.U64.data());
491             bpWriter.Put(var_r32, currentTestData.R32.data());
492             bpWriter.Put(var_r64, currentTestData.R64.data());
493             bpWriter.PerformPuts();
494 
495             bpWriter.EndStep();
496         }
497 
498         // Close the file
499         bpWriter.Close();
500     }
501 
502     {
503         adios2::IO io = adios.DeclareIO("ReadIO");
504 
505         if (!engineName.empty())
506         {
507             io.SetEngine(engineName);
508         }
509 
510         adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read);
511 
512         EXPECT_EQ(bpReader.Steps(), NSteps);
513         auto var_iString = io.InquireVariable<std::string>("iString");
514         EXPECT_TRUE(var_iString);
515         ASSERT_EQ(var_iString.Shape().size(), 0);
516         ASSERT_EQ(var_iString.Steps(), NSteps);
517 
518         auto var_i8 = io.InquireVariable<int8_t>("i8");
519         EXPECT_TRUE(var_i8);
520         ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
521         ASSERT_EQ(var_i8.Steps(), NSteps);
522         ASSERT_EQ(var_i8.Shape()[0], Ny);
523         ASSERT_EQ(var_i8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
524 
525         auto var_i16 = io.InquireVariable<int16_t>("i16");
526         EXPECT_TRUE(var_i16);
527         ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
528         ASSERT_EQ(var_i16.Steps(), NSteps);
529         ASSERT_EQ(var_i16.Shape()[0], Ny);
530         ASSERT_EQ(var_i16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
531 
532         auto var_i32 = io.InquireVariable<int32_t>("i32");
533         EXPECT_TRUE(var_i32);
534         ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
535         ASSERT_EQ(var_i32.Steps(), NSteps);
536         ASSERT_EQ(var_i32.Shape()[0], Ny);
537         ASSERT_EQ(var_i32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
538 
539         auto var_i64 = io.InquireVariable<int64_t>("i64");
540         EXPECT_TRUE(var_i64);
541         ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
542         ASSERT_EQ(var_i64.Steps(), NSteps);
543         ASSERT_EQ(var_i64.Shape()[0], Ny);
544         ASSERT_EQ(var_i64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
545 
546         auto var_u8 = io.InquireVariable<uint8_t>("u8");
547         EXPECT_TRUE(var_u8);
548         ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
549         ASSERT_EQ(var_u8.Steps(), NSteps);
550         ASSERT_EQ(var_u8.Shape()[0], Ny);
551         ASSERT_EQ(var_u8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
552 
553         auto var_u16 = io.InquireVariable<uint16_t>("u16");
554         EXPECT_TRUE(var_u16);
555         ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
556         ASSERT_EQ(var_u16.Steps(), NSteps);
557         ASSERT_EQ(var_u16.Shape()[0], Ny);
558         ASSERT_EQ(var_u16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
559 
560         auto var_u32 = io.InquireVariable<uint32_t>("u32");
561         EXPECT_TRUE(var_u32);
562         ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
563         ASSERT_EQ(var_u32.Steps(), NSteps);
564         ASSERT_EQ(var_u32.Shape()[0], Ny);
565         ASSERT_EQ(var_u32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
566 
567         auto var_u64 = io.InquireVariable<uint64_t>("u64");
568         EXPECT_TRUE(var_u64);
569         ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
570         ASSERT_EQ(var_u64.Steps(), NSteps);
571         ASSERT_EQ(var_u64.Shape()[0], Ny);
572         ASSERT_EQ(var_u64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
573 
574         auto var_r32 = io.InquireVariable<float>("r32");
575         EXPECT_TRUE(var_r32);
576         ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
577         ASSERT_EQ(var_r32.Steps(), NSteps);
578         ASSERT_EQ(var_r32.Shape()[0], Ny);
579         ASSERT_EQ(var_r32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
580 
581         auto var_r64 = io.InquireVariable<double>("r64");
582         EXPECT_TRUE(var_r64);
583         ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
584         ASSERT_EQ(var_r64.Steps(), NSteps);
585         ASSERT_EQ(var_r64.Shape()[0], Ny);
586         ASSERT_EQ(var_r64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
587 
588         std::string IString;
589         std::array<int8_t, Nx * Ny> I8;
590         std::array<int16_t, Nx * Ny> I16;
591         std::array<int32_t, Nx * Ny> I32;
592         std::array<int64_t, Nx * Ny> I64;
593         std::array<uint8_t, Nx * Ny> U8;
594         std::array<uint16_t, Nx * Ny> U16;
595         std::array<uint32_t, Nx * Ny> U32;
596         std::array<uint64_t, Nx * Ny> U64;
597         std::array<float, Nx * Ny> R32;
598         std::array<double, Nx * Ny> R64;
599 
600         const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
601         const adios2::Dims count{Ny, Nx};
602 
603         const adios2::Box<adios2::Dims> sel(start, count);
604 
605         var_i8.SetSelection(sel);
606         var_i16.SetSelection(sel);
607         var_i32.SetSelection(sel);
608         var_i64.SetSelection(sel);
609 
610         var_u8.SetSelection(sel);
611         var_u16.SetSelection(sel);
612         var_u32.SetSelection(sel);
613         var_u64.SetSelection(sel);
614 
615         var_r32.SetSelection(sel);
616         var_r64.SetSelection(sel);
617 
618         for (size_t t = 0; t < NSteps; ++t)
619         {
620             var_i8.SetStepSelection({t, 1});
621             var_i16.SetStepSelection({t, 1});
622             var_i32.SetStepSelection({t, 1});
623             var_i64.SetStepSelection({t, 1});
624 
625             var_u8.SetStepSelection({t, 1});
626             var_u16.SetStepSelection({t, 1});
627             var_u32.SetStepSelection({t, 1});
628             var_u64.SetStepSelection({t, 1});
629 
630             var_r32.SetStepSelection({t, 1});
631             var_r64.SetStepSelection({t, 1});
632 
633             bpReader.Get(var_iString, IString);
634 
635             bpReader.Get(var_i8, I8.data());
636             bpReader.Get(var_i16, I16.data());
637             bpReader.Get(var_i32, I32.data());
638             bpReader.Get(var_i64, I64.data());
639 
640             bpReader.Get(var_u8, U8.data());
641             bpReader.Get(var_u16, U16.data());
642             bpReader.Get(var_u32, U32.data());
643             bpReader.Get(var_u64, U64.data());
644 
645             bpReader.Get(var_r32, R32.data());
646             bpReader.Get(var_r64, R64.data());
647 
648             bpReader.PerformGets();
649 
650             // Generate test data for each rank uniquely
651             SmallTestData currentTestData = generateNewSmallTestData(
652                 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
653 
654             EXPECT_EQ(IString, currentTestData.S1);
655 
656             for (size_t i = 0; i < Nx * Ny; ++i)
657             {
658                 std::stringstream ss;
659                 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
660                 std::string msg = ss.str();
661 
662                 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
663                 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
664                 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
665                 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
666                 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
667                 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
668                 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
669                 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
670                 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
671                 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
672             }
673         }
674         bpReader.Close();
675     }
676 }
677 
678 //******************************************************************************
679 // 2D 4x2 test data
680 //******************************************************************************
681 
TEST_F(BPWriteReadTestADIOS2,ADIOS2BPWriteRead2D4x2)682 TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead2D4x2)
683 {
684     // Each process would write a 4x2 array and all processes would
685     // form a 2D 4 * (NumberOfProcess * Nx) matrix where Nx is 2 here
686     const std::string fname("ADIOS2BPWriteRead2D4x2Test.bp");
687 
688     int mpiRank = 0, mpiSize = 1;
689     // Number of rows
690     const std::size_t Nx = 2;
691     // Number of cols
692     const std::size_t Ny = 4;
693 
694     // Number of steps
695     const std::size_t NSteps = 3;
696 
697 #if ADIOS2_USE_MPI
698     MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
699     MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
700 #endif
701 
702     // Write test data using ADIOS2
703 
704 #if ADIOS2_USE_MPI
705     adios2::ADIOS adios(MPI_COMM_WORLD);
706 #else
707     adios2::ADIOS adios;
708 #endif
709     {
710         adios2::IO io = adios.DeclareIO("TestIO");
711 
712         // Declare 2D variables (4 * (NumberOfProcess * Nx))
713         // The local process' part (start, count) can be defined now or later
714         // before Write().
715         {
716             adios2::Dims shape{static_cast<unsigned int>(Ny),
717                                static_cast<unsigned int>(mpiSize * Nx)};
718             adios2::Dims start{static_cast<unsigned int>(0),
719                                static_cast<unsigned int>(mpiRank * Nx)};
720             adios2::Dims count{static_cast<unsigned int>(Ny),
721                                static_cast<unsigned int>(Nx)};
722             auto var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count);
723             auto var_i16 =
724                 io.DefineVariable<int16_t>("i16", shape, start, count);
725             auto var_i32 =
726                 io.DefineVariable<int32_t>("i32", shape, start, count);
727             auto var_i64 =
728                 io.DefineVariable<int64_t>("i64", shape, start, count);
729             auto var_u8 = io.DefineVariable<uint8_t>("u8", shape, start, count);
730             auto var_u16 =
731                 io.DefineVariable<uint16_t>("u16", shape, start, count);
732             auto var_u32 =
733                 io.DefineVariable<uint32_t>("u32", shape, start, count);
734             auto var_u64 =
735                 io.DefineVariable<uint64_t>("u64", shape, start, count);
736             auto var_r32 = io.DefineVariable<float>("r32", shape, start, count);
737             auto var_r64 =
738                 io.DefineVariable<double>("r64", shape, start, count);
739         }
740 
741         if (!engineName.empty())
742         {
743             io.SetEngine(engineName);
744         }
745         else
746         {
747             // Create the BP Engine
748             io.SetEngine("BPFile");
749         }
750 
751         io.AddTransport("file");
752 
753         adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write);
754 
755         for (size_t step = 0; step < NSteps; ++step)
756         {
757             // Generate test data for each process uniquely
758             SmallTestData currentTestData = generateNewSmallTestData(
759                 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
760 
761             // Retrieve the variables that previously went out of scope
762             auto var_i8 = io.InquireVariable<int8_t>("i8");
763             auto var_i16 = io.InquireVariable<int16_t>("i16");
764             auto var_i32 = io.InquireVariable<int32_t>("i32");
765             auto var_i64 = io.InquireVariable<int64_t>("i64");
766             auto var_u8 = io.InquireVariable<uint8_t>("u8");
767             auto var_u16 = io.InquireVariable<uint16_t>("u16");
768             auto var_u32 = io.InquireVariable<uint32_t>("u32");
769             auto var_u64 = io.InquireVariable<uint64_t>("u64");
770             auto var_r32 = io.InquireVariable<float>("r32");
771             auto var_r64 = io.InquireVariable<double>("r64");
772 
773             // Make a 2D selection to describe the local dimensions of the
774             // variable we write and its offsets in the global spaces
775             adios2::Box<adios2::Dims> sel(
776                 {0, static_cast<unsigned int>(mpiRank * Nx)}, {Ny, Nx});
777             var_i8.SetSelection(sel);
778             var_i16.SetSelection(sel);
779             var_i32.SetSelection(sel);
780             var_i64.SetSelection(sel);
781             var_u8.SetSelection(sel);
782             var_u16.SetSelection(sel);
783             var_u32.SetSelection(sel);
784             var_u64.SetSelection(sel);
785             var_r32.SetSelection(sel);
786             var_r64.SetSelection(sel);
787 
788             // Write each one
789             // fill in the variable with values from starting index to
790             // starting index + count
791             bpWriter.BeginStep();
792             bpWriter.Put(var_i8, currentTestData.I8.data());
793             bpWriter.Put(var_i16, currentTestData.I16.data());
794             bpWriter.Put(var_i32, currentTestData.I32.data());
795             bpWriter.Put(var_i64, currentTestData.I64.data());
796             bpWriter.Put(var_u8, currentTestData.U8.data());
797             bpWriter.Put(var_u16, currentTestData.U16.data());
798             bpWriter.Put(var_u32, currentTestData.U32.data());
799             bpWriter.Put(var_u64, currentTestData.U64.data());
800             bpWriter.Put(var_r32, currentTestData.R32.data());
801             bpWriter.Put(var_r64, currentTestData.R64.data());
802             bpWriter.EndStep();
803         }
804 
805         // Close the file
806         bpWriter.Close();
807     }
808 
809     {
810         adios2::IO io = adios.DeclareIO("ReadIO");
811 
812         if (!engineName.empty())
813         {
814             io.SetEngine(engineName);
815         }
816 
817         adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read);
818 
819         EXPECT_EQ(bpReader.Steps(), NSteps);
820 
821         auto var_i8 = io.InquireVariable<int8_t>("i8");
822         EXPECT_TRUE(var_i8);
823         ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
824         ASSERT_EQ(var_i8.Steps(), NSteps);
825         ASSERT_EQ(var_i8.Shape()[0], Ny);
826         ASSERT_EQ(var_i8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
827 
828         auto var_i16 = io.InquireVariable<int16_t>("i16");
829         EXPECT_TRUE(var_i16);
830         ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
831         ASSERT_EQ(var_i16.Steps(), NSteps);
832         ASSERT_EQ(var_i16.Shape()[0], Ny);
833         ASSERT_EQ(var_i16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
834 
835         auto var_i32 = io.InquireVariable<int32_t>("i32");
836         EXPECT_TRUE(var_i32);
837         ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
838         ASSERT_EQ(var_i32.Steps(), NSteps);
839         ASSERT_EQ(var_i32.Shape()[0], Ny);
840         ASSERT_EQ(var_i32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
841 
842         auto var_i64 = io.InquireVariable<int64_t>("i64");
843         EXPECT_TRUE(var_i64);
844         ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
845         ASSERT_EQ(var_i64.Steps(), NSteps);
846         ASSERT_EQ(var_i64.Shape()[0], Ny);
847         ASSERT_EQ(var_i64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
848 
849         auto var_u8 = io.InquireVariable<uint8_t>("u8");
850         EXPECT_TRUE(var_u8);
851         ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
852         ASSERT_EQ(var_u8.Steps(), NSteps);
853         ASSERT_EQ(var_u8.Shape()[0], Ny);
854         ASSERT_EQ(var_u8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
855 
856         auto var_u16 = io.InquireVariable<uint16_t>("u16");
857         EXPECT_TRUE(var_u16);
858         ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
859         ASSERT_EQ(var_u16.Steps(), NSteps);
860         ASSERT_EQ(var_u16.Shape()[0], Ny);
861         ASSERT_EQ(var_u16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
862 
863         auto var_u32 = io.InquireVariable<uint32_t>("u32");
864         EXPECT_TRUE(var_u32);
865         ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
866         ASSERT_EQ(var_u32.Steps(), NSteps);
867         ASSERT_EQ(var_u32.Shape()[0], Ny);
868         ASSERT_EQ(var_u32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
869 
870         auto var_u64 = io.InquireVariable<uint64_t>("u64");
871         EXPECT_TRUE(var_u64);
872         ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
873         ASSERT_EQ(var_u64.Steps(), NSteps);
874         ASSERT_EQ(var_u64.Shape()[0], Ny);
875         ASSERT_EQ(var_u64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
876 
877         auto var_r32 = io.InquireVariable<float>("r32");
878         EXPECT_TRUE(var_r32);
879         ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
880         ASSERT_EQ(var_r32.Steps(), NSteps);
881         ASSERT_EQ(var_r32.Shape()[0], Ny);
882         ASSERT_EQ(var_r32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
883 
884         auto var_r64 = io.InquireVariable<double>("r64");
885         EXPECT_TRUE(var_r64);
886         ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
887         ASSERT_EQ(var_r64.Steps(), NSteps);
888         ASSERT_EQ(var_r64.Shape()[0], Ny);
889         ASSERT_EQ(var_r64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
890 
891         // If the size of the array is smaller than the data
892         // the result is weird... double and uint64_t would get
893         // completely garbage data
894         std::array<int8_t, Nx * Ny> I8;
895         std::array<int16_t, Nx * Ny> I16;
896         std::array<int32_t, Nx * Ny> I32;
897         std::array<int64_t, Nx * Ny> I64;
898         std::array<uint8_t, Nx * Ny> U8;
899         std::array<uint16_t, Nx * Ny> U16;
900         std::array<uint32_t, Nx * Ny> U32;
901         std::array<uint64_t, Nx * Ny> U64;
902         std::array<float, Nx * Ny> R32;
903         std::array<double, Nx * Ny> R64;
904 
905         const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
906         const adios2::Dims count{Ny, Nx};
907 
908         const adios2::Box<adios2::Dims> sel(start, count);
909 
910         var_i8.SetSelection(sel);
911         var_i16.SetSelection(sel);
912         var_i32.SetSelection(sel);
913         var_i64.SetSelection(sel);
914 
915         var_u8.SetSelection(sel);
916         var_u16.SetSelection(sel);
917         var_u32.SetSelection(sel);
918         var_u64.SetSelection(sel);
919 
920         var_r32.SetSelection(sel);
921         var_r64.SetSelection(sel);
922 
923         for (size_t t = 0; t < NSteps; ++t)
924         {
925             var_i8.SetStepSelection({t, 1});
926             var_i16.SetStepSelection({t, 1});
927             var_i32.SetStepSelection({t, 1});
928             var_i64.SetStepSelection({t, 1});
929 
930             var_u8.SetStepSelection({t, 1});
931             var_u16.SetStepSelection({t, 1});
932             var_u32.SetStepSelection({t, 1});
933             var_u64.SetStepSelection({t, 1});
934 
935             var_r32.SetStepSelection({t, 1});
936             var_r64.SetStepSelection({t, 1});
937 
938             bpReader.Get(var_i8, I8.data());
939             bpReader.Get(var_i16, I16.data());
940             bpReader.Get(var_i32, I32.data());
941             bpReader.Get(var_i64, I64.data());
942 
943             bpReader.Get(var_u8, U8.data());
944             bpReader.Get(var_u16, U16.data());
945             bpReader.Get(var_u32, U32.data());
946             bpReader.Get(var_u64, U64.data());
947 
948             bpReader.Get(var_r32, R32.data());
949             bpReader.Get(var_r64, R64.data());
950 
951             bpReader.PerformGets();
952 
953             // Generate test data for each rank uniquely
954             SmallTestData currentTestData = generateNewSmallTestData(
955                 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
956 
957             for (size_t i = 0; i < Nx * Ny; ++i)
958             {
959                 std::stringstream ss;
960                 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
961                 std::string msg = ss.str();
962 
963                 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
964                 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
965                 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
966                 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
967                 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
968                 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
969                 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
970                 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
971                 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
972                 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
973             }
974         }
975         bpReader.Close();
976     }
977 }
978 
TEST_F(BPWriteReadTestADIOS2,ADIOS2BPWriteRead10D2x2)979 TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead10D2x2)
980 {
981     // Each process would write a 2x2x...x2 9D array and all processes would
982     // form a 10D NumberOfProcess x 2 x ... x 2) array
983     const std::string fname("ADIOS2BPWriteRead10D2x2Test.bp");
984 
985     int mpiRank = 0, mpiSize = 1;
986     // Number of steps
987     const std::size_t NSteps = 3;
988 
989 #if ADIOS2_USE_MPI
990     MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
991     MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
992 #endif
993 
994     size_t NX = static_cast<unsigned int>(mpiSize);
995     size_t OX = static_cast<unsigned int>(mpiRank);
996     const adios2::Dims shape{NX, 2, 2, 2, 2, 2, 2, 2, 2, 2};
997     const adios2::Dims start{OX, 0, 0, 0, 0, 0, 0, 0, 0, 0};
998     const adios2::Dims count{1, 2, 2, 2, 2, 2, 2, 2, 2, 2};
999 
1000     std::array<double, 512> R64w, R64r;
1001     std::array<std::complex<double>, 512> CR64w, CR64r;
1002 
1003     // Write test data using ADIOS2
1004 
1005 #if ADIOS2_USE_MPI
1006     adios2::ADIOS adios(MPI_COMM_WORLD);
1007 #else
1008     adios2::ADIOS adios;
1009 #endif
1010     {
1011         adios2::IO io = adios.DeclareIO("TestIO");
1012 
1013         // Declare 10D variables
1014         {
1015             auto var_r64 =
1016                 io.DefineVariable<double>("r64", shape, start, count);
1017             auto var_c64 = io.DefineVariable<std::complex<double>>(
1018                 "cr64", shape, start, count);
1019         }
1020 
1021         if (!engineName.empty())
1022         {
1023             io.SetEngine(engineName);
1024         }
1025         else
1026         {
1027             // Create the BP Engine
1028             io.SetEngine("BPFile");
1029         }
1030 
1031         io.AddTransport("file");
1032 
1033         adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write);
1034 
1035         for (size_t step = 0; step < NSteps; ++step)
1036         {
1037             double d = mpiRank + 1 + step / 10.0;
1038             // Generate test data for each process uniquely
1039             std::for_each(R64w.begin(), R64w.end(), [&](double &v) {
1040                 v = d;
1041                 d += 0.0001;
1042             });
1043             std::for_each(CR64w.begin(), CR64w.end(),
1044                           [&](std::complex<double> &v) {
1045                               v.real(d);
1046                               v.imag(d);
1047                           });
1048 
1049             // Retrieve the variables that previously went out of scope
1050             auto var_r64 = io.InquireVariable<double>("r64");
1051             auto var_cr64 = io.InquireVariable<std::complex<double>>("cr64");
1052 
1053             // Make a 2D selection to describe the local dimensions of the
1054             // variable we write and its offsets in the global spaces
1055             adios2::Box<adios2::Dims> sel({start, count});
1056             var_r64.SetSelection(sel);
1057             var_cr64.SetSelection(sel);
1058 
1059             // Write each one
1060             // fill in the variable with values from starting index to
1061             // starting index + count
1062             bpWriter.BeginStep();
1063             bpWriter.Put(var_r64, R64w.data());
1064             bpWriter.Put(var_cr64, CR64w.data());
1065             bpWriter.EndStep();
1066         }
1067 
1068         // Close the file
1069         bpWriter.Close();
1070     }
1071 
1072     {
1073         adios2::IO io = adios.DeclareIO("ReadIO");
1074 
1075         if (!engineName.empty())
1076         {
1077             io.SetEngine(engineName);
1078         }
1079 
1080         adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read);
1081 
1082         EXPECT_EQ(bpReader.Steps(), NSteps);
1083 
1084         auto var_r64 = io.InquireVariable<double>("r64");
1085         EXPECT_TRUE(var_r64);
1086         ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
1087         ASSERT_EQ(var_r64.Steps(), NSteps);
1088         ASSERT_EQ(var_r64.Shape().size(), 10);
1089         ASSERT_EQ(var_r64.Shape()[0], NX);
1090         ASSERT_EQ(var_r64.Shape()[1], 2);
1091         ASSERT_EQ(var_r64.Shape()[2], 2);
1092         ASSERT_EQ(var_r64.Shape()[3], 2);
1093         ASSERT_EQ(var_r64.Shape()[4], 2);
1094         ASSERT_EQ(var_r64.Shape()[5], 2);
1095         ASSERT_EQ(var_r64.Shape()[6], 2);
1096         ASSERT_EQ(var_r64.Shape()[7], 2);
1097         ASSERT_EQ(var_r64.Shape()[8], 2);
1098         ASSERT_EQ(var_r64.Shape()[9], 2);
1099 
1100         auto var_cr64 = io.InquireVariable<std::complex<double>>("cr64");
1101         EXPECT_TRUE(var_cr64);
1102         ASSERT_EQ(var_cr64.ShapeID(), adios2::ShapeID::GlobalArray);
1103         ASSERT_EQ(var_cr64.Steps(), NSteps);
1104         ASSERT_EQ(var_cr64.Shape().size(), 10);
1105         ASSERT_EQ(var_cr64.Shape()[0], NX);
1106         ASSERT_EQ(var_cr64.Shape()[1], 2);
1107         ASSERT_EQ(var_cr64.Shape()[2], 2);
1108         ASSERT_EQ(var_cr64.Shape()[3], 2);
1109         ASSERT_EQ(var_cr64.Shape()[4], 2);
1110         ASSERT_EQ(var_cr64.Shape()[5], 2);
1111         ASSERT_EQ(var_cr64.Shape()[6], 2);
1112         ASSERT_EQ(var_cr64.Shape()[7], 2);
1113         ASSERT_EQ(var_cr64.Shape()[8], 2);
1114         ASSERT_EQ(var_cr64.Shape()[9], 2);
1115 
1116         const adios2::Box<adios2::Dims> sel(start, count);
1117 
1118         var_r64.SetSelection(sel);
1119         var_cr64.SetSelection(sel);
1120 
1121         for (size_t step = 0; step < NSteps; ++step)
1122         {
1123             var_r64.SetStepSelection({step, 1});
1124             var_cr64.SetStepSelection({step, 1});
1125             bpReader.Get(var_r64, R64r.data());
1126             bpReader.Get(var_cr64, CR64r.data());
1127             bpReader.PerformGets();
1128 
1129             double d = mpiRank + 1 + step / 10.0;
1130             // Re-generate test data for each process uniquely that was written
1131             std::for_each(R64w.begin(), R64w.end(), [&](double &v) {
1132                 v = d;
1133                 d += 0.0001;
1134             });
1135             std::for_each(CR64w.begin(), CR64w.end(),
1136                           [&](std::complex<double> &v) {
1137                               v.real(d);
1138                               v.imag(d);
1139                           });
1140 
1141             for (size_t i = 0; i < 512; ++i)
1142             {
1143                 std::stringstream ss;
1144                 ss << "t=" << step << " i=" << i << " rank=" << mpiRank;
1145                 std::string msg = ss.str();
1146 
1147                 EXPECT_EQ(R64r[i], R64w[i]) << msg;
1148                 EXPECT_EQ(CR64r[i], CR64w[i]) << msg;
1149             }
1150         }
1151         bpReader.Close();
1152     }
1153 }
1154 
TEST_F(BPWriteReadTestADIOS2,ADIOS2BPWriteRead2D4x2_ReadMultiSteps)1155 TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead2D4x2_ReadMultiSteps)
1156 {
1157     // Each process would write a 4x2 array and all processes would
1158     // form a 2D 4 * (NumberOfProcess * Nx) matrix where Nx is 2 here
1159     const std::string fname("ADIOS2BPWriteRead2D4x2Test_ReadMultiSteps.bp");
1160 
1161     int mpiRank = 0, mpiSize = 1;
1162     // Number of rows
1163     const std::size_t Nx = 2;
1164     // Number of cols
1165     const std::size_t Ny = 4;
1166 
1167     // Number of steps
1168     const std::size_t NSteps = 5;
1169     const std::size_t tInitial = 2;
1170 
1171 #if ADIOS2_USE_MPI
1172     MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
1173     MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
1174 #endif
1175 
1176     // Write test data using ADIOS2
1177 
1178 #if ADIOS2_USE_MPI
1179     adios2::ADIOS adios(MPI_COMM_WORLD);
1180 #else
1181     adios2::ADIOS adios;
1182 #endif
1183     {
1184         adios2::IO io = adios.DeclareIO("TestIO");
1185 
1186         // Declare 2D variables (4 * (NumberOfProcess * Nx))
1187         // The local process' part (start, count) can be defined now or
1188         // later before Write().
1189         {
1190             adios2::Dims shape{Ny, static_cast<size_t>(mpiSize * Nx)};
1191             adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
1192             adios2::Dims count{Ny, Nx};
1193             auto var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count);
1194             auto var_i16 =
1195                 io.DefineVariable<int16_t>("i16", shape, start, count);
1196             auto var_i32 =
1197                 io.DefineVariable<int32_t>("i32", shape, start, count);
1198             auto var_i64 =
1199                 io.DefineVariable<int64_t>("i64", shape, start, count);
1200             auto var_u8 = io.DefineVariable<uint8_t>("u8", shape, start, count);
1201             auto var_u16 =
1202                 io.DefineVariable<uint16_t>("u16", shape, start, count);
1203             auto var_u32 =
1204                 io.DefineVariable<uint32_t>("u32", shape, start, count);
1205             auto var_u64 =
1206                 io.DefineVariable<uint64_t>("u64", shape, start, count);
1207             auto var_r32 = io.DefineVariable<float>("r32", shape, start, count);
1208             auto var_r64 =
1209                 io.DefineVariable<double>("r64", shape, start, count);
1210         }
1211 
1212         if (!engineName.empty())
1213         {
1214             io.SetEngine(engineName);
1215         }
1216         else
1217         {
1218             // Create the BP Engine
1219             io.SetEngine("BPFile");
1220         }
1221 
1222         io.AddTransport("file");
1223 
1224         adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write);
1225 
1226         for (size_t step = 0; step < NSteps; ++step)
1227         {
1228             // Generate test data for each process uniquely
1229             SmallTestData currentTestData = generateNewSmallTestData(
1230                 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
1231 
1232             // Retrieve the variables that previously went out of scope
1233             auto var_i8 = io.InquireVariable<int8_t>("i8");
1234             auto var_i16 = io.InquireVariable<int16_t>("i16");
1235             auto var_i32 = io.InquireVariable<int32_t>("i32");
1236             auto var_i64 = io.InquireVariable<int64_t>("i64");
1237             auto var_u8 = io.InquireVariable<uint8_t>("u8");
1238             auto var_u16 = io.InquireVariable<uint16_t>("u16");
1239             auto var_u32 = io.InquireVariable<uint32_t>("u32");
1240             auto var_u64 = io.InquireVariable<uint64_t>("u64");
1241             auto var_r32 = io.InquireVariable<float>("r32");
1242             auto var_r64 = io.InquireVariable<double>("r64");
1243 
1244             // Make a 2D selection to describe the local dimensions of the
1245             // variable we write and its offsets in the global spaces
1246             adios2::Box<adios2::Dims> sel(
1247                 {0, static_cast<unsigned int>(mpiRank * Nx)}, {Ny, Nx});
1248             var_i8.SetSelection(sel);
1249             var_i16.SetSelection(sel);
1250             var_i32.SetSelection(sel);
1251             var_i64.SetSelection(sel);
1252             var_u8.SetSelection(sel);
1253             var_u16.SetSelection(sel);
1254             var_u32.SetSelection(sel);
1255             var_u64.SetSelection(sel);
1256             var_r32.SetSelection(sel);
1257             var_r64.SetSelection(sel);
1258 
1259             // Write each one
1260             // fill in the variable with values from starting index to
1261             // starting index + count
1262             bpWriter.BeginStep();
1263             bpWriter.Put(var_i8, currentTestData.I8.data());
1264             bpWriter.Put(var_i16, currentTestData.I16.data());
1265             bpWriter.Put(var_i32, currentTestData.I32.data());
1266             bpWriter.Put(var_i64, currentTestData.I64.data());
1267             bpWriter.Put(var_u8, currentTestData.U8.data());
1268             bpWriter.Put(var_u16, currentTestData.U16.data());
1269             bpWriter.Put(var_u32, currentTestData.U32.data());
1270             bpWriter.Put(var_u64, currentTestData.U64.data());
1271             bpWriter.Put(var_r32, currentTestData.R32.data());
1272             bpWriter.Put(var_r64, currentTestData.R64.data());
1273             bpWriter.EndStep();
1274         }
1275 
1276         // Close the file
1277         bpWriter.Close();
1278     }
1279 
1280     {
1281         adios2::IO io = adios.DeclareIO("ReadIO");
1282 
1283         if (!engineName.empty())
1284         {
1285             io.SetEngine(engineName);
1286         }
1287 
1288         adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read);
1289 
1290         EXPECT_EQ(bpReader.Steps(), NSteps);
1291 
1292         auto var_i8 = io.InquireVariable<int8_t>("i8");
1293         EXPECT_TRUE(var_i8);
1294         ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
1295         ASSERT_EQ(var_i8.Steps(), NSteps);
1296         ASSERT_EQ(var_i8.Shape()[0], Ny);
1297         ASSERT_EQ(var_i8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1298 
1299         auto var_i16 = io.InquireVariable<int16_t>("i16");
1300         EXPECT_TRUE(var_i16);
1301         ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
1302         ASSERT_EQ(var_i16.Steps(), NSteps);
1303         ASSERT_EQ(var_i16.Shape()[0], Ny);
1304         ASSERT_EQ(var_i16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1305 
1306         auto var_i32 = io.InquireVariable<int32_t>("i32");
1307         EXPECT_TRUE(var_i32);
1308         ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
1309         ASSERT_EQ(var_i32.Steps(), NSteps);
1310         ASSERT_EQ(var_i32.Shape()[0], Ny);
1311         ASSERT_EQ(var_i32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1312 
1313         auto var_i64 = io.InquireVariable<int64_t>("i64");
1314         EXPECT_TRUE(var_i64);
1315         ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
1316         ASSERT_EQ(var_i64.Steps(), NSteps);
1317         ASSERT_EQ(var_i64.Shape()[0], Ny);
1318         ASSERT_EQ(var_i64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1319 
1320         auto var_u8 = io.InquireVariable<uint8_t>("u8");
1321         EXPECT_TRUE(var_u8);
1322         ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
1323         ASSERT_EQ(var_u8.Steps(), NSteps);
1324         ASSERT_EQ(var_u8.Shape()[0], Ny);
1325         ASSERT_EQ(var_u8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1326 
1327         auto var_u16 = io.InquireVariable<uint16_t>("u16");
1328         EXPECT_TRUE(var_u16);
1329         ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
1330         ASSERT_EQ(var_u16.Steps(), NSteps);
1331         ASSERT_EQ(var_u16.Shape()[0], Ny);
1332         ASSERT_EQ(var_u16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1333 
1334         auto var_u32 = io.InquireVariable<uint32_t>("u32");
1335         EXPECT_TRUE(var_u32);
1336         ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
1337         ASSERT_EQ(var_u32.Steps(), NSteps);
1338         ASSERT_EQ(var_u32.Shape()[0], Ny);
1339         ASSERT_EQ(var_u32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1340 
1341         auto var_u64 = io.InquireVariable<uint64_t>("u64");
1342         EXPECT_TRUE(var_u64);
1343         ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
1344         ASSERT_EQ(var_u64.Steps(), NSteps);
1345         ASSERT_EQ(var_u64.Shape()[0], Ny);
1346         ASSERT_EQ(var_u64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1347 
1348         auto var_r32 = io.InquireVariable<float>("r32");
1349         EXPECT_TRUE(var_r32);
1350         ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
1351         ASSERT_EQ(var_r32.Steps(), NSteps);
1352         ASSERT_EQ(var_r32.Shape()[0], Ny);
1353         ASSERT_EQ(var_r32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1354 
1355         auto var_r64 = io.InquireVariable<double>("r64");
1356         EXPECT_TRUE(var_r64);
1357         ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
1358         ASSERT_EQ(var_r64.Steps(), NSteps);
1359         ASSERT_EQ(var_r64.Shape()[0], Ny);
1360         ASSERT_EQ(var_r64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1361 
1362         // If the size of the array is smaller than the data
1363         // the result is weird... double and uint64_t would get
1364         // completely garbage data
1365         std::array<int8_t, NSteps * Nx * Ny> I8;
1366         std::array<int16_t, NSteps * Nx * Ny> I16;
1367         std::array<int32_t, NSteps * Nx * Ny> I32;
1368         std::array<int64_t, NSteps * Nx * Ny> I64;
1369         std::array<uint8_t, NSteps * Nx * Ny> U8;
1370         std::array<uint16_t, NSteps * Nx * Ny> U16;
1371         std::array<uint32_t, NSteps * Nx * Ny> U32;
1372         std::array<uint64_t, NSteps * Nx * Ny> U64;
1373         std::array<float, NSteps * Nx * Ny> R32;
1374         std::array<double, NSteps * Nx * Ny> R64;
1375 
1376         const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
1377         const adios2::Dims count{Ny, Nx};
1378 
1379         const adios2::Box<adios2::Dims> sel(start, count);
1380 
1381         var_i8.SetSelection(sel);
1382         var_i16.SetSelection(sel);
1383         var_i32.SetSelection(sel);
1384         var_i64.SetSelection(sel);
1385 
1386         var_u8.SetSelection(sel);
1387         var_u16.SetSelection(sel);
1388         var_u32.SetSelection(sel);
1389         var_u64.SetSelection(sel);
1390 
1391         var_r32.SetSelection(sel);
1392         var_r64.SetSelection(sel);
1393 
1394         var_i8.SetStepSelection({tInitial, NSteps - tInitial});
1395         var_i16.SetStepSelection({tInitial, NSteps - tInitial});
1396         var_i32.SetStepSelection({tInitial, NSteps - tInitial});
1397         var_i64.SetStepSelection({tInitial, NSteps - tInitial});
1398 
1399         var_u8.SetStepSelection({tInitial, NSteps - tInitial});
1400         var_u16.SetStepSelection({tInitial, NSteps - tInitial});
1401         var_u32.SetStepSelection({tInitial, NSteps - tInitial});
1402         var_u64.SetStepSelection({tInitial, NSteps - tInitial});
1403 
1404         var_r32.SetStepSelection({tInitial, NSteps - tInitial});
1405         var_r64.SetStepSelection({tInitial, NSteps - tInitial});
1406 
1407         bpReader.Get(var_i8, I8.data());
1408         bpReader.Get(var_i16, I16.data());
1409         bpReader.Get(var_i32, I32.data());
1410         bpReader.Get(var_i64, I64.data());
1411 
1412         bpReader.Get(var_u8, U8.data());
1413         bpReader.Get(var_u16, U16.data());
1414         bpReader.Get(var_u32, U32.data());
1415         bpReader.Get(var_u64, U64.data());
1416 
1417         bpReader.Get(var_r32, R32.data());
1418         bpReader.Get(var_r64, R64.data());
1419 
1420         bpReader.PerformGets();
1421 
1422         for (size_t t = tInitial; t < NSteps; ++t)
1423         {
1424             // Generate test data for each rank uniquely
1425             SmallTestData currentTestData = generateNewSmallTestData(
1426                 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
1427 
1428             for (size_t i = 0; i < Nx * Ny; ++i)
1429             {
1430                 const size_t index = (t - tInitial) * Nx * Ny + i;
1431                 std::stringstream ss;
1432                 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
1433                 std::string msg = ss.str();
1434 
1435                 EXPECT_EQ(I8[index], currentTestData.I8[i]) << msg;
1436                 EXPECT_EQ(I16[index], currentTestData.I16[i]) << msg;
1437                 EXPECT_EQ(I32[index], currentTestData.I32[i]) << msg;
1438                 EXPECT_EQ(I64[index], currentTestData.I64[i]) << msg;
1439                 EXPECT_EQ(U8[index], currentTestData.U8[i]) << msg;
1440                 EXPECT_EQ(U16[index], currentTestData.U16[i]) << msg;
1441                 EXPECT_EQ(U32[index], currentTestData.U32[i]) << msg;
1442                 EXPECT_EQ(U64[index], currentTestData.U64[i]) << msg;
1443                 EXPECT_EQ(R32[index], currentTestData.R32[i]) << msg;
1444                 EXPECT_EQ(R64[index], currentTestData.R64[i]) << msg;
1445             }
1446         }
1447 
1448         bpReader.Close();
1449     }
1450 }
1451 
TEST_F(BPWriteReadTestADIOS2,ADIOS2BPWriteRead2D4x2_MultiStepsOverflow)1452 TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead2D4x2_MultiStepsOverflow)
1453 {
1454     // Each process would write a 4x2 array and all processes would
1455     // form a 2D 4 * (NumberOfProcess * Nx) matrix where Nx is 2 here
1456     const std::string fname("ADIOS2BPWriteRead2D4x2Test_Overflow.bp");
1457 
1458     int mpiRank = 0, mpiSize = 1;
1459     // Number of rows
1460     const std::size_t Nx = 2;
1461     // Number of cols
1462     const std::size_t Ny = 4;
1463 
1464     // Number of steps
1465     const std::size_t NSteps = 5;
1466     const std::size_t tInitial = 2;
1467 
1468 #if ADIOS2_USE_MPI
1469     MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
1470     MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
1471 #endif
1472 
1473     // Write test data using ADIOS2
1474 
1475 #if ADIOS2_USE_MPI
1476     adios2::ADIOS adios(MPI_COMM_WORLD);
1477 #else
1478     adios2::ADIOS adios;
1479 #endif
1480     {
1481         adios2::IO io = adios.DeclareIO("TestIO");
1482 
1483         // Declare 2D variables (4 * (NumberOfProcess * Nx))
1484         // The local process' part (start, count) can be defined now or
1485         // later before Write().
1486         {
1487             adios2::Dims shape{Ny, static_cast<size_t>(mpiSize * Nx)};
1488             adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
1489             adios2::Dims count{Ny, Nx};
1490             auto var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count);
1491             auto var_i16 =
1492                 io.DefineVariable<int16_t>("i16", shape, start, count);
1493             auto var_i32 =
1494                 io.DefineVariable<int32_t>("i32", shape, start, count);
1495             auto var_i64 =
1496                 io.DefineVariable<int64_t>("i64", shape, start, count);
1497             auto var_u8 = io.DefineVariable<uint8_t>("u8", shape, start, count);
1498             auto var_u16 =
1499                 io.DefineVariable<uint16_t>("u16", shape, start, count);
1500             auto var_u32 =
1501                 io.DefineVariable<uint32_t>("u32", shape, start, count);
1502             auto var_u64 =
1503                 io.DefineVariable<uint64_t>("u64", shape, start, count);
1504             auto var_r32 = io.DefineVariable<float>("r32", shape, start, count);
1505             auto var_r64 =
1506                 io.DefineVariable<double>("r64", shape, start, count);
1507         }
1508 
1509         if (!engineName.empty())
1510         {
1511             io.SetEngine(engineName);
1512         }
1513         else
1514         {
1515             // Create the BP Engine
1516             io.SetEngine("BPFile");
1517         }
1518 
1519         io.AddTransport("file");
1520 
1521         adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write);
1522 
1523         for (size_t step = 0; step < NSteps; ++step)
1524         {
1525             // Generate test data for each process uniquely
1526             SmallTestData currentTestData = generateNewSmallTestData(
1527                 m_TestData, static_cast<int>(step), mpiRank, mpiSize);
1528 
1529             // Retrieve the variables that previously went out of scope
1530             auto var_i8 = io.InquireVariable<int8_t>("i8");
1531             auto var_i16 = io.InquireVariable<int16_t>("i16");
1532             auto var_i32 = io.InquireVariable<int32_t>("i32");
1533             auto var_i64 = io.InquireVariable<int64_t>("i64");
1534             auto var_u8 = io.InquireVariable<uint8_t>("u8");
1535             auto var_u16 = io.InquireVariable<uint16_t>("u16");
1536             auto var_u32 = io.InquireVariable<uint32_t>("u32");
1537             auto var_u64 = io.InquireVariable<uint64_t>("u64");
1538             auto var_r32 = io.InquireVariable<float>("r32");
1539             auto var_r64 = io.InquireVariable<double>("r64");
1540 
1541             // Make a 2D selection to describe the local dimensions of the
1542             // variable we write and its offsets in the global spaces
1543             adios2::Box<adios2::Dims> sel(
1544                 {0, static_cast<unsigned int>(mpiRank * Nx)}, {Ny, Nx});
1545             var_i8.SetSelection(sel);
1546             var_i16.SetSelection(sel);
1547             var_i32.SetSelection(sel);
1548             var_i64.SetSelection(sel);
1549             var_u8.SetSelection(sel);
1550             var_u16.SetSelection(sel);
1551             var_u32.SetSelection(sel);
1552             var_u64.SetSelection(sel);
1553             var_r32.SetSelection(sel);
1554             var_r64.SetSelection(sel);
1555 
1556             // Write each one
1557             // fill in the variable with values from starting index to
1558             // starting index + count
1559             bpWriter.BeginStep();
1560             bpWriter.Put(var_i8, currentTestData.I8.data());
1561             bpWriter.Put(var_i16, currentTestData.I16.data());
1562             bpWriter.Put(var_i32, currentTestData.I32.data());
1563             bpWriter.Put(var_i64, currentTestData.I64.data());
1564             bpWriter.Put(var_u8, currentTestData.U8.data());
1565             bpWriter.Put(var_u16, currentTestData.U16.data());
1566             bpWriter.Put(var_u32, currentTestData.U32.data());
1567             bpWriter.Put(var_u64, currentTestData.U64.data());
1568             bpWriter.Put(var_r32, currentTestData.R32.data());
1569             bpWriter.Put(var_r64, currentTestData.R64.data());
1570             bpWriter.EndStep();
1571         }
1572 
1573         // Close the file
1574         bpWriter.Close();
1575     }
1576 
1577     {
1578         adios2::IO io = adios.DeclareIO("ReadIO");
1579 
1580         if (!engineName.empty())
1581         {
1582             io.SetEngine(engineName);
1583         }
1584 
1585         adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read);
1586 
1587         auto var_i8 = io.InquireVariable<int8_t>("i8");
1588         auto var_i16 = io.InquireVariable<int16_t>("i16");
1589         auto var_i32 = io.InquireVariable<int32_t>("i32");
1590         auto var_i64 = io.InquireVariable<int64_t>("i64");
1591 
1592         auto var_u8 = io.InquireVariable<uint8_t>("u8");
1593         auto var_u16 = io.InquireVariable<uint16_t>("u16");
1594         auto var_u32 = io.InquireVariable<uint32_t>("u32");
1595         auto var_u64 = io.InquireVariable<uint64_t>("u64");
1596 
1597         auto var_r32 = io.InquireVariable<float>("r32");
1598         auto var_r64 = io.InquireVariable<double>("r64");
1599         // If the size of the array is smaller than the data
1600         // the result is weird... double and uint64_t would get
1601         // completely garbage data
1602         std::array<int8_t, NSteps * Nx * Ny> I8;
1603         std::array<int16_t, NSteps * Nx * Ny> I16;
1604         std::array<int32_t, NSteps * Nx * Ny> I32;
1605         std::array<int64_t, NSteps * Nx * Ny> I64;
1606         std::array<uint8_t, NSteps * Nx * Ny> U8;
1607         std::array<uint16_t, NSteps * Nx * Ny> U16;
1608         std::array<uint32_t, NSteps * Nx * Ny> U32;
1609         std::array<uint64_t, NSteps * Nx * Ny> U64;
1610         std::array<float, NSteps * Nx * Ny> R32;
1611         std::array<double, NSteps * Nx * Ny> R64;
1612 
1613         const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
1614         const adios2::Dims count{Ny, Nx};
1615 
1616         const adios2::Box<adios2::Dims> sel(start, count);
1617 
1618         var_i8.SetSelection(sel);
1619         var_i16.SetSelection(sel);
1620         var_i32.SetSelection(sel);
1621         var_i64.SetSelection(sel);
1622 
1623         var_u8.SetSelection(sel);
1624         var_u16.SetSelection(sel);
1625         var_u32.SetSelection(sel);
1626         var_u64.SetSelection(sel);
1627 
1628         var_r32.SetSelection(sel);
1629         var_r64.SetSelection(sel);
1630 
1631         var_i8.SetStepSelection({tInitial, NSteps - tInitial + 1});
1632         var_i16.SetStepSelection({tInitial + 1, NSteps - tInitial + 1});
1633         var_i32.SetStepSelection({tInitial + 1, NSteps - tInitial + 1});
1634         var_i64.SetStepSelection({tInitial + 1, NSteps - tInitial + 1});
1635 
1636         var_u8.SetStepSelection({tInitial + 1, NSteps - tInitial + 1});
1637         var_u16.SetStepSelection({tInitial + 1, NSteps - tInitial + 1});
1638         var_u32.SetStepSelection({tInitial + 1, NSteps - tInitial + 1});
1639         var_u64.SetStepSelection({tInitial + 1, NSteps - tInitial + 1});
1640 
1641         var_r32.SetStepSelection({tInitial + 1, NSteps - tInitial + 1});
1642         var_r64.SetStepSelection({tInitial + 1, NSteps - tInitial + 1});
1643 
1644         EXPECT_THROW(bpReader.Get(var_i8, I8.data()), std::invalid_argument);
1645         EXPECT_THROW(bpReader.Get(var_i16, I16.data()), std::invalid_argument);
1646         EXPECT_THROW(bpReader.Get(var_i32, I32.data()), std::invalid_argument);
1647         EXPECT_THROW(bpReader.Get(var_i64, I64.data()), std::invalid_argument);
1648 
1649         EXPECT_THROW(bpReader.Get(var_u8, U8.data()), std::invalid_argument);
1650         EXPECT_THROW(bpReader.Get(var_u16, U16.data()), std::invalid_argument);
1651         EXPECT_THROW(bpReader.Get(var_u32, U32.data()), std::invalid_argument);
1652         EXPECT_THROW(bpReader.Get(var_u64, U64.data()), std::invalid_argument);
1653 
1654         EXPECT_THROW(bpReader.Get(var_r32, R32.data()), std::invalid_argument);
1655         EXPECT_THROW(bpReader.Get(var_r64, R64.data()), std::invalid_argument);
1656     }
1657 }
1658 
TEST_F(BPWriteReadTestADIOS2,OpenEngineTwice)1659 TEST_F(BPWriteReadTestADIOS2, OpenEngineTwice)
1660 {
1661     // Each process would write a 4x2 array and all processes would
1662     // form a 2D 4 * (NumberOfProcess * Nx) matrix where Nx is 2 here
1663     const std::string fname("OpenTwice.bp");
1664 
1665 #if ADIOS2_USE_MPI
1666     adios2::ADIOS adios(MPI_COMM_WORLD);
1667 #else
1668     adios2::ADIOS adios;
1669 #endif
1670     {
1671         adios2::IO io = adios.DeclareIO("TwoOpens");
1672 
1673         if (!engineName.empty())
1674         {
1675             io.SetEngine(engineName);
1676         }
1677         else
1678         {
1679             // Create the BP Engine
1680             io.SetEngine("BPFile");
1681         }
1682 
1683         adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write);
1684 
1685         EXPECT_THROW(io.Open(fname, adios2::Mode::Write),
1686                      std::invalid_argument);
1687 
1688         bpWriter.Close();
1689 
1690         EXPECT_NO_THROW(io.Open(fname, adios2::Mode::Write));
1691         EXPECT_THROW(io.Open(fname, adios2::Mode::Read), std::invalid_argument);
1692     }
1693 }
1694 
TEST_F(BPWriteReadTestADIOS2,ReadStartCount)1695 TEST_F(BPWriteReadTestADIOS2, ReadStartCount)
1696 {
1697     // Each process would write a 4x2 array and all processes would
1698     // form a 2D 4 * (NumberOfProcess * Nx) matrix where Nx is 2 here
1699     const std::string fname("ReadStartCount.bp");
1700 
1701     int mpiRank = 0, mpiSize = 1;
1702 
1703     const std::size_t Nx = 10;
1704 
1705 #if ADIOS2_USE_MPI
1706     MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
1707     MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
1708 #endif
1709 
1710     std::vector<int64_t> localData(Nx);
1711     std::iota(localData.begin(), localData.end(), mpiRank * Nx);
1712 
1713 #if ADIOS2_USE_MPI
1714     adios2::ADIOS adios(MPI_COMM_WORLD);
1715 #else
1716     adios2::ADIOS adios;
1717 #endif
1718     {
1719         adios2::IO io = adios.DeclareIO("StartCountWrite");
1720         if (!engineName.empty())
1721         {
1722             io.SetEngine(engineName);
1723         }
1724 
1725         io.DefineVariable<int64_t>(
1726             "range", {static_cast<std::size_t>(Nx * mpiSize)},
1727             {static_cast<std::size_t>(Nx * mpiRank)}, {Nx});
1728 
1729         adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write);
1730 
1731         bpWriter.Put<int64_t>("range", localData.data());
1732         bpWriter.Close();
1733     }
1734     // Reader
1735     {
1736         adios2::IO io = adios.DeclareIO("StartCountRead");
1737         if (!engineName.empty())
1738         {
1739             io.SetEngine(engineName);
1740         }
1741 
1742         adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read);
1743         adios2::Variable<int64_t> varRange =
1744             io.InquireVariable<int64_t>("range");
1745 
1746         const std::size_t gNx = static_cast<std::size_t>(Nx * mpiSize);
1747         std::vector<int64_t> globalData(gNx);
1748         bpReader.Get(varRange, globalData);
1749         bpReader.PerformGets();
1750 
1751         std::vector<int64_t> iStartEndData;
1752         iStartEndData.reserve(gNx); // maximum possible
1753 
1754         for (size_t i = 1; i < gNx; ++i)
1755         {
1756             varRange.SetSelection({{i}, {gNx - i}});
1757 
1758             bpReader.Get("range", iStartEndData);
1759             bpReader.PerformGets();
1760 
1761             for (size_t j = i; j < gNx; ++j)
1762             {
1763                 EXPECT_EQ(globalData[j], iStartEndData[j - i]);
1764             }
1765         }
1766         bpReader.Close();
1767     }
1768 }
1769 
1770 //******************************************************************************
1771 // main
1772 //******************************************************************************
1773 
main(int argc,char ** argv)1774 int main(int argc, char **argv)
1775 {
1776 #if ADIOS2_USE_MPI
1777     MPI_Init(nullptr, nullptr);
1778 #endif
1779 
1780     int result;
1781     ::testing::InitGoogleTest(&argc, argv);
1782 
1783     if (argc > 1)
1784     {
1785         engineName = std::string(argv[1]);
1786     }
1787     result = RUN_ALL_TESTS();
1788 
1789 #if ADIOS2_USE_MPI
1790     MPI_Finalize();
1791 #endif
1792 
1793     return result;
1794 }
1795