diff --git a/Grid/serialisation/Hdf5IO.h b/Grid/serialisation/Hdf5IO.h index 19537599..ed09bc5c 100644 --- a/Grid/serialisation/Hdf5IO.h +++ b/Grid/serialisation/Hdf5IO.h @@ -34,11 +34,13 @@ namespace Grid template void writeDefault(const std::string &s, const U &x); template + void writeRagged(const std::string &s, const std::vector &x); + template typename std::enable_if>::is_number, void>::type writeDefault(const std::string &s, const std::vector &x); template typename std::enable_if>::is_number, void>::type - writeDefault(const std::string &s, const std::vector &x); + writeDefault(const std::string &s, const std::vector &x) { writeRagged(s, x); } template void writeMultiDim(const std::string &s, const std::vector & Dimensions, const U * pDataRowMajor, size_t NumElements); H5NS::Group & getGroup(void); @@ -64,11 +66,13 @@ namespace Grid template void readDefault(const std::string &s, U &output); template + void readRagged(const std::string &s, std::vector &x); + template typename std::enable_if>::is_number, void>::type readDefault(const std::string &s, std::vector &x); template typename std::enable_if>::is_number, void>::type - readDefault(const std::string &s, std::vector &x); + readDefault(const std::string &s, std::vector &x) { readRagged(s, x); } template void readMultiDim(const std::string &s, std::vector &buf, std::vector &dim); H5NS::Group & getGroup(void); @@ -179,21 +183,27 @@ namespace Grid typename std::enable_if>::is_number, void>::type Hdf5Writer::writeDefault(const std::string &s, const std::vector &x) { - // alias to element type - typedef typename element>::type Element; - - // flatten the vector and getting dimensions - Flatten> flat(x); - std::vector dim; - const auto &flatx = flat.getFlatVector(); - for (auto &d: flat.getDim()) - dim.push_back(d); - writeMultiDim(s, dim, &flatx[0], flatx.size()); + if (isFlat(x)) + { + // alias to element type + typedef typename element>::type Element; + + // flatten the vector and getting dimensions + Flatten> flat(x); + std::vector dim; + const auto &flatx = flat.getFlatVector(); + for (auto &d: flat.getDim()) + dim.push_back(d); + writeMultiDim(s, dim, &flatx[0], flatx.size()); + } + else + { + writeRagged(s, x); + } } template - typename std::enable_if>::is_number, void>::type - Hdf5Writer::writeDefault(const std::string &s, const std::vector &x) + void Hdf5Writer::writeRagged(const std::string &s, const std::vector &x) { push(s); writeSingleAttribute(x.size(), HDF5_GRID_GUARD "vector_size", @@ -275,22 +285,39 @@ namespace Grid typename std::enable_if>::is_number, void>::type Hdf5Reader::readDefault(const std::string &s, std::vector &x) { - // alias to element type - typedef typename element>::type Element; + bool bRagged{ false }; + H5E_auto2_t h5at; + void * f5at_p; + ::H5::Exception::getAutoPrint(h5at, &f5at_p); + ::H5::Exception::dontPrint(); + try { + push(s); + bRagged = group_.attrExists(HDF5_GRID_GUARD "vector_size"); + pop(); + } catch(...) {} + ::H5::Exception::setAutoPrint(h5at, f5at_p); + if (bRagged) + { + readRagged(s, x); + } + else + { + // alias to element type + typedef typename element>::type Element; - std::vector dim; - std::vector buf; - readMultiDim( s, buf, dim ); + std::vector dim; + std::vector buf; + readMultiDim( s, buf, dim ); - // reconstruct the multidimensional vector - Reconstruct> r(buf, dim); - - x = r.getVector(); + // reconstruct the multidimensional vector + Reconstruct> r(buf, dim); + + x = r.getVector(); + } } template - typename std::enable_if>::is_number, void>::type - Hdf5Reader::readDefault(const std::string &s, std::vector &x) + void Hdf5Reader::readRagged(const std::string &s, std::vector &x) { uint64_t size; diff --git a/Grid/serialisation/VectorUtils.h b/Grid/serialisation/VectorUtils.h index dd5ff0b8..3327b4f0 100644 --- a/Grid/serialisation/VectorUtils.h +++ b/Grid/serialisation/VectorUtils.h @@ -459,6 +459,25 @@ namespace Grid { return os; } + + // In general, scalar types are considered "flat" (regularly shaped) + template + bool isFlat(const T &t) { return true; } + + // Return non-zero if all dimensions of this std::vector> are regularly shaped + template + bool isFlat(const std::vector> &v) + { + // Make sure all of my rows are the same size + for (std::size_t i = 1; i < v.size(); ++i) + { + if (v[i].size() != v[0].size() || !isFlat(v[i])) + { + return false; + } + } + return true; + } } // helper function to read space-separated values