QMCPACK
hdf_archive.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
8 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
9 //
10 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
11 //////////////////////////////////////////////////////////////////////////////////////
12 
13 
14 #include "hdf_archive.h"
15 #ifdef HAVE_MPI
16 #include "mpi3/communicator.hpp"
17 #endif
18 #include "Message/Communicate.h"
19 
20 namespace qmcplusplus
21 {
22 
24 
26 {
27 #if defined(ENABLE_PHDF5)
28  if (xfer_plist != H5P_DEFAULT)
29  H5Pclose(xfer_plist);
30  if (access_id != H5P_DEFAULT)
31  H5Pclose(access_id);
32 #endif
33  if (lcpl_id != H5P_DEFAULT)
34  H5Pclose(lcpl_id);
35  close();
36 }
37 
39 {
40  while (!group_id.empty())
41  {
42  hid_t gid = group_id.top();
43  group_id.pop();
44  group_names.pop_back();
45  H5Gclose(gid);
46  }
47  if (file_id != is_closed)
48  H5Fclose(file_id);
50 }
51 
53 {
54  access_id = H5P_DEFAULT;
55  lcpl_id = H5Pcreate(H5P_LINK_CREATE);
56  H5Pset_create_intermediate_group(lcpl_id, true);
57  Mode.set(IS_PARALLEL, false);
58  Mode.set(IS_MASTER, true);
59  Mode.set(NOIO, false);
60 }
61 
63 {
64  access_id = H5P_DEFAULT;
65  lcpl_id = H5Pcreate(H5P_LINK_CREATE);
66  H5Pset_create_intermediate_group(lcpl_id, true);
67  if (comm && comm->size() > 1) //for parallel communicator
68  {
69  bool use_phdf5 = false;
70 #if defined(ENABLE_PHDF5)
71  if (request_pio)
72  {
73  // enable parallel I/O
74  MPI_Info info = MPI_INFO_NULL;
75  access_id = H5Pcreate(H5P_FILE_ACCESS);
76  H5Pset_all_coll_metadata_ops(access_id, true);
77  H5Pset_coll_metadata_write(access_id, true);
78  H5Pset_fapl_mpio(access_id, comm->getMPI(), info);
79  xfer_plist = H5Pcreate(H5P_DATASET_XFER);
80  // enable parallel collective I/O
81  H5Pset_dxpl_mpio(xfer_plist, H5FD_MPIO_COLLECTIVE);
82  use_phdf5 = true;
83  }
84 #endif
85  Mode.set(IS_PARALLEL, use_phdf5);
86  Mode.set(IS_MASTER, !comm->rank());
87  if (request_pio && !use_phdf5)
88  Mode.set(NOIO, comm->rank()); // master only
89  else
90  Mode.set(NOIO, false); // pio or all.
91  }
92  else
93  {
94  Mode.set(IS_PARALLEL, false);
95  Mode.set(IS_MASTER, true);
96  Mode.set(NOIO, false);
97  }
98 }
99 
100 #ifdef HAVE_MPI
101 void hdf_archive::set_access_plist(boost::mpi3::communicator& comm, bool request_pio)
102 {
103  access_id = H5P_DEFAULT;
104  lcpl_id = H5Pcreate(H5P_LINK_CREATE);
105  H5Pset_create_intermediate_group(lcpl_id, true);
106  if (comm.size() > 1) //for parallel communicator
107  {
108  bool use_phdf5 = false;
109  if (request_pio)
110  {
111 #if defined(ENABLE_PHDF5)
112  // enable parallel I/O
113  MPI_Info info = MPI_INFO_NULL;
114  access_id = H5Pcreate(H5P_FILE_ACCESS);
115  H5Pset_all_coll_metadata_ops(access_id, true);
116  H5Pset_coll_metadata_write(access_id, true);
117  H5Pset_fapl_mpio(access_id, comm.get(), info);
118  xfer_plist = H5Pcreate(H5P_DATASET_XFER);
119  // enable parallel collective I/O
120  H5Pset_dxpl_mpio(xfer_plist, H5FD_MPIO_COLLECTIVE);
121  use_phdf5 = true;
122 #else
123  use_phdf5 = false;
124 #endif
125  }
126  Mode.set(IS_PARALLEL, use_phdf5);
127  Mode.set(IS_MASTER, !comm.rank());
128  if (request_pio && !use_phdf5)
129  Mode.set(NOIO, comm.rank()); // master only
130  else
131  Mode.set(NOIO, false); // pio or all.
132  }
133  else
134  {
135  Mode.set(IS_PARALLEL, false);
136  Mode.set(IS_MASTER, true);
137  Mode.set(NOIO, false);
138  }
139 }
140 #endif
141 
142 
143 bool hdf_archive::create(const std::filesystem::path& fname, unsigned flags)
144 {
145  possible_filename_ = fname;
146  if (Mode[NOIO])
147  return true;
148  if (!(Mode[IS_PARALLEL] || Mode[IS_MASTER]))
149  throw std::runtime_error("Only create file in parallel or by master but not every rank!");
150  close();
151  file_id = H5Fcreate(fname.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, access_id);
152  return file_id != is_closed;
153 }
154 
155 bool hdf_archive::open(const std::filesystem::path& fname, unsigned flags)
156 {
157  possible_filename_ = fname;
158  if (Mode[NOIO])
159  return true;
160  close();
161  file_id = H5Fopen(fname.c_str(), flags, access_id);
162  return file_id != is_closed;
163 }
164 
165 bool hdf_archive::is_group(const std::string& aname)
166 {
167  if (Mode[NOIO])
168  return true;
169  if (file_id == is_closed)
170  return false;
171  hid_t p = group_id.empty() ? file_id : group_id.top();
172  p = (aname[0] == '/') ? file_id : p;
173 
174  if (H5Lexists(p, aname.c_str(), H5P_DEFAULT) > 0)
175  {
176 #if H5_VERSION_GE(1, 12, 0)
177  H5O_info2_t oinfo;
178 #else
179  H5O_info_t oinfo;
180 #endif
181  oinfo.type = H5O_TYPE_UNKNOWN;
182 #if H5_VERSION_GE(1, 12, 0)
183  H5Oget_info_by_name3(p, aname.c_str(), &oinfo, H5O_INFO_BASIC, H5P_DEFAULT);
184 #else
185  H5Oget_info_by_name(p, aname.c_str(), &oinfo, H5P_DEFAULT);
186 #endif
187 
188  if (oinfo.type != H5O_TYPE_GROUP)
189  return false;
190  return true;
191  }
192  else
193  {
194  return false;
195  }
196 }
197 
198 void hdf_archive::push(const std::string& gname, bool createit)
199 {
200  hid_t g = is_closed;
201  if (Mode[NOIO])
202  return;
203 
204  if (file_id == is_closed)
205  throw std::runtime_error("Failed to open group \"" + gname +
206  "\" because file is not open. Expected file: " + possible_filename_);
207 
208  hid_t p = group_id.empty() ? file_id : group_id.top();
209 
210 #if H5_VERSION_GE(1, 12, 0)
211  H5O_info2_t oinfo;
212 #else
213  H5O_info_t oinfo;
214 #endif
215  oinfo.type = H5O_TYPE_UNKNOWN;
216  if (H5Lexists(p, gname.c_str(), H5P_DEFAULT) > 0)
217  {
218 #if H5_VERSION_GE(1, 12, 0)
219  H5Oget_info_by_name3(p, gname.c_str(), &oinfo, H5O_INFO_BASIC, H5P_DEFAULT);
220 #else
221  H5Oget_info_by_name(p, gname.c_str(), &oinfo, H5P_DEFAULT);
222 #endif
223  }
224 
225  if ((oinfo.type != H5O_TYPE_GROUP) && createit)
226  {
227  g = H5Gcreate2(p, gname.c_str(), lcpl_id, H5P_DEFAULT, H5P_DEFAULT);
228  }
229  else
230  {
231  g = H5Gopen2(p, gname.c_str(), H5P_DEFAULT);
232  }
233  if (g != is_closed)
234  {
235  group_id.push(g);
236  group_names.push_back(gname);
237  }
238 
239  if (!createit && g < 0)
240  throw std::runtime_error("Group \"" + gname + "\" not found in file " + possible_filename_ +
241  ". Group path: " + group_path_as_string());
242 }
243 
244 void hdf_archive::push(const hdf_path& gname, bool createit) { push(gname.string(), createit); }
245 
247 {
248  std::string group_path;
249  for (auto it = group_names.begin(); it != group_names.end(); it++)
250  {
251  group_path += *it;
252  if (it != group_names.end() - 1)
253  group_path += "/";
254  }
255 
256  return group_path;
257 }
258 
259 } // namespace qmcplusplus
bool open(const std::filesystem::path &fname, unsigned flags=H5F_ACC_RDWR)
open a file
const std::string & string() const
Return std::string for use with HDF5.
Definition: hdf_path.h:67
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
int rank() const
return the rank
Definition: Communicate.h:116
hid_t lcpl_id
Link creation property list identifier.
Definition: hdf_archive.h:74
void close()
close all the open groups and file
Definition: hdf_archive.cpp:38
std::stack< hid_t > group_id
FILO to handle H5Group.
Definition: hdf_archive.h:76
std::string possible_filename_
Name of file that hdf_archive thinks is open.
Definition: hdf_archive.h:84
std::bitset< 4 > Mode
bitset of the io mode Mode[IS_PARALLEL] : true, if parallel Mode[IS_MASTER] : true, if the node is master Mode[NOIO] : true, if I/O is not performed
Definition: hdf_archive.h:66
int size() const
return the number of tasks
Definition: Communicate.h:118
Wrapping information on parallelism.
Definition: Communicate.h:68
class suppressing warnings from the HDF5 library
hdf_error_suppression hide_hdf_errors
Suppress HDF5 warning and error messages.
Definition: hdf_archive.cpp:23
static const hid_t is_closed
Definition: hdf_archive.h:60
hid_t access_id
access id
Definition: hdf_archive.h:70
hid_t file_id
file id
Definition: hdf_archive.h:68
void push(const std::string &gname, bool createit=true)
push a group to the group stack
bool create(const std::filesystem::path &fname, unsigned flags=H5F_ACC_TRUNC)
create a file
std::string group_path_as_string() const
Return a string representation of the current group stack.
hid_t xfer_plist
transfer property
Definition: hdf_archive.h:72
bool is_group(const std::string &aname)
check if aname is a group
mpi_comm_type getMPI() const
return the Communicator ID (typically MPI_WORLD_COMM)
Definition: Communicate.h:113
std::vector< std::string > group_names
Track group names corresponding to group_id.
Definition: hdf_archive.h:78