mirror of
https://github.com/triqs/dft_tools
synced 2024-12-25 05:43:40 +01:00
arrays: clean h5 code
- c++11 cleaning, more doc. - clean the array_stack and its doc.
This commit is contained in:
parent
899210ff53
commit
fa6f991473
@ -2,7 +2,7 @@
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2011 by O. Parcollet
|
||||
* 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
|
||||
@ -24,134 +24,144 @@
|
||||
#include <triqs/h5.hpp>
|
||||
#include "./simple_read_write.hpp"
|
||||
|
||||
namespace triqs { namespace arrays {
|
||||
|
||||
namespace h5_stack_details { // to be replaced by ellipsis
|
||||
template<class T, size_t N, ull_t Opt> array_view<T,N-1,Opt> slice0( array<T,N,Opt> & A, size_t ind);
|
||||
#define AUX(z,p,unused) BOOST_PP_COMMA_IF(p) range()
|
||||
#define IMPL(z, NN, unused) \
|
||||
template<class T, ull_t Opt> array_view<T,BOOST_PP_INC(NN),Opt> slice0( array<T,BOOST_PP_INC(NN)+1,Opt> & A, size_t ind) {\
|
||||
return A(ind,BOOST_PP_REPEAT(BOOST_PP_INC(NN),AUX,nil));}
|
||||
BOOST_PP_REPEAT(ARRAY_NRANK_MAX , IMPL, nil);
|
||||
#undef IMPL
|
||||
#undef AUX
|
||||
template<class T, ull_t Opt> T & slice0( array<T,1,Opt> & A, size_t ind) { return A(ind);}
|
||||
|
||||
template<typename B, typename Enable = void> struct get_value_type { typedef B type; static const size_t rank = 0;};
|
||||
template<typename B> struct get_value_type<B, typename boost::enable_if<is_amv_value_class<B> >::type > {
|
||||
typedef typename B::value_type type;static const size_t rank = B::rank;};
|
||||
|
||||
}
|
||||
namespace triqs {
|
||||
namespace arrays {
|
||||
|
||||
/**
|
||||
* \brief Hdf5 array stack
|
||||
* \tparam BaseElementType The type of the base element of the stack. Can be an array/matrix/vector or a scalar.
|
||||
* If it in a scalar, the array_stack will write an hdf5 array of dimension 1
|
||||
* If it in an array/matrix/vector, the array_stack will write an hdf5 array of dimension BaseElementType::rank +1
|
||||
*
|
||||
* The implementation class
|
||||
*/
|
||||
template< typename BaseElementType>
|
||||
class array_stack {
|
||||
typedef BaseElementType base_element_type;
|
||||
static_assert( (is_amv_value_class<BaseElementType>::value || is_scalar<BaseElementType>::value), "BaseElementType must be an array/matrix/vector or a simple number");
|
||||
typedef typename h5_stack_details::get_value_type<BaseElementType>::type T;
|
||||
static const size_t dim = h5_stack_details::get_value_type<BaseElementType>::rank;
|
||||
static const bool base_is_array = dim >0;
|
||||
size_t bufsize_, step, _size;
|
||||
static const bool T_is_complex = boost::is_complex<T>::value;
|
||||
static const unsigned int RANK = dim + 1 + (T_is_complex ? 1 : 0);
|
||||
utility::mini_vector<hsize_t,RANK> dims, offset, maxdims, dim_chunk, buffer_dim, zero;
|
||||
H5::DataSet dataset;
|
||||
array<T,dim+1> buffer;
|
||||
template <typename T, int R> class array_stack_impl {
|
||||
static const size_t dim = R;
|
||||
static const bool base_is_array = dim > 0;
|
||||
size_t bufsize_, step, _size;
|
||||
static const bool T_is_complex = boost::is_complex<T>::value;
|
||||
static const unsigned int RANK = dim + 1 + (T_is_complex ? 1 : 0);
|
||||
utility::mini_vector<hsize_t, RANK> dims, offset, maxdims, dim_chunk, buffer_dim, zero;
|
||||
H5::DataSet dataset;
|
||||
array<T, dim + 1> buffer;
|
||||
|
||||
template <typename FileGroupType >
|
||||
void construct_delegate ( FileGroupType g, std::string const & name, mini_vector<size_t,dim> const & a_dims, size_t bufsize) {
|
||||
mini_vector<hsize_t,RANK> dim_chunk;
|
||||
bufsize_ = bufsize; step = 0; _size =0;
|
||||
for (size_t i =1; i<=dim; ++i) { dims[i] = a_dims[i-1];}
|
||||
if (T_is_complex) { dims[RANK-1] =2; }
|
||||
maxdims = dims; buffer_dim = dims; dim_chunk = dims;
|
||||
dims[0] = 0; maxdims[0] = H5S_UNLIMITED; dim_chunk[0]=1; buffer_dim[0] = bufsize_;
|
||||
mini_vector<size_t,dim+1> s; for (size_t i =0; i<=dim; ++i) {s[i] = buffer_dim[i];}
|
||||
buffer.resize(s);
|
||||
H5::DataSpace mspace1( RANK, dims.ptr(), maxdims.ptr());
|
||||
H5::DSetCreatPropList cparms; cparms.setChunk( RANK, dim_chunk.ptr() ); // Modify dataset creation properties, i.e. enable chunking.
|
||||
try {
|
||||
dataset = g.create_dataset(name,h5::native_type_from_C(typename h5::remove_complex<T>::type()), mspace1, cparms );
|
||||
if (boost::is_complex<T>::value) h5::write_string_attribute(&dataset,"__complex__","1");
|
||||
}
|
||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||
}
|
||||
|
||||
public :
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \param g The h5 file or group, of type FileGroupType
|
||||
* \param name The name of the hdf5 array in the file/group where the stack will be stored
|
||||
* \param base_element_shape The shape of the base array/matrix/vector [or mini_vector<size_t,0>() for a scalar]
|
||||
* \param bufsize The size of the bufferThe name of the hdf5 array in the file/group where the stack will be stored
|
||||
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with stackstrace, cf doc).
|
||||
*/
|
||||
template <typename FileGroupType >
|
||||
array_stack( FileGroupType g, std::string const & name, mini_vector<size_t,dim> const & base_element_shape, size_t bufsize) {
|
||||
construct_delegate ( g, name, base_element_shape, bufsize);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constructor : valid only if the base is a scalar
|
||||
* \param g The h5 file or group, of type FileGroupType
|
||||
* \param name The name of the hdf5 array in the file/group where the stack will be stored
|
||||
* \param bufsize The size of the bufferThe name of the hdf5 array in the file/group where the stack will be stored
|
||||
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with stackstrace, cf doc).
|
||||
*/
|
||||
template <typename FileGroupType >
|
||||
array_stack( FileGroupType g, std::string const & name, size_t bufsize) {
|
||||
static_assert( (is_scalar<BaseElementType>::value), "This constructor is only available for a scalar BaseElementType");
|
||||
construct_delegate ( g, name,mini_vector<size_t,0>() , bufsize);
|
||||
}
|
||||
|
||||
///
|
||||
~array_stack() {flush();}
|
||||
|
||||
/// The type of the base of the stack (a view or a reference)
|
||||
typedef typename boost::mpl::if_c< base_is_array , array_view<T,dim>, T &>::type slice_type;
|
||||
|
||||
/**
|
||||
* \return A view (for an array/matrix/vector base) or a reference (for a scalar base) to the top of the stack
|
||||
* i.e. the next element to be assigned to
|
||||
*/
|
||||
slice_type operator() () { return h5_stack_details::slice0(buffer, step); }
|
||||
|
||||
/// Advance the stack by one
|
||||
void operator++() { ++step; ++_size; if (step==bufsize_) flush(); }
|
||||
|
||||
/// Flush the buffer to the disk. Automatically called at destruction.
|
||||
void flush() { save_buffer(); step=0;}
|
||||
|
||||
/**
|
||||
* \brief Add a element onto the stack and advance it by one.
|
||||
* S << A is equivalent to S() = A; ++S;
|
||||
*/
|
||||
template<class AType> void operator << ( AType const & A) { (*this)() = A; ++(*this);}
|
||||
|
||||
/// Current size of the stack
|
||||
size_t size() const { return _size;}
|
||||
|
||||
private:
|
||||
void save_buffer () {
|
||||
if (step==0) return;
|
||||
dims[0] += step;
|
||||
buffer_dim[0] = step;
|
||||
dataset.extend(dims.ptr());
|
||||
H5::DataSpace fspace1 = dataset.getSpace (), mspace = h5_impl::data_space(buffer);
|
||||
fspace1.selectHyperslab( H5S_SELECT_SET, buffer_dim.ptr(), offset.ptr() );
|
||||
mspace.selectHyperslab( H5S_SELECT_SET, buffer_dim.ptr(), zero.ptr() );
|
||||
try { dataset.write( h5_impl::get_array_data_ptr(buffer), h5::data_type_memory<T>(), mspace, fspace1 ); }
|
||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||
offset [0] += step;
|
||||
public:
|
||||
array_stack_impl(h5::group g, std::string const &name, mini_vector<size_t, dim> const &base_element_shape, size_t bufsize) {
|
||||
mini_vector<hsize_t, RANK> dim_chunk;
|
||||
bufsize_ = bufsize;
|
||||
step = 0;
|
||||
_size = 0;
|
||||
for (size_t i = 1; i <= dim; ++i) {
|
||||
dims[i] = base_element_shape[i - 1];
|
||||
}
|
||||
};
|
||||
}} // namespace
|
||||
if (T_is_complex) {
|
||||
dims[RANK - 1] = 2;
|
||||
}
|
||||
maxdims = dims;
|
||||
buffer_dim = dims;
|
||||
dim_chunk = dims;
|
||||
dims[0] = 0;
|
||||
maxdims[0] = H5S_UNLIMITED;
|
||||
dim_chunk[0] = 1;
|
||||
buffer_dim[0] = bufsize_;
|
||||
mini_vector<size_t, dim + 1> s;
|
||||
for (size_t i = 0; i <= dim; ++i) {
|
||||
s[i] = buffer_dim[i];
|
||||
}
|
||||
buffer.resize(s);
|
||||
H5::DataSpace mspace1(RANK, dims.ptr(), maxdims.ptr());
|
||||
H5::DSetCreatPropList cparms;
|
||||
cparms.setChunk(RANK, dim_chunk.ptr()); // Modify dataset creation properties, i.e. enable chunking.
|
||||
try {
|
||||
dataset = g.create_dataset(name, h5::native_type_from_C(typename h5::remove_complex<T>::type()), mspace1, cparms);
|
||||
if (boost::is_complex<T>::value) h5::write_string_attribute(&dataset, "__complex__", "1");
|
||||
}
|
||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||
}
|
||||
|
||||
///
|
||||
~array_stack_impl() { flush(); }
|
||||
|
||||
#ifdef TRIQS_DOXYGEN
|
||||
/// A view (for an array/matrix/vector base) or a reference (for a scalar base) to the top of the stack i.e. the next element to be assigned to
|
||||
auto operator()() { return buffer(step, ellipsis()); }
|
||||
|
||||
/// A view (for an array/matrix/vector base) or a reference (for a scalar base) to the top of the stack i.e. the next element to be assigned to
|
||||
auto operator()() const { return buffer(step, ellipsis()); }
|
||||
#else
|
||||
auto operator()() DECL_AND_RETURN(buffer(step, ellipsis()));
|
||||
auto operator()() const DECL_AND_RETURN(buffer(step, ellipsis()));
|
||||
#endif
|
||||
|
||||
/// Advance the stack by one
|
||||
void operator++() {
|
||||
++step;
|
||||
++_size;
|
||||
if (step == bufsize_) flush();
|
||||
}
|
||||
|
||||
/// Flush the buffer to the disk. Automatically called at destruction.
|
||||
void flush() {
|
||||
save_buffer();
|
||||
step = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add a element onto the stack and advance it by one.
|
||||
* S << A is equivalent to S() = A; ++S;
|
||||
*/
|
||||
template <class AType> void operator<<(AType const &A) {
|
||||
(*this)() = A;
|
||||
++(*this);
|
||||
}
|
||||
|
||||
/// Current size of the stack
|
||||
size_t size() const { return _size; }
|
||||
|
||||
private:
|
||||
void save_buffer() {
|
||||
if (step == 0) return;
|
||||
dims[0] += step;
|
||||
buffer_dim[0] = step;
|
||||
dataset.extend(dims.ptr());
|
||||
H5::DataSpace fspace1 = dataset.getSpace(), mspace = h5_impl::data_space(buffer);
|
||||
fspace1.selectHyperslab(H5S_SELECT_SET, buffer_dim.ptr(), offset.ptr());
|
||||
mspace.selectHyperslab(H5S_SELECT_SET, buffer_dim.ptr(), zero.ptr());
|
||||
try {
|
||||
dataset.write(h5_impl::__get_array_data_ptr(buffer), h5::data_type_memory<T>(), mspace, fspace1);
|
||||
}
|
||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||
offset[0] += step;
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------- User classes ------------------------------
|
||||
|
||||
// The simple case, 1d
|
||||
template <typename T> class array_stack : public array_stack_impl<T, 0> {
|
||||
static_assert((is_scalar<T>::value), "Only available for a scalar type");
|
||||
public:
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \param g The h5 group
|
||||
* \param name The name of the hdf5 array in the file/group where the stack will be stored
|
||||
* \param bufsize The size of the buffer
|
||||
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with stackstrace, cf doc).
|
||||
*/
|
||||
array_stack(h5::group g, std::string const &name, size_t bufsize)
|
||||
: array_stack_impl<T, 0>{g, name, mini_vector<size_t, 0>{}, bufsize} {}
|
||||
};
|
||||
|
||||
// Specialisation for The simple case, 1d
|
||||
template <typename T, int N> class array_stack<array<T, N>> : public array_stack_impl<T, N> {
|
||||
public:
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \param g The h5 group
|
||||
* \param name The name of the hdf5 array in the file/group where the stack will be stored
|
||||
* \param base_element_shape The shape of the base array of the stack.
|
||||
* \param bufsize The size of the buffer
|
||||
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with stackstrace, cf doc).
|
||||
*/
|
||||
array_stack(h5::group g, std::string const &name, mini_vector<size_t,N> const &base_element_shape, size_t bufsize)
|
||||
: array_stack_impl<T, N>{g, name, base_element_shape, bufsize} {}
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
|
@ -25,174 +25,175 @@
|
||||
#include <triqs/h5.hpp>
|
||||
#include "../cache.hpp"
|
||||
|
||||
namespace triqs { namespace arrays {
|
||||
namespace triqs {
|
||||
namespace arrays {
|
||||
namespace h5_impl {
|
||||
|
||||
template <typename T, int R> const void * get_array_data_cptr ( array_const_view<T,R> const & A) { return h5::get_data_ptr(&(A.storage()[0]));}
|
||||
template <typename T, int R> const void * get_array_data_cptr ( array_view<T,R> const & A) { return h5::get_data_ptr(&(A.storage()[0]));}
|
||||
template <typename T, int R> const void * get_array_data_cptr ( array<T,R> const & A) { return h5::get_data_ptr(&(A.storage()[0]));}
|
||||
//template <typename T, int R> void * get_array_data_ptr ( array_view<T,R> & A) { return h5::get_data_ptr(&(A.storage()[0]));}
|
||||
//template <typename T, int R> void * get_array_data_ptr ( array<T,R> & A) { return h5::get_data_ptr(&(A.storage()[0]));}
|
||||
template <typename A> const void* __get_array_data_cptr(A const& a) { return h5::get_data_ptr(&(a.storage()[0])); }
|
||||
template <typename A> void* __get_array_data_ptr(A& x) { return h5::get_data_ptr(&(x.storage()[0])); }
|
||||
|
||||
template <typename A> ENABLE_IF(is_amv_value_or_view_class<A>) *
|
||||
get_array_data_ptr (A & x) { return h5::get_data_ptr(&(x.storage()[0]));}
|
||||
|
||||
// the dataspace corresponding to the array. Contiguous data only...
|
||||
template <typename ArrayType >
|
||||
H5::DataSpace data_space ( ArrayType const & A) {
|
||||
static const unsigned int R = ArrayType::rank;
|
||||
mini_vector<hsize_t,R> S;
|
||||
mini_vector<std::ptrdiff_t,R> const & S1 ( A.indexmap().strides() );
|
||||
for (size_t u=0; u<R ; ++u) {
|
||||
if (S1[u]<=0) TRIQS_RUNTIME_ERROR<<" negative strides not permitted in h5";
|
||||
S[u] =1;
|
||||
}
|
||||
if (!A.indexmap().is_contiguous()) TRIQS_RUNTIME_ERROR<<" h5 : internal error : array not contiguous";
|
||||
static const bool is_complex = boost::is_complex<typename ArrayType::value_type>::value;
|
||||
return h5::dataspace_from_LS<R,is_complex > ( A.indexmap().domain().lengths(),A.indexmap().domain().lengths(), S);
|
||||
template <typename ArrayType> H5::DataSpace data_space(ArrayType const& A) {
|
||||
if (!A.indexmap().is_contiguous()) TRIQS_RUNTIME_ERROR << " h5 : internal error : array not contiguous";
|
||||
static const unsigned int R = ArrayType::rank;
|
||||
mini_vector<hsize_t, R> S;
|
||||
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 = boost::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 ****************************************************/
|
||||
|
||||
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)); }
|
||||
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));
|
||||
}
|
||||
|
||||
template <typename A> ENABLE_IF(is_amv_view_class<A>)
|
||||
resize_or_check ( A const & a, mini_vector<size_t,A::rank> const & dimsf ) {
|
||||
if (a.indexmap().domain().lengths() != dimsf) TRIQS_RUNTIME_ERROR<<"Dimension error : the view can not be resized : "
|
||||
<< "\n in file : "<< dimsf.to_string()
|
||||
<< "\n in view : "<<a.indexmap().domain().lengths().to_string() ;
|
||||
}
|
||||
template <typename A> ENABLE_IF(is_amv_view_class<A>) resize_or_check(A const& a, mini_vector<size_t, A::rank> const& dimsf) {
|
||||
if (a.indexmap().domain().lengths() != dimsf)
|
||||
TRIQS_RUNTIME_ERROR << "Dimension error : the view can not be resized : "
|
||||
<< "\n in file : " << dimsf.to_string()
|
||||
<< "\n in view : " << a.indexmap().domain().lengths().to_string();
|
||||
}
|
||||
|
||||
/*********************************** WRITE array ****************************************************************/
|
||||
/**
|
||||
* \brief Write an array or a view into an hdf5 file
|
||||
* \tparam
|
||||
* \param f The h5 file or group of type H5::H5File or H5::Group
|
||||
* \param name The name of the hdf5 array in the file/group where the stack will be stored
|
||||
* \param A The array to be stored
|
||||
* \param C_reorder bool If true [default] the data will be stored in C order in the hdf5, hence making a temporary
|
||||
/*
|
||||
* Write an array or a view into an hdf5 file
|
||||
*
|
||||
* 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]
|
||||
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
||||
* 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 (h5::group g, std::string const & name, array_const_view <T,R> const & A, bool C_reorder = true) {
|
||||
static_assert( !std::is_base_of<std::string, T>::value, " Not implemented");// 1d is below
|
||||
if (C_reorder) { write_array(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 (boost::is_complex<T>::value) h5::write_string_attribute(&ds,"__complex__","1");
|
||||
}
|
||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||
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;
|
||||
}
|
||||
|
||||
template <typename T, int R>
|
||||
void write_array (h5::group g, std::string const & name, array <T,R> const & A, bool C_reorder = true) { write_array(g,name,A(),C_reorder);}
|
||||
template <typename T, int R>
|
||||
void write_array (h5::group g, std::string const & name, array_view <T,R> const & A, bool C_reorder = true) { write_array(g,name,A(),C_reorder);}
|
||||
|
||||
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 (boost::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) {
|
||||
write_array_impl(g, name, typename A::const_view_type{a}, C_reorder);
|
||||
}
|
||||
|
||||
/*********************************** READ array ****************************************************************/
|
||||
/**
|
||||
* \brief Read an array or a view from an hdf5 file
|
||||
* \tparam ArrayType The type of the array/matrix/vector, etc..
|
||||
* \param f The h5 file or group of type H5::H5File or H5::Group
|
||||
* \param name The name of the hdf5 array in the file/group where the stack will be stored
|
||||
* \param A The array to be stored
|
||||
* \param C_reorder bool If true [default] the data will be stored in C order in the hdf5, hence making a temporary
|
||||
/*
|
||||
* 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]
|
||||
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
||||
* 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
|
||||
typedef typename ArrayType::value_type V;
|
||||
try {
|
||||
H5::DataSet ds = g.open_dataset(name);
|
||||
H5::DataSpace dataspace = ds.getSpace();
|
||||
static const unsigned int Rank = ArrayType::rank + (boost::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;
|
||||
//int ndims = dataspace.getSimpleExtentDims( &dims_out[0], NULL);
|
||||
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, cache<ArrayType,typename ArrayType::regular_type>(A).view(),false);}
|
||||
//if (C_reorder) { read_array(g,name, make_cache(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;
|
||||
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 + (boost::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, 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).
|
||||
inline void write_array (h5::group f, std::string const & name, vector_const_view<std::string> V) {
|
||||
h5::detail::write_1darray_vector_of_string_impl(f,name,V);
|
||||
inline void write_array(h5::group f, std::string const& name, vector_const_view<std::string> V) {
|
||||
h5::detail::write_1darray_vector_of_string_impl(f, name, V);
|
||||
}
|
||||
|
||||
inline void write_array (h5::group f, std::string const & name, array_const_view<std::string,1> V) {
|
||||
write_array(f,name,vector_const_view<std::string>(V));
|
||||
inline void write_array(h5::group f, std::string const& name, array_const_view<std::string, 1> V) {
|
||||
write_array(f, name, vector_const_view<std::string>(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);
|
||||
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
|
||||
// Ok, speed is no issue here...
|
||||
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;
|
||||
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 h5impl
|
||||
|
||||
//template<typename ArrayType> struct is_amv_value_or_view_class_no_string :
|
||||
// boost::mpl::and_<is_amv_value_or_view_class<ArrayType>, boost::mpl::not_<boost::is_base_of<std::string, typename ArrayType::value_type> > > {};
|
||||
|
||||
template<typename A, typename Enable=void> struct has_scalar_or_string_value_type : std::false_type{};
|
||||
template<typename A> struct has_scalar_or_string_value_type<A, decltype(nop(std::declval<typename A::value_type>()))> :
|
||||
boost::mpl::or_<is_scalar<typename A::value_type>,std::is_base_of<std::string,typename A::value_type>>{};
|
||||
} // namespace h5impl
|
||||
|
||||
// a trait to detect if A::value_type exists and is a scalar or a string
|
||||
// used to exclude array<array<..>>
|
||||
template <typename A, typename Enable = void> struct has_scalar_or_string_value_type : std::false_type {};
|
||||
template <typename A>
|
||||
struct has_scalar_or_string_value_type<
|
||||
A, decltype(nop(std::declval<
|
||||
typename A::value_type>()))> : std::integral_constant<bool, is_scalar<typename A::value_type>::value ||
|
||||
std::is_base_of<std::string,
|
||||
typename A::value_type>::value> {};
|
||||
// get_triqs_hdf5_data_scheme
|
||||
template <typename ArrayType>
|
||||
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
|
||||
std::stringstream fs;
|
||||
fs<<"array<"<<get_triqs_hdf5_data_scheme(typename ArrayType::value_type())<<","<<ArrayType::rank<<">";
|
||||
return fs.str();
|
||||
}
|
||||
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
|
||||
std::stringstream fs;
|
||||
fs << "array<" << get_triqs_hdf5_data_scheme(typename ArrayType::value_type()) << "," << ArrayType::rank << ">";
|
||||
return fs.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read an array or a view from an hdf5 file
|
||||
* \tparam ArrayType The type of the array/matrix/vector, etc..
|
||||
* \param fg The h5 file or group of type H5::H5File or H5::Group
|
||||
* \param name The name of the hdf5 array in the file/group where the stack will be stored
|
||||
* \param A The array to be stored
|
||||
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
||||
/*
|
||||
* Read an array or a view from an hdf5 file
|
||||
* 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>
|
||||
//ENABLE_IF(is_amv_value_or_view_class<ArrayType>)
|
||||
ENABLE_IFC(is_amv_value_or_view_class<ArrayType>::value && has_scalar_or_string_value_type<ArrayType>::value)
|
||||
h5_read (h5::group fg, std::string const & name, ArrayType & A) { h5_impl::read_array(fg,name, A);}
|
||||
ENABLE_IFC(is_amv_value_or_view_class<ArrayType>::value&& has_scalar_or_string_value_type<ArrayType>::value)
|
||||
h5_read(h5::group g, std::string const& name, ArrayType& A) {
|
||||
h5_impl::read_array(g, name, A);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Write an array or a view into an hdf5 file
|
||||
* \tparam ArrayType The type of the array/matrix/vector, etc..
|
||||
* \param fg The h5 file or group of type H5::H5File or H5::Group
|
||||
* \param name The name of the hdf5 array in the file/group where the stack will be stored
|
||||
* \param A The array to be stored
|
||||
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
||||
/*
|
||||
* Write an array or a view into an hdf5 file
|
||||
* 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>
|
||||
//ENABLE_IF(is_amv_value_or_view_class<ArrayType>)
|
||||
ENABLE_IFC(is_amv_value_or_view_class<ArrayType>::value && has_scalar_or_string_value_type<ArrayType>::value)
|
||||
h5_write (h5::group fg, std::string const & name, ArrayType const & A) { h5_impl::write_array(fg,name, array_const_view<typename ArrayType::value_type, ArrayType::rank>(A));}
|
||||
|
||||
}}
|
||||
ENABLE_IFC(is_amv_value_or_view_class<ArrayType>::value&& has_scalar_or_string_value_type<ArrayType>::value)
|
||||
h5_write(h5::group g, std::string const& name, ArrayType const& A) {
|
||||
h5_impl::write_array(g, name, array_const_view<typename ArrayType::value_type, ArrayType::rank>(A));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -29,11 +29,11 @@ namespace triqs { namespace h5 {
|
||||
class group {
|
||||
H5::Group _g, _parent;
|
||||
std::string _name_in_parent;
|
||||
group(H5::Group g, H5::Group parent, std::string name_in_parent) : _g(g), _parent(parent), _name_in_parent(name_in_parent) {}
|
||||
public:
|
||||
group() = default;
|
||||
group(group const &) = default;
|
||||
group(H5::Group g) : _g(g) {}
|
||||
group(H5::Group g, H5::Group parent, std::string name_in_parent) : _g(g), _parent(parent), _name_in_parent(name_in_parent) {}
|
||||
|
||||
/// Takes the "/" group at the top of the file.
|
||||
group (H5::H5File f) : _g(f.openGroup("/")) {} // can not fail, right ?
|
||||
@ -75,8 +75,8 @@ namespace triqs { namespace h5 {
|
||||
}
|
||||
/**
|
||||
* \brief Create a subgroup.
|
||||
* \param key : the name of the subgroup
|
||||
* \param delete_if_exists : unlink the group if it exists
|
||||
* \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);
|
||||
@ -84,9 +84,10 @@ namespace triqs { namespace h5 {
|
||||
}
|
||||
/**
|
||||
* \brief Create a dataset.
|
||||
* \param key : the name of the subgroup
|
||||
* \param all others are forwarded to H5::Group
|
||||
* It unlinks the dataset if it exists.
|
||||
* \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 {
|
||||
|
Loading…
Reference in New Issue
Block a user