diff --git a/lib/lattice/Lattice_transfer.h b/lib/lattice/Lattice_transfer.h index 44f0337d..f988f310 100644 --- a/lib/lattice/Lattice_transfer.h +++ b/lib/lattice/Lattice_transfer.h @@ -599,6 +599,51 @@ unvectorizeToLexOrdArray(std::vector &out, const Lattice &in) extract1(in_vobj, out_ptrs, 0); } } + +template +typename std::enable_if::value && !isSIMDvectorized::value, void>::type +unvectorizeToRevLexOrdArray(std::vector &out, const Lattice &in) +{ + + typedef typename vobj::vector_type vtype; + + GridBase* in_grid = in._grid; + out.resize(in_grid->lSites()); + + int ndim = in_grid->Nd(); + int in_nsimd = vtype::Nsimd(); + + std::vector > in_icoor(in_nsimd); + + for(int lane=0; lane < in_nsimd; lane++){ + in_icoor[lane].resize(ndim); + in_grid->iCoorFromIindex(in_icoor[lane], lane); + } + + parallel_for(int in_oidx = 0; in_oidx < in_grid->oSites(); in_oidx++){ //loop over outer index + //Assemble vector of pointers to output elements + std::vector out_ptrs(in_nsimd); + + std::vector in_ocoor(ndim); + in_grid->oCoorFromOindex(in_ocoor, in_oidx); + + std::vector lcoor(in_grid->Nd()); + + for(int lane=0; lane < in_nsimd; lane++){ + for(int mu=0;mu_rdimensions[mu]*in_icoor[lane][mu]; + + int lex; + Lexicographic::IndexFromCoorReversed(lcoor, lex, in_grid->_ldimensions); + out_ptrs[lane] = &out[lex]; + } + + //Unpack into those ptrs + const vobj & in_vobj = in._odata[in_oidx]; + extract1(in_vobj, out_ptrs, 0); + } +} + //Copy SIMD-vectorized lattice to array of scalar objects in lexicographic order template typename std::enable_if::value @@ -648,6 +693,54 @@ vectorizeFromLexOrdArray( std::vector &in, Lattice &out) } } +template +typename std::enable_if::value + && !isSIMDvectorized::value, void>::type +vectorizeFromRevLexOrdArray( std::vector &in, Lattice &out) +{ + + typedef typename vobj::vector_type vtype; + + GridBase* grid = out._grid; + assert(in.size()==grid->lSites()); + + int ndim = grid->Nd(); + int nsimd = vtype::Nsimd(); + + std::vector > icoor(nsimd); + + for(int lane=0; lane < nsimd; lane++){ + icoor[lane].resize(ndim); + grid->iCoorFromIindex(icoor[lane],lane); + } + + parallel_for(uint64_t oidx = 0; oidx < grid->oSites(); oidx++){ //loop over outer index + //Assemble vector of pointers to output elements + std::vector ptrs(nsimd); + + std::vector ocoor(ndim); + grid->oCoorFromOindex(ocoor, oidx); + + std::vector lcoor(grid->Nd()); + + for(int lane=0; lane < nsimd; lane++){ + + for(int mu=0;mu_rdimensions[mu]*icoor[lane][mu]; + } + + int lex; + Lexicographic::IndexFromCoorReversed(lcoor, lex, grid->_ldimensions); + ptrs[lane] = &in[lex]; + } + + //pack from those ptrs + vobj vecobj; + merge1(vecobj, ptrs, 0); + out._odata[oidx] = vecobj; + } +} + //Convert a Lattice from one precision to another template void precisionChange(Lattice &out, const Lattice &in){ diff --git a/lib/serialisation/Hdf5IO.h b/lib/serialisation/Hdf5IO.h index 12625ab8..940bb11a 100644 --- a/lib/serialisation/Hdf5IO.h +++ b/lib/serialisation/Hdf5IO.h @@ -22,6 +22,8 @@ namespace Grid { + template class Lattice; + class Hdf5Writer: public Writer { public: @@ -33,6 +35,8 @@ namespace Grid template void writeDefault(const std::string &s, const U &x); template + void writeDefault(const std::string &s, const Lattice &field); + template typename std::enable_if>::is_number, void>::type writeDefault(const std::string &s, const std::vector &x); template @@ -60,6 +64,8 @@ namespace Grid template void readDefault(const std::string &s, U &output); template + void readDefault(const std::string &s, Lattice &field); + template typename std::enable_if>::is_number, void>::type readDefault(const std::string &s, std::vector &x); template @@ -98,7 +104,40 @@ namespace Grid template <> void Hdf5Writer::writeDefault(const std::string &s, const std::string &x); - + + + template + void Hdf5Writer::writeDefault(const std::string &s, const Lattice &field) + { + // alias scalar types + typedef std::vector ScalarLattice; + typedef typename U::scalar_type ScalarType; + + ScalarLattice scalField; + + unvectorizeToRevLexOrdArray(scalField, field); + + std::vector dim; + std::vector tDim; + + tensorDim(tDim, scalField[0]); + for (auto &d: field._grid->GlobalDimensions()) + { + dim.push_back(d); + } + for (auto &d: tDim) + { + dim.push_back(d); + } + + // write to file + H5NS::DataSpace dataSpace(dim.size(), dim.data()); + H5NS::DataSet dataSet; + + dataSet = group_.createDataSet(s, Hdf5Type::type(), dataSpace); + dataSet.write(scalField.data(), Hdf5Type::type()); + } + template typename std::enable_if>::is_number, void>::type Hdf5Writer::writeDefault(const std::string &s, const std::vector &x) @@ -169,6 +208,29 @@ namespace Grid template <> void Hdf5Reader::readDefault(const std::string &s, std::string &x); + template + void Hdf5Reader::readDefault(const std::string &s, Lattice &field) + { + // alias scalar types + typedef std::vector ScalarLattice; + typedef typename U::scalar_type ScalarType; + + ScalarLattice scalField; + H5NS::DataSet dataSet; + std::vector dim; + hsize_t size = 1; + + dataSet = group_.openDataSet(s); + for (auto &d: field._grid->GlobalDimensions()) + { + dim.push_back(d); + size *= d; + } + scalField.resize(size); + dataSet.read(scalField.data(), Hdf5Type::type()); + vectorizeFromRevLexOrdArray(scalField, field); + } + template typename std::enable_if>::is_number, void>::type Hdf5Reader::readDefault(const std::string &s, std::vector &x) diff --git a/lib/serialisation/VectorUtils.h b/lib/serialisation/VectorUtils.h index 6df9416d..e1095488 100644 --- a/lib/serialisation/VectorUtils.h +++ b/lib/serialisation/VectorUtils.h @@ -2,7 +2,7 @@ #define GRID_SERIALISATION_VECTORUTILS_H #include -#include +#include namespace Grid { // Pair IO utilities ///////////////////////////////////////////////////////// @@ -78,6 +78,48 @@ namespace Grid { typedef typename std::vector::type>> type; }; + template + void tensorDim(std::vector &dim, const T &t, const bool wipe = true) + { + if (wipe) + { + dim.clear(); + } + } + + template + void tensorDim(std::vector &dim, const iScalar &t, const bool wipe = true) + { + if (wipe) + { + dim.clear(); + } + tensorDim(dim, t._internal, false); + } + + template + void tensorDim(std::vector &dim, const iVector &t, const bool wipe = true) + { + if (wipe) + { + dim.clear(); + } + dim.push_back(N); + tensorDim(dim, t._internal[0], false); + } + + template + void tensorDim(std::vector &dim, const iMatrix &t, const bool wipe = true) + { + if (wipe) + { + dim.clear(); + } + dim.push_back(N); + dim.push_back(N); + tensorDim(dim, t._internal[0][0], false); + } + template typename TensorToVec::type tensorToVec(const T &t) {