mirror of
https://github.com/paboyle/Grid.git
synced 2025-06-18 15:57:05 +01:00
Merge branch 'develop' of https://github.com/paboyle/Grid into develop
This commit is contained in:
@ -42,6 +42,7 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
|
||||
#include <Grid/GridQCDcore.h>
|
||||
#include <Grid/qcd/action/Action.h>
|
||||
#include <Grid/qcd/utils/GaugeFix.h>
|
||||
#include <Grid/qcd/utils/CovariantSmearing.h>
|
||||
#include <Grid/qcd/smearing/Smearing.h>
|
||||
#include <Grid/parallelIO/MetaData.h>
|
||||
#include <Grid/qcd/hmc/HMC_aggregate.h>
|
||||
|
@ -619,6 +619,7 @@ PARALLEL_CRITICAL
|
||||
{
|
||||
std::cout << GridLogMessage << "writeLatticeObject: read test checksum failure, re-writing (" << attemptsLeft << " attempt(s) remaining)" << std::endl;
|
||||
offset = offsetCopy;
|
||||
parallel_for(uint64_t x=0;x<lsites;x++) munge(scalardata[x],iodata[x]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -47,8 +47,10 @@ namespace Grid {
|
||||
namespace QCD {
|
||||
|
||||
#define GRID_FIELD_NORM "FieldNormMetaData"
|
||||
#define GRID_FIELD_NORM_CHECK(FieldNormMetaData_,n2ck) \
|
||||
assert(0.5*fabs(FieldNormMetaData_.norm2 - n2ck)/(FieldNormMetaData_.norm2 + n2ck) < 1.0e-5 );
|
||||
#define GRID_FIELD_NORM_CALC(FieldNormMetaData_, n2ck) \
|
||||
0.5*fabs(FieldNormMetaData_.norm2 - n2ck)/(FieldNormMetaData_.norm2 + n2ck)
|
||||
#define GRID_FIELD_NORM_CHECK(FieldNormMetaData_, n2ck) \
|
||||
assert(GRID_FIELD_NORM_CALC(FieldNormMetaData_, n2ck) < 1.0e-5);
|
||||
|
||||
/////////////////////////////////
|
||||
// Encode word types as strings
|
||||
@ -249,9 +251,9 @@ class GridLimeReader : public BinaryIO {
|
||||
/////////////////////////////////////////////
|
||||
if(FieldNormMetaData_.norm2 != 0.0){
|
||||
RealD n2ck = norm2(field);
|
||||
std::cout << GridLogMessage << "Field norm: metadata= "<<FieldNormMetaData_.norm2<< " / field= " << n2ck<<std::endl;
|
||||
std::cout << GridLogMessage << "Field norm: metadata= " << FieldNormMetaData_.norm2
|
||||
<< " / field= " << n2ck << " / rdiff= " << GRID_FIELD_NORM_CALC(FieldNormMetaData_,n2ck) << std::endl;
|
||||
GRID_FIELD_NORM_CHECK(FieldNormMetaData_,n2ck);
|
||||
std::cout << GridLogMessage << "FieldNormMetaData OK! "<<std::endl;
|
||||
}
|
||||
assert(scidacChecksumVerify(scidacChecksum_,scidac_csuma,scidac_csumb)==1);
|
||||
|
||||
|
@ -53,7 +53,7 @@ namespace Grid {
|
||||
ComplexField coor(in._grid);
|
||||
ComplexField ph(in._grid); ph = zero;
|
||||
FermionField in_buf(in._grid); in_buf = zero;
|
||||
Complex ci(0.0,1.0);
|
||||
Scalar ci(0.0,1.0);
|
||||
assert(twist.size() == Nd);//check that twist is Nd
|
||||
int shift = 0;
|
||||
if(fiveD) shift = 1;
|
||||
@ -63,7 +63,7 @@ namespace Grid {
|
||||
LatticeCoordinate(coor, nu + shift);
|
||||
ph = ph + twist[nu]*coor*((1./(in._grid->_fdimensions[nu+shift])));
|
||||
}
|
||||
in_buf = exp((Real)(2.0*M_PI)*ci*ph*(-1.0))*in;
|
||||
in_buf = exp(Scalar(2.0*M_PI)*ci*ph*(-1.0))*in;
|
||||
|
||||
if(fiveD){//FFT only on temporal and spatial dimensions
|
||||
std::vector<int> mask(Nd+1,1); mask[0] = 0;
|
||||
@ -78,7 +78,7 @@ namespace Grid {
|
||||
}
|
||||
|
||||
//phase for boundary condition
|
||||
out = out * exp((Real)(2.0*M_PI)*ci*ph);
|
||||
out = out * exp(Scalar(2.0*M_PI)*ci*ph);
|
||||
};
|
||||
|
||||
virtual void FreePropagator(const FermionField &in,FermionField &out,RealD mass,std::vector<double> twist) {
|
||||
|
@ -106,21 +106,21 @@ namespace Grid {
|
||||
ComplexField coor(in._grid);
|
||||
ComplexField ph(in._grid); ph = zero;
|
||||
FermionField in_buf(in._grid); in_buf = zero;
|
||||
Complex ci(0.0,1.0);
|
||||
Scalar ci(0.0,1.0);
|
||||
assert(twist.size() == Nd);//check that twist is Nd
|
||||
for(unsigned int nu = 0; nu < Nd; nu++)
|
||||
{
|
||||
LatticeCoordinate(coor, nu);
|
||||
ph = ph + twist[nu]*coor*((1./(in._grid->_fdimensions[nu])));
|
||||
}
|
||||
in_buf = exp((Real)(2.0*M_PI)*ci*ph*(-1.0))*in;
|
||||
in_buf = exp(Scalar(-2.0*M_PI)*ci*ph)*in;
|
||||
|
||||
theFFT.FFT_all_dim(in_k,in_buf,FFT::forward);
|
||||
this->MomentumSpacePropagator(prop_k,in_k,mass,twist);
|
||||
theFFT.FFT_all_dim(out,prop_k,FFT::backward);
|
||||
|
||||
//phase for boundary condition
|
||||
out = out * exp((Real)(2.0*M_PI)*ci*ph);
|
||||
out = out * exp(Scalar(2.0*M_PI)*ci*ph);
|
||||
|
||||
};
|
||||
virtual void FreePropagator(const FermionField &in,FermionField &out,RealD mass) {
|
||||
|
@ -46,6 +46,7 @@ namespace QCD {
|
||||
|
||||
#define INHERIT_GIMPL_TYPES(GImpl) \
|
||||
typedef typename GImpl::Simd Simd; \
|
||||
typedef typename GImpl::Scalar Scalar; \
|
||||
typedef typename GImpl::LinkField GaugeLinkField; \
|
||||
typedef typename GImpl::Field GaugeField; \
|
||||
typedef typename GImpl::ComplexField ComplexField;\
|
||||
@ -63,7 +64,8 @@ namespace QCD {
|
||||
template <class S, int Nrepresentation = Nc, int Nexp = 12 > class GaugeImplTypes {
|
||||
public:
|
||||
typedef S Simd;
|
||||
|
||||
typedef typename Simd::scalar_type scalar_type;
|
||||
typedef scalar_type Scalar;
|
||||
template <typename vtype> using iImplScalar = iScalar<iScalar<iScalar<vtype> > >;
|
||||
template <typename vtype> using iImplGaugeLink = iScalar<iScalar<iMatrix<vtype, Nrepresentation> > >;
|
||||
template <typename vtype> using iImplGaugeField = iVector<iScalar<iMatrix<vtype, Nrepresentation> >, Nd>;
|
||||
|
@ -38,6 +38,7 @@ namespace QCD{
|
||||
{
|
||||
public:
|
||||
typedef S Simd;
|
||||
typedef typename Simd::scalar_type Scalar;
|
||||
|
||||
template <typename vtype>
|
||||
using iImplGaugeLink = iScalar<iScalar<iScalar<vtype>>>;
|
||||
|
87
Grid/qcd/utils/CovariantSmearing.h
Normal file
87
Grid/qcd/utils/CovariantSmearing.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./lib/qcd/action/scalar/CovariantLaplacian.h
|
||||
|
||||
Copyright (C) 2016
|
||||
|
||||
Author: Azusa Yamaguchi
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution
|
||||
directory
|
||||
*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
namespace Grid {
|
||||
namespace QCD {
|
||||
|
||||
template <class Gimpl> class CovariantSmearing : public Gimpl
|
||||
{
|
||||
public:
|
||||
INHERIT_GIMPL_TYPES(Gimpl);
|
||||
|
||||
typedef typename Gimpl::GaugeLinkField GaugeMat;
|
||||
typedef typename Gimpl::GaugeField GaugeLorentz;
|
||||
|
||||
template<typename T>
|
||||
static void GaussianSmear(const std::vector<LatticeColourMatrix>& U,
|
||||
T& chi,
|
||||
const Real& width, int Iterations, int orthog)
|
||||
{
|
||||
GridBase *grid = chi._grid;
|
||||
T psi(grid);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Follow Chroma conventions for width to keep compatibility with previous data
|
||||
// Free field iterates
|
||||
// chi = (1 - w^2/4N p^2)^N chi
|
||||
//
|
||||
// ~ (e^(-w^2/4N p^2)^N chi
|
||||
// ~ (e^(-w^2/4 p^2) chi
|
||||
// ~ (e^(-w'^2/2 p^2) chi [ w' = w/sqrt(2) ]
|
||||
//
|
||||
// Which in coordinate space is proportional to
|
||||
//
|
||||
// e^(-x^2/w^2) = e^(-x^2/2w'^2)
|
||||
//
|
||||
// The 4 is a bit unconventional from Gaussian width perspective, but... it's Chroma convention.
|
||||
// 2nd derivative approx d^2/dx^2 = x+mu + x-mu - 2x
|
||||
//
|
||||
// d^2/dx^2 = - p^2
|
||||
//
|
||||
// chi = ( 1 + w^2/4N d^2/dx^2 )^N chi
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
Real coeff = (width*width) / Real(4*Iterations);
|
||||
|
||||
int dims = Nd;
|
||||
if( orthog < Nd ) dims=Nd-1;
|
||||
|
||||
for(int n = 0; n < Iterations; ++n) {
|
||||
psi = (-2.0*dims)*chi;
|
||||
for(int mu=0;mu<Nd;mu++) {
|
||||
if ( mu != orthog ) {
|
||||
psi = psi + Gimpl::CovShiftForward(U[mu],mu,chi);
|
||||
psi = psi + Gimpl::CovShiftBackward(U[mu],mu,chi);
|
||||
}
|
||||
}
|
||||
chi = chi + coeff*psi;
|
||||
}
|
||||
}
|
||||
};
|
||||
}}
|
@ -33,12 +33,76 @@ Author: Guido Cossu <guido.cossu@ed.ac.uk>
|
||||
#include <type_traits>
|
||||
#include <Grid/tensors/Tensors.h>
|
||||
#include <Grid/serialisation/VectorUtils.h>
|
||||
#include <Grid/Eigen/unsupported/CXX11/Tensor>
|
||||
|
||||
namespace Grid {
|
||||
namespace EigenIO {
|
||||
// EigenIO works for scalars that are not just Grid supported scalars
|
||||
template<typename T, typename V = void> struct is_complex : public std::false_type {};
|
||||
// Support all complex types (not just Grid complex types) - even if the definitions overlap (!)
|
||||
template<typename T> struct is_complex< T , typename
|
||||
std::enable_if< ::Grid::is_complex< T >::value>::type> : public std::true_type {};
|
||||
template<typename T> struct is_complex<std::complex<T>, typename
|
||||
std::enable_if<!::Grid::is_complex<std::complex<T>>::value>::type> : public std::true_type {};
|
||||
|
||||
// Helpers to support I/O for Eigen tensors of arithmetic scalars, complex types, or Grid tensors
|
||||
template<typename T, typename V = void> struct is_scalar : public std::false_type {};
|
||||
template<typename T> struct is_scalar<T, typename std::enable_if<std::is_arithmetic<T>::value || is_complex<T>::value>::type> : public std::true_type {};
|
||||
|
||||
// Is this an Eigen tensor
|
||||
template<typename T> struct is_tensor : std::integral_constant<bool,
|
||||
std::is_base_of<Eigen::TensorBase<T, Eigen::ReadOnlyAccessors>, T>::value> {};
|
||||
|
||||
// Is this an Eigen tensor of a supported scalar
|
||||
template<typename T, typename V = void> struct is_tensor_of_scalar : public std::false_type {};
|
||||
template<typename T> struct is_tensor_of_scalar<T, typename std::enable_if<is_tensor<T>::value && is_scalar<typename T::Scalar>::value>::type> : public std::true_type {};
|
||||
|
||||
// Is this an Eigen tensor of a supported container
|
||||
template<typename T, typename V = void> struct is_tensor_of_container : public std::false_type {};
|
||||
template<typename T> struct is_tensor_of_container<T, typename std::enable_if<is_tensor<T>::value && isGridTensor<typename T::Scalar>::value>::type> : public std::true_type {};
|
||||
|
||||
// These traits describe the scalars inside Eigen tensors
|
||||
// I wish I could define these in reference to the scalar type (so there would be fewer traits defined)
|
||||
// but I'm unable to find a syntax to make this work
|
||||
template<typename T, typename V = void> struct Traits {};
|
||||
// Traits are the default for scalars, or come from GridTypeMapper for GridTensors
|
||||
template<typename T> struct Traits<T, typename std::enable_if<is_tensor_of_scalar<T>::value>::type>
|
||||
: public GridTypeMapper_Base {
|
||||
using scalar_type = typename T::Scalar; // ultimate base scalar
|
||||
static constexpr bool is_complex = ::Grid::EigenIO::is_complex<scalar_type>::value;
|
||||
};
|
||||
// Traits are the default for scalars, or come from GridTypeMapper for GridTensors
|
||||
template<typename T> struct Traits<T, typename std::enable_if<is_tensor_of_container<T>::value>::type> {
|
||||
using BaseTraits = GridTypeMapper<typename T::Scalar>;
|
||||
using scalar_type = typename BaseTraits::scalar_type; // ultimate base scalar
|
||||
static constexpr bool is_complex = ::Grid::EigenIO::is_complex<scalar_type>::value;
|
||||
static constexpr int TensorLevel = BaseTraits::TensorLevel;
|
||||
static constexpr int Rank = BaseTraits::Rank;
|
||||
static constexpr std::size_t count = BaseTraits::count;
|
||||
static constexpr int Dimension(int dim) { return BaseTraits::Dimension(dim); }
|
||||
};
|
||||
|
||||
// Is this a fixed-size Eigen tensor
|
||||
template<typename T> struct is_tensor_fixed : public std::false_type {};
|
||||
template<typename Scalar_, typename Dimensions_, int Options_, typename IndexType>
|
||||
struct is_tensor_fixed<Eigen::TensorFixedSize<Scalar_, Dimensions_, Options_, IndexType>>
|
||||
: public std::true_type {};
|
||||
template<typename Scalar_, typename Dimensions_, int Options_, typename IndexType,
|
||||
int MapOptions_, template <class> class MapPointer_>
|
||||
struct is_tensor_fixed<Eigen::TensorMap<Eigen::TensorFixedSize<Scalar_, Dimensions_,
|
||||
Options_, IndexType>, MapOptions_, MapPointer_>>
|
||||
: public std::true_type {};
|
||||
|
||||
// Is this a variable-size Eigen tensor
|
||||
template<typename T, typename V = void> struct is_tensor_variable : public std::false_type {};
|
||||
template<typename T> struct is_tensor_variable<T, typename std::enable_if<is_tensor<T>::value
|
||||
&& !is_tensor_fixed<T>::value>::type> : public std::true_type {};
|
||||
}
|
||||
|
||||
// Abstract writer/reader classes ////////////////////////////////////////////
|
||||
// static polymorphism implemented using CRTP idiom
|
||||
class Serializable;
|
||||
|
||||
|
||||
// Static abstract writer
|
||||
template <typename T>
|
||||
class Writer
|
||||
@ -49,10 +113,10 @@ namespace Grid {
|
||||
void push(const std::string &s);
|
||||
void pop(void);
|
||||
template <typename U>
|
||||
typename std::enable_if<std::is_base_of<Serializable, U>::value, void>::type
|
||||
typename std::enable_if<std::is_base_of<Serializable, U>::value>::type
|
||||
write(const std::string& s, const U &output);
|
||||
template <typename U>
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value && !EigenIO::is_tensor<U>::value>::type
|
||||
write(const std::string& s, const U &output);
|
||||
template <typename U>
|
||||
void write(const std::string &s, const iScalar<U> &output);
|
||||
@ -60,6 +124,42 @@ namespace Grid {
|
||||
void write(const std::string &s, const iVector<U, N> &output);
|
||||
template <typename U, int N>
|
||||
void write(const std::string &s, const iMatrix<U, N> &output);
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor<ETensor>::value>::type
|
||||
write(const std::string &s, const ETensor &output);
|
||||
|
||||
// Helper functions for Scalar vs Container specialisations
|
||||
template <typename ETensor>
|
||||
inline typename std::enable_if<EigenIO::is_tensor_of_scalar<ETensor>::value,
|
||||
const typename ETensor::Scalar *>::type
|
||||
getFirstScalar(const ETensor &output)
|
||||
{
|
||||
return output.data();
|
||||
}
|
||||
|
||||
template <typename ETensor>
|
||||
inline typename std::enable_if<EigenIO::is_tensor_of_container<ETensor>::value,
|
||||
const typename EigenIO::Traits<ETensor>::scalar_type *>::type
|
||||
getFirstScalar(const ETensor &output)
|
||||
{
|
||||
return output.data()->begin();
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
inline typename std::enable_if<EigenIO::is_scalar<S>::value, void>::type
|
||||
copyScalars(S * &pCopy, const S &Source)
|
||||
{
|
||||
* pCopy ++ = Source;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
inline typename std::enable_if<isGridTensor<S>::value, void>::type
|
||||
copyScalars(typename GridTypeMapper<S>::scalar_type * &pCopy, const S &Source)
|
||||
{
|
||||
for( const typename GridTypeMapper<S>::scalar_type &item : Source )
|
||||
* pCopy ++ = item;
|
||||
}
|
||||
|
||||
void scientificFormat(const bool set);
|
||||
bool isScientific(void);
|
||||
void setPrecision(const unsigned int prec);
|
||||
@ -83,7 +183,8 @@ namespace Grid {
|
||||
typename std::enable_if<std::is_base_of<Serializable, U>::value, void>::type
|
||||
read(const std::string& s, U &output);
|
||||
template <typename U>
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value
|
||||
&& !EigenIO::is_tensor<U>::value, void>::type
|
||||
read(const std::string& s, U &output);
|
||||
template <typename U>
|
||||
void read(const std::string &s, iScalar<U> &output);
|
||||
@ -91,6 +192,32 @@ namespace Grid {
|
||||
void read(const std::string &s, iVector<U, N> &output);
|
||||
template <typename U, int N>
|
||||
void read(const std::string &s, iMatrix<U, N> &output);
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor<ETensor>::value, void>::type
|
||||
read(const std::string &s, ETensor &output);
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor_fixed<ETensor>::value, void>::type
|
||||
Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims );
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor_variable<ETensor>::value, void>::type
|
||||
Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims );
|
||||
|
||||
// Helper functions for Scalar vs Container specialisations
|
||||
template <typename S>
|
||||
inline typename std::enable_if<EigenIO::is_scalar<S>::value, void>::type
|
||||
copyScalars(S &Dest, const S * &pSource)
|
||||
{
|
||||
Dest = * pSource ++;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
inline typename std::enable_if<isGridTensor<S>::value, void>::type
|
||||
copyScalars(S &Dest, const typename GridTypeMapper<S>::scalar_type * &pSource)
|
||||
{
|
||||
for( typename GridTypeMapper<S>::scalar_type &item : Dest )
|
||||
item = * pSource ++;
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename U>
|
||||
void fromString(U &output, const std::string &s);
|
||||
@ -135,12 +262,14 @@ namespace Grid {
|
||||
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value
|
||||
&& !EigenIO::is_tensor<U>::value, void>::type
|
||||
Writer<T>::write(const std::string &s, const U &output)
|
||||
{
|
||||
upcast->writeDefault(s, output);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
void Writer<T>::write(const std::string &s, const iScalar<U> &output)
|
||||
@ -161,6 +290,57 @@ namespace Grid {
|
||||
{
|
||||
upcast->writeDefault(s, tensorToVec(output));
|
||||
}
|
||||
|
||||
// Eigen::Tensors of Grid tensors (iScalar, iVector, iMatrix)
|
||||
template <typename T>
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor<ETensor>::value, void>::type
|
||||
Writer<T>::write(const std::string &s, const ETensor &output)
|
||||
{
|
||||
using Index = typename ETensor::Index;
|
||||
using Container = typename ETensor::Scalar; // NB: could be same as scalar
|
||||
using Traits = EigenIO::Traits<ETensor>;
|
||||
using Scalar = typename Traits::scalar_type; // type of the underlying scalar
|
||||
constexpr unsigned int TensorRank{ETensor::NumIndices};
|
||||
constexpr unsigned int ContainerRank{Traits::Rank}; // Only non-zero for containers
|
||||
constexpr unsigned int TotalRank{TensorRank + ContainerRank};
|
||||
const Index NumElements{output.size()};
|
||||
assert( NumElements > 0 );
|
||||
|
||||
// Get the dimensionality of the tensor
|
||||
std::vector<std::size_t> TotalDims(TotalRank);
|
||||
for(auto i = 0; i < TensorRank; i++ ) {
|
||||
auto dim = output.dimension(i);
|
||||
TotalDims[i] = static_cast<size_t>(dim);
|
||||
assert( TotalDims[i] == dim ); // check we didn't lose anything in the conversion
|
||||
}
|
||||
for(auto i = 0; i < ContainerRank; i++ )
|
||||
TotalDims[TensorRank + i] = Traits::Dimension(i);
|
||||
|
||||
// If the Tensor isn't in Row-Major order, then we'll need to copy it's data
|
||||
const bool CopyData{NumElements > 1 && ETensor::Layout != Eigen::StorageOptions::RowMajor};
|
||||
const Scalar * pWriteBuffer;
|
||||
std::vector<Scalar> CopyBuffer;
|
||||
const Index TotalNumElements = NumElements * Traits::count;
|
||||
if( !CopyData ) {
|
||||
pWriteBuffer = getFirstScalar( output );
|
||||
} else {
|
||||
// Regardless of the Eigen::Tensor storage order, the copy will be Row Major
|
||||
CopyBuffer.resize( TotalNumElements );
|
||||
Scalar * pCopy = &CopyBuffer[0];
|
||||
pWriteBuffer = pCopy;
|
||||
std::array<Index, TensorRank> MyIndex;
|
||||
for( auto &idx : MyIndex ) idx = 0;
|
||||
for( auto n = 0; n < NumElements; n++ ) {
|
||||
const Container & c = output( MyIndex );
|
||||
copyScalars( pCopy, c );
|
||||
// Now increment the index
|
||||
for( int i = output.NumDimensions - 1; i >= 0 && ++MyIndex[i] == output.dimension(i); i-- )
|
||||
MyIndex[i] = 0;
|
||||
}
|
||||
}
|
||||
upcast->template writeMultiDim<Scalar>(s, TotalDims, pWriteBuffer, TotalNumElements);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Writer<T>::scientificFormat(const bool set)
|
||||
@ -215,7 +395,8 @@ namespace Grid {
|
||||
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value
|
||||
&& !EigenIO::is_tensor<U>::value, void>::type
|
||||
Reader<T>::read(const std::string &s, U &output)
|
||||
{
|
||||
upcast->readDefault(s, output);
|
||||
@ -251,6 +432,79 @@ namespace Grid {
|
||||
vecToTensor(output, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor<ETensor>::value, void>::type
|
||||
Reader<T>::read(const std::string &s, ETensor &output)
|
||||
{
|
||||
using Index = typename ETensor::Index;
|
||||
using Container = typename ETensor::Scalar; // NB: could be same as scalar
|
||||
using Traits = EigenIO::Traits<ETensor>;
|
||||
using Scalar = typename Traits::scalar_type; // type of the underlying scalar
|
||||
constexpr unsigned int TensorRank{ETensor::NumIndices};
|
||||
constexpr unsigned int ContainerRank{Traits::Rank}; // Only non-zero for containers
|
||||
constexpr unsigned int TotalRank{TensorRank + ContainerRank};
|
||||
using ETDims = std::array<Index, TensorRank>; // Dimensions of the tensor
|
||||
|
||||
// read the (flat) data and dimensionality
|
||||
std::vector<std::size_t> dimData;
|
||||
std::vector<Scalar> buf;
|
||||
upcast->readMultiDim( s, buf, dimData );
|
||||
assert(dimData.size() == TotalRank && "EigenIO: Tensor rank mismatch" );
|
||||
// Make sure that the number of elements read matches dimensions read
|
||||
std::size_t NumContainers = 1;
|
||||
for( auto i = 0 ; i < TensorRank ; i++ )
|
||||
NumContainers *= dimData[i];
|
||||
// If our scalar object is a Container, make sure it's dimensions match what we read back
|
||||
std::size_t ElementsPerContainer = 1;
|
||||
for( auto i = 0 ; i < ContainerRank ; i++ ) {
|
||||
assert( dimData[TensorRank+i] == Traits::Dimension(i) && "Tensor Container dimensions don't match data" );
|
||||
ElementsPerContainer *= dimData[TensorRank+i];
|
||||
}
|
||||
assert( NumContainers * ElementsPerContainer == buf.size() && "EigenIO: Number of elements != product of dimensions" );
|
||||
// Now see whether the tensor is the right shape, or can be made to be
|
||||
const auto & dims = output.dimensions();
|
||||
bool bShapeOK = (output.data() != nullptr);
|
||||
for( auto i = 0; bShapeOK && i < TensorRank ; i++ )
|
||||
if( dims[i] != dimData[i] )
|
||||
bShapeOK = false;
|
||||
// Make the tensor the same size as the data read
|
||||
ETDims MyIndex;
|
||||
if( !bShapeOK ) {
|
||||
for( auto i = 0 ; i < TensorRank ; i++ )
|
||||
MyIndex[i] = dimData[i];
|
||||
Reshape(output, MyIndex);
|
||||
}
|
||||
// Copy the data into the tensor
|
||||
for( auto &d : MyIndex ) d = 0;
|
||||
const Scalar * pSource = &buf[0];
|
||||
for( std::size_t n = 0 ; n < NumContainers ; n++ ) {
|
||||
Container & c = output( MyIndex );
|
||||
copyScalars( c, pSource );
|
||||
// Now increment the index
|
||||
for( int i = TensorRank - 1; i != -1 && ++MyIndex[i] == dims[i]; i-- )
|
||||
MyIndex[i] = 0;
|
||||
}
|
||||
assert( pSource == &buf[NumContainers * ElementsPerContainer] );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor_fixed<ETensor>::value, void>::type
|
||||
Reader<T>::Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims )
|
||||
{
|
||||
assert( 0 && "EigenIO: Fixed tensor dimensions can't be changed" );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor_variable<ETensor>::value, void>::type
|
||||
Reader<T>::Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims )
|
||||
{
|
||||
//t.reshape( dims );
|
||||
t.resize( dims );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
void Reader<T>::fromString(U &output, const std::string &s)
|
||||
@ -289,8 +543,70 @@ namespace Grid {
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
static inline typename std::enable_if<!EigenIO::is_tensor<T1>::value || !EigenIO::is_tensor<T2>::value, bool>::type
|
||||
CompareMember(const T1 &lhs, const T2 &rhs) {
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
static inline typename std::enable_if<EigenIO::is_tensor<T1>::value && EigenIO::is_tensor<T2>::value, bool>::type
|
||||
CompareMember(const T1 &lhs, const T2 &rhs) {
|
||||
// First check whether dimensions match (Eigen tensor library will assert if they don't match)
|
||||
bool bReturnValue = (T1::NumIndices == T2::NumIndices);
|
||||
for( auto i = 0 ; bReturnValue && i < T1::NumIndices ; i++ )
|
||||
bReturnValue = ( lhs.dimension(i) == rhs.dimension(i) );
|
||||
if( bReturnValue ) {
|
||||
Eigen::Tensor<bool, 0, T1::Options> bResult = (lhs == rhs).all();
|
||||
bReturnValue = bResult(0);
|
||||
}
|
||||
return bReturnValue;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline typename std::enable_if<EigenIO::is_tensor<T>::value, bool>::type
|
||||
CompareMember(const std::vector<T> &lhs, const std::vector<T> &rhs) {
|
||||
const auto NumElements = lhs.size();
|
||||
bool bResult = ( NumElements == rhs.size() );
|
||||
for( auto i = 0 ; i < NumElements && bResult ; i++ )
|
||||
bResult = CompareMember(lhs[i], rhs[i]);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline typename std::enable_if<!EigenIO::is_tensor<T>::value, void>::type
|
||||
WriteMember(std::ostream &os, const T &object) {
|
||||
os << object;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline typename std::enable_if<EigenIO::is_tensor<T>::value, void>::type
|
||||
WriteMember(std::ostream &os, const T &object) {
|
||||
using Index = typename T::Index;
|
||||
const Index NumElements{object.size()};
|
||||
assert( NumElements > 0 );
|
||||
Index count = 1;
|
||||
os << "T<";
|
||||
for( int i = 0; i < T::NumIndices; i++ ) {
|
||||
Index dim = object.dimension(i);
|
||||
count *= dim;
|
||||
if( i )
|
||||
os << ",";
|
||||
os << dim;
|
||||
}
|
||||
assert( count == NumElements && "Number of elements doesn't match tensor dimensions" );
|
||||
os << ">{";
|
||||
const typename T::Scalar * p = object.data();
|
||||
for( Index i = 0; i < count; i++ ) {
|
||||
if( i )
|
||||
os << ",";
|
||||
os << *p++;
|
||||
}
|
||||
os << "}";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Generic writer interface //////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline void push(Writer<T> &w, const std::string &s) {
|
||||
|
@ -51,6 +51,8 @@ namespace Grid {
|
||||
template <typename U>
|
||||
void writeDefault(const std::string &s, const std::vector<U> &x);
|
||||
void writeDefault(const std::string &s, const char *x);
|
||||
template <typename U>
|
||||
void writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements);
|
||||
private:
|
||||
std::ofstream file_;
|
||||
};
|
||||
@ -66,6 +68,8 @@ namespace Grid {
|
||||
void readDefault(const std::string &s, U &output);
|
||||
template <typename U>
|
||||
void readDefault(const std::string &s, std::vector<U> &output);
|
||||
template <typename U>
|
||||
void readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim);
|
||||
private:
|
||||
std::ifstream file_;
|
||||
};
|
||||
@ -92,6 +96,27 @@ namespace Grid {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void BinaryWriter::writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements)
|
||||
{
|
||||
uint64_t rank = static_cast<uint64_t>( Dimensions.size() );
|
||||
uint64_t tmp = 1;
|
||||
for( auto i = 0 ; i < rank ; i++ )
|
||||
tmp *= Dimensions[i];
|
||||
assert( tmp == NumElements && "Dimensions don't match size of data being written" );
|
||||
// Total number of elements
|
||||
write("", tmp);
|
||||
// Number of dimensions
|
||||
write("", rank);
|
||||
// Followed by each dimension
|
||||
for( auto i = 0 ; i < rank ; i++ ) {
|
||||
tmp = Dimensions[i];
|
||||
write("", tmp);
|
||||
}
|
||||
for( auto i = 0; i < NumElements; ++i)
|
||||
write("", pDataRowMajor[i]);
|
||||
}
|
||||
|
||||
// Reader template implementation ////////////////////////////////////////////
|
||||
template <typename U>
|
||||
void BinaryReader::readDefault(const std::string &s, U &output)
|
||||
@ -114,6 +139,30 @@ namespace Grid {
|
||||
read("", output[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void BinaryReader::readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim)
|
||||
{
|
||||
// Number of elements
|
||||
uint64_t NumElements;
|
||||
read("", NumElements);
|
||||
// Number of dimensions
|
||||
uint64_t rank;
|
||||
read("", rank);
|
||||
// Followed by each dimension
|
||||
uint64_t count = 1;
|
||||
dim.resize(rank);
|
||||
uint64_t tmp;
|
||||
for( auto i = 0 ; i < rank ; i++ ) {
|
||||
read("", tmp);
|
||||
dim[i] = tmp;
|
||||
count *= tmp;
|
||||
}
|
||||
assert( count == NumElements && "Dimensions don't match size of data being read" );
|
||||
buf.resize(count);
|
||||
for( auto i = 0; i < count; ++i)
|
||||
read("", buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <H5Cpp.h>
|
||||
#include <Grid/tensors/Tensors.h>
|
||||
@ -38,6 +39,8 @@ namespace Grid
|
||||
template <typename U>
|
||||
typename std::enable_if<!element<std::vector<U>>::is_number, void>::type
|
||||
writeDefault(const std::string &s, const std::vector<U> &x);
|
||||
template <typename U>
|
||||
void writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements);
|
||||
H5NS::Group & getGroup(void);
|
||||
private:
|
||||
template <typename U>
|
||||
@ -48,7 +51,7 @@ namespace Grid
|
||||
std::vector<std::string> path_;
|
||||
H5NS::H5File file_;
|
||||
H5NS::Group group_;
|
||||
unsigned int dataSetThres_{HDF5_DEF_DATASET_THRES};
|
||||
const unsigned int dataSetThres_{HDF5_DEF_DATASET_THRES};
|
||||
};
|
||||
|
||||
class Hdf5Reader: public Reader<Hdf5Reader>
|
||||
@ -66,6 +69,8 @@ namespace Grid
|
||||
template <typename U>
|
||||
typename std::enable_if<!element<std::vector<U>>::is_number, void>::type
|
||||
readDefault(const std::string &s, std::vector<U> &x);
|
||||
template <typename U>
|
||||
void readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim);
|
||||
H5NS::Group & getGroup(void);
|
||||
private:
|
||||
template <typename U>
|
||||
@ -101,6 +106,75 @@ namespace Grid
|
||||
template <>
|
||||
void Hdf5Writer::writeDefault(const std::string &s, const std::string &x);
|
||||
|
||||
template <typename U>
|
||||
void Hdf5Writer::writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements)
|
||||
{
|
||||
// Hdf5 needs the dimensions as hsize_t
|
||||
const int rank = static_cast<int>(Dimensions.size());
|
||||
std::vector<hsize_t> dim(rank);
|
||||
for(int i = 0; i < rank; i++)
|
||||
dim[i] = Dimensions[i];
|
||||
// write the entire dataset to file
|
||||
H5NS::DataSpace dataSpace(rank, dim.data());
|
||||
|
||||
if (NumElements > dataSetThres_)
|
||||
{
|
||||
// Make sure 1) each dimension; and 2) chunk size is < 4GB
|
||||
const hsize_t MaxElements = ( sizeof( U ) == 1 ) ? 0xffffffff : 0x100000000 / sizeof( U );
|
||||
hsize_t ElementsPerChunk = 1;
|
||||
bool bTooBig = false;
|
||||
for( int i = rank - 1 ; i != -1 ; i-- ) {
|
||||
auto &d = dim[i];
|
||||
if( bTooBig )
|
||||
d = 1; // Chunk size is already as big as can be - remaining dimensions = 1
|
||||
else {
|
||||
// If individual dimension too big, reduce by prime factors if possible
|
||||
while( d > MaxElements && ( d & 1 ) == 0 )
|
||||
d >>= 1;
|
||||
const char ErrorMsg[] = " dimension > 4GB and not divisible by 2^n. "
|
||||
"Hdf5IO chunk size will be inefficient. NB Serialisation is not intended for large datasets - please consider alternatives.";
|
||||
if( d > MaxElements ) {
|
||||
std::cout << GridLogWarning << "Individual" << ErrorMsg << std::endl;
|
||||
hsize_t quotient = d / MaxElements;
|
||||
if( d % MaxElements )
|
||||
quotient++;
|
||||
d /= quotient;
|
||||
}
|
||||
// Now make sure overall size is not too big
|
||||
hsize_t OverflowCheck = ElementsPerChunk;
|
||||
ElementsPerChunk *= d;
|
||||
assert( OverflowCheck == ElementsPerChunk / d && "Product of dimensions overflowed hsize_t" );
|
||||
// If product of dimensions too big, reduce by prime factors
|
||||
while( ElementsPerChunk > MaxElements && ( ElementsPerChunk & 1 ) == 0 ) {
|
||||
bTooBig = true;
|
||||
d >>= 1;
|
||||
ElementsPerChunk >>= 1;
|
||||
}
|
||||
if( ElementsPerChunk > MaxElements ) {
|
||||
std::cout << GridLogWarning << "Product of" << ErrorMsg << std::endl;
|
||||
hsize_t quotient = ElementsPerChunk / MaxElements;
|
||||
if( ElementsPerChunk % MaxElements )
|
||||
quotient++;
|
||||
d /= quotient;
|
||||
ElementsPerChunk /= quotient;
|
||||
}
|
||||
}
|
||||
}
|
||||
H5NS::DataSet dataSet;
|
||||
H5NS::DSetCreatPropList plist;
|
||||
plist.setChunk(rank, dim.data());
|
||||
plist.setFletcher32();
|
||||
dataSet = group_.createDataSet(s, Hdf5Type<U>::type(), dataSpace, plist);
|
||||
dataSet.write(pDataRowMajor, Hdf5Type<U>::type());
|
||||
}
|
||||
else
|
||||
{
|
||||
H5NS::Attribute attribute;
|
||||
attribute = group_.createAttribute(s, Hdf5Type<U>::type(), dataSpace);
|
||||
attribute.write(Hdf5Type<U>::type(), pDataRowMajor);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
typename std::enable_if<element<std::vector<U>>::is_number, void>::type
|
||||
Hdf5Writer::writeDefault(const std::string &s, const std::vector<U> &x)
|
||||
@ -110,34 +184,11 @@ namespace Grid
|
||||
|
||||
// flatten the vector and getting dimensions
|
||||
Flatten<std::vector<U>> flat(x);
|
||||
std::vector<hsize_t> dim;
|
||||
std::vector<size_t> dim;
|
||||
const auto &flatx = flat.getFlatVector();
|
||||
|
||||
for (auto &d: flat.getDim())
|
||||
{
|
||||
dim.push_back(d);
|
||||
}
|
||||
|
||||
// write to file
|
||||
H5NS::DataSpace dataSpace(dim.size(), dim.data());
|
||||
|
||||
if (flatx.size() > dataSetThres_)
|
||||
{
|
||||
H5NS::DataSet dataSet;
|
||||
H5NS::DSetCreatPropList plist;
|
||||
|
||||
plist.setChunk(dim.size(), dim.data());
|
||||
plist.setFletcher32();
|
||||
dataSet = group_.createDataSet(s, Hdf5Type<Element>::type(), dataSpace, plist);
|
||||
dataSet.write(flatx.data(), Hdf5Type<Element>::type());
|
||||
}
|
||||
else
|
||||
{
|
||||
H5NS::Attribute attribute;
|
||||
|
||||
attribute = group_.createAttribute(s, Hdf5Type<Element>::type(), dataSpace);
|
||||
attribute.write(Hdf5Type<Element>::type(), flatx.data());
|
||||
}
|
||||
writeMultiDim<Element>(s, dim, &flatx[0], flatx.size());
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
@ -173,10 +224,9 @@ namespace Grid
|
||||
|
||||
template <>
|
||||
void Hdf5Reader::readDefault(const std::string &s, std::string &x);
|
||||
|
||||
|
||||
template <typename U>
|
||||
typename std::enable_if<element<std::vector<U>>::is_number, void>::type
|
||||
Hdf5Reader::readDefault(const std::string &s, std::vector<U> &x)
|
||||
void Hdf5Reader::readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim)
|
||||
{
|
||||
// alias to element type
|
||||
typedef typename element<std::vector<U>>::type Element;
|
||||
@ -184,7 +234,6 @@ namespace Grid
|
||||
// read the dimensions
|
||||
H5NS::DataSpace dataSpace;
|
||||
std::vector<hsize_t> hdim;
|
||||
std::vector<size_t> dim;
|
||||
hsize_t size = 1;
|
||||
|
||||
if (group_.attrExists(s))
|
||||
@ -204,8 +253,8 @@ namespace Grid
|
||||
}
|
||||
|
||||
// read the flat vector
|
||||
std::vector<Element> buf(size);
|
||||
|
||||
buf.resize(size);
|
||||
|
||||
if (size > dataSetThres_)
|
||||
{
|
||||
H5NS::DataSet dataSet;
|
||||
@ -220,7 +269,19 @@ namespace Grid
|
||||
attribute = group_.openAttribute(s);
|
||||
attribute.read(Hdf5Type<Element>::type(), buf.data());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
typename std::enable_if<element<std::vector<U>>::is_number, void>::type
|
||||
Hdf5Reader::readDefault(const std::string &s, std::vector<U> &x)
|
||||
{
|
||||
// alias to element type
|
||||
typedef typename element<std::vector<U>>::type Element;
|
||||
|
||||
std::vector<size_t> dim;
|
||||
std::vector<Element> buf;
|
||||
readMultiDim( s, buf, dim );
|
||||
|
||||
// reconstruct the multidimensional vector
|
||||
Reconstruct<std::vector<U>> r(buf, dim);
|
||||
|
||||
|
@ -109,8 +109,8 @@ THE SOFTWARE.
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define GRID_MACRO_MEMBER(A,B) A B;
|
||||
#define GRID_MACRO_COMP_MEMBER(A,B) result = (result and (lhs. B == rhs. B));
|
||||
#define GRID_MACRO_OS_WRITE_MEMBER(A,B) os<< #A <<" " #B << " = " << obj. B << " ; " <<std::endl;
|
||||
#define GRID_MACRO_COMP_MEMBER(A,B) result = (result and CompareMember(lhs. B, rhs. B));
|
||||
#define GRID_MACRO_OS_WRITE_MEMBER(A,B) os<< #A <<" " #B << " = "; WriteMember( os, obj. B ); os << " ; " <<std::endl;
|
||||
#define GRID_MACRO_READ_MEMBER(A,B) Grid::read(RD,#B,obj. B);
|
||||
#define GRID_MACRO_WRITE_MEMBER(A,B) Grid::write(WR,#B,obj. B);
|
||||
|
||||
|
@ -51,6 +51,8 @@ namespace Grid
|
||||
void writeDefault(const std::string &s, const U &x);
|
||||
template <typename U>
|
||||
void writeDefault(const std::string &s, const std::vector<U> &x);
|
||||
template <typename U>
|
||||
void writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements);
|
||||
private:
|
||||
void indent(void);
|
||||
private:
|
||||
@ -69,6 +71,8 @@ namespace Grid
|
||||
void readDefault(const std::string &s, U &output);
|
||||
template <typename U>
|
||||
void readDefault(const std::string &s, std::vector<U> &output);
|
||||
template <typename U>
|
||||
void readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim);
|
||||
private:
|
||||
void checkIndent(void);
|
||||
private:
|
||||
@ -95,7 +99,18 @@ namespace Grid
|
||||
write(s, x[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename U>
|
||||
void TextWriter::writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements)
|
||||
{
|
||||
uint64_t Rank = Dimensions.size();
|
||||
write(s, Rank);
|
||||
for( uint64_t d : Dimensions )
|
||||
write(s, d);
|
||||
while( NumElements-- )
|
||||
write(s, *pDataRowMajor++);
|
||||
}
|
||||
|
||||
// Reader template implementation ////////////////////////////////////////////
|
||||
template <typename U>
|
||||
void TextReader::readDefault(const std::string &s, U &output)
|
||||
@ -121,6 +136,23 @@ namespace Grid
|
||||
read("", output[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void TextReader::readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim)
|
||||
{
|
||||
const char sz[] = "";
|
||||
uint64_t Rank;
|
||||
read(sz, Rank);
|
||||
dim.resize( Rank );
|
||||
size_t NumElements = 1;
|
||||
for( auto &d : dim ) {
|
||||
read(sz, d);
|
||||
NumElements *= d;
|
||||
}
|
||||
buf.resize( NumElements );
|
||||
for( auto &x : buf )
|
||||
read(s, x);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,3 +1,32 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./Grid/serialisation/VectorUtils.h
|
||||
|
||||
Copyright (C) 2015
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
Author: paboyle <paboyle@ph.ed.ac.uk>
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#ifndef GRID_SERIALISATION_VECTORUTILS_H
|
||||
#define GRID_SERIALISATION_VECTORUTILS_H
|
||||
|
||||
@ -53,6 +82,17 @@ namespace Grid {
|
||||
return os;
|
||||
}
|
||||
|
||||
// std::vector<std:vector<...>> nested to specified Rank //////////////////////////////////
|
||||
template<typename T, unsigned int Rank>
|
||||
struct NestedStdVector {
|
||||
typedef typename std::vector<typename NestedStdVector<T, Rank - 1>::type> type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct NestedStdVector<T,0> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
// Grid scalar tensors to nested std::vectors //////////////////////////////////
|
||||
template <typename T>
|
||||
struct TensorToVec
|
||||
@ -436,4 +476,4 @@ std::string vecToStr(const std::vector<T> &v)
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -57,6 +57,8 @@ namespace Grid
|
||||
void writeDefault(const std::string &s, const U &x);
|
||||
template <typename U>
|
||||
void writeDefault(const std::string &s, const std::vector<U> &x);
|
||||
template <typename U>
|
||||
void writeMultiDim(const std::string &s, const std::vector<size_t> & 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 <typename U>
|
||||
void readDefault(const std::string &s, std::vector<U> &output);
|
||||
template <typename U>
|
||||
void readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim);
|
||||
void readCurrentSubtree(std::string &s);
|
||||
private:
|
||||
void checkParse(const pugi::xml_parse_result &result, const std::string name);
|
||||
@ -122,13 +126,45 @@ namespace Grid
|
||||
void XmlWriter::writeDefault(const std::string &s, const std::vector<U> &x)
|
||||
{
|
||||
push(s);
|
||||
for (auto &x_i: x)
|
||||
for( auto &u : x )
|
||||
{
|
||||
write("elem", x_i);
|
||||
write("elem", u);
|
||||
}
|
||||
pop();
|
||||
}
|
||||
|
||||
|
||||
template <typename U>
|
||||
void XmlWriter::writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements)
|
||||
{
|
||||
push(s);
|
||||
size_t count = 1;
|
||||
const int Rank = static_cast<int>( Dimensions.size() );
|
||||
write("rank", Rank );
|
||||
std::vector<size_t> MyIndex( Rank );
|
||||
for( auto d : Dimensions ) {
|
||||
write("dim", d);
|
||||
count *= d;
|
||||
}
|
||||
assert( count == NumElements && "XmlIO : element count doesn't match dimensions" );
|
||||
static const char sName[] = "tensor";
|
||||
for( int i = 0 ; i < Rank ; i++ ) {
|
||||
MyIndex[i] = 0;
|
||||
push(sName);
|
||||
}
|
||||
while (NumElements--) {
|
||||
write("elem", *pDataRowMajor++);
|
||||
int i;
|
||||
for( i = Rank - 1 ; i != -1 && ++MyIndex[i] == Dimensions[i] ; i-- )
|
||||
MyIndex[i] = 0;
|
||||
int Rollover = Rank - 1 - i;
|
||||
for( i = 0 ; i < Rollover ; i++ )
|
||||
pop();
|
||||
for( i = 0 ; NumElements && i < Rollover ; i++ )
|
||||
push(sName);
|
||||
}
|
||||
pop();
|
||||
}
|
||||
|
||||
// Reader template implementation ////////////////////////////////////////////
|
||||
template <typename U>
|
||||
void XmlReader::readDefault(const std::string &s, U &output)
|
||||
@ -145,25 +181,66 @@ namespace Grid
|
||||
template <typename U>
|
||||
void XmlReader::readDefault(const std::string &s, std::vector<U> &output)
|
||||
{
|
||||
std::string buf;
|
||||
unsigned int i = 0;
|
||||
|
||||
if (!push(s))
|
||||
{
|
||||
std::cout << GridLogWarning << "XML: cannot open node '" << s << "'";
|
||||
std::cout << std::endl;
|
||||
|
||||
return;
|
||||
} else {
|
||||
for(unsigned int i = 0; node_.child("elem"); )
|
||||
{
|
||||
output.resize(i + 1);
|
||||
read("elem", output[i++]);
|
||||
node_.child("elem").set_name("elem-done");
|
||||
}
|
||||
pop();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void XmlReader::readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim)
|
||||
{
|
||||
if (!push(s))
|
||||
{
|
||||
std::cout << GridLogWarning << "XML: cannot open node '" << s << "'";
|
||||
std::cout << std::endl;
|
||||
} else {
|
||||
static const char sName[] = "tensor";
|
||||
static const char sNameDone[] = "tensor-done";
|
||||
int Rank;
|
||||
read("rank", Rank);
|
||||
dim.resize( Rank );
|
||||
size_t NumElements = 1;
|
||||
for( auto &d : dim )
|
||||
{
|
||||
read("dim", d);
|
||||
node_.child("dim").set_name("dim-done");
|
||||
NumElements *= d;
|
||||
}
|
||||
buf.resize( NumElements );
|
||||
std::vector<size_t> MyIndex( Rank );
|
||||
for( int i = 0 ; i < Rank ; i++ ) {
|
||||
MyIndex[i] = 0;
|
||||
push(sName);
|
||||
}
|
||||
|
||||
for( auto &x : buf )
|
||||
{
|
||||
NumElements--;
|
||||
read("elem", x);
|
||||
node_.child("elem").set_name("elem-done");
|
||||
int i;
|
||||
for( i = Rank - 1 ; i != -1 && ++MyIndex[i] == dim[i] ; i-- )
|
||||
MyIndex[i] = 0;
|
||||
int Rollover = Rank - 1 - i;
|
||||
for( i = 0 ; i < Rollover ; i++ ) {
|
||||
node_.set_name(sNameDone);
|
||||
pop();
|
||||
}
|
||||
for( i = 0 ; NumElements && i < Rollover ; i++ )
|
||||
push(sName);
|
||||
}
|
||||
pop();
|
||||
}
|
||||
while (node_.child("elem"))
|
||||
{
|
||||
output.resize(i + 1);
|
||||
read("elem", output[i]);
|
||||
node_.child("elem").set_name("elem-done");
|
||||
i++;
|
||||
}
|
||||
pop();
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -10,6 +10,7 @@ Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
|
||||
Author: Guido Cossu <cossu@iroiro-pc.kek.jp>
|
||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
Author: neo <cossu@post.kek.jp>
|
||||
Author: Michael Marshall <michael.marshall@ed.ac.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -89,17 +90,25 @@ template <typename Condition, typename ReturnType> using NotEnableIf = Invoke<st
|
||||
////////////////////////////////////////////////////////
|
||||
// Check for complexity with type traits
|
||||
template <typename T> struct is_complex : public std::false_type {};
|
||||
template <> struct is_complex<std::complex<double> > : public std::true_type {};
|
||||
template <> struct is_complex<std::complex<float> > : public std::true_type {};
|
||||
template <> struct is_complex<ComplexD> : public std::true_type {};
|
||||
template <> struct is_complex<ComplexF> : public std::true_type {};
|
||||
|
||||
template <typename T> using IfReal = Invoke<std::enable_if<std::is_floating_point<T>::value, int> >;
|
||||
template<typename T, typename V=void> struct is_real : public std::false_type {};
|
||||
template<typename T> struct is_real<T, typename std::enable_if<std::is_floating_point<T>::value,
|
||||
void>::type> : public std::true_type {};
|
||||
|
||||
template<typename T, typename V=void> struct is_integer : public std::false_type {};
|
||||
template<typename T> struct is_integer<T, typename std::enable_if<std::is_integral<T>::value,
|
||||
void>::type> : public std::true_type {};
|
||||
|
||||
template <typename T> using IfReal = Invoke<std::enable_if<is_real<T>::value, int> >;
|
||||
template <typename T> using IfComplex = Invoke<std::enable_if<is_complex<T>::value, int> >;
|
||||
template <typename T> using IfInteger = Invoke<std::enable_if<std::is_integral<T>::value, int> >;
|
||||
template <typename T> using IfInteger = Invoke<std::enable_if<is_integer<T>::value, int> >;
|
||||
template <typename T1,typename T2> using IfSame = Invoke<std::enable_if<std::is_same<T1,T2>::value, int> >;
|
||||
|
||||
template <typename T> using IfNotReal = Invoke<std::enable_if<!std::is_floating_point<T>::value, int> >;
|
||||
template <typename T> using IfNotReal = Invoke<std::enable_if<!is_real<T>::value, int> >;
|
||||
template <typename T> using IfNotComplex = Invoke<std::enable_if<!is_complex<T>::value, int> >;
|
||||
template <typename T> using IfNotInteger = Invoke<std::enable_if<!std::is_integral<T>::value, int> >;
|
||||
template <typename T> using IfNotInteger = Invoke<std::enable_if<!is_integer<T>::value, int> >;
|
||||
template <typename T1,typename T2> using IfNotSame = Invoke<std::enable_if<!std::is_same<T1,T2>::value, int> >;
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
@ -857,8 +866,10 @@ template <typename T>
|
||||
struct is_simd : public std::false_type {};
|
||||
template <> struct is_simd<vRealF> : public std::true_type {};
|
||||
template <> struct is_simd<vRealD> : public std::true_type {};
|
||||
template <> struct is_simd<vRealH> : public std::true_type {};
|
||||
template <> struct is_simd<vComplexF> : public std::true_type {};
|
||||
template <> struct is_simd<vComplexD> : public std::true_type {};
|
||||
template <> struct is_simd<vComplexH> : public std::true_type {};
|
||||
template <> struct is_simd<vInteger> : public std::true_type {};
|
||||
|
||||
template <typename T> using IfSimd = Invoke<std::enable_if<is_simd<T>::value, int> >;
|
||||
|
@ -5,6 +5,7 @@ Copyright (C) 2015
|
||||
|
||||
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
|
||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
Author: Michael Marshall <michael.marshall@ed.ac.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -42,27 +43,26 @@ namespace Grid {
|
||||
//
|
||||
class GridTensorBase {};
|
||||
|
||||
// Too late to remove these traits from Grid Tensors, so inherit from GridTypeMapper
|
||||
#define GridVector_CopyTraits \
|
||||
using element = vtype; \
|
||||
using scalar_type = typename Traits::scalar_type; \
|
||||
using vector_type = typename Traits::vector_type; \
|
||||
using vector_typeD = typename Traits::vector_typeD; \
|
||||
using tensor_reduced = typename Traits::tensor_reduced; \
|
||||
using scalar_object = typename Traits::scalar_object; \
|
||||
using Complexified = typename Traits::Complexified; \
|
||||
using Realified = typename Traits::Realified; \
|
||||
using DoublePrecision = typename Traits::DoublePrecision; \
|
||||
static constexpr int TensorLevel = Traits::TensorLevel
|
||||
|
||||
template <class vtype>
|
||||
class iScalar {
|
||||
public:
|
||||
vtype _internal;
|
||||
|
||||
typedef vtype element;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_type scalar_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_type vector_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_typeD vector_typeD;
|
||||
typedef typename GridTypeMapper<vtype>::tensor_reduced tensor_reduced_v;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_object recurse_scalar_object;
|
||||
typedef iScalar<tensor_reduced_v> tensor_reduced;
|
||||
typedef iScalar<recurse_scalar_object> scalar_object;
|
||||
// substitutes a real or complex version with same tensor structure
|
||||
typedef iScalar<typename GridTypeMapper<vtype>::Complexified> Complexified;
|
||||
typedef iScalar<typename GridTypeMapper<vtype>::Realified> Realified;
|
||||
|
||||
// get double precision version
|
||||
typedef iScalar<typename GridTypeMapper<vtype>::DoublePrecision> DoublePrecision;
|
||||
|
||||
enum { TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1 };
|
||||
using Traits = GridTypeMapper<iScalar<vtype> >;
|
||||
GridVector_CopyTraits;
|
||||
|
||||
// Scalar no action
|
||||
// template<int Level> using tensor_reduce_level = typename
|
||||
@ -173,7 +173,10 @@ class iScalar {
|
||||
return stream;
|
||||
};
|
||||
|
||||
|
||||
strong_inline const scalar_type * begin() const { return reinterpret_cast<const scalar_type *>(&_internal); }
|
||||
strong_inline scalar_type * begin() { return reinterpret_cast< scalar_type *>(&_internal); }
|
||||
strong_inline const scalar_type * end() const { return begin() + Traits::count; }
|
||||
strong_inline scalar_type * end() { return begin() + Traits::count; }
|
||||
};
|
||||
///////////////////////////////////////////////////////////
|
||||
// Allows to turn scalar<scalar<scalar<double>>>> back to double.
|
||||
@ -194,22 +197,9 @@ class iVector {
|
||||
public:
|
||||
vtype _internal[N];
|
||||
|
||||
typedef vtype element;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_type scalar_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_type vector_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_typeD vector_typeD;
|
||||
typedef typename GridTypeMapper<vtype>::tensor_reduced tensor_reduced_v;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_object recurse_scalar_object;
|
||||
typedef iScalar<tensor_reduced_v> tensor_reduced;
|
||||
typedef iVector<recurse_scalar_object, N> scalar_object;
|
||||
using Traits = GridTypeMapper<iVector<vtype, N> >;
|
||||
GridVector_CopyTraits;
|
||||
|
||||
// substitutes a real or complex version with same tensor structure
|
||||
typedef iVector<typename GridTypeMapper<vtype>::Complexified, N> Complexified;
|
||||
typedef iVector<typename GridTypeMapper<vtype>::Realified, N> Realified;
|
||||
|
||||
// get double precision version
|
||||
typedef iVector<typename GridTypeMapper<vtype>::DoublePrecision, N> DoublePrecision;
|
||||
|
||||
template <class T, typename std::enable_if<!isGridTensor<T>::value, T>::type
|
||||
* = nullptr>
|
||||
strong_inline auto operator=(T arg) -> iVector<vtype, N> {
|
||||
@ -218,7 +208,6 @@ class iVector {
|
||||
return *this;
|
||||
}
|
||||
|
||||
enum { TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1 };
|
||||
iVector(const Zero &z) { *this = zero; };
|
||||
iVector() = default;
|
||||
/*
|
||||
@ -303,6 +292,11 @@ class iVector {
|
||||
// strong_inline vtype && operator ()(int i) {
|
||||
// return _internal[i];
|
||||
// }
|
||||
|
||||
strong_inline const scalar_type * begin() const { return reinterpret_cast<const scalar_type *>(_internal); }
|
||||
strong_inline scalar_type * begin() { return reinterpret_cast< scalar_type *>(_internal); }
|
||||
strong_inline const scalar_type * end() const { return begin() + Traits::count; }
|
||||
strong_inline scalar_type * end() { return begin() + Traits::count; }
|
||||
};
|
||||
|
||||
template <class vtype, int N>
|
||||
@ -310,25 +304,8 @@ class iMatrix {
|
||||
public:
|
||||
vtype _internal[N][N];
|
||||
|
||||
typedef vtype element;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_type scalar_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_type vector_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_typeD vector_typeD;
|
||||
typedef typename GridTypeMapper<vtype>::tensor_reduced tensor_reduced_v;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_object recurse_scalar_object;
|
||||
|
||||
// substitutes a real or complex version with same tensor structure
|
||||
typedef iMatrix<typename GridTypeMapper<vtype>::Complexified, N> Complexified;
|
||||
typedef iMatrix<typename GridTypeMapper<vtype>::Realified, N> Realified;
|
||||
|
||||
// get double precision version
|
||||
typedef iMatrix<typename GridTypeMapper<vtype>::DoublePrecision, N> DoublePrecision;
|
||||
|
||||
// Tensor removal
|
||||
typedef iScalar<tensor_reduced_v> tensor_reduced;
|
||||
typedef iMatrix<recurse_scalar_object, N> scalar_object;
|
||||
|
||||
enum { TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1 };
|
||||
using Traits = GridTypeMapper<iMatrix<vtype, N> >;
|
||||
GridVector_CopyTraits;
|
||||
|
||||
iMatrix(const Zero &z) { *this = zero; };
|
||||
iMatrix() = default;
|
||||
@ -458,6 +435,11 @@ class iMatrix {
|
||||
// strong_inline vtype && operator ()(int i,int j) {
|
||||
// return _internal[i][j];
|
||||
// }
|
||||
|
||||
strong_inline const scalar_type * begin() const { return reinterpret_cast<const scalar_type *>(_internal[0]); }
|
||||
strong_inline scalar_type * begin() { return reinterpret_cast< scalar_type *>(_internal[0]); }
|
||||
strong_inline const scalar_type * end() const { return begin() + Traits::count; }
|
||||
strong_inline scalar_type * end() { return begin() + Traits::count; }
|
||||
};
|
||||
|
||||
template <class v>
|
||||
@ -480,6 +462,3 @@ void vprefetch(const iMatrix<v, N> &vv) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
|
||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
Author: Christopher Kelly <ckelly@phys.columbia.edu>
|
||||
Author: Michael Marshall <michael.marshall@ed.ac.au>
|
||||
This program 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 2 of the License, or
|
||||
@ -26,6 +27,17 @@ Author: Christopher Kelly <ckelly@phys.columbia.edu>
|
||||
|
||||
namespace Grid {
|
||||
|
||||
// Forward declarations
|
||||
template<class T> class iScalar;
|
||||
template<class T, int N> class iVector;
|
||||
template<class T, int N> class iMatrix;
|
||||
|
||||
// These are the Grid tensors
|
||||
template<typename T> struct isGridTensor : public std::false_type { static constexpr bool notvalue = true; };
|
||||
template<class T> struct isGridTensor<iScalar<T>> : public std::true_type { static constexpr bool notvalue = false; };
|
||||
template<class T, int N> struct isGridTensor<iVector<T, N>> : public std::true_type { static constexpr bool notvalue = false; };
|
||||
template<class T, int N> struct isGridTensor<iMatrix<T, N>> : public std::true_type { static constexpr bool notvalue = false; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Want to recurse: GridTypeMapper<Matrix<vComplexD> >::scalar_type == ComplexD.
|
||||
// Use of a helper class like this allows us to template specialise and "dress"
|
||||
@ -40,25 +52,26 @@ namespace Grid {
|
||||
// to study C++11's type_traits.h file. (std::enable_if<isGridTensorType<vtype> >)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T> class GridTypeMapper {
|
||||
public:
|
||||
typedef typename T::scalar_type scalar_type;
|
||||
typedef typename T::vector_type vector_type;
|
||||
typedef typename T::vector_typeD vector_typeD;
|
||||
typedef typename T::tensor_reduced tensor_reduced;
|
||||
typedef typename T::scalar_object scalar_object;
|
||||
typedef typename T::Complexified Complexified;
|
||||
typedef typename T::Realified Realified;
|
||||
typedef typename T::DoublePrecision DoublePrecision;
|
||||
enum { TensorLevel = T::TensorLevel };
|
||||
|
||||
// This saves repeating common properties for supported Grid Scalar types
|
||||
// TensorLevel How many nested grid tensors
|
||||
// Rank Rank of the grid tensor
|
||||
// count Total number of elements, i.e. product of dimensions
|
||||
// Dimension(dim) Size of dimension dim
|
||||
struct GridTypeMapper_Base {
|
||||
static constexpr int TensorLevel = 0;
|
||||
static constexpr int Rank = 0;
|
||||
static constexpr std::size_t count = 1;
|
||||
static constexpr int Dimension(int dim) { return 0; }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Recursion stops with these template specialisations
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
template<> class GridTypeMapper<RealF> {
|
||||
public:
|
||||
|
||||
template<typename T> struct GridTypeMapper {};
|
||||
|
||||
template<> struct GridTypeMapper<RealF> : public GridTypeMapper_Base {
|
||||
typedef RealF scalar_type;
|
||||
typedef RealF vector_type;
|
||||
typedef RealD vector_typeD;
|
||||
@ -67,10 +80,8 @@ namespace Grid {
|
||||
typedef ComplexF Complexified;
|
||||
typedef RealF Realified;
|
||||
typedef RealD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<RealD> {
|
||||
public:
|
||||
template<> struct GridTypeMapper<RealD> : public GridTypeMapper_Base {
|
||||
typedef RealD scalar_type;
|
||||
typedef RealD vector_type;
|
||||
typedef RealD vector_typeD;
|
||||
@ -79,10 +90,8 @@ namespace Grid {
|
||||
typedef ComplexD Complexified;
|
||||
typedef RealD Realified;
|
||||
typedef RealD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<ComplexF> {
|
||||
public:
|
||||
template<> struct GridTypeMapper<ComplexF> : public GridTypeMapper_Base {
|
||||
typedef ComplexF scalar_type;
|
||||
typedef ComplexF vector_type;
|
||||
typedef ComplexD vector_typeD;
|
||||
@ -91,10 +100,8 @@ namespace Grid {
|
||||
typedef ComplexF Complexified;
|
||||
typedef RealF Realified;
|
||||
typedef ComplexD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<ComplexD> {
|
||||
public:
|
||||
template<> struct GridTypeMapper<ComplexD> : public GridTypeMapper_Base {
|
||||
typedef ComplexD scalar_type;
|
||||
typedef ComplexD vector_type;
|
||||
typedef ComplexD vector_typeD;
|
||||
@ -103,10 +110,8 @@ namespace Grid {
|
||||
typedef ComplexD Complexified;
|
||||
typedef RealD Realified;
|
||||
typedef ComplexD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<Integer> {
|
||||
public:
|
||||
template<> struct GridTypeMapper<Integer> : public GridTypeMapper_Base {
|
||||
typedef Integer scalar_type;
|
||||
typedef Integer vector_type;
|
||||
typedef Integer vector_typeD;
|
||||
@ -115,11 +120,9 @@ namespace Grid {
|
||||
typedef void Complexified;
|
||||
typedef void Realified;
|
||||
typedef void DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
|
||||
template<> class GridTypeMapper<vRealF> {
|
||||
public:
|
||||
template<> struct GridTypeMapper<vRealF> : public GridTypeMapper_Base {
|
||||
typedef RealF scalar_type;
|
||||
typedef vRealF vector_type;
|
||||
typedef vRealD vector_typeD;
|
||||
@ -128,10 +131,8 @@ namespace Grid {
|
||||
typedef vComplexF Complexified;
|
||||
typedef vRealF Realified;
|
||||
typedef vRealD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<vRealD> {
|
||||
public:
|
||||
template<> struct GridTypeMapper<vRealD> : public GridTypeMapper_Base {
|
||||
typedef RealD scalar_type;
|
||||
typedef vRealD vector_type;
|
||||
typedef vRealD vector_typeD;
|
||||
@ -140,10 +141,20 @@ namespace Grid {
|
||||
typedef vComplexD Complexified;
|
||||
typedef vRealD Realified;
|
||||
typedef vRealD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<vComplexH> {
|
||||
public:
|
||||
template<> struct GridTypeMapper<vRealH> : public GridTypeMapper_Base {
|
||||
// Fixme this is incomplete until Grid supports fp16 or bfp16 arithmetic types
|
||||
typedef RealF scalar_type;
|
||||
typedef vRealH vector_type;
|
||||
typedef vRealD vector_typeD;
|
||||
typedef vRealH tensor_reduced;
|
||||
typedef RealF scalar_object;
|
||||
typedef vComplexH Complexified;
|
||||
typedef vRealH Realified;
|
||||
typedef vRealD DoublePrecision;
|
||||
};
|
||||
template<> struct GridTypeMapper<vComplexH> : public GridTypeMapper_Base {
|
||||
// Fixme this is incomplete until Grid supports fp16 or bfp16 arithmetic types
|
||||
typedef ComplexF scalar_type;
|
||||
typedef vComplexH vector_type;
|
||||
typedef vComplexD vector_typeD;
|
||||
@ -152,10 +163,8 @@ namespace Grid {
|
||||
typedef vComplexH Complexified;
|
||||
typedef vRealH Realified;
|
||||
typedef vComplexD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<vComplexF> {
|
||||
public:
|
||||
template<> struct GridTypeMapper<vComplexF> : public GridTypeMapper_Base {
|
||||
typedef ComplexF scalar_type;
|
||||
typedef vComplexF vector_type;
|
||||
typedef vComplexD vector_typeD;
|
||||
@ -164,10 +173,8 @@ namespace Grid {
|
||||
typedef vComplexF Complexified;
|
||||
typedef vRealF Realified;
|
||||
typedef vComplexD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<vComplexD> {
|
||||
public:
|
||||
template<> struct GridTypeMapper<vComplexD> : public GridTypeMapper_Base {
|
||||
typedef ComplexD scalar_type;
|
||||
typedef vComplexD vector_type;
|
||||
typedef vComplexD vector_typeD;
|
||||
@ -176,10 +183,8 @@ namespace Grid {
|
||||
typedef vComplexD Complexified;
|
||||
typedef vRealD Realified;
|
||||
typedef vComplexD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<vInteger> {
|
||||
public:
|
||||
template<> struct GridTypeMapper<vInteger> : public GridTypeMapper_Base {
|
||||
typedef Integer scalar_type;
|
||||
typedef vInteger vector_type;
|
||||
typedef vInteger vector_typeD;
|
||||
@ -188,57 +193,52 @@ namespace Grid {
|
||||
typedef void Complexified;
|
||||
typedef void Realified;
|
||||
typedef void DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
|
||||
// First some of my own traits
|
||||
template<typename T> struct isGridTensor {
|
||||
static const bool value = true;
|
||||
static const bool notvalue = false;
|
||||
#define GridTypeMapper_RepeatedTypes \
|
||||
using BaseTraits = GridTypeMapper<T>; \
|
||||
using scalar_type = typename BaseTraits::scalar_type; \
|
||||
using vector_type = typename BaseTraits::vector_type; \
|
||||
using vector_typeD = typename BaseTraits::vector_typeD; \
|
||||
static constexpr int TensorLevel = BaseTraits::TensorLevel + 1
|
||||
|
||||
template<typename T> struct GridTypeMapper<iScalar<T>> {
|
||||
GridTypeMapper_RepeatedTypes;
|
||||
using tensor_reduced = iScalar<typename BaseTraits::tensor_reduced>;
|
||||
using scalar_object = iScalar<typename BaseTraits::scalar_object>;
|
||||
using Complexified = iScalar<typename BaseTraits::Complexified>;
|
||||
using Realified = iScalar<typename BaseTraits::Realified>;
|
||||
using DoublePrecision = iScalar<typename BaseTraits::DoublePrecision>;
|
||||
static constexpr int Rank = BaseTraits::Rank + 1;
|
||||
static constexpr std::size_t count = BaseTraits::count;
|
||||
static constexpr int Dimension(int dim) {
|
||||
return ( dim == 0 ) ? 1 : BaseTraits::Dimension(dim - 1); }
|
||||
};
|
||||
template<> struct isGridTensor<int > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
|
||||
template<typename T, int N> struct GridTypeMapper<iVector<T, N>> {
|
||||
GridTypeMapper_RepeatedTypes;
|
||||
using tensor_reduced = iScalar<typename BaseTraits::tensor_reduced>;
|
||||
using scalar_object = iVector<typename BaseTraits::scalar_object, N>;
|
||||
using Complexified = iVector<typename BaseTraits::Complexified, N>;
|
||||
using Realified = iVector<typename BaseTraits::Realified, N>;
|
||||
using DoublePrecision = iVector<typename BaseTraits::DoublePrecision, N>;
|
||||
static constexpr int Rank = BaseTraits::Rank + 1;
|
||||
static constexpr std::size_t count = BaseTraits::count * N;
|
||||
static constexpr int Dimension(int dim) {
|
||||
return ( dim == 0 ) ? N : BaseTraits::Dimension(dim - 1); }
|
||||
};
|
||||
template<> struct isGridTensor<RealD > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<RealF > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<ComplexD > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<ComplexF > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<Integer > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<vRealD > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<vRealF > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<vComplexD > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<vComplexF > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<vInteger > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
|
||||
template<typename T, int N> struct GridTypeMapper<iMatrix<T, N>> {
|
||||
GridTypeMapper_RepeatedTypes;
|
||||
using tensor_reduced = iScalar<typename BaseTraits::tensor_reduced>;
|
||||
using scalar_object = iMatrix<typename BaseTraits::scalar_object, N>;
|
||||
using Complexified = iMatrix<typename BaseTraits::Complexified, N>;
|
||||
using Realified = iMatrix<typename BaseTraits::Realified, N>;
|
||||
using DoublePrecision = iMatrix<typename BaseTraits::DoublePrecision, N>;
|
||||
static constexpr int Rank = BaseTraits::Rank + 2;
|
||||
static constexpr std::size_t count = BaseTraits::count * N * N;
|
||||
static constexpr int Dimension(int dim) {
|
||||
return ( dim == 0 || dim == 1 ) ? N : BaseTraits::Dimension(dim - 2); }
|
||||
};
|
||||
|
||||
// Match the index
|
||||
@ -263,20 +263,13 @@ namespace Grid {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
//Query if a tensor or Lattice<Tensor> is SIMD vector or scalar
|
||||
template<typename T>
|
||||
class isSIMDvectorized{
|
||||
template<typename U>
|
||||
static typename std::enable_if< !std::is_same< typename GridTypeMapper<typename getVectorType<U>::type>::scalar_type,
|
||||
typename GridTypeMapper<typename getVectorType<U>::type>::vector_type>::value, char>::type test(void *);
|
||||
//Query whether a tensor or Lattice<Tensor> is SIMD vector or scalar
|
||||
template<typename T, typename V=void> struct isSIMDvectorized : public std::false_type {};
|
||||
template<typename U> struct isSIMDvectorized<U, typename std::enable_if< !std::is_same<
|
||||
typename GridTypeMapper<typename getVectorType<U>::type>::scalar_type,
|
||||
typename GridTypeMapper<typename getVectorType<U>::type>::vector_type>::value, void>::type>
|
||||
: public std::true_type {};
|
||||
|
||||
template<typename U>
|
||||
static double test(...);
|
||||
|
||||
public:
|
||||
enum {value = sizeof(test<T>(0)) == sizeof(char) };
|
||||
};
|
||||
|
||||
//Get the precision of a Lattice, tensor or scalar type in units of sizeof(float)
|
||||
template<typename T>
|
||||
class getPrecision{
|
||||
|
Reference in New Issue
Block a user