/******************************************************************************* * * 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 . * ******************************************************************************/ #ifndef TRIQS_ARRAYS_H5_STACK_H #define TRIQS_ARRAYS_H5_STACK_H #include "../array.hpp" #include #include "./simple_read_write.hpp" namespace triqs { namespace arrays { namespace h5_stack_details { // to be replaced by ellipsis template array_view slice0( array & A, size_t ind); #define AUX(z,p,unused) BOOST_PP_COMMA_IF(p) range() #define IMPL(z, NN, unused) \ template array_view slice0( array & 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 T & slice0( array & A, size_t ind) { return A(ind);} template struct get_value_type { typedef B type; static const size_t rank = 0;}; template struct get_value_type >::type > { typedef typename B::value_type type;static const size_t rank = B::rank;}; } /** * \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 * */ template< typename BaseElementType> class array_stack { typedef BaseElementType base_element_type; static_assert( (is_amv_value_class::value || is_scalar::value), "BaseElementType must be an array/matrix/vector or a simple number"); typedef typename h5_stack_details::get_value_type::type T; static const size_t dim = h5_stack_details::get_value_type::rank; static const bool base_is_array = dim >0; size_t bufsize_, step, _size; static const bool T_is_complex = boost::is_complex::value; static const unsigned int RANK = dim + 1 + (T_is_complex ? 1 : 0); utility::mini_vector dims, offset, maxdims, dim_chunk, buffer_dim, zero; H5::DataSet dataset; array buffer; template void construct_delegate ( FileGroupType g, std::string const & name, mini_vector const & a_dims, size_t bufsize) { mini_vector 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 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::type()), mspace1, cparms ); if (boost::is_complex::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() 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 array_stack( FileGroupType g, std::string const & name, mini_vector 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 array_stack( FileGroupType g, std::string const & name, size_t bufsize) { static_assert( (is_scalar::value), "This constructor is only available for a scalar BaseElementType"); construct_delegate ( g, name,mini_vector() , 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 &>::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 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(), mspace, fspace1 ); } TRIQS_ARRAYS_H5_CATCH_EXCEPTION; offset [0] += step; } }; }} // namespace #endif