diff --git a/Grid/serialisation/BaseIO.h b/Grid/serialisation/BaseIO.h index a6746864..86dc1113 100644 --- a/Grid/serialisation/BaseIO.h +++ b/Grid/serialisation/BaseIO.h @@ -172,7 +172,7 @@ namespace Grid { template typename std::enable_if::value, void>::type for_all_do_lambda( Lambda lambda, typename ETensor::Scalar &scalar, typename ETensor::Index &Seq, - std::array::rank_non_trivial> &MyIndex) + std::array::rank> &MyIndex) { lambda( scalar, Seq++, MyIndex ); } @@ -180,8 +180,8 @@ namespace Grid { // for_all helper function to call the lambda template typename std::enable_if::value, void>::type - for_all_do_lambda( Lambda lambda, typename ETensor::Scalar &scalar, typename ETensor::Index Seq, - std::array::rank_non_trivial> &MyIndex) + for_all_do_lambda( Lambda lambda, typename ETensor::Scalar &scalar, typename ETensor::Index &Seq, + std::array::rank> &MyIndex) { using Scalar = typename ETensor::Scalar; // This could be a Container - we'll check later const auto InnerRank = EigenIO::Traits::rank_non_trivial; @@ -190,7 +190,7 @@ namespace Grid { lambda(Source, Seq++, MyIndex ); // Now increment SubIndex for( auto i = InnerRank - 1; i != -1 && ++MyIndex[rank + i] == EigenIO::Traits::DimensionNT(i); i-- ) - MyIndex[i] = 0; + MyIndex[rank + i] = 0; } } @@ -206,7 +206,7 @@ namespace Grid { assert( NumScalars > 0 ); using Index = typename ETensor::Index; Index ScalarElementCount{1}; - const auto InnerRank = EigenIO::Traits::rank_non_trivial; + const auto InnerRank = EigenIO::Traits::rank; const auto rank{ETensor::NumIndices}; std::array Dims; for(auto i = 0; i < rank; i++ ) { @@ -218,11 +218,11 @@ namespace Grid { } // Check that the number of containers is correct ... and we didn't lose anything in conversions assert( NumScalars == ScalarElementCount ); - // If the Scalar is actually a container, add the inner Scalar's non-trivial dimensions + // If the Scalar is actually a container, add the inner Scalar's dimensions size_t InnerScalarCount{1}; for(auto i = 0; i < InnerRank; i++ ) { - auto dim = EigenIO::Traits::DimensionNT(i); - assert( dim > 1 ); + auto dim = EigenIO::Traits::Dimension(i); + assert( dim > 0 ); Dims[rank + i] = static_cast(dim); assert( Dims[rank + i] == dim ); // check we didn't lose anything in the conversion InnerScalarCount *= dim; @@ -242,11 +242,12 @@ namespace Grid { } else { for( auto i = 0; i < rank && ++MyIndex[i] == Dims[i]; i++ ) MyIndex[i] = 0; - Seq = 0; + size_t NewSeq = 0; for( auto i = 0; i < rank + InnerRank ; i++ ) { - Seq *= Dims[i]; - Seq += MyIndex[i]; + NewSeq *= Dims[i]; + NewSeq += MyIndex[i]; } + Seq = static_cast( NewSeq ); } pScalar++; } @@ -271,7 +272,7 @@ namespace Grid { { using Traits = EigenIO::Traits; using scalar_type = typename Traits::scalar_type; - for_all( ET, [&](scalar_type &c, typename ETensor::Index n, const std::array &Dims ) { + for_all( ET, [&](scalar_type &c, typename ETensor::Index n, const std::array &Dims ) { c = Inc * static_cast::type>(n); } ); } @@ -291,7 +292,7 @@ namespace Grid { std::cout << pName; for( auto i = 0 ; i < rank; i++ ) std::cout << "[" << dims[i] << "]"; std::cout << " in memory order:" << std::endl; - for_all( t, [&](typename Traits::scalar_type &c, typename T::Index index, const std::array &Dims ){ + for_all( t, [&](typename Traits::scalar_type &c, typename T::Index index, const std::array &Dims ){ std::cout << " "; for( auto dim : Dims ) std::cout << "[" << dim << "]"; diff --git a/Grid/serialisation/XmlIO.h b/Grid/serialisation/XmlIO.h index a26a33c5..38958ba0 100644 --- a/Grid/serialisation/XmlIO.h +++ b/Grid/serialisation/XmlIO.h @@ -57,6 +57,8 @@ namespace Grid void writeDefault(const std::string &s, const U &x); template void writeDefault(const std::string &s, const std::vector &x); + template + void writeMultiDim(const std::string &s, const std::vector & Dimensions, const U * pDataRowMajor, size_t NumElements); std::string docString(void); std::string string(void); private: @@ -79,6 +81,8 @@ namespace Grid void readDefault(const std::string &s, U &output); template void readDefault(const std::string &s, std::vector &output); + template + void readMultiDim(const std::string &s, std::vector &buf, std::vector &dim); void readCurrentSubtree(std::string &s); private: void checkParse(const pugi::xml_parse_result &result, const std::string name); @@ -120,15 +124,28 @@ namespace Grid template void XmlWriter::writeDefault(const std::string &s, const std::vector &x) + { + std::vector dims(1); + dims[0] = x.size(); + writeMultiDim(s, dims, &x[0], dims[0]); + } + + template + void XmlWriter::writeMultiDim(const std::string &s, const std::vector & Dimensions, const U * pDataRowMajor, size_t NumElements) { push(s); - for (auto &x_i: x) + if( Dimensions.size() > 1 ) { - write("elem", x_i); + for( auto d : Dimensions ) + write("dim", d); + } + while (NumElements--) + { + write("elem", *pDataRowMajor++); } pop(); } - + // Reader template implementation //////////////////////////////////////////// template void XmlReader::readDefault(const std::string &s, U &output) @@ -145,25 +162,39 @@ namespace Grid template void XmlReader::readDefault(const std::string &s, std::vector &output) { - std::string buf; - unsigned int i = 0; - + std::vector dims; + readMultiDim(s, output, dims); + assert( dims.size() == 1 && dims[0] == output.size() && "XmlIO: Expected 1D vector" ); + } + + template + void XmlReader::readMultiDim(const std::string &s, std::vector &buf, std::vector &dim) + { + unsigned int i = 0; + unsigned int Rank = 0; if (!push(s)) { std::cout << GridLogWarning << "XML: cannot open node '" << s << "'"; std::cout << std::endl; - - return; + } else { + while (node_.child("dim")) + { + dim.resize(Rank + 1); + read("dim", dim[Rank]); + node_.child("dim").set_name("dim-done"); + Rank++; + } + while (node_.child("elem")) + { + buf.resize(i + 1); + read("elem", buf[i]); + node_.child("elem").set_name("elem-done"); + i++; + } + pop(); + if( Rank == 0 ) + dim.push_back(i); } - while (node_.child("elem")) - { - output.resize(i + 1); - read("elem", output[i]); - node_.child("elem").set_name("elem-done"); - i++; - } - pop(); } - } #endif diff --git a/tests/IO/Test_serialisation.cc b/tests/IO/Test_serialisation.cc index f14d118e..305de088 100644 --- a/tests/IO/Test_serialisation.cc +++ b/tests/IO/Test_serialisation.cc @@ -86,7 +86,7 @@ void ioTest(const std::string &filename, const O &object, const std::string &nam // writer needs to be destroyed so that writing physically happens { W writer(filename); - + writer.setPrecision(std::numeric_limits::digits10 + 1); write(writer, tag , object); } @@ -141,14 +141,14 @@ public: , tensorRank3(7,3,2) , atensor_9_4_2(3) { - Grid_complex Flag{1,-3.1415927}; + //Grid_complex Flag{1,-3.1415927}; // Gives errors on readback for text types + Grid_complex Flag{1,-1}; SequentialInit(Perambulator, Flag); SequentialInit(Perambulator2, Flag); SequentialInit(tensorRank5UShort); SequentialInit(tensorRank3, Flag); SequentialInit(tensor_9_4_2, Flag); - for( auto &t : atensor_9_4_2 ) - SequentialInit(t, Flag); + for( auto &t : atensor_9_4_2 ) SequentialInit(t, Flag); SequentialInit( MyLSCTensor ); } }; @@ -295,6 +295,8 @@ int main(int argc,char **argv) std::cout << "\n==== detailed Hdf5 tensor tests (Grid::EigenIO)" << std::endl; EigenHdf5IOTest(".h5"); #endif + std::cout << "\n==== detailed xml tensor tests (Grid::EigenIO)" << std::endl; + EigenHdf5IOTest(".xml"); std::cout << "\n==== detailed binary tensor tests (Grid::EigenIO)" << std::endl; EigenHdf5IOTest(".bin");