libROM  v1.0
Data-driven physical simulation library
HDFDatabase.cpp
1 
11 // Description: The concrete database implementation using HDF5.
12 
13 #include "HDFDatabase.h"
14 #include "Utilities.h"
15 #include <iostream>
16 
17 namespace CAROM {
18 
19 const int HDFDatabase::KEY_DOUBLE_ARRAY = 0;
20 const int HDFDatabase::KEY_INT_ARRAY = 1;
21 
23  d_is_file(false),
24  d_file_id(-1),
25  d_group_id(-1)
26 {
27 }
28 
30 {
31  if (d_is_file) {
32  close();
33  }
34 
35  if (d_group_id != -1) {
36  herr_t errf = H5Gclose(d_group_id);
37  CAROM_VERIFY(errf >= 0);
38 #ifndef DEBUG_CHECK_ASSERTIONS
39  CAROM_NULL_USE(errf);
40 #endif
41  }
42 }
43 
44 bool
46  const std::string& file_name,
47  const MPI_Comm comm)
48 {
49  CAROM_VERIFY(!file_name.empty());
50  std::string ext_filename(file_name);
51 
52  if (comm != MPI_COMM_NULL)
53  {
54  MPI_Comm_rank(comm, &d_rank);
55  char tmp[10];
56  sprintf(tmp, ".%06d", d_rank);
57  ext_filename += tmp;
58  }
59 
60  Database::create(ext_filename, comm);
61 
62  hid_t file_id = H5Fcreate(ext_filename.c_str(),
63  H5F_ACC_TRUNC,
64  H5P_DEFAULT,
65  H5P_DEFAULT);
66  bool result = file_id >= 0;
67  CAROM_VERIFY(result);
68  d_is_file = true;
69  d_file_id = file_id;
70  d_group_id = file_id;
71 
72  return result;
73 }
74 
75 bool
77  const std::string& file_name,
78  const std::string& type,
79  const MPI_Comm comm)
80 {
81  CAROM_VERIFY(!file_name.empty());
82  std::string ext_filename(file_name);
83 
84  if (comm != MPI_COMM_NULL)
85  {
86  MPI_Comm_rank(comm, &d_rank);
87  char tmp[10];
88  sprintf(tmp, ".%06d", d_rank);
89  ext_filename += tmp;
90  }
91 
92  Database::open(ext_filename, type, comm);
93 
94  CAROM_VERIFY(type == "r" || type == "wr");
95  hid_t file_id;
96  if (type == "r")
97  {
98  file_id = H5Fopen(ext_filename.c_str(),
99  H5F_ACC_RDONLY,
100  H5P_DEFAULT);
101  }
102  else if (type == "wr")
103  {
104  file_id = H5Fopen(ext_filename.c_str(),
105  H5F_ACC_RDWR,
106  H5P_DEFAULT);
107  }
108  bool result = file_id >= 0;
109  CAROM_VERIFY(result);
110  d_is_file = true;
111  d_file_id = file_id;
112  d_group_id = file_id;
113 
114  return result;
115 }
116 
117 bool
119 {
120  herr_t errf = 0;
121  if (d_is_file) {
122  errf = H5Fclose(d_file_id);
123  CAROM_VERIFY(errf >= 0);
124 
125  if (d_group_id == d_file_id) {
126  d_group_id = -1;
127  }
128  d_file_id = -1;
129  d_is_file = false;
130  }
131 
132  return errf >= 0;
133 }
134 
135 void
137  const std::string& key,
138  const int* const data,
139  int nelements,
140  const bool distributed)
141 {
142  CAROM_VERIFY(!key.empty());
143  CAROM_VERIFY(data != nullptr);
144  CAROM_VERIFY(nelements > 0);
145 
146  hsize_t dim[] = { static_cast<hsize_t>(nelements) };
147  hid_t space = H5Screate_simple(1, dim, 0);
148  CAROM_VERIFY(space >= 0);
149 
150 #if (H5_VERS_MAJOR > 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR > 6))
151  hid_t dataset = H5Dcreate(d_group_id,
152  key.c_str(),
153  H5T_STD_I32BE,
154  space,
155  H5P_DEFAULT,
156  H5P_DEFAULT,
157  H5P_DEFAULT);
158 #else
159  hid_t dataset = H5Dcreate(d_group_id,
160  key.c_str(),
161  H5T_STD_I32BE,
162  space,
163  H5P_DEFAULT);
164 #endif
165  CAROM_VERIFY(dataset >= 0);
166 
167  herr_t errf = H5Dwrite(dataset,
168  H5T_NATIVE_INT,
169  H5S_ALL,
170  H5S_ALL,
171  H5P_DEFAULT,
172  data);
173  CAROM_VERIFY(errf >= 0);
174 
175  // Write attribute so we know what kind of data this is.
176  writeAttribute(KEY_INT_ARRAY, dataset);
177 
178  errf = H5Sclose(space);
179  CAROM_VERIFY(errf >= 0);
180 
181  errf = H5Dclose(dataset);
182  CAROM_VERIFY(errf >= 0);
183 #ifndef DEBUG_CHECK_ASSERTIONS
184  CAROM_NULL_USE(errf);
185 #endif
186 }
187 
188 void
190  const std::string& key,
191  const double* const data,
192  int nelements,
193  const bool distributed)
194 {
195  CAROM_VERIFY(!key.empty());
196  CAROM_VERIFY(data != nullptr);
197  CAROM_VERIFY(nelements > 0);
198 
199  hsize_t dim[] = { static_cast<hsize_t>(nelements) };
200  hid_t space = H5Screate_simple(1, dim, 0);
201  CAROM_VERIFY(space >= 0);
202 
203 #if (H5_VERS_MAJOR > 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR > 6))
204  hid_t dataset = H5Dcreate(d_group_id,
205  key.c_str(),
206  H5T_IEEE_F64BE,
207  space,
208  H5P_DEFAULT,
209  H5P_DEFAULT,
210  H5P_DEFAULT);
211 #else
212  hid_t dataset = H5Dcreate(d_group_id,
213  key.c_str(),
214  H5T_IEEE_F64BE,
215  space,
216  H5P_DEFAULT);
217 #endif
218  CAROM_VERIFY(dataset >= 0);
219 
220  herr_t errf = H5Dwrite(dataset,
221  H5T_NATIVE_DOUBLE,
222  H5S_ALL,
223  H5S_ALL,
224  H5P_DEFAULT,
225  data);
226  CAROM_VERIFY(errf >= 0);
227 
228  // Write attribute so we know what kind of data this is.
230 
231  errf = H5Sclose(space);
232  CAROM_VERIFY(errf >= 0);
233 
234  errf = H5Dclose(dataset);
235  CAROM_VERIFY(errf >= 0);
236 #ifndef DEBUG_CHECK_ASSERTIONS
237  CAROM_NULL_USE(errf);
238 #endif
239 }
240 
241 void
243  const std::string& key,
244  const std::vector<double>& data,
245  int nelements,
246  const bool distributed)
247 {
248  putDoubleArray(key, data.data(), nelements);
249 }
250 
251 void
253  const std::string& key,
254  int* data,
255  int nelements,
256  const bool distributed)
257 {
258  if (nelements == 0) return;
259 
260  CAROM_VERIFY(!key.empty());
261 #ifndef DEBUG_CHECK_ASSERTIONS
262  CAROM_NULL_USE(nelements);
263 #endif
264 
265 #if (H5_VERS_MAJOR > 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR > 6))
266  hid_t dset = H5Dopen(d_group_id, key.c_str(), H5P_DEFAULT);
267 #else
268  hid_t dset = H5Dopen(d_group_id, key.c_str());
269 #endif
270  CAROM_VERIFY(dset >= 0);
271 
272  hid_t dspace = H5Dget_space(dset);
273  CAROM_VERIFY(dspace >= 0);
274 
275  hsize_t nsel = H5Sget_select_npoints(dspace);
276  CAROM_VERIFY(static_cast<int>(nsel) == nelements);
277 
278  herr_t errf;
279  if (nsel > 0) {
280  errf = H5Dread(dset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
281  CAROM_VERIFY(errf >= 0);
282  }
283 
284  errf = H5Sclose(dspace);
285  CAROM_VERIFY(errf >= 0);
286 
287  errf = H5Dclose(dset);
288  CAROM_VERIFY(errf >= 0);
289 #ifndef DEBUG_CHECK_ASSERTIONS
290  CAROM_NULL_USE(errf);
291 #endif
292 }
293 
294 int HDFDatabase::getDoubleArraySize(const std::string& key)
295 {
296  CAROM_VERIFY(!key.empty());
297 
298 #if (H5_VERS_MAJOR > 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR > 6))
299  hid_t dset = H5Dopen(d_group_id, key.c_str(), H5P_DEFAULT);
300 #else
301  hid_t dset = H5Dopen(d_group_id, key.c_str());
302 #endif
303  CAROM_VERIFY(dset >= 0);
304 
305  hid_t dspace = H5Dget_space(dset);
306  CAROM_VERIFY(dspace >= 0);
307 
308  hsize_t nsel = H5Sget_select_npoints(dspace);
309 
310  herr_t errf = H5Sclose(dspace);
311  CAROM_VERIFY(errf >= 0);
312 
313  errf = H5Dclose(dset);
314  CAROM_VERIFY(errf >= 0);
315 #ifndef DEBUG_CHECK_ASSERTIONS
316  CAROM_NULL_USE(errf);
317 #endif
318 
319  return static_cast<int>(nsel);
320 }
321 
322 void
324  const std::string& key,
325  double* data,
326  int nelements,
327  const bool distributed)
328 {
329  if (nelements == 0) return;
330 
331  CAROM_VERIFY(!key.empty());
332 #ifndef DEBUG_CHECK_ASSERTIONS
333  CAROM_NULL_USE(nelements);
334 #endif
335 
336 #if (H5_VERS_MAJOR > 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR > 6))
337  hid_t dset = H5Dopen(d_group_id, key.c_str(), H5P_DEFAULT);
338 #else
339  hid_t dset = H5Dopen(d_group_id, key.c_str());
340 #endif
341  CAROM_VERIFY(dset >= 0);
342 
343  hid_t dspace = H5Dget_space(dset);
344  CAROM_VERIFY(dspace >= 0);
345 
346  hsize_t nsel = H5Sget_select_npoints(dspace);
347  CAROM_VERIFY(static_cast<int>(nsel) == nelements);
348 
349  herr_t errf;
350  if (nsel > 0) {
351  errf = H5Dread(dset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
352  CAROM_VERIFY(errf >= 0);
353  }
354 
355  errf = H5Sclose(dspace);
356  CAROM_VERIFY(errf >= 0);
357 
358  errf = H5Dclose(dset);
359  CAROM_VERIFY(errf >= 0);
360 #ifndef DEBUG_CHECK_ASSERTIONS
361  CAROM_NULL_USE(errf);
362 #endif
363 }
364 
365 void
367  const std::string& key,
368  double* data,
369  int nelements,
370  const std::vector<int>& idx,
371  const bool distributed)
372 {
373  if (idx.size() == 0)
374  {
375  getDoubleArray(key, data, nelements);
376  }
377  else
378  {
379  std::vector<double> alldata(nelements);
380  getDoubleArray(key, alldata.data(), nelements);
381  int k = 0;
382  for (int i = 0; i < nelements; ++i)
383  {
384  if (idx[k] == i)
385  {
386  data[k++] = alldata[i];
387  }
388  if (k == idx.size())
389  {
390  break;
391  }
392  }
393  CAROM_VERIFY(k == idx.size());
394  }
395 }
396 
397 void
399  const std::string& key,
400  double* data,
401  int nelements,
402  int offset,
403  int block_size,
404  int stride,
405  const bool distributed)
406 {
407  CAROM_VERIFY(!key.empty());
408 #ifndef DEBUG_CHECK_ASSERTIONS
409  CAROM_NULL_USE(nelements);
410 #endif
411 
412 #if (H5_VERS_MAJOR > 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR > 6))
413  hid_t dset = H5Dopen(d_group_id, key.c_str(), H5P_DEFAULT);
414 #else
415  hid_t dset = H5Dopen(d_group_id, key.c_str());
416 #endif
417  CAROM_VERIFY(dset >= 0);
418 
419  hid_t dspace = H5Dget_space(dset);
420  CAROM_VERIFY(dspace >= 0);
421 
422  hsize_t nsel = H5Sget_select_npoints(dspace);
423 
424  herr_t errf;
425  if (nsel > 0) {
426 
427  hsize_t num_blocks[1] = {(hsize_t) nelements/block_size};
428  hsize_t buffer_array_size[1] = {(hsize_t) nelements};
429  hsize_t offsets[1] = {(hsize_t) offset};
430  hsize_t strides[1] = {(hsize_t) stride};
431  hsize_t block_sizes[1] = {(hsize_t) block_size};
432  hid_t nodespace = H5Screate_simple(1,buffer_array_size,NULL);
433 
434  // select hyperslab
435  H5Sselect_hyperslab(dspace, H5S_SELECT_SET, offsets,
436  strides, num_blocks, block_sizes);
437 
438  errf = H5Dread(dset, H5T_NATIVE_DOUBLE, nodespace, dspace, H5P_DEFAULT, data);
439  CAROM_VERIFY(errf >= 0);
440  }
441 
442  errf = H5Sclose(dspace);
443  CAROM_VERIFY(errf >= 0);
444 
445  errf = H5Dclose(dset);
446  CAROM_VERIFY(errf >= 0);
447 #ifndef DEBUG_CHECK_ASSERTIONS
448  CAROM_NULL_USE(errf);
449 #endif
450 }
451 
452 bool
454  const std::string& key)
455 {
456  bool is_int = false;
457 
458  if (!key.empty()) {
459 #if (H5_VERS_MAJOR > 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR > 6))
460  hid_t this_set = H5Dopen(d_group_id, key.c_str(), H5P_DEFAULT);
461 #else
462  hid_t this_set = H5Dopen(d_group_id, key.c_str());
463 #endif
464  if (this_set > 0) {
465  int type_key = readAttribute(this_set);
466  if (type_key == KEY_INT_ARRAY) {
467  is_int = true;
468  }
469  herr_t errf = H5Dclose(this_set);
470  CAROM_VERIFY(errf >= 0);
471 #ifndef DEBUG_CHECK_ASSERTIONS
472  CAROM_NULL_USE(errf);
473 #endif
474  }
475  }
476 
477  return is_int;
478 }
479 
480 bool
482  const std::string& key)
483 {
484  bool is_double = false;
485 
486  if (!key.empty()) {
487 #if (H5_VERS_MAJOR > 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR > 6))
488  hid_t this_set = H5Dopen(d_group_id, key.c_str(), H5P_DEFAULT);
489 #else
490  hid_t this_set = H5Dopen(d_group_id, key.c_str());
491 #endif
492  if (this_set > 0) {
493  int type_key = readAttribute(this_set);
494  if (type_key == KEY_DOUBLE_ARRAY) {
495  is_double = true;
496  }
497  herr_t errf = H5Dclose(this_set);
498  CAROM_VERIFY(errf >= 0);
499 #ifndef DEBUG_CHECK_ASSERTIONS
500  CAROM_NULL_USE(errf);
501 #endif
502  }
503  }
504 
505  return is_double;
506 }
507 
508 void
510  int type_key,
511  hid_t dataset_id)
512 {
513  hid_t attr_id = H5Screate(H5S_SCALAR);
514  CAROM_VERIFY(attr_id >= 0);
515 
516 #if (H5_VERS_MAJOR > 1) || ((H5_VERS_MAJOR == 1) && (H5_VERS_MINOR > 6))
517  hid_t attr = H5Acreate(dataset_id,
518  "Type",
519  H5T_STD_I8BE,
520  attr_id,
521  H5P_DEFAULT,
522  H5P_DEFAULT);
523 #else
524  hid_t attr = H5Acreate(dataset_id,
525  "Type",
526  H5T_STD_I8BE,
527  attr_id,
528  H5P_DEFAULT);
529 #endif
530  CAROM_VERIFY(attr >= 0);
531 
532  herr_t errf = H5Awrite(attr, H5T_NATIVE_INT, &type_key);
533  CAROM_VERIFY(errf >= 0);
534 
535  errf = H5Aclose(attr);
536  CAROM_VERIFY(errf >= 0);
537 
538  errf = H5Sclose(attr_id);
539  CAROM_VERIFY(errf >= 0);
540 #ifndef DEBUG_CHECK_ASSERTIONS
541  CAROM_NULL_USE(errf);
542 #endif
543 }
544 
545 int
547  hid_t dataset_id)
548 {
549  hid_t attr = H5Aopen_name(dataset_id, "Type");
550  CAROM_VERIFY(attr >= 0);
551 
552  int type_key;
553  herr_t errf = H5Aread(attr, H5T_NATIVE_INT, &type_key);
554  CAROM_VERIFY(errf >= 0);
555 
556  errf = H5Aclose(attr);
557  CAROM_VERIFY(errf >= 0);
558 #ifndef DEBUG_CHECK_ASSERTIONS
559  CAROM_NULL_USE(errf);
560 #endif
561 
562  return type_key;
563 }
564 
565 }
virtual bool create(const std::string &file_name, const MPI_Comm comm=MPI_COMM_NULL)
Creates a new database file with the supplied name.
Definition: Database.cpp:35
virtual bool open(const std::string &file_name, const std::string &type, const MPI_Comm comm=MPI_COMM_NULL)
Opens an existing database file with the supplied name.
Definition: Database.cpp:44
bool d_is_file
True if the HDF5 database is mounted to a file.
Definition: HDFDatabase.h:323
static const int KEY_DOUBLE_ARRAY
The key representing a double array.
Definition: HDFDatabase.h:338
virtual ~HDFDatabase()
Destructor.
Definition: HDFDatabase.cpp:29
bool isInteger(const std::string &key)
Returns true if the specified key represents an integer entry. If the key does not exist or if the st...
bool isDouble(const std::string &key)
Returns true if the specified key represents a double entry. If the key does not exist or if the stri...
int d_rank
MPI process rank.
Definition: HDFDatabase.h:348
virtual void getIntegerArray(const std::string &key, int *data, int nelements, const bool distributed=false)
Reads an array of integers associated with the supplied key from the currently open HDF5 database fil...
virtual bool create(const std::string &file_name, const MPI_Comm comm=MPI_COMM_NULL) override
Creates a new HDF5 database file with the supplied name.
Definition: HDFDatabase.cpp:45
int readAttribute(hid_t dataset_id)
Read an attribute from the specified dataset.
virtual bool open(const std::string &file_name, const std::string &type, const MPI_Comm comm=MPI_COMM_NULL) override
Opens an existing HDF5 database file with the supplied name.
Definition: HDFDatabase.cpp:76
virtual void getDoubleArray(const std::string &key, double *data, int nelements, const bool distributed=false)
Reads an array of doubles associated with the supplied key from the currently open HDF5 database file...
hid_t d_group_id
ID of the group attached to the database.
Definition: HDFDatabase.h:333
HDFDatabase()
Default constructor.
Definition: HDFDatabase.cpp:22
static const int KEY_INT_ARRAY
The key representing an integer array.
Definition: HDFDatabase.h:343
virtual int getDoubleArraySize(const std::string &key)
Count the number of elements in an array of doubles associated with the supplied key from the current...
virtual void putDoubleArray(const std::string &key, const double *const data, int nelements, const bool distributed=false)
Writes an array of doubles associated with the supplied key to the currently open HDF5 database file.
virtual void putIntegerArray(const std::string &key, const int *const data, int nelements, const bool distributed=false)
Writes an array of integers associated with the supplied key to the currently open HDF5 database file...
virtual void writeAttribute(int type_key, hid_t dataset_id)
Write an attribute to the specified dataset.
virtual bool close()
Closes the currently open HDF5 database file.
hid_t d_file_id
ID of file attached to database or -1 if not mounted to a file.
Definition: HDFDatabase.h:328
virtual void putDoubleVector(const std::string &key, const std::vector< double > &data, int nelements, const bool distributed=false)
Writes a vector of doubles associated with the supplied key to the currently open HDF5 database file.