ALPSCore reference
hdf5.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1998-2018 ALPS Collaboration. See COPYRIGHT.TXT
3  * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4  * For use in publications, see ACKNOWLEDGE.TXT
5  */
6 #pragma once
7 
8 #include <sstream>
9 #include <numeric>
10 #include <iostream>
11 
12 #include <alps/alea/core.hpp>
13 
14 #include <alps/hdf5/archive.hpp>
15 
16 namespace alps { namespace alea {
17 
19  : public serializer
20  , public deserializer
21 {
22 public:
23  hdf5_serializer(hdf5::archive &ar, const std::string &path)
24  : archive_(&ar)
25  , path_(path)
26  , group_()
27  { }
28 
29  // Common methods
30 
31  void enter(const std::string &group) override
32  {
33  archive_->create_group(get_path(group)); // TODO: what if exists?
34  group_.push_back(group);
35  }
36 
37  void exit() override
38  {
39  if (group_.empty())
40  throw std::runtime_error("exit without enter");
41  group_.pop_back();
42  }
43 
44  void write(const std::string &key, ndview<const double> value) override {
45  do_write(key, value);
46  }
47 
48  void write(const std::string &key, ndview<const std::complex<double>> value) override {
49  do_write(key, value);
50  }
51 
52  void write(const std::string &key, ndview<const complex_op<double>> value) override {
53  throw unsupported_operation(); // FIXME
54  }
55 
56  void write(const std::string &key, ndview<const long> value) override {
57  do_write(key, value);
58  }
59 
60  void write(const std::string &key, ndview<const unsigned long> value) override {
61  do_write(key, value);
62  }
63 
64  // Deserialization methods
65 
66  std::vector<size_t> get_shape(const std::string &key) override {
67  return get_extent(get_path(key));
68  }
69 
70  void read(const std::string &key, ndview<double> value) override {
71  do_read(key, value);
72  }
73 
74  void read(const std::string &key, ndview<std::complex<double>> value) override {
75  do_read(key, value);
76  }
77 
78  void read(const std::string &key, ndview<complex_op<double>> value) override {
79  throw unsupported_operation(); // FIXME
80  }
81 
82  void read(const std::string &key, ndview<long> value) override {
83  do_read(key, value);
84  }
85 
86  void read(const std::string &key, ndview<unsigned long> value) override {
87  do_read(key, value);
88  }
89 
91  {
92  // Cannot do exception because we are in destructor
93  if (!group_.empty()) {
94  std::cerr << "alps::alea::hdf5_serializer: warning: "
95  << "enter without exit\n Lingering groups:"
96  << get_path("") << "\n\n";
97  }
98  }
99 
100 protected:
101  template <typename T>
102  void do_write(const std::string &relpath, ndview<const T> data)
103  {
104  std::string path = get_path(relpath);
105 
106  std::vector<size_t> shape(data.shape(), data.shape() + data.ndim());
107  std::vector<size_t> offset(shape.size(), 0);
108  std::vector<size_t> chunk = shape;
109 
110  if (data.ndim() == 0)
111  archive_->write(path, *data.data());
112  else
113  archive_->write(path, data.data(), shape, chunk, offset);
114  }
115 
116  template <typename T>
117  void do_write(const std::string &relpath, ndview<const std::complex<T>> data)
118  {
119  std::string path = get_path(relpath);
120 
121  if (data.ndim() == 0)
122  throw unsupported_operation();
123 
124  std::vector<size_t> shape(data.shape(), data.shape() + data.ndim());
125  shape.push_back(2); // for complex
126  std::vector<size_t> offset(shape.size(), 0);
127  std::vector<size_t> chunk = shape;
128 
129  // hdf5::archive does not support complex
130  archive_->write(path, reinterpret_cast<const T*>(data.data()), shape,
131  chunk, offset);
132  archive_->write(path + "/@__complex__", true);
133  }
134 
135  template <typename T>
136  void do_read(const std::string &relpath, ndview<T> data)
137  {
138  std::string path = get_path(relpath);
139 
140  // check shape (this is cheap compared to reading)
141  std::vector<size_t> shape = get_extent(path);
142  if (data.ndim() != shape.size())
143  throw size_mismatch();
144  for (size_t i = 0; i != shape.size(); ++i)
145  if (shape[i] != data.shape()[i])
146  throw size_mismatch();
147 
148  // discard the data
149  if (data.data() == nullptr)
150  return;
151 
152  if (shape.empty()) {
153  archive_->read(path, *data.data());
154  } else {
155  // vector read
156  std::vector<size_t> offset(shape.size(), 0);
157  std::vector<size_t> chunk = shape;
158  archive_->read(path, data.data(), chunk, offset);
159  }
160  }
161 
162  template <typename T>
163  void do_read(const std::string &relpath, ndview<std::complex<T>> data)
164  {
165  std::string path = get_path(relpath);
166 
167  // check shape (this is cheap compared to reading)
168  std::vector<size_t> shape = get_extent(path);
169  if (data.ndim() != shape.size() - 1)
170  throw size_mismatch();
171  for (size_t i = 0; i != data.ndim(); ++i)
172  if (shape[i] != data.shape()[i])
173  throw size_mismatch();
174  if (shape[data.ndim()] != 2)
175  throw size_mismatch();
176 
177  // discard the data
178  if (data.data() == nullptr)
179  return;
180 
181  // vector read
182  std::vector<size_t> offset(shape.size(), 0);
183  std::vector<size_t> chunk = shape;
184  archive_->read(path, reinterpret_cast<T*>(data.data()), chunk, offset);
185 
186  bool tag;
187  archive_->read(path + "/@__complex__", tag);
188  }
189 
190  std::string get_path(const std::string &key)
191  {
192  std::ostringstream maker(path_, std::ios_base::app);
193  maker << '/';
194  for (const std::string &group : group_)
195  maker << group << '/';
196  if (key.find('/') != std::string::npos)
197  throw std::runtime_error("Key must not contain '/'");
198  maker << key;
199  return maker.str();
200  }
201 
202  std::vector<size_t> get_extent(const std::string &path)
203  {
204  if (archive_->is_scalar(path))
205  return std::vector<size_t>();
206  else
207  return archive_->extent(path);
208  }
209 
210 private:
211  hdf5::archive *archive_;
212  std::string path_;
213  std::vector<std::string> group_;
214 };
215 
216 }}
hdf5_serializer(hdf5::archive &ar, const std::string &path)
Definition: hdf5.hpp:23
T * data()
Definition: core.hpp:68
bool is_scalar(std::string path) const
Definition: archive.cpp:199
std::string get_path(const std::string &key)
Definition: hdf5.hpp:190
const size_t * shape() const
Definition: core.hpp:117
void read(const std::string &key, ndview< long > value) override
Definition: hdf5.hpp:82
void do_write(const std::string &relpath, ndview< const T > data)
Definition: hdf5.hpp:102
void enter(const std::string &group) override
Definition: hdf5.hpp:31
void write(const std::string &key, ndview< const unsigned long > value) override
Definition: hdf5.hpp:60
void read(const std::string &key, ndview< unsigned long > value) override
Definition: hdf5.hpp:86
void write(const std::string &key, ndview< const long > value) override
Definition: hdf5.hpp:56
void do_write(const std::string &relpath, ndview< const std::complex< T >> data)
Definition: hdf5.hpp:117
void write(const std::string &key, ndview< const std::complex< double >> value) override
Definition: hdf5.hpp:48
std::vector< std::size_t > extent(std::string path) const
Definition: archive.cpp:291
std::vector< size_t > get_shape(const std::string &key) override
Definition: hdf5.hpp:66
void read(const std::string &key, ndview< std::complex< double >> value) override
Definition: hdf5.hpp:74
void create_group(std::string path) const
Definition: archive.cpp:327
void write(const std::string &key, ndview< const complex_op< double >> value) override
Definition: hdf5.hpp:52
auto read(std::string path, T *, std::vector< std::size_t >, std::vector< std::size_t >=std::vector< std::size_t >()) const -> typename std::enable_if<!is_native_type< T >::value, void >::type
Definition: archive.hpp:163
auto write(std::string path, T const *value, std::vector< std::size_t > size, std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t > offset=std::vector< std::size_t >()) const -> typename std::enable_if<!is_native_type< T >::value, void >::type
Definition: archive.hpp:172
void read(const std::string &key, ndview< complex_op< double >> value) override
Definition: hdf5.hpp:78
void do_read(const std::string &relpath, ndview< std::complex< T >> data)
Definition: hdf5.hpp:163
size_t ndim() const
Definition: core.hpp:120
void write(const std::string &key, ndview< const double > value) override
Definition: hdf5.hpp:44
void exit() override
Definition: hdf5.hpp:37
void read(const std::string &key, ndview< double > value) override
Definition: hdf5.hpp:70
std::vector< size_t > get_extent(const std::string &path)
Definition: hdf5.hpp:202
void do_read(const std::string &relpath, ndview< T > data)
Definition: hdf5.hpp:136