1 /*
2 * Distributed under the OSI-approved Apache License, Version 2.0. See
3 * accompanying file Copyright.txt for details.
4 */
5 #include <cstdint>
6 #include <cstring>
7
8 #include <iostream>
9 #include <stdexcept>
10
11 #include <adios2.h>
12
13 #include <hdf5.h>
14
15 #include <gtest/gtest.h>
16
17 #include "../SmallTestData.h"
18
19 class HDF5WriteReadTest : public ::testing::Test
20 {
21 public:
22 HDF5WriteReadTest() = default;
23
24 SmallTestData m_TestData;
25 };
26
27 class HDF5NativeReader
28 {
29
30 public:
31 HDF5NativeReader(const std::string fileName);
32 ~HDF5NativeReader();
33
34 bool Advance();
35
36 void GetVarInfo(const std::string varName, std::vector<hsize_t> &dims,
37 hid_t &h5Type);
38 // If offset, count and memspaceSize are provided, then variable would be
39 // read by selection
40 void ReadString(const std::string varName, std::string &result);
41 void ReadVar(const std::string varName, void *dataArray,
42 hsize_t *offset = nullptr, hsize_t *count = nullptr,
43 const size_t memsspaceSize = 0);
44
45 int m_CurrentTimeStep;
46 unsigned int m_TotalTimeSteps;
47
48 private:
49 hid_t m_FilePropertyListId;
50 hid_t m_FileId;
51 hid_t m_GroupId;
52 };
53
54 class HDF5NativeWriter
55 {
56 public:
57 #ifdef TEST_HDF5_MPI
58 HDF5NativeWriter(const std::string &fileName, MPI_Comm comm);
59 #else
60 HDF5NativeWriter(const std::string &fileName);
61 #endif
62 ~HDF5NativeWriter();
63
64 void Advance();
65
66 void CreateAndStoreScalar(std::string const &variableName, hid_t h5Type,
67 const void *values);
68 void CreateAndStoreVar(std::string const &variableName, int dimSize,
69 hid_t h5Type, const hsize_t *global_dims,
70 const hsize_t *offsets, const hsize_t *counts,
71 const void *values);
72
73 /*
74 void WriteVar(const std::string varName, void *dataArray,
75 hsize_t *offset = nullptr, hsize_t *count = nullptr,
76 const size_t memsspaceSize = 0);
77 */
78 int m_CurrentTimeStep;
79 unsigned int m_TotalTimeSteps;
80
81 private:
82 void CheckWriteGroup();
83
84 hid_t m_FilePropertyListId;
85 hid_t m_FileId;
86 hid_t m_GroupId;
87 };
88 #ifdef TEST_HDF5_MPI
HDF5NativeWriter(const std::string & fileName,MPI_Comm comm)89 HDF5NativeWriter::HDF5NativeWriter(const std::string &fileName, MPI_Comm comm)
90 #else
91 HDF5NativeWriter::HDF5NativeWriter(const std::string &fileName)
92 #endif
93 : m_CurrentTimeStep(0), m_TotalTimeSteps(0)
94 {
95 m_FilePropertyListId = H5Pcreate(H5P_FILE_ACCESS);
96
97 #ifdef TEST_HDF5_MPI
98 H5Pset_fapl_mpio(m_FilePropertyListId, comm, MPI_INFO_NULL);
99 #endif
100
101 // std::string ts0 = "/AdiosStep0";
102 // stepName = "/Step" + std::to_string(ts);
103 std::string ts0 = "/Step0";
104
105 /*
106 * Create a new file collectively and release property list identifier.
107 */
108 m_FileId = H5Fcreate(fileName.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT,
109 m_FilePropertyListId);
110 if (m_FileId < 0)
111 {
112 throw std::runtime_error("Unable to create file: " + fileName);
113 }
114
115 m_GroupId = H5Gcreate2(m_FileId, ts0.c_str(), H5P_DEFAULT, H5P_DEFAULT,
116 H5P_DEFAULT);
117
118 if (m_GroupId < 0)
119 {
120 throw std::runtime_error("ERROR: Unable to create HDF5 group " + ts0);
121 }
122 }
123
~HDF5NativeWriter()124 HDF5NativeWriter::~HDF5NativeWriter()
125 {
126 if (m_FileId < 0)
127 {
128 return;
129 }
130
131 // write NumStep attr
132 hid_t s = H5Screate(H5S_SCALAR);
133
134 hid_t attr = H5Acreate(m_FileId, "NumSteps", H5T_NATIVE_UINT, s,
135 H5P_DEFAULT, H5P_DEFAULT);
136 unsigned int totalAdiosSteps = m_CurrentTimeStep + 1;
137
138 if (m_GroupId < 0)
139 {
140 totalAdiosSteps = m_CurrentTimeStep;
141 }
142
143 H5Awrite(attr, H5T_NATIVE_UINT, &totalAdiosSteps);
144
145 H5Sclose(s);
146 H5Aclose(attr);
147
148 // now close necessary ids
149 if (m_GroupId >= 0)
150 {
151 H5Gclose(m_GroupId);
152 }
153
154 H5Fclose(m_FileId);
155 H5Pclose(m_FilePropertyListId);
156 }
157
CheckWriteGroup()158 void HDF5NativeWriter::CheckWriteGroup()
159 {
160 if (m_GroupId >= 0)
161 {
162 return;
163 }
164
165 std::string stepName = "/Step" + std::to_string(m_CurrentTimeStep);
166
167 m_GroupId = H5Gcreate2(m_FileId, stepName.c_str(), H5P_DEFAULT, H5P_DEFAULT,
168 H5P_DEFAULT);
169
170 if (m_GroupId < 0)
171 {
172 throw std::runtime_error("ERROR: Unable to create HDF5 group " +
173 stepName);
174 }
175 }
176
CreateAndStoreScalar(std::string const & variableName,hid_t h5Type,const void * values)177 void HDF5NativeWriter::CreateAndStoreScalar(std::string const &variableName,
178 hid_t h5Type, const void *values)
179 {
180 CheckWriteGroup();
181
182 // write scalar
183 hid_t filespaceID = H5Screate(H5S_SCALAR);
184 hid_t plistID = H5Pcreate(H5P_DATASET_XFER);
185 #ifdef TEST_HDF5_MPI
186 H5Pset_dxpl_mpio(plistID, H5FD_MPIO_COLLECTIVE);
187 #endif
188
189 hid_t dsetID;
190
191 if (h5Type != H5T_STRING)
192 {
193 dsetID = H5Dcreate(m_GroupId, variableName.c_str(), h5Type, filespaceID,
194 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
195 herr_t status =
196 H5Dwrite(dsetID, h5Type, H5S_ALL, H5S_ALL, plistID, values);
197 }
198 else
199 {
200 /* Create a datatype to refer to. */
201 hid_t type = H5Tcopy(H5T_C_S1);
202 char *strval = (char *)values;
203 hid_t ret = H5Tset_size(type, strlen(strval));
204
205 ret = H5Tset_strpad(type, H5T_STR_NULLTERM);
206
207 /* Test creating a "normal" sized string attribute */
208 dsetID = H5Dcreate(m_GroupId, variableName.c_str(), type, filespaceID,
209 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
210
211 ret = H5Dwrite(dsetID, type, H5S_ALL, H5S_ALL, plistID, values);
212
213 #ifdef DOUBLECHECK
214 size_t typesize = H5Tget_size(type);
215 char *val = (char *)(calloc(typesize, sizeof(char)));
216
217 hid_t ret2 = H5Dread(dsetID, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, val);
218 std::cerr << " .... typesize=" << typesize << " val=" << val
219 << std::endl;
220 free val;
221 #endif
222 }
223
224 H5Sclose(filespaceID);
225 H5Dclose(dsetID);
226 }
227
CreateAndStoreVar(std::string const & variableName,int dimSize,hid_t h5Type,const hsize_t * global_dims,const hsize_t * offsets,const hsize_t * counts,const void * values)228 void HDF5NativeWriter::CreateAndStoreVar(std::string const &variableName,
229 int dimSize, hid_t h5Type,
230 const hsize_t *global_dims,
231 const hsize_t *offsets,
232 const hsize_t *counts,
233 const void *values)
234 {
235 if (h5Type == H5T_STRING)
236 {
237 throw std::runtime_error("Sync with ADIOS2. It does not store string "
238 "var with dimensions yet!");
239 }
240
241 CheckWriteGroup();
242 hid_t fileSpace = H5Screate_simple(dimSize, global_dims, NULL);
243
244 hid_t dsetID = H5Dcreate(m_GroupId, variableName.c_str(), h5Type, fileSpace,
245 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
246 hid_t memSpace = H5Screate_simple(dimSize, counts, NULL);
247
248 // Select hyperslab
249 fileSpace = H5Dget_space(dsetID);
250 H5Sselect_hyperslab(fileSpace, H5S_SELECT_SET, offsets, NULL, counts, NULL);
251
252 // Create property list for collective dataset write.
253
254 hid_t plistID = H5Pcreate(H5P_DATASET_XFER);
255 #ifdef TEST_HDF5_MPI
256 H5Pset_dxpl_mpio(plistID, H5FD_MPIO_COLLECTIVE);
257 #endif
258 herr_t status =
259 H5Dwrite(dsetID, h5Type, memSpace, fileSpace, plistID, values);
260
261 if (status < 0)
262 {
263 throw std::runtime_error(
264 "ERROR: HDF5 file Write failed, in call to Write\n");
265 }
266
267 H5Dclose(dsetID);
268 H5Sclose(fileSpace);
269 H5Sclose(memSpace);
270 H5Pclose(plistID);
271 }
272
Advance()273 void HDF5NativeWriter::Advance()
274 {
275 if (m_GroupId >= 0)
276 {
277 H5Gclose(m_GroupId);
278 m_GroupId = -1;
279 }
280 ++m_CurrentTimeStep;
281 }
282
283 //
284 //
285 //
HDF5NativeReader(const std::string fileName)286 HDF5NativeReader::HDF5NativeReader(const std::string fileName)
287 : m_CurrentTimeStep(0), m_TotalTimeSteps(0)
288 {
289 m_FilePropertyListId = H5Pcreate(H5P_FILE_ACCESS);
290
291 #ifdef TEST_HDF5_MPI
292 // read a file collectively
293 H5Pset_fapl_mpio(m_FilePropertyListId, MPI_COMM_WORLD, MPI_INFO_NULL);
294 #endif
295
296 m_FileId = H5Fopen(fileName.c_str(), H5F_ACC_RDONLY, m_FilePropertyListId);
297 if (m_FileId < 0)
298 {
299 throw std::runtime_error("Unable to open " + fileName + " for reading");
300 }
301
302 std::string ts0 = "/Step0";
303 m_GroupId = H5Gopen(m_FileId, ts0.c_str(), H5P_DEFAULT);
304 if (m_GroupId < 0)
305 {
306 throw std::runtime_error("Unable to open group " + ts0 +
307 " for reading");
308 }
309
310 hid_t attrId = H5Aopen(m_FileId, "NumSteps", H5P_DEFAULT);
311 if (attrId < 0)
312 {
313 throw std::runtime_error("Unable to open attribute NumSteps");
314 }
315 H5Aread(attrId, H5T_NATIVE_UINT, &m_TotalTimeSteps);
316 H5Aclose(attrId);
317 }
318
~HDF5NativeReader()319 HDF5NativeReader::~HDF5NativeReader()
320 {
321 if (m_GroupId >= 0)
322 {
323 H5Gclose(m_GroupId);
324 }
325
326 H5Fclose(m_FileId);
327 H5Pclose(m_FilePropertyListId);
328 }
329
GetVarInfo(const std::string varName,std::vector<hsize_t> & dims,hid_t & h5Type)330 void HDF5NativeReader::GetVarInfo(const std::string varName,
331 std::vector<hsize_t> &dims, hid_t &h5Type)
332 {
333 hid_t dataSetId = H5Dopen(m_GroupId, varName.c_str(), H5P_DEFAULT);
334 if (dataSetId < 0)
335 {
336 throw std::runtime_error("Unable to open dataset " + varName +
337 " when getVarInfo");
338 }
339
340 hid_t fileSpaceId = H5Dget_space(dataSetId);
341 if (fileSpaceId < 0)
342 {
343 throw std::runtime_error("Unable to get filespace for dataset " +
344 varName);
345 }
346
347 const int ndims = H5Sget_simple_extent_ndims(fileSpaceId);
348 if (ndims < 0)
349 {
350 throw std::runtime_error(
351 "Unable to get number of dimensions for dataset " + varName);
352 }
353
354 dims.resize(ndims);
355 if (H5Sget_simple_extent_dims(fileSpaceId, dims.data(), NULL) != ndims)
356 {
357 throw std::runtime_error("Unable to get dimensions for dataset " +
358 varName);
359 }
360
361 h5Type = H5Dget_type(dataSetId);
362
363 H5Sclose(fileSpaceId);
364 H5Dclose(dataSetId);
365 }
366
Advance()367 bool HDF5NativeReader::Advance()
368 {
369 if (m_GroupId >= 0)
370 {
371 H5Gclose(m_GroupId);
372 m_GroupId = -1;
373 }
374
375 if (m_CurrentTimeStep + 1 >= m_TotalTimeSteps)
376 {
377 return false;
378 }
379
380 const std::string tsName = "Step" + std::to_string(m_CurrentTimeStep + 1);
381 m_GroupId = H5Gopen(m_FileId, tsName.c_str(), H5P_DEFAULT);
382 if (m_GroupId < 0)
383 {
384 throw std::runtime_error("Unable to open group " + tsName +
385 " for reading");
386 }
387 ++m_CurrentTimeStep;
388
389 return true;
390 }
391
ReadString(const std::string varName,std::string & result)392 void HDF5NativeReader::ReadString(const std::string varName,
393 std::string &result)
394 {
395 if (m_GroupId < 0)
396 {
397 throw std::runtime_error("Can't read variable " + varName +
398 " since a group is not currently open");
399 }
400
401 hid_t dataSetId = H5Dopen(m_GroupId, varName.c_str(), H5P_DEFAULT);
402 if (dataSetId < 0)
403 {
404 throw std::runtime_error("Unable to open dataset " + varName +
405 "when ReadVar");
406 }
407
408 hid_t h5Type = H5Dget_type(dataSetId);
409 size_t typesize = H5Tget_size(h5Type);
410
411 char *val = (char *)(calloc(typesize, sizeof(char)));
412 hid_t ret2 = H5Dread(dataSetId, h5Type, H5S_ALL, H5S_ALL, H5P_DEFAULT, val);
413
414 result.assign(val, typesize);
415 free(val);
416
417 H5Dclose(dataSetId);
418 }
419
ReadVar(const std::string varName,void * dataArray,hsize_t * offset,hsize_t * count,const size_t memspaceSize)420 void HDF5NativeReader::ReadVar(const std::string varName, void *dataArray,
421 hsize_t *offset, hsize_t *count,
422 const size_t memspaceSize)
423 {
424 if (m_GroupId < 0)
425 {
426 throw std::runtime_error("Can't read variable " + varName +
427 " since a group is not currently open");
428 }
429
430 hid_t dataSetId = H5Dopen(m_GroupId, varName.c_str(), H5P_DEFAULT);
431 if (dataSetId < 0)
432 {
433 throw std::runtime_error("Unable to open dataset " + varName +
434 "when ReadVar");
435 }
436 hid_t fileSpace = H5Dget_space(dataSetId);
437 if (fileSpace < 0)
438 {
439 throw std::runtime_error("Unable to get filespace for dataset " +
440 varName);
441 }
442
443 hid_t h5type = H5Dget_type(dataSetId);
444
445 // Extend reader to support read by hyperslab selection
446 // Reference link: https://support.hdfgroup.org/HDF5/Tutor/select.html
447 // Check if hyperspace is provided
448 if (offset && count)
449 {
450 // Get the dataspace
451 hid_t dataspace = H5Dget_space(dataSetId);
452 // Define hyperslab in the dataset
453 hid_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset,
454 NULL, count, NULL);
455 if (status < 0)
456 {
457 throw std::runtime_error(
458 "Unable to create a selection for dataset" + varName);
459 }
460
461 hsize_t dimsm[1];
462 dimsm[0] = memspaceSize;
463 hid_t memspace = H5Screate_simple(1, dimsm, NULL);
464
465 hid_t ret = H5Dread(dataSetId, h5type, memspace, dataspace, H5P_DEFAULT,
466 dataArray);
467 }
468 else
469 {
470 hid_t ret = H5Dread(dataSetId, h5type, H5S_ALL, H5S_ALL, H5P_DEFAULT,
471 dataArray);
472 }
473
474 H5Sclose(fileSpace);
475 H5Dclose(dataSetId);
476 }
477
478 //******************************************************************************
479 // 1D 1x8 test data
480 //******************************************************************************
481
482 // ADIOS2 write, native HDF5 read
TEST_F(HDF5WriteReadTest,ADIOS2HDF5WriteHDF5Read1D8)483 TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteHDF5Read1D8)
484 {
485 // Each process would write a 1x8 array and all processes would
486 // form a mpiSize * Nx 1D array
487 const std::string fname = "ADIOS2HDF5WriteHDF5Read1D8.h5";
488
489 int mpiRank = 0, mpiSize = 1;
490 // Number of rows
491 const std::size_t Nx = 8;
492
493 // Number of steps
494 const std::size_t NSteps = 3;
495
496 #ifdef TEST_HDF5_MPI
497 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
498 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
499 #endif
500
501 // Write test data using ADIOS2
502
503 #ifdef TEST_HDF5_MPI
504 adios2::ADIOS adios(MPI_COMM_WORLD);
505 #else
506 adios2::ADIOS adios;
507 #endif
508 adios2::IO io = adios.DeclareIO("TestIO");
509
510 // Declare 1D variables (NumOfProcesses * Nx)
511 // The local process' part (start, count) can be defined now or later
512 // before Write().
513 {
514 adios2::Dims shape{static_cast<unsigned int>(Nx * mpiSize)};
515 adios2::Dims start{static_cast<unsigned int>(Nx * mpiRank)};
516 adios2::Dims count{static_cast<unsigned int>(Nx)};
517
518 io.DefineVariable<std::string>("iString");
519 io.DefineVariable<int8_t>("i8", shape, start, count);
520 io.DefineVariable<int16_t>("i16", shape, start, count);
521 io.DefineVariable<int32_t>("i32", shape, start, count);
522 io.DefineVariable<int64_t>("i64", shape, start, count);
523 io.DefineVariable<uint8_t>("u8", shape, start, count);
524 io.DefineVariable<uint16_t>("u16", shape, start, count);
525 io.DefineVariable<uint32_t>("u32", shape, start, count);
526 io.DefineVariable<uint64_t>("u64", shape, start, count);
527 io.DefineVariable<float>("r32", shape, start, count);
528 io.DefineVariable<double>("r64", shape, start, count);
529 }
530
531 // Create the HDF5 Engine
532 io.SetEngine("HDF5");
533
534 // HDf5 engine calls the HDF5 common object that calls the hDF5 library.
535 // The IO functionality, SetParameters and AddTransports will be added
536 // in the future. For now `io.AddTransport("file", {
537 // "library", "MPI"}});` is omitted.
538 // })
539 // io.AddTransport("File");
540
541 adios2::Engine engine = io.Open(fname, adios2::Mode::Write);
542
543 for (size_t step = 0; step < NSteps; ++step)
544 {
545 // Generate test data for each process uniquely
546 SmallTestData currentTestData =
547 generateNewSmallTestData(m_TestData, step, mpiRank, mpiSize);
548
549 // Retrieve the variables that previously went out of scope
550 auto var_iString = io.InquireVariable<std::string>("iString");
551 auto var_i8 = io.InquireVariable<int8_t>("i8");
552 auto var_i16 = io.InquireVariable<int16_t>("i16");
553 auto var_i32 = io.InquireVariable<int32_t>("i32");
554 auto var_i64 = io.InquireVariable<int64_t>("i64");
555 auto var_u8 = io.InquireVariable<uint8_t>("u8");
556 auto var_u16 = io.InquireVariable<uint16_t>("u16");
557 auto var_u32 = io.InquireVariable<uint32_t>("u32");
558 auto var_u64 = io.InquireVariable<uint64_t>("u64");
559 auto var_r32 = io.InquireVariable<float>("r32");
560 auto var_r64 = io.InquireVariable<double>("r64");
561
562 // Make a 1D selection to describe the local dimensions of the
563 // variable we write and its offsets in the global spaces
564 adios2::Box<adios2::Dims> sel({mpiRank * Nx}, {Nx});
565 var_i8.SetSelection(sel);
566 var_i16.SetSelection(sel);
567 var_i32.SetSelection(sel);
568 var_i64.SetSelection(sel);
569 var_u8.SetSelection(sel);
570 var_u16.SetSelection(sel);
571 var_u32.SetSelection(sel);
572 var_u64.SetSelection(sel);
573 var_r32.SetSelection(sel);
574 var_r64.SetSelection(sel);
575
576 // Write each one
577 // fill in the variable with values from starting index to
578 // starting index + count
579 engine.BeginStep();
580 engine.Put(var_iString, currentTestData.S1);
581 engine.Put(var_i8, currentTestData.I8.data());
582 engine.Put(var_i16, currentTestData.I16.data());
583 engine.Put(var_i32, currentTestData.I32.data());
584 engine.Put(var_i64, currentTestData.I64.data());
585 engine.Put(var_u8, currentTestData.U8.data());
586 engine.Put(var_u16, currentTestData.U16.data());
587 engine.Put(var_u32, currentTestData.U32.data());
588 engine.Put(var_u64, currentTestData.U64.data());
589 engine.Put(var_r32, currentTestData.R32.data());
590 engine.Put(var_r64, currentTestData.R64.data());
591 // Advance to the next time step
592 engine.EndStep();
593 }
594
595 // Close the file
596 engine.Close();
597
598 bool doRead = true;
599 if (doRead)
600 {
601 const size_t arraySize = Nx;
602 std::string IString;
603 std::array<int8_t, arraySize> I8;
604 std::array<int16_t, arraySize> I16;
605 std::array<int32_t, arraySize> I32;
606 std::array<int64_t, arraySize> I64;
607 std::array<uint8_t, arraySize> U8;
608 std::array<uint16_t, arraySize> U16;
609 std::array<uint32_t, arraySize> U32;
610 std::array<uint64_t, arraySize> U64;
611 std::array<float, arraySize> R32;
612 std::array<double, arraySize> R64;
613
614 HDF5NativeReader hdf5Reader(fname);
615 // 1D
616 hsize_t count[1], offset[1];
617 offset[0] = mpiRank * Nx;
618 count[0] = Nx;
619 size_t globalArraySize = Nx * mpiSize;
620
621 // For each variable, we would verify its global size and type.
622 // Then we would retrieve the data back which is written by the
623 // current process and validate the value
624 for (size_t t = 0; t < NSteps; ++t)
625 {
626 SmallTestData currentTestData =
627 generateNewSmallTestData(m_TestData, t, mpiRank, mpiSize);
628
629 std::vector<hsize_t> gDims;
630 hid_t h5Type;
631
632 // auto var_iString = io.InquireVariable<std::string>("iString");
633 hdf5Reader.GetVarInfo("iString", gDims, h5Type);
634 // ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_IN), 1);
635 ASSERT_EQ(gDims.size(), 0);
636 hdf5Reader.ReadString("iString", IString);
637
638 hdf5Reader.GetVarInfo("i8", gDims, h5Type);
639 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_INT8), 1);
640 ASSERT_EQ(gDims.size(), 1);
641 ASSERT_EQ(gDims[0], globalArraySize);
642 hdf5Reader.ReadVar("i8", I8.data(), offset, count, arraySize);
643
644 hdf5Reader.GetVarInfo("i16", gDims, h5Type);
645 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_SHORT), 1);
646 ASSERT_EQ(gDims.size(), 1);
647 ASSERT_EQ(gDims[0], globalArraySize);
648 hdf5Reader.ReadVar("i16", I16.data(), offset, count, arraySize);
649
650 hdf5Reader.GetVarInfo("i32", gDims, h5Type);
651 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_INT), 1);
652 ASSERT_EQ(gDims.size(), 1);
653 ASSERT_EQ(gDims[0], globalArraySize);
654 hdf5Reader.ReadVar("i32", I32.data(), offset, count, arraySize);
655
656 hdf5Reader.GetVarInfo("i64", gDims, h5Type);
657 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_LONG), 1);
658 ASSERT_EQ(gDims.size(), 1);
659 ASSERT_EQ(gDims[0], globalArraySize);
660 hdf5Reader.ReadVar("i64", I64.data(), offset, count, arraySize);
661
662 hdf5Reader.GetVarInfo("u8", gDims, h5Type);
663 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_UCHAR), 1);
664 ASSERT_EQ(gDims.size(), 1);
665 ASSERT_EQ(gDims[0], globalArraySize);
666 hdf5Reader.ReadVar("u8", U8.data(), offset, count, arraySize);
667
668 hdf5Reader.GetVarInfo("u16", gDims, h5Type);
669 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_USHORT), 1);
670 ASSERT_EQ(gDims.size(), 1);
671 ASSERT_EQ(gDims[0], globalArraySize);
672 hdf5Reader.ReadVar("u16", U16.data(), offset, count, arraySize);
673
674 hdf5Reader.GetVarInfo("u32", gDims, h5Type);
675 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_UINT), 1);
676 ASSERT_EQ(gDims.size(), 1);
677 ASSERT_EQ(gDims[0], globalArraySize);
678 hdf5Reader.ReadVar("u32", U32.data(), offset, count, arraySize);
679
680 hdf5Reader.GetVarInfo("u64", gDims, h5Type);
681 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_ULONG), 1);
682 ASSERT_EQ(gDims.size(), 1);
683 ASSERT_EQ(gDims[0], globalArraySize);
684 hdf5Reader.ReadVar("u64", U64.data(), offset, count, arraySize);
685
686 hdf5Reader.GetVarInfo("r32", gDims, h5Type);
687 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_FLOAT), 1);
688 ASSERT_EQ(gDims.size(), 1);
689 ASSERT_EQ(gDims[0], globalArraySize);
690 hdf5Reader.ReadVar("r32", R32.data(), offset, count, arraySize);
691
692 hdf5Reader.GetVarInfo("r64", gDims, h5Type);
693 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_DOUBLE), 1);
694 ASSERT_EQ(gDims.size(), 1);
695 ASSERT_EQ(gDims[0], globalArraySize);
696 hdf5Reader.ReadVar("r64", R64.data(), offset, count, arraySize);
697
698 EXPECT_EQ(IString, currentTestData.S1);
699
700 // Check if it's correct
701 for (size_t i = 0; i < Nx; ++i)
702 {
703 std::stringstream ss;
704 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
705 std::string msg = ss.str();
706
707 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
708 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
709 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
710 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
711 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
712 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
713 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
714 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
715 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
716 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
717 }
718 hdf5Reader.Advance();
719 }
720 }
721 }
722
723 // ADIOS2 write, ADIOS2 read
TEST_F(HDF5WriteReadTest,ADIOS2HDF5WriteADIOS2HDF5Read1D8)724 TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteADIOS2HDF5Read1D8)
725 {
726 // Each process would write a 1x8 array and all processes would
727 // form a mpiSize * Nx 1D array
728 const std::string fname = "ADIOS2HDF5WriteADIOS2HDF5Read1D8.h5";
729
730 int mpiRank = 0, mpiSize = 1;
731 // Number of rows
732 const std::size_t Nx = 8;
733
734 // Number of steps
735 const std::size_t NSteps = 3;
736
737 #ifdef TEST_HDF5_MPI
738 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
739 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
740 #endif
741
742 // Write test data using ADIOS2
743
744 #ifdef TEST_HDF5_MPI
745 adios2::ADIOS adios(MPI_COMM_WORLD);
746 #else
747 adios2::ADIOS adios;
748 #endif
749 adios2::IO io = adios.DeclareIO("TestIO");
750
751 // Declare 1D variables (NumOfProcesses * Nx)
752 // The local process' part (start, count) can be defined now or later
753 // before Write().
754 {
755 adios2::Dims shape{static_cast<unsigned int>(Nx * mpiSize)};
756 adios2::Dims start{static_cast<unsigned int>(Nx * mpiRank)};
757 adios2::Dims count{static_cast<unsigned int>(Nx)};
758
759 io.DefineVariable<std::string>("iString");
760 io.DefineVariable<int8_t>("i8", shape, start, count);
761 io.DefineVariable<int16_t>("i16", shape, start, count);
762 io.DefineVariable<int32_t>("i32", shape, start, count);
763 io.DefineVariable<int64_t>("i64", shape, start, count);
764 io.DefineVariable<uint8_t>("u8", shape, start, count);
765 io.DefineVariable<uint16_t>("u16", shape, start, count);
766 io.DefineVariable<uint32_t>("u32", shape, start, count);
767 io.DefineVariable<uint64_t>("u64", shape, start, count);
768 io.DefineVariable<float>("r32", shape, start, count);
769 io.DefineVariable<double>("r64", shape, start, count);
770 }
771
772 // Create the HDF5 Engine
773 io.SetEngine("HDF5");
774
775 // HDf5 engine calls the HDF5 common object that calls the hDF5 library.
776 // The IO functionality, SetParameters and AddTransports will be added
777 // in the future. For now `io.AddTransport("file", {
778 // "library", "MPI"}});` is omitted.
779 // })
780 // io.AddTransport("File");
781
782 adios2::Engine engine = io.Open(fname, adios2::Mode::Write);
783
784 for (size_t step = 0; step < NSteps; ++step)
785 {
786 // Generate test data for each process uniquely
787 SmallTestData currentTestData =
788 generateNewSmallTestData(m_TestData, step, mpiRank, mpiSize);
789
790 // Retrieve the variables that previously went out of scope
791 auto var_iString = io.InquireVariable<std::string>("iString");
792 auto var_i8 = io.InquireVariable<int8_t>("i8");
793 auto var_i16 = io.InquireVariable<int16_t>("i16");
794 auto var_i32 = io.InquireVariable<int32_t>("i32");
795 auto var_i64 = io.InquireVariable<int64_t>("i64");
796 auto var_u8 = io.InquireVariable<uint8_t>("u8");
797 auto var_u16 = io.InquireVariable<uint16_t>("u16");
798 auto var_u32 = io.InquireVariable<uint32_t>("u32");
799 auto var_u64 = io.InquireVariable<uint64_t>("u64");
800 auto var_r32 = io.InquireVariable<float>("r32");
801 auto var_r64 = io.InquireVariable<double>("r64");
802
803 // Make a 1D selection to describe the local dimensions of the
804 // variable we write and its offsets in the global spaces
805
806 adios2::Box<adios2::Dims> sel({mpiRank * Nx}, {Nx});
807
808 EXPECT_THROW(var_iString.SetSelection(sel), std::invalid_argument);
809
810 var_i8.SetSelection(sel);
811 var_i16.SetSelection(sel);
812 var_i32.SetSelection(sel);
813 var_i64.SetSelection(sel);
814 var_u8.SetSelection(sel);
815 var_u16.SetSelection(sel);
816 var_u32.SetSelection(sel);
817 var_u64.SetSelection(sel);
818 var_r32.SetSelection(sel);
819 var_r64.SetSelection(sel);
820
821 // Write each one
822 // fill in the variable with values from starting index to
823 // starting index + count
824 engine.BeginStep();
825 engine.Put(var_iString, currentTestData.S1);
826 engine.Put(var_i8, currentTestData.I8.data());
827 engine.Put(var_i16, currentTestData.I16.data());
828 engine.Put(var_i32, currentTestData.I32.data());
829 engine.Put(var_i64, currentTestData.I64.data());
830 engine.Put(var_u8, currentTestData.U8.data());
831 engine.Put(var_u16, currentTestData.U16.data());
832 engine.Put(var_u32, currentTestData.U32.data());
833 engine.Put(var_u64, currentTestData.U64.data());
834 engine.Put(var_r32, currentTestData.R32.data());
835 engine.Put(var_r64, currentTestData.R64.data());
836 // Advance to the next time step
837 engine.EndStep();
838 }
839
840 // Close the file
841 engine.Close();
842
843 {
844 adios2::IO io = adios.DeclareIO("HDF5ReadIO");
845 io.SetEngine("HDF5");
846
847 adios2::Engine hdf5Reader = io.Open(fname, adios2::Mode::Read);
848
849 auto var_iString = io.InquireVariable<std::string>("iString");
850 EXPECT_TRUE(var_iString);
851 ASSERT_EQ(var_iString.Shape().size(), 0);
852 ASSERT_EQ(var_iString.Steps(), NSteps);
853
854 auto var_i8 = io.InquireVariable<int8_t>("i8");
855 EXPECT_TRUE(var_i8);
856 ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
857 ASSERT_EQ(var_i8.Steps(), NSteps);
858 ASSERT_EQ(var_i8.Shape()[0], mpiSize * Nx);
859
860 auto var_i16 = io.InquireVariable<int16_t>("i16");
861 EXPECT_TRUE(var_i16);
862 ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
863 ASSERT_EQ(var_i16.Steps(), NSteps);
864 ASSERT_EQ(var_i16.Shape()[0], mpiSize * Nx);
865
866 auto var_i32 = io.InquireVariable<int32_t>("i32");
867 EXPECT_TRUE(var_i32);
868 ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
869 ASSERT_EQ(var_i32.Steps(), NSteps);
870 ASSERT_EQ(var_i32.Shape()[0], mpiSize * Nx);
871
872 auto var_i64 = io.InquireVariable<int64_t>("i64");
873 EXPECT_TRUE(var_i64);
874 ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
875 ASSERT_EQ(var_i64.Steps(), NSteps);
876 ASSERT_EQ(var_i64.Shape()[0], mpiSize * Nx);
877
878 auto var_u8 = io.InquireVariable<uint8_t>("u8");
879 EXPECT_TRUE(var_u8);
880 ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
881 ASSERT_EQ(var_u8.Steps(), NSteps);
882 ASSERT_EQ(var_u8.Shape()[0], mpiSize * Nx);
883
884 auto var_u16 = io.InquireVariable<uint16_t>("u16");
885 EXPECT_TRUE(var_u16);
886 ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
887 ASSERT_EQ(var_u16.Steps(), NSteps);
888 ASSERT_EQ(var_u16.Shape()[0], mpiSize * Nx);
889
890 auto var_u32 = io.InquireVariable<uint32_t>("u32");
891 EXPECT_TRUE(var_u32);
892 ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
893 ASSERT_EQ(var_u32.Steps(), NSteps);
894 ASSERT_EQ(var_u32.Shape()[0], mpiSize * Nx);
895
896 auto var_u64 = io.InquireVariable<uint64_t>("u64");
897 EXPECT_TRUE(var_u64);
898 ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
899 ASSERT_EQ(var_u64.Steps(), NSteps);
900 ASSERT_EQ(var_u64.Shape()[0], mpiSize * Nx);
901
902 auto var_r32 = io.InquireVariable<float>("r32");
903 EXPECT_TRUE(var_r32);
904 ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
905 ASSERT_EQ(var_r32.Steps(), NSteps);
906 ASSERT_EQ(var_r32.Shape()[0], mpiSize * Nx);
907
908 auto var_r64 = io.InquireVariable<double>("r64");
909 EXPECT_TRUE(var_r64);
910 ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
911 ASSERT_EQ(var_r64.Steps(), NSteps);
912 ASSERT_EQ(var_r64.Shape()[0], mpiSize * Nx);
913
914 // TODO: other types
915
916 SmallTestData testData;
917
918 std::string IString;
919 std::array<int8_t, Nx> I8;
920 std::array<int16_t, Nx> I16;
921 std::array<int32_t, Nx> I32;
922 std::array<int64_t, Nx> I64;
923 std::array<uint8_t, Nx> U8;
924 std::array<uint16_t, Nx> U16;
925 std::array<uint32_t, Nx> U32;
926 std::array<uint64_t, Nx> U64;
927 std::array<float, Nx> R32;
928 std::array<double, Nx> R64;
929
930 const adios2::Dims start{mpiRank * Nx};
931 const adios2::Dims count{Nx};
932
933 const adios2::Box<adios2::Dims> sel(start, count);
934
935 var_i8.SetSelection(sel);
936 var_i16.SetSelection(sel);
937 var_i32.SetSelection(sel);
938 var_i64.SetSelection(sel);
939
940 var_u8.SetSelection(sel);
941 var_u16.SetSelection(sel);
942 var_u32.SetSelection(sel);
943 var_u64.SetSelection(sel);
944
945 var_r32.SetSelection(sel);
946 var_r64.SetSelection(sel);
947
948 for (size_t t = 0; t < NSteps; ++t)
949 {
950 var_i8.SetStepSelection({t, 1});
951 var_i16.SetStepSelection({t, 1});
952 var_i32.SetStepSelection({t, 1});
953 var_i64.SetStepSelection({t, 1});
954
955 var_u8.SetStepSelection({t, 1});
956 var_u16.SetStepSelection({t, 1});
957 var_u32.SetStepSelection({t, 1});
958 var_u64.SetStepSelection({t, 1});
959
960 var_r32.SetStepSelection({t, 1});
961 var_r64.SetStepSelection({t, 1});
962
963 // Generate test data for each rank uniquely
964 SmallTestData currentTestData = generateNewSmallTestData(
965 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
966
967 hdf5Reader.Get(var_iString, IString);
968
969 hdf5Reader.Get(var_i8, I8.data());
970 hdf5Reader.Get(var_i16, I16.data());
971 hdf5Reader.Get(var_i32, I32.data());
972 hdf5Reader.Get(var_i64, I64.data());
973
974 hdf5Reader.Get(var_u8, U8.data());
975 hdf5Reader.Get(var_u16, U16.data());
976 hdf5Reader.Get(var_u32, U32.data());
977 hdf5Reader.Get(var_u64, U64.data());
978
979 hdf5Reader.Get(var_r32, R32.data());
980 hdf5Reader.Get(var_r64, R64.data());
981 hdf5Reader.PerformGets();
982
983 EXPECT_EQ(IString, currentTestData.S1);
984
985 for (size_t i = 0; i < Nx; ++i)
986 {
987 std::stringstream ss;
988 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
989 std::string msg = ss.str();
990
991 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
992 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
993 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
994 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
995 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
996 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
997 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
998 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
999 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
1000 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
1001 }
1002 }
1003 hdf5Reader.Close();
1004 }
1005 }
1006
1007 // Native HDF5 write, ADIOS2 read
TEST_F(HDF5WriteReadTest,HDF5WriteADIOS2HDF5Read1D8)1008 TEST_F(HDF5WriteReadTest, HDF5WriteADIOS2HDF5Read1D8)
1009 {
1010 std::string fname = "HDF5WriteADIOS2HDF5Read1D8.h5";
1011
1012 int mpiRank = 0, mpiSize = 1;
1013 // Number of rows
1014 const std::size_t Nx = 8;
1015
1016 // Number of steps
1017 const std::size_t NSteps = 3;
1018
1019 {
1020 #ifdef TEST_HDF5_MPI
1021 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
1022 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
1023
1024 HDF5NativeWriter h5writer(fname, MPI_COMM_WORLD);
1025 #else
1026 HDF5NativeWriter h5writer(fname);
1027 #endif
1028
1029 int dimSize = 1;
1030 hsize_t global_dims[1] = {Nx * mpiSize};
1031 hsize_t count[1] = {Nx};
1032 hsize_t offset[1] = {Nx * mpiRank};
1033
1034 for (size_t step = 0; step < NSteps; ++step)
1035 {
1036 // Generate test data for each process uniquely
1037 SmallTestData currentTestData =
1038 generateNewSmallTestData(m_TestData, step, mpiRank, mpiSize);
1039
1040 h5writer.CreateAndStoreScalar("iString", H5T_STRING,
1041 currentTestData.S1.data());
1042 h5writer.CreateAndStoreVar("i8", dimSize, H5T_NATIVE_INT8,
1043 global_dims, offset, count,
1044 currentTestData.I8.data());
1045 h5writer.CreateAndStoreVar("i16", dimSize, H5T_NATIVE_SHORT,
1046 global_dims, offset, count,
1047 currentTestData.I16.data());
1048 h5writer.CreateAndStoreVar("i32", dimSize, H5T_NATIVE_INT,
1049 global_dims, offset, count,
1050 currentTestData.I32.data());
1051 h5writer.CreateAndStoreVar("i64", dimSize, H5T_NATIVE_LONG,
1052 global_dims, offset, count,
1053 currentTestData.I64.data());
1054 h5writer.CreateAndStoreVar("u8", dimSize, H5T_NATIVE_UCHAR,
1055 global_dims, offset, count,
1056 currentTestData.U8.data());
1057 h5writer.CreateAndStoreVar("u16", dimSize, H5T_NATIVE_USHORT,
1058 global_dims, offset, count,
1059 currentTestData.U16.data());
1060 h5writer.CreateAndStoreVar("u32", dimSize, H5T_NATIVE_UINT,
1061 global_dims, offset, count,
1062 currentTestData.U32.data());
1063 h5writer.CreateAndStoreVar("u64", dimSize, H5T_NATIVE_ULONG,
1064 global_dims, offset, count,
1065 currentTestData.U64.data());
1066 h5writer.CreateAndStoreVar("r32", dimSize, H5T_NATIVE_FLOAT,
1067 global_dims, offset, count,
1068 currentTestData.R32.data());
1069 h5writer.CreateAndStoreVar("r64", dimSize, H5T_NATIVE_DOUBLE,
1070 global_dims, offset, count,
1071 currentTestData.R64.data());
1072 h5writer.Advance();
1073 }
1074 }
1075
1076 { // ADIOS2 read back
1077
1078 // Write test data using ADIOS2
1079
1080 #ifdef TEST_HDF5_MPI
1081 adios2::ADIOS adios(MPI_COMM_WORLD);
1082 #else
1083 adios2::ADIOS adios;
1084 #endif
1085 adios2::IO io = adios.DeclareIO("HDF5ReadIO");
1086 io.SetEngine("HDF5");
1087
1088 adios2::Engine hdf5Reader = io.Open(fname, adios2::Mode::Read);
1089
1090 auto var_iString = io.InquireVariable<std::string>("iString");
1091 EXPECT_TRUE(var_iString);
1092 ASSERT_EQ(var_iString.Shape().size(), 0);
1093 ASSERT_EQ(var_iString.Steps(), NSteps);
1094
1095 auto var_i8 = io.InquireVariable<int8_t>("i8");
1096 EXPECT_TRUE(var_i8);
1097 ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
1098 ASSERT_EQ(var_i8.Steps(), NSteps);
1099 ASSERT_EQ(var_i8.Shape()[0], mpiSize * Nx);
1100
1101 auto var_i16 = io.InquireVariable<int16_t>("i16");
1102 EXPECT_TRUE(var_i16);
1103 ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
1104 ASSERT_EQ(var_i16.Steps(), NSteps);
1105 ASSERT_EQ(var_i16.Shape()[0], mpiSize * Nx);
1106
1107 auto var_i32 = io.InquireVariable<int32_t>("i32");
1108 EXPECT_TRUE(var_i32);
1109 ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
1110 ASSERT_EQ(var_i32.Steps(), NSteps);
1111 ASSERT_EQ(var_i32.Shape()[0], mpiSize * Nx);
1112
1113 auto var_i64 = io.InquireVariable<int64_t>("i64");
1114 EXPECT_TRUE(var_i64);
1115 ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
1116 ASSERT_EQ(var_i64.Steps(), NSteps);
1117 ASSERT_EQ(var_i64.Shape()[0], mpiSize * Nx);
1118
1119 auto var_u8 = io.InquireVariable<uint8_t>("u8");
1120 EXPECT_TRUE(var_u8);
1121 ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
1122 ASSERT_EQ(var_u8.Steps(), NSteps);
1123 ASSERT_EQ(var_u8.Shape()[0], mpiSize * Nx);
1124
1125 auto var_u16 = io.InquireVariable<uint16_t>("u16");
1126 EXPECT_TRUE(var_u16);
1127 ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
1128 ASSERT_EQ(var_u16.Steps(), NSteps);
1129 ASSERT_EQ(var_u16.Shape()[0], mpiSize * Nx);
1130
1131 auto var_u32 = io.InquireVariable<uint32_t>("u32");
1132 EXPECT_TRUE(var_u32);
1133 ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
1134 ASSERT_EQ(var_u32.Steps(), NSteps);
1135 ASSERT_EQ(var_u32.Shape()[0], mpiSize * Nx);
1136
1137 auto var_u64 = io.InquireVariable<uint64_t>("u64");
1138 EXPECT_TRUE(var_u64);
1139 ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
1140 ASSERT_EQ(var_u64.Steps(), NSteps);
1141 ASSERT_EQ(var_u64.Shape()[0], mpiSize * Nx);
1142
1143 auto var_r32 = io.InquireVariable<float>("r32");
1144 EXPECT_TRUE(var_r32);
1145 ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
1146 ASSERT_EQ(var_r32.Steps(), NSteps);
1147 ASSERT_EQ(var_r32.Shape()[0], mpiSize * Nx);
1148
1149 auto var_r64 = io.InquireVariable<double>("r64");
1150 EXPECT_TRUE(var_r64);
1151 ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
1152 ASSERT_EQ(var_r64.Steps(), NSteps);
1153 ASSERT_EQ(var_r64.Shape()[0], mpiSize * Nx);
1154
1155 // TODO: other types
1156
1157 SmallTestData testData;
1158
1159 std::string IString;
1160 std::array<int8_t, Nx> I8;
1161 std::array<int16_t, Nx> I16;
1162 std::array<int32_t, Nx> I32;
1163 std::array<int64_t, Nx> I64;
1164 std::array<uint8_t, Nx> U8;
1165 std::array<uint16_t, Nx> U16;
1166 std::array<uint32_t, Nx> U32;
1167 std::array<uint64_t, Nx> U64;
1168 std::array<float, Nx> R32;
1169 std::array<double, Nx> R64;
1170
1171 const adios2::Dims start{mpiRank * Nx};
1172 const adios2::Dims count{Nx};
1173
1174 const adios2::Box<adios2::Dims> sel(start, count);
1175
1176 var_i8.SetSelection(sel);
1177 var_i16.SetSelection(sel);
1178 var_i32.SetSelection(sel);
1179 var_i64.SetSelection(sel);
1180
1181 var_u8.SetSelection(sel);
1182 var_u16.SetSelection(sel);
1183 var_u32.SetSelection(sel);
1184 var_u64.SetSelection(sel);
1185
1186 var_r32.SetSelection(sel);
1187 var_r64.SetSelection(sel);
1188
1189 for (size_t t = 0; t < NSteps; ++t)
1190 {
1191 var_i8.SetStepSelection({t, 1});
1192 var_i16.SetStepSelection({t, 1});
1193 var_i32.SetStepSelection({t, 1});
1194 var_i64.SetStepSelection({t, 1});
1195
1196 var_u8.SetStepSelection({t, 1});
1197 var_u16.SetStepSelection({t, 1});
1198 var_u32.SetStepSelection({t, 1});
1199 var_u64.SetStepSelection({t, 1});
1200
1201 var_r32.SetStepSelection({t, 1});
1202 var_r64.SetStepSelection({t, 1});
1203
1204 // Generate test data for each rank uniquely
1205 SmallTestData currentTestData = generateNewSmallTestData(
1206 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
1207
1208 hdf5Reader.Get(var_iString, IString);
1209
1210 hdf5Reader.Get(var_i8, I8.data());
1211 hdf5Reader.Get(var_i16, I16.data());
1212 hdf5Reader.Get(var_i32, I32.data());
1213 hdf5Reader.Get(var_i64, I64.data());
1214
1215 hdf5Reader.Get(var_u8, U8.data());
1216 hdf5Reader.Get(var_u16, U16.data());
1217 hdf5Reader.Get(var_u32, U32.data());
1218 hdf5Reader.Get(var_u64, U64.data());
1219
1220 hdf5Reader.Get(var_r32, R32.data());
1221 hdf5Reader.Get(var_r64, R64.data());
1222
1223 hdf5Reader.PerformGets();
1224
1225 EXPECT_EQ(IString, currentTestData.S1);
1226
1227 for (size_t i = 0; i < Nx; ++i)
1228 {
1229 std::stringstream ss;
1230 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
1231 std::string msg = ss.str();
1232
1233 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
1234 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
1235 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
1236 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
1237 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
1238 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
1239 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
1240 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
1241 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
1242 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
1243 }
1244 }
1245 hdf5Reader.Close();
1246 }
1247 }
1248
1249 //******************************************************************************
1250 // 2D 2x4 test data
1251 //******************************************************************************
1252
1253 // ADIOS2 write, native HDF5 read
TEST_F(HDF5WriteReadTest,ADIOS2HDF5WriteHDF5Read2D2x4)1254 TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteHDF5Read2D2x4)
1255 {
1256 // Each process would write a 2x4 array and all processes would
1257 // form a 2D 2 * (numberOfProcess*Nx) matrix where Nx is 4 here
1258 std::string fname = "ADIOS2HDF5WriteHDF5Read2D2x4Test.h5";
1259
1260 int mpiRank = 0, mpiSize = 1;
1261 // Number of rows
1262 const std::size_t Nx = 4;
1263
1264 // Number of rows
1265 const std::size_t Ny = 2;
1266
1267 // Number of steps
1268 const std::size_t NSteps = 3;
1269
1270 #ifdef TEST_HDF5_MPI
1271 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
1272 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
1273 #endif
1274
1275 // Write test data using ADIOS2
1276 {
1277 #ifdef TEST_HDF5_MPI
1278 adios2::ADIOS adios(MPI_COMM_WORLD);
1279 #else
1280 adios2::ADIOS adios;
1281 #endif
1282 adios2::IO io = adios.DeclareIO("TestIO");
1283
1284 // Declare 2D variables (Ny * (NumOfProcesses * Nx))
1285 // The local process' part (start, count) can be defined now or later
1286 // before Write().
1287 {
1288 adios2::Dims shape{static_cast<unsigned int>(Ny),
1289 static_cast<unsigned int>(Nx * mpiSize)};
1290 adios2::Dims start{static_cast<unsigned int>(0),
1291 static_cast<unsigned int>(mpiRank * Nx)};
1292 adios2::Dims count{static_cast<unsigned int>(Ny),
1293 static_cast<unsigned int>(Nx)};
1294 auto var_iString = io.DefineVariable<std::string>("iString");
1295 auto var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count);
1296 auto var_i16 =
1297 io.DefineVariable<int16_t>("i16", shape, start, count);
1298 auto var_i32 =
1299 io.DefineVariable<int32_t>("i32", shape, start, count);
1300 auto var_i64 =
1301 io.DefineVariable<int64_t>("i64", shape, start, count);
1302 auto var_u8 = io.DefineVariable<uint8_t>("u8", shape, start, count);
1303 auto var_u16 =
1304 io.DefineVariable<uint16_t>("u16", shape, start, count);
1305 auto var_u32 =
1306 io.DefineVariable<uint32_t>("u32", shape, start, count);
1307 auto var_u64 =
1308 io.DefineVariable<uint64_t>("u64", shape, start, count);
1309 auto var_r32 = io.DefineVariable<float>("r32", shape, start, count);
1310 auto var_r64 =
1311 io.DefineVariable<double>("r64", shape, start, count);
1312 }
1313
1314 // Create the HDF5 Engine
1315 io.SetEngine("HDF5");
1316
1317 // HDf5 engine calls the HDF5 common object that calls the hDF5 library.
1318 // The IO functionality, SetParameters and AddTransports will be added
1319 // in the future. For now `io.AddTransport("file", {
1320 // "library", "MPI"}});` is omitted.
1321 // })
1322 io.AddTransport("file");
1323
1324 adios2::Engine engine = io.Open(fname, adios2::Mode::Write);
1325
1326 for (size_t step = 0; step < NSteps; ++step)
1327 {
1328 // Generate test data for each process uniquely
1329 SmallTestData currentTestData =
1330 generateNewSmallTestData(m_TestData, step, mpiRank, mpiSize);
1331
1332 // Retrieve the variables that previously went out of scope
1333 auto var_iString = io.InquireVariable<std::string>("iString");
1334 auto var_i8 = io.InquireVariable<int8_t>("i8");
1335 auto var_i16 = io.InquireVariable<int16_t>("i16");
1336 auto var_i32 = io.InquireVariable<int32_t>("i32");
1337 auto var_i64 = io.InquireVariable<int64_t>("i64");
1338 auto var_u8 = io.InquireVariable<uint8_t>("u8");
1339 auto var_u16 = io.InquireVariable<uint16_t>("u16");
1340 auto var_u32 = io.InquireVariable<uint32_t>("u32");
1341 auto var_u64 = io.InquireVariable<uint64_t>("u64");
1342 auto var_r32 = io.InquireVariable<float>("r32");
1343 auto var_r64 = io.InquireVariable<double>("r64");
1344
1345 // Make a 2D selection to describe the local dimensions of the
1346 // variable we write and its offsets in the global spaces
1347 adios2::Box<adios2::Dims> sel(
1348 {0, static_cast<unsigned int>(mpiRank * Nx)}, {Ny, Nx});
1349 var_i8.SetSelection(sel);
1350 var_i16.SetSelection(sel);
1351 var_i32.SetSelection(sel);
1352 var_i64.SetSelection(sel);
1353 var_u8.SetSelection(sel);
1354 var_u16.SetSelection(sel);
1355 var_u32.SetSelection(sel);
1356 var_u64.SetSelection(sel);
1357 var_r32.SetSelection(sel);
1358 var_r64.SetSelection(sel);
1359
1360 // Write each one
1361 // fill in the variable with values from starting index to
1362 // starting index + count
1363 engine.Put(var_iString, currentTestData.S1);
1364 engine.Put(var_i8, currentTestData.I8.data());
1365 engine.Put(var_i16, currentTestData.I16.data());
1366 engine.Put(var_i32, currentTestData.I32.data());
1367 engine.Put(var_i64, currentTestData.I64.data());
1368 engine.Put(var_u8, currentTestData.U8.data());
1369 engine.Put(var_u16, currentTestData.U16.data());
1370 engine.Put(var_u32, currentTestData.U32.data());
1371 engine.Put(var_u64, currentTestData.U64.data());
1372 engine.Put(var_r32, currentTestData.R32.data());
1373 engine.Put(var_r64, currentTestData.R64.data());
1374
1375 // Advance to the next time step
1376 engine.EndStep();
1377 }
1378
1379 // Close the file
1380 engine.Close();
1381 }
1382
1383 {
1384 HDF5NativeReader hdf5Reader(fname);
1385
1386 std::string IString;
1387 const size_t arraySize = Nx * Ny;
1388 std::array<int8_t, arraySize> I8;
1389 std::array<int16_t, arraySize> I16;
1390 std::array<int32_t, arraySize> I32;
1391 std::array<int64_t, arraySize> I64;
1392 std::array<uint8_t, arraySize> U8;
1393 std::array<uint16_t, arraySize> U16;
1394 std::array<uint32_t, arraySize> U32;
1395 std::array<uint64_t, arraySize> U64;
1396 std::array<float, arraySize> R32;
1397 std::array<double, arraySize> R64;
1398 // 2D
1399 hsize_t count[2], offset[2];
1400
1401 offset[0] = 0;
1402 offset[1] = mpiRank * Nx;
1403 count[0] = Ny;
1404 count[1] = Nx;
1405
1406 size_t globalArraySize = Nx * mpiSize;
1407
1408 // For each variable, we would verify its global size and type.
1409 // Then we would retrieve the data back which is written by the
1410 // current process and validate the value
1411 for (size_t t = 0; t < NSteps; ++t)
1412 {
1413 SmallTestData currentTestData =
1414 generateNewSmallTestData(m_TestData, t, mpiRank, mpiSize);
1415
1416 std::vector<hsize_t> gDims;
1417 hid_t h5Type;
1418
1419 hdf5Reader.GetVarInfo("iString", gDims, h5Type);
1420 // ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_IN), 1);
1421 ASSERT_EQ(gDims.size(), 0);
1422 hdf5Reader.ReadString("iString", IString);
1423
1424 hdf5Reader.GetVarInfo("i8", gDims, h5Type);
1425 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_INT8), 1);
1426 ASSERT_EQ(gDims.size(), 2);
1427 ASSERT_EQ(gDims[0], 2);
1428 ASSERT_EQ(gDims[1], globalArraySize);
1429 hdf5Reader.ReadVar("i8", I8.data(), offset, count, arraySize);
1430
1431 hdf5Reader.GetVarInfo("i16", gDims, h5Type);
1432 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_SHORT), 1);
1433 ASSERT_EQ(gDims.size(), 2);
1434 ASSERT_EQ(gDims[0], 2);
1435 ASSERT_EQ(gDims[1], globalArraySize);
1436 hdf5Reader.ReadVar("i16", I16.data(), offset, count, arraySize);
1437
1438 hdf5Reader.GetVarInfo("i32", gDims, h5Type);
1439 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_INT), 1);
1440 ASSERT_EQ(gDims.size(), 2);
1441 ASSERT_EQ(gDims[0], 2);
1442 ASSERT_EQ(gDims[1], globalArraySize);
1443 hdf5Reader.ReadVar("i32", I32.data(), offset, count, arraySize);
1444
1445 hdf5Reader.GetVarInfo("i64", gDims, h5Type);
1446 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_LONG), 1);
1447 ASSERT_EQ(gDims.size(), 2);
1448 ASSERT_EQ(gDims[0], 2);
1449 ASSERT_EQ(gDims[1], globalArraySize);
1450 hdf5Reader.ReadVar("i64", I64.data(), offset, count, arraySize);
1451
1452 hdf5Reader.GetVarInfo("u8", gDims, h5Type);
1453 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_UCHAR), 1);
1454 ASSERT_EQ(gDims.size(), 2);
1455 ASSERT_EQ(gDims[0], 2);
1456 ASSERT_EQ(gDims[1], globalArraySize);
1457 hdf5Reader.ReadVar("u8", U8.data(), offset, count, arraySize);
1458
1459 hdf5Reader.GetVarInfo("u16", gDims, h5Type);
1460 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_USHORT), 1);
1461 ASSERT_EQ(gDims.size(), 2);
1462 ASSERT_EQ(gDims[0], 2);
1463 ASSERT_EQ(gDims[1], globalArraySize);
1464 hdf5Reader.ReadVar("u16", U16.data(), offset, count, arraySize);
1465
1466 hdf5Reader.GetVarInfo("u32", gDims, h5Type);
1467 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_UINT), 1);
1468 ASSERT_EQ(gDims.size(), 2);
1469 ASSERT_EQ(gDims[0], 2);
1470 ASSERT_EQ(gDims[1], globalArraySize);
1471 hdf5Reader.ReadVar("u32", U32.data(), offset, count, arraySize);
1472
1473 hdf5Reader.GetVarInfo("u64", gDims, h5Type);
1474 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_ULONG), 1);
1475 ASSERT_EQ(gDims.size(), 2);
1476 ASSERT_EQ(gDims[0], 2);
1477 ASSERT_EQ(gDims[1], globalArraySize);
1478 hdf5Reader.ReadVar("u64", U64.data(), offset, count, arraySize);
1479
1480 hdf5Reader.GetVarInfo("r32", gDims, h5Type);
1481 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_FLOAT), 1);
1482 ASSERT_EQ(gDims.size(), 2);
1483 ASSERT_EQ(gDims[0], 2);
1484 ASSERT_EQ(gDims[1], globalArraySize);
1485 hdf5Reader.ReadVar("r32", R32.data(), offset, count, arraySize);
1486
1487 hdf5Reader.GetVarInfo("r64", gDims, h5Type);
1488 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_DOUBLE), 1);
1489 ASSERT_EQ(gDims.size(), 2);
1490 ASSERT_EQ(gDims[0], 2);
1491 ASSERT_EQ(gDims[1], globalArraySize);
1492 hdf5Reader.ReadVar("r64", R64.data(), offset, count, arraySize);
1493
1494 EXPECT_EQ(IString, currentTestData.S1);
1495
1496 // Check if it's correct
1497 for (size_t i = 0; i < Nx; ++i)
1498 {
1499 std::stringstream ss;
1500 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
1501 std::string msg = ss.str();
1502
1503 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
1504 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
1505 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
1506 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
1507 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
1508 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
1509 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
1510 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
1511 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
1512 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
1513 }
1514 hdf5Reader.Advance();
1515 }
1516 }
1517 }
1518
1519 // ADIOS2 write, ADIOS2 read
TEST_F(HDF5WriteReadTest,ADIOS2HDF5WriteADIOS2HDF5Read2D2x4)1520 TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteADIOS2HDF5Read2D2x4)
1521 {
1522 std::string fname = "ADIOS2HDF5WriteADIOS2HDF5Read2D2x4Test.h5";
1523 int mpiRank = 0, mpiSize = 1;
1524 // Number of rows
1525 const std::size_t Nx = 4;
1526
1527 // Number of rows
1528 const std::size_t Ny = 2;
1529
1530 // Number of steps
1531 const std::size_t NSteps = 3;
1532
1533 #ifdef TEST_HDF5_MPI
1534 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
1535 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
1536 #endif
1537
1538 #ifdef TEST_HDF5_MPI
1539 adios2::ADIOS adios(MPI_COMM_WORLD);
1540 #else
1541 adios2::ADIOS adios;
1542 #endif
1543 // Write test data using ADIOS2
1544 {
1545 adios2::IO io = adios.DeclareIO("TestIO");
1546
1547 // Declare 2D variables (Ny * (NumOfProcesses * Nx))
1548 // The local process' part (start, count) can be defined now or later
1549 // before Write().
1550 {
1551 adios2::Dims shape{static_cast<unsigned int>(Ny),
1552 static_cast<unsigned int>(Nx * mpiSize)};
1553 adios2::Dims start{static_cast<unsigned int>(0),
1554 static_cast<unsigned int>(mpiRank * Nx)};
1555 adios2::Dims count{static_cast<unsigned int>(Ny),
1556 static_cast<unsigned int>(Nx)};
1557
1558 auto var_iString = io.DefineVariable<std::string>("iString");
1559
1560 auto var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count);
1561 auto var_i16 =
1562 io.DefineVariable<int16_t>("i16", shape, start, count);
1563 auto var_i32 =
1564 io.DefineVariable<int32_t>("i32", shape, start, count);
1565 auto var_i64 =
1566 io.DefineVariable<int64_t>("i64", shape, start, count);
1567 auto var_u8 = io.DefineVariable<uint8_t>("u8", shape, start, count);
1568 auto var_u16 =
1569 io.DefineVariable<uint16_t>("u16", shape, start, count);
1570 auto var_u32 =
1571 io.DefineVariable<uint32_t>("u32", shape, start, count);
1572 auto var_u64 =
1573 io.DefineVariable<uint64_t>("u64", shape, start, count);
1574 auto var_r32 = io.DefineVariable<float>("r32", shape, start, count);
1575 auto var_r64 =
1576 io.DefineVariable<double>("r64", shape, start, count);
1577 }
1578
1579 // Create the HDF5 Engine
1580 io.SetEngine("HDF5");
1581
1582 // HDf5 engine calls the HDF5 common object that calls the hDF5 library.
1583 // The IO functionality, SetParameters and AddTransports will be added
1584 // in the future. For now `io.AddTransport("file", {
1585 // "library", "MPI"}});` is omitted.
1586 // })
1587 io.AddTransport("file");
1588
1589 adios2::Engine engine = io.Open(fname, adios2::Mode::Write);
1590
1591 for (size_t step = 0; step < NSteps; ++step)
1592 {
1593 // Generate test data for each process uniquely
1594 SmallTestData currentTestData =
1595 generateNewSmallTestData(m_TestData, step, mpiRank, mpiSize);
1596
1597 // Retrieve the variables that previously went out of scope
1598 auto var_iString = io.InquireVariable<std::string>("iString");
1599 auto var_i8 = io.InquireVariable<int8_t>("i8");
1600 auto var_i16 = io.InquireVariable<int16_t>("i16");
1601 auto var_i32 = io.InquireVariable<int32_t>("i32");
1602 auto var_i64 = io.InquireVariable<int64_t>("i64");
1603 auto var_u8 = io.InquireVariable<uint8_t>("u8");
1604 auto var_u16 = io.InquireVariable<uint16_t>("u16");
1605 auto var_u32 = io.InquireVariable<uint32_t>("u32");
1606 auto var_u64 = io.InquireVariable<uint64_t>("u64");
1607 auto var_r32 = io.InquireVariable<float>("r32");
1608 auto var_r64 = io.InquireVariable<double>("r64");
1609
1610 // Make a 2D selection to describe the local dimensions of the
1611 // variable we write and its offsets in the global spaces
1612 adios2::Box<adios2::Dims> sel(
1613 {0, static_cast<unsigned int>(mpiRank * Nx)}, {Ny, Nx});
1614 var_i8.SetSelection(sel);
1615 var_i16.SetSelection(sel);
1616 var_i32.SetSelection(sel);
1617 var_i64.SetSelection(sel);
1618 var_u8.SetSelection(sel);
1619 var_u16.SetSelection(sel);
1620 var_u32.SetSelection(sel);
1621 var_u64.SetSelection(sel);
1622 var_r32.SetSelection(sel);
1623 var_r64.SetSelection(sel);
1624
1625 // Write each one
1626 // fill in the variable with values from starting index to
1627 // starting index + count
1628 engine.Put(var_iString, currentTestData.S1);
1629 engine.Put(var_i8, currentTestData.I8.data());
1630 engine.Put(var_i16, currentTestData.I16.data());
1631 engine.Put(var_i32, currentTestData.I32.data());
1632 engine.Put(var_i64, currentTestData.I64.data());
1633 engine.Put(var_u8, currentTestData.U8.data());
1634 engine.Put(var_u16, currentTestData.U16.data());
1635 engine.Put(var_u32, currentTestData.U32.data());
1636 engine.Put(var_u64, currentTestData.U64.data());
1637 engine.Put(var_r32, currentTestData.R32.data());
1638 engine.Put(var_r64, currentTestData.R64.data());
1639
1640 // Advance to the next time step
1641 engine.EndStep();
1642 }
1643
1644 // Close the file
1645 engine.Close();
1646 }
1647
1648 { // reading back
1649 adios2::IO io = adios.DeclareIO("HDF5ReadIO");
1650 io.SetEngine("HDF5");
1651
1652 adios2::Engine hdf5Reader = io.Open(fname, adios2::Mode::Read);
1653
1654 auto var_iString = io.InquireVariable<std::string>("iString");
1655 EXPECT_TRUE(var_iString);
1656 ASSERT_EQ(var_iString.Shape().size(), 0);
1657 ASSERT_EQ(var_iString.Steps(), NSteps);
1658
1659 auto var_i8 = io.InquireVariable<int8_t>("i8");
1660 EXPECT_TRUE(var_i8);
1661 ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
1662 ASSERT_EQ(var_i8.Steps(), NSteps);
1663 ASSERT_EQ(var_i8.Shape()[0], Ny);
1664 ASSERT_EQ(var_i8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1665
1666 auto var_i16 = io.InquireVariable<int16_t>("i16");
1667 EXPECT_TRUE(var_i16);
1668 ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
1669 ASSERT_EQ(var_i16.Steps(), NSteps);
1670 ASSERT_EQ(var_i16.Shape()[0], Ny);
1671 ASSERT_EQ(var_i16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1672
1673 auto var_i32 = io.InquireVariable<int32_t>("i32");
1674 EXPECT_TRUE(var_i32);
1675 ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
1676 ASSERT_EQ(var_i32.Steps(), NSteps);
1677 ASSERT_EQ(var_i32.Shape()[0], Ny);
1678 ASSERT_EQ(var_i32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1679
1680 auto var_i64 = io.InquireVariable<int64_t>("i64");
1681 EXPECT_TRUE(var_i64);
1682 ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
1683 ASSERT_EQ(var_i64.Steps(), NSteps);
1684 ASSERT_EQ(var_i64.Shape()[0], Ny);
1685 ASSERT_EQ(var_i64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1686
1687 auto var_u8 = io.InquireVariable<uint8_t>("u8");
1688 EXPECT_TRUE(var_u8);
1689 ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
1690 ASSERT_EQ(var_u8.Steps(), NSteps);
1691 ASSERT_EQ(var_u8.Shape()[0], Ny);
1692 ASSERT_EQ(var_u8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1693
1694 auto var_u16 = io.InquireVariable<uint16_t>("u16");
1695 EXPECT_TRUE(var_u16);
1696 ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
1697 ASSERT_EQ(var_u16.Steps(), NSteps);
1698 ASSERT_EQ(var_u16.Shape()[0], Ny);
1699 ASSERT_EQ(var_u16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1700
1701 auto var_u32 = io.InquireVariable<uint32_t>("u32");
1702 EXPECT_TRUE(var_u32);
1703 ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
1704 ASSERT_EQ(var_u32.Steps(), NSteps);
1705 ASSERT_EQ(var_u32.Shape()[0], Ny);
1706 ASSERT_EQ(var_u32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1707
1708 auto var_u64 = io.InquireVariable<uint64_t>("u64");
1709 EXPECT_TRUE(var_u64);
1710 ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
1711 ASSERT_EQ(var_u64.Steps(), NSteps);
1712 ASSERT_EQ(var_u64.Shape()[0], Ny);
1713 ASSERT_EQ(var_u64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1714
1715 auto var_r32 = io.InquireVariable<float>("r32");
1716 EXPECT_TRUE(var_r32);
1717 ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
1718 ASSERT_EQ(var_r32.Steps(), NSteps);
1719 ASSERT_EQ(var_r32.Shape()[0], Ny);
1720 ASSERT_EQ(var_r32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1721
1722 auto var_r64 = io.InquireVariable<double>("r64");
1723 EXPECT_TRUE(var_r64);
1724 ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
1725 ASSERT_EQ(var_r64.Steps(), NSteps);
1726 ASSERT_EQ(var_r64.Shape()[0], Ny);
1727 ASSERT_EQ(var_r64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1728
1729 std::string IString;
1730 std::array<int8_t, Nx * Ny> I8;
1731 std::array<int16_t, Nx * Ny> I16;
1732 std::array<int32_t, Nx * Ny> I32;
1733 std::array<int64_t, Nx * Ny> I64;
1734 std::array<uint8_t, Nx * Ny> U8;
1735 std::array<uint16_t, Nx * Ny> U16;
1736 std::array<uint32_t, Nx * Ny> U32;
1737 std::array<uint64_t, Nx * Ny> U64;
1738 std::array<float, Nx * Ny> R32;
1739 std::array<double, Nx * Ny> R64;
1740
1741 const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
1742 const adios2::Dims count{Ny, Nx};
1743
1744 const adios2::Box<adios2::Dims> sel(start, count);
1745
1746 var_i8.SetSelection(sel);
1747 var_i16.SetSelection(sel);
1748 var_i32.SetSelection(sel);
1749 var_i64.SetSelection(sel);
1750
1751 var_u8.SetSelection(sel);
1752 var_u16.SetSelection(sel);
1753 var_u32.SetSelection(sel);
1754 var_u64.SetSelection(sel);
1755
1756 var_r32.SetSelection(sel);
1757 var_r64.SetSelection(sel);
1758
1759 for (size_t t = 0; t < NSteps; ++t)
1760 {
1761 var_i8.SetStepSelection({t, 1});
1762 var_i16.SetStepSelection({t, 1});
1763 var_i32.SetStepSelection({t, 1});
1764 var_i64.SetStepSelection({t, 1});
1765
1766 var_u8.SetStepSelection({t, 1});
1767 var_u16.SetStepSelection({t, 1});
1768 var_u32.SetStepSelection({t, 1});
1769 var_u64.SetStepSelection({t, 1});
1770
1771 var_r32.SetStepSelection({t, 1});
1772 var_r64.SetStepSelection({t, 1});
1773
1774 hdf5Reader.Get(var_iString, IString);
1775
1776 hdf5Reader.Get(var_i8, I8.data());
1777 hdf5Reader.Get(var_i16, I16.data());
1778 hdf5Reader.Get(var_i32, I32.data());
1779 hdf5Reader.Get(var_i64, I64.data());
1780
1781 hdf5Reader.Get(var_u8, U8.data());
1782 hdf5Reader.Get(var_u16, U16.data());
1783 hdf5Reader.Get(var_u32, U32.data());
1784 hdf5Reader.Get(var_u64, U64.data());
1785
1786 hdf5Reader.Get(var_r32, R32.data());
1787 hdf5Reader.Get(var_r64, R64.data());
1788
1789 hdf5Reader.PerformGets();
1790
1791 // Generate test data for each rank uniquely
1792 SmallTestData currentTestData = generateNewSmallTestData(
1793 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
1794
1795 EXPECT_EQ(IString, currentTestData.S1);
1796
1797 for (size_t i = 0; i < Nx * Ny; ++i)
1798 {
1799 std::stringstream ss;
1800 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
1801 std::string msg = ss.str();
1802
1803 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
1804 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
1805 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
1806 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
1807 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
1808 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
1809 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
1810 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
1811 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
1812 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
1813 }
1814 }
1815 hdf5Reader.Close();
1816 }
1817 }
1818
1819 // Native HDF5 write, ADIOS2 read
TEST_F(HDF5WriteReadTest,HDF5WriteADIOS2HDF5Read2D2x4)1820 TEST_F(HDF5WriteReadTest, HDF5WriteADIOS2HDF5Read2D2x4)
1821 {
1822 std::string fname = "HDF5WriteADIOS2HDF5Read2D2x4Test.h5";
1823
1824 int mpiRank = 0, mpiSize = 1;
1825 // Number of rows
1826 const std::size_t Nx = 4;
1827 const std::size_t Ny = 2;
1828 // Number of steps
1829 const std::size_t NSteps = 3;
1830
1831 {
1832 #ifdef TEST_HDF5_MPI
1833 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
1834 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
1835
1836 HDF5NativeWriter h5writer(fname, MPI_COMM_WORLD);
1837 #else
1838 HDF5NativeWriter h5writer(fname);
1839 #endif
1840
1841 int dimSize = 2;
1842 hsize_t global_dims[2] = {Ny, Nx * mpiSize};
1843 hsize_t count[2] = {Ny, Nx};
1844 hsize_t offset[2] = {0, Nx * mpiRank};
1845
1846 for (size_t step = 0; step < NSteps; ++step)
1847 {
1848 // Generate test data for each process uniquely
1849 SmallTestData currentTestData =
1850 generateNewSmallTestData(m_TestData, step, mpiRank, mpiSize);
1851
1852 h5writer.CreateAndStoreScalar("iString", H5T_STRING,
1853 currentTestData.S1.data());
1854 h5writer.CreateAndStoreVar("i8", dimSize, H5T_NATIVE_INT8,
1855 global_dims, offset, count,
1856 currentTestData.I8.data());
1857 h5writer.CreateAndStoreVar("i16", dimSize, H5T_NATIVE_SHORT,
1858 global_dims, offset, count,
1859 currentTestData.I16.data());
1860 h5writer.CreateAndStoreVar("i32", dimSize, H5T_NATIVE_INT,
1861 global_dims, offset, count,
1862 currentTestData.I32.data());
1863 h5writer.CreateAndStoreVar("i64", dimSize, H5T_NATIVE_LONG,
1864 global_dims, offset, count,
1865 currentTestData.I64.data());
1866 h5writer.CreateAndStoreVar("u8", dimSize, H5T_NATIVE_UCHAR,
1867 global_dims, offset, count,
1868 currentTestData.U8.data());
1869 h5writer.CreateAndStoreVar("u16", dimSize, H5T_NATIVE_USHORT,
1870 global_dims, offset, count,
1871 currentTestData.U16.data());
1872 h5writer.CreateAndStoreVar("u32", dimSize, H5T_NATIVE_UINT,
1873 global_dims, offset, count,
1874 currentTestData.U32.data());
1875 h5writer.CreateAndStoreVar("u64", dimSize, H5T_NATIVE_ULONG,
1876 global_dims, offset, count,
1877 currentTestData.U64.data());
1878 h5writer.CreateAndStoreVar("r32", dimSize, H5T_NATIVE_FLOAT,
1879 global_dims, offset, count,
1880 currentTestData.R32.data());
1881 h5writer.CreateAndStoreVar("r64", dimSize, H5T_NATIVE_DOUBLE,
1882 global_dims, offset, count,
1883 currentTestData.R64.data());
1884 h5writer.Advance();
1885 }
1886 }
1887
1888 { // read back
1889 #ifdef TEST_HDF5_MPI
1890 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
1891 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
1892 #endif
1893
1894 #ifdef TEST_HDF5_MPI
1895 adios2::ADIOS adios(MPI_COMM_WORLD);
1896 #else
1897 adios2::ADIOS adios;
1898 #endif
1899 adios2::IO io = adios.DeclareIO("HDF5ReadIO");
1900 io.SetEngine("HDF5");
1901
1902 adios2::Engine hdf5Reader = io.Open(fname, adios2::Mode::Read);
1903
1904 auto var_iString = io.InquireVariable<std::string>("iString");
1905 EXPECT_TRUE(var_iString);
1906 ASSERT_EQ(var_iString.Shape().size(), 0);
1907 ASSERT_EQ(var_iString.Steps(), NSteps);
1908
1909 auto var_i8 = io.InquireVariable<int8_t>("i8");
1910 EXPECT_TRUE(var_i8);
1911 ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
1912 ASSERT_EQ(var_i8.Steps(), NSteps);
1913 ASSERT_EQ(var_i8.Shape()[0], Ny);
1914 ASSERT_EQ(var_i8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1915
1916 auto var_i16 = io.InquireVariable<int16_t>("i16");
1917 EXPECT_TRUE(var_i16);
1918 ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
1919 ASSERT_EQ(var_i16.Steps(), NSteps);
1920 ASSERT_EQ(var_i16.Shape()[0], Ny);
1921 ASSERT_EQ(var_i16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1922
1923 auto var_i32 = io.InquireVariable<int32_t>("i32");
1924 EXPECT_TRUE(var_i32);
1925 ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
1926 ASSERT_EQ(var_i32.Steps(), NSteps);
1927 ASSERT_EQ(var_i32.Shape()[0], Ny);
1928 ASSERT_EQ(var_i32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1929
1930 auto var_i64 = io.InquireVariable<int64_t>("i64");
1931 EXPECT_TRUE(var_i64);
1932 ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
1933 ASSERT_EQ(var_i64.Steps(), NSteps);
1934 ASSERT_EQ(var_i64.Shape()[0], Ny);
1935 ASSERT_EQ(var_i64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1936
1937 auto var_u8 = io.InquireVariable<uint8_t>("u8");
1938 EXPECT_TRUE(var_u8);
1939 ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
1940 ASSERT_EQ(var_u8.Steps(), NSteps);
1941 ASSERT_EQ(var_u8.Shape()[0], Ny);
1942 ASSERT_EQ(var_u8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1943
1944 auto var_u16 = io.InquireVariable<uint16_t>("u16");
1945 EXPECT_TRUE(var_u16);
1946 ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
1947 ASSERT_EQ(var_u16.Steps(), NSteps);
1948 ASSERT_EQ(var_u16.Shape()[0], Ny);
1949 ASSERT_EQ(var_u16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1950
1951 auto var_u32 = io.InquireVariable<uint32_t>("u32");
1952 EXPECT_TRUE(var_u32);
1953 ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
1954 ASSERT_EQ(var_u32.Steps(), NSteps);
1955 ASSERT_EQ(var_u32.Shape()[0], Ny);
1956 ASSERT_EQ(var_u32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1957
1958 auto var_u64 = io.InquireVariable<uint64_t>("u64");
1959 EXPECT_TRUE(var_u64);
1960 ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
1961 ASSERT_EQ(var_u64.Steps(), NSteps);
1962 ASSERT_EQ(var_u64.Shape()[0], Ny);
1963 ASSERT_EQ(var_u64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1964
1965 auto var_r32 = io.InquireVariable<float>("r32");
1966 EXPECT_TRUE(var_r32);
1967 ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
1968 ASSERT_EQ(var_r32.Steps(), NSteps);
1969 ASSERT_EQ(var_r32.Shape()[0], Ny);
1970 ASSERT_EQ(var_r32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1971
1972 auto var_r64 = io.InquireVariable<double>("r64");
1973 EXPECT_TRUE(var_r64);
1974 ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
1975 ASSERT_EQ(var_r64.Steps(), NSteps);
1976 ASSERT_EQ(var_r64.Shape()[0], Ny);
1977 ASSERT_EQ(var_r64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
1978
1979 std::string IString;
1980 std::array<int8_t, Nx * Ny> I8;
1981 std::array<int16_t, Nx * Ny> I16;
1982 std::array<int32_t, Nx * Ny> I32;
1983 std::array<int64_t, Nx * Ny> I64;
1984 std::array<uint8_t, Nx * Ny> U8;
1985 std::array<uint16_t, Nx * Ny> U16;
1986 std::array<uint32_t, Nx * Ny> U32;
1987 std::array<uint64_t, Nx * Ny> U64;
1988 std::array<float, Nx * Ny> R32;
1989 std::array<double, Nx * Ny> R64;
1990
1991 const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
1992 const adios2::Dims count{Ny, Nx};
1993
1994 const adios2::Box<adios2::Dims> sel(start, count);
1995
1996 var_i8.SetSelection(sel);
1997 var_i16.SetSelection(sel);
1998 var_i32.SetSelection(sel);
1999 var_i64.SetSelection(sel);
2000
2001 var_u8.SetSelection(sel);
2002 var_u16.SetSelection(sel);
2003 var_u32.SetSelection(sel);
2004 var_u64.SetSelection(sel);
2005
2006 var_r32.SetSelection(sel);
2007 var_r64.SetSelection(sel);
2008
2009 for (size_t t = 0; t < NSteps; ++t)
2010 {
2011 var_i8.SetStepSelection({t, 1});
2012 var_i16.SetStepSelection({t, 1});
2013 var_i32.SetStepSelection({t, 1});
2014 var_i64.SetStepSelection({t, 1});
2015
2016 var_u8.SetStepSelection({t, 1});
2017 var_u16.SetStepSelection({t, 1});
2018 var_u32.SetStepSelection({t, 1});
2019 var_u64.SetStepSelection({t, 1});
2020
2021 var_r32.SetStepSelection({t, 1});
2022 var_r64.SetStepSelection({t, 1});
2023
2024 hdf5Reader.Get(var_iString, IString);
2025
2026 hdf5Reader.Get(var_i8, I8.data());
2027 hdf5Reader.Get(var_i16, I16.data());
2028 hdf5Reader.Get(var_i32, I32.data());
2029 hdf5Reader.Get(var_i64, I64.data());
2030
2031 hdf5Reader.Get(var_u8, U8.data());
2032 hdf5Reader.Get(var_u16, U16.data());
2033 hdf5Reader.Get(var_u32, U32.data());
2034 hdf5Reader.Get(var_u64, U64.data());
2035
2036 hdf5Reader.Get(var_r32, R32.data());
2037 hdf5Reader.Get(var_r64, R64.data());
2038
2039 hdf5Reader.PerformGets();
2040
2041 // Generate test data for each rank uniquely
2042 SmallTestData currentTestData = generateNewSmallTestData(
2043 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
2044
2045 EXPECT_EQ(IString, currentTestData.S1);
2046
2047 for (size_t i = 0; i < Nx * Ny; ++i)
2048 {
2049 std::stringstream ss;
2050 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
2051 std::string msg = ss.str();
2052
2053 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
2054 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
2055 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
2056 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
2057 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
2058 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
2059 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
2060 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
2061 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
2062 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
2063 }
2064 }
2065 hdf5Reader.Close();
2066 }
2067 }
2068
2069 //******************************************************************************
2070 // 2D 4x2 test data
2071 //******************************************************************************
2072
2073 // ADIOS2 write, native HDF5 read
TEST_F(HDF5WriteReadTest,ADIOS2HDF5WriteHDF5Read2D4x2)2074 TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteHDF5Read2D4x2)
2075 {
2076
2077 // Each process would write a 4x2 array and all processes would
2078 // form a 2D 4 * (NumberOfProcess * Nx) matrix where Nx is 2 here
2079 std::string fname = "ADIOS2HDF5WriteHDF5Read2D4x2Test.h5";
2080
2081 int mpiRank = 0, mpiSize = 1;
2082 // Number of rows
2083 const std::size_t Nx = 2;
2084 // Number of cols
2085 const std::size_t Ny = 4;
2086
2087 // Number of steps
2088 const std::size_t NSteps = 3;
2089
2090 #ifdef TEST_HDF5_MPI
2091 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
2092 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
2093 #endif
2094
2095 // Write test data using ADIOS2
2096 {
2097 #ifdef TEST_HDF5_MPI
2098 adios2::ADIOS adios(MPI_COMM_WORLD);
2099 #else
2100 adios2::ADIOS adios;
2101 #endif
2102 adios2::IO io = adios.DeclareIO("TestIO");
2103
2104 // Declare 2D variables (4 * (NumberOfProcess * Nx))
2105 // The local process' part (start, count) can be defined now or later
2106 // before Write().
2107 {
2108 adios2::Dims shape{static_cast<unsigned int>(Ny),
2109 static_cast<unsigned int>(mpiSize * Nx)};
2110 adios2::Dims start{static_cast<unsigned int>(0),
2111 static_cast<unsigned int>(mpiRank * Nx)};
2112 adios2::Dims count{static_cast<unsigned int>(Ny),
2113 static_cast<unsigned int>(Nx)};
2114
2115 auto var_iString = io.DefineVariable<std::string>("iString");
2116 auto var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count);
2117 auto var_i16 =
2118 io.DefineVariable<int16_t>("i16", shape, start, count);
2119 auto var_i32 =
2120 io.DefineVariable<int32_t>("i32", shape, start, count);
2121 auto var_i64 =
2122 io.DefineVariable<int64_t>("i64", shape, start, count);
2123 auto var_u8 = io.DefineVariable<uint8_t>("u8", shape, start, count);
2124 auto var_u16 =
2125 io.DefineVariable<uint16_t>("u16", shape, start, count);
2126 auto var_u32 =
2127 io.DefineVariable<uint32_t>("u32", shape, start, count);
2128 auto var_u64 =
2129 io.DefineVariable<uint64_t>("u64", shape, start, count);
2130 auto var_r32 = io.DefineVariable<float>("r32", shape, start, count);
2131 auto var_r64 =
2132 io.DefineVariable<double>("r64", shape, start, count);
2133 }
2134
2135 // Create the HDF5 Engine
2136 io.SetEngine("HDF5");
2137
2138 // HDf5 engine calls the HDF5 common object that calls the hDF5 library.
2139 // The IO functionality, SetParameters and AddTransports will be added
2140 // in the future. For now `io.AddTransport("file", {
2141 // "library", "MPI"}});` is omitted.
2142 // })
2143 io.AddTransport("file");
2144
2145 adios2::Engine engine = io.Open(fname, adios2::Mode::Write);
2146
2147 for (size_t step = 0; step < NSteps; ++step)
2148 {
2149 // Generate test data for each process uniquely
2150 SmallTestData currentTestData =
2151 generateNewSmallTestData(m_TestData, step, mpiRank, mpiSize);
2152
2153 // Retrieve the variables that previously went out of scope
2154 auto var_iString = io.InquireVariable<std::string>("iString");
2155 auto var_i8 = io.InquireVariable<int8_t>("i8");
2156 auto var_i16 = io.InquireVariable<int16_t>("i16");
2157 auto var_i32 = io.InquireVariable<int32_t>("i32");
2158 auto var_i64 = io.InquireVariable<int64_t>("i64");
2159 auto var_u8 = io.InquireVariable<uint8_t>("u8");
2160 auto var_u16 = io.InquireVariable<uint16_t>("u16");
2161 auto var_u32 = io.InquireVariable<uint32_t>("u32");
2162 auto var_u64 = io.InquireVariable<uint64_t>("u64");
2163 auto var_r32 = io.InquireVariable<float>("r32");
2164 auto var_r64 = io.InquireVariable<double>("r64");
2165
2166 // Make a 2D selection to describe the local dimensions of the
2167 // variable we write and its offsets in the global spaces
2168 adios2::Box<adios2::Dims> sel(
2169 {0, static_cast<unsigned int>(mpiRank * Nx)}, {Ny, Nx});
2170 var_i8.SetSelection(sel);
2171 var_i16.SetSelection(sel);
2172 var_i32.SetSelection(sel);
2173 var_i64.SetSelection(sel);
2174 var_u8.SetSelection(sel);
2175 var_u16.SetSelection(sel);
2176 var_u32.SetSelection(sel);
2177 var_u64.SetSelection(sel);
2178 var_r32.SetSelection(sel);
2179 var_r64.SetSelection(sel);
2180
2181 // Write each one
2182 // fill in the variable with values from starting index to
2183 // starting index + count
2184 engine.BeginStep();
2185 engine.Put(var_iString, currentTestData.S1);
2186 engine.Put(var_i8, currentTestData.I8.data());
2187 engine.Put(var_i16, currentTestData.I16.data());
2188 engine.Put(var_i32, currentTestData.I32.data());
2189 engine.Put(var_i64, currentTestData.I64.data());
2190 engine.Put(var_u8, currentTestData.U8.data());
2191 engine.Put(var_u16, currentTestData.U16.data());
2192 engine.Put(var_u32, currentTestData.U32.data());
2193 engine.Put(var_u64, currentTestData.U64.data());
2194 engine.Put(var_r32, currentTestData.R32.data());
2195 engine.Put(var_r64, currentTestData.R64.data());
2196 engine.EndStep();
2197 }
2198
2199 engine.Close();
2200 }
2201
2202 {
2203
2204 HDF5NativeReader hdf5Reader(fname);
2205
2206 std::string IString;
2207 const size_t arraySize = Nx * Ny;
2208 std::array<int8_t, arraySize> I8;
2209 std::array<int16_t, arraySize> I16;
2210 std::array<int32_t, arraySize> I32;
2211 std::array<int64_t, arraySize> I64;
2212 std::array<uint8_t, arraySize> U8;
2213 std::array<uint16_t, arraySize> U16;
2214 std::array<uint32_t, arraySize> U32;
2215 std::array<uint64_t, arraySize> U64;
2216 std::array<float, arraySize> R32;
2217 std::array<double, arraySize> R64;
2218 // 2D
2219 hsize_t count[2], offset[2];
2220 offset[0] = 0;
2221 offset[1] = mpiRank * Nx;
2222 count[0] = Ny;
2223 count[1] = Nx;
2224 size_t globalArraySize = Nx * mpiSize;
2225
2226 // For each variable, we would verify its global size and type.
2227 // Then we would retrieve the data back which is written by the
2228 // current process and validate the value
2229 for (size_t t = 0; t < NSteps; ++t)
2230 {
2231 SmallTestData currentTestData =
2232 generateNewSmallTestData(m_TestData, t, mpiRank, mpiSize);
2233
2234 std::vector<hsize_t> gDims;
2235 hid_t h5Type;
2236
2237 hdf5Reader.GetVarInfo("iString", gDims, h5Type);
2238 // ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_IN), 1);
2239 ASSERT_EQ(gDims.size(), 0);
2240 hdf5Reader.ReadString("iString", IString);
2241
2242 hdf5Reader.GetVarInfo("i8", gDims, h5Type);
2243 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_INT8), 1);
2244 ASSERT_EQ(gDims.size(), 2);
2245 ASSERT_EQ(gDims[0], 4);
2246 ASSERT_EQ(gDims[1], globalArraySize);
2247 hdf5Reader.ReadVar("i8", I8.data(), offset, count, arraySize);
2248
2249 hdf5Reader.GetVarInfo("i16", gDims, h5Type);
2250 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_SHORT), 1);
2251 ASSERT_EQ(gDims.size(), 2);
2252 ASSERT_EQ(gDims[0], 4);
2253 ASSERT_EQ(gDims[1], globalArraySize);
2254 hdf5Reader.ReadVar("i16", I16.data(), offset, count, arraySize);
2255
2256 hdf5Reader.GetVarInfo("i32", gDims, h5Type);
2257 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_INT), 1);
2258 ASSERT_EQ(gDims.size(), 2);
2259 ASSERT_EQ(gDims[0], 4);
2260 ASSERT_EQ(gDims[1], globalArraySize);
2261 hdf5Reader.ReadVar("i32", I32.data(), offset, count, arraySize);
2262
2263 hdf5Reader.GetVarInfo("i64", gDims, h5Type);
2264 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_LONG), 1);
2265 ASSERT_EQ(gDims.size(), 2);
2266 ASSERT_EQ(gDims[0], 4);
2267 ASSERT_EQ(gDims[1], globalArraySize);
2268 hdf5Reader.ReadVar("i64", I64.data(), offset, count, arraySize);
2269
2270 hdf5Reader.GetVarInfo("u8", gDims, h5Type);
2271 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_UCHAR), 1);
2272 ASSERT_EQ(gDims.size(), 2);
2273 ASSERT_EQ(gDims[0], 4);
2274 ASSERT_EQ(gDims[1], globalArraySize);
2275 hdf5Reader.ReadVar("u8", U8.data(), offset, count, arraySize);
2276
2277 hdf5Reader.GetVarInfo("u16", gDims, h5Type);
2278 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_USHORT), 1);
2279 ASSERT_EQ(gDims.size(), 2);
2280 ASSERT_EQ(gDims[0], 4);
2281 ASSERT_EQ(gDims[1], globalArraySize);
2282 hdf5Reader.ReadVar("u16", U16.data(), offset, count, arraySize);
2283
2284 hdf5Reader.GetVarInfo("u32", gDims, h5Type);
2285 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_UINT), 1);
2286 ASSERT_EQ(gDims.size(), 2);
2287 ASSERT_EQ(gDims[0], 4);
2288 ASSERT_EQ(gDims[1], globalArraySize);
2289 hdf5Reader.ReadVar("u32", U32.data(), offset, count, arraySize);
2290
2291 hdf5Reader.GetVarInfo("u64", gDims, h5Type);
2292 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_ULONG), 1);
2293 ASSERT_EQ(gDims.size(), 2);
2294 ASSERT_EQ(gDims[0], 4);
2295 ASSERT_EQ(gDims[1], globalArraySize);
2296 hdf5Reader.ReadVar("u64", U64.data(), offset, count, arraySize);
2297
2298 hdf5Reader.GetVarInfo("r32", gDims, h5Type);
2299 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_FLOAT), 1);
2300 ASSERT_EQ(gDims.size(), 2);
2301 ASSERT_EQ(gDims[0], 4);
2302 ASSERT_EQ(gDims[1], globalArraySize);
2303 hdf5Reader.ReadVar("r32", R32.data(), offset, count, arraySize);
2304
2305 hdf5Reader.GetVarInfo("r64", gDims, h5Type);
2306 ASSERT_EQ(H5Tequal(h5Type, H5T_NATIVE_DOUBLE), 1);
2307 ASSERT_EQ(gDims.size(), 2);
2308 ASSERT_EQ(gDims[0], 4);
2309 ASSERT_EQ(gDims[1], globalArraySize);
2310 hdf5Reader.ReadVar("r64", R64.data(), offset, count, arraySize);
2311
2312 EXPECT_EQ(IString, currentTestData.S1);
2313 // Check if it's correct
2314 for (size_t i = 0; i < Nx; ++i)
2315 {
2316 std::stringstream ss;
2317 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
2318 std::string msg = ss.str();
2319
2320 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
2321 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
2322 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
2323 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
2324 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
2325 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
2326 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
2327 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
2328 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
2329 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
2330 }
2331 hdf5Reader.Advance();
2332 }
2333 }
2334 }
2335
2336 // ADIOS2 write, ADIOS2 read
TEST_F(HDF5WriteReadTest,ADIOS2HDF5WriteADIOS2HDF5Read2D4x2)2337 TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteADIOS2HDF5Read2D4x2)
2338 {
2339 std::string fname = "ADIOS2HDF5WriteADIOS2HDF5Read2D4x2Test.h5";
2340
2341 int mpiRank = 0, mpiSize = 1;
2342 // Number of rows
2343 const std::size_t Nx = 2;
2344 // Number of cols
2345 const std::size_t Ny = 4;
2346
2347 // Number of steps
2348 const std::size_t NSteps = 3;
2349
2350 #ifdef TEST_HDF5_MPI
2351 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
2352 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
2353 #endif
2354
2355 #ifdef TEST_HDF5_MPI
2356 adios2::ADIOS adios(MPI_COMM_WORLD);
2357 #else
2358 adios2::ADIOS adios;
2359 #endif
2360
2361 // Write test data using ADIOS2
2362 {
2363 adios2::IO io = adios.DeclareIO("TestIO");
2364
2365 // Declare 2D variables (4 * (NumberOfProcess * Nx))
2366 // The local process' part (start, count) can be defined now or later
2367 // before Write().
2368 {
2369 adios2::Dims shape{static_cast<unsigned int>(Ny),
2370 static_cast<unsigned int>(mpiSize * Nx)};
2371 adios2::Dims start{static_cast<unsigned int>(0),
2372 static_cast<unsigned int>(mpiRank * Nx)};
2373 adios2::Dims count{static_cast<unsigned int>(Ny),
2374 static_cast<unsigned int>(Nx)};
2375 auto var_iString = io.DefineVariable<std::string>("iString");
2376 auto var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count);
2377 auto var_i16 =
2378 io.DefineVariable<int16_t>("i16", shape, start, count);
2379 auto var_i32 =
2380 io.DefineVariable<int32_t>("i32", shape, start, count);
2381 auto var_i64 =
2382 io.DefineVariable<int64_t>("i64", shape, start, count);
2383 auto var_u8 = io.DefineVariable<uint8_t>("u8", shape, start, count);
2384 auto var_u16 =
2385 io.DefineVariable<uint16_t>("u16", shape, start, count);
2386 auto var_u32 =
2387 io.DefineVariable<uint32_t>("u32", shape, start, count);
2388 auto var_u64 =
2389 io.DefineVariable<uint64_t>("u64", shape, start, count);
2390 auto var_r32 = io.DefineVariable<float>("r32", shape, start, count);
2391 auto var_r64 =
2392 io.DefineVariable<double>("r64", shape, start, count);
2393 }
2394
2395 // Create the HDF5 Engine
2396 io.SetEngine("HDF5");
2397
2398 // HDf5 engine calls the HDF5 common object that calls the hDF5 library.
2399 // The IO functionality, SetParameters and AddTransports will be added
2400 // in the future. For now `io.AddTransport("file", {
2401 // "library", "MPI"}});` is omitted.
2402 // })
2403 io.AddTransport("file");
2404
2405 adios2::Engine engine = io.Open(fname, adios2::Mode::Write);
2406
2407 for (size_t step = 0; step < NSteps; ++step)
2408 {
2409 // Generate test data for each process uniquely
2410 SmallTestData currentTestData =
2411 generateNewSmallTestData(m_TestData, step, mpiRank, mpiSize);
2412
2413 // Retrieve the variables that previously went out of scope
2414 auto var_iString = io.InquireVariable<std::string>("iString");
2415 auto var_i8 = io.InquireVariable<int8_t>("i8");
2416 auto var_i16 = io.InquireVariable<int16_t>("i16");
2417 auto var_i32 = io.InquireVariable<int32_t>("i32");
2418 auto var_i64 = io.InquireVariable<int64_t>("i64");
2419 auto var_u8 = io.InquireVariable<uint8_t>("u8");
2420 auto var_u16 = io.InquireVariable<uint16_t>("u16");
2421 auto var_u32 = io.InquireVariable<uint32_t>("u32");
2422 auto var_u64 = io.InquireVariable<uint64_t>("u64");
2423 auto var_r32 = io.InquireVariable<float>("r32");
2424 auto var_r64 = io.InquireVariable<double>("r64");
2425
2426 // Make a 2D selection to describe the local dimensions of the
2427 // variable we write and its offsets in the global spaces
2428 adios2::Box<adios2::Dims> sel(
2429 {0, static_cast<unsigned int>(mpiRank * Nx)}, {Ny, Nx});
2430 var_i8.SetSelection(sel);
2431 var_i16.SetSelection(sel);
2432 var_i32.SetSelection(sel);
2433 var_i64.SetSelection(sel);
2434 var_u8.SetSelection(sel);
2435 var_u16.SetSelection(sel);
2436 var_u32.SetSelection(sel);
2437 var_u64.SetSelection(sel);
2438 var_r32.SetSelection(sel);
2439 var_r64.SetSelection(sel);
2440
2441 // Write each one
2442 // fill in the variable with values from starting index to
2443 // starting index + count
2444 engine.BeginStep();
2445 engine.Put(var_iString, currentTestData.S1);
2446 engine.Put(var_i8, currentTestData.I8.data());
2447 engine.Put(var_i16, currentTestData.I16.data());
2448 engine.Put(var_i32, currentTestData.I32.data());
2449 engine.Put(var_i64, currentTestData.I64.data());
2450 engine.Put(var_u8, currentTestData.U8.data());
2451 engine.Put(var_u16, currentTestData.U16.data());
2452 engine.Put(var_u32, currentTestData.U32.data());
2453 engine.Put(var_u64, currentTestData.U64.data());
2454 engine.Put(var_r32, currentTestData.R32.data());
2455 engine.Put(var_r64, currentTestData.R64.data());
2456 engine.EndStep();
2457 }
2458
2459 engine.Close();
2460 }
2461
2462 { // reading back
2463 adios2::IO io = adios.DeclareIO("HDF5ReadIO");
2464 io.SetEngine("HDF5");
2465
2466 adios2::Engine hdf5Reader = io.Open(fname, adios2::Mode::Read);
2467
2468 auto var_iString = io.InquireVariable<std::string>("iString");
2469 EXPECT_TRUE(var_iString);
2470 ASSERT_EQ(var_iString.Shape().size(), 0);
2471 ASSERT_EQ(var_iString.Steps(), NSteps);
2472
2473 auto var_i8 = io.InquireVariable<int8_t>("i8");
2474 EXPECT_TRUE(var_i8);
2475 ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
2476 ASSERT_EQ(var_i8.Steps(), NSteps);
2477 ASSERT_EQ(var_i8.Shape()[0], Ny);
2478 ASSERT_EQ(var_i8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2479
2480 auto var_i16 = io.InquireVariable<int16_t>("i16");
2481 EXPECT_TRUE(var_i16);
2482 ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
2483 ASSERT_EQ(var_i16.Steps(), NSteps);
2484 ASSERT_EQ(var_i16.Shape()[0], Ny);
2485 ASSERT_EQ(var_i16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2486
2487 auto var_i32 = io.InquireVariable<int32_t>("i32");
2488 EXPECT_TRUE(var_i32);
2489 ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
2490 ASSERT_EQ(var_i32.Steps(), NSteps);
2491 ASSERT_EQ(var_i32.Shape()[0], Ny);
2492 ASSERT_EQ(var_i32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2493
2494 auto var_i64 = io.InquireVariable<int64_t>("i64");
2495 EXPECT_TRUE(var_i64);
2496 ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
2497 ASSERT_EQ(var_i64.Steps(), NSteps);
2498 ASSERT_EQ(var_i64.Shape()[0], Ny);
2499 ASSERT_EQ(var_i64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2500
2501 auto var_u8 = io.InquireVariable<uint8_t>("u8");
2502 EXPECT_TRUE(var_u8);
2503 ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
2504 ASSERT_EQ(var_u8.Steps(), NSteps);
2505 ASSERT_EQ(var_u8.Shape()[0], Ny);
2506 ASSERT_EQ(var_u8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2507
2508 auto var_u16 = io.InquireVariable<uint16_t>("u16");
2509 EXPECT_TRUE(var_u16);
2510 ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
2511 ASSERT_EQ(var_u16.Steps(), NSteps);
2512 ASSERT_EQ(var_u16.Shape()[0], Ny);
2513 ASSERT_EQ(var_u16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2514
2515 auto var_u32 = io.InquireVariable<uint32_t>("u32");
2516 EXPECT_TRUE(var_u32);
2517 ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
2518 ASSERT_EQ(var_u32.Steps(), NSteps);
2519 ASSERT_EQ(var_u32.Shape()[0], Ny);
2520 ASSERT_EQ(var_u32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2521
2522 auto var_u64 = io.InquireVariable<uint64_t>("u64");
2523 EXPECT_TRUE(var_u64);
2524 ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
2525 ASSERT_EQ(var_u64.Steps(), NSteps);
2526 ASSERT_EQ(var_u64.Shape()[0], Ny);
2527 ASSERT_EQ(var_u64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2528
2529 auto var_r32 = io.InquireVariable<float>("r32");
2530 EXPECT_TRUE(var_r32);
2531 ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
2532 ASSERT_EQ(var_r32.Steps(), NSteps);
2533 ASSERT_EQ(var_r32.Shape()[0], Ny);
2534 ASSERT_EQ(var_r32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2535
2536 auto var_r64 = io.InquireVariable<double>("r64");
2537 EXPECT_TRUE(var_r64);
2538 ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
2539 ASSERT_EQ(var_r64.Steps(), NSteps);
2540 ASSERT_EQ(var_r64.Shape()[0], Ny);
2541 ASSERT_EQ(var_r64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2542
2543 std::string IString;
2544 std::array<int8_t, Nx * Ny> I8;
2545 std::array<int16_t, Nx * Ny> I16;
2546 std::array<int32_t, Nx * Ny> I32;
2547 std::array<int64_t, Nx * Ny> I64;
2548 std::array<uint8_t, Nx * Ny> U8;
2549 std::array<uint16_t, Nx * Ny> U16;
2550 std::array<uint32_t, Nx * Ny> U32;
2551 std::array<uint64_t, Nx * Ny> U64;
2552 std::array<float, Nx * Ny> R32;
2553 std::array<double, Nx * Ny> R64;
2554
2555 const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
2556 const adios2::Dims count{Ny, Nx};
2557
2558 const adios2::Box<adios2::Dims> sel(start, count);
2559
2560 var_i8.SetSelection(sel);
2561 var_i16.SetSelection(sel);
2562 var_i32.SetSelection(sel);
2563 var_i64.SetSelection(sel);
2564
2565 var_u8.SetSelection(sel);
2566 var_u16.SetSelection(sel);
2567 var_u32.SetSelection(sel);
2568 var_u64.SetSelection(sel);
2569
2570 var_r32.SetSelection(sel);
2571 var_r64.SetSelection(sel);
2572
2573 for (size_t t = 0; t < NSteps; ++t)
2574 {
2575 var_i8.SetStepSelection({t, 1});
2576 var_i16.SetStepSelection({t, 1});
2577 var_i32.SetStepSelection({t, 1});
2578 var_i64.SetStepSelection({t, 1});
2579
2580 var_u8.SetStepSelection({t, 1});
2581 var_u16.SetStepSelection({t, 1});
2582 var_u32.SetStepSelection({t, 1});
2583 var_u64.SetStepSelection({t, 1});
2584
2585 var_r32.SetStepSelection({t, 1});
2586 var_r64.SetStepSelection({t, 1});
2587
2588 hdf5Reader.Get(var_iString, IString);
2589
2590 hdf5Reader.Get(var_i8, I8.data());
2591 hdf5Reader.Get(var_i16, I16.data());
2592 hdf5Reader.Get(var_i32, I32.data());
2593 hdf5Reader.Get(var_i64, I64.data());
2594
2595 hdf5Reader.Get(var_u8, U8.data());
2596 hdf5Reader.Get(var_u16, U16.data());
2597 hdf5Reader.Get(var_u32, U32.data());
2598 hdf5Reader.Get(var_u64, U64.data());
2599
2600 hdf5Reader.Get(var_r32, R32.data());
2601 hdf5Reader.Get(var_r64, R64.data());
2602 hdf5Reader.PerformGets();
2603
2604 // Generate test data for each rank uniquely
2605 SmallTestData currentTestData = generateNewSmallTestData(
2606 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
2607
2608 EXPECT_EQ(IString, currentTestData.S1);
2609
2610 for (size_t i = 0; i < Nx * Ny; ++i)
2611 {
2612 std::stringstream ss;
2613 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
2614 std::string msg = ss.str();
2615
2616 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
2617 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
2618 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
2619 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
2620 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
2621 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
2622 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
2623 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
2624 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
2625 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
2626 }
2627 }
2628 hdf5Reader.Close();
2629 }
2630 }
2631
2632 // Native HDF5 write, ADIOS2 read
TEST_F(HDF5WriteReadTest,HDF5WriteADIOS2HDF5Read2D4x2)2633 TEST_F(HDF5WriteReadTest, HDF5WriteADIOS2HDF5Read2D4x2)
2634 {
2635 std::string fname = "HDF5WriteADIOS2HDF5Read2D4x2Test.h5";
2636
2637 int mpiRank = 0, mpiSize = 1;
2638 // Number of rows
2639 const std::size_t Nx = 2;
2640 const std::size_t Ny = 4;
2641 // Number of steps
2642 const std::size_t NSteps = 3;
2643
2644 {
2645 #ifdef TEST_HDF5_MPI
2646 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
2647 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
2648
2649 HDF5NativeWriter h5writer(fname, MPI_COMM_WORLD);
2650 #else
2651 HDF5NativeWriter h5writer(fname);
2652 #endif
2653
2654 int dimSize = 2;
2655 hsize_t global_dims[2] = {Ny, Nx * mpiSize};
2656 hsize_t count[2] = {Ny, Nx};
2657 hsize_t offset[2] = {0, Nx * mpiRank};
2658
2659 for (size_t step = 0; step < NSteps; ++step)
2660 {
2661 // Generate test data for each process uniquely
2662 SmallTestData currentTestData =
2663 generateNewSmallTestData(m_TestData, step, mpiRank, mpiSize);
2664
2665 h5writer.CreateAndStoreScalar("iString", H5T_STRING,
2666 currentTestData.S1.data());
2667 h5writer.CreateAndStoreVar("i8", dimSize, H5T_NATIVE_INT8,
2668 global_dims, offset, count,
2669 currentTestData.I8.data());
2670 h5writer.CreateAndStoreVar("i16", dimSize, H5T_NATIVE_SHORT,
2671 global_dims, offset, count,
2672 currentTestData.I16.data());
2673 h5writer.CreateAndStoreVar("i32", dimSize, H5T_NATIVE_INT,
2674 global_dims, offset, count,
2675 currentTestData.I32.data());
2676 h5writer.CreateAndStoreVar("i64", dimSize, H5T_NATIVE_LONG,
2677 global_dims, offset, count,
2678 currentTestData.I64.data());
2679 h5writer.CreateAndStoreVar("u8", dimSize, H5T_NATIVE_UCHAR,
2680 global_dims, offset, count,
2681 currentTestData.U8.data());
2682 h5writer.CreateAndStoreVar("u16", dimSize, H5T_NATIVE_USHORT,
2683 global_dims, offset, count,
2684 currentTestData.U16.data());
2685 h5writer.CreateAndStoreVar("u32", dimSize, H5T_NATIVE_UINT,
2686 global_dims, offset, count,
2687 currentTestData.U32.data());
2688 h5writer.CreateAndStoreVar("u64", dimSize, H5T_NATIVE_ULONG,
2689 global_dims, offset, count,
2690 currentTestData.U64.data());
2691 h5writer.CreateAndStoreVar("r32", dimSize, H5T_NATIVE_FLOAT,
2692 global_dims, offset, count,
2693 currentTestData.R32.data());
2694 h5writer.CreateAndStoreVar("r64", dimSize, H5T_NATIVE_DOUBLE,
2695 global_dims, offset, count,
2696 currentTestData.R64.data());
2697 h5writer.Advance();
2698 }
2699 }
2700
2701 { // read back
2702 #ifdef TEST_HDF5_MPI
2703 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
2704 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
2705 #endif
2706
2707 #ifdef TEST_HDF5_MPI
2708 adios2::ADIOS adios(MPI_COMM_WORLD);
2709 #else
2710 adios2::ADIOS adios;
2711 #endif
2712
2713 adios2::IO io = adios.DeclareIO("HDF5ReadIO");
2714 io.SetEngine("HDF5");
2715
2716 adios2::Engine hdf5Reader = io.Open(fname, adios2::Mode::Read);
2717
2718 auto var_iString = io.InquireVariable<std::string>("iString");
2719 EXPECT_TRUE(var_iString);
2720 ASSERT_EQ(var_iString.Shape().size(), 0);
2721 ASSERT_EQ(var_iString.Steps(), NSteps);
2722
2723 auto var_i8 = io.InquireVariable<int8_t>("i8");
2724 EXPECT_TRUE(var_i8);
2725 ASSERT_EQ(var_i8.ShapeID(), adios2::ShapeID::GlobalArray);
2726 ASSERT_EQ(var_i8.Steps(), NSteps);
2727 ASSERT_EQ(var_i8.Shape()[0], Ny);
2728 ASSERT_EQ(var_i8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2729
2730 auto var_i16 = io.InquireVariable<int16_t>("i16");
2731 EXPECT_TRUE(var_i16);
2732 ASSERT_EQ(var_i16.ShapeID(), adios2::ShapeID::GlobalArray);
2733 ASSERT_EQ(var_i16.Steps(), NSteps);
2734 ASSERT_EQ(var_i16.Shape()[0], Ny);
2735 ASSERT_EQ(var_i16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2736
2737 auto var_i32 = io.InquireVariable<int32_t>("i32");
2738 EXPECT_TRUE(var_i32);
2739 ASSERT_EQ(var_i32.ShapeID(), adios2::ShapeID::GlobalArray);
2740 ASSERT_EQ(var_i32.Steps(), NSteps);
2741 ASSERT_EQ(var_i32.Shape()[0], Ny);
2742 ASSERT_EQ(var_i32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2743
2744 auto var_i64 = io.InquireVariable<int64_t>("i64");
2745 EXPECT_TRUE(var_i64);
2746 ASSERT_EQ(var_i64.ShapeID(), adios2::ShapeID::GlobalArray);
2747 ASSERT_EQ(var_i64.Steps(), NSteps);
2748 ASSERT_EQ(var_i64.Shape()[0], Ny);
2749 ASSERT_EQ(var_i64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2750
2751 auto var_u8 = io.InquireVariable<uint8_t>("u8");
2752 EXPECT_TRUE(var_u8);
2753 ASSERT_EQ(var_u8.ShapeID(), adios2::ShapeID::GlobalArray);
2754 ASSERT_EQ(var_u8.Steps(), NSteps);
2755 ASSERT_EQ(var_u8.Shape()[0], Ny);
2756 ASSERT_EQ(var_u8.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2757
2758 auto var_u16 = io.InquireVariable<uint16_t>("u16");
2759 EXPECT_TRUE(var_u16);
2760 ASSERT_EQ(var_u16.ShapeID(), adios2::ShapeID::GlobalArray);
2761 ASSERT_EQ(var_u16.Steps(), NSteps);
2762 ASSERT_EQ(var_u16.Shape()[0], Ny);
2763 ASSERT_EQ(var_u16.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2764
2765 auto var_u32 = io.InquireVariable<uint32_t>("u32");
2766 EXPECT_TRUE(var_u32);
2767 ASSERT_EQ(var_u32.ShapeID(), adios2::ShapeID::GlobalArray);
2768 ASSERT_EQ(var_u32.Steps(), NSteps);
2769 ASSERT_EQ(var_u32.Shape()[0], Ny);
2770 ASSERT_EQ(var_u32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2771
2772 auto var_u64 = io.InquireVariable<uint64_t>("u64");
2773 EXPECT_TRUE(var_u64);
2774 ASSERT_EQ(var_u64.ShapeID(), adios2::ShapeID::GlobalArray);
2775 ASSERT_EQ(var_u64.Steps(), NSteps);
2776 ASSERT_EQ(var_u64.Shape()[0], Ny);
2777 ASSERT_EQ(var_u64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2778
2779 auto var_r32 = io.InquireVariable<float>("r32");
2780 EXPECT_TRUE(var_r32);
2781 ASSERT_EQ(var_r32.ShapeID(), adios2::ShapeID::GlobalArray);
2782 ASSERT_EQ(var_r32.Steps(), NSteps);
2783 ASSERT_EQ(var_r32.Shape()[0], Ny);
2784 ASSERT_EQ(var_r32.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2785
2786 auto var_r64 = io.InquireVariable<double>("r64");
2787 EXPECT_TRUE(var_r64);
2788 ASSERT_EQ(var_r64.ShapeID(), adios2::ShapeID::GlobalArray);
2789 ASSERT_EQ(var_r64.Steps(), NSteps);
2790 ASSERT_EQ(var_r64.Shape()[0], Ny);
2791 ASSERT_EQ(var_r64.Shape()[1], static_cast<size_t>(mpiSize * Nx));
2792
2793 std::string IString;
2794 std::array<int8_t, Nx * Ny> I8;
2795 std::array<int16_t, Nx * Ny> I16;
2796 std::array<int32_t, Nx * Ny> I32;
2797 std::array<int64_t, Nx * Ny> I64;
2798 std::array<uint8_t, Nx * Ny> U8;
2799 std::array<uint16_t, Nx * Ny> U16;
2800 std::array<uint32_t, Nx * Ny> U32;
2801 std::array<uint64_t, Nx * Ny> U64;
2802 std::array<float, Nx * Ny> R32;
2803 std::array<double, Nx * Ny> R64;
2804
2805 const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)};
2806 const adios2::Dims count{Ny, Nx};
2807
2808 const adios2::Box<adios2::Dims> sel(start, count);
2809
2810 var_i8.SetSelection(sel);
2811 var_i16.SetSelection(sel);
2812 var_i32.SetSelection(sel);
2813 var_i64.SetSelection(sel);
2814
2815 var_u8.SetSelection(sel);
2816 var_u16.SetSelection(sel);
2817 var_u32.SetSelection(sel);
2818 var_u64.SetSelection(sel);
2819
2820 var_r32.SetSelection(sel);
2821 var_r64.SetSelection(sel);
2822
2823 for (size_t t = 0; t < NSteps; ++t)
2824 {
2825 var_i8.SetStepSelection({t, 1});
2826 var_i16.SetStepSelection({t, 1});
2827 var_i32.SetStepSelection({t, 1});
2828 var_i64.SetStepSelection({t, 1});
2829
2830 var_u8.SetStepSelection({t, 1});
2831 var_u16.SetStepSelection({t, 1});
2832 var_u32.SetStepSelection({t, 1});
2833 var_u64.SetStepSelection({t, 1});
2834
2835 var_r32.SetStepSelection({t, 1});
2836 var_r64.SetStepSelection({t, 1});
2837
2838 hdf5Reader.Get(var_iString, IString);
2839
2840 hdf5Reader.Get(var_i8, I8.data());
2841 hdf5Reader.Get(var_i16, I16.data());
2842 hdf5Reader.Get(var_i32, I32.data());
2843 hdf5Reader.Get(var_i64, I64.data());
2844
2845 hdf5Reader.Get(var_u8, U8.data());
2846 hdf5Reader.Get(var_u16, U16.data());
2847 hdf5Reader.Get(var_u32, U32.data());
2848 hdf5Reader.Get(var_u64, U64.data());
2849
2850 hdf5Reader.Get(var_r32, R32.data());
2851 hdf5Reader.Get(var_r64, R64.data());
2852 hdf5Reader.PerformGets();
2853
2854 // Generate test data for each rank uniquely
2855 SmallTestData currentTestData = generateNewSmallTestData(
2856 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
2857
2858 EXPECT_EQ(IString, currentTestData.S1);
2859
2860 for (size_t i = 0; i < Nx * Ny; ++i)
2861 {
2862 std::stringstream ss;
2863 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
2864 std::string msg = ss.str();
2865
2866 EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg;
2867 EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg;
2868 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
2869 EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg;
2870 EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg;
2871 EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg;
2872 EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg;
2873 EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg;
2874 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
2875 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
2876 }
2877 }
2878 hdf5Reader.Close();
2879 }
2880 }
2881
TEST_F(HDF5WriteReadTest,ATTRTESTADIOS2vsHDF5)2882 TEST_F(HDF5WriteReadTest, /*DISABLE_*/ ATTRTESTADIOS2vsHDF5)
2883 {
2884 // Each process would write a 1x8 array and all processes would
2885 // form a mpiSize * Nx 1D array
2886 const std::string h5name = "ATTRTESTADIOS2vsHDF5.h5";
2887 const std::string bpname = "ATTRTESTADIOS2vsHDF5.bp";
2888
2889 int mpiRank = 0, mpiSize = 1;
2890 // Number of rows
2891 const std::size_t Nx = 8;
2892
2893 // Number of steps
2894 const std::size_t NSteps = 3;
2895
2896 #ifdef TEST_HDF5_MPI
2897 MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
2898 MPI_Comm_size(MPI_COMM_WORLD, &mpiSize);
2899 #endif
2900
2901 // Write test data using ADIOS2
2902
2903 #ifdef TEST_HDF5_MPI
2904 adios2::ADIOS adios(MPI_COMM_WORLD);
2905 #else
2906 adios2::ADIOS adios;
2907 #endif
2908 adios2::IO io = adios.DeclareIO("TestIO");
2909
2910 std::string var1Name = "var1";
2911 // std::string var1Name = "/var1";
2912 std::string var2Name = "var2";
2913 std::string var3Name = "grp/var3";
2914 std::string var4Name = "var4";
2915
2916 std::string ioAttrName = "file_notes";
2917 std::string ioAttrValue = "this is a comment";
2918
2919 std::string v1AttrAName = "var1/meshWidth";
2920 int32_t v1AttrAValue = 111;
2921 std::string v1AttrBName = "var1/meshLength";
2922 int32_t v1AttrBValue = 222;
2923
2924 std::string v2AttrName = "var2/meshName";
2925 std::string v2AttrValue = "unstructured";
2926
2927 std::string v3AttrName = var3Name + "/targetDensity";
2928 double v3AttrValue = 55;
2929
2930 std::string v4AttrName = "var4/unitName";
2931 std::string v4AttrValue = "kg";
2932
2933 std::string fantacyPathName = "no/such/path";
2934 std::string longerV1AttrName1 = "var1/mesh/level";
2935 std::string longerV1AttrName2 = "mesh/also/level";
2936
2937 int numAttr = 0;
2938 // Declare 1D variables (NumOfProcesses * Nx)
2939 // The local process' part (start, count) can be defined now or later
2940 // before Write().
2941 {
2942 adios2::Dims shape{static_cast<unsigned int>(Nx * mpiSize)};
2943 adios2::Dims start{static_cast<unsigned int>(Nx * mpiRank)};
2944 adios2::Dims count{static_cast<unsigned int>(Nx)};
2945
2946 io.DefineVariable<int32_t>(var1Name, shape, start, count);
2947 io.DefineVariable<float>(var2Name, shape, start, count);
2948 io.DefineVariable<double>(var3Name, shape, start, count);
2949
2950 io.DefineAttribute<std::string>(ioAttrName, ioAttrValue);
2951 numAttr++;
2952
2953 io.DefineAttribute<int32_t>(v1AttrAName, v1AttrAValue);
2954 numAttr++;
2955 io.DefineAttribute<int32_t>(v1AttrBName, v1AttrBValue);
2956 numAttr++;
2957
2958 // this expects that var and attr can have different names
2959 io.DefineAttribute<double>(var1Name, v3AttrValue);
2960 numAttr++;
2961
2962 // this allows attr can be path like (no need to exist)
2963 io.DefineAttribute<int32_t>(fantacyPathName, v1AttrAValue);
2964 numAttr++;
2965
2966 // this allows variable can attach attr with long name
2967 io.DefineAttribute<int32_t>(longerV1AttrName1, v1AttrBValue);
2968 numAttr++;
2969 io.DefineAttribute<int32_t>(longerV1AttrName2, v1AttrBValue, var1Name);
2970 numAttr++;
2971
2972 io.DefineAttribute<std::string>(v2AttrName, v2AttrValue);
2973 numAttr++;
2974 io.DefineAttribute<double>(v3AttrName, v3AttrValue);
2975 numAttr++;
2976 }
2977
2978 // Create the HDF5 Engine
2979 io.SetEngine("HDF5");
2980
2981 // HDf5 engine calls the HDF5 common object that calls the hDF5 library.
2982 // The IO functionality, SetParameters and AddTransports will be added
2983 // in the future. For now `io.AddTransport("file", {
2984 // "library", "MPI"}});` is omitted.
2985 // })
2986 // io.AddTransport("File");
2987
2988 adios2::Engine engine = io.Open(h5name, adios2::Mode::Write);
2989
2990 for (size_t step = 0; step < NSteps; ++step)
2991 {
2992 // Generate test data for each process uniquely
2993 SmallTestData currentTestData =
2994 generateNewSmallTestData(m_TestData, step, mpiRank, mpiSize);
2995
2996 // Retrieve the variables that previously went out of scope
2997 auto var1 = io.InquireVariable<int32_t>(var1Name);
2998 auto var2 = io.InquireVariable<float>(var2Name);
2999 auto var3 = io.InquireVariable<double>(var3Name);
3000
3001 // Make a 1D selection to describe the local dimensions of the
3002 // variable we write and its offsets in the global spaces
3003
3004 adios2::Box<adios2::Dims> sel({mpiRank * Nx}, {Nx});
3005
3006 var1.SetSelection(sel);
3007 var2.SetSelection(sel);
3008 var3.SetSelection(sel);
3009
3010 // Write each one
3011 // fill in the variable with values from starting index to
3012 // starting index + count
3013 engine.BeginStep();
3014 engine.Put(var1, currentTestData.I32.data());
3015 engine.Put(var2, currentTestData.R32.data());
3016 engine.Put(var3, currentTestData.R64.data());
3017 if (step == 1)
3018 {
3019 adios2::Dims shape{static_cast<unsigned int>(Nx * mpiSize)};
3020 adios2::Dims start{static_cast<unsigned int>(Nx * mpiRank)};
3021 adios2::Dims count{static_cast<unsigned int>(Nx)};
3022
3023 io.DefineVariable<int32_t>(var4Name, shape, start, count);
3024 auto var4 = io.InquireVariable<int32_t>(var4Name);
3025 engine.Put(var4, currentTestData.I32.data());
3026
3027 io.DefineAttribute<std::string>(v4AttrName, v4AttrValue);
3028 numAttr++;
3029 }
3030
3031 // Advance to the next time step
3032 engine.EndStep();
3033
3034 if (step == 1)
3035 {
3036 io.RemoveVariable(var4Name);
3037 io.RemoveAttribute(v4AttrName);
3038 }
3039 }
3040
3041 // Close the file
3042 engine.Close();
3043
3044 {
3045 adios2::IO io = adios.DeclareIO("HDF5ReadIO");
3046 io.SetEngine("HDF5");
3047
3048 adios2::Engine hdf5Reader = io.Open(h5name, adios2::Mode::Read);
3049
3050 auto var1 = io.InquireVariable<int32_t>(var1Name);
3051 EXPECT_TRUE(var1);
3052 ASSERT_EQ(var1.ShapeID(), adios2::ShapeID::GlobalArray);
3053 ASSERT_EQ(var1.Steps(), NSteps);
3054 ASSERT_EQ(var1.Shape()[0], mpiSize * Nx);
3055
3056 auto var2 = io.InquireVariable<float>(var2Name);
3057 EXPECT_TRUE(var2);
3058 ASSERT_EQ(var2.ShapeID(), adios2::ShapeID::GlobalArray);
3059 ASSERT_EQ(var2.Steps(), NSteps);
3060 ASSERT_EQ(var2.Shape()[0], mpiSize * Nx);
3061
3062 auto var3 = io.InquireVariable<double>(var3Name);
3063 EXPECT_TRUE(var3);
3064 ASSERT_EQ(var3.ShapeID(), adios2::ShapeID::GlobalArray);
3065 ASSERT_EQ(var3.Steps(), NSteps);
3066 ASSERT_EQ(var3.Shape()[0], mpiSize * Nx);
3067
3068 SmallTestData testData;
3069
3070 std::array<int32_t, Nx> I32;
3071 std::array<float, Nx> R32;
3072 std::array<double, Nx> R64;
3073
3074 const adios2::Dims start{mpiRank * Nx};
3075 const adios2::Dims count{Nx};
3076
3077 const adios2::Box<adios2::Dims> sel(start, count);
3078
3079 var1.SetSelection(sel);
3080 var2.SetSelection(sel);
3081 var3.SetSelection(sel);
3082
3083 for (size_t t = 0; t < NSteps; ++t)
3084 {
3085 var1.SetStepSelection({t, 1});
3086 var2.SetStepSelection({t, 1});
3087 var3.SetStepSelection({t, 1});
3088
3089 // Generate test data for each rank uniquely
3090 SmallTestData currentTestData = generateNewSmallTestData(
3091 m_TestData, static_cast<int>(t), mpiRank, mpiSize);
3092
3093 hdf5Reader.BeginStep();
3094
3095 hdf5Reader.Get(var1, I32.data());
3096 hdf5Reader.Get(var2, R32.data());
3097 hdf5Reader.Get(var3, R64.data());
3098
3099 hdf5Reader.EndStep();
3100
3101 // EXPECT_EQ(IString, currentTestData.S1);
3102
3103 for (size_t i = 0; i < Nx; ++i)
3104 {
3105 std::stringstream ss;
3106 ss << "t=" << t << " i=" << i << " rank=" << mpiRank;
3107 std::string msg = ss.str();
3108
3109 EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg;
3110 EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg;
3111 EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg;
3112 }
3113 }
3114
3115 const std::map<std::string, adios2::Params> &attributesInfo =
3116 io.AvailableAttributes();
3117
3118 EXPECT_EQ(numAttr, attributesInfo.size());
3119
3120 EXPECT_EQ(4, io.AvailableAttributes(var1Name).size());
3121 EXPECT_EQ(1, io.AvailableAttributes(var2Name).size());
3122 EXPECT_EQ(1, io.AvailableAttributes(var3Name).size());
3123
3124 std::cout << " test below of attrs of var4Name is false b/c "
3125 "io.m_EngineStep=2 but var4 is only in step 1, this it "
3126 "thinks so such var"
3127 << std::endl;
3128 std::cout << " need to fix semantics of io.AvailableAttributes()"
3129 << std::endl;
3130 // EXPECT_EQ(1, io.AvailableAttributes(var4Name).size());
3131
3132 std::cout << " other tests will follow after William make changes: "
3133 "e.g. GetNumAttr(var) etc + Write a bp file and read "
3134 "back in hdf5 and verify"
3135 << std::endl;
3136 /*
3137 hdf5Reader.GetNumAttributes(var1); // expects 2
3138 hdf5Reader.GetNumAttributes(var2); // expects 1
3139 hdf5Reader.GetNumAttributes(var3); // expects 0
3140
3141 hdf5Reader.GetNumAttributes(); // expects 4
3142 */
3143 hdf5Reader.Close();
3144 }
3145 }
3146
3147 //******************************************************************************
3148 // main
3149 //******************************************************************************
3150
main(int argc,char ** argv)3151 int main(int argc, char **argv)
3152 {
3153 #ifdef TEST_HDF5_MPI
3154 MPI_Init(nullptr, nullptr);
3155 #endif
3156
3157 int result;
3158 ::testing::InitGoogleTest(&argc, argv);
3159 result = RUN_ALL_TESTS();
3160
3161 #ifdef TEST_HDF5_MPI
3162 MPI_Finalize();
3163 #endif
3164
3165 return result;
3166 }
3167