1
0
mirror of https://github.com/paboyle/Grid.git synced 2024-11-10 07:55:35 +00:00

Eigen tensor serialisation fixes after Antonin's review

This commit is contained in:
Michael Marshall 2019-04-03 22:48:07 +01:00
parent 47f5b1e2b5
commit 00b4139c16
13 changed files with 686 additions and 519 deletions

View File

@ -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
{

View File

@ -61,15 +61,25 @@ namespace Grid {
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 {};
// Traits are the default for scalars, or come from GridTypeMapper for GridTensors
// 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 {};
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;
// 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;
};
template<typename T> struct Traits<T, typename std::enable_if<is_tensor_of_container<T>::value>::type> : public GridTypeMapper<typename T::Scalar> {
using scalar_type = typename GridTypeMapper<typename T::Scalar>::scalar_type;
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
@ -310,15 +320,15 @@ namespace Grid {
// 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;
Scalar * pCopyBuffer = nullptr;
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
pCopyBuffer = new Scalar[TotalNumElements];
pWriteBuffer = pCopyBuffer;
Scalar * pCopy = pCopyBuffer;
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++ ) {
@ -330,7 +340,6 @@ namespace Grid {
}
}
upcast->template writeMultiDim<Scalar>(s, TotalDims, pWriteBuffer, TotalNumElements);
if( pCopyBuffer ) delete [] pCopyBuffer;
}
template <typename T>

View File

@ -51,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>
@ -117,15 +117,8 @@ namespace Grid
// write the entire dataset to file
H5NS::DataSpace dataSpace(rank, dim.data());
size_t DataSize = NumElements * sizeof(U);
if (DataSize > dataSetThres_)
if (NumElements > dataSetThres_)
{
// First few prime numbers from https://oeis.org/A000040
static const unsigned short Primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109,
113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271 };
constexpr int NumPrimes = sizeof( Primes ) / sizeof( Primes[0] );
// 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;
@ -136,13 +129,9 @@ namespace Grid
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
for( int PrimeIdx = 0; d > MaxElements && PrimeIdx < NumPrimes; ) {
if( d % Primes[PrimeIdx] )
PrimeIdx++;
else
d /= Primes[PrimeIdx];
}
const char ErrorMsg[] = " dimension > 4GB without small prime factors. "
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;
@ -156,17 +145,13 @@ namespace Grid
ElementsPerChunk *= d;
assert( OverflowCheck == ElementsPerChunk / d && "Product of dimensions overflowed hsize_t" );
// If product of dimensions too big, reduce by prime factors
for( int PrimeIdx = 0; ElementsPerChunk > MaxElements && PrimeIdx < NumPrimes; ) {
while( ElementsPerChunk > MaxElements && ( ElementsPerChunk & 1 ) == 0 ) {
bTooBig = true;
if( d % Primes[PrimeIdx] )
PrimeIdx++;
else {
d /= Primes[PrimeIdx];
ElementsPerChunk /= Primes[PrimeIdx];
}
d >>= 1;
ElementsPerChunk >>= 1;
}
if( ElementsPerChunk > MaxElements ) {
std::cout << GridLogMessage << "Product of" << ErrorMsg << std::endl;
std::cout << GridLogWarning << "Product of" << ErrorMsg << std::endl;
hsize_t quotient = ElementsPerChunk / MaxElements;
if( ElementsPerChunk % MaxElements )
quotient++;
@ -270,7 +255,7 @@ namespace Grid
// read the flat vector
buf.resize(size);
if (size * sizeof(Element) > dataSetThres_)
if (size > dataSetThres_)
{
H5NS::DataSet dataSet;

View File

@ -1,271 +0,0 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: Grid/util/EigenUtil.h
Copyright (C) 2019
Author: Michael Marshall <michael.marshall@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_UTIL_EIGENUTIL_H
#define GRID_UTIL_EIGENUTIL_H
#include <Grid/tensors/Tensor_traits.h>
#include <Grid/Eigen/unsupported/CXX11/Tensor>
namespace Grid {
// Custom iterator for Eigen tensors
namespace EigenUtil {
template <typename ETensor, bool bConst> // Is the tensor constant
class TensorIterator_raw{
public:
using Index = typename ETensor::Index;
using Scalar = typename ETensor::Scalar;
using FullIndex = std::array<Index, ETensor::NumIndices>;
const ETensor * pET;
const Index end; // same as pET->size()
Index position; // position (memory order)
Index Seq; // sequence (what our position would be if we were column major)
FullIndex indexPos;
FullIndex indexSize;
inline TensorIterator_raw( ETensor & eT, Index pos = 0 ) : pET{&eT}, position{pos}, Seq{pos}, end{pET->size()} {
for( int i = 0 ; i < ETensor::NumIndices ; i++ ) {
indexPos[i] = 0;
indexSize[i] = pET->dimension(i);
}
}
inline TensorIterator_raw<ETensor, bConst> & operator++() {
auto sz = pET->size();
if( position < sz ) {
position++;
if( ETensor::Options & Eigen::RowMajor ) {
for( int i = ETensor::NumIndices - 1; i != -1 && ++indexPos[i] == indexSize[i]; i-- )
indexPos[i] = 0;
Seq++;
} else {
for( int i = 0; i < ETensor::NumIndices && ++indexPos[i] == indexSize[i]; i++ )
indexPos[i] = 0;
Seq = 0;
for( int i = 0; i < ETensor::NumIndices; i++ ) {
Seq *= indexSize[i];
Seq += indexPos[i];
}
}
}
return * this;
}
inline typename std::conditional<bConst,const Scalar &,Scalar &>::type operator*() const {
assert( position >= 0 && position < pET->size() && "Attempt to access Eigen tensor iterator out of range" );
return ( ( typename std::conditional<bConst,const Scalar *,Scalar*>::type ) pET->data() )[position];
}
inline bool operator!=(const TensorIterator_raw<ETensor, bConst> &r)
{ return pET == nullptr || pET != r.pET || position != r.position; }
// These functions aren't required for iterators, but they make using them easier
inline bool AtEnd() { return position == end; }
inline void DumpIndex(void) {
for( auto dim : indexPos )
std::cout << "[" << dim << "]";
}
};
}
}
// The only way I could get these iterators to work is to put the begin() and end() functions in the Eigen namespace
// So if Eigen ever defines these, we'll have a conflict and have to change this
namespace Eigen {
template <typename ETensor> using TensorIterator = Grid::EigenUtil::TensorIterator_raw< ETensor, false>;
template <typename ETensor> using TensorIteratorConst = Grid::EigenUtil::TensorIterator_raw<const ETensor, true>;
template <typename ETensor>
inline typename std::enable_if<Grid::EigenIO::is_tensor<ETensor>::value, TensorIterator<ETensor>>::type
begin( ETensor & ET ) { return TensorIterator<ETensor>(ET); }
template <typename ETensor>
inline typename std::enable_if<Grid::EigenIO::is_tensor<ETensor>::value, TensorIterator<ETensor>>::type
end( ETensor & ET ) { return TensorIterator<ETensor>(ET, ET.size()); }
template <typename ETensor>
inline typename std::enable_if<Grid::EigenIO::is_tensor<ETensor>::value, TensorIteratorConst<ETensor>>::type
begin( const ETensor & ET ) { return TensorIteratorConst<ETensor>(ET); }
template <typename ETensor>
inline typename std::enable_if<Grid::EigenIO::is_tensor<ETensor>::value, TensorIteratorConst<ETensor>>::type
end( const ETensor & ET ) { return TensorIteratorConst<ETensor>(ET, ET.size()); }
}
namespace Grid {
// for_all helper function to call the lambda for scalar
template <typename ETensor, typename Lambda>
typename std::enable_if<EigenIO::is_tensor_of_scalar<ETensor>::value, void>::type
for_all_do_lambda( Lambda lambda, typename ETensor::Scalar &scalar, typename ETensor::Index &Seq,
const std::array<typename ETensor::Index, ETensor::NumIndices> &MyIndex,
const std::array<int, EigenIO::Traits<ETensor>::Rank> &DimGridTensor,
std::array<int, EigenIO::Traits<ETensor>::Rank> &GridTensorIndex)
{
lambda( scalar, Seq++, MyIndex, GridTensorIndex );
}
// for_all helper function to call the lambda for container
template <typename ETensor, typename Lambda>
typename std::enable_if<EigenIO::is_tensor_of_container<ETensor>::value, void>::type
for_all_do_lambda( Lambda lambda, typename ETensor::Scalar &container, typename ETensor::Index &Seq,
const std::array<typename ETensor::Index, ETensor::NumIndices> &MyIndex,
const std::array<int, EigenIO::Traits<ETensor>::Rank> &DimGridTensor,
std::array<int, EigenIO::Traits<ETensor>::Rank> &GridTensorIndex)
{
using Traits = EigenIO::Traits<ETensor>;
const int InnerRank = Traits::Rank;
for( typename Traits::scalar_type &Source : container ) {
lambda(Source, Seq++, MyIndex, GridTensorIndex );
// Now increment SubIndex
for( int i = InnerRank - 1; i != -1 && ++GridTensorIndex[i] == DimGridTensor[i]; i-- )
GridTensorIndex[i] = 0;
}
}
// Calls a lamda (passing index and sequence number) for every member of an Eigen::Tensor
// For efficiency, iteration proceeds in memory order,
// ... but parameters guaranteed to be the same regardless of memory order
template <typename ETensor, typename Lambda>
typename std::enable_if<EigenIO::is_tensor<ETensor>::value, void>::type
for_all( ETensor &ET, Lambda lambda )
{
using Scalar = typename ETensor::Scalar; // This could be a Container - we'll check later
using Index = typename ETensor::Index;
using Traits = EigenIO::Traits<ETensor>;
// Check that the number of elements in the container is the product of tensor dimensions
const Index NumScalars = ET.size();
assert( NumScalars > 0 && "EigenUtil: tensor has no elements" );
Index ScalarElementCount{1};
const int rank{ETensor::NumIndices};
std::array<Index, rank> DimTensor, MyIndex;
for(int i = 0; i < rank; i++ ) {
DimTensor[i] = ET.dimension(i);
ScalarElementCount *= DimTensor[i];
MyIndex[i] = 0;
}
assert( NumScalars == ScalarElementCount && "EigenUtil: tensor size not product of dimensions" );
// Save the GridTensor dimensions
const int InnerRank{Traits::Rank};
std::array<int, InnerRank> DimGridTensor, GridTensorIndex;
for(int i = 0; i < InnerRank; i++ ) {
DimGridTensor[i] = Traits::Dimension(i);
GridTensorIndex[i] = 0;
}
// Now walk the tensor in memory order
Index Seq = 0;
Scalar * pScalar = ET.data();
for( Index j = 0; j < NumScalars; j++ ) {
for_all_do_lambda<ETensor, Lambda>( lambda, * pScalar, Seq, MyIndex, DimGridTensor, GridTensorIndex );
// Now increment the index to pass to the lambda (bearing in mind we're walking in memory order)
if( ETensor::Options & Eigen::RowMajor ) {
for( int i = rank - 1; i != -1 && ++MyIndex[i] == DimTensor[i]; i-- )
MyIndex[i] = 0;
} else {
for( int i = 0; i < rank && ++MyIndex[i] == DimTensor[i]; i++ )
MyIndex[i] = 0;
Seq = 0;
for( int i = 0; i < rank; i++ ) {
Seq *= DimTensor[i];
Seq += MyIndex[i];
}
Seq *= Traits::count;
}
pScalar++;
}
}
// Sequential initialisation of tensors up to specified precision
// Would have preferred to define template variables for this, but that's c++ 17
template <typename ETensor>
typename std::enable_if<EigenIO::is_tensor<ETensor>::value && !EigenIO::Traits<ETensor>::is_complex>::type
SequentialInit( ETensor &ET, typename EigenIO::Traits<ETensor>::scalar_type Inc = 1, unsigned short Precision = 0 )
{
using Traits = EigenIO::Traits<ETensor>;
using scalar_type = typename Traits::scalar_type;
using Index = typename ETensor::Index;
for_all( ET, [&](scalar_type &c, Index n, const std::array<Index, ETensor::NumIndices> &TensorIndex,
const std::array<int, Traits::Rank> &ScalarIndex ) {
scalar_type x = Inc * static_cast<scalar_type>(n);
if( Precision ) {
std::stringstream s;
s << std::setprecision(Precision) << x;
s >> x;
}
c = x;
} );
}
template <typename ETensor>
typename std::enable_if<EigenIO::is_tensor<ETensor>::value && EigenIO::Traits<ETensor>::is_complex>::type
SequentialInit( ETensor &ET, typename EigenIO::Traits<ETensor>::scalar_type Inc={1,-1}, unsigned short Precision = 0 )
{
using Traits = EigenIO::Traits<ETensor>;
using scalar_type = typename Traits::scalar_type;
using Index = typename ETensor::Index;
for_all( ET, [&](scalar_type &c, Index n, const std::array<Index, ETensor::NumIndices> &TensorIndex,
const std::array<int, Traits::Rank> &ScalarIndex ) {
auto re = Inc.real();
auto im = Inc.imag();
re *= n;
im *= n;
if( Precision ) {
std::stringstream s;
s << std::setprecision(Precision) << re;
s >> re;
s.clear();
s << im;
s >> im;
}
c = scalar_type(re,im);
} );
}
// Helper to dump a tensor
template <typename T>
typename std::enable_if<EigenIO::is_tensor<T>::value, void>::type
dump_tensor(T &t, const char * pName = nullptr)
{
using Traits = EigenIO::Traits<T>;
using scalar_type = typename Traits::scalar_type;
using Index = typename T::Index;
const int rank{T::NumIndices};
const auto &dims = t.dimensions();
std::cout << "Dumping rank " << rank + Traits::Rank << ((T::Options & Eigen::RowMajor) ? ", row" : ", column") << "-major tensor ";
if( pName )
std::cout << pName;
for( int i = 0 ; i < rank; i++ ) std::cout << "[" << dims[i] << "]";
for( int i = 0 ; i < Traits::Rank; i++ ) std::cout << "(" << Traits::Dimension(i) << ")";
std::cout << " in memory order:" << std::endl;
for( auto it = begin(t); !it.AtEnd(); ++it ) {
std::cout << " ";
it.DumpIndex();
std::cout << " = " << (const typename T::Scalar)(*it) << std::endl;
}
std::cout << "========================================" << std::endl;
}
template <typename T>
typename std::enable_if<!EigenIO::is_tensor<T>::value, void>::type
dump_tensor(T &t, const char * pName = nullptr)
{
std::cout << "Dumping non-tensor object ";
if( pName ) std::cout << pName;
std::cout << "=" << t;
}
}
#endif

View File

@ -1,66 +1,78 @@
#include <Hadrons/Modules/MContraction/WeakEye3pt.hpp>
#include <Hadrons/Modules/MContraction/Baryon.hpp>
#include <Hadrons/Modules/MContraction/A2AAslashField.hpp>
#include <Hadrons/Modules/MContraction/A2ALoop.hpp>
#include <Hadrons/Modules/MContraction/A2AMesonField.hpp>
#include <Hadrons/Modules/MContraction/Meson.hpp>
#include <Hadrons/Modules/MContraction/DiscLoop.hpp>
#include <Hadrons/Modules/MContraction/Gamma3pt.hpp>
#include <Hadrons/Modules/MContraction/WeakNonEye3pt.hpp>
#include <Hadrons/Modules/MFermion/FreeProp.hpp>
#include <Hadrons/Modules/MFermion/GaugeProp.hpp>
#include <Hadrons/Modules/MSource/SeqGamma.hpp>
#include <Hadrons/Modules/MSource/Point.hpp>
#include <Hadrons/Modules/MSource/Wall.hpp>
#include <Hadrons/Modules/MSource/Z2.hpp>
#include <Hadrons/Modules/MSource/SeqConserved.hpp>
#include <Hadrons/Modules/MSource/Momentum.hpp>
#include <Hadrons/Modules/MSink/Smear.hpp>
#include <Hadrons/Modules/MSink/Point.hpp>
#include <Hadrons/Modules/MUtilities/RandomVectors.hpp>
#include <Hadrons/Modules/MUtilities/PrecisionCast.hpp>
#include <Hadrons/Modules/MSolver/MixedPrecisionRBPrecCG.hpp>
#include <Hadrons/Modules/MSolver/LocalCoherenceLanczos.hpp>
#include <Hadrons/Modules/MSolver/A2AAslashVectors.hpp>
#include <Hadrons/Modules/MSolver/Guesser.hpp>
#include <Hadrons/Modules/MSolver/LocalCoherenceLanczos.hpp>
#include <Hadrons/Modules/MSolver/RBPrecCG.hpp>
#include <Hadrons/Modules/MSolver/A2AVectors.hpp>
#include <Hadrons/Modules/MGauge/UnitEm.hpp>
#include <Hadrons/Modules/MGauge/StoutSmearing.hpp>
#include <Hadrons/Modules/MGauge/Unit.hpp>
#include <Hadrons/Modules/MGauge/Random.hpp>
#include <Hadrons/Modules/MGauge/GaugeFix.hpp>
#include <Hadrons/Modules/MGauge/FundtoHirep.hpp>
#include <Hadrons/Modules/MGauge/StochEm.hpp>
#include <Hadrons/Modules/MGauge/Electrify.hpp>
#include <Hadrons/Modules/MNoise/TimeDilutedSpinColorDiagonal.hpp>
#include <Hadrons/Modules/MNoise/FullVolumeSpinColorDiagonal.hpp>
#include <Hadrons/Modules/MUtilities/PrecisionCast.hpp>
#include <Hadrons/Modules/MUtilities/RandomVectors.hpp>
#include <Hadrons/Modules/MScalar/FreeProp.hpp>
#include <Hadrons/Modules/MScalar/Scalar.hpp>
#include <Hadrons/Modules/MScalar/ChargedProp.hpp>
#include <Hadrons/Modules/MNPR/Bilinear.hpp>
#include <Hadrons/Modules/MNPR/Amputate.hpp>
#include <Hadrons/Modules/MNPR/FourQuark.hpp>
#include <Hadrons/Modules/MAction/DWF.hpp>
#include <Hadrons/Modules/MAction/MobiusDWF.hpp>
#include <Hadrons/Modules/MDistil/LapEvec.hpp>
#include <Hadrons/Modules/MDistil/Distil.hpp>
#include <Hadrons/Modules/MDistil/g5_multiply.hpp>
#include <Hadrons/Modules/MDistil/Noises.hpp>
#include <Hadrons/Modules/MDistil/DistilVectors.hpp>
#include <Hadrons/Modules/MDistil/Baryon2pt.hpp>
#include <Hadrons/Modules/MDistil/BContraction.hpp>
#include <Hadrons/Modules/MDistil/PerambLight.hpp>
#include <Hadrons/Modules/MDistil/DistilSink.hpp>
#include <Hadrons/Modules/MDistil/PerambFromSolve.hpp>
#include <Hadrons/Modules/MDistil/BC2.hpp>
#include <Hadrons/Modules/MContraction/WeakNonEye3pt.hpp>
#include <Hadrons/Modules/MContraction/WeakEye3pt.hpp>
#include <Hadrons/Modules/MContraction/DiscLoop.hpp>
#include <Hadrons/Modules/MContraction/Baryon.hpp>
#include <Hadrons/Modules/MContraction/Gamma3pt.hpp>
#include <Hadrons/Modules/MContraction/A2ALoop.hpp>
#include <Hadrons/Modules/MContraction/A2AMesonField.hpp>
#include <Hadrons/Modules/MContraction/A2AAslashField.hpp>
#include <Hadrons/Modules/MContraction/Meson.hpp>
#include <Hadrons/Modules/MAction/Wilson.hpp>
#include <Hadrons/Modules/MAction/WilsonClover.hpp>
#include <Hadrons/Modules/MAction/ZMobiusDWF.hpp>
#include <Hadrons/Modules/MAction/DWF.hpp>
#include <Hadrons/Modules/MAction/ScaledDWF.hpp>
#include <Hadrons/Modules/MScalarSUN/StochFreeField.hpp>
#include <Hadrons/Modules/MScalarSUN/TwoPointNPR.hpp>
#include <Hadrons/Modules/MScalarSUN/Div.hpp>
#include <Hadrons/Modules/MScalarSUN/TrMag.hpp>
#include <Hadrons/Modules/MScalarSUN/EMT.hpp>
#include <Hadrons/Modules/MScalarSUN/TwoPoint.hpp>
#include <Hadrons/Modules/MScalarSUN/TrPhi.hpp>
#include <Hadrons/Modules/MScalarSUN/Utils.hpp>
#include <Hadrons/Modules/MScalarSUN/TransProj.hpp>
#include <Hadrons/Modules/MScalarSUN/Grad.hpp>
#include <Hadrons/Modules/MScalarSUN/TrKinetic.hpp>
#include <Hadrons/Modules/MIO/LoadEigenPack.hpp>
#include <Hadrons/Modules/MAction/ZMobiusDWF.hpp>
#include <Hadrons/Modules/MAction/MobiusDWF.hpp>
#include <Hadrons/Modules/MGauge/Random.hpp>
#include <Hadrons/Modules/MGauge/Unit.hpp>
#include <Hadrons/Modules/MGauge/UnitEm.hpp>
#include <Hadrons/Modules/MGauge/StoutSmearing.hpp>
#include <Hadrons/Modules/MGauge/StochEm.hpp>
#include <Hadrons/Modules/MGauge/Electrify.hpp>
#include <Hadrons/Modules/MGauge/FundtoHirep.hpp>
#include <Hadrons/Modules/MGauge/GaugeFix.hpp>
#include <Hadrons/Modules/MNoise/TimeDilutedSpinColorDiagonal.hpp>
#include <Hadrons/Modules/MNoise/FullVolumeSpinColorDiagonal.hpp>
#include <Hadrons/Modules/MIO/LoadBinary.hpp>
#include <Hadrons/Modules/MIO/LoadCosmHol.hpp>
#include <Hadrons/Modules/MIO/LoadNersc.hpp>
#include <Hadrons/Modules/MIO/LoadA2AVectors.hpp>
#include <Hadrons/Modules/MIO/LoadCosmHol.hpp>
#include <Hadrons/Modules/MIO/LoadCoarseEigenPack.hpp>
#include <Hadrons/Modules/MIO/LoadBinary.hpp>
#include <Hadrons/Modules/MIO/LoadEigenPack.hpp>
#include <Hadrons/Modules/MIO/LoadPerambulator.hpp>
#include <Hadrons/Modules/MNPR/Amputate.hpp>
#include <Hadrons/Modules/MNPR/FourQuark.hpp>
#include <Hadrons/Modules/MNPR/Bilinear.hpp>
#include <Hadrons/Modules/MScalarSUN/TransProj.hpp>
#include <Hadrons/Modules/MScalarSUN/TwoPoint.hpp>
#include <Hadrons/Modules/MScalarSUN/TrMag.hpp>
#include <Hadrons/Modules/MScalarSUN/TrKinetic.hpp>
#include <Hadrons/Modules/MScalarSUN/EMT.hpp>
#include <Hadrons/Modules/MScalarSUN/Grad.hpp>
#include <Hadrons/Modules/MScalarSUN/Utils.hpp>
#include <Hadrons/Modules/MScalarSUN/Div.hpp>
#include <Hadrons/Modules/MScalarSUN/TrPhi.hpp>
#include <Hadrons/Modules/MScalarSUN/TwoPointNPR.hpp>
#include <Hadrons/Modules/MScalarSUN/StochFreeField.hpp>
#include <Hadrons/Modules/MSink/Smear.hpp>
#include <Hadrons/Modules/MSink/Point.hpp>
#include <Hadrons/Modules/MFermion/GaugeProp.hpp>
#include <Hadrons/Modules/MFermion/FreeProp.hpp>
#include <Hadrons/Modules/MScalar/Scalar.hpp>
#include <Hadrons/Modules/MScalar/FreeProp.hpp>
#include <Hadrons/Modules/MScalar/ChargedProp.hpp>
#include <Hadrons/Modules/MSource/Momentum.hpp>
#include <Hadrons/Modules/MSource/SeqGamma.hpp>
#include <Hadrons/Modules/MSource/Point.hpp>
#include <Hadrons/Modules/MSource/Z2.hpp>
#include <Hadrons/Modules/MSource/Wall.hpp>
#include <Hadrons/Modules/MSource/SeqConserved.hpp>

View File

@ -7,6 +7,7 @@ Source file: Hadrons/Modules/MGauge/GaugeFix.hpp
Copyright (C) 2015-2019
Author: Antonin Portelli <antonin.portelli@me.com>
Author: Nils Asmussen <n.asmussen@soton.ac.uk>
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
This program is free software; you can redistribute it and/or modify
@ -58,6 +59,7 @@ class TGaugeFix: public Module<GaugeFixPar>
{
public:
GAUGE_TYPE_ALIASES(GImpl,);
typedef typename GImpl::GaugeLinkField GaugeMat;
public:
// constructor
TGaugeFix(const std::string name);
@ -94,7 +96,7 @@ std::vector<std::string> TGaugeFix<GImpl>::getInput(void)
template <typename GImpl>
std::vector<std::string> TGaugeFix<GImpl>::getOutput(void)
{
std::vector<std::string> out = {getName()};
std::vector<std::string> out = {getName(), getName()+"_xform"};
return out;
}
@ -103,6 +105,7 @@ template <typename GImpl>
void TGaugeFix<GImpl>::setup(void)
{
envCreateLat(GaugeField, getName());
envCreateLat(GaugeMat, getName()+"_xform");
}
@ -116,6 +119,7 @@ void TGaugeFix<GImpl>::execute(void)
LOG(Message) << par().gauge << std::endl;
auto &U = envGet(GaugeField, par().gauge);
auto &Umu = envGet(GaugeField, getName());
auto &xform = envGet(GaugeMat, getName()+"_xform");
LOG(Message) << "Gauge Field fetched" << std::endl;
//do we allow maxiter etc to be user set?
Real alpha = par().alpha;
@ -123,8 +127,8 @@ void TGaugeFix<GImpl>::execute(void)
Real Omega_tol = par().Omega_tol;
Real Phi_tol = par().Phi_tol;
bool Fourier = par().Fourier;
FourierAcceleratedGaugeFixer<PeriodicGimplR>::SteepestDescentGaugeFix(U,alpha,maxiter,Omega_tol,Phi_tol,Fourier);
Umu = U;
FourierAcceleratedGaugeFixer<PeriodicGimplR>::SteepestDescentGaugeFix(Umu,xform,alpha,maxiter,Omega_tol,Phi_tol,Fourier);
LOG(Message) << "Gauge Fixed" << std::endl;
}

View File

@ -1,133 +1,156 @@
modules_cc =\
Modules/MContraction/Baryon.cc \
Modules/MContraction/Meson.cc \
Modules/MContraction/WeakEye3pt.cc \
Modules/MContraction/A2ALoop.cc \
Modules/MContraction/WeakNonEye3pt.cc \
Modules/MContraction/A2AAslashField.cc \
Modules/MContraction/A2AMesonField.cc \
Modules/MContraction/DiscLoop.cc \
Modules/MContraction/Gamma3pt.cc \
Modules/MFermion/FreeProp.cc \
Modules/MFermion/GaugeProp.cc \
Modules/MSource/Momentum.cc \
Modules/MSource/Point.cc \
Modules/MSource/Wall.cc \
Modules/MSource/SeqConserved.cc \
Modules/MSource/SeqGamma.cc \
Modules/MSource/Z2.cc \
Modules/MSink/Point.cc \
Modules/MSink/Smear.cc \
Modules/MSolver/A2AVectors.cc \
Modules/MSolver/A2AAslashVectors.cc \
Modules/MSolver/RBPrecCG.cc \
Modules/MSolver/MixedPrecisionRBPrecCG.cc \
Modules/MSolver/LocalCoherenceLanczos.cc \
Modules/MGauge/StoutSmearing.cc \
Modules/MGauge/Unit.cc \
Modules/MGauge/UnitEm.cc \
Modules/MGauge/StochEm.cc \
Modules/MGauge/Random.cc \
Modules/MGauge/Electrify.cc \
Modules/MGauge/FundtoHirep.cc \
Modules/MGauge/GaugeFix.cc \
Modules/MNoise/FullVolumeSpinColorDiagonal.cc \
Modules/MNoise/TimeDilutedSpinColorDiagonal.cc \
Modules/MUtilities/RandomVectors.cc \
Modules/MUtilities/PrecisionCast.cc \
Modules/MScalar/FreeProp.cc \
Modules/MScalar/ChargedProp.cc \
Modules/MSolver/MixedPrecisionRBPrecCG.cc \
Modules/MSolver/A2AVectors.cc \
Modules/MSolver/A2AAslashVectors.cc \
Modules/MSolver/LocalCoherenceLanczos.cc \
Modules/MSolver/RBPrecCG.cc \
Modules/MDistil/g5_multiply.cc \
Modules/MDistil/BContraction.cc \
Modules/MDistil/BC2.cc \
Modules/MDistil/LapEvec.cc \
Modules/MDistil/PerambFromSolve.cc \
Modules/MDistil/Baryon2pt.cc \
Modules/MDistil/PerambLight.cc \
Modules/MDistil/DistilSink.cc \
Modules/MDistil/Noises.cc \
Modules/MDistil/DistilVectors.cc \
Modules/MContraction/WeakEye3pt.cc \
Modules/MContraction/WeakNonEye3pt.cc \
Modules/MContraction/Gamma3pt.cc \
Modules/MContraction/DiscLoop.cc \
Modules/MContraction/Meson.cc \
Modules/MContraction/A2ALoop.cc \
Modules/MContraction/A2AMesonField.cc \
Modules/MContraction/Baryon.cc \
Modules/MContraction/A2AAslashField.cc \
Modules/MAction/ZMobiusDWF.cc \
Modules/MAction/WilsonClover.cc \
Modules/MAction/Wilson.cc \
Modules/MAction/DWF.cc \
Modules/MAction/MobiusDWF.cc \
Modules/MAction/ScaledDWF.cc \
Modules/MGauge/FundtoHirep.cc \
Modules/MGauge/Random.cc \
Modules/MGauge/UnitEm.cc \
Modules/MGauge/StochEm.cc \
Modules/MGauge/GaugeFix.cc \
Modules/MGauge/Unit.cc \
Modules/MGauge/StoutSmearing.cc \
Modules/MGauge/Electrify.cc \
Modules/MNoise/TimeDilutedSpinColorDiagonal.cc \
Modules/MNoise/FullVolumeSpinColorDiagonal.cc \
Modules/MIO/LoadNersc.cc \
Modules/MIO/LoadA2AVectors.cc \
Modules/MIO/LoadCoarseEigenPack.cc \
Modules/MIO/LoadEigenPack.cc \
Modules/MIO/LoadPerambulator.cc \
Modules/MIO/LoadBinary.cc \
Modules/MIO/LoadCosmHol.cc \
Modules/MNPR/Amputate.cc \
Modules/MNPR/Bilinear.cc \
Modules/MNPR/FourQuark.cc \
Modules/MAction/Wilson.cc \
Modules/MAction/MobiusDWF.cc \
Modules/MAction/ZMobiusDWF.cc \
Modules/MAction/WilsonClover.cc \
Modules/MAction/DWF.cc \
Modules/MAction/ScaledDWF.cc \
Modules/MScalarSUN/TrPhi.cc \
Modules/MScalarSUN/Grad.cc \
Modules/MScalarSUN/TrMag.cc \
Modules/MScalarSUN/TrKinetic.cc \
Modules/MScalarSUN/EMT.cc \
Modules/MScalarSUN/TransProj.cc \
Modules/MScalarSUN/StochFreeField.cc \
Modules/MScalarSUN/TwoPoint.cc \
Modules/MScalarSUN/TwoPointNPR.cc \
Modules/MScalarSUN/Div.cc \
Modules/MIO/LoadEigenPack.cc \
Modules/MIO/LoadBinary.cc \
Modules/MIO/LoadNersc.cc \
Modules/MIO/LoadCoarseEigenPack.cc \
Modules/MIO/LoadCosmHol.cc \
Modules/MIO/LoadA2AVectors.cc
Modules/MScalarSUN/TwoPointNPR.cc \
Modules/MScalarSUN/TrPhi.cc \
Modules/MScalarSUN/TrMag.cc \
Modules/MScalarSUN/TransProj.cc \
Modules/MScalarSUN/TrKinetic.cc \
Modules/MScalarSUN/StochFreeField.cc \
Modules/MScalarSUN/EMT.cc \
Modules/MScalarSUN/Grad.cc \
Modules/MSink/Smear.cc \
Modules/MSink/Point.cc \
Modules/MFermion/GaugeProp.cc \
Modules/MFermion/FreeProp.cc \
Modules/MScalar/FreeProp.cc \
Modules/MScalar/ChargedProp.cc \
Modules/MSource/SeqConserved.cc \
Modules/MSource/SeqGamma.cc \
Modules/MSource/Wall.cc \
Modules/MSource/Z2.cc \
Modules/MSource/Point.cc \
Modules/MSource/Momentum.cc
modules_hpp =\
Modules/MContraction/WeakEye3pt.hpp \
Modules/MContraction/Baryon.hpp \
Modules/MContraction/A2AAslashField.hpp \
Modules/MContraction/A2ALoop.hpp \
Modules/MContraction/A2AMesonField.hpp \
Modules/MContraction/Meson.hpp \
Modules/MContraction/DiscLoop.hpp \
Modules/MContraction/Gamma3pt.hpp \
Modules/MContraction/WeakNonEye3pt.hpp \
Modules/MFermion/FreeProp.hpp \
Modules/MFermion/GaugeProp.hpp \
Modules/MSource/SeqGamma.hpp \
Modules/MSource/Point.hpp \
Modules/MSource/Wall.hpp \
Modules/MSource/Z2.hpp \
Modules/MSource/SeqConserved.hpp \
Modules/MSource/Momentum.hpp \
Modules/MSink/Smear.hpp \
Modules/MSink/Point.hpp \
Modules/MUtilities/RandomVectors.hpp \
Modules/MUtilities/PrecisionCast.hpp \
Modules/MSolver/MixedPrecisionRBPrecCG.hpp \
Modules/MSolver/LocalCoherenceLanczos.hpp \
Modules/MSolver/A2AAslashVectors.hpp \
Modules/MSolver/Guesser.hpp \
Modules/MSolver/LocalCoherenceLanczos.hpp \
Modules/MSolver/RBPrecCG.hpp \
Modules/MSolver/A2AVectors.hpp \
Modules/MGauge/UnitEm.hpp \
Modules/MGauge/StoutSmearing.hpp \
Modules/MGauge/Unit.hpp \
Modules/MGauge/Random.hpp \
Modules/MGauge/GaugeFix.hpp \
Modules/MGauge/FundtoHirep.hpp \
Modules/MGauge/StochEm.hpp \
Modules/MGauge/Electrify.hpp \
Modules/MNoise/TimeDilutedSpinColorDiagonal.hpp \
Modules/MNoise/FullVolumeSpinColorDiagonal.hpp \
Modules/MUtilities/PrecisionCast.hpp \
Modules/MUtilities/RandomVectors.hpp \
Modules/MScalar/FreeProp.hpp \
Modules/MScalar/Scalar.hpp \
Modules/MScalar/ChargedProp.hpp \
Modules/MNPR/Bilinear.hpp \
Modules/MNPR/Amputate.hpp \
Modules/MNPR/FourQuark.hpp \
Modules/MAction/DWF.hpp \
Modules/MAction/MobiusDWF.hpp \
Modules/MDistil/LapEvec.hpp \
Modules/MDistil/Distil.hpp \
Modules/MDistil/g5_multiply.hpp \
Modules/MDistil/Noises.hpp \
Modules/MDistil/DistilVectors.hpp \
Modules/MDistil/Baryon2pt.hpp \
Modules/MDistil/BContraction.hpp \
Modules/MDistil/PerambLight.hpp \
Modules/MDistil/DistilSink.hpp \
Modules/MDistil/PerambFromSolve.hpp \
Modules/MDistil/BC2.hpp \
Modules/MContraction/WeakNonEye3pt.hpp \
Modules/MContraction/WeakEye3pt.hpp \
Modules/MContraction/DiscLoop.hpp \
Modules/MContraction/Baryon.hpp \
Modules/MContraction/Gamma3pt.hpp \
Modules/MContraction/A2ALoop.hpp \
Modules/MContraction/A2AMesonField.hpp \
Modules/MContraction/A2AAslashField.hpp \
Modules/MContraction/Meson.hpp \
Modules/MAction/Wilson.hpp \
Modules/MAction/WilsonClover.hpp \
Modules/MAction/ZMobiusDWF.hpp \
Modules/MAction/DWF.hpp \
Modules/MAction/ScaledDWF.hpp \
Modules/MScalarSUN/StochFreeField.hpp \
Modules/MScalarSUN/TwoPointNPR.hpp \
Modules/MScalarSUN/Div.hpp \
Modules/MScalarSUN/TrMag.hpp \
Modules/MScalarSUN/EMT.hpp \
Modules/MScalarSUN/TwoPoint.hpp \
Modules/MScalarSUN/TrPhi.hpp \
Modules/MScalarSUN/Utils.hpp \
Modules/MScalarSUN/TransProj.hpp \
Modules/MScalarSUN/Grad.hpp \
Modules/MScalarSUN/TrKinetic.hpp \
Modules/MIO/LoadEigenPack.hpp \
Modules/MAction/ZMobiusDWF.hpp \
Modules/MAction/MobiusDWF.hpp \
Modules/MGauge/Random.hpp \
Modules/MGauge/Unit.hpp \
Modules/MGauge/UnitEm.hpp \
Modules/MGauge/StoutSmearing.hpp \
Modules/MGauge/StochEm.hpp \
Modules/MGauge/Electrify.hpp \
Modules/MGauge/FundtoHirep.hpp \
Modules/MGauge/GaugeFix.hpp \
Modules/MNoise/TimeDilutedSpinColorDiagonal.hpp \
Modules/MNoise/FullVolumeSpinColorDiagonal.hpp \
Modules/MIO/LoadBinary.hpp \
Modules/MIO/LoadCosmHol.hpp \
Modules/MIO/LoadNersc.hpp \
Modules/MIO/LoadA2AVectors.hpp \
Modules/MIO/LoadCosmHol.hpp \
Modules/MIO/LoadCoarseEigenPack.hpp \
Modules/MIO/LoadBinary.hpp
Modules/MIO/LoadEigenPack.hpp \
Modules/MIO/LoadPerambulator.hpp \
Modules/MNPR/Amputate.hpp \
Modules/MNPR/FourQuark.hpp \
Modules/MNPR/Bilinear.hpp \
Modules/MScalarSUN/TransProj.hpp \
Modules/MScalarSUN/TwoPoint.hpp \
Modules/MScalarSUN/TrMag.hpp \
Modules/MScalarSUN/TrKinetic.hpp \
Modules/MScalarSUN/EMT.hpp \
Modules/MScalarSUN/Grad.hpp \
Modules/MScalarSUN/Utils.hpp \
Modules/MScalarSUN/Div.hpp \
Modules/MScalarSUN/TrPhi.hpp \
Modules/MScalarSUN/TwoPointNPR.hpp \
Modules/MScalarSUN/StochFreeField.hpp \
Modules/MSink/Smear.hpp \
Modules/MSink/Point.hpp \
Modules/MFermion/GaugeProp.hpp \
Modules/MFermion/FreeProp.hpp \
Modules/MScalar/Scalar.hpp \
Modules/MScalar/FreeProp.hpp \
Modules/MScalar/ChargedProp.hpp \
Modules/MSource/Momentum.hpp \
Modules/MSource/SeqGamma.hpp \
Modules/MSource/Point.hpp \
Modules/MSource/Z2.hpp \
Modules/MSource/Wall.hpp \
Modules/MSource/SeqConserved.hpp

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

View File

@ -0,0 +1,422 @@
# Using Xcode with Grid on Mac OS
This guide explains how to use Xcode as an IDE on Mac OS.
# Initial setup
For first time setup of the Xcode and Grid build environment on Mac OS, you will need to do the following, in this order:
1. Install Xcode and the Xcode command-line utilities
2. Set Grid environment variables
3. Install and build Open MPI ***optional***
4. Install and build Grid pre-requisites
5. Install, Configure and Build Grid
Apple's [Xcode website][Xcode] is the go-to reference for 1, and the definitive reference for 4 and 5 is the [Grid Documentation][GridDoc].
[Xcode]: https://developer.apple.com/xcode/
[GridDoc]: https://github.com/paboyle/Grid/blob/develop/documentation/Grid.pdf
The following sections explain these steps in more detail
## 1. Install Xcode and the Xcode command-line utilities
See Apple's [Xcode website][Xcode] for instructions on installing Xcode.
Once Xcode is installed, install the Xcode command-line utilities using:
xcode-select --install
*NB: the screenshots from this guide were generated from Xcode 10.1.*
## 2. Set Grid environment variables
To make sure we can share Xcode projects via git and have them work without requiring modification, we will define Grid environment variables. To make sure these environment variables will be available to the Xcode build system, issue the following command:
defaults write com.apple.dt.Xcode UseSanitizedBuildSystemEnvironment -bool NO
These are the environment variables we will define for Grid:
Variable | Typical Value | Use
--- | --- | ---
`Grid` | `/Users/user_id/src/Grid` | Path to grid source
`GridPre` | `/Users/user_id/bin` | Path to install directory containing grid pre-requisites built from source
`GridPkg` | **MacPorts**=`/opt/local`, **Homebrew**=`/usr/local` | Path to package manager install directory
Choose either of the following ways to do this, and when you're done, log out and in again. To check these have been set:
printenv|grep -i grid
### Method 1 -- Apple Script
* Start *Script Editor* (cmd-space, *script editor*)
* Click on *New Document*. Paste the following into the new script, editing the paths appropriately (just replace `user_id` with your *user_id* if you are unsure):
```apple script
do shell script "launchctl setenv Grid $HOME/src/Grid
launchctl setenv GridPre $HOME/bin
launchctl setenv GridPkg /opt/local"
```
* Save the script inside `~/Applications` and give it the name `GridEnv.app`.
* Open `System Preferences`, `Users & Groups`
* Click on `Login Items`
* Click the plus sign to add a new login item
* Select the `~/Applications` folder and select `GridEnv.app`
Log out and in again.
### Method 2 -- `environment.plist`
Make the file `environment.plist` in `~/Library/LaunchAgents` with the following contents, editing the paths appropriately (just replace `user_id` with your *user_id* if you are unsure):
```html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>Grid.startup</string>
<key>ProgramArguments</key>
<array>
<string>sh</string>
<string>-c</string>
<string>launchctl setenv Grid $HOME/src/Grid
launchctl setenv GridPre $HOME/bin
launchctl setenv GridPkg /opt/local</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
```
## 3. Install and build Open MPI -- ***optional***
Download the latest version of [Open MPI][OMPI] version 3.1 (I used 3.1.3).
NB: Grid does not have any dependencies on fortran, however many standard scientific packages do, so you may as well download GNU fortran (e.g. MacPorts ``gfortran`` package) and build Open MPI like so:
[OMPI]: https://www.open-mpi.org/software/ompi/v3.1/
../configure CC=clang CXX=clang++ F77=gfortran FC=gfortran CXXFLAGS=-g --prefix=$GridPre/openmpi-3.1.3
make -j 4 all install
(If you don't want to bother with fortran bindings, just don't include the F77 and FC flags)
## 4. Install and build Grid pre-requisites
To simplify the installation of **Grid pre-requisites**, you can use your favourite package manager, e.g.:
### 1. [MacPorts][MacPorts]
[MacPorts]: https://www.macports.org "MacPorts package manager"
Install [MacPorts][MacPorts] if you haven't done so already, and then install packages with:
sudo port install <portname>
These are the `portname`s for mandatory Grid libraries:
* git
* gmp
* mpfr
and these are the `portname`s for optional Grid libraries:
* fftw-3
* hdf5
* lapack
* doxygen
* OpenBLAS
***Please update this list with any packages I've missed! ... and double-check whether OpenBLAS is really for Grid***
### 2. [Homebrew][Homebrew]
[Homebrew]: https://brew.sh "Homebrew package manager"
Install [Homebrew][Homebrew] if you haven't done so already, and then install packages with:
sudo brew install <packagename>
The same packages are available as from MacPorts.
### Install LIME ***optional***
There isn't currently a port for [C-LIME][C-LIME], so download the source and then build it:
[C-LIME]: https://usqcd-software.github.io/c-lime/ "C-language API for Lattice QCD Interchange Message Encapsulation / Large Internet Message Encapsulation"
../configure --prefix=$GridPre/lime-1.3.2 CC=clang
make -j 4
make install
## 5. Install, Configure and Build Grid
### 5.1 Install Grid
[Grid]: https://github.com/paboyle/Grid
Start by cloning [Grid (from GitHub)][Grid] ***into the directory you specified in*** `$Grid`. Bear in mind that git will create the `Grid` subdirectory to place Grid in, so for example if `$Grid` is set to `~/src/Grid` then install Grid with:
cd ~/src
followed by either:
git clone git@github.com:paboyle/Grid.git
or
git clone https://github.com/paboyle/Grid.git
depending on whether you are using https or ssh.
### 5.2 Configure Grid
The Xcode build system supports multiple configurations for each project, by default: `Debug` and `Release`, but more configurations can be defined. We will create separate Grid build directories for each configuration, using the Grid **Autoconf** build system to make each configuration. NB: it is **not** necessary to run `make install` on them once they are built (IDE features such as *jump to definition* will work better of you don't).
Below are shown the `configure` script invocations for three recommended configurations. You are free to define more, less or different configurations, but as a minimum, be sure to build a `Debug` configuration.
#### 1. `Debug`
This is the build for every day developing and debugging with Xcode. It uses the Xcode clang c++ compiler, without MPI, and defaults to double-precision. Xcode builds the `Debug` configuration with debug symbols for full debugging:
../configure --with-hdf5=$GridPkg --with-gmp=$GridPkg --with-mpfr=$GridPkg --with-fftw=$GridPkg --with-lime=$GridPre/lime-1.3.2 --enable-simd=GEN --enable-precision=double CXX=clang++ --prefix=$GridPre/GridDebug --enable-comms=none --enable-doxygen-doc
#### 2. `Release`
Since Grid itself doesn't really have debug configurations, the release build is recommended to be the same as `Debug`, except using single-precision (handy for validation):
../configure --with-hdf5=$GridPkg --with-gmp=$GridPkg --with-mpfr=$GridPkg --with-fftw=$GridPkg --with-lime=$GridPre/lime-1.3.2 --enable-simd=GEN --enable-precision=single CXX=clang++ --prefix=$GridPre/GridRelease --enable-comms=none --enable-doxygen-doc
#### 3. `MPIDebug`
Debug configuration with MPI:
../configure --with-hdf5=$GridPkg --with-gmp=$GridPkg --with-mpfr=$GridPkg --with-fftw=$GridPkg --with-lime=$GridPre/lime-1.3.2 --enable-simd=GEN --enable-precision=double CXX=clang++ --prefix=$GridPre/GridMPIDebug --enable-comms=mpi-auto MPICXX=$GridPre/openmpi-3.1.3/bin/mpicxx --enable-doxygen-doc
### 5.3 Build Grid
Each configuration must be built before they can be used. You can either:
1. Use automake and the Grid Makefile with `make -j 4` (NB: you **do not** need to run `make install` for these to work with Xcode)
2. Build `Grid` and `Hadrons` under Xcode (see below)
# Make a new application which links to Grid / Hadrons
Making an Xcode project which links to Grid / Hadrons is straightforward:
* Make a new application (in the usual way)
* Configure your application to use Grid (via three project settings:)
1. `HEADER_SEARCH_PATHS`
2. `LIBRARY_SEARCH_PATHS`
3. `OTHER_LDFLAGS`
* Make additional configurations, e.g. `MPIDebug` (NB Xcode will make `Debug` and `Release` by default)
Detailed instructions follow, but instead of following the instructions in this section, you can clone `HelloGrid` from the [University of Edinburgh GitLab site][HelloGrid].
[HelloGrid]: https://git.ecdf.ed.ac.uk/s1786208/HelloGrid
## Make a new application
To make a hello world application for Grid:
* Start Xcode
* Click 'Create a new project'
* Click macOS, then in the Application section choose Command Line Tool, then click Next
* Choose options for your new project:
* Product Name: HelloGrid
* Team: None
* Organisation Name: sopa
* Organisation Identifier: uk.ac.ed.ph
* Language: C++
* ... then click Next
* Choose a location for your project, e.g. `$HOME/src`. NB: The project and all its files will be created inside `$HOME/src/HelloGrid`. If you are using Git, you can put the new project under Git source control immediately, if you like. Now click Create.
## Configure your new application to use Grid
Click the project name (`HelloGrid`) in the project navigator pane on the left (command-1 if it's not visible), then click the project name (`HelloGrid`) under `PROJECT` in the second pane. Click the `Build Settings` tab on the right, then under that click `All` and `Combined`. You should see:
![Project settings](GridXcFig1.png)
We now need to make changes to two sections (these are listed in alphabetical order), bearing in mind that if you are not using MPI (or you gave your build directories different names) replace `build_mpidebug` and `build_mpirelease` with the directory names you used.
### 1. Search Paths
#### HEADER_SEARCH_PATHS
Obtain a list of header locations required by Grid by running the following from your Grid build directory (choose an MPI configuration if you built one, e.g. `MPIDebug`):
./grid-config --cxxflags
Output should look similar to:
-I$GridPre/openmpi-3.1.3/include -I$GridPkg/include -I$GridPre/lime-1.3.2/include -I$GridPkg/include -I$GridPkg/include -I$GridPkg/include -O3 -g -std=c++11
The header locations follow the `-I` switches. You can ignore the other switches, and you can ignore duplicate entries, which just mean that your package manager has installed multiple packages in the same location.
*Note: `grid-config` will output absolute paths. Make sure to replace absolute paths with environment variables (such as `$GridPre`) in your settings, so that the project will work unmodified for other collaborators downloading the same project from git.*
Set HEADER_SEARCH_PATHS to:
$Grid/build$(CONFIGURATION)/Grid
$Grid
$Grid/Grid
followed by (***the order is important***) the locations reported by `grid-config --cxxflags`, ignoring duplicates, e.g.:
$GridPre/openmpi-3.1.3/include
$GridPkg/include
$GridPre/lime-1.3.2/include
**Note: the easiest way to set this value is to put it all on one line, space separated, and edit the text to the right of `HEADER_SEARCH_PATHS`**, i.e.:
$Grid/build$(CONFIGURATION)/Grid $Grid $Grid/Grid $GridPre/openmpi-3.1.3/include $GridPkg/include $GridPre/lime-1.3.2/include
#### LIBRARY_SEARCH_PATHS
Obtain a list of library locations required by Grid by running the following from your Grid build directory (again, choose an MPI configuration if you built one, e.g. `MPIDebug`):
./grid-config --ldflags
Output should look similar to:
-L$GridPre/openmpi-3.1.3/lib -L$GridPkg/lib -L$GridPre/lime-1.3.2/lib -L$GridPkg/lib -L$GridPkg/lib -L$GridPkg/lib
Paste the output ***with `$Grid/build$(CONFIGURATION)/Grid $Grid/build$(CONFIGURATION)/Hadrons ` prepended*** into `LIBRARY_SEARCH_PATHS`:
$Grid/build$(CONFIGURATION)/Grid $Grid/build$(CONFIGURATION)/Hadrons $GridPre/openmpi-3.1.3/lib $GridPkg/lib $GridPre/lime-1.3.2/lib
### 2. Linking
#### OTHER_LDFLAGS
The easiest way to link to all required libraries is to obtain a list of all libraries required by Grid by running the following from your Grid build directory:
./grid-config --libs
and pasting the output ***with `-lGrid -lHadrons ` prepended*** (including the `-l` switches) directly into `OTHER_LDFLAGS`, e.g.:
-lGrid -lHadrons -lmpi -lhdf5_cpp -lz -lcrypto -llime -lfftw3f -lfftw3 -lmpfr -lgmp -lstdc++ -lm -lz -lhdf5
## Make additional configurations
On the project settings, `Info` tab, click the plus sign underneath configurations:
![Add configurations](GridXcFig4.png)
Choose `Duplicate "Debug" Configuration` (you can choose `Release` if you prefer) and give the new configuration a name, e.g. `MPIDebug`.
## Edit your source code
A hello world for grid is:
```c++
#include <Grid/Grid.h>
using namespace Grid;
int main(int argc, char * argv[]) {
Grid_init(&argc,&argv);
std::cout << GridLogMessage << "Hello Grid" << std::endl;
Grid_finalize();
return 0;
}
```
## Create a `.gitignore` file for Xcode
You can create an up-to-date .gitignore file to ignore all the Xcode temporary build files using [gitignore.io][GIO].
[GIO]: https://www.gitignore.io/api/xcode
NB: If you let Xcode add your project to git when you created it, you probably want to remove your personal scheme selection from git:
git rm --cached HelloGrid.xcodeproj/xcuserdata/$USER.xcuserdatad/xcschemes/xcschememanagement.plist
## Run your program under the Xcode debugger
First, specify command-line arguments. From the menu, select `Product`, then `Scheme`, then `Edit Scheme`. Select `Run` on the left, then select the `Arguments` tab on the right. Add the following to `Arguments passed on Launch`:
--grid 4.4.4.8
If your program will be manipulating files, it's a good idea to specify the working directory on the `Options` tab under `Use Custom Working Directory` (by default, Xcode launches the program inside the Xcode build folder).
Then click `Close`.
Let's set a breakpoint by clicking on:
Grid_finalize();
then from the menu selecting `Debug`, then `Breakpoints`, then `Add Breakpoint at Current Line`.
Now click on the `Play` button (the right pointing triangle just to the right of the maximise button) to run your program under the debugger. (You may see dialog boxes the first couple of times asking whether to allow MPI to receive network requests - say yes to these.)
The debug output pane opens at the bottom of Xcode, with output on the right (ending with `Hello Grid`) and local variables on the left i.e.:
![Running under the debugger](GridXcFig2.png)
See the Xcode documentation to learn about the debugger. When you're done, press `ctl-cmd-Y` to let the program run to completion.
# Debugging multiple MPI processes under Xcode
You could tell Xcode to use mpirun to launch multiple copies of a target executable, however if you do this the debugger will attach to mpirun - not your target process.
Instead:
1. Set a breakpoint just inside `main()` (otherwise your programs may complete before you attach to them all)
2. From the `Debug` menu, select `Attach to Process by PID or Name ...`. In the `PID or Process Name` field, enter the name of your target. Then click `Attach`.
3. From a terminal session, locate and run your executable using `mpirun` (*the mangled name of the project build products will not be exactly the same as this example*):
`$GridPre/openmpi-3.1.3/bin/mpirun -np 2 ~/Library/Developer/Xcode/DerivedData/HelloGrid-fiyyuveptaqelbbvllomcgjyvghr/Build/Products/Debug/HelloGrid --grid 4.4.4.8 --mpi 1.1.1.2`
The Xcode debugger will attach to the first process.
4. From the `Debug` menu in Xcode, select `Attach to Process`, and other running instances of your application will appear at the top of the list. Attach to as many instances as you wish to debug.
5. Click on the first process (which should have stopped at the breakpoint) and restart it with ctl-cmd-y
You are now debugging multiple MPI instances, and the Xcode debugger should look similar to this:
![Debugging multiple MPI instances under the Xcode debugger](GridXcFig3.png)
# Build `Grid` and `Hadrons` libraries under Xcode
If you want to build `Grid` and `Hadrons` libraries using Xcode, you will need to:
1. Make new library targets for `Grid` and `Hadrons`
2. Add Grid source folders to your project:
a. Right click project then `Add files to "project" ...`
b. Choose `$Grid/Grid` folder
c. Select `Create groups` (`folder references` doesn't work)
d. Select `Grid` (containing just the Grid sources, not the entire Git repository) as your target
e. Click `Add`
3. Add Hadrons source folders to your project
a. As per `Grid`, but change the target to `Hadrons`
b. For each source file in `Archive`, remove them from the target (option-command-1, then untick source files)
4. Set the following values for each target in `Build Settings`
Group | Variable | Value
--- | --- | ---
`Deployment` | `DSTROOT` | `$Grid/build$(CONFIGURATION)` *(do this for the entire project)*
`Deployment` | `DEPLOYMENT_LOCATION` | `Yes`
`Deployment` | `INSTALL_PATH` | `$(PRODUCT_NAME)/`
`Deployment` | `SKIP_INSTALL` | `No`
`Linking` | `OTHER_LDFLAGS` | remove `-lGrid -lHadrons` from the list
This ensures that the libraries are copied back into the build folders when they are made (removing the need to run `make -j 4`)
5. For `Grid`, in `Build Settings` in the `Build Options` group, set:
Variable | Configuration | Value
--- | --- | ---
`EXCLUDED_SOURCE_FILE_NAMES` | Non-MPI configurations (`Debug` and `Release`) | `$(Grid)/Grid/communicator/Communicator_mpi3.cc $(Grid)/Grid/communicator/SharedMemoryMPI.cc`
`EXCLUDED_SOURCE_FILE_NAMES` | MPI configurations (`MPIDebug`) | `$(Grid)/Grid/communicator/Communicator_none.cc $(Grid)/Grid/communicator/SharedMemoryNone.cc`
You should now be able to build and debug any configuration.

View File

@ -29,7 +29,6 @@ Author: Michael Marshall <michael.marshall@ed.ac.uk>
*************************************************************************************/
/* END LEGAL */
#include <Grid/Grid.h>
#include <Grid/util/EigenUtil.h>
#include <typeinfo>
using namespace Grid;
@ -103,13 +102,22 @@ void ioTest(const std::string &filename, const O &object, const std::string &nam
bool good = Serializable::CompareMember(object, *buf);
if (!good) {
std::cout << " failure!" << std::endl;
if (EigenIO::is_tensor<O>::value)
dump_tensor(*buf);
exit(EXIT_FAILURE);
}
std::cout << " done." << std::endl;
}
// The only way I could get these iterators to work is to put the begin() and end() functions in the Eigen namespace
// So if Eigen ever defines these, we'll have a conflict and have to change this
namespace Eigen {
template <typename ET>
inline typename std::enable_if<EigenIO::is_tensor<ET>::value, typename EigenIO::Traits<ET>::scalar_type *>::type
begin( ET & et ) { return reinterpret_cast<typename Grid::EigenIO::Traits<ET>::scalar_type *>(et.data()); }
template <typename ET>
inline typename std::enable_if<EigenIO::is_tensor<ET>::value, typename EigenIO::Traits<ET>::scalar_type *>::type
end( ET & et ) { return begin(et) + et.size() * EigenIO::Traits<ET>::count; }
}
// Perform I/O tests on a range of tensor types
// Test coverage: scalars, complex and GridVectors in single, double and default precision
class TensorIO : public Serializable {
@ -133,14 +141,14 @@ class TensorIO : public Serializable {
void Init(unsigned short Precision)
{
SequentialInit(Perambulator1, Flag, Precision);
SequentialInit(Perambulator2, Flag, Precision);
SequentialInit(tensorR5, FlagR, Precision);
SequentialInit(tensorRank3, FlagF, Precision);
SequentialInit(tensor_9_4_2, FlagTS, Precision);
for( auto &s : Perambulator1 ) s = Flag;
for( auto &s : Perambulator2 ) s = Flag;
for( auto &s : tensorR5 ) s = FlagR;
for( auto &s : tensorRank3 ) s = FlagF;
for( auto &s : tensor_9_4_2 ) s = FlagTS;
for( auto &t : atensor_9_4_2 )
SequentialInit(t, FlagTS, Precision);
SequentialInit(MyLSCTensor, Flag, Precision);
for( auto &s : t ) s = FlagTS;
for( auto &s : MyLSCTensor ) s = Flag;
}
// Perform an I/O test for a single Eigen tensor (of any type)
@ -152,7 +160,7 @@ class TensorIO : public Serializable {
using Traits = EigenIO::Traits<T>;
using scalar_type = typename Traits::scalar_type;
std::unique_ptr<T> pTensor{new T(otherDims...)};
SequentialInit( * pTensor, Flag, Precision );
for( auto &s : * pTensor ) s = Flag;
filename = pszFilePrefix + std::to_string(++TestNum) + "_" + MyTypeName + pszExtension;
ioTest<W, R, T>(filename, * pTensor, MyTypeName, MyTypeName);
}
@ -191,41 +199,15 @@ public:
// Rank 1 tensor containing a single integer
using TensorSingle = Eigen::TensorFixedSize<Integer, Eigen::Sizes<1>>;
TestOne<WTR_, RDR_, TensorSingle>( TEST_PARAMS( TensorSingle ), 7 ); // lucky!
// Rather convoluted way of defining a single complex number
using TensorSimple = Eigen::Tensor<iMatrix<TestScalar,1>, 6>;
// Rather convoluted way of defining four complex numbers
using TensorSimple = Eigen::Tensor<iMatrix<TestScalar,2>, 6>;
using I = typename TensorSimple::Index; // NB: Never specified, so same for all my test tensors
// Try progressively more complicated tensors
TestOne<WTR_, RDR_, TensorSimple, I,I,I,I,I,I>( TEST_PARAMS( TensorSimple ), FlagTS, 1,1,1,1,1,1 );
TestOne<WTR_, RDR_, TensorRank3, I, I, I>( TEST_PARAMS( TensorRank3 ), FlagF, 6, 3, 2 );
TestOne<WTR_, RDR_, Tensor942>(TEST_PARAMS( Tensor942 ), FlagTS);
TestOne<WTR_, RDR_, LSCTensor>(TEST_PARAMS( LSCTensor ), Flag );
// Now see whether we can write a tensor in one memory order and read back in the other
{
TestOne<WTR_, RDR_, TensorR5>(TEST_PARAMS( TensorR5 ), FlagR);
std::cout << " Testing alternate memory order read ... ";
TensorR5Alt t2;
RDR_ reader(filename);
::Grid::read(reader, "TensorR5", t2);
bool good = true;
TensorR5 cf;
SequentialInit( cf, FlagR, Precision );
for_all( t2, [&](typename EigenIO::Traits<TensorR5Alt>::scalar_type c, I n,
const std::array<I, TensorR5Alt::NumIndices> &TensorIndex,
const std::array<int, EigenIO::Traits<TensorR5Alt>::Rank> &GridTensorIndex ){
Real &r = cf(TensorIndex);
if( c != r ){
good = false;
std::cout << "\nError: " << n << ": " << c << " != " << r;
}
} );
if (!good) {
std::cout << std::endl;
dump_tensor(t2,"t2");
exit(EXIT_FAILURE);
}
std::cout << " done." << std::endl;
}
TestOne<WTR_, RDR_, TensorR5>(TEST_PARAMS( TensorR5 ), FlagR);
// Now test a serialisable object containing a number of tensors
{
static const char MyTypeName[] = "TensorIO";
@ -247,10 +229,10 @@ public:
}
};
const Real TensorIO::FlagR {-1.001};
const Complex TensorIO::Flag {1,-3.1415927};
const ComplexF TensorIO::FlagF {1,-3.1415927};
const TensorIO::TestScalar TensorIO::FlagTS{1,-3.1415927};
const Real TensorIO::FlagR {1};
const Complex TensorIO::Flag {1,-1};
const ComplexF TensorIO::FlagF {1,-1};
const TensorIO::TestScalar TensorIO::FlagTS{1,-1};
const char * const TensorIO::pszFilePrefix = "tensor_";
template <typename T>