Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 08:55:35

0001 /*
0002  *  Copyright (c), 2017, Adrien Devresse <adrien.devresse@epfl.ch>
0003  *
0004  *  Distributed under the Boost Software License, Version 1.0.
0005  *    (See accompanying file LICENSE_1_0.txt or copy at
0006  *          http://www.boost.org/LICENSE_1_0.txt)
0007  *
0008  */
0009 #pragma once
0010 
0011 #include <algorithm>
0012 #include <cassert>
0013 #include <functional>
0014 #include <numeric>
0015 #include <sstream>
0016 #include <string>
0017 
0018 #include "h5d_wrapper.hpp"
0019 #include "h5s_wrapper.hpp"
0020 
0021 #include "H5ReadWrite_misc.hpp"
0022 #include "H5Converter_misc.hpp"
0023 
0024 namespace HighFive {
0025 
0026 namespace details {
0027 
0028 // map the correct reference to the dataset depending of the layout
0029 // dataset -> itself
0030 // subselection -> parent dataset
0031 inline const DataSet& get_dataset(const Selection& sel) {
0032     return sel.getDataset();
0033 }
0034 
0035 inline const DataSet& get_dataset(const DataSet& ds) {
0036     return ds;
0037 }
0038 
0039 // map the correct memspace identifier depending of the layout
0040 // dataset -> entire memspace
0041 // selection -> resolve space id
0042 inline hid_t get_memspace_id(const Selection& ptr) {
0043     return ptr.getMemSpace().getId();
0044 }
0045 
0046 inline hid_t get_memspace_id(const DataSet&) {
0047     return H5S_ALL;
0048 }
0049 }  // namespace details
0050 
0051 inline ElementSet::ElementSet(std::initializer_list<std::size_t> list)
0052     : _ids(list) {}
0053 
0054 inline ElementSet::ElementSet(std::initializer_list<std::vector<std::size_t>> list)
0055     : ElementSet(std::vector<std::vector<std::size_t>>(list)) {}
0056 
0057 inline ElementSet::ElementSet(const std::vector<std::size_t>& element_ids)
0058     : _ids(element_ids) {}
0059 
0060 inline ElementSet::ElementSet(const std::vector<std::vector<std::size_t>>& element_ids) {
0061     for (const auto& vec: element_ids) {
0062         std::copy(vec.begin(), vec.end(), std::back_inserter(_ids));
0063     }
0064 }
0065 
0066 template <typename Derivate>
0067 inline Selection SliceTraits<Derivate>::select(const HyperSlab& hyperslab,
0068                                                const DataSpace& memspace) const {
0069     // Note: The current limitation are that memspace must describe a
0070     //       packed memspace.
0071     //
0072     //       The reason for this is that we're unable to unpack general
0073     //       hyperslabs when the memory is not contiguous, e.g.
0074     //       `std::vector<std::vector<double>>`.
0075     const auto& slice = static_cast<const Derivate&>(*this);
0076     auto filespace = hyperslab.apply(slice.getSpace());
0077 
0078     return detail::make_selection(memspace, filespace, details::get_dataset(slice));
0079 }
0080 
0081 template <typename Derivate>
0082 inline Selection SliceTraits<Derivate>::select(const HyperSlab& hyper_slab) const {
0083     const auto& slice = static_cast<const Derivate&>(*this);
0084     auto filespace = slice.getSpace();
0085     filespace = hyper_slab.apply(filespace);
0086 
0087     auto n_elements = detail::h5s_get_select_npoints(filespace.getId());
0088     auto memspace = DataSpace(std::array<size_t, 1>{size_t(n_elements)});
0089 
0090     return detail::make_selection(memspace, filespace, details::get_dataset(slice));
0091 }
0092 
0093 
0094 template <typename Derivate>
0095 inline Selection SliceTraits<Derivate>::select(const std::vector<size_t>& offset,
0096                                                const std::vector<size_t>& count,
0097                                                const std::vector<size_t>& stride,
0098                                                const std::vector<size_t>& block) const {
0099     auto slab = HyperSlab(RegularHyperSlab(offset, count, stride, block));
0100     auto memspace = DataSpace(count);
0101     return select(slab, memspace);
0102 }
0103 
0104 template <typename Derivate>
0105 inline Selection SliceTraits<Derivate>::select(const std::vector<size_t>& columns) const {
0106     const auto& slice = static_cast<const Derivate&>(*this);
0107     const DataSpace& space = slice.getSpace();
0108     std::vector<size_t> dims = space.getDimensions();
0109 
0110     std::vector<size_t> counts = dims;
0111     counts.back() = 1;
0112 
0113     std::vector<size_t> offsets(dims.size(), 0);
0114 
0115     HyperSlab slab;
0116     for (const auto& column: columns) {
0117         offsets.back() = column;
0118         slab |= RegularHyperSlab(offsets, counts);
0119     }
0120 
0121     std::vector<size_t> memdims = dims;
0122     memdims.back() = columns.size();
0123 
0124     return select(slab, DataSpace(memdims));
0125 }
0126 
0127 template <typename Derivate>
0128 inline Selection SliceTraits<Derivate>::select(const ElementSet& elements) const {
0129     const auto& slice = static_cast<const Derivate&>(*this);
0130     const hsize_t* data = nullptr;
0131     const DataSpace space = slice.getSpace().clone();
0132     const std::size_t length = elements._ids.size();
0133     if (length % space.getNumberDimensions() != 0) {
0134         throw DataSpaceException(
0135             "Number of coordinates in elements picking "
0136             "should be a multiple of the dimensions.");
0137     }
0138     const std::size_t num_elements = length / space.getNumberDimensions();
0139     std::vector<hsize_t> raw_elements;
0140 
0141     // optimised at compile time
0142     // switch for data conversion on 32bits platforms
0143     if (std::is_same<std::size_t, hsize_t>::value) {
0144         // `if constexpr` can't be used, thus a reinterpret_cast is needed.
0145         data = reinterpret_cast<const hsize_t*>(&(elements._ids[0]));
0146     } else {
0147         raw_elements.resize(length);
0148         std::copy(elements._ids.begin(), elements._ids.end(), raw_elements.begin());
0149         data = raw_elements.data();
0150     }
0151 
0152     detail::h5s_select_elements(space.getId(), H5S_SELECT_SET, num_elements, data);
0153 
0154     return detail::make_selection(DataSpace(num_elements), space, details::get_dataset(slice));
0155 }
0156 
0157 
0158 template <typename Derivate>
0159 template <typename T>
0160 inline T SliceTraits<Derivate>::read(const DataTransferProps& xfer_props) const {
0161     T array;
0162     read(array, xfer_props);
0163     return array;
0164 }
0165 
0166 
0167 template <typename Derivate>
0168 template <typename T>
0169 inline void SliceTraits<Derivate>::read(T& array, const DataTransferProps& xfer_props) const {
0170     const auto& slice = static_cast<const Derivate&>(*this);
0171     const DataSpace& mem_space = slice.getMemSpace();
0172 
0173     auto file_datatype = slice.getDataType();
0174 
0175     const details::BufferInfo<T> buffer_info(
0176         file_datatype,
0177         [&slice]() -> std::string { return details::get_dataset(slice).getPath(); },
0178         details::BufferInfo<T>::Operation::read);
0179 
0180     if (!details::checkDimensions(mem_space, buffer_info.n_dimensions)) {
0181         std::ostringstream ss;
0182         ss << "Impossible to read DataSet of dimensions " << mem_space.getNumberDimensions()
0183            << " into arrays of dimensions " << buffer_info.n_dimensions;
0184         throw DataSpaceException(ss.str());
0185     }
0186     auto dims = mem_space.getDimensions();
0187 
0188     auto r = details::data_converter::get_reader<T>(dims, array, file_datatype);
0189     read_raw(r.getPointer(), buffer_info.data_type, xfer_props);
0190     // re-arrange results
0191     r.unserialize(array);
0192 
0193     auto t = buffer_info.data_type;
0194     auto c = t.getClass();
0195     if (c == DataTypeClass::VarLen || t.isVariableStr()) {
0196 #if H5_VERSION_GE(1, 12, 0)
0197         // This one have been created in 1.12.0
0198         (void)
0199             detail::h5t_reclaim(t.getId(), mem_space.getId(), xfer_props.getId(), r.getPointer());
0200 #else
0201         // This one is deprecated since 1.12.0
0202         (void) detail::h5d_vlen_reclaim(t.getId(),
0203                                         mem_space.getId(),
0204                                         xfer_props.getId(),
0205                                         r.getPointer());
0206 #endif
0207     }
0208 }
0209 
0210 template <typename Derivate>
0211 template <typename T>
0212 inline void SliceTraits<Derivate>::read(T* array,
0213                                         const DataType& mem_datatype,
0214                                         const DataTransferProps& xfer_props) const {
0215     read_raw(array, mem_datatype, xfer_props);
0216 }
0217 
0218 template <typename Derivate>
0219 template <typename T>
0220 inline void SliceTraits<Derivate>::read(T* array, const DataTransferProps& xfer_props) const {
0221     read_raw(array, xfer_props);
0222 }
0223 
0224 
0225 template <typename Derivate>
0226 template <typename T>
0227 inline void SliceTraits<Derivate>::read_raw(T* array,
0228                                             const DataType& mem_datatype,
0229                                             const DataTransferProps& xfer_props) const {
0230     static_assert(!std::is_const<T>::value,
0231                   "read() requires a non-const structure to read data into");
0232 
0233     const auto& slice = static_cast<const Derivate&>(*this);
0234 
0235     detail::h5d_read(details::get_dataset(slice).getId(),
0236                      mem_datatype.getId(),
0237                      details::get_memspace_id(slice),
0238                      slice.getSpace().getId(),
0239                      xfer_props.getId(),
0240                      static_cast<void*>(array));
0241 }
0242 
0243 
0244 template <typename Derivate>
0245 template <typename T>
0246 inline void SliceTraits<Derivate>::read_raw(T* array, const DataTransferProps& xfer_props) const {
0247     using element_type = typename details::inspector<T>::base_type;
0248     const DataType& mem_datatype = create_and_check_datatype<element_type>();
0249 
0250     read_raw(array, mem_datatype, xfer_props);
0251 }
0252 
0253 
0254 template <typename Derivate>
0255 template <typename T>
0256 inline void SliceTraits<Derivate>::write(const T& buffer, const DataTransferProps& xfer_props) {
0257     const auto& slice = static_cast<const Derivate&>(*this);
0258     const DataSpace& mem_space = slice.getMemSpace();
0259 
0260     auto file_datatype = slice.getDataType();
0261 
0262     const details::BufferInfo<T> buffer_info(
0263         file_datatype,
0264         [&slice]() -> std::string { return details::get_dataset(slice).getPath(); },
0265         details::BufferInfo<T>::Operation::write);
0266 
0267     if (!details::checkDimensions(mem_space, buffer_info.n_dimensions)) {
0268         std::ostringstream ss;
0269         ss << "Impossible to write buffer of dimensions "
0270            << details::format_vector(mem_space.getDimensions())
0271            << " into dataset with n = " << buffer_info.n_dimensions << " dimensions.";
0272         throw DataSpaceException(ss.str());
0273     }
0274     auto w = details::data_converter::serialize<T>(buffer, file_datatype);
0275     write_raw(w.getPointer(), buffer_info.data_type, xfer_props);
0276 }
0277 
0278 
0279 template <typename Derivate>
0280 template <typename T>
0281 inline void SliceTraits<Derivate>::write_raw(const T* buffer,
0282                                              const DataType& mem_datatype,
0283                                              const DataTransferProps& xfer_props) {
0284     const auto& slice = static_cast<const Derivate&>(*this);
0285 
0286     detail::h5d_write(details::get_dataset(slice).getId(),
0287                       mem_datatype.getId(),
0288                       details::get_memspace_id(slice),
0289                       slice.getSpace().getId(),
0290                       xfer_props.getId(),
0291                       static_cast<const void*>(buffer));
0292 }
0293 
0294 
0295 template <typename Derivate>
0296 template <typename T>
0297 inline void SliceTraits<Derivate>::write_raw(const T* buffer, const DataTransferProps& xfer_props) {
0298     using element_type = typename details::inspector<T>::base_type;
0299     const auto& mem_datatype = create_and_check_datatype<element_type>();
0300 
0301     write_raw(buffer, mem_datatype, xfer_props);
0302 }
0303 
0304 
0305 }  // namespace HighFive