14#include <boost/array.hpp>
15#include <boost/utility/enable_if.hpp>
16#include <boost/noncopyable.hpp>
17#include <boost/type_traits.hpp>
18#include <boost/assert.hpp>
20#include <boost/typeof/typeof.hpp>
22#include "mpqc/range.hpp"
23#include "mpqc/range/operator.hpp"
25#include "mpqc/utility/check.hpp"
26#include <boost/foreach.hpp>
27#include "mpqc/utility/timer.hpp"
28#include "mpqc/utility/mutex.hpp"
30#include <util/misc/exenv.h>
41#define MPQC_FILE_VERIFY(expr) MPQC_CHECK((expr) >= 0)
43#ifndef H5_HAVE_THREADSAFE
44#warning "HDF5 NOT THREADSAFE, HDF5 will use global mutex"
57 static void lock() { mutex::global::lock(); }
58 static void unlock() { mutex::global::unlock(); }
62#define MPQC_FILE_THREADSAFE mpqc::detail::File::threadsafe _threadsafe
69 typedef typename boost::remove_const<T>::type U;
70 if (boost::is_same<U,int>::value)
return H5T_NATIVE_INT;
71 if (boost::is_same<U,double>::value)
return H5T_NATIVE_DOUBLE;
72 throw std::runtime_error(
"no mapping to HDF5 type");
78 props_ = H5Pcreate(props);
110 Object(
const Object &parent, hid_t
id,
void (*close)(hid_t),
bool increment) {
112 parent_.reset(
new Object(parent));
113 update(
id, close, increment);
119 MPQC_FILE_THREADSAFE;
123 void operator=(
const Object &o) {
124 Object *parent = o.parent_.get();
125 parent_.reset(parent ?
new Object(*parent) : NULL);
126 update(o.id_, o.close_,
true);
133 const Object& parent()
const {
138 MPQC_FILE_THREADSAFE;
139 return H5Iget_file_id(id_);
142 static std::string filename(hid_t
id) {
143 MPQC_FILE_THREADSAFE;
144 std::vector<char> str(H5Fget_name(
id, NULL, 0) + 1);
145 MPQC_FILE_VERIFY(H5Fget_name(
id, &str[0], str.size()));
146 return std::string(&str[0]);
149 operator bool()
const {
155 std::auto_ptr<Object> parent_;
157 void (*close_)(hid_t);
160 void update(hid_t
id, F close,
bool increment) {
161 if (
id && increment) {
162 MPQC_FILE_THREADSAFE;
163 MPQC_FILE_VERIFY(H5Iinc_ref(
id));
173 template<
class Container>
175 static Container data;
178 template<
class Container>
217 this->fapl_ = H5Pcreate(H5P_FILE_ACCESS);
218 MPQC_FILE_VERIFY(this->fapl_);
231 struct DirectDriver :
Driver {
234 MPQC_FILE_VERIFY(H5Pset_fapl_direct(Driver::fapl_, 1024, 4096, 8*4096));
253 initialize(name, driver);
261 Group
group(
const std::string &name =
"/");
269 void initialize(
const std::string &name,
const Driver &driver) {
270 Object o = File::open(name, driver);
272 o = File::create(name, driver);
274 Object::operator=(o);
280 static void close(hid_t
id) {
282 MPQC_FILE_VERIFY((count = H5Iget_ref(
id)));
283 MPQC_FILE_VERIFY(result = H5Fclose(
id));
285 files_::data.erase(
id);
289 explicit File(hid_t
id,
bool increment) :
290 Object(Object(), id, &
File::close, increment)
292 MPQC_FILE_VERIFY(
id);
299 static std::string realpath(
const std::string &name) {
300 char *str = ::realpath(name.c_str(), NULL);
302 std::string path(str ? str : name);
314 static File open(
const std::string &name,
const Driver &driver) {
315 if (name.empty())
return File();
316 std::string path = realpath(name);
318 BOOST_FOREACH (
auto id, files_::data) {
319 if (path == realpath(Object::filename(
id)))
320 return File(
id,
true);
322 hid_t fapl = driver.fapl();
323 hid_t
id = H5Fcreate(name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
324 MPQC_FILE_VERIFY(
id);
325 files_::data.insert(
id);
326 return File(
id,
false);
336 static File create(
const std::string &name,
const Driver &driver) {
337 hid_t fapl = driver.fapl();
338 hid_t
id = H5Fcreate(name.c_str(), H5F_ACC_EXCL, H5P_DEFAULT, fapl);
339 MPQC_FILE_VERIFY(
id);
340 files_::data.insert(
id);
341 return File(
id,
false);
350 template<
typename T_>
353 typedef typename boost::remove_const<T_>::type T;
367 std::vector<range> r = range_;
368 r[ndims_ - 1] =
range(i, i + 1);
369 return Dataspace(parent_, base_, r, ndims_ - 1);
385 template<
class R, ...>
390 return this->
operator()(std::vector<range>(t));
402 apply(&H5Dwrite, this->parent_.id(), rebase(range_), (T*) buffer);
414 apply(&H5Dread, this->parent_.id(), rebase(range_), buffer);
422 size_t ndims_, size_;
423 std::vector<size_t> base_;
424 std::vector<mpqc::range> range_;
428 const std::vector<mpqc::range> &r,
size_t ndims) :
434 MPQC_ASSERT(ndims <= range_.size());
435 size_ = (r.size() ? 1 : 0);
436 for (
int i = 0; i < range_.size(); ++i) {
437 size_ *= range_[i].size();
443 std::vector<range> extend(
const std::vector<range> &r)
const {
445 MPQC_ASSERT(r.size() == ndims_);
446 std::vector<range> x = r;
447 for (
size_t i = ndims_; i < range_.size(); ++i) {
448 x.push_back(range_[i]);
454 std::vector<range> rebase(
const std::vector<range> &r)
const {
455 MPQC_ASSERT(r.size() == base_.size());
456 std::vector<range> v;
457 for (
int i = 0; i < base_.size(); ++i) {
458 auto begin = *r[i].begin() - base_[i];
459 v.push_back(range(begin, begin + r[i].
size()));
466 static void apply(F f, hid_t dset,
const std::vector<range> &r, T *buffer) {
467 MPQC_FILE_THREADSAFE;
468 hid_t fspace = H5Dget_space(dset);
469 size_t size = select(fspace, r);
470 hsize_t mdims[] = {
size };
471 hid_t mspace = H5Screate_simple(1, mdims, NULL);
472 MPQC_FILE_VERIFY(mspace);
473 MPQC_FILE_VERIFY(H5Sselect_all(mspace));
476 MPQC_FILE_VERIFY(f(dset, type, mspace, fspace, H5P_DEFAULT, buffer));
477 MPQC_FILE_VERIFY(H5Sclose(mspace));
478 MPQC_FILE_VERIFY(H5Sclose(fspace));
482 static size_t select(hid_t space,
const std::vector<range> &r) {
483 size_t N = H5Sget_simple_extent_ndims(space);
492 for (
size_t i = 0, j = N - 1; i < N; ++i, --j) {
493 fstart[i] = *r[j].begin();
494 fcount[i] = r[j].size();
505 (space, H5S_SELECT_SET, fstart, fstride, fcount, fblock));
526 template<
typename Extents>
527 Dataset(
const Object &parent,
const std::string &name,
const Extents &extents,
531 MPQC_ASSERT(
id() > 0);
532 BOOST_FOREACH (
auto e, extents) {
535 base_.push_back(*r.begin());
536 dims_.push_back(r.size());
545 std::vector<range> extents()
const {
546 std::vector<range> r;
547 for (
size_t i = 0; i < this->rank(); ++i) {
548 r.push_back(
range(base_[i], base_[i]+dims_[i]));
559 this->operator()(this->extents()).write(buffer);
568 this->operator()(this->extents()).read(buffer);
573 std::vector<range> r;
574 for (
int i = 0; i < this->rank(); ++i) {
575 r.push_back(
range(base_[i], base_[i] + dims_[i]));
583 MPQC_ASSERT(this->rank() == r.size());
589 MPQC_ASSERT(this->rank() == r.size());
601 template<
class R, ...>
606 return this->operator()(std::vector<range>(t));
610 return this->operator()(std::vector<range>(t));
616 template<
typename Extents>
617 static Object create(
const Object &parent,
618 const std::string &name,
619 const Extents &extents,
620 const Properties &dcpl) {
626 MPQC_FILE_THREADSAFE;
627 std::vector<hsize_t> dims;
628 BOOST_FOREACH (
auto e, extents) {
629 dims.push_back(extent(e).size());
632 std::reverse(dims.begin(), dims.end());
634 hid_t fspace = H5Screate_simple(dims.size(), &dims[0], NULL);
637#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
638 id = H5Dcreate(parent.id(), name.c_str(), type, fspace, dcpl.id());
640 id = H5Dcreate1(parent.id(), name.c_str(), type, fspace, dcpl.id());
642 MPQC_FILE_VERIFY(
id);
644 return Object(parent,
id, &Dataset::close,
false);
659 template <
typename E>
666 std::vector<size_t> base_;
667 std::vector<size_t> dims_;
672 static void close(hid_t
id) {
674 MPQC_FILE_VERIFY(H5Dclose(
id));
691#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
692 hid_t
id = H5Gopen(parent.id(), name.c_str());
694 hid_t
id = H5Gopen1(parent.id(), name.c_str());
696 return Group(
Object(parent,
id, &Group::close,
false));
705 template<
typename T,
typename Dims>
715 static void close(hid_t
id) {
717 MPQC_FILE_VERIFY(H5Gclose(
id));
720 Group(Object o) : Object(o) {}
734 template<
typename T,
class A>
746 template<
typename T,
class A>
758 template<
typename T,
class A>
770 template<
typename T,
class A>
Group group(const std::string &name="/")
Creates or opens a file group.
Definition file.hpp:723
void operator<<(Array< T > A, const V &v)
Write to Array from a generic vector V.
Definition array.hpp:191
void operator>>(Array< T > A, V &v)
Read from Array to a generic vector V.
Definition array.hpp:204
#define MPQC_RANGE_OPERATORS(N, Type, Function)
Generates operators()(const R1 r1, ...) of arity 1 to N.
Definition operator.hpp:41
#define MPQC_RANGE_CONST_OPERATORS(N, Type, Function)
Generates const version of MPQC_RANGE_OPERATORS.
Definition operator.hpp:45
hid_t h5t()
Translate C type into corresponding HDF5 type.
Definition file.hpp:68
Contains new MPQC code since version 3.
Definition integralenginepool.hpp:37
Array-like collection of data.
Definition file.hpp:515
Dataspace< T > operator()(const R &r,...)
N-ary sub-dataspace access operators.
size_t rank() const
Dataspace rank (number of dimensions)
Definition file.hpp:541
void read(T *buffer) const
Reads contiguous buffer from dataset.
Definition file.hpp:567
Dataspace< T > operator()(const std::vector< range > &r)
Access dataspace of same rank.
Definition file.hpp:581
Dataset(const Object &parent, const std::string &name, const Extents &extents, const File::Properties &dcpl=File::Properties(H5P_DATASET_CREATE))
Create dataset belonging to some file object.
Definition file.hpp:527
Dataspace< const T > operator()(const std::vector< range > &r) const
Access dataspace of same rank.
Definition file.hpp:588
Dataspace< T > operator[](size_t index)
Access dataspace of rank-1.
Definition file.hpp:572
void write(const T *buffer)
Writes contiguous buffer into dataset.
Definition file.hpp:558
static range extent(const range &r)
Return range as is.
Definition file.hpp:654
static range extent(const E &e)
Return integral argument e as range(0,e)
Definition file.hpp:660
A subset of File::Dataset.
Definition file.hpp:351
void read(T *buffer) const
Reads contiguous buffer from dataset.
Definition file.hpp:412
Dataspace< T > operator()(const std::vector< range > &r)
Access sub-dataspace of the same rank.
Definition file.hpp:373
size_t size() const
Number of elements in the set.
Definition file.hpp:356
Dataspace< T > operator()(const R &r,...)
N-ary sub-dataspace access operators.
const std::vector< range > & extents() const
The extents of the set in terms of ranges.
Definition file.hpp:361
void write(const T *buffer)
Writes contiguous buffer into dataset.
Definition file.hpp:400
Dataspace< T > operator[](size_t i)
Access sub-dataspace of rank-1.
Definition file.hpp:366
Base file driver.
Definition file.hpp:211
Directory-like container that holds datasets and other groups.
Definition file.hpp:682
static Group create(Object parent, const std::string &name)
Create a group.
Definition file.hpp:690
Dataset< T > dataset(const std::string &name, const Dims &dims)
Create or open Dataset.
Definition file.hpp:706
POSIX I/O file driver, the default.
Definition file.hpp:224
Top-level file object that holds groups.
Definition file.hpp:196
File(const std::string &name, const Driver &driver=POSIXDriver())
Create or open File.
Definition file.hpp:252
File()
Constructs a null file object.
Definition file.hpp:241
A reference-counted HDF5 handle object, superclass for eg File, Dataset, Attribute,...
Definition file.hpp:94
Object(const Object &parent, hid_t id, void(*close)(hid_t), bool increment)
Definition file.hpp:110
Object(const Object &o)
Copy constructor.
Definition file.hpp:100
Object()
Default constructor with an invalid handle.
Definition file.hpp:97
HDF5 may not be threadsafe, in that case mpqc::mutex::global is used.
Definition file.hpp:48
boost::tuple tie wrapper
Definition tie.hpp:15