QMCPACK
hdf_hyperslab.h
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 //
9 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 
13 #ifndef QMCPLUSPLUS_HDF_HYPERSLAB_IO_H
14 #define QMCPLUSPLUS_HDF_HYPERSLAB_IO_H
15 
16 #include <array>
18 #include "hdf_datatype.h"
19 #include "hdf_dataspace.h"
20 #include "hdf_dataproxy.h"
21 
22 namespace qmcplusplus
23 {
24 /** class to use file space hyperslab with a serialized container
25  * @tparam CT container type, std::vector, Vector, Matrix, Array, boost::multi::array
26  * @tparam RANK hyperslab user rank. The dimensions contributed by T are excluded.
27  *
28  * The container may get resized for sufficient space if
29  * the template specialization of container_traits<CT> is available
30  * additional restriction:
31  * 1D containers can be resized to hold any multi-dimensional data
32  * >1D containers can only be resize to hold data with matching dimensions.
33  */
34 template<typename CT, unsigned RANK>
36 {
37  ///user rank of a hyperslab
38  static const unsigned int slab_rank = RANK;
39 
41  /** type alias for h5_space_type
42  * encapsulates both RANK and ranks contributed by element_type
43  * for constructing an hdf5 dataspace.
44  */
46  ///global dimension of the hyperslab
48  ///local dimension of the hyperslab
50  ///offset of the hyperslab
51  std::array<hsize_t, SpaceType::rank> slab_offset;
52  ///container reference
53  CT& ref_;
54 
55  /** constructor
56  * @tparam IT integer type
57  * @param a data containter
58  * @param dims_in dimension sizes of a dataset.
59  * @param selected_in dimension sizes of the selected part of the dataset
60  * @param offsets_in offsets of the selected part of the dataset
61  *
62  * value 0 in any dimension of dims_in or selected_in is allowed when reading a dataset.
63  * The actual size is derived from file dataset.
64  */
65  template<typename IT>
66  inline hyperslab_proxy(CT& a,
67  const std::array<IT, RANK>& dims_in,
68  const std::array<IT, RANK>& selected_in,
69  const std::array<IT, RANK>& offsets_in)
70  : ref_(a)
71  {
72  static_assert(std::is_unsigned<IT>::value, "only accept unsigned integer types like size_t");
73  for (int i = 0; i < slab_rank; ++i)
74  {
75  file_space.dims[i] = static_cast<hsize_t>(dims_in[i]);
76  selected_space.dims[i] = static_cast<hsize_t>(selected_in[i]);
77  slab_offset[i] = static_cast<hsize_t>(offsets_in[i]);
78  }
79 
80  /// element_type related dimensions always have offset 0
81  for (int i = slab_rank; i < SpaceType::rank; ++i)
82  slab_offset[i] = 0;
83  }
84 
85  /** return the size of the i-th dimension of global space
86  * @param i dimension
87  */
88  inline hsize_t size(int i) const { return (i > SpaceType::rank) ? 0 : file_space.dims[i]; }
89 
90  /** checks if file_space, elected_space and offset are self-consistent
91  */
92  inline void checkUserRankSizes() const
93  {
94  if (std::any_of(file_space.dims, file_space.dims + slab_rank, [](int i) { return i == 0; }))
95  throw std::runtime_error("Zero size detected in some dimensions of filespace\n");
96  if (std::any_of(selected_space.dims, selected_space.dims + slab_rank, [](int i) { return i == 0; }))
97  throw std::runtime_error("Zero size detected in some dimensions of selected filespace\n");
98  for (int dim = 0; dim < slab_rank; dim++)
99  {
100  if (slab_offset[dim] > file_space.dims[dim])
101  throw std::runtime_error("offset outsdie the bound of filespace");
102  if (slab_offset[dim] + selected_space.dims[dim] > file_space.dims[dim])
103  {
104  std::ostringstream err_msg;
105  err_msg << "dim " << dim << " offset " << slab_offset[dim] << " + selected_space size "
106  << selected_space.dims[dim] << " outsdie the bound of filespace " << file_space.dims[dim] << std::endl;
107  throw std::runtime_error(err_msg.str());
108  }
109  }
110  }
111 
112  /** check if the container is large enough for the selected space and resize if requested
113  */
114  inline bool checkContainerCapacity() const
115  {
116  hsize_t total_size = slab_rank > 0 ? 1 : 0;
117  for (int dim = 0; dim < slab_rank; dim++)
118  total_size *= selected_space.dims[dim];
119  return total_size > container_traits<CT>::getSize(ref_) ? false : true;
120  }
121 
122  /** adjust file_space and selected_space shapes based on sizes_file
123  * @tparam IT integer type
124  * @param sizes_file sizes of all the user dimensions of a dataset
125  *
126  * This function can only be used when reading a dataset not writing
127  * if the size value of a dimension is 0, use the value based on the dataset on disk
128  */
129  template<typename IT>
130  inline void adaptShape(const std::vector<IT>& sizes_file)
131  {
132  // validate user ranks
133  if (sizes_file.size() != slab_rank)
134  throw std::runtime_error("User specified and filespace dimensions mismatch!\n");
135 
136  for (int dim = 0; dim < slab_rank; dim++)
137  {
138  if (file_space.dims[dim] == 0)
139  file_space.dims[dim] = sizes_file[dim];
140  else if (file_space.dims[dim] != sizes_file[dim])
141  {
142  std::ostringstream err_msg;
143  err_msg << "dim " << dim << " user specified size " << file_space.dims[dim] << " filespace size "
144  << sizes_file[dim] << " mismatched!" << std::endl;
145  throw std::runtime_error(err_msg.str());
146  }
147 
148  if (selected_space.dims[dim] == 0)
149  selected_space.dims[dim] = file_space.dims[dim];
150  }
151  }
152 };
153 
154 template<typename CT, unsigned RANK>
155 struct h5data_proxy<hyperslab_proxy<CT, RANK>>
156 {
158 
159  h5data_proxy(const data_type& a) {}
160 
161  inline bool read(data_type& ref, hid_t grp, const std::string& aname, hid_t xfer_plist = H5P_DEFAULT)
162  {
163  std::vector<hsize_t> sizes_file;
164  getDataShape<typename data_type::element_type>(grp, aname, sizes_file);
165  ref.adaptShape(sizes_file);
166  ref.checkUserRankSizes();
167  if (!ref.checkContainerCapacity())
169  return h5d_read(grp, aname.c_str(), ref.file_space.rank, ref.file_space.dims, ref.selected_space.dims,
170  ref.slab_offset.data(),
172  xfer_plist);
173  }
174 
175  inline bool write(const data_type& ref, hid_t grp, const std::string& aname, hid_t xfer_plist = H5P_DEFAULT) const
176  {
177  ref.checkUserRankSizes();
178  if (!ref.checkContainerCapacity())
179  throw std::runtime_error("Not large enough container capacity!\n");
180  return h5d_write(grp, aname.c_str(), ref.file_space.rank, ref.file_space.dims, ref.selected_space.dims,
181  ref.slab_offset.data(),
183  xfer_plist);
184  }
185 };
186 
187 } // namespace qmcplusplus
188 #endif
define h5_space_type to handle basic datatype for hdf5
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
void checkUserRankSizes() const
checks if file_space, elected_space and offset are self-consistent
Definition: hdf_hyperslab.h:92
class to use file space hyperslab with a serialized container
Definition: hdf_hyperslab.h:35
bool checkContainerCapacity() const
check if the container is large enough for the selected space and resize if requested ...
typename container_traits< CT >::element_type element_type
Definition: hdf_hyperslab.h:40
std::array< hsize_t, SpaceType::rank > slab_offset
offset of the hyperslab
Definition: hdf_hyperslab.h:51
typename CT::value_type element_type
the data type of elements
void adaptShape(const std::vector< IT > &sizes_file)
adjust file_space and selected_space shapes based on sizes_file
hsize_t dims[RANK > 0 ? RANK :1]
shape of the dataspace, protected for zero size array, hdf5 support scalar as rank = 0 ...
Definition: hdf_dataspace.h:47
hyperslab_proxy(CT &a, const std::array< IT, RANK > &dims_in, const std::array< IT, RANK > &selected_in, const std::array< IT, RANK > &offsets_in)
constructor
Definition: hdf_hyperslab.h:66
CT & ref_
container reference
Definition: hdf_hyperslab.h:53
static auto get_address(element_type *a)
return the address
Definition: hdf_dataspace.h:53
SpaceType selected_space
local dimension of the hyperslab
Definition: hdf_hyperslab.h:49
SpaceType file_space
global dimension of the hyperslab
Definition: hdf_hyperslab.h:47
static constexpr hsize_t rank
rank of the multidimensional dataspace
Definition: hdf_dataspace.h:49
bool h5d_read(hid_t grp, const std::string &aname, T *first, hid_t xfer_plist)
return true, if successful
bool read(data_type &ref, hid_t grp, const std::string &aname, hid_t xfer_plist=H5P_DEFAULT)
bool write(const data_type &ref, hid_t grp, const std::string &aname, hid_t xfer_plist=H5P_DEFAULT) const
bool h5d_write(hid_t grp, const std::string &aname, hsize_t ndims, const hsize_t *dims, const T *first, hid_t xfer_plist)
static const unsigned int slab_rank
user rank of a hyperslab
Definition: hdf_hyperslab.h:38
generic h5data_proxy<T> for scalar basic datatypes defined in hdf_dataspace.h Note if the dataset to ...
Definition: hdf_dataproxy.h:29
hsize_t size(int i) const
return the size of the i-th dimension of global space
Definition: hdf_hyperslab.h:88