3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-25 05:43:40 +01:00

Cleaning h5 interface

This commit is contained in:
Olivier Parcollet 2014-05-04 15:30:32 +02:00
parent 3a31077d51
commit e32602180c
18 changed files with 1029 additions and 613 deletions

View File

@ -18,7 +18,6 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_ARRAYS_H5_H #pragma once
#define TRIQS_ARRAYS_H5_H
#include "./h5/simple_read_write.hpp" #include "./h5/simple_read_write.hpp"
#endif #include "./h5/array_of_non_basic.hpp"

View File

@ -0,0 +1,111 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011-2013 by O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#pragma once
#include <triqs/arrays/array.hpp>
#include <triqs/arrays/vector.hpp>
#include <triqs/h5.hpp>
#include "../cache.hpp"
namespace triqs {
namespace arrays {
// details for generic save/read of arrays.
namespace h5_impl {
inline std::string _h5_name() { return ""; }
template <typename T0, typename... Ts> std::string _h5_name(T0 const& t0, Ts const&... ts) {
auto r = std::to_string(t0);
auto r1 = _h5_name(ts...);
if (r1 != "") r += "_" + r1;
return r;
}
#ifndef __cpp_generic_lambdas
template <typename ArrayType> struct _save_lambda {
ArrayType const& a;
h5::group g;
template <typename... Is> void operator()(Is const&... is) const { h5_write(g, _h5_name(is...), a(is...)); }
};
template <typename ArrayType> struct _load_lambda {
ArrayType& a;
h5::group g;
template <typename... Is> void operator()(Is const&... is) { h5_read(g, _h5_name(is...), a(is...)); }
};
#endif
} // details
/*
* Write an array or a view into an hdf5 file when type is not fundamental
* ArrayType The type of the array/matrix/vector, etc..
* g The h5 group
* name The name of the hdf5 array in the file/group where the stack will be stored
* A The array to be stored
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
*/
template <typename ArrayType>
std::c14::enable_if_t<is_amv_value_or_view_class<ArrayType>::value && !has_scalar_or_string_value_type<ArrayType>::value>
h5_write(h5::group gr, std::string name, ArrayType const& a) {
if (a.is_empty()) TRIQS_RUNTIME_ERROR << " Can not save an empty array into hdf5";
auto gr2 = gr.create_group(name);
gr2.write_triqs_hdf5_data_scheme(a);
// save the shape
array<int, 1> sha(ArrayType::rank);
for (int u = 0; u < ArrayType::rank; ++u) sha(u) = a.shape()[u];
h5_write(gr2, "shape", sha);
#ifndef __cpp_generic_lambdas
foreach(a, h5_impl::_save_lambda<ArrayType>{a, gr2});
#else
foreach(a, [&](auto... is) { h5_write(gr2, h5_impl::_h5_name(is...), a(is...)); });
#endif
}
/*
* Read an array or a view from an hdf5 file when type is not fundamental
* ArrayType The type of the array/matrix/vector, etc..
* g The h5 group
* name The name of the hdf5 array in the file/group where the stack will be stored
* A The array to be stored
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
*/
template <typename ArrayType>
std::c14::enable_if_t<is_amv_value_or_view_class<ArrayType>::value && !has_scalar_or_string_value_type<ArrayType>::value>
h5_read(h5::group gr, std::string name, ArrayType& a) {
static_assert(!std::is_const<ArrayType>::value, "Can not read in const object");
auto gr2 = gr.open_group(name);
// TODO checking scheme...
// load the shape
auto sha2 = a.shape();
array<int, 1> sha;
h5_read(gr2, "shape", sha);
if (first_dim(sha) != sha2.size())
TRIQS_RUNTIME_ERROR << " array<array<...>> load : rank mismatch. Expected " << sha2.size()<< " Got " << first_dim(sha);
for (int u = 0; u < sha2.size(); ++u) sha2[u] = sha(u);
if (a.shape() != sha2) a.resize(sha2);
#ifndef __cpp_generic_lambdas
foreach(a, h5_impl::_load_lambda<ArrayType>{a, gr2});
#else
foreach(a, [&](auto... is) { h5_read(gr2, h5_impl::_h5_name(is...), a(is...)); });
#endif
}
}
}

View File

@ -27,6 +27,18 @@
namespace triqs { namespace triqs {
namespace arrays { namespace arrays {
// to be cleaned
namespace h5_impl {
template <typename A> void* __get_array_data_ptr(A& x) { return h5::get_data_ptr(&(x.storage()[0])); }
H5::DataSpace data_space_impl(array_stride_info info, bool is_complex);
template <typename ArrayType> H5::DataSpace data_space(ArrayType const& A) {
if (!A.indexmap().is_contiguous()) TRIQS_RUNTIME_ERROR << " h5 : internal error : array not contiguous";
return data_space_impl(array_stride_info{A}, triqs::is_complex<typename ArrayType::value_type>::value);
}
}
/// The implementation class /// The implementation class
template <typename T, int R> class array_stack_impl { template <typename T, int R> class array_stack_impl {
static const size_t dim = R; static const size_t dim = R;

View File

@ -0,0 +1,150 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011-2014 by O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#include "./simple_read_write.hpp"
using dcomplex = std::complex<double>;
namespace triqs {
namespace arrays {
namespace h5_impl {
// the dataspace corresponding to the array. Contiguous data only...
H5::DataSpace data_space_impl(array_stride_info info, bool is_complex) {
hsize_t L[info.R], S[info.R];
for (int u = 0; u < info.R; ++u) {
if (info.strides[u] <= 0) TRIQS_RUNTIME_ERROR << " negative strides not permitted in h5";
S[u] = 1;
L[u] = info.lengths[u];
}
return h5::dataspace_from_LS(info.R, is_complex, L, L, S);
}
/// --------------------------- WRITE ---------------------------------------------
template <typename T> void write_array_impl(h5::group g, std::string const& name, const T* start, array_stride_info info) {
static_assert(!std::is_base_of<std::string, T>::value, " Not implemented"); // 1d is below
bool is_complex = triqs::is_complex<T>::value;
try {
H5::DataSet ds = g.create_dataset(name, h5::data_type_file<T>(), data_space_impl(info, is_complex));
ds.write(h5::get_data_ptr(start), h5::data_type_memory<T>(), data_space_impl(info, is_complex));
// if complex, to be python compatible, we add the __complex__ attribute
if (is_complex) h5::write_string_attribute(&ds, "__complex__", "1");
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
template void write_array_impl<int>(h5::group g, std::string const& name, const int* start, array_stride_info info);
template void write_array_impl<long>(h5::group g, std::string const& name, const long* start, array_stride_info info);
template void write_array_impl<double>(h5::group g, std::string const& name, const double* start, array_stride_info info);
template void write_array_impl<dcomplex>(h5::group g, std::string const& name, const dcomplex* start, array_stride_info info);
// overload : special treatment for arrays of strings (one dimension only).
void write_array(h5::group g, std::string const& name, vector_const_view<std::string> V) {
std::vector<std::string> tmp(V.size());
std::copy(begin(V), end(V), begin(tmp));
h5_write(g, name, tmp);
}
void write_array(h5::group g, std::string const& name, array_const_view<std::string, 1> V) {
std::vector<std::string> tmp(first_dim(V));
std::copy(begin(V), end(V), begin(tmp));
h5_write(g, name, tmp);
}
/// --------------------------- READ ---------------------------------------------
/* template <typename ArrayType1> void read_array(h5::group g, std::string const& name, ArrayType1&& A, bool C_reorder = true) {
typedef typename std::remove_reference<ArrayType1>::type ArrayType;
static_assert(!std::is_base_of<std::string, typename ArrayType::value_type>::value, " Not implemented"); // 1d is below
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
static const unsigned int Rank = ArrayType::rank + (triqs::is_complex<typename ArrayType::value_type>::value ? 1 : 0);
int rank = dataspace.getSimpleExtentNdims();
if (rank != Rank)
TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : the array has rank = " << Rank
<< " while the array stored in the hdf5 file has rank = " << rank;
mini_vector<hsize_t, Rank> dims_out;
dataspace.getSimpleExtentDims(&dims_out[0], NULL);
mini_vector<size_t, ArrayType::rank> d2;
for (size_t u = 0; u < ArrayType::rank; ++u) d2[u] = dims_out[u];
resize_or_check(A, d2);
if (C_reorder) {
read_array(g, name, make_cache(A).view(), false);
//read_array(g, name, cache<ArrayType, typename ArrayType::regular_type>(A).view(), false);
} else
ds.read(__get_array_data_ptr(A), h5::data_type_memory<typename ArrayType::value_type>(), data_space(A), dataspace);
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
*/
std::vector<size_t> get_array_lengths(int R, h5::group g, std::string const& name, bool is_complex) {
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
int Rank = R + (is_complex ? 1 : 0);
int rank = dataspace.getSimpleExtentNdims();
if (rank != Rank)
TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : the array has rank = " << Rank
<< " while the array stored in the hdf5 file has rank = " << rank;
std::vector<size_t> d2(R);
hsize_t dims_out[rank];
dataspace.getSimpleExtentDims(&dims_out[0], NULL);
for (size_t u = 0; u < R; ++u) d2[u] = dims_out[u];
return d2;
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
template <typename T> void read_array_impl(h5::group g, std::string const& name, T* start, array_stride_info info) {
static_assert(!std::is_base_of<std::string, T>::value, " Not implemented"); // 1d is below
bool is_complex = triqs::is_complex<T>::value;
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
ds.read(h5::get_data_ptr(start), h5::data_type_memory<T>(), data_space_impl(info, is_complex), dataspace);
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
template void read_array_impl<int>(h5::group g, std::string const& name, int* start, array_stride_info info);
template void read_array_impl<long>(h5::group g, std::string const& name, long* start, array_stride_info info);
template void read_array_impl<double>(h5::group g, std::string const& name, double* start, array_stride_info info);
template void read_array_impl<dcomplex>(h5::group g, std::string const& name, dcomplex* start, array_stride_info info);
void read_array(h5::group g, std::string const& name, arrays::vector<std::string>& V) {
std::vector<std::string> tmp;
h5_read(g, name, tmp);
V.resize(tmp.size());
std::copy(begin(tmp), end(tmp), begin(V));
}
// I can not use the generic code, just because the resize of the array take a shape, not a size_t as std::vector and vector
void read_array(h5::group f, std::string const& name, arrays::array<std::string, 1>& V) {
arrays::vector<std::string> res;
read_array(f, name, res);
V = res;
}
}
}
}

View File

@ -18,8 +18,7 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_ARRAYS_H5_LOWLEVEL_H #pragma once
#define TRIQS_ARRAYS_H5_LOWLEVEL_H
#include <triqs/arrays/array.hpp> #include <triqs/arrays/array.hpp>
#include <triqs/arrays/vector.hpp> #include <triqs/arrays/vector.hpp>
#include <triqs/h5.hpp> #include <triqs/h5.hpp>
@ -29,24 +28,18 @@ namespace triqs {
namespace arrays { namespace arrays {
namespace h5_impl { namespace h5_impl {
template <typename A> const void* __get_array_data_cptr(A const& a) { return h5::get_data_ptr(&(a.storage()[0])); } struct array_stride_info {
template <typename A> void* __get_array_data_ptr(A& x) { return h5::get_data_ptr(&(x.storage()[0])); } int R;
size_t const* lengths;
// the dataspace corresponding to the array. Contiguous data only... long const* strides;
template <typename ArrayType> H5::DataSpace data_space(ArrayType const& A) { template<typename A> explicit array_stride_info(A && a) {
if (!A.indexmap().is_contiguous()) TRIQS_RUNTIME_ERROR << " h5 : internal error : array not contiguous"; R = std::c14::decay_t<A>::rank;
static const unsigned int R = ArrayType::rank; lengths = a.indexmap().domain().lengths().ptr();
mini_vector<hsize_t, R> S; strides = a.indexmap().strides().ptr();
auto const& S1(A.indexmap().strides());
for (int u = 0; u < R; ++u) {
if (S1[u] <= 0) TRIQS_RUNTIME_ERROR << " negative strides not permitted in h5";
S[u] = 1;
} }
static const bool is_complex = triqs::is_complex<typename ArrayType::value_type>::value; };
return h5::dataspace_from_LS<R, is_complex>(A.indexmap().domain().lengths(), A.indexmap().domain().lengths(), S);
}
/******************** resize or check the size ****************************************************/ /******************** resize or check the size ****************************************************/
template <typename A> ENABLE_IF(is_amv_value_class<A>) resize_or_check(A& a, mini_vector<size_t, A::rank> const& dimsf) { template <typename A> ENABLE_IF(is_amv_value_class<A>) resize_or_check(A& a, mini_vector<size_t, A::rank> const& dimsf) {
a.resize(indexmaps::cuboid::domain_t<A::rank>(dimsf)); a.resize(indexmaps::cuboid::domain_t<A::rank>(dimsf));
@ -60,92 +53,44 @@ namespace arrays {
} }
/*********************************** WRITE array ****************************************************************/ /*********************************** WRITE array ****************************************************************/
/*
* Write an array or a view into an hdf5 file template <typename T> void write_array_impl(h5::group g, std::string const& name, const T* start, array_stride_info info);
*
* f The h5 file or group of type H5::H5File or H5::Group
* name The name of the hdf5 array in the file/group where the stack will be stored
* A The array to be stored
* C_reorder bool If true [default] the data will be stored in C order in the hdf5, hence making a temporary
* cache of the data to reorder them in memory.
* If false, the array is stored as it [if you know what you are doing]
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
*/
template <typename T, int R>
void write_array_impl(h5::group g, std::string const& name, array_const_view<T, R> A, bool C_reorder) {
static_assert(!std::is_base_of<std::string, T>::value, " Not implemented"); // 1d is below
if (C_reorder) {
write_array_impl(g, name, make_const_cache(A).view(), false);
return;
}
try {
H5::DataSet ds = g.create_dataset(name, h5::data_type_file<T>(), data_space(A));
ds.write(__get_array_data_cptr(A), h5::data_type_memory<T>(), data_space(A));
// if complex, to be python compatible, we add the __complex__ attribute
if (triqs::is_complex<T>::value) h5::write_string_attribute(&ds, "__complex__", "1");
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
template <typename A> void write_array(h5::group g, std::string const& name, A const& a, bool C_reorder = true) { template <typename A> void write_array(h5::group g, std::string const& name, A const& a, bool C_reorder = true) {
write_array_impl(g, name, typename A::const_view_type{a}, C_reorder); if (C_reorder) {
} auto b = make_const_cache(a).view();
write_array_impl(g, name, b.data_start(), array_stride_info{b});
/*********************************** READ array ****************************************************************/ } else
/* write_array_impl(g, name, a.data_start(), array_stride_info{a});
* Read an array or a view from an hdf5 file
* ArrayType The type of the array/matrix/vector, etc..
* f The h5 file or group of type H5::H5File or H5::Group
* name The name of the hdf5 array in the file/group where the stack will be stored
* A The array to be stored
* C_reorder bool If true [default] the data will be stored in C order in the hdf5, hence making a temporary
* cache of the data to reorder them in memory. If false, the array is stored as it [if you know what you are doing]
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
*/
template <typename ArrayType1> void read_array(h5::group g, std::string const& name, ArrayType1&& A, bool C_reorder = true) {
typedef typename std::remove_reference<ArrayType1>::type ArrayType;
static_assert(!std::is_base_of<std::string, typename ArrayType::value_type>::value, " Not implemented"); // 1d is below
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
static const unsigned int Rank = ArrayType::rank + (triqs::is_complex<typename ArrayType::value_type>::value ? 1 : 0);
int rank = dataspace.getSimpleExtentNdims();
if (rank != Rank)
TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : the array has rank = " << Rank
<< " while the array stored in the hdf5 file has rank = " << rank;
mini_vector<hsize_t, Rank> dims_out;
dataspace.getSimpleExtentDims(&dims_out[0], NULL);
mini_vector<size_t, ArrayType::rank> d2;
for (size_t u = 0; u < ArrayType::rank; ++u) d2[u] = dims_out[u];
resize_or_check(A, d2);
if (C_reorder) {
read_array(g, name, make_cache(A).view(), false);
//read_array(g, name, cache<ArrayType, typename ArrayType::regular_type>(A).view(), false);
} else
ds.read(__get_array_data_ptr(A), h5::data_type_memory<typename ArrayType::value_type>(), data_space(A), dataspace);
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
} }
// overload : special treatment for arrays of strings (one dimension only). // overload : special treatment for arrays of strings (one dimension only).
inline void write_array(h5::group f, std::string const& name, vector_const_view<std::string> V) { void write_array(h5::group g, std::string const& name, vector_const_view<std::string> V);
h5::detail::write_1darray_vector_of_string_impl(f, name, V); void write_array(h5::group g, std::string const& name, array_const_view<std::string, 1> V);
/*********************************** READ array ****************************************************************/
std::vector<size_t> get_array_lengths(int R, h5::group g, std::string const& name, bool is_complex);
template <typename T> void read_array_impl(h5::group g, std::string const& name, T* start, array_stride_info info);
template <typename A> void read_array(h5::group g, std::string const& name, A&& a, bool C_reorder = true) {
resize_or_check(a, get_array_lengths(a.rank, g, name, triqs::is_complex<typename std::c14::decay_t<A>::value_type>::value));
if (C_reorder) {
{
// read_array(g, name, make_cache(a).view(), false);
// return ;
auto b = make_cache(a);
// auto b = make_cache(a).view();
read_array_impl(g, name, b.view().data_start(), array_stride_info{b.view()});
// read_array_impl(g, name, b.data_start(), array_stride_info{b});
}
} else
read_array_impl(g, name, a.data_start(), array_stride_info{a});
} }
inline void write_array(h5::group f, std::string const& name, array_const_view<std::string, 1> V) { // overload : special treatment for arrays of strings (one dimension only).
write_array(f, name, vector_const_view<std::string>(V)); void read_array(h5::group g, std::string const& name, arrays::vector<std::string>& V);
} void read_array(h5::group f, std::string const& name, arrays::array<std::string, 1>& V);
inline void read_array(h5::group f, std::string const& name, arrays::vector<std::string>& V) {
h5::detail::read_1darray_vector_of_string_impl(f, name, V);
}
// I can not use the generic code, just because the resize of the array take a shape, not a size_t as std::vector and vector
inline void read_array(h5::group f, std::string const& name, arrays::array<std::string, 1>& V) {
arrays::vector<std::string> res;
read_array(f, name, res);
V = res;
}
} // namespace h5_impl } // namespace h5_impl
@ -162,9 +107,7 @@ namespace arrays {
template <typename ArrayType> template <typename ArrayType>
TYPE_ENABLE_IFC(std::string, is_amv_value_or_view_class<ArrayType>::value) get_triqs_hdf5_data_scheme(ArrayType const&) { TYPE_ENABLE_IFC(std::string, is_amv_value_or_view_class<ArrayType>::value) get_triqs_hdf5_data_scheme(ArrayType const&) {
using triqs::get_triqs_hdf5_data_scheme; // for the basic types, not found by ADL using triqs::get_triqs_hdf5_data_scheme; // for the basic types, not found by ADL
std::stringstream fs; return "array<" + get_triqs_hdf5_data_scheme(typename ArrayType::value_type()) + "," + std::to_string(ArrayType::rank) + ">";
fs << "array<" << get_triqs_hdf5_data_scheme(typename ArrayType::value_type()) << "," << ArrayType::rank << ">";
return fs.str();
} }
/* /*
@ -196,86 +139,5 @@ namespace arrays {
h5_impl::write_array(g, name, array_const_view<typename ArrayType::value_type, ArrayType::rank>(A)); h5_impl::write_array(g, name, array_const_view<typename ArrayType::value_type, ArrayType::rank>(A));
} }
// details for generic save/read of arrays. }}
namespace h5_impl {
inline std::string _h5_name() { return ""; }
template <typename T0, typename... Ts> std::string _h5_name(T0 const& t0, Ts const&... ts) {
auto r = std::to_string(t0);
auto r1 = _h5_name(ts...);
if (r1 != "") r += "_" + r1;
return r;
}
#ifndef __cpp_generic_lambdas
template <typename ArrayType> struct _save_lambda {
ArrayType const& a;
h5::group g;
template <typename... Is> void operator()(Is const&... is) const { h5_write(g, _h5_name(is...), a(is...)); }
};
template <typename ArrayType> struct _load_lambda {
ArrayType& a;
h5::group g;
template <typename... Is> void operator()(Is const&... is) { h5_read(g, _h5_name(is...), a(is...)); }
};
#endif
} // details
/*
* Write an array or a view into an hdf5 file when type is not fundamental
* ArrayType The type of the array/matrix/vector, etc..
* g The h5 group
* name The name of the hdf5 array in the file/group where the stack will be stored
* A The array to be stored
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
*/
template <typename ArrayType>
std::c14::enable_if_t<is_amv_value_or_view_class<ArrayType>::value && !has_scalar_or_string_value_type<ArrayType>::value>
h5_write(h5::group gr, std::string name, ArrayType const& a) {
if (a.is_empty()) TRIQS_RUNTIME_ERROR << " Can not save an empty array into hdf5";
auto gr2 = gr.create_group(name);
gr2.write_triqs_hdf5_data_scheme(a);
// save the shape
array<int, 1> sha(ArrayType::rank);
for (int u = 0; u < ArrayType::rank; ++u) sha(u) = a.shape()[u];
h5_write(gr2, "shape", sha);
#ifndef __cpp_generic_lambdas
foreach(a, h5_impl::_save_lambda<ArrayType>{a, gr2});
#else
foreach(a, [&](auto... is) { h5_write(gr2, h5_impl::_h5_name(is...), a(is...)); });
#endif
}
/*
* Read an array or a view from an hdf5 file when type is not fundamental
* ArrayType The type of the array/matrix/vector, etc..
* g The h5 group
* name The name of the hdf5 array in the file/group where the stack will be stored
* A The array to be stored
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
*/
template <typename ArrayType>
std::c14::enable_if_t<is_amv_value_or_view_class<ArrayType>::value && !has_scalar_or_string_value_type<ArrayType>::value>
h5_read(h5::group gr, std::string name, ArrayType& a) {
static_assert(!std::is_const<ArrayType>::value, "Can not read in const object");
auto gr2 = gr.open_group(name);
// TODO checking scheme...
// load the shape
auto sha2 = a.shape();
array<int, 1> sha;
h5_read(gr2, "shape", sha);
if (first_dim(sha) != sha2.size())
TRIQS_RUNTIME_ERROR << " array<array<...>> load : rank mismatch. Expected " << sha2.size()<< " Got " << first_dim(sha);
for (int u = 0; u < sha2.size(); ++u) sha2[u] = sha(u);
if (a.shape() != sha2) a.resize(sha2);
#ifndef __cpp_generic_lambdas
foreach(a, h5_impl::_load_lambda<ArrayType>{a, gr2});
#else
foreach(a, [&](auto... is) { h5_read(gr2, h5_impl::_h5_name(is...), a(is...)); });
#endif
}
}
}
#endif

View File

@ -0,0 +1,122 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011 by O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#include "../impl/common.hpp"
#include "../impl/traits.hpp"
#include "../impl/flags.hpp"
#include "../../utility/mini_vector.hpp"
#include "./numpy_extractor.hpp"
#ifdef TRIQS_WITH_PYTHON_SUPPORT
namespace triqs { namespace arrays { namespace numpy_interface {
PyObject * numpy_extractor_impl ( PyObject * X, bool allow_copy, std::string type_name,
int elementsType, int rank, size_t * lengths, std::ptrdiff_t * strides, size_t size_of_ValueType) {
PyObject * numpy_obj;
if (X==NULL) TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is NULL !";
if (_import_array()!=0) TRIQS_RUNTIME_ERROR <<"Internal Error in importing numpy";
static const char * error_msg = " A deep copy of the object would be necessary while views are supposed to guarantee to present a *view* of the python data.\n";
if (!allow_copy) {
if (!PyArray_Check(X)) throw copy_exception () << error_msg<<" Indeed the object was not even an array !\n";
if ( elementsType != PyArray_TYPE((PyArrayObject*)X))
throw copy_exception () << error_msg<<" The deep copy is caused by a type mismatch of the elements. Expected "<< type_name<< " and found XXX \n";
PyArrayObject *arr = (PyArrayObject *)X;
#ifdef TRIQS_NUMPY_VERSION_LT_17
if ( arr->nd != rank) throw copy_exception () << error_msg<<" Rank mismatch . numpy array is of rank "<< arr->nd << "while you ask for rank "<< rank<<". \n";
#else
if ( PyArray_NDIM(arr) != rank) throw copy_exception () << error_msg<<" Rank mismatch . numpy array is of rank "<< PyArray_NDIM(arr) << "while you ask for rank "<< rank<<". \n";
#endif
numpy_obj = X; Py_INCREF(X);
}
else {
// From X, we ask the numpy library to make a numpy, and of the correct type.
// This handles automatically the cases where :
// - we have list, or list of list/tuple
// - the numpy type is not the one we want.
// - adjust the dimension if needed
// If X is an array :
// - if Order is same, don't change it
// - else impose it (may provoque a copy).
// if X is not array :
// - Order = FortranOrder or SameOrder - > Fortran order otherwise C
//bool ForceCast = false;// Unless FORCECAST is present in flags, this call will generate an error if the data type cannot be safely obtained from the object.
int flags = 0; //(ForceCast ? NPY_FORCECAST : 0) ;// do NOT force a copy | (make_copy ? NPY_ENSURECOPY : 0);
if (!(PyArray_Check(X) ))
//flags |= ( IndexMapType::traversal_order == indexmaps::mem_layout::c_order(rank) ? NPY_C_CONTIGUOUS : NPY_F_CONTIGUOUS); //impose mem order
#ifdef TRIQS_NUMPY_VERSION_LT_17
flags |= (NPY_C_CONTIGUOUS); //impose mem order
#else
flags |= (NPY_ARRAY_C_CONTIGUOUS); //impose mem order
#endif
numpy_obj= PyArray_FromAny(X,PyArray_DescrFromType(elementsType), rank,rank, flags , NULL );
// do several checks
if (!numpy_obj) {// The convertion of X to a numpy has failed !
if (PyErr_Occurred()) {
//PyErr_Print();
PyErr_Clear();
}
TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is not convertible to a numpy. ";
}
assert (PyArray_Check(numpy_obj)); assert((numpy_obj->ob_refcnt==1) || ((numpy_obj ==X)));
PyArrayObject *arr_obj;
arr_obj = (PyArrayObject *)numpy_obj;
try {
#ifdef TRIQS_NUMPY_VERSION_LT_17
if (arr_obj->nd!=rank) TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : dimensions do not match";
if (arr_obj->descr->type_num != elementsType)
TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : incorrect type of element :" <<arr_obj->descr->type_num <<" vs "<<elementsType;
#else
if ( PyArray_NDIM(arr_obj) !=rank) TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : dimensions do not match";
if ( PyArray_DESCR(arr_obj)->type_num != elementsType)
TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : incorrect type of element :" <<PyArray_DESCR(arr_obj)->type_num <<" vs "<<elementsType;
#endif
}
catch(...) { Py_DECREF(numpy_obj); throw;} // make sure that in case of problem, the reference counting of python is still ok...
}
// extract strides and lengths
PyArrayObject *arr_obj;
arr_obj = (PyArrayObject *)numpy_obj;
#ifdef TRIQS_NUMPY_VERSION_LT_17
const size_t dim =arr_obj->nd; // we know that dim == rank
for (size_t i=0; i< dim ; ++i) {
lengths[i] = size_t(arr_obj-> dimensions[i]);
strides[i] = std::ptrdiff_t(arr_obj-> strides[i])/ size_of_ValueType;
}
#else
const size_t dim = PyArray_NDIM(arr_obj); // we know that dim == rank
for (size_t i=0; i< dim ; ++i) {
lengths[i] = size_t( PyArray_DIMS(arr_obj)[i]);
strides[i] = std::ptrdiff_t( PyArray_STRIDES(arr_obj)[i])/ size_of_ValueType;
}
#endif
return numpy_obj;
}
}}}
#endif

View File

@ -21,13 +21,15 @@
#ifndef TRIQS_ARRAYS_NUMPY_EXTRACTOR_H #ifndef TRIQS_ARRAYS_NUMPY_EXTRACTOR_H
#define TRIQS_ARRAYS_NUMPY_EXTRACTOR_H #define TRIQS_ARRAYS_NUMPY_EXTRACTOR_H
#ifdef TRIQS_WITH_PYTHON_SUPPORT
#include "../storages/shared_block.hpp" #include "../storages/shared_block.hpp"
#include "triqs/utility/exceptions.hpp" #include "triqs/utility/exceptions.hpp"
#ifdef TRIQS_WITH_PYTHON_SUPPORT
#include "numpy/arrayobject.h" #include "numpy/arrayobject.h"
namespace triqs { namespace arrays { namespace numpy_interface { namespace triqs { namespace arrays { namespace numpy_interface {
using utility::mini_vector;
inline std::string object_to_string (PyObject * p) { inline std::string object_to_string (PyObject * p) {
if (!PyString_Check(p)) TRIQS_RUNTIME_ERROR<<" Internal error, expected a python string ....."; if (!PyString_Check(p)) TRIQS_RUNTIME_ERROR<<" Internal error, expected a python string .....";
return PyString_AsString(p); return PyString_AsString(p);
@ -58,98 +60,9 @@ namespace triqs { namespace arrays { namespace numpy_interface {
struct copy_exception : public triqs::runtime_error {}; struct copy_exception : public triqs::runtime_error {};
// return a NEW (owned) reference // return a NEW (owned) reference
// PyObject * numpy_extractor_impl ( PyObject * X, bool allow_copy, std::string type_name,
inline PyObject * numpy_extractor_impl ( PyObject * X, bool allow_copy, std::string type_name, int elementsType, int rank, size_t * lengths, std::ptrdiff_t * strides, size_t size_of_ValueType);
int elementsType, int rank, size_t * lengths, std::ptrdiff_t * strides, size_t size_of_ValueType) {
PyObject * numpy_obj;
if (X==NULL) TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is NULL !";
if (_import_array()!=0) TRIQS_RUNTIME_ERROR <<"Internal Error in importing numpy";
static const char * error_msg = " A deep copy of the object would be necessary while views are supposed to guarantee to present a *view* of the python data.\n";
if (!allow_copy) {
if (!PyArray_Check(X)) throw copy_exception () << error_msg<<" Indeed the object was not even an array !\n";
if ( elementsType != PyArray_TYPE((PyArrayObject*)X))
throw copy_exception () << error_msg<<" The deep copy is caused by a type mismatch of the elements. Expected "<< type_name<< " and found XXX \n";
PyArrayObject *arr = (PyArrayObject *)X;
#ifdef TRIQS_NUMPY_VERSION_LT_17
if ( arr->nd != rank) throw copy_exception () << error_msg<<" Rank mismatch . numpy array is of rank "<< arr->nd << "while you ask for rank "<< rank<<". \n";
#else
if ( PyArray_NDIM(arr) != rank) throw copy_exception () << error_msg<<" Rank mismatch . numpy array is of rank "<< PyArray_NDIM(arr) << "while you ask for rank "<< rank<<". \n";
#endif
numpy_obj = X; Py_INCREF(X);
}
else {
// From X, we ask the numpy library to make a numpy, and of the correct type.
// This handles automatically the cases where :
// - we have list, or list of list/tuple
// - the numpy type is not the one we want.
// - adjust the dimension if needed
// If X is an array :
// - if Order is same, don't change it
// - else impose it (may provoque a copy).
// if X is not array :
// - Order = FortranOrder or SameOrder - > Fortran order otherwise C
//bool ForceCast = false;// Unless FORCECAST is present in flags, this call will generate an error if the data type cannot be safely obtained from the object.
int flags = 0; //(ForceCast ? NPY_FORCECAST : 0) ;// do NOT force a copy | (make_copy ? NPY_ENSURECOPY : 0);
if (!(PyArray_Check(X) ))
//flags |= ( IndexMapType::traversal_order == indexmaps::mem_layout::c_order(rank) ? NPY_C_CONTIGUOUS : NPY_F_CONTIGUOUS); //impose mem order
#ifdef TRIQS_NUMPY_VERSION_LT_17
flags |= (NPY_C_CONTIGUOUS); //impose mem order
#else
flags |= (NPY_ARRAY_C_CONTIGUOUS); //impose mem order
#endif
numpy_obj= PyArray_FromAny(X,PyArray_DescrFromType(elementsType), rank,rank, flags , NULL );
// do several checks
if (!numpy_obj) {// The convertion of X to a numpy has failed !
if (PyErr_Occurred()) {
//PyErr_Print();
PyErr_Clear();
}
TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is not convertible to a numpy. ";
}
assert (PyArray_Check(numpy_obj)); assert((numpy_obj->ob_refcnt==1) || ((numpy_obj ==X)));
PyArrayObject *arr_obj;
arr_obj = (PyArrayObject *)numpy_obj;
try {
#ifdef TRIQS_NUMPY_VERSION_LT_17
if (arr_obj->nd!=rank) TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : dimensions do not match";
if (arr_obj->descr->type_num != elementsType)
TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : incorrect type of element :" <<arr_obj->descr->type_num <<" vs "<<elementsType;
#else
if ( PyArray_NDIM(arr_obj) !=rank) TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : dimensions do not match";
if ( PyArray_DESCR(arr_obj)->type_num != elementsType)
TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : incorrect type of element :" <<PyArray_DESCR(arr_obj)->type_num <<" vs "<<elementsType;
#endif
}
catch(...) { Py_DECREF(numpy_obj); throw;} // make sure that in case of problem, the reference counting of python is still ok...
}
// extract strides and lengths
PyArrayObject *arr_obj;
arr_obj = (PyArrayObject *)numpy_obj;
#ifdef TRIQS_NUMPY_VERSION_LT_17
const size_t dim =arr_obj->nd; // we know that dim == rank
for (size_t i=0; i< dim ; ++i) {
lengths[i] = size_t(arr_obj-> dimensions[i]);
strides[i] = std::ptrdiff_t(arr_obj-> strides[i])/ size_of_ValueType;
}
#else
const size_t dim = PyArray_NDIM(arr_obj); // we know that dim == rank
for (size_t i=0; i< dim ; ++i) {
lengths[i] = size_t( PyArray_DIMS(arr_obj)[i]);
strides[i] = std::ptrdiff_t( PyArray_STRIDES(arr_obj)[i])/ size_of_ValueType;
}
#endif
return numpy_obj;
}
// a little template class // a little template class
template<typename IndexMapType, typename ValueType > struct numpy_extractor { template<typename IndexMapType, typename ValueType > struct numpy_extractor {

View File

@ -129,7 +129,7 @@ namespace gfs {
h5_write(gr, "max", ((Fermion ? 1 : 0) + 2 * m.size()) * M_PI / beta); h5_write(gr, "max", ((Fermion ? 1 : 0) + 2 * m.size()) * M_PI / beta);
h5_write(gr, "kind", 2); h5_write(gr, "kind", 2);
} else { // A strange way : to preserve backward compatibility for old archive. } else { // A strange way : to preserve backward compatibility for old archive.
h5_write(gr, "start_at_0", m._positive_only); h5_write(gr, "start_at_0", (m._positive_only?1:0));
} }
} }
@ -138,11 +138,11 @@ namespace gfs {
h5::group gr = fg.open_group(subgroup_name); h5::group gr = fg.open_group(subgroup_name);
typename matsubara_freq_mesh::domain_t dom; typename matsubara_freq_mesh::domain_t dom;
int L; int L;
bool s = true; int s = 1;
h5_read(gr, "domain", dom); h5_read(gr, "domain", dom);
h5_read(gr, "size", L); h5_read(gr, "size", L);
if (gr.has_key("start_at_0")) h5_read(gr, "start_at_0", s); if (gr.has_key("start_at_0")) h5_read(gr, "start_at_0", s);
m = matsubara_freq_mesh{std::move(dom), L, s}; m = matsubara_freq_mesh{std::move(dom), L, (s==1)};
} }
friend class boost::serialization::access; friend class boost::serialization::access;

96
triqs/h5/base.cpp Normal file
View File

@ -0,0 +1,96 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011-2014 by O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#include "./base.hpp"
#include <hdf5_hl.h>
namespace triqs {
namespace h5 {
// dataspace from lengths and strides. Correct for the complex. strides must be >0
H5::DataSpace dataspace_from_LS(int R, bool is_complex, hsize_t const *Ltot, hsize_t const *L, hsize_t const *S,
hsize_t const *offset) {
int rank = R + (is_complex ? 1 : 0);
hsize_t totdimsf[rank], dimsf[rank], stridesf[rank], offsetf[rank]; // dataset dimensions
for (size_t u = 0; u < R; ++u) {
offsetf[u] = (offset ? offset[u] : 0);
dimsf[u] = L[u];
totdimsf[u] = Ltot[u];
stridesf[u] = S[u];
}
if (is_complex) {
offsetf[rank - 1] = 0;
dimsf[rank - 1] = 2;
totdimsf[rank - 1] = 2;
stridesf[rank - 1] = 1;
}
H5::DataSpace ds(rank, totdimsf);
ds.selectHyperslab(H5S_SELECT_SET, dimsf, offsetf, stridesf);
return ds;
}
/****************** Write string attribute *********************************************/
void write_string_attribute(H5::H5Object const *obj, std::string name, std::string value) {
H5::DataSpace attr_dataspace = H5::DataSpace(H5S_SCALAR);
// Create new string datatype for attribute
H5::StrType strdatatype(H5::PredType::C_S1, value.size());
// Set up write buffer for attribute
// const H5std_string strwritebuf (value);
// Create attribute and write to it
H5::Attribute myatt_in = obj->createAttribute(name.c_str(), strdatatype, attr_dataspace);
// myatt_in.write(strdatatype, strwritebuf);
myatt_in.write(strdatatype, (void *)(value.c_str()));
}
/****************** Read string attribute *********************************************/
/// Return the attribute name of obj, and "" if the attribute does not exist.
std::string read_string_attribute(H5::H5Object const *obj, std::string name) {
std::string value = "";
H5::Attribute attr;
if (H5LTfind_attribute(obj->getId(), name.c_str()) == 0) return value; // not present
// can not find how to get the size with hl. Using full interface
// herr_t err2 = H5LTget_attribute_string(gr.getId(), x.c_str(), name.c_str() , &(buf.front()) ) ;
// value.append( &(buf.front()) );
try {
attr = obj->openAttribute(name.c_str());
}
catch (H5::AttributeIException) {
return value;
}
try {
H5::DataSpace dataspace = attr.getSpace();
int rank = dataspace.getSimpleExtentNdims();
if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string attribute and got rank !=0";
size_t size = attr.getStorageSize();
H5::StrType strdatatype(H5::PredType::C_S1, size + 1);
std::vector<char> buf(size + 1, 0x00);
attr.read(strdatatype, (void *)(&buf[0]));
value.append(&(buf.front()));
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
return value;
}
}
}

View File

@ -2,7 +2,7 @@
* *
* TRIQS: a Toolbox for Research in Interacting Quantum Systems * TRIQS: a Toolbox for Research in Interacting Quantum Systems
* *
* Copyright (C) 2011-2013 by O. Parcollet * Copyright (C) 2011-2014 by O. Parcollet
* *
* TRIQS is free software: you can redistribute it and/or modify it under the * TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software * terms of the GNU General Public License as published by the Free Software
@ -18,12 +18,10 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_H5_BASE_H #pragma once
#define TRIQS_H5_BASE_H
#include <triqs/utility/mini_vector.hpp> #include <triqs/utility/mini_vector.hpp>
#include <type_traits> #include <type_traits>
#include <H5Cpp.h> #include <H5Cpp.h>
#include "hdf5_hl.h"
#include <triqs/utility/is_complex.hpp> #include <triqs/utility/is_complex.hpp>
namespace triqs { namespace triqs {
@ -108,21 +106,9 @@ namespace triqs {
get_data_ptr (S * p) {return p;} get_data_ptr (S * p) {return p;}
// dataspace from lengths and strides. Correct for the complex. strides must be >0 // dataspace from lengths and strides. Correct for the complex. strides must be >0
template<int R, bool IsComplex> // used in array and vectors
H5::DataSpace dataspace_from_LS ( H5::DataSpace dataspace_from_LS(int R, bool is_complex, hsize_t const *Ltot, hsize_t const *L, hsize_t const *S,
mini_vector<hsize_t, R> const & Ltot, hsize_t const *offset = NULL);
mini_vector<hsize_t, R> const & L,
mini_vector<hsize_t, R> const & S,
mini_vector<hsize_t, R> const & offset = mini_vector<hsize_t,R>() )
{
static const unsigned int rank = R + (IsComplex ? 1 : 0);
hsize_t totdimsf[rank], dimsf [rank], stridesf[rank], offsetf[rank]; // dataset dimensions
for (size_t u=0; u<R ; ++u) { offsetf[u] = offset[u]; dimsf[u] = L[u]; totdimsf[u] = Ltot[u]; stridesf[u] = S[u]; }
if (IsComplex) { offsetf[rank-1]=0; dimsf[rank-1]=2; totdimsf[rank-1] = 2; stridesf[rank-1]=1; }
H5::DataSpace ds ( rank, totdimsf );
ds.selectHyperslab (H5S_SELECT_SET , dimsf, offsetf, stridesf);
return ds;
}
#define TRIQS_ARRAYS_H5_CATCH_EXCEPTION \ #define TRIQS_ARRAYS_H5_CATCH_EXCEPTION \
catch( triqs::runtime_error const & error) { throw triqs::runtime_error() << error.what();}\ catch( triqs::runtime_error const & error) { throw triqs::runtime_error() << error.what();}\
@ -138,47 +124,12 @@ namespace triqs {
catch( H5::ReferenceException const & error ) { error.printError(); TRIQS_RUNTIME_ERROR<<"H5 ReferenceException error"; }\ catch( H5::ReferenceException const & error ) { error.printError(); TRIQS_RUNTIME_ERROR<<"H5 ReferenceException error"; }\
catch(...) { TRIQS_RUNTIME_ERROR<<"H5 unknown error";} catch(...) { TRIQS_RUNTIME_ERROR<<"H5 unknown error";}
/****************** Write string attribute *********************************************/ /****************** Read/Write string attribute *********************************************/
inline void write_string_attribute ( H5::H5Object const * obj, std::string name, std::string value ) { void write_string_attribute(H5::H5Object const *obj, std::string name, std::string value);
H5::DataSpace attr_dataspace = H5::DataSpace(H5S_SCALAR);
// Create new string datatype for attribute
H5::StrType strdatatype(H5::PredType::C_S1, value.size());
// Set up write buffer for attribute
//const H5std_string strwritebuf (value);
// Create attribute and write to it
H5::Attribute myatt_in = obj->createAttribute(name.c_str(), strdatatype, attr_dataspace);
//myatt_in.write(strdatatype, strwritebuf);
myatt_in.write(strdatatype, (void *)(value.c_str()));
}
/// Returns the attribute name of obj, and "" if the attribute does not exist.
/****************** Read string attribute *********************************************/ std::string read_string_attribute(H5::H5Object const *obj, std::string name);
/// Return the attribute name of obj, and "" if the attribute does not exist.
inline std::string read_string_attribute (H5::H5Object const * obj, std::string name ) {
std::string value ="";
H5::Attribute attr;
if (H5LTfind_attribute(obj -> getId(), name.c_str() )==0) return value;// not present
// can not find how to get the size with hl. Using full interface
//herr_t err2 = H5LTget_attribute_string(gr.getId(), x.c_str(), name.c_str() , &(buf.front()) ) ;
//value.append( &(buf.front()) );
try { attr= obj->openAttribute(name.c_str());}
catch (H5::AttributeIException) { return value;}
try {
H5::DataSpace dataspace = attr.getSpace();
int rank = dataspace.getSimpleExtentNdims();
if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string attribute and got rank !=0";
size_t size = attr.getStorageSize();
H5::StrType strdatatype(H5::PredType::C_S1, size+1);
std::vector<char> buf(size+1, 0x00);
attr.read(strdatatype, (void *)(&buf[0]));
value.append( &(buf.front()) );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
return value;
}
}} }}
#endif

View File

@ -1,36 +1,144 @@
#include "./group.hpp" #include "./group.hpp"
#include <hdf5_hl.h>
namespace triqs { namespace h5 { namespace triqs {
namespace h5 {
group::group(H5::Group g, H5::Group parent, std::string name_in_parent)
: _g(g), _parent(parent), _name_in_parent(name_in_parent) {}
//group::group(H5::Group g) : _g(g) {}
group::group(H5::H5File f) : _g(f.openGroup("/")) {} // can not fail, right ?
group::group(std::string const &filename, int flag) {
H5::H5File f(filename, H5F_ACC_TRUNC);
*this = group(f);
}
group::group(hid_t id_, bool is_group) {
if (is_group) {
_g.setId(id_);
} else {
H5::H5File f;
f.setId(id_);
*this = group(f);
}
}
void group::_write_triqs_hdf5_data_scheme(const char *a) { h5::write_string_attribute(&_g, "TRIQS_HDF5_data_scheme", a); }
std::string group::read_triqs_hdf5_data_scheme() const { return read_string_attribute(&_g, "TRIQS_HDF5_data_scheme"); }
bool group::has_key(std::string const &key) const { return (H5Lexists(_g.getId(), key.c_str(), H5P_DEFAULT)); }
void group::unlink_key_if_exists(std::string const &key) const {
if (this->has_key(key)) _g.unlink(key.c_str());
}
group group::open_group(std::string const &key) const {
if (!has_key(key)) TRIQS_RUNTIME_ERROR << "no subgroup " << key << " in the group";
group res;
try {
res = group(_g.openGroup(key.c_str()), _g, key);
} // has a parent
catch (H5::GroupIException const &e) {
TRIQS_RUNTIME_ERROR << "Error in opening the subgroup " << key << "\n H5 error message : \n " << e.getCDetailMsg();
}
return res;
}
/// Open an existing DataSet. Throw it if does not exists
H5::DataSet group::open_dataset(std::string const &key) const {
if (!has_key(key)) TRIQS_RUNTIME_ERROR << "no dataset " << key << " in the group";
H5::DataSet res;
try {
res = _g.openDataSet(key.c_str());
}
catch (H5::GroupIException const &e) {
TRIQS_RUNTIME_ERROR << "Error in opening the dataset " << key << "\n H5 error message : \n " << e.getCDetailMsg();
}
return res;
}
/**
* \brief Create a subgroup.
* \param key The name of the subgroup
* \param delete_if_exists Unlink the group if it exists
*/
group group::create_group(std::string const &key, bool delete_if_exists) const {
unlink_key_if_exists(key);
return group(_g.createGroup(key.c_str()), _g, key);
}
/**
* \brief Create a dataset.
* \param key The name of the subgroup
* \param args Other parameters are forwarded to H5::Group
*
* NB : It unlinks the dataset if it exists.
*/
H5::DataSet group::create_dataset(std::string const &key, const H5::DataType &data_type, const H5::DataSpace &data_space,
const H5::DSetCreatPropList &create_plist) const {
unlink_key_if_exists(key);
H5::DataSet res;
try {
res = _g.createDataSet(key.c_str(), data_type, data_space, create_plist);
}
catch (H5::GroupIException const &e) {
TRIQS_RUNTIME_ERROR << "Error in creating the dataset " << key << "\n H5 error message : \n " << e.getCDetailMsg();
}
return res;
}
void group::write_string_attribute (std::string const & obj_name, std::string const & attr_name, std::string const & value){
herr_t err = H5LTset_attribute_string(_g.getId(),obj_name.c_str(),attr_name.c_str(), value.c_str() ) ;
if (err<0) TRIQS_RUNTIME_ERROR << "Error in setting attribute of "<< obj_name<<" named "<< attr_name << " to " << value;
}
//-----------------------------------------------------------------------
extern "C" { extern "C" {
herr_t get_group_elements_name_ds(hid_t loc_id, const char *name, void *opdata) { herr_t get_group_elements_name_ds(hid_t loc_id, const char *name, void *opdata) {
H5O_info_t object_info; herr_t err =H5Oget_info_by_name(loc_id,name,&object_info,H5P_DEFAULT ); H5O_info_t object_info;
if (err<0) TRIQS_RUNTIME_ERROR << "get_group_elements_name_ds internal"; herr_t err = H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT);
if (object_info.type == H5O_TYPE_DATASET) static_cast<std::vector<std::string> *>(opdata)->push_back(name); if (err < 0) TRIQS_RUNTIME_ERROR << "get_group_elements_name_ds internal";
return 0; if (object_info.type == H5O_TYPE_DATASET) static_cast<std::vector<std::string> *>(opdata)->push_back(name);
} return 0;
herr_t get_group_elements_name_grp(hid_t loc_id, const char *name, void *opdata) { }
H5O_info_t object_info; herr_t err =H5Oget_info_by_name(loc_id,name,&object_info,H5P_DEFAULT ); herr_t get_group_elements_name_grp(hid_t loc_id, const char *name, void *opdata) {
if (err<0) TRIQS_RUNTIME_ERROR << "get_group_elements_name_grp internal"; H5O_info_t object_info;
if (object_info.type == H5O_TYPE_GROUP) static_cast<std::vector<std::string> *>(opdata)->push_back(name); herr_t err = H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT);
return 0; if (err < 0) TRIQS_RUNTIME_ERROR << "get_group_elements_name_grp internal";
} if (object_info.type == H5O_TYPE_GROUP) static_cast<std::vector<std::string> *>(opdata)->push_back(name);
return 0;
}
} }
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
std::vector<std::string> group::get_all_subgroup_names(std::string const & key) const { std::vector<std::string> group::get_all_subgroup_names(std::string const &key) const {
std::vector<std::string> grp_name; std::vector<std::string> grp_name;
H5::Group F(_g); H5::Group F(_g);
F.iterateElems(key.c_str(), NULL, get_group_elements_name_grp, static_cast<void*>(&grp_name)); F.iterateElems(key.c_str(), NULL, get_group_elements_name_grp, static_cast<void *>(&grp_name));
return grp_name; return grp_name;
} }
std::vector<std::string> group::get_all_dataset_names(std::string const & key) const { std::vector<std::string> group::get_all_dataset_names(std::string const &key) const {
std::vector<std::string> ds_name; std::vector<std::string> ds_name;
H5::Group F(_g); H5::Group F(_g);
F.iterateElems(key.c_str(), NULL, get_group_elements_name_ds, static_cast<void*>(&ds_name)); F.iterateElems(key.c_str(), NULL, get_group_elements_name_ds, static_cast<void *>(&ds_name));
return ds_name; return ds_name;
} }
}} std::vector<std::string> group::get_all_subgroup_names() const {
if (!has_parent()) TRIQS_RUNTIME_ERROR << "Group hdf5 : parent not found";
return group(_parent).get_all_subgroup_names(_name_in_parent);
}
std::vector<std::string> group::get_all_dataset_names() const {
if (!has_parent()) TRIQS_RUNTIME_ERROR << "Group hdf5 : parent not found";
return group(_parent).get_all_dataset_names(_name_in_parent);
}
}
}

View File

@ -18,107 +18,84 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_H5_GROUP_H #pragma once
#define TRIQS_H5_GROUP_H
#include "./base.hpp" #include "./base.hpp"
namespace triqs { namespace h5 {
namespace triqs {
namespace h5 {
// using hid_t = int;
/** /**
* \brief A local derivative of Group. * \brief A local derivative of Group.
* Rational : use ADL for h5_read/h5_write, catch and rethrow exception, add some policy for opening/creating * Rational : use ADL for h5_read/h5_write, catch and rethrow exception, add some policy for opening/creating
*/ */
class group { class group {
H5::Group _g, _parent; // hid_t _g_id, _parent_id;
std::string _name_in_parent; H5::Group _g, _parent;
group(H5::Group g, H5::Group parent, std::string name_in_parent) : _g(g), _parent(parent), _name_in_parent(name_in_parent) {} std::string _name_in_parent;
group(H5::Group g, H5::Group parent, std::string name_in_parent);
void _write_triqs_hdf5_data_scheme(const char *a);
public: public:
group() = default; group() = default;
group(group const &) = default; group(group const &) = default;
group(H5::Group g) : _g(g) {} group(H5::Group g) : _g(g) {}
group(H5::H5File f); /// Takes the "/" group at the top of the file
/// Takes the "/" group at the top of the file. group(std::string const &filename, int flag);
group (H5::H5File f) : _g(f.openGroup("/")) {} // can not fail, right ? group(hid_t id_, bool is_group);
group(std::string const & filename, int flag) { H5::H5File f(filename, H5F_ACC_TRUNC); *this = group(f);} bool has_parent() const { return _name_in_parent != ""; }
group(hid_t id_, bool is_group) { /// Write the triqs tag of the group if it is an object.
if (is_group) { _g.setId(id_); } template <typename T> void write_triqs_hdf5_data_scheme(T const &obj) {
else { H5::H5File f; f.setId(id_); *this = group(f); } _write_triqs_hdf5_data_scheme(get_triqs_hdf5_data_scheme(obj).c_str());
} }
bool has_parent() const { return _name_in_parent != "";} /// Read the triqs tag of the group if it is an object. Returns"" if attribute is not present
std::string read_triqs_hdf5_data_scheme() const;
/// Write the triqs tag of the group if it is an object. ///
template<typename T> void write_triqs_hdf5_data_scheme (T const & obj) { bool has_key(std::string const &key) const;
h5::write_string_attribute( &_g, "TRIQS_HDF5_data_scheme" , get_triqs_hdf5_data_scheme(obj).c_str() ) ; ///
}
/// Read the triqs tag of the group if it is an object. Returns"" if attribute is not present
std::string read_triqs_hdf5_data_scheme() const { return read_string_attribute(&_g, "TRIQS_HDF5_data_scheme") ; }
///
bool has_key (std::string const & key) const { return (H5Lexists(_g.getId(), key.c_str(), H5P_DEFAULT)); }
///
void unlink_key_if_exists(std::string const & key) const { if (this->has_key(key)) _g.unlink(key.c_str()); }
/// Open a subgroup. Throw it if does not exists
group open_group(std::string const & key) const {
if (!has_key(key)) TRIQS_RUNTIME_ERROR << "no subgroup "<<key <<" in the group";
group res;
try { res = group( _g.openGroup(key.c_str()), _g, key) ;} // has a parent
catch (H5::GroupIException const & e){ TRIQS_RUNTIME_ERROR << "Error in opening the subgroup "<< key <<"\n H5 error message : \n "<< e.getCDetailMsg(); }
return res;
}
/// Open an existing DataSet. Throw it if does not exists
H5::DataSet open_dataset(std::string const & key) const {
if (!has_key(key)) TRIQS_RUNTIME_ERROR << "no dataset "<<key <<" in the group";
H5::DataSet res;
try { res = _g.openDataSet(key.c_str());}
catch (H5::GroupIException const & e){ TRIQS_RUNTIME_ERROR << "Error in opening the dataset "<< key <<"\n H5 error message : \n "<< e.getCDetailMsg(); }
return res;
}
/**
* \brief Create a subgroup.
* \param key The name of the subgroup
* \param delete_if_exists Unlink the group if it exists
*/
group create_group(std::string const & key, bool delete_if_exists = true) const {
unlink_key_if_exists(key);
return group(_g.createGroup(key.c_str()),_g, key);
}
/**
* \brief Create a dataset.
* \param key The name of the subgroup
* \param args Other parameters are forwarded to H5::Group
*
* NB : It unlinks the dataset if it exists.
*/
template<typename ... Args>
H5::DataSet create_dataset(std::string const & key, Args && ... args) const {
unlink_key_if_exists(key);
H5::DataSet res;
try{ res = _g.createDataSet(key.c_str(), std::forward<Args>(args)...);}
catch (H5::GroupIException const & e){ TRIQS_RUNTIME_ERROR << "Error in creating the dataset "<< key <<"\n H5 error message : \n "<< e.getCDetailMsg(); }
return res;
}
/// Returns all names of subgroup of key in G void unlink_key_if_exists(std::string const &key) const;
std::vector<std::string> get_all_subgroup_names(std::string const & key) const;
std::vector<std::string> get_all_subgroup_names() const { /// Open a subgroup. Throw it if does not exists
if (!has_parent()) TRIQS_RUNTIME_ERROR << "Group hdf5 : parent not found"; group open_group(std::string const &key) const;
return group(_parent).get_all_subgroup_names(_name_in_parent);
}
/// Returns all names of dataset of key in G /// Open an existing DataSet. Throw it if does not exists
std::vector<std::string> get_all_dataset_names(std::string const & key) const; H5::DataSet open_dataset(std::string const &key) const;
std::vector<std::string> get_all_dataset_names() const { /**
if (!has_parent()) TRIQS_RUNTIME_ERROR << "Group hdf5 : parent not found"; * \brief Create a subgroup.
return group(_parent).get_all_dataset_names(_name_in_parent); * \param key The name of the subgroup
} * \param delete_if_exists Unlink the group if it exists
*/
group create_group(std::string const &key, bool delete_if_exists = true) const;
/**
* \brief Create a dataset.
* \param key The name of the subgroup
*
* NB : It unlinks the dataset if it exists.
*/
H5::DataSet create_dataset(std::string const &key, const H5::DataType &data_type, const H5::DataSpace &data_space,
const H5::DSetCreatPropList &create_plist= H5::DSetCreatPropList::DEFAULT) const;
void write_string_attribute (std::string const & obj_name, std::string const & attr_name, std::string const & value){ /// Returns all names of subgroup of key in G
herr_t err = H5LTset_attribute_string(_g.getId(),obj_name.c_str(),attr_name.c_str(), value.c_str() ) ; std::vector<std::string> get_all_subgroup_names(std::string const &key) const;
if (err<0) TRIQS_RUNTIME_ERROR << "Error in setting attribute of "<< obj_name<<" named "<< attr_name << " to " << value;
}
/// Returns all names of subgroup of G
std::vector<std::string> get_all_subgroup_names() const;
/// Returns all names of dataset of key in G
std::vector<std::string> get_all_dataset_names(std::string const &key) const;
/// Returns all names of dataset of G
std::vector<std::string> get_all_dataset_names() const;
void write_string_attribute (std::string const & obj_name, std::string const & attr_name, std::string const & value);
}; };
}} }
#endif }

74
triqs/h5/scalar.cpp Normal file
View File

@ -0,0 +1,74 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011-2014 by O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#include "./scalar.hpp"
namespace triqs { namespace h5 {
namespace {
// TODO : Fix complex number ....
// S must be scalar
template <typename S>
void h5_write_impl (group g, std::string const & name, S const & A) {
try {
g.unlink_key_if_exists(name);
H5::DataSet ds = g.create_dataset( name, data_type_file<S>(), H5::DataSpace() );
ds.write( (void *)(&A), data_type_memory<S>(), H5::DataSpace() );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
template <typename S>
void h5_read_impl (group g, std::string const & name, S & A) {
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
int rank = dataspace.getSimpleExtentNdims();
if (rank != 0) TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : expecting a scalar (rank =0)"
<<" while the array stored in the hdf5 file has rank = "<<rank;
ds.read( (void *)(&A), data_type_memory<S>(), H5::DataSpace() , H5::DataSpace() );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
}
void h5_write(group g, std::string const &name, int const &x) { h5_write_impl(g, name, x); }
void h5_write(group g, std::string const &name, long const &x) { h5_write_impl(g, name, x); }
void h5_write(group g, std::string const &name, size_t const &x) { h5_write_impl(g, name, x); }
void h5_write(group g, std::string const &name, char const &x) { h5_write_impl(g, name, x); }
void h5_write(group g, std::string const &name, bool const &x) { h5_write_impl(g, name, x); }
void h5_write(group g, std::string const &name, double const &x) { h5_write_impl(g, name, x); }
void h5_write(group g, std::string const &name, std::complex<double> const &x) { h5_write_impl(g, name, x); }
void h5_read(group g, std::string const &name, int &x) { h5_read_impl(g, name, x); }
void h5_read(group g, std::string const &name, long &x) { h5_read_impl(g, name, x); }
void h5_read(group g, std::string const &name, size_t &x) { h5_read_impl(g, name, x); }
void h5_read(group g, std::string const &name, char &x) { h5_read_impl(g, name, x); }
void h5_read(group g, std::string const &name, bool &x) { h5_read_impl(g, name, x); }
void h5_read(group g, std::string const &name, double &x) { h5_read_impl(g, name, x); }
void h5_read(group g, std::string const &name, std::complex<double> &x) { h5_read_impl(g, name, x); }
}}

View File

@ -18,39 +18,29 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_H5_SCALAR_H #pragma once
#define TRIQS_H5_SCALAR_H
#include "./group.hpp" #include "./group.hpp"
namespace triqs { namespace h5 { namespace triqs { namespace h5 {
template <typename S> // Issue several types are *implicitly* convertible to bool
typename std::enable_if<std::is_arithmetic<S>::value>::type // it could be confusing. Better to use int in hdf5 files.
h5_write (group g, std::string const & name, S const & A) { void h5_write(group g, std::string const &name, int const &x);
try { void h5_write(group g, std::string const &name, long const &x);
g.unlink_key_if_exists(name); void h5_write(group g, std::string const &name, size_t const &x);
H5::DataSet ds = g.create_dataset( name, data_type_file<S>(), H5::DataSpace() ); void h5_write(group g, std::string const &name, bool const &x);
ds.write( (void *)(&A), data_type_memory<S>(), H5::DataSpace() ); void h5_write(group g, std::string const &name, char const &x);
} void h5_write(group g, std::string const &name, double const &x);
TRIQS_ARRAYS_H5_CATCH_EXCEPTION; void h5_write(group g, std::string const &name, std::complex<double> const &x);
}
template <typename S>
typename std::enable_if<std::is_arithmetic<S>::value>::type
h5_read (group g, std::string const & name, S & A) {
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
int rank = dataspace.getSimpleExtentNdims();
if (rank != 0) TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : expecting a scalar (rank =0)"
<<" while the array stored in the hdf5 file has rank = "<<rank;
ds.read( (void *)(&A), data_type_memory<S>(), H5::DataSpace() , H5::DataSpace() );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
// the complex number is missing here...
}}
#endif
void h5_read(group g, std::string const &name, int &x);
void h5_read(group g, std::string const &name, long &x);
void h5_read(group g, std::string const &name, size_t &x);
void h5_read(group g, std::string const &name, bool &x);
void h5_read(group g, std::string const &name, char &x);
void h5_read(group g, std::string const &name, double &x);
void h5_read(group g, std::string const &name, std::complex<double> &x);
// the implementation complex number is missing ...
}
}

51
triqs/h5/string.cpp Normal file
View File

@ -0,0 +1,51 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011-2014 by O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#include "./string.hpp"
namespace triqs {
namespace h5 {
void h5_write (group g, std::string const & name, std::string const & value) {
try {
H5::StrType strdatatype(H5::PredType::C_S1, value.size());
H5::DataSet ds = g.create_dataset(name, strdatatype, H5::DataSpace());
ds.write((void*)(value.c_str()), strdatatype );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
void h5_read (group g, std::string const & name, std::string & value) {
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
int rank = dataspace.getSimpleExtentNdims();
if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string and got rank !=0";
size_t size = ds.getStorageSize();
H5::StrType strdatatype(H5::PredType::C_S1, size);
std::vector<char> buf(size+1, 0x00);
ds.read( (void *)(&buf[0]), strdatatype, H5::DataSpace(), H5::DataSpace() );
value = ""; value.append( &(buf.front()) );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
}}

View File

@ -18,10 +18,10 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_H5_STRING_H #pragma once
#define TRIQS_H5_STRING_H
#include "./group.hpp" #include "./group.hpp"
#include <cstring> #include <cstring>
namespace triqs { namespace triqs {
inline std::string get_triqs_hdf5_data_scheme(std::string const & ) { return "string";} inline std::string get_triqs_hdf5_data_scheme(std::string const & ) { return "string";}
@ -35,14 +35,9 @@ namespace triqs {
* \param value The string * \param value The string
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc). * \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
*/ */
inline void h5_write (group g, std::string const & name, std::string const & value) { void h5_write (group g, std::string const & name, std::string const & value);
try {
H5::StrType strdatatype(H5::PredType::C_S1, value.size()); inline void h5_write (group g, std::string const & name, const char * s) { h5_write(g,name,std::string{s});}
H5::DataSet ds = g.create_dataset(name, strdatatype, H5::DataSpace());
ds.write((void*)(value.c_str()), strdatatype );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
/** /**
* \brief Read a string from an hdf5 file * \brief Read a string from an hdf5 file
@ -51,74 +46,9 @@ namespace triqs {
* \param value The string to fill * \param value The string to fill
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc). * \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
*/ */
inline void h5_read (group g, std::string const & name, std::string & value) { void h5_read (group g, std::string const & name, std::string & value);
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
int rank = dataspace.getSimpleExtentNdims();
if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string and got rank !=0";
size_t size = ds.getStorageSize();
H5::StrType strdatatype(H5::PredType::C_S1, size);
std::vector<char> buf(size+1, 0x00);
ds.read( (void *)(&buf[0]), strdatatype, H5::DataSpace(), H5::DataSpace() );
value = ""; value.append( &(buf.front()) );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
/*********************************** 1d array and std::vector of string *********************************/
namespace detail {
template<typename ArrayVectorOfStringType>
void write_1darray_vector_of_string_impl (group g, std::string const & name, ArrayVectorOfStringType const & V) {
size_t s=0; for (auto & x : V) s = std::max(s,x.size());
try {
H5::DataSet ds;
H5::StrType strdatatype(H5::PredType::C_S1, s);
const size_t n = V.size();
std::vector<char> buf(n*(s+1), 0x00);
size_t i=0; for (auto & x : V) {strcpy( &buf[i*s], x.c_str()); ++i;}
mini_vector<hsize_t,1> L; L[0]=V.size();
mini_vector<hsize_t,1> S; S[0]=1;
auto d_space = dataspace_from_LS<1,false > (L,L,S);
ds = g.create_dataset(name, strdatatype, d_space );
ds.write( (void *)(&buf[0]),strdatatype, d_space );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
//------------------------------------------------------------
template<typename ArrayVectorOfStringType>
void read_1darray_vector_of_string_impl (group g, std::string const & name, ArrayVectorOfStringType & V) {
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
mini_vector<hsize_t,1> dims_out;
int ndims = dataspace.getSimpleExtentDims( &dims_out[0], NULL);
if (ndims !=1) TRIQS_RUNTIME_ERROR << "triqs::h5 : Trying to read 1d array/vector . Rank mismatch : the array stored in the hdf5 file has rank = "<<ndims;
size_t Len = dims_out[0];
V.resize(Len);
size_t size = ds.getStorageSize();
H5::StrType strdatatype(H5::PredType::C_S1, size);
std::vector<char> buf(Len*(size+1), 0x00);
mini_vector<hsize_t,1> L; L[0]=V.size();
mini_vector<hsize_t,1> S; S[0]=1;
auto d_space = dataspace_from_LS<1,false > (L,L,S);
ds.read( (void *)(&buf[0]),strdatatype, d_space );
size_t i=0; for (auto & x : V) { x = ""; x.append(&buf[i*(size)]); ++i;}
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
}// detail
inline void h5_read (group g, std::string const & name, char * s) = delete;
}} }}
#endif

120
triqs/h5/vector.cpp Normal file
View File

@ -0,0 +1,120 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011-2014 by O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#include "./vector.hpp"
namespace triqs {
namespace h5 {
void h5_write (group g, std::string const & name, std::vector<std::string> const & V) {
size_t s=0; for (auto & x : V) s = std::max(s,x.size());
try {
H5::DataSet ds;
H5::StrType strdatatype(H5::PredType::C_S1, s);
const size_t n = V.size();
std::vector<char> buf(n*(s+1), 0x00);
size_t i=0; for (auto & x : V) {strcpy( &buf[i*s], x.c_str()); ++i;}
hsize_t L[1], S[1];
L[0] = V.size();
S[0] = 1;
auto d_space = dataspace_from_LS(1,false,L,L,S);
ds = g.create_dataset(name, strdatatype, d_space );
ds.write( (void *)(&buf[0]),strdatatype, d_space );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
void h5_read (group g, std::string const & name, std::vector<std::string> & V) {
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
mini_vector<hsize_t,1> dims_out;
int ndims = dataspace.getSimpleExtentDims( &dims_out[0], NULL);
if (ndims !=1) TRIQS_RUNTIME_ERROR << "triqs::h5 : Trying to read 1d array/vector . Rank mismatch : the array stored in the hdf5 file has rank = "<<ndims;
size_t Len = dims_out[0];
V.resize(Len);
size_t size = ds.getStorageSize();
H5::StrType strdatatype(H5::PredType::C_S1, size);
std::vector<char> buf(Len*(size+1), 0x00);
hsize_t L[1], S[1];
L[0] = V.size();
S[0] = 1;
auto d_space = dataspace_from_LS(1,false, L,L,S);
ds.read( (void *)(&buf[0]),strdatatype, d_space );
size_t i=0; for (auto & x : V) { x = ""; x.append(&buf[i*(size)]); ++i;}
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
// implementation for vector of double and complex
namespace {
// the dataspace corresponding to the array. Contiguous data only...
template <typename T> H5::DataSpace data_space_for_vector(std::vector<T> const &V) {
hsize_t L[1], S[1];
S[0] = 1;
L[0] = V.size();
return h5::dataspace_from_LS(1, triqs::is_complex<T>::value, L, L, S);
}
template<typename T>
inline void h5_write_vector_impl (group g, std::string const & name, std::vector<T> const & V) {
try {
H5::DataSet ds = g.create_dataset(name, h5::data_type_file<T>(), data_space_for_vector(V) );
ds.write( &V[0], h5::data_type_memory<T>(), data_space_for_vector(V) );
// if complex, to be python compatible, we add the __complex__ attribute
if (triqs::is_complex<T>::value) h5::write_string_attribute(&ds,"__complex__","1");
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
template<typename T>
inline void h5_read_impl (group g, std::string const & name, std::vector<T> & V) {
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
static const unsigned int Rank = 1 + (triqs::is_complex<T>::value ? 1 : 0);
int rank = dataspace.getSimpleExtentNdims();
if (rank != Rank) TRIQS_RUNTIME_ERROR << "triqs : h5 : read vector. Rank mismatch : the array stored in the hdf5 file has rank = "<<rank;
mini_vector<hsize_t,Rank> dims_out;
dataspace.getSimpleExtentDims( &dims_out[0], NULL);
V.resize(dims_out[0]);
ds.read( &V[0], h5::data_type_memory<T>(), data_space_for_vector(V) , dataspace );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
}// impl namespace
void h5_write (group f, std::string const & name, std::vector<double> const & V) { h5_write_vector_impl(f,name,V);}
void h5_write (group f, std::string const & name, std::vector<std::complex<double>> const & V) { h5_write_vector_impl(f,name,V);}
void h5_read (group f, std::string const & name, std::vector<double> & V) { h5_read_impl(f,name,V);}
void h5_read (group f, std::string const & name, std::vector<std::complex<double>> & V) { h5_read_impl(f,name,V);}
}
}

View File

@ -18,8 +18,7 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_H5_VECTOR_H #pragma once
#define TRIQS_H5_VECTOR_H
#include "./group.hpp" #include "./group.hpp"
#include "./string.hpp" #include "./string.hpp"
#include <vector> #include <vector>
@ -28,72 +27,23 @@ namespace triqs {
inline std::string get_triqs_hdf5_data_scheme(std::vector<std::string> const & ) { return "vector<string>";} inline std::string get_triqs_hdf5_data_scheme(std::vector<std::string> const & ) { return "vector<string>";}
template <typename T> template <typename T> std::string get_triqs_hdf5_data_scheme(std::vector<T> const&) {
std::string get_triqs_hdf5_data_scheme(std::vector<T> const&) { using triqs::get_triqs_hdf5_data_scheme; // for the basic types, not found by ADL
using triqs::get_triqs_hdf5_data_scheme;// for the basic types, not found by ADL return "std::vector<" + get_triqs_hdf5_data_scheme(T()) + ">";
std::stringstream fs; }
fs<<"std::vector<"<<get_triqs_hdf5_data_scheme(T())<<">";
return fs.str();
}
namespace h5 { namespace h5 {
// special case of vector of string void h5_write (group f, std::string const & name, std::vector<std::string> const & V);
inline void h5_write (group f, std::string const & name, std::vector<std::string> const & V) { void h5_read (group f, std::string const & name, std::vector<std::string> & V);
detail::write_1darray_vector_of_string_impl(f,name,V);
}
inline void h5_read (group f, std::string const & name, std::vector<std::string> & V) { void h5_write (group f, std::string const & name, std::vector<double> const & V);
detail::read_1darray_vector_of_string_impl(f,name,V); void h5_write (group f, std::string const & name, std::vector<std::complex<double>> const & V);
}
// implementation for vector of double and complex void h5_read (group f, std::string const & name, std::vector<double> & V);
namespace vector_impl { void h5_read (group f, std::string const & name, std::vector<std::complex<double>> & V);
// the dataspace corresponding to the array. Contiguous data only...
template <typename T>
H5::DataSpace data_space_for_vector (std::vector<T> const & V) {
mini_vector<hsize_t,1> L,S; S[0]=1;L[0] = V.size();
return h5::dataspace_from_LS<1, triqs::is_complex<T>::value > (L,L,S);
}
template<typename T>
inline void h5_write_vector_impl (group g, std::string const & name, std::vector<T> const & V) {
try {
H5::DataSet ds = g.create_dataset(name, h5::data_type_file<T>(), data_space_for_vector(V) );
ds.write( &V[0], h5::data_type_memory<T>(), data_space_for_vector(V) );
// if complex, to be python compatible, we add the __complex__ attribute
if (triqs::is_complex<T>::value) h5::write_string_attribute(&ds,"__complex__","1");
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
template<typename T>
inline void h5_read_impl (group g, std::string const & name, std::vector<T> & V) {
try {
H5::DataSet ds = g.open_dataset(name);
H5::DataSpace dataspace = ds.getSpace();
static const unsigned int Rank = 1 + (triqs::is_complex<T>::value ? 1 : 0);
int rank = dataspace.getSimpleExtentNdims();
if (rank != Rank) TRIQS_RUNTIME_ERROR << "triqs : h5 : read vector. Rank mismatch : the array stored in the hdf5 file has rank = "<<rank;
mini_vector<hsize_t,Rank> dims_out;
dataspace.getSimpleExtentDims( &dims_out[0], NULL);
V.resize(dims_out[0]);
ds.read( &V[0], h5::data_type_memory<T>(), data_space_for_vector(V) , dataspace );
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
}
}// impl namespace
inline void h5_write (group f, std::string const & name, std::vector<double> const & V) { vector_impl::h5_write_vector_impl(f,name,V);}
inline void h5_write (group f, std::string const & name, std::vector<std::complex<double>> const & V) { vector_impl::h5_write_vector_impl(f,name,V);}
inline void h5_read (group f, std::string const & name, std::vector<double> & V) { vector_impl::h5_read_impl(f,name,V);}
inline void h5_read (group f, std::string const & name, std::vector<std::complex<double>> & V) { vector_impl::h5_read_impl(f,name,V);}
} }
} }
#endif