/******************************************************************************* * * 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 . * ******************************************************************************/ #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 { /** * The implementation class */ template 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::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; public: array_stack_impl(h5::group g, std::string const &name, mini_vector const &base_element_shape, size_t bufsize) { mini_vector dim_chunk; bufsize_ = bufsize; step = 0; _size = 0; for (size_t i = 1; i <= dim; ++i) { dims[i] = base_element_shape[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; } /// ~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 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; } }; // ------------------------- User classes ------------------------------ // The simple case, 1d template class array_stack : public array_stack_impl { static_assert((is_scalar::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{g, name, mini_vector{}, bufsize} {} }; // Specialisation for The simple case, 1d template class array_stack> : public array_stack_impl { 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 const &base_element_shape, size_t bufsize) : array_stack_impl{g, name, base_element_shape, bufsize} {} }; } } // namespace #endif