mirror of
https://github.com/paboyle/Grid.git
synced 2025-07-04 15:37:05 +01:00
Compare commits
31 Commits
feature/pa
...
feature/la
Author | SHA1 | Date | |
---|---|---|---|
9e56c65730 | |||
ef4f2b8c41 | |||
e8b95bd35b | |||
7e35286860 | |||
0486ff8e79 | |||
e9cc21900f | |||
0a8faac271 | |||
abc4de0fd2 | |||
cfe3cd76d1 | |||
3fa5e3109f | |||
8b7049f737 | |||
c85024683e | |||
70ab598c96 | |||
1d0ca65e28 | |||
2bc4d0a20e | |||
4a8c4ccfba | |||
9b44189d5a | |||
7da4856e8e | |||
aaf1e33a77 | |||
d8648307ff | |||
064315c00b | |||
7c6cc85df6 | |||
a6691ef87c | |||
8e0ced627a | |||
0de314870d | |||
ffb91e53d2 | |||
f4e8bf2858 | |||
a74c34315c | |||
75856f2945 | |||
3c112a7a25 | |||
ab3596d4d3 |
28
TODO
28
TODO
@ -1,24 +1,30 @@
|
||||
TODO:
|
||||
---------------
|
||||
|
||||
Peter's work list:
|
||||
1)- Precision conversion and sort out localConvert <--
|
||||
2)- Remove DenseVector, DenseMatrix; Use Eigen instead. <--
|
||||
Large item work list:
|
||||
1)- MultiRHS with spread out extra dim -- Go through filesystem with SciDAC I/O
|
||||
|
||||
-- Profile CG, BlockCG, etc... Flop count/rate -- PARTIAL, time but no flop/s yet
|
||||
-- Physical propagator interface
|
||||
-- Conserved currents
|
||||
-- GaugeFix into central location
|
||||
-- Multigrid Wilson and DWF, compare to other Multigrid implementations
|
||||
-- HDCR resume
|
||||
2)- Christoph's local basis expansion Lanczos
|
||||
3)- BG/Q port and check
|
||||
4)- Precision conversion and sort out localConvert <-- partial
|
||||
- Consistent linear solver flop count/rate -- PARTIAL, time but no flop/s yet
|
||||
5)- Physical propagator interface
|
||||
6)- Conserved currents
|
||||
7)- Multigrid Wilson and DWF, compare to other Multigrid implementations
|
||||
8)- HDCR resume
|
||||
|
||||
Recent DONE
|
||||
-- Lanczos Remove DenseVector, DenseMatrix; Use Eigen instead. <-- DONE
|
||||
-- GaugeFix into central location <-- DONE
|
||||
-- Scidac and Ildg metadata handling <-- DONE
|
||||
-- Binary I/O MPI2 IO <-- DONE
|
||||
-- Binary I/O speed up & x-strips <-- DONE
|
||||
-- Cut down the exterior overhead <-- DONE
|
||||
-- Interior legs from SHM comms <-- DONE
|
||||
-- Half-precision comms <-- DONE
|
||||
-- Merge high precision reduction into develop
|
||||
-- multiRHS DWF; benchmark on Cori/BNL for comms elimination
|
||||
-- Merge high precision reduction into develop <-- DONE
|
||||
-- BlockCG, BCGrQ <-- DONE
|
||||
-- multiRHS DWF; benchmark on Cori/BNL for comms elimination <-- DONE
|
||||
-- slice* linalg routines for multiRHS, BlockCG
|
||||
|
||||
-----
|
||||
|
@ -1,4 +1,4 @@
|
||||
]#!/usr/bin/env bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
EIGEN_URL='http://bitbucket.org/eigen/eigen/get/3.3.3.tar.bz2'
|
||||
|
||||
|
@ -48,7 +48,8 @@ public:
|
||||
std::string, gauge,
|
||||
unsigned int, Ls,
|
||||
double , mass,
|
||||
double , M5);
|
||||
double , M5,
|
||||
std::string , boundary);
|
||||
};
|
||||
|
||||
template <typename FImpl>
|
||||
@ -116,14 +117,19 @@ void TDWF<FImpl>::execute(void)
|
||||
<< par().mass << ", M5= " << par().M5 << " and Ls= "
|
||||
<< par().Ls << " using gauge field '" << par().gauge << "'"
|
||||
<< std::endl;
|
||||
LOG(Message) << "Fermion boundary conditions: " << par().boundary
|
||||
<< std::endl;
|
||||
env().createGrid(par().Ls);
|
||||
auto &U = *env().template getObject<LatticeGaugeField>(par().gauge);
|
||||
auto &g4 = *env().getGrid();
|
||||
auto &grb4 = *env().getRbGrid();
|
||||
auto &g5 = *env().getGrid(par().Ls);
|
||||
auto &grb5 = *env().getRbGrid(par().Ls);
|
||||
std::vector<Complex> boundary = strToVec<Complex>(par().boundary);
|
||||
typename DomainWallFermion<FImpl>::ImplParams implParams(boundary);
|
||||
FMat *fMatPt = new DomainWallFermion<FImpl>(U, g5, grb5, g4, grb4,
|
||||
par().mass, par().M5);
|
||||
par().mass, par().M5,
|
||||
implParams);
|
||||
env().setObject(getName(), fMatPt);
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,8 @@ class WilsonPar: Serializable
|
||||
public:
|
||||
GRID_SERIALIZABLE_CLASS_MEMBERS(WilsonPar,
|
||||
std::string, gauge,
|
||||
double , mass);
|
||||
double , mass,
|
||||
std::string, boundary);
|
||||
};
|
||||
|
||||
template <typename FImpl>
|
||||
@ -112,10 +113,15 @@ void TWilson<FImpl>::execute()
|
||||
{
|
||||
LOG(Message) << "Setting up TWilson fermion matrix with m= " << par().mass
|
||||
<< " using gauge field '" << par().gauge << "'" << std::endl;
|
||||
LOG(Message) << "Fermion boundary conditions: " << par().boundary
|
||||
<< std::endl;
|
||||
auto &U = *env().template getObject<LatticeGaugeField>(par().gauge);
|
||||
auto &grid = *env().getGrid();
|
||||
auto &gridRb = *env().getRbGrid();
|
||||
FMat *fMatPt = new WilsonFermion<FImpl>(U, grid, gridRb, par().mass);
|
||||
std::vector<Complex> boundary = strToVec<Complex>(par().boundary);
|
||||
typename WilsonFermion<FImpl>::ImplParams implParams(boundary);
|
||||
FMat *fMatPt = new WilsonFermion<FImpl>(U, grid, gridRb, par().mass,
|
||||
implParams);
|
||||
env().setObject(getName(), fMatPt);
|
||||
}
|
||||
|
||||
|
@ -131,12 +131,11 @@ std::vector<std::string> TMeson<FImpl1, FImpl2>::getOutput(void)
|
||||
template <typename FImpl1, typename FImpl2>
|
||||
void TMeson<FImpl1, FImpl2>::parseGammaString(std::vector<GammaPair> &gammaList)
|
||||
{
|
||||
gammaList.clear();
|
||||
// Determine gamma matrices to insert at source/sink.
|
||||
if (par().gammas.compare("all") == 0)
|
||||
{
|
||||
// Do all contractions.
|
||||
unsigned int n_gam = Ns * Ns;
|
||||
gammaList.resize(n_gam*n_gam);
|
||||
for (unsigned int i = 1; i < Gamma::nGamma; i += 2)
|
||||
{
|
||||
for (unsigned int j = 1; j < Gamma::nGamma; j += 2)
|
||||
|
@ -41,6 +41,7 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
|
||||
#include <Grid/GridCore.h>
|
||||
#include <Grid/GridQCDcore.h>
|
||||
#include <Grid/qcd/action/Action.h>
|
||||
#include <Grid/qcd/utils/GaugeFix.h>
|
||||
#include <Grid/qcd/smearing/Smearing.h>
|
||||
#include <Grid/parallelIO/MetaData.h>
|
||||
#include <Grid/qcd/hmc/HMC_aggregate.h>
|
||||
|
@ -1,137 +0,0 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./lib/algorithms/iterative/DenseMatrix.h
|
||||
|
||||
Copyright (C) 2015
|
||||
|
||||
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_DENSE_MATRIX_H
|
||||
#define GRID_DENSE_MATRIX_H
|
||||
|
||||
namespace Grid {
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Matrix untils
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T> using DenseVector = std::vector<T>;
|
||||
template<class T> using DenseMatrix = DenseVector<DenseVector<T> >;
|
||||
|
||||
template<class T> void Size(DenseVector<T> & vec, int &N)
|
||||
{
|
||||
N= vec.size();
|
||||
}
|
||||
template<class T> void Size(DenseMatrix<T> & mat, int &N,int &M)
|
||||
{
|
||||
N= mat.size();
|
||||
M= mat[0].size();
|
||||
}
|
||||
|
||||
template<class T> void SizeSquare(DenseMatrix<T> & mat, int &N)
|
||||
{
|
||||
int M; Size(mat,N,M);
|
||||
assert(N==M);
|
||||
}
|
||||
|
||||
template<class T> void Resize(DenseVector<T > & mat, int N) {
|
||||
mat.resize(N);
|
||||
}
|
||||
template<class T> void Resize(DenseMatrix<T > & mat, int N, int M) {
|
||||
mat.resize(N);
|
||||
for(int i=0;i<N;i++){
|
||||
mat[i].resize(M);
|
||||
}
|
||||
}
|
||||
template<class T> void Fill(DenseMatrix<T> & mat, T&val) {
|
||||
int N,M;
|
||||
Size(mat,N,M);
|
||||
for(int i=0;i<N;i++){
|
||||
for(int j=0;j<M;j++){
|
||||
mat[i][j] = val;
|
||||
}}
|
||||
}
|
||||
|
||||
/** Transpose of a matrix **/
|
||||
template<class T> DenseMatrix<T> Transpose(DenseMatrix<T> & mat){
|
||||
int N,M;
|
||||
Size(mat,N,M);
|
||||
DenseMatrix<T> C; Resize(C,M,N);
|
||||
for(int i=0;i<M;i++){
|
||||
for(int j=0;j<N;j++){
|
||||
C[i][j] = mat[j][i];
|
||||
}}
|
||||
return C;
|
||||
}
|
||||
/** Set DenseMatrix to unit matrix **/
|
||||
template<class T> void Unity(DenseMatrix<T> &A){
|
||||
int N; SizeSquare(A,N);
|
||||
for(int i=0;i<N;i++){
|
||||
for(int j=0;j<N;j++){
|
||||
if ( i==j ) A[i][j] = 1;
|
||||
else A[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Add C * I to matrix **/
|
||||
template<class T>
|
||||
void PlusUnit(DenseMatrix<T> & A,T c){
|
||||
int dim; SizeSquare(A,dim);
|
||||
for(int i=0;i<dim;i++){A[i][i] = A[i][i] + c;}
|
||||
}
|
||||
|
||||
/** return the Hermitian conjugate of matrix **/
|
||||
template<class T>
|
||||
DenseMatrix<T> HermitianConj(DenseMatrix<T> &mat){
|
||||
|
||||
int dim; SizeSquare(mat,dim);
|
||||
|
||||
DenseMatrix<T> C; Resize(C,dim,dim);
|
||||
|
||||
for(int i=0;i<dim;i++){
|
||||
for(int j=0;j<dim;j++){
|
||||
C[i][j] = conj(mat[j][i]);
|
||||
}
|
||||
}
|
||||
return C;
|
||||
}
|
||||
/**Get a square submatrix**/
|
||||
template <class T>
|
||||
DenseMatrix<T> GetSubMtx(DenseMatrix<T> &A,int row_st, int row_end, int col_st, int col_end)
|
||||
{
|
||||
DenseMatrix<T> H; Resize(H,row_end - row_st,col_end-col_st);
|
||||
|
||||
for(int i = row_st; i<row_end; i++){
|
||||
for(int j = col_st; j<col_end; j++){
|
||||
H[i-row_st][j-col_st]=A[i][j];
|
||||
}}
|
||||
return H;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "Householder.h"
|
||||
#include "Francis.h"
|
||||
|
||||
#endif
|
||||
|
@ -1,525 +0,0 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./lib/algorithms/iterative/Francis.h
|
||||
|
||||
Copyright (C) 2015
|
||||
|
||||
Author: Peter Boyle <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 FRANCIS_H
|
||||
#define FRANCIS_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
#include <complex>
|
||||
#include <algorithm>
|
||||
|
||||
//#include <timer.h>
|
||||
//#include <lapacke.h>
|
||||
//#include <Eigen/Dense>
|
||||
|
||||
namespace Grid {
|
||||
|
||||
template <class T> int SymmEigensystem(DenseMatrix<T > &Ain, DenseVector<T> &evals, DenseMatrix<T> &evecs, RealD small);
|
||||
template <class T> int Eigensystem(DenseMatrix<T > &Ain, DenseVector<T> &evals, DenseMatrix<T> &evecs, RealD small);
|
||||
|
||||
/**
|
||||
Find the eigenvalues of an upper hessenberg matrix using the Francis QR algorithm.
|
||||
H =
|
||||
x x x x x x x x x
|
||||
x x x x x x x x x
|
||||
0 x x x x x x x x
|
||||
0 0 x x x x x x x
|
||||
0 0 0 x x x x x x
|
||||
0 0 0 0 x x x x x
|
||||
0 0 0 0 0 x x x x
|
||||
0 0 0 0 0 0 x x x
|
||||
0 0 0 0 0 0 0 x x
|
||||
Factorization is P T P^H where T is upper triangular (mod cc blocks) and P is orthagonal/unitary.
|
||||
**/
|
||||
template <class T>
|
||||
int QReigensystem(DenseMatrix<T> &Hin, DenseVector<T> &evals, DenseMatrix<T> &evecs, RealD small)
|
||||
{
|
||||
DenseMatrix<T> H = Hin;
|
||||
|
||||
int N ; SizeSquare(H,N);
|
||||
int M = N;
|
||||
|
||||
Fill(evals,0);
|
||||
Fill(evecs,0);
|
||||
|
||||
T s,t,x=0,y=0,z=0;
|
||||
T u,d;
|
||||
T apd,amd,bc;
|
||||
DenseVector<T> p(N,0);
|
||||
T nrm = Norm(H); ///DenseMatrix Norm
|
||||
int n, m;
|
||||
int e = 0;
|
||||
int it = 0;
|
||||
int tot_it = 0;
|
||||
int l = 0;
|
||||
int r = 0;
|
||||
DenseMatrix<T> P; Resize(P,N,N); Unity(P);
|
||||
DenseVector<int> trows(N,0);
|
||||
|
||||
/// Check if the matrix is really hessenberg, if not abort
|
||||
RealD sth = 0;
|
||||
for(int j=0;j<N;j++){
|
||||
for(int i=j+2;i<N;i++){
|
||||
sth = abs(H[i][j]);
|
||||
if(sth > small){
|
||||
std::cout << "Non hessenberg H = " << sth << " > " << small << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do{
|
||||
std::cout << "Francis QR Step N = " << N << std::endl;
|
||||
/** Check for convergence
|
||||
x x x x x
|
||||
0 x x x x
|
||||
0 0 x x x
|
||||
0 0 x x x
|
||||
0 0 0 0 x
|
||||
for this matrix l = 4
|
||||
**/
|
||||
do{
|
||||
l = Chop_subdiag(H,nrm,e,small);
|
||||
r = 0; ///May have converged on more than one eval
|
||||
///Single eval
|
||||
if(l == N-1){
|
||||
evals[e] = H[l][l];
|
||||
N--; e++; r++; it = 0;
|
||||
}
|
||||
///RealD eval
|
||||
if(l == N-2){
|
||||
trows[l+1] = 1; ///Needed for UTSolve
|
||||
apd = H[l][l] + H[l+1][l+1];
|
||||
amd = H[l][l] - H[l+1][l+1];
|
||||
bc = (T)4.0*H[l+1][l]*H[l][l+1];
|
||||
evals[e] = (T)0.5*( apd + sqrt(amd*amd + bc) );
|
||||
evals[e+1] = (T)0.5*( apd - sqrt(amd*amd + bc) );
|
||||
N-=2; e+=2; r++; it = 0;
|
||||
}
|
||||
} while(r>0);
|
||||
|
||||
if(N ==0) break;
|
||||
|
||||
DenseVector<T > ck; Resize(ck,3);
|
||||
DenseVector<T> v; Resize(v,3);
|
||||
|
||||
for(int m = N-3; m >= l; m--){
|
||||
///Starting vector essentially random shift.
|
||||
if(it%10 == 0 && N >= 3 && it > 0){
|
||||
s = (T)1.618033989*( abs( H[N-1][N-2] ) + abs( H[N-2][N-3] ) );
|
||||
t = (T)0.618033989*( abs( H[N-1][N-2] ) + abs( H[N-2][N-3] ) );
|
||||
x = H[m][m]*H[m][m] + H[m][m+1]*H[m+1][m] - s*H[m][m] + t;
|
||||
y = H[m+1][m]*(H[m][m] + H[m+1][m+1] - s);
|
||||
z = H[m+1][m]*H[m+2][m+1];
|
||||
}
|
||||
///Starting vector implicit Q theorem
|
||||
else{
|
||||
s = (H[N-2][N-2] + H[N-1][N-1]);
|
||||
t = (H[N-2][N-2]*H[N-1][N-1] - H[N-2][N-1]*H[N-1][N-2]);
|
||||
x = H[m][m]*H[m][m] + H[m][m+1]*H[m+1][m] - s*H[m][m] + t;
|
||||
y = H[m+1][m]*(H[m][m] + H[m+1][m+1] - s);
|
||||
z = H[m+1][m]*H[m+2][m+1];
|
||||
}
|
||||
ck[0] = x; ck[1] = y; ck[2] = z;
|
||||
|
||||
if(m == l) break;
|
||||
|
||||
/** Some stupid thing from numerical recipies, seems to work**/
|
||||
// PAB.. for heaven's sake quote page, purpose, evidence it works.
|
||||
// what sort of comment is that!?!?!?
|
||||
u=abs(H[m][m-1])*(abs(y)+abs(z));
|
||||
d=abs(x)*(abs(H[m-1][m-1])+abs(H[m][m])+abs(H[m+1][m+1]));
|
||||
if ((T)abs(u+d) == (T)abs(d) ){
|
||||
l = m; break;
|
||||
}
|
||||
|
||||
//if (u < small){l = m; break;}
|
||||
}
|
||||
if(it > 100000){
|
||||
std::cout << "QReigensystem: bugger it got stuck after 100000 iterations" << std::endl;
|
||||
std::cout << "got " << e << " evals " << l << " " << N << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
normalize(ck); ///Normalization cancels in PHP anyway
|
||||
T beta;
|
||||
Householder_vector<T >(ck, 0, 2, v, beta);
|
||||
Householder_mult<T >(H,v,beta,0,l,l+2,0);
|
||||
Householder_mult<T >(H,v,beta,0,l,l+2,1);
|
||||
///Accumulate eigenvector
|
||||
Householder_mult<T >(P,v,beta,0,l,l+2,1);
|
||||
int sw = 0; ///Are we on the last row?
|
||||
for(int k=l;k<N-2;k++){
|
||||
x = H[k+1][k];
|
||||
y = H[k+2][k];
|
||||
z = (T)0.0;
|
||||
if(k+3 <= N-1){
|
||||
z = H[k+3][k];
|
||||
} else{
|
||||
sw = 1;
|
||||
v[2] = (T)0.0;
|
||||
}
|
||||
ck[0] = x; ck[1] = y; ck[2] = z;
|
||||
normalize(ck);
|
||||
Householder_vector<T >(ck, 0, 2-sw, v, beta);
|
||||
Householder_mult<T >(H,v, beta,0,k+1,k+3-sw,0);
|
||||
Householder_mult<T >(H,v, beta,0,k+1,k+3-sw,1);
|
||||
///Accumulate eigenvector
|
||||
Householder_mult<T >(P,v, beta,0,k+1,k+3-sw,1);
|
||||
}
|
||||
it++;
|
||||
tot_it++;
|
||||
}while(N > 1);
|
||||
N = evals.size();
|
||||
///Annoying - UT solves in reverse order;
|
||||
DenseVector<T> tmp; Resize(tmp,N);
|
||||
for(int i=0;i<N;i++){
|
||||
tmp[i] = evals[N-i-1];
|
||||
}
|
||||
evals = tmp;
|
||||
UTeigenvectors(H, trows, evals, evecs);
|
||||
for(int i=0;i<evals.size();i++){evecs[i] = P*evecs[i]; normalize(evecs[i]);}
|
||||
return tot_it;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int my_Wilkinson(DenseMatrix<T> &Hin, DenseVector<T> &evals, DenseMatrix<T> &evecs, RealD small)
|
||||
{
|
||||
/**
|
||||
Find the eigenvalues of an upper Hessenberg matrix using the Wilkinson QR algorithm.
|
||||
H =
|
||||
x x 0 0 0 0
|
||||
x x x 0 0 0
|
||||
0 x x x 0 0
|
||||
0 0 x x x 0
|
||||
0 0 0 x x x
|
||||
0 0 0 0 x x
|
||||
Factorization is P T P^H where T is upper triangular (mod cc blocks) and P is orthagonal/unitary. **/
|
||||
return my_Wilkinson(Hin, evals, evecs, small, small);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int my_Wilkinson(DenseMatrix<T> &Hin, DenseVector<T> &evals, DenseMatrix<T> &evecs, RealD small, RealD tol)
|
||||
{
|
||||
int N; SizeSquare(Hin,N);
|
||||
int M = N;
|
||||
|
||||
///I don't want to modify the input but matricies must be passed by reference
|
||||
//Scale a matrix by its "norm"
|
||||
//RealD Hnorm = abs( Hin.LargestDiag() ); H = H*(1.0/Hnorm);
|
||||
DenseMatrix<T> H; H = Hin;
|
||||
|
||||
RealD Hnorm = abs(Norm(Hin));
|
||||
H = H * (1.0 / Hnorm);
|
||||
|
||||
// TODO use openmp and memset
|
||||
Fill(evals,0);
|
||||
Fill(evecs,0);
|
||||
|
||||
T s, t, x = 0, y = 0, z = 0;
|
||||
T u, d;
|
||||
T apd, amd, bc;
|
||||
DenseVector<T> p; Resize(p,N); Fill(p,0);
|
||||
|
||||
T nrm = Norm(H); ///DenseMatrix Norm
|
||||
int n, m;
|
||||
int e = 0;
|
||||
int it = 0;
|
||||
int tot_it = 0;
|
||||
int l = 0;
|
||||
int r = 0;
|
||||
DenseMatrix<T> P; Resize(P,N,N);
|
||||
Unity(P);
|
||||
DenseVector<int> trows(N, 0);
|
||||
/// Check if the matrix is really symm tridiag
|
||||
RealD sth = 0;
|
||||
for(int j = 0; j < N; ++j)
|
||||
{
|
||||
for(int i = j + 2; i < N; ++i)
|
||||
{
|
||||
if(abs(H[i][j]) > tol || abs(H[j][i]) > tol)
|
||||
{
|
||||
std::cout << "Non Tridiagonal H(" << i << ","<< j << ") = |" << Real( real( H[j][i] ) ) << "| > " << tol << std::endl;
|
||||
std::cout << "Warning tridiagonalize and call again" << std::endl;
|
||||
// exit(1); // see what is going on
|
||||
//return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do{
|
||||
do{
|
||||
//Jasper
|
||||
//Check if the subdiagonal term is small enough (<small)
|
||||
//if true then it is converged.
|
||||
//check start from H.dim - e - 1
|
||||
//How to deal with more than 2 are converged?
|
||||
//What if Chop_symm_subdiag return something int the middle?
|
||||
//--------------
|
||||
l = Chop_symm_subdiag(H,nrm, e, small);
|
||||
r = 0; ///May have converged on more than one eval
|
||||
//Jasper
|
||||
//In this case
|
||||
// x x 0 0 0 0
|
||||
// x x x 0 0 0
|
||||
// 0 x x x 0 0
|
||||
// 0 0 x x x 0
|
||||
// 0 0 0 x x 0
|
||||
// 0 0 0 0 0 x <- l
|
||||
//--------------
|
||||
///Single eval
|
||||
if(l == N - 1)
|
||||
{
|
||||
evals[e] = H[l][l];
|
||||
N--;
|
||||
e++;
|
||||
r++;
|
||||
it = 0;
|
||||
}
|
||||
//Jasper
|
||||
// x x 0 0 0 0
|
||||
// x x x 0 0 0
|
||||
// 0 x x x 0 0
|
||||
// 0 0 x x 0 0
|
||||
// 0 0 0 0 x x <- l
|
||||
// 0 0 0 0 x x
|
||||
//--------------
|
||||
///RealD eval
|
||||
if(l == N - 2)
|
||||
{
|
||||
trows[l + 1] = 1; ///Needed for UTSolve
|
||||
apd = H[l][l] + H[l + 1][ l + 1];
|
||||
amd = H[l][l] - H[l + 1][l + 1];
|
||||
bc = (T) 4.0 * H[l + 1][l] * H[l][l + 1];
|
||||
evals[e] = (T) 0.5 * (apd + sqrt(amd * amd + bc));
|
||||
evals[e + 1] = (T) 0.5 * (apd - sqrt(amd * amd + bc));
|
||||
N -= 2;
|
||||
e += 2;
|
||||
r++;
|
||||
it = 0;
|
||||
}
|
||||
}while(r > 0);
|
||||
//Jasper
|
||||
//Already converged
|
||||
//--------------
|
||||
if(N == 0) break;
|
||||
|
||||
DenseVector<T> ck,v; Resize(ck,2); Resize(v,2);
|
||||
|
||||
for(int m = N - 3; m >= l; m--)
|
||||
{
|
||||
///Starting vector essentially random shift.
|
||||
if(it%10 == 0 && N >= 3 && it > 0)
|
||||
{
|
||||
t = abs(H[N - 1][N - 2]) + abs(H[N - 2][N - 3]);
|
||||
x = H[m][m] - t;
|
||||
z = H[m + 1][m];
|
||||
} else {
|
||||
///Starting vector implicit Q theorem
|
||||
d = (H[N - 2][N - 2] - H[N - 1][N - 1]) * (T) 0.5;
|
||||
t = H[N - 1][N - 1] - H[N - 1][N - 2] * H[N - 1][N - 2]
|
||||
/ (d + sign(d) * sqrt(d * d + H[N - 1][N - 2] * H[N - 1][N - 2]));
|
||||
x = H[m][m] - t;
|
||||
z = H[m + 1][m];
|
||||
}
|
||||
//Jasper
|
||||
//why it is here????
|
||||
//-----------------------
|
||||
if(m == l)
|
||||
break;
|
||||
|
||||
u = abs(H[m][m - 1]) * (abs(y) + abs(z));
|
||||
d = abs(x) * (abs(H[m - 1][m - 1]) + abs(H[m][m]) + abs(H[m + 1][m + 1]));
|
||||
if ((T)abs(u + d) == (T)abs(d))
|
||||
{
|
||||
l = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Jasper
|
||||
if(it > 1000000)
|
||||
{
|
||||
std::cout << "Wilkinson: bugger it got stuck after 100000 iterations" << std::endl;
|
||||
std::cout << "got " << e << " evals " << l << " " << N << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
//
|
||||
T s, c;
|
||||
Givens_calc<T>(x, z, c, s);
|
||||
Givens_mult<T>(H, l, l + 1, c, -s, 0);
|
||||
Givens_mult<T>(H, l, l + 1, c, s, 1);
|
||||
Givens_mult<T>(P, l, l + 1, c, s, 1);
|
||||
//
|
||||
for(int k = l; k < N - 2; ++k)
|
||||
{
|
||||
x = H.A[k + 1][k];
|
||||
z = H.A[k + 2][k];
|
||||
Givens_calc<T>(x, z, c, s);
|
||||
Givens_mult<T>(H, k + 1, k + 2, c, -s, 0);
|
||||
Givens_mult<T>(H, k + 1, k + 2, c, s, 1);
|
||||
Givens_mult<T>(P, k + 1, k + 2, c, s, 1);
|
||||
}
|
||||
it++;
|
||||
tot_it++;
|
||||
}while(N > 1);
|
||||
|
||||
N = evals.size();
|
||||
///Annoying - UT solves in reverse order;
|
||||
DenseVector<T> tmp(N);
|
||||
for(int i = 0; i < N; ++i)
|
||||
tmp[i] = evals[N-i-1];
|
||||
evals = tmp;
|
||||
//
|
||||
UTeigenvectors(H, trows, evals, evecs);
|
||||
//UTSymmEigenvectors(H, trows, evals, evecs);
|
||||
for(int i = 0; i < evals.size(); ++i)
|
||||
{
|
||||
evecs[i] = P * evecs[i];
|
||||
normalize(evecs[i]);
|
||||
evals[i] = evals[i] * Hnorm;
|
||||
}
|
||||
// // FIXME this is to test
|
||||
// Hin.write("evecs3", evecs);
|
||||
// Hin.write("evals3", evals);
|
||||
// // check rsd
|
||||
// for(int i = 0; i < M; i++) {
|
||||
// vector<T> Aevec = Hin * evecs[i];
|
||||
// RealD norm2(0.);
|
||||
// for(int j = 0; j < M; j++) {
|
||||
// norm2 += (Aevec[j] - evals[i] * evecs[i][j]) * (Aevec[j] - evals[i] * evecs[i][j]);
|
||||
// }
|
||||
// }
|
||||
return tot_it;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Hess(DenseMatrix<T > &A, DenseMatrix<T> &Q, int start){
|
||||
|
||||
/**
|
||||
turn a matrix A =
|
||||
x x x x x
|
||||
x x x x x
|
||||
x x x x x
|
||||
x x x x x
|
||||
x x x x x
|
||||
into
|
||||
x x x x x
|
||||
x x x x x
|
||||
0 x x x x
|
||||
0 0 x x x
|
||||
0 0 0 x x
|
||||
with householder rotations
|
||||
Slow.
|
||||
*/
|
||||
int N ; SizeSquare(A,N);
|
||||
DenseVector<T > p; Resize(p,N); Fill(p,0);
|
||||
|
||||
for(int k=start;k<N-2;k++){
|
||||
//cerr << "hess" << k << std::endl;
|
||||
DenseVector<T > ck,v; Resize(ck,N-k-1); Resize(v,N-k-1);
|
||||
for(int i=k+1;i<N;i++){ck[i-k-1] = A(i,k);} ///kth column
|
||||
normalize(ck); ///Normalization cancels in PHP anyway
|
||||
T beta;
|
||||
Householder_vector<T >(ck, 0, ck.size()-1, v, beta); ///Householder vector
|
||||
Householder_mult<T>(A,v,beta,start,k+1,N-1,0); ///A -> PA
|
||||
Householder_mult<T >(A,v,beta,start,k+1,N-1,1); ///PA -> PAP^H
|
||||
///Accumulate eigenvector
|
||||
Householder_mult<T >(Q,v,beta,start,k+1,N-1,1); ///Q -> QP^H
|
||||
}
|
||||
/*for(int l=0;l<N-2;l++){
|
||||
for(int k=l+2;k<N;k++){
|
||||
A(0,k,l);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Tri(DenseMatrix<T > &A, DenseMatrix<T> &Q, int start){
|
||||
///Tridiagonalize a matrix
|
||||
int N; SizeSquare(A,N);
|
||||
Hess(A,Q,start);
|
||||
/*for(int l=0;l<N-2;l++){
|
||||
for(int k=l+2;k<N;k++){
|
||||
A(0,l,k);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ForceTridiagonal(DenseMatrix<T> &A){
|
||||
///Tridiagonalize a matrix
|
||||
int N ; SizeSquare(A,N);
|
||||
for(int l=0;l<N-2;l++){
|
||||
for(int k=l+2;k<N;k++){
|
||||
A[l][k]=0;
|
||||
A[k][l]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int my_SymmEigensystem(DenseMatrix<T > &Ain, DenseVector<T> &evals, DenseVector<DenseVector<T> > &evecs, RealD small){
|
||||
///Solve a symmetric eigensystem, not necessarily in tridiagonal form
|
||||
int N; SizeSquare(Ain,N);
|
||||
DenseMatrix<T > A; A = Ain;
|
||||
DenseMatrix<T > Q; Resize(Q,N,N); Unity(Q);
|
||||
Tri(A,Q,0);
|
||||
int it = my_Wilkinson<T>(A, evals, evecs, small);
|
||||
for(int k=0;k<N;k++){evecs[k] = Q*evecs[k];}
|
||||
return it;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
int Wilkinson(DenseMatrix<T> &Ain, DenseVector<T> &evals, DenseVector<DenseVector<T> > &evecs, RealD small){
|
||||
return my_Wilkinson(Ain, evals, evecs, small);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int SymmEigensystem(DenseMatrix<T> &Ain, DenseVector<T> &evals, DenseVector<DenseVector<T> > &evecs, RealD small){
|
||||
return my_SymmEigensystem(Ain, evals, evecs, small);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int Eigensystem(DenseMatrix<T > &Ain, DenseVector<T> &evals, DenseVector<DenseVector<T> > &evecs, RealD small){
|
||||
///Solve a general eigensystem, not necessarily in tridiagonal form
|
||||
int N = Ain.dim;
|
||||
DenseMatrix<T > A(N); A = Ain;
|
||||
DenseMatrix<T > Q(N);Q.Unity();
|
||||
Hess(A,Q,0);
|
||||
int it = QReigensystem<T>(A, evals, evecs, small);
|
||||
for(int k=0;k<N;k++){evecs[k] = Q*evecs[k];}
|
||||
return it;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
@ -1,242 +0,0 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./lib/algorithms/iterative/Householder.h
|
||||
|
||||
Copyright (C) 2015
|
||||
|
||||
Author: Peter Boyle <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 HOUSEHOLDER_H
|
||||
#define HOUSEHOLDER_H
|
||||
|
||||
#define TIMER(A) std::cout << GridLogMessage << __FUNC__ << " file "<< __FILE__ <<" line " << __LINE__ << std::endl;
|
||||
#define ENTER() std::cout << GridLogMessage << "ENTRY "<<__FUNC__ << " file "<< __FILE__ <<" line " << __LINE__ << std::endl;
|
||||
#define LEAVE() std::cout << GridLogMessage << "EXIT "<<__FUNC__ << " file "<< __FILE__ <<" line " << __LINE__ << std::endl;
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
#include <complex>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Grid {
|
||||
/** Comparison function for finding the max element in a vector **/
|
||||
template <class T> bool cf(T i, T j) {
|
||||
return abs(i) < abs(j);
|
||||
}
|
||||
|
||||
/**
|
||||
Calculate a real Givens angle
|
||||
**/
|
||||
template <class T> inline void Givens_calc(T y, T z, T &c, T &s){
|
||||
|
||||
RealD mz = (RealD)abs(z);
|
||||
|
||||
if(mz==0.0){
|
||||
c = 1; s = 0;
|
||||
}
|
||||
if(mz >= (RealD)abs(y)){
|
||||
T t = -y/z;
|
||||
s = (T)1.0 / sqrt ((T)1.0 + t * t);
|
||||
c = s * t;
|
||||
} else {
|
||||
T t = -z/y;
|
||||
c = (T)1.0 / sqrt ((T)1.0 + t * t);
|
||||
s = c * t;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> inline void Givens_mult(DenseMatrix<T> &A, int i, int k, T c, T s, int dir)
|
||||
{
|
||||
int q ; SizeSquare(A,q);
|
||||
|
||||
if(dir == 0){
|
||||
for(int j=0;j<q;j++){
|
||||
T nu = A[i][j];
|
||||
T w = A[k][j];
|
||||
A[i][j] = (c*nu + s*w);
|
||||
A[k][j] = (-s*nu + c*w);
|
||||
}
|
||||
}
|
||||
|
||||
if(dir == 1){
|
||||
for(int j=0;j<q;j++){
|
||||
T nu = A[j][i];
|
||||
T w = A[j][k];
|
||||
A[j][i] = (c*nu - s*w);
|
||||
A[j][k] = (s*nu + c*w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
from input = x;
|
||||
Compute the complex Householder vector, v, such that
|
||||
P = (I - b v transpose(v) )
|
||||
b = 2/v.v
|
||||
|
||||
P | x | | x | k = 0
|
||||
| x | | 0 |
|
||||
| x | = | 0 |
|
||||
| x | | 0 | j = 3
|
||||
| x | | x |
|
||||
|
||||
These are the "Unreduced" Householder vectors.
|
||||
|
||||
**/
|
||||
template <class T> inline void Householder_vector(DenseVector<T> input, int k, int j, DenseVector<T> &v, T &beta)
|
||||
{
|
||||
int N ; Size(input,N);
|
||||
T m = *max_element(input.begin() + k, input.begin() + j + 1, cf<T> );
|
||||
|
||||
if(abs(m) > 0.0){
|
||||
T alpha = 0;
|
||||
|
||||
for(int i=k; i<j+1; i++){
|
||||
v[i] = input[i]/m;
|
||||
alpha = alpha + v[i]*conj(v[i]);
|
||||
}
|
||||
alpha = sqrt(alpha);
|
||||
beta = (T)1.0/(alpha*(alpha + abs(v[k]) ));
|
||||
|
||||
if(abs(v[k]) > 0.0) v[k] = v[k] + (v[k]/abs(v[k]))*alpha;
|
||||
else v[k] = -alpha;
|
||||
} else{
|
||||
for(int i=k; i<j+1; i++){
|
||||
v[i] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
from input = x;
|
||||
Compute the complex Householder vector, v, such that
|
||||
P = (I - b v transpose(v) )
|
||||
b = 2/v.v
|
||||
|
||||
Px = alpha*e_dir
|
||||
|
||||
These are the "Unreduced" Householder vectors.
|
||||
|
||||
**/
|
||||
|
||||
template <class T> inline void Householder_vector(DenseVector<T> input, int k, int j, int dir, DenseVector<T> &v, T &beta)
|
||||
{
|
||||
int N = input.size();
|
||||
T m = *max_element(input.begin() + k, input.begin() + j + 1, cf);
|
||||
|
||||
if(abs(m) > 0.0){
|
||||
T alpha = 0;
|
||||
|
||||
for(int i=k; i<j+1; i++){
|
||||
v[i] = input[i]/m;
|
||||
alpha = alpha + v[i]*conj(v[i]);
|
||||
}
|
||||
|
||||
alpha = sqrt(alpha);
|
||||
beta = 1.0/(alpha*(alpha + abs(v[dir]) ));
|
||||
|
||||
if(abs(v[dir]) > 0.0) v[dir] = v[dir] + (v[dir]/abs(v[dir]))*alpha;
|
||||
else v[dir] = -alpha;
|
||||
}else{
|
||||
for(int i=k; i<j+1; i++){
|
||||
v[i] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Compute the product PA if trans = 0
|
||||
AP if trans = 1
|
||||
P = (I - b v transpose(v) )
|
||||
b = 2/v.v
|
||||
start at element l of matrix A
|
||||
v is of length j - k + 1 of v are nonzero
|
||||
**/
|
||||
|
||||
template <class T> inline void Householder_mult(DenseMatrix<T> &A , DenseVector<T> v, T beta, int l, int k, int j, int trans)
|
||||
{
|
||||
int N ; SizeSquare(A,N);
|
||||
|
||||
if(abs(beta) > 0.0){
|
||||
for(int p=l; p<N; p++){
|
||||
T s = 0;
|
||||
if(trans==0){
|
||||
for(int i=k;i<j+1;i++) s += conj(v[i-k])*A[i][p];
|
||||
s *= beta;
|
||||
for(int i=k;i<j+1;i++){ A[i][p] = A[i][p]-s*conj(v[i-k]);}
|
||||
} else {
|
||||
for(int i=k;i<j+1;i++){ s += conj(v[i-k])*A[p][i];}
|
||||
s *= beta;
|
||||
for(int i=k;i<j+1;i++){ A[p][i]=A[p][i]-s*conj(v[i-k]);}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Compute the product PA if trans = 0
|
||||
AP if trans = 1
|
||||
P = (I - b v transpose(v) )
|
||||
b = 2/v.v
|
||||
start at element l of matrix A
|
||||
v is of length j - k + 1 of v are nonzero
|
||||
A is tridiagonal
|
||||
**/
|
||||
template <class T> inline void Householder_mult_tri(DenseMatrix<T> &A , DenseVector<T> v, T beta, int l, int M, int k, int j, int trans)
|
||||
{
|
||||
if(abs(beta) > 0.0){
|
||||
|
||||
int N ; SizeSquare(A,N);
|
||||
|
||||
DenseMatrix<T> tmp; Resize(tmp,N,N); Fill(tmp,0);
|
||||
|
||||
T s;
|
||||
for(int p=l; p<M; p++){
|
||||
s = 0;
|
||||
if(trans==0){
|
||||
for(int i=k;i<j+1;i++) s = s + conj(v[i-k])*A[i][p];
|
||||
}else{
|
||||
for(int i=k;i<j+1;i++) s = s + v[i-k]*A[p][i];
|
||||
}
|
||||
s = beta*s;
|
||||
if(trans==0){
|
||||
for(int i=k;i<j+1;i++) tmp[i][p] = tmp(i,p) - s*v[i-k];
|
||||
}else{
|
||||
for(int i=k;i<j+1;i++) tmp[p][i] = tmp[p][i] - s*conj(v[i-k]);
|
||||
}
|
||||
}
|
||||
for(int p=l; p<M; p++){
|
||||
if(trans==0){
|
||||
for(int i=k;i<j+1;i++) A[i][p] = A[i][p] + tmp[i][p];
|
||||
}else{
|
||||
for(int i=k;i<j+1;i++) A[p][i] = A[p][i] + tmp[p][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -33,6 +33,8 @@ directory
|
||||
|
||||
namespace Grid {
|
||||
|
||||
enum BlockCGtype { BlockCG, BlockCGrQ, CGmultiRHS };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Block conjugate gradient. Dimension zero should be the block direction
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -40,25 +42,273 @@ template <class Field>
|
||||
class BlockConjugateGradient : public OperatorFunction<Field> {
|
||||
public:
|
||||
|
||||
|
||||
typedef typename Field::scalar_type scomplex;
|
||||
|
||||
const int blockDim = 0;
|
||||
|
||||
int blockDim ;
|
||||
int Nblock;
|
||||
|
||||
BlockCGtype CGtype;
|
||||
bool ErrorOnNoConverge; // throw an assert when the CG fails to converge.
|
||||
// Defaults true.
|
||||
RealD Tolerance;
|
||||
Integer MaxIterations;
|
||||
Integer IterationsToComplete; //Number of iterations the CG took to finish. Filled in upon completion
|
||||
|
||||
BlockConjugateGradient(RealD tol, Integer maxit, bool err_on_no_conv = true)
|
||||
: Tolerance(tol),
|
||||
MaxIterations(maxit),
|
||||
ErrorOnNoConverge(err_on_no_conv){};
|
||||
BlockConjugateGradient(BlockCGtype cgtype,int _Orthog,RealD tol, Integer maxit, bool err_on_no_conv = true)
|
||||
: Tolerance(tol), CGtype(cgtype), blockDim(_Orthog), MaxIterations(maxit), ErrorOnNoConverge(err_on_no_conv)
|
||||
{};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Thin QR factorisation (google it)
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ThinQRfact (Eigen::MatrixXcd &m_rr,
|
||||
Eigen::MatrixXcd &C,
|
||||
Eigen::MatrixXcd &Cinv,
|
||||
Field & Q,
|
||||
const Field & R)
|
||||
{
|
||||
int Orthog = blockDim; // First dimension is block dim; this is an assumption
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Dimensions
|
||||
// R_{ferm x Nblock} = Q_{ferm x Nblock} x C_{Nblock x Nblock} -> ferm x Nblock
|
||||
//
|
||||
// Rdag R = m_rr = Herm = L L^dag <-- Cholesky decomposition (LLT routine in Eigen)
|
||||
//
|
||||
// Q C = R => Q = R C^{-1}
|
||||
//
|
||||
// Want Ident = Q^dag Q = C^{-dag} R^dag R C^{-1} = C^{-dag} L L^dag C^{-1} = 1_{Nblock x Nblock}
|
||||
//
|
||||
// Set C = L^{dag}, and then Q^dag Q = ident
|
||||
//
|
||||
// Checks:
|
||||
// Cdag C = Rdag R ; passes.
|
||||
// QdagQ = 1 ; passes
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
sliceInnerProductMatrix(m_rr,R,R,Orthog);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Cholesky from Eigen
|
||||
// There exists a ldlt that is documented as more stable
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Eigen::MatrixXcd L = m_rr.llt().matrixL();
|
||||
|
||||
C = L.adjoint();
|
||||
Cinv = C.inverse();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Q = R C^{-1}
|
||||
//
|
||||
// Q_j = R_i Cinv(i,j)
|
||||
//
|
||||
// NB maddMatrix conventions are Right multiplication X[j] a[j,i] already
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FIXME:: make a sliceMulMatrix to avoid zero vector
|
||||
sliceMulMatrix(Q,Cinv,R,Orthog);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Call one of several implementations
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void operator()(LinearOperatorBase<Field> &Linop, const Field &Src, Field &Psi)
|
||||
{
|
||||
int Orthog = 0; // First dimension is block dim
|
||||
if ( CGtype == BlockCGrQ ) {
|
||||
BlockCGrQsolve(Linop,Src,Psi);
|
||||
} else if (CGtype == BlockCG ) {
|
||||
BlockCGsolve(Linop,Src,Psi);
|
||||
} else if (CGtype == CGmultiRHS ) {
|
||||
CGmultiRHSsolve(Linop,Src,Psi);
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// BlockCGrQ implementation:
|
||||
//--------------------------
|
||||
// X is guess/Solution
|
||||
// B is RHS
|
||||
// Solve A X_i = B_i ; i refers to Nblock index
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void BlockCGrQsolve(LinearOperatorBase<Field> &Linop, const Field &B, Field &X)
|
||||
{
|
||||
int Orthog = blockDim; // First dimension is block dim; this is an assumption
|
||||
Nblock = B._grid->_fdimensions[Orthog];
|
||||
|
||||
std::cout<<GridLogMessage<<" Block Conjugate Gradient : Orthog "<<Orthog<<" Nblock "<<Nblock<<std::endl;
|
||||
|
||||
X.checkerboard = B.checkerboard;
|
||||
conformable(X, B);
|
||||
|
||||
Field tmp(B);
|
||||
Field Q(B);
|
||||
Field D(B);
|
||||
Field Z(B);
|
||||
Field AD(B);
|
||||
|
||||
Eigen::MatrixXcd m_DZ = Eigen::MatrixXcd::Identity(Nblock,Nblock);
|
||||
Eigen::MatrixXcd m_M = Eigen::MatrixXcd::Identity(Nblock,Nblock);
|
||||
Eigen::MatrixXcd m_rr = Eigen::MatrixXcd::Zero(Nblock,Nblock);
|
||||
|
||||
Eigen::MatrixXcd m_C = Eigen::MatrixXcd::Zero(Nblock,Nblock);
|
||||
Eigen::MatrixXcd m_Cinv = Eigen::MatrixXcd::Zero(Nblock,Nblock);
|
||||
Eigen::MatrixXcd m_S = Eigen::MatrixXcd::Zero(Nblock,Nblock);
|
||||
Eigen::MatrixXcd m_Sinv = Eigen::MatrixXcd::Zero(Nblock,Nblock);
|
||||
|
||||
Eigen::MatrixXcd m_tmp = Eigen::MatrixXcd::Identity(Nblock,Nblock);
|
||||
Eigen::MatrixXcd m_tmp1 = Eigen::MatrixXcd::Identity(Nblock,Nblock);
|
||||
|
||||
// Initial residual computation & set up
|
||||
std::vector<RealD> residuals(Nblock);
|
||||
std::vector<RealD> ssq(Nblock);
|
||||
|
||||
sliceNorm(ssq,B,Orthog);
|
||||
RealD sssum=0;
|
||||
for(int b=0;b<Nblock;b++) sssum+=ssq[b];
|
||||
|
||||
sliceNorm(residuals,B,Orthog);
|
||||
for(int b=0;b<Nblock;b++){ assert(std::isnan(residuals[b])==0); }
|
||||
|
||||
sliceNorm(residuals,X,Orthog);
|
||||
for(int b=0;b<Nblock;b++){ assert(std::isnan(residuals[b])==0); }
|
||||
|
||||
/************************************************************************
|
||||
* Block conjugate gradient rQ (Sebastien Birk Thesis, after Dubrulle 2001)
|
||||
************************************************************************
|
||||
* Dimensions:
|
||||
*
|
||||
* X,B==(Nferm x Nblock)
|
||||
* A==(Nferm x Nferm)
|
||||
*
|
||||
* Nferm = Nspin x Ncolour x Ncomplex x Nlattice_site
|
||||
*
|
||||
* QC = R = B-AX, D = Q ; QC => Thin QR factorisation (google it)
|
||||
* for k:
|
||||
* Z = AD
|
||||
* M = [D^dag Z]^{-1}
|
||||
* X = X + D MC
|
||||
* QS = Q - ZM
|
||||
* D = Q + D S^dag
|
||||
* C = S C
|
||||
*/
|
||||
///////////////////////////////////////
|
||||
// Initial block: initial search dir is guess
|
||||
///////////////////////////////////////
|
||||
std::cout << GridLogMessage<<"BlockCGrQ algorithm initialisation " <<std::endl;
|
||||
|
||||
//1. QC = R = B-AX, D = Q ; QC => Thin QR factorisation (google it)
|
||||
|
||||
Linop.HermOp(X, AD);
|
||||
tmp = B - AD;
|
||||
ThinQRfact (m_rr, m_C, m_Cinv, Q, tmp);
|
||||
D=Q;
|
||||
|
||||
std::cout << GridLogMessage<<"BlockCGrQ computed initial residual and QR fact " <<std::endl;
|
||||
|
||||
///////////////////////////////////////
|
||||
// Timers
|
||||
///////////////////////////////////////
|
||||
GridStopWatch sliceInnerTimer;
|
||||
GridStopWatch sliceMaddTimer;
|
||||
GridStopWatch QRTimer;
|
||||
GridStopWatch MatrixTimer;
|
||||
GridStopWatch SolverTimer;
|
||||
SolverTimer.Start();
|
||||
|
||||
int k;
|
||||
for (k = 1; k <= MaxIterations; k++) {
|
||||
|
||||
//3. Z = AD
|
||||
MatrixTimer.Start();
|
||||
Linop.HermOp(D, Z);
|
||||
MatrixTimer.Stop();
|
||||
|
||||
//4. M = [D^dag Z]^{-1}
|
||||
sliceInnerTimer.Start();
|
||||
sliceInnerProductMatrix(m_DZ,D,Z,Orthog);
|
||||
sliceInnerTimer.Stop();
|
||||
m_M = m_DZ.inverse();
|
||||
|
||||
//5. X = X + D MC
|
||||
m_tmp = m_M * m_C;
|
||||
sliceMaddTimer.Start();
|
||||
sliceMaddMatrix(X,m_tmp, D,X,Orthog);
|
||||
sliceMaddTimer.Stop();
|
||||
|
||||
//6. QS = Q - ZM
|
||||
sliceMaddTimer.Start();
|
||||
sliceMaddMatrix(tmp,m_M,Z,Q,Orthog,-1.0);
|
||||
sliceMaddTimer.Stop();
|
||||
QRTimer.Start();
|
||||
ThinQRfact (m_rr, m_S, m_Sinv, Q, tmp);
|
||||
QRTimer.Stop();
|
||||
|
||||
//7. D = Q + D S^dag
|
||||
m_tmp = m_S.adjoint();
|
||||
sliceMaddTimer.Start();
|
||||
sliceMaddMatrix(D,m_tmp,D,Q,Orthog);
|
||||
sliceMaddTimer.Stop();
|
||||
|
||||
//8. C = S C
|
||||
m_C = m_S*m_C;
|
||||
|
||||
/*********************
|
||||
* convergence monitor
|
||||
*********************
|
||||
*/
|
||||
m_rr = m_C.adjoint() * m_C;
|
||||
|
||||
RealD max_resid=0;
|
||||
RealD rrsum=0;
|
||||
RealD rr;
|
||||
|
||||
for(int b=0;b<Nblock;b++) {
|
||||
rrsum+=real(m_rr(b,b));
|
||||
rr = real(m_rr(b,b))/ssq[b];
|
||||
if ( rr > max_resid ) max_resid = rr;
|
||||
}
|
||||
|
||||
std::cout << GridLogIterative << "\titeration "<<k<<" rr_sum "<<rrsum<<" ssq_sum "<< sssum
|
||||
<<" ave "<<std::sqrt(rrsum/sssum) << " max "<< max_resid <<std::endl;
|
||||
|
||||
if ( max_resid < Tolerance*Tolerance ) {
|
||||
|
||||
SolverTimer.Stop();
|
||||
|
||||
std::cout << GridLogMessage<<"BlockCGrQ converged in "<<k<<" iterations"<<std::endl;
|
||||
|
||||
for(int b=0;b<Nblock;b++){
|
||||
std::cout << GridLogMessage<< "\t\tblock "<<b<<" computed resid "
|
||||
<< std::sqrt(real(m_rr(b,b))/ssq[b])<<std::endl;
|
||||
}
|
||||
std::cout << GridLogMessage<<"\tMax residual is "<<std::sqrt(max_resid)<<std::endl;
|
||||
|
||||
Linop.HermOp(X, AD);
|
||||
AD = AD-B;
|
||||
std::cout << GridLogMessage <<"\t True residual is " << std::sqrt(norm2(AD)/norm2(B)) <<std::endl;
|
||||
|
||||
std::cout << GridLogMessage << "Time Breakdown "<<std::endl;
|
||||
std::cout << GridLogMessage << "\tElapsed " << SolverTimer.Elapsed() <<std::endl;
|
||||
std::cout << GridLogMessage << "\tMatrix " << MatrixTimer.Elapsed() <<std::endl;
|
||||
std::cout << GridLogMessage << "\tInnerProd " << sliceInnerTimer.Elapsed() <<std::endl;
|
||||
std::cout << GridLogMessage << "\tMaddMatrix " << sliceMaddTimer.Elapsed() <<std::endl;
|
||||
std::cout << GridLogMessage << "\tThinQRfact " << QRTimer.Elapsed() <<std::endl;
|
||||
|
||||
IterationsToComplete = k;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
std::cout << GridLogMessage << "BlockConjugateGradient(rQ) did NOT converge" << std::endl;
|
||||
|
||||
if (ErrorOnNoConverge) assert(0);
|
||||
IterationsToComplete = k;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Block conjugate gradient; Original O'Leary Dimension zero should be the block direction
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void BlockCGsolve(LinearOperatorBase<Field> &Linop, const Field &Src, Field &Psi)
|
||||
{
|
||||
int Orthog = blockDim; // First dimension is block dim; this is an assumption
|
||||
Nblock = Src._grid->_fdimensions[Orthog];
|
||||
|
||||
std::cout<<GridLogMessage<<" Block Conjugate Gradient : Orthog "<<Orthog<<" Nblock "<<Nblock<<std::endl;
|
||||
@ -162,8 +412,9 @@ void operator()(LinearOperatorBase<Field> &Linop, const Field &Src, Field &Psi)
|
||||
*********************
|
||||
*/
|
||||
RealD max_resid=0;
|
||||
RealD rr;
|
||||
for(int b=0;b<Nblock;b++){
|
||||
RealD rr = real(m_rr(b,b))/ssq[b];
|
||||
rr = real(m_rr(b,b))/ssq[b];
|
||||
if ( rr > max_resid ) max_resid = rr;
|
||||
}
|
||||
|
||||
@ -173,13 +424,14 @@ void operator()(LinearOperatorBase<Field> &Linop, const Field &Src, Field &Psi)
|
||||
|
||||
std::cout << GridLogMessage<<"BlockCG converged in "<<k<<" iterations"<<std::endl;
|
||||
for(int b=0;b<Nblock;b++){
|
||||
std::cout << GridLogMessage<< "\t\tblock "<<b<<" resid "<< std::sqrt(real(m_rr(b,b))/ssq[b])<<std::endl;
|
||||
std::cout << GridLogMessage<< "\t\tblock "<<b<<" computed resid "
|
||||
<< std::sqrt(real(m_rr(b,b))/ssq[b])<<std::endl;
|
||||
}
|
||||
std::cout << GridLogMessage<<"\tMax residual is "<<std::sqrt(max_resid)<<std::endl;
|
||||
|
||||
Linop.HermOp(Psi, AP);
|
||||
AP = AP-Src;
|
||||
std::cout << GridLogMessage <<"\tTrue residual is " << std::sqrt(norm2(AP)/norm2(Src)) <<std::endl;
|
||||
std::cout << GridLogMessage <<"\t True residual is " << std::sqrt(norm2(AP)/norm2(Src)) <<std::endl;
|
||||
|
||||
std::cout << GridLogMessage << "Time Breakdown "<<std::endl;
|
||||
std::cout << GridLogMessage << "\tElapsed " << SolverTimer.Elapsed() <<std::endl;
|
||||
@ -197,35 +449,13 @@ void operator()(LinearOperatorBase<Field> &Linop, const Field &Src, Field &Psi)
|
||||
if (ErrorOnNoConverge) assert(0);
|
||||
IterationsToComplete = k;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// multiRHS conjugate gradient. Dimension zero should be the block direction
|
||||
// Use this for spread out across nodes
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class Field>
|
||||
class MultiRHSConjugateGradient : public OperatorFunction<Field> {
|
||||
public:
|
||||
|
||||
typedef typename Field::scalar_type scomplex;
|
||||
|
||||
const int blockDim = 0;
|
||||
|
||||
int Nblock;
|
||||
bool ErrorOnNoConverge; // throw an assert when the CG fails to converge.
|
||||
// Defaults true.
|
||||
RealD Tolerance;
|
||||
Integer MaxIterations;
|
||||
Integer IterationsToComplete; //Number of iterations the CG took to finish. Filled in upon completion
|
||||
|
||||
MultiRHSConjugateGradient(RealD tol, Integer maxit, bool err_on_no_conv = true)
|
||||
: Tolerance(tol),
|
||||
MaxIterations(maxit),
|
||||
ErrorOnNoConverge(err_on_no_conv){};
|
||||
|
||||
void operator()(LinearOperatorBase<Field> &Linop, const Field &Src, Field &Psi)
|
||||
void CGmultiRHSsolve(LinearOperatorBase<Field> &Linop, const Field &Src, Field &Psi)
|
||||
{
|
||||
int Orthog = 0; // First dimension is block dim
|
||||
int Orthog = blockDim; // First dimension is block dim
|
||||
Nblock = Src._grid->_fdimensions[Orthog];
|
||||
|
||||
std::cout<<GridLogMessage<<"MultiRHS Conjugate Gradient : Orthog "<<Orthog<<" Nblock "<<Nblock<<std::endl;
|
||||
@ -285,12 +515,10 @@ void operator()(LinearOperatorBase<Field> &Linop, const Field &Src, Field &Psi)
|
||||
MatrixTimer.Stop();
|
||||
|
||||
// Alpha
|
||||
// sliceInnerProductVectorTest(v_pAp_test,P,AP,Orthog);
|
||||
sliceInnerTimer.Start();
|
||||
sliceInnerProductVector(v_pAp,P,AP,Orthog);
|
||||
sliceInnerTimer.Stop();
|
||||
for(int b=0;b<Nblock;b++){
|
||||
// std::cout << " "<< v_pAp[b]<<" "<< v_pAp_test[b]<<std::endl;
|
||||
v_alpha[b] = v_rr[b]/real(v_pAp[b]);
|
||||
}
|
||||
|
||||
@ -332,7 +560,7 @@ void operator()(LinearOperatorBase<Field> &Linop, const Field &Src, Field &Psi)
|
||||
|
||||
std::cout << GridLogMessage<<"MultiRHS solver converged in " <<k<<" iterations"<<std::endl;
|
||||
for(int b=0;b<Nblock;b++){
|
||||
std::cout << GridLogMessage<< "\t\tBlock "<<b<<" resid "<< std::sqrt(v_rr[b]/ssq[b])<<std::endl;
|
||||
std::cout << GridLogMessage<< "\t\tBlock "<<b<<" computed resid "<< std::sqrt(v_rr[b]/ssq[b])<<std::endl;
|
||||
}
|
||||
std::cout << GridLogMessage<<"\tMax residual is "<<std::sqrt(max_resid)<<std::endl;
|
||||
|
||||
@ -358,9 +586,8 @@ void operator()(LinearOperatorBase<Field> &Linop, const Field &Src, Field &Psi)
|
||||
if (ErrorOnNoConverge) assert(0);
|
||||
IterationsToComplete = k;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -1,81 +0,0 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./lib/algorithms/iterative/EigenSort.h
|
||||
|
||||
Copyright (C) 2015
|
||||
|
||||
Author: Peter Boyle <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_EIGENSORT_H
|
||||
#define GRID_EIGENSORT_H
|
||||
|
||||
|
||||
namespace Grid {
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Eigen sorter to begin with
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Field>
|
||||
class SortEigen {
|
||||
private:
|
||||
|
||||
//hacking for testing for now
|
||||
private:
|
||||
static bool less_lmd(RealD left,RealD right){
|
||||
return left > right;
|
||||
}
|
||||
static bool less_pair(std::pair<RealD,Field const*>& left,
|
||||
std::pair<RealD,Field const*>& right){
|
||||
return left.first > (right.first);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
void push(DenseVector<RealD>& lmd,
|
||||
DenseVector<Field>& evec,int N) {
|
||||
DenseVector<Field> cpy(lmd.size(),evec[0]._grid);
|
||||
for(int i=0;i<lmd.size();i++) cpy[i] = evec[i];
|
||||
|
||||
DenseVector<std::pair<RealD, Field const*> > emod(lmd.size());
|
||||
for(int i=0;i<lmd.size();++i)
|
||||
emod[i] = std::pair<RealD,Field const*>(lmd[i],&cpy[i]);
|
||||
|
||||
partial_sort(emod.begin(),emod.begin()+N,emod.end(),less_pair);
|
||||
|
||||
typename DenseVector<std::pair<RealD, Field const*> >::iterator it = emod.begin();
|
||||
for(int i=0;i<N;++i){
|
||||
lmd[i]=it->first;
|
||||
evec[i]=*(it->second);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
void push(DenseVector<RealD>& lmd,int N) {
|
||||
std::partial_sort(lmd.begin(),lmd.begin()+N,lmd.end(),less_lmd);
|
||||
}
|
||||
bool saturated(RealD lmd, RealD thrs) {
|
||||
return fabs(lmd) > fabs(thrs);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/*************************************************************************************
|
||||
/*************************************************************************************
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
Source file: ./lib/lattice/Lattice_reduction.h
|
||||
Copyright (C) 2015
|
||||
@ -369,71 +369,6 @@ static void sliceMaddVector(Lattice<vobj> &R,std::vector<RealD> &a,const Lattice
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
template<class vobj>
|
||||
static void sliceMaddVectorSlow (Lattice<vobj> &R,std::vector<RealD> &a,const Lattice<vobj> &X,const Lattice<vobj> &Y,
|
||||
int Orthog,RealD scale=1.0)
|
||||
{
|
||||
// FIXME: Implementation is slow
|
||||
// Best base the linear combination by constructing a
|
||||
// set of vectors of size grid->_rdimensions[Orthog].
|
||||
typedef typename vobj::scalar_object sobj;
|
||||
typedef typename vobj::scalar_type scalar_type;
|
||||
typedef typename vobj::vector_type vector_type;
|
||||
|
||||
int Nblock = X._grid->GlobalDimensions()[Orthog];
|
||||
|
||||
GridBase *FullGrid = X._grid;
|
||||
GridBase *SliceGrid = makeSubSliceGrid(FullGrid,Orthog);
|
||||
|
||||
Lattice<vobj> Xslice(SliceGrid);
|
||||
Lattice<vobj> Rslice(SliceGrid);
|
||||
// If we based this on Cshift it would work for spread out
|
||||
// but it would be even slower
|
||||
for(int i=0;i<Nblock;i++){
|
||||
ExtractSlice(Rslice,Y,i,Orthog);
|
||||
ExtractSlice(Xslice,X,i,Orthog);
|
||||
Rslice = Rslice + Xslice*(scale*a[i]);
|
||||
InsertSlice(Rslice,R,i,Orthog);
|
||||
}
|
||||
};
|
||||
template<class vobj>
|
||||
static void sliceInnerProductVectorSlow( std::vector<ComplexD> & vec, const Lattice<vobj> &lhs,const Lattice<vobj> &rhs,int Orthog)
|
||||
{
|
||||
// FIXME: Implementation is slow
|
||||
// Look at localInnerProduct implementation,
|
||||
// and do inside a site loop with block strided iterators
|
||||
typedef typename vobj::scalar_object sobj;
|
||||
typedef typename vobj::scalar_type scalar_type;
|
||||
typedef typename vobj::vector_type vector_type;
|
||||
typedef typename vobj::tensor_reduced scalar;
|
||||
typedef typename scalar::scalar_object scomplex;
|
||||
|
||||
int Nblock = lhs._grid->GlobalDimensions()[Orthog];
|
||||
vec.resize(Nblock);
|
||||
std::vector<scomplex> sip(Nblock);
|
||||
Lattice<scalar> IP(lhs._grid);
|
||||
IP=localInnerProduct(lhs,rhs);
|
||||
sliceSum(IP,sip,Orthog);
|
||||
|
||||
for(int ss=0;ss<Nblock;ss++){
|
||||
vec[ss] = TensorRemove(sip[ss]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FIXME: Implementation is slow
|
||||
// If we based this on Cshift it would work for spread out
|
||||
// but it would be even slower
|
||||
//
|
||||
// Repeated extract slice is inefficient
|
||||
//
|
||||
// Best base the linear combination by constructing a
|
||||
// set of vectors of size grid->_rdimensions[Orthog].
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline GridBase *makeSubSliceGrid(const GridBase *BlockSolverGrid,int Orthog)
|
||||
{
|
||||
int NN = BlockSolverGrid->_ndimension;
|
||||
@ -453,7 +388,6 @@ inline GridBase *makeSubSliceGrid(const GridBase *BlockSolverGrid,int Or
|
||||
return (GridBase *)new GridCartesian(latt_phys,simd_phys,mpi_phys);
|
||||
}
|
||||
|
||||
|
||||
template<class vobj>
|
||||
static void sliceMaddMatrix (Lattice<vobj> &R,Eigen::MatrixXcd &aa,const Lattice<vobj> &X,const Lattice<vobj> &Y,int Orthog,RealD scale=1.0)
|
||||
{
|
||||
@ -462,28 +396,103 @@ static void sliceMaddMatrix (Lattice<vobj> &R,Eigen::MatrixXcd &aa,const Lattice
|
||||
typedef typename vobj::vector_type vector_type;
|
||||
|
||||
int Nblock = X._grid->GlobalDimensions()[Orthog];
|
||||
|
||||
|
||||
GridBase *FullGrid = X._grid;
|
||||
GridBase *SliceGrid = makeSubSliceGrid(FullGrid,Orthog);
|
||||
|
||||
|
||||
Lattice<vobj> Xslice(SliceGrid);
|
||||
Lattice<vobj> Rslice(SliceGrid);
|
||||
|
||||
for(int i=0;i<Nblock;i++){
|
||||
ExtractSlice(Rslice,Y,i,Orthog);
|
||||
for(int j=0;j<Nblock;j++){
|
||||
ExtractSlice(Xslice,X,j,Orthog);
|
||||
Rslice = Rslice + Xslice*(scale*aa(j,i));
|
||||
}
|
||||
InsertSlice(Rslice,R,i,Orthog);
|
||||
|
||||
assert( FullGrid->_simd_layout[Orthog]==1);
|
||||
int nh = FullGrid->_ndimension;
|
||||
int nl = SliceGrid->_ndimension;
|
||||
|
||||
//FIXME package in a convenient iterator
|
||||
//Should loop over a plane orthogonal to direction "Orthog"
|
||||
int stride=FullGrid->_slice_stride[Orthog];
|
||||
int block =FullGrid->_slice_block [Orthog];
|
||||
int nblock=FullGrid->_slice_nblock[Orthog];
|
||||
int ostride=FullGrid->_ostride[Orthog];
|
||||
#pragma omp parallel
|
||||
{
|
||||
std::vector<vobj> s_x(Nblock);
|
||||
|
||||
#pragma omp for collapse(2)
|
||||
for(int n=0;n<nblock;n++){
|
||||
for(int b=0;b<block;b++){
|
||||
int o = n*stride + b;
|
||||
|
||||
for(int i=0;i<Nblock;i++){
|
||||
s_x[i] = X[o+i*ostride];
|
||||
}
|
||||
|
||||
vobj dot;
|
||||
for(int i=0;i<Nblock;i++){
|
||||
dot = Y[o+i*ostride];
|
||||
for(int j=0;j<Nblock;j++){
|
||||
dot = dot + s_x[j]*(scale*aa(j,i));
|
||||
}
|
||||
R[o+i*ostride]=dot;
|
||||
}
|
||||
}}
|
||||
}
|
||||
};
|
||||
|
||||
template<class vobj>
|
||||
static void sliceMulMatrix (Lattice<vobj> &R,Eigen::MatrixXcd &aa,const Lattice<vobj> &X,int Orthog,RealD scale=1.0)
|
||||
{
|
||||
typedef typename vobj::scalar_object sobj;
|
||||
typedef typename vobj::scalar_type scalar_type;
|
||||
typedef typename vobj::vector_type vector_type;
|
||||
|
||||
int Nblock = X._grid->GlobalDimensions()[Orthog];
|
||||
|
||||
GridBase *FullGrid = X._grid;
|
||||
GridBase *SliceGrid = makeSubSliceGrid(FullGrid,Orthog);
|
||||
|
||||
Lattice<vobj> Xslice(SliceGrid);
|
||||
Lattice<vobj> Rslice(SliceGrid);
|
||||
|
||||
assert( FullGrid->_simd_layout[Orthog]==1);
|
||||
int nh = FullGrid->_ndimension;
|
||||
int nl = SliceGrid->_ndimension;
|
||||
|
||||
//FIXME package in a convenient iterator
|
||||
//Should loop over a plane orthogonal to direction "Orthog"
|
||||
int stride=FullGrid->_slice_stride[Orthog];
|
||||
int block =FullGrid->_slice_block [Orthog];
|
||||
int nblock=FullGrid->_slice_nblock[Orthog];
|
||||
int ostride=FullGrid->_ostride[Orthog];
|
||||
#pragma omp parallel
|
||||
{
|
||||
std::vector<vobj> s_x(Nblock);
|
||||
|
||||
#pragma omp for collapse(2)
|
||||
for(int n=0;n<nblock;n++){
|
||||
for(int b=0;b<block;b++){
|
||||
int o = n*stride + b;
|
||||
|
||||
for(int i=0;i<Nblock;i++){
|
||||
s_x[i] = X[o+i*ostride];
|
||||
}
|
||||
|
||||
vobj dot;
|
||||
for(int i=0;i<Nblock;i++){
|
||||
dot = s_x[0]*(scale*aa(0,i));
|
||||
for(int j=1;j<Nblock;j++){
|
||||
dot = dot + s_x[j]*(scale*aa(j,i));
|
||||
}
|
||||
R[o+i*ostride]=dot;
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<class vobj>
|
||||
static void sliceInnerProductMatrix( Eigen::MatrixXcd &mat, const Lattice<vobj> &lhs,const Lattice<vobj> &rhs,int Orthog)
|
||||
{
|
||||
// FIXME: Implementation is slow
|
||||
// Not sure of best solution.. think about it
|
||||
typedef typename vobj::scalar_object sobj;
|
||||
typedef typename vobj::scalar_type scalar_type;
|
||||
typedef typename vobj::vector_type vector_type;
|
||||
@ -497,22 +506,49 @@ static void sliceInnerProductMatrix( Eigen::MatrixXcd &mat, const Lattice<vobj>
|
||||
Lattice<vobj> Rslice(SliceGrid);
|
||||
|
||||
mat = Eigen::MatrixXcd::Zero(Nblock,Nblock);
|
||||
|
||||
for(int i=0;i<Nblock;i++){
|
||||
ExtractSlice(Lslice,lhs,i,Orthog);
|
||||
for(int j=0;j<Nblock;j++){
|
||||
ExtractSlice(Rslice,rhs,j,Orthog);
|
||||
mat(i,j) = innerProduct(Lslice,Rslice);
|
||||
}
|
||||
|
||||
assert( FullGrid->_simd_layout[Orthog]==1);
|
||||
int nh = FullGrid->_ndimension;
|
||||
int nl = SliceGrid->_ndimension;
|
||||
|
||||
//FIXME package in a convenient iterator
|
||||
//Should loop over a plane orthogonal to direction "Orthog"
|
||||
int stride=FullGrid->_slice_stride[Orthog];
|
||||
int block =FullGrid->_slice_block [Orthog];
|
||||
int nblock=FullGrid->_slice_nblock[Orthog];
|
||||
int ostride=FullGrid->_ostride[Orthog];
|
||||
|
||||
typedef typename vobj::vector_typeD vector_typeD;
|
||||
|
||||
#pragma omp parallel
|
||||
{
|
||||
std::vector<vobj> Left(Nblock);
|
||||
std::vector<vobj> Right(Nblock);
|
||||
Eigen::MatrixXcd mat_thread = Eigen::MatrixXcd::Zero(Nblock,Nblock);
|
||||
|
||||
#pragma omp for collapse(2)
|
||||
for(int n=0;n<nblock;n++){
|
||||
for(int b=0;b<block;b++){
|
||||
|
||||
int o = n*stride + b;
|
||||
|
||||
for(int i=0;i<Nblock;i++){
|
||||
Left [i] = lhs[o+i*ostride];
|
||||
Right[i] = rhs[o+i*ostride];
|
||||
}
|
||||
|
||||
for(int i=0;i<Nblock;i++){
|
||||
for(int j=0;j<Nblock;j++){
|
||||
auto tmp = innerProduct(Left[i],Right[j]);
|
||||
vector_typeD rtmp = TensorRemove(tmp);
|
||||
mat_thread(i,j) += Reduce(rtmp);
|
||||
}}
|
||||
}}
|
||||
#pragma omp critical
|
||||
{
|
||||
mat += mat_thread;
|
||||
}
|
||||
}
|
||||
#undef FORCE_DIAG
|
||||
#ifdef FORCE_DIAG
|
||||
for(int i=0;i<Nblock;i++){
|
||||
for(int j=0;j<Nblock;j++){
|
||||
if ( i != j ) mat(i,j)=0.0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -62,17 +62,12 @@ namespace Grid {
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class obj> Lattice<obj> expMat(const Lattice<obj> &rhs, ComplexD alpha, Integer Nexp = DEFAULT_MAT_EXP){
|
||||
template<class obj> Lattice<obj> expMat(const Lattice<obj> &rhs, RealD alpha, Integer Nexp = DEFAULT_MAT_EXP){
|
||||
Lattice<obj> ret(rhs._grid);
|
||||
ret.checkerboard = rhs.checkerboard;
|
||||
conformable(ret,rhs);
|
||||
obj unit(1.0);
|
||||
parallel_for(int ss=0;ss<rhs._grid->oSites();ss++){
|
||||
//ret._odata[ss]=Exponentiate(rhs._odata[ss],alpha, Nexp);
|
||||
ret._odata[ss] = unit;
|
||||
for(int i=Nexp; i>=1;--i)
|
||||
ret._odata[ss] = unit + ret._odata[ss]*rhs._odata[ss]*(alpha/RealD(i));
|
||||
|
||||
ret._odata[ss]=Exponentiate(rhs._odata[ss],alpha, Nexp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -598,9 +598,14 @@ class IldgReader : public GridLimeReader {
|
||||
}
|
||||
|
||||
if ( !strncmp(limeReaderType(LimeR), SCIDAC_RECORD_XML,strlen(SCIDAC_RECORD_XML)) ) {
|
||||
XmlReader RD(&xmlc[0],"");
|
||||
read(RD,"usqcdInfo",usqcdInfo_);
|
||||
found_usqcdInfo = 1;
|
||||
std::string xmls(&xmlc[0]);
|
||||
// is it a USQCD info field
|
||||
if ( xmls.find(std::string("usqcdInfo")) != std::string::npos ) {
|
||||
std::cout << GridLogMessage<<"...found a usqcdInfo field"<<std::endl;
|
||||
XmlReader RD(&xmlc[0],"");
|
||||
read(RD,"usqcdInfo",usqcdInfo_);
|
||||
found_usqcdInfo = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !strncmp(limeReaderType(LimeR), SCIDAC_CHECKSUM,strlen(SCIDAC_CHECKSUM)) ) {
|
||||
|
@ -65,8 +65,8 @@ public:
|
||||
typedef iImplGaugeField<Simd> SiteField;
|
||||
|
||||
typedef Lattice<SiteComplex> ComplexField;
|
||||
typedef Lattice<SiteLink> LinkField;
|
||||
typedef Lattice<SiteField> Field;
|
||||
typedef Lattice<SiteLink> LinkField;
|
||||
typedef Lattice<SiteField> Field;
|
||||
|
||||
// Guido: we can probably separate the types from the HMC functions
|
||||
// this will create 2 kind of implementations
|
||||
@ -86,7 +86,7 @@ public:
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Move these to another class
|
||||
// HMC auxiliary functions
|
||||
// HMC auxiliary functions
|
||||
static inline void generate_momenta(Field &P, GridParallelRNG &pRNG) {
|
||||
// specific for SU gauge fields
|
||||
LinkField Pmu(P._grid);
|
||||
@ -98,14 +98,19 @@ public:
|
||||
}
|
||||
|
||||
static inline Field projectForce(Field &P) { return Ta(P); }
|
||||
|
||||
|
||||
static inline void update_field(Field& P, Field& U, double ep){
|
||||
for (int mu = 0; mu < Nd; mu++) {
|
||||
auto Umu = PeekIndex<LorentzIndex>(U, mu);
|
||||
auto Pmu = PeekIndex<LorentzIndex>(P, mu);
|
||||
Umu = expMat(Pmu, ep, Nexp) * Umu;
|
||||
PokeIndex<LorentzIndex>(U, ProjectOnGroup(Umu), mu);
|
||||
//static std::chrono::duration<double> diff;
|
||||
|
||||
//auto start = std::chrono::high_resolution_clock::now();
|
||||
parallel_for(int ss=0;ss<P._grid->oSites();ss++){
|
||||
for (int mu = 0; mu < Nd; mu++)
|
||||
U[ss]._internal[mu] = ProjectOnGroup(Exponentiate(P[ss]._internal[mu], ep, Nexp) * U[ss]._internal[mu]);
|
||||
}
|
||||
|
||||
//auto end = std::chrono::high_resolution_clock::now();
|
||||
// diff += end - start;
|
||||
// std::cout << "Time to exponentiate matrix " << diff.count() << " s\n";
|
||||
}
|
||||
|
||||
static inline RealD FieldSquareNorm(Field& U){
|
||||
|
@ -71,14 +71,18 @@ class WilsonGaugeAction : public Action<typename Gimpl::GaugeField> {
|
||||
|
||||
RealD factor = 0.5 * beta / RealD(Nc);
|
||||
|
||||
GaugeLinkField Umu(U._grid);
|
||||
//GaugeLinkField Umu(U._grid);
|
||||
GaugeLinkField dSdU_mu(U._grid);
|
||||
for (int mu = 0; mu < Nd; mu++) {
|
||||
Umu = PeekIndex<LorentzIndex>(U, mu);
|
||||
//Umu = PeekIndex<LorentzIndex>(U, mu);
|
||||
|
||||
// Staple in direction mu
|
||||
WilsonLoops<Gimpl>::Staple(dSdU_mu, U, mu);
|
||||
dSdU_mu = Ta(Umu * dSdU_mu) * factor;
|
||||
//WilsonLoops<Gimpl>::Staple(dSdU_mu, U, mu);
|
||||
//dSdU_mu = Ta(Umu * dSdU_mu) * factor;
|
||||
|
||||
|
||||
WilsonLoops<Gimpl>::StapleMult(dSdU_mu, U, mu);
|
||||
dSdU_mu = Ta(dSdU_mu) * factor;
|
||||
|
||||
PokeIndex<LorentzIndex>(dSdU, dSdU_mu, mu);
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ namespace Grid {
|
||||
|
||||
typedef iImplField<Simd> SiteField;
|
||||
|
||||
template <typename vtype> using iImplScalar= iScalar<iScalar<iScalar<vtype > > >;
|
||||
typedef iImplScalar<Simd> ComplexField;
|
||||
|
||||
typedef Lattice<SiteField> Field;
|
||||
|
||||
@ -51,13 +53,14 @@ namespace Grid {
|
||||
public:
|
||||
typedef S Simd;
|
||||
|
||||
template <typename vtype>
|
||||
using iImplField = iScalar<iScalar<iMatrix<vtype, N> > >;
|
||||
|
||||
template <typename vtype> using iImplField = iScalar<iScalar<iMatrix<vtype, N> > >;
|
||||
|
||||
typedef iImplField<Simd> SiteField;
|
||||
|
||||
|
||||
typedef Lattice<SiteField> Field;
|
||||
|
||||
template <typename vtype> using iImplScalar= iScalar<iScalar<iScalar<vtype > > >;
|
||||
typedef iImplScalar<Simd> ComplexField;
|
||||
|
||||
|
||||
static inline void generate_momenta(Field& P, GridParallelRNG& pRNG){
|
||||
gaussian(pRNG, P);
|
||||
|
@ -102,7 +102,7 @@ class ILDGHmcCheckpointer : public BaseHmcCheckpointer<Implementation> {
|
||||
FieldMetaData header;
|
||||
IldgReader _IldgReader;
|
||||
_IldgReader.open(config);
|
||||
_IldgReader.readConfiguration(config,U,header); // format from the header
|
||||
_IldgReader.readConfiguration(U,header); // format from the header
|
||||
_IldgReader.close();
|
||||
|
||||
std::cout << GridLogMessage << "Read ILDG Configuration from " << config
|
||||
|
@ -58,6 +58,8 @@ class Smear_Stout : public Smear<Gimpl> {
|
||||
SmearBase->smear(C, U);
|
||||
};
|
||||
|
||||
|
||||
// Repetion of code here (use the Tensor_exp.h function)
|
||||
void exponentiate_iQ(GaugeLinkField& e_iQ, const GaugeLinkField& iQ) const {
|
||||
// Put this outside
|
||||
// only valid for SU(3) matrices
|
||||
|
@ -36,20 +36,23 @@ namespace QCD {
|
||||
template <class Gimpl>
|
||||
class WilsonFlow: public Smear<Gimpl>{
|
||||
unsigned int Nstep;
|
||||
RealD epsilon;
|
||||
unsigned int measure_interval;
|
||||
mutable RealD epsilon, taus;
|
||||
|
||||
|
||||
mutable WilsonGaugeAction<Gimpl> SG;
|
||||
|
||||
void evolve_step(typename Gimpl::GaugeField&) const;
|
||||
void evolve_step_adaptive(typename Gimpl::GaugeField&, RealD);
|
||||
RealD tau(unsigned int t)const {return epsilon*(t+1.0); }
|
||||
|
||||
|
||||
public:
|
||||
INHERIT_GIMPL_TYPES(Gimpl)
|
||||
|
||||
explicit WilsonFlow(unsigned int Nstep, RealD epsilon):
|
||||
explicit WilsonFlow(unsigned int Nstep, RealD epsilon, unsigned int interval = 1):
|
||||
Nstep(Nstep),
|
||||
epsilon(epsilon),
|
||||
measure_interval(interval),
|
||||
SG(WilsonGaugeAction<Gimpl>(3.0)) {
|
||||
// WilsonGaugeAction with beta 3.0
|
||||
assert(epsilon > 0.0);
|
||||
@ -72,7 +75,9 @@ class WilsonFlow: public Smear<Gimpl>{
|
||||
// undefined for WilsonFlow
|
||||
}
|
||||
|
||||
void smear_adaptive(GaugeField&, const GaugeField&, RealD maxTau);
|
||||
RealD energyDensityPlaquette(unsigned int step, const GaugeField& U) const;
|
||||
RealD energyDensityPlaquette(const GaugeField& U) const;
|
||||
};
|
||||
|
||||
|
||||
@ -98,23 +103,111 @@ void WilsonFlow<Gimpl>::evolve_step(typename Gimpl::GaugeField &U) const{
|
||||
Gimpl::update_field(Z, U, -2.0*epsilon); // V(t+e) = exp(ep*Z)*W2
|
||||
}
|
||||
|
||||
template <class Gimpl>
|
||||
void WilsonFlow<Gimpl>::evolve_step_adaptive(typename Gimpl::GaugeField &U, RealD maxTau) {
|
||||
if (maxTau - taus < epsilon){
|
||||
epsilon = maxTau-taus;
|
||||
}
|
||||
std::cout << GridLogMessage << "Integration epsilon : " << epsilon << std::endl;
|
||||
GaugeField Z(U._grid);
|
||||
GaugeField Zprime(U._grid);
|
||||
GaugeField tmp(U._grid), Uprime(U._grid);
|
||||
Uprime = U;
|
||||
SG.deriv(U, Z);
|
||||
Zprime = -Z;
|
||||
Z *= 0.25; // Z0 = 1/4 * F(U)
|
||||
Gimpl::update_field(Z, U, -2.0*epsilon); // U = W1 = exp(ep*Z0)*W0
|
||||
|
||||
Z *= -17.0/8.0;
|
||||
SG.deriv(U, tmp); Z += tmp; // -17/32*Z0 +Z1
|
||||
Zprime += 2.0*tmp;
|
||||
Z *= 8.0/9.0; // Z = -17/36*Z0 +8/9*Z1
|
||||
Gimpl::update_field(Z, U, -2.0*epsilon); // U_= W2 = exp(ep*Z)*W1
|
||||
|
||||
|
||||
Z *= -4.0/3.0;
|
||||
SG.deriv(U, tmp); Z += tmp; // 4/3*(17/36*Z0 -8/9*Z1) +Z2
|
||||
Z *= 3.0/4.0; // Z = 17/36*Z0 -8/9*Z1 +3/4*Z2
|
||||
Gimpl::update_field(Z, U, -2.0*epsilon); // V(t+e) = exp(ep*Z)*W2
|
||||
|
||||
// Ramos
|
||||
Gimpl::update_field(Zprime, Uprime, -2.0*epsilon); // V'(t+e) = exp(ep*Z')*W0
|
||||
// Compute distance as norm^2 of the difference
|
||||
GaugeField diffU = U - Uprime;
|
||||
RealD diff = norm2(diffU);
|
||||
// adjust integration step
|
||||
|
||||
taus += epsilon;
|
||||
std::cout << GridLogMessage << "Adjusting integration step with distance: " << diff << std::endl;
|
||||
|
||||
epsilon = epsilon*0.95*std::pow(1e-4/diff,1./3.);
|
||||
std::cout << GridLogMessage << "New epsilon : " << epsilon << std::endl;
|
||||
|
||||
}
|
||||
|
||||
template <class Gimpl>
|
||||
RealD WilsonFlow<Gimpl>::energyDensityPlaquette(unsigned int step, const GaugeField& U) const {
|
||||
RealD td = tau(step);
|
||||
return 2.0 * td * td * SG.S(U)/U._grid->gSites();
|
||||
}
|
||||
|
||||
template <class Gimpl>
|
||||
RealD WilsonFlow<Gimpl>::energyDensityPlaquette(const GaugeField& U) const {
|
||||
return 2.0 * taus * taus * SG.S(U)/U._grid->gSites();
|
||||
}
|
||||
|
||||
|
||||
//#define WF_TIMING
|
||||
|
||||
|
||||
|
||||
template <class Gimpl>
|
||||
void WilsonFlow<Gimpl>::smear(GaugeField& out, const GaugeField& in) const {
|
||||
out = in;
|
||||
for (unsigned int step = 0; step < Nstep; step++) {
|
||||
for (unsigned int step = 1; step <= Nstep; step++) {
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
std::cout << GridLogMessage << "Evolution time :"<< tau(step) << std::endl;
|
||||
evolve_step(out);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> diff = end - start;
|
||||
#ifdef WF_TIMING
|
||||
std::cout << "Time to evolve " << diff.count() << " s\n";
|
||||
#endif
|
||||
std::cout << GridLogMessage << "[WilsonFlow] Energy density (plaq) : "
|
||||
<< step << " "
|
||||
<< step << " "
|
||||
<< energyDensityPlaquette(step,out) << std::endl;
|
||||
if( step % measure_interval == 0){
|
||||
std::cout << GridLogMessage << "[WilsonFlow] Top. charge : "
|
||||
<< step << " "
|
||||
<< WilsonLoops<PeriodicGimplR>::TopologicalCharge(out) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Gimpl>
|
||||
void WilsonFlow<Gimpl>::smear_adaptive(GaugeField& out, const GaugeField& in, RealD maxTau){
|
||||
out = in;
|
||||
taus = epsilon;
|
||||
unsigned int step = 0;
|
||||
do{
|
||||
step++;
|
||||
std::cout << GridLogMessage << "Evolution time :"<< taus << std::endl;
|
||||
evolve_step_adaptive(out, maxTau);
|
||||
std::cout << GridLogMessage << "[WilsonFlow] Energy density (plaq) : "
|
||||
<< step << " "
|
||||
<< energyDensityPlaquette(out) << std::endl;
|
||||
if( step % measure_interval == 0){
|
||||
std::cout << GridLogMessage << "[WilsonFlow] Top. charge : "
|
||||
<< step << " "
|
||||
<< WilsonLoops<PeriodicGimplR>::TopologicalCharge(out) << std::endl;
|
||||
}
|
||||
} while (taus < maxTau);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace QCD
|
||||
} // namespace Grid
|
||||
|
||||
|
188
lib/qcd/utils/GaugeFix.h
Normal file
188
lib/qcd/utils/GaugeFix.h
Normal file
@ -0,0 +1,188 @@
|
||||
/*************************************************************************************
|
||||
|
||||
grid` physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Copyright (C) 2015
|
||||
|
||||
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
|
||||
Author: Peter Boyle <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 */
|
||||
//#include <Grid/Grid.h>
|
||||
|
||||
using namespace Grid;
|
||||
using namespace Grid::QCD;
|
||||
|
||||
template <class Gimpl>
|
||||
class FourierAcceleratedGaugeFixer : public Gimpl {
|
||||
public:
|
||||
INHERIT_GIMPL_TYPES(Gimpl);
|
||||
|
||||
typedef typename Gimpl::GaugeLinkField GaugeMat;
|
||||
typedef typename Gimpl::GaugeField GaugeLorentz;
|
||||
|
||||
static void GaugeLinkToLieAlgebraField(const std::vector<GaugeMat> &U,std::vector<GaugeMat> &A) {
|
||||
for(int mu=0;mu<Nd;mu++){
|
||||
Complex cmi(0.0,-1.0);
|
||||
A[mu] = Ta(U[mu]) * cmi;
|
||||
}
|
||||
}
|
||||
static void DmuAmu(const std::vector<GaugeMat> &A,GaugeMat &dmuAmu) {
|
||||
dmuAmu=zero;
|
||||
for(int mu=0;mu<Nd;mu++){
|
||||
dmuAmu = dmuAmu + A[mu] - Cshift(A[mu],mu,-1);
|
||||
}
|
||||
}
|
||||
static void SteepestDescentGaugeFix(GaugeLorentz &Umu,Real & alpha,int maxiter,Real Omega_tol, Real Phi_tol,bool Fourier=false) {
|
||||
GridBase *grid = Umu._grid;
|
||||
|
||||
Real org_plaq =WilsonLoops<Gimpl>::avgPlaquette(Umu);
|
||||
Real org_link_trace=WilsonLoops<Gimpl>::linkTrace(Umu);
|
||||
Real old_trace = org_link_trace;
|
||||
Real trG;
|
||||
|
||||
std::vector<GaugeMat> U(Nd,grid);
|
||||
GaugeMat dmuAmu(grid);
|
||||
|
||||
for(int i=0;i<maxiter;i++){
|
||||
for(int mu=0;mu<Nd;mu++) U[mu]= PeekIndex<LorentzIndex>(Umu,mu);
|
||||
if ( Fourier==false ) {
|
||||
trG = SteepestDescentStep(U,alpha,dmuAmu);
|
||||
} else {
|
||||
trG = FourierAccelSteepestDescentStep(U,alpha,dmuAmu);
|
||||
}
|
||||
for(int mu=0;mu<Nd;mu++) PokeIndex<LorentzIndex>(Umu,U[mu],mu);
|
||||
// Monitor progress and convergence test
|
||||
// infrequently to minimise cost overhead
|
||||
if ( i %20 == 0 ) {
|
||||
Real plaq =WilsonLoops<Gimpl>::avgPlaquette(Umu);
|
||||
Real link_trace=WilsonLoops<Gimpl>::linkTrace(Umu);
|
||||
|
||||
if (Fourier)
|
||||
std::cout << GridLogMessage << "Fourier Iteration "<<i<< " plaq= "<<plaq<< " dmuAmu " << norm2(dmuAmu)<< std::endl;
|
||||
else
|
||||
std::cout << GridLogMessage << " Iteration "<<i<< " plaq= "<<plaq<< " dmuAmu " << norm2(dmuAmu)<< std::endl;
|
||||
|
||||
Real Phi = 1.0 - old_trace / link_trace ;
|
||||
Real Omega= 1.0 - trG;
|
||||
|
||||
|
||||
std::cout << GridLogMessage << " Iteration "<<i<< " Phi= "<<Phi<< " Omega= " << Omega<< " trG " << trG <<std::endl;
|
||||
if ( (Omega < Omega_tol) && ( ::fabs(Phi) < Phi_tol) ) {
|
||||
std::cout << GridLogMessage << "Converged ! "<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
old_trace = link_trace;
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
static Real SteepestDescentStep(std::vector<GaugeMat> &U,Real & alpha, GaugeMat & dmuAmu) {
|
||||
GridBase *grid = U[0]._grid;
|
||||
|
||||
std::vector<GaugeMat> A(Nd,grid);
|
||||
GaugeMat g(grid);
|
||||
|
||||
GaugeLinkToLieAlgebraField(U,A);
|
||||
ExpiAlphaDmuAmu(A,g,alpha,dmuAmu);
|
||||
|
||||
|
||||
Real vol = grid->gSites();
|
||||
Real trG = TensorRemove(sum(trace(g))).real()/vol/Nc;
|
||||
|
||||
SU<Nc>::GaugeTransform(U,g);
|
||||
|
||||
return trG;
|
||||
}
|
||||
|
||||
static Real FourierAccelSteepestDescentStep(std::vector<GaugeMat> &U,Real & alpha, GaugeMat & dmuAmu) {
|
||||
|
||||
GridBase *grid = U[0]._grid;
|
||||
|
||||
Real vol = grid->gSites();
|
||||
|
||||
FFT theFFT((GridCartesian *)grid);
|
||||
|
||||
LatticeComplex Fp(grid);
|
||||
LatticeComplex psq(grid); psq=zero;
|
||||
LatticeComplex pmu(grid);
|
||||
LatticeComplex one(grid); one = Complex(1.0,0.0);
|
||||
|
||||
GaugeMat g(grid);
|
||||
GaugeMat dmuAmu_p(grid);
|
||||
std::vector<GaugeMat> A(Nd,grid);
|
||||
|
||||
GaugeLinkToLieAlgebraField(U,A);
|
||||
|
||||
DmuAmu(A,dmuAmu);
|
||||
|
||||
theFFT.FFT_all_dim(dmuAmu_p,dmuAmu,FFT::forward);
|
||||
|
||||
//////////////////////////////////
|
||||
// Work out Fp = psq_max/ psq...
|
||||
//////////////////////////////////
|
||||
std::vector<int> latt_size = grid->GlobalDimensions();
|
||||
std::vector<int> coor(grid->_ndimension,0);
|
||||
for(int mu=0;mu<Nd;mu++) {
|
||||
|
||||
Real TwoPiL = M_PI * 2.0/ latt_size[mu];
|
||||
LatticeCoordinate(pmu,mu);
|
||||
pmu = TwoPiL * pmu ;
|
||||
psq = psq + 4.0*sin(pmu*0.5)*sin(pmu*0.5);
|
||||
}
|
||||
|
||||
Complex psqMax(16.0);
|
||||
Fp = psqMax*one/psq;
|
||||
|
||||
/*
|
||||
static int once;
|
||||
if ( once == 0 ) {
|
||||
std::cout << " Fp " << Fp <<std::endl;
|
||||
once ++;
|
||||
}*/
|
||||
|
||||
pokeSite(TComplex(1.0),Fp,coor);
|
||||
|
||||
dmuAmu_p = dmuAmu_p * Fp;
|
||||
|
||||
theFFT.FFT_all_dim(dmuAmu,dmuAmu_p,FFT::backward);
|
||||
|
||||
GaugeMat ciadmam(grid);
|
||||
Complex cialpha(0.0,-alpha);
|
||||
ciadmam = dmuAmu*cialpha;
|
||||
SU<Nc>::taExp(ciadmam,g);
|
||||
|
||||
Real trG = TensorRemove(sum(trace(g))).real()/vol/Nc;
|
||||
|
||||
SU<Nc>::GaugeTransform(U,g);
|
||||
|
||||
return trG;
|
||||
}
|
||||
|
||||
static void ExpiAlphaDmuAmu(const std::vector<GaugeMat> &A,GaugeMat &g,Real & alpha, GaugeMat &dmuAmu) {
|
||||
GridBase *grid = g._grid;
|
||||
Complex cialpha(0.0,-alpha);
|
||||
GaugeMat ciadmam(grid);
|
||||
DmuAmu(A,dmuAmu);
|
||||
ciadmam = dmuAmu*cialpha;
|
||||
SU<Nc>::taExp(ciadmam,g);
|
||||
}
|
||||
};
|
||||
|
@ -188,6 +188,32 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For the force term
|
||||
static void StapleMult(GaugeMat &staple, const GaugeLorentz &Umu, int mu) {
|
||||
GridBase *grid = Umu._grid;
|
||||
std::vector<GaugeMat> U(Nd, grid);
|
||||
for (int d = 0; d < Nd; d++) {
|
||||
// this operation is taking too much time
|
||||
U[d] = PeekIndex<LorentzIndex>(Umu, d);
|
||||
}
|
||||
staple = zero;
|
||||
GaugeMat tmp1(grid);
|
||||
GaugeMat tmp2(grid);
|
||||
|
||||
for (int nu = 0; nu < Nd; nu++) {
|
||||
if (nu != mu) {
|
||||
// this is ~10% faster than the Staple
|
||||
tmp1 = Cshift(U[nu], mu, 1);
|
||||
tmp2 = Cshift(U[mu], nu, 1);
|
||||
staple += tmp1* adj(U[nu]*tmp2);
|
||||
tmp2 = adj(U[mu]*tmp1)*U[nu];
|
||||
staple += Cshift(tmp2, nu, -1);
|
||||
}
|
||||
}
|
||||
staple = U[mu]*staple;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// the sum over all staples on each site
|
||||
//////////////////////////////////////////////////
|
||||
@ -200,7 +226,6 @@ public:
|
||||
U[d] = PeekIndex<LorentzIndex>(Umu, d);
|
||||
}
|
||||
staple = zero;
|
||||
GaugeMat tmp(grid);
|
||||
|
||||
for (int nu = 0; nu < Nd; nu++) {
|
||||
|
||||
@ -214,7 +239,7 @@ public:
|
||||
// |
|
||||
// __|
|
||||
//
|
||||
|
||||
|
||||
staple += Gimpl::ShiftStaple(
|
||||
Gimpl::CovShiftForward(
|
||||
U[nu], nu,
|
||||
@ -227,6 +252,7 @@ public:
|
||||
// |__
|
||||
//
|
||||
//
|
||||
|
||||
staple += Gimpl::ShiftStaple(
|
||||
Gimpl::CovShiftBackward(U[nu], nu,
|
||||
Gimpl::CovShiftBackward(U[mu], mu, U[nu])), mu);
|
||||
@ -289,8 +315,7 @@ public:
|
||||
//
|
||||
staple = Gimpl::ShiftStaple(
|
||||
Gimpl::CovShiftBackward(U[nu], nu,
|
||||
Gimpl::CovShiftBackward(U[mu], mu, U[nu])),
|
||||
mu);
|
||||
Gimpl::CovShiftBackward(U[mu], mu, U[nu])), mu);
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,10 +332,10 @@ public:
|
||||
GaugeMat Vup(Umu._grid), Vdn(Umu._grid);
|
||||
StapleUpper(Vup, Umu, mu, nu);
|
||||
StapleLower(Vdn, Umu, mu, nu);
|
||||
GaugeMat v = adj(Vup) - adj(Vdn);
|
||||
GaugeMat v = Vup - Vdn;
|
||||
GaugeMat u = PeekIndex<LorentzIndex>(Umu, mu); // some redundant copies
|
||||
GaugeMat vu = v*u;
|
||||
FS = 0.25*Ta(u*v + Cshift(vu, mu, +1));
|
||||
FS = 0.25*Ta(u*v + Cshift(vu, mu, -1));
|
||||
}
|
||||
|
||||
static Real TopologicalCharge(GaugeLorentz &U){
|
||||
|
@ -751,8 +751,8 @@ inline Grid_simd<std::complex<R>, V> toComplex(const Grid_simd<R, V> &in) {
|
||||
|
||||
conv.v = in.v;
|
||||
for (int i = 0; i < Rsimd::Nsimd(); i += 2) {
|
||||
assert(conv.s[i + 1] ==
|
||||
conv.s[i]); // trap any cases where real was not duplicated
|
||||
assert(conv.s[i + 1] == conv.s[i]);
|
||||
// trap any cases where real was not duplicated
|
||||
// indicating the SIMD grids of real and imag assignment did not correctly
|
||||
// match
|
||||
conv.s[i + 1] = 0.0; // zero imaginary parts
|
||||
|
@ -156,11 +156,18 @@ class iScalar {
|
||||
|
||||
// convert from a something to a scalar via constructor of something arg
|
||||
template <class T, typename std::enable_if<!isGridTensor<T>::value, T>::type * = nullptr>
|
||||
strong_inline iScalar<vtype> operator=(T arg) {
|
||||
strong_inline iScalar<vtype> operator=(T arg) {
|
||||
_internal = arg;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Convert elements
|
||||
template <class ttype>
|
||||
strong_inline iScalar<vtype> operator=(iScalar<ttype> &&arg) {
|
||||
_internal = arg._internal;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream,const iScalar<vtype> &o) {
|
||||
stream << "S {" << o._internal << "}";
|
||||
return stream;
|
||||
|
@ -37,30 +37,108 @@ namespace Grid {
|
||||
///////////////////////////////////////////////
|
||||
|
||||
|
||||
template<class vtype> inline iScalar<vtype> Exponentiate(const iScalar<vtype>&r, ComplexD alpha , Integer Nexp = DEFAULT_MAT_EXP)
|
||||
template<class vtype> inline iScalar<vtype> Exponentiate(const iScalar<vtype>&r, RealD alpha , Integer Nexp = DEFAULT_MAT_EXP)
|
||||
{
|
||||
iScalar<vtype> ret;
|
||||
ret._internal = Exponentiate(r._internal, alpha, Nexp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template<class vtype,int N, typename std::enable_if< GridTypeMapper<vtype>::TensorLevel == 0 >::type * =nullptr>
|
||||
inline iMatrix<vtype,N> Exponentiate(const iMatrix<vtype,N> &arg, ComplexD alpha , Integer Nexp = DEFAULT_MAT_EXP )
|
||||
template<class vtype, int N> inline iVector<vtype, N> Exponentiate(const iVector<vtype,N>&r, RealD alpha , Integer Nexp = DEFAULT_MAT_EXP)
|
||||
{
|
||||
iMatrix<vtype,N> unit(1.0);
|
||||
iMatrix<vtype,N> temp(unit);
|
||||
|
||||
for(int i=Nexp; i>=1;--i){
|
||||
temp *= alpha/ComplexD(i);
|
||||
temp = unit + temp*arg;
|
||||
}
|
||||
|
||||
return temp;
|
||||
|
||||
iVector<vtype, N> ret;
|
||||
for (int i = 0; i < N; i++)
|
||||
ret._internal[i] = Exponentiate(r._internal[i], alpha, Nexp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Specialisation: Cayley-Hamilton exponential for SU(3)
|
||||
template<class vtype, typename std::enable_if< GridTypeMapper<vtype>::TensorLevel == 0>::type * =nullptr>
|
||||
inline iMatrix<vtype,3> Exponentiate(const iMatrix<vtype,3> &arg, RealD alpha , Integer Nexp = DEFAULT_MAT_EXP )
|
||||
{
|
||||
// for SU(3) 2x faster than the std implementation using Nexp=12
|
||||
// notice that it actually computes
|
||||
// exp ( input matrix )
|
||||
// the i sign is coming from outside
|
||||
// input matrix is anti-hermitian NOT hermitian
|
||||
typedef iMatrix<vtype,3> mat;
|
||||
typedef iScalar<vtype> scalar;
|
||||
mat unit(1.0);
|
||||
mat temp(unit);
|
||||
const Complex one_over_three = 1.0 / 3.0;
|
||||
const Complex one_over_two = 1.0 / 2.0;
|
||||
|
||||
scalar c0, c1, tmp, c0max, theta, u, w;
|
||||
scalar xi0, u2, w2, cosw;
|
||||
scalar fden, h0, h1, h2;
|
||||
scalar e2iu, emiu, ixi0, qt;
|
||||
scalar f0, f1, f2;
|
||||
scalar unity(1.0);
|
||||
|
||||
mat iQ2 = arg*arg*alpha*alpha;
|
||||
mat iQ3 = arg*iQ2*alpha;
|
||||
// sign in c0 from the conventions on the Ta
|
||||
scalar imQ3, reQ2;
|
||||
imQ3 = imag( trace(iQ3) );
|
||||
reQ2 = real( trace(iQ2) );
|
||||
c0 = -imQ3 * one_over_three;
|
||||
c1 = -reQ2 * one_over_two;
|
||||
|
||||
// Cayley Hamilton checks to machine precision, tested
|
||||
tmp = c1 * one_over_three;
|
||||
c0max = 2.0 * pow(tmp, 1.5);
|
||||
|
||||
theta = acos(c0 / c0max) * one_over_three;
|
||||
u = sqrt(tmp) * cos(theta);
|
||||
w = sqrt(c1) * sin(theta);
|
||||
|
||||
xi0 = sin(w) / w;
|
||||
u2 = u * u;
|
||||
w2 = w * w;
|
||||
cosw = cos(w);
|
||||
|
||||
ixi0 = timesI(xi0);
|
||||
emiu = cos(u) - timesI(sin(u));
|
||||
e2iu = cos(2.0 * u) + timesI(sin(2.0 * u));
|
||||
|
||||
h0 = e2iu * (u2 - w2) +
|
||||
emiu * ((8.0 * u2 * cosw) + (2.0 * u * (3.0 * u2 + w2) * ixi0));
|
||||
h1 = e2iu * (2.0 * u) - emiu * ((2.0 * u * cosw) - (3.0 * u2 - w2) * ixi0);
|
||||
h2 = e2iu - emiu * (cosw + (3.0 * u) * ixi0);
|
||||
|
||||
fden = unity / (9.0 * u2 - w2); // reals
|
||||
f0 = h0 * fden;
|
||||
f1 = h1 * fden;
|
||||
f2 = h2 * fden;
|
||||
|
||||
return (f0 * unit + timesMinusI(f1) * arg*alpha - f2 * iQ2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// General exponential
|
||||
template<class vtype,int N, typename std::enable_if< GridTypeMapper<vtype>::TensorLevel == 0 >::type * =nullptr>
|
||||
inline iMatrix<vtype,N> Exponentiate(const iMatrix<vtype,N> &arg, RealD alpha , Integer Nexp = DEFAULT_MAT_EXP )
|
||||
{
|
||||
// notice that it actually computes
|
||||
// exp ( input matrix )
|
||||
// the i sign is coming from outside
|
||||
// input matrix is anti-hermitian NOT hermitian
|
||||
typedef iMatrix<vtype,N> mat;
|
||||
mat unit(1.0);
|
||||
mat temp(unit);
|
||||
for(int i=Nexp; i>=1;--i){
|
||||
temp *= alpha/RealD(i);
|
||||
temp = unit + temp*arg;
|
||||
}
|
||||
return temp;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -73,7 +73,7 @@ int main (int argc, char ** argv)
|
||||
|
||||
std::vector<LatticeColourMatrix> U(4,&Fine);
|
||||
|
||||
NerscField header;
|
||||
FieldMetaData header;
|
||||
|
||||
std::string file("./ckpoint_lat.4000");
|
||||
NerscIO::readConfiguration(Umu,header,file);
|
||||
|
@ -90,7 +90,7 @@ int main (int argc, char ** argv)
|
||||
|
||||
std::vector<LatticeColourMatrix> U(4,&Fine);
|
||||
|
||||
NerscField header;
|
||||
FieldMetaData header;
|
||||
|
||||
std::string file("./ckpoint_lat.4000");
|
||||
NerscIO::readConfiguration(Umu,header,file);
|
||||
|
@ -28,212 +28,6 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
/* END LEGAL */
|
||||
#include <Grid/Grid.h>
|
||||
|
||||
using namespace Grid;
|
||||
using namespace Grid::QCD;
|
||||
|
||||
template <class Gimpl>
|
||||
class FourierAcceleratedGaugeFixer : public Gimpl {
|
||||
public:
|
||||
INHERIT_GIMPL_TYPES(Gimpl);
|
||||
|
||||
typedef typename Gimpl::GaugeLinkField GaugeMat;
|
||||
typedef typename Gimpl::GaugeField GaugeLorentz;
|
||||
|
||||
static void GaugeLinkToLieAlgebraField(const std::vector<GaugeMat> &U,std::vector<GaugeMat> &A) {
|
||||
for(int mu=0;mu<Nd;mu++){
|
||||
// ImplComplex cmi(0.0,-1.0);
|
||||
Complex cmi(0.0,-1.0);
|
||||
A[mu] = Ta(U[mu]) * cmi;
|
||||
}
|
||||
}
|
||||
static void DmuAmu(const std::vector<GaugeMat> &A,GaugeMat &dmuAmu) {
|
||||
dmuAmu=zero;
|
||||
for(int mu=0;mu<Nd;mu++){
|
||||
dmuAmu = dmuAmu + A[mu] - Cshift(A[mu],mu,-1);
|
||||
}
|
||||
}
|
||||
static void SteepestDescentGaugeFix(GaugeLorentz &Umu,Real & alpha,int maxiter,Real Omega_tol, Real Phi_tol) {
|
||||
GridBase *grid = Umu._grid;
|
||||
|
||||
Real org_plaq =WilsonLoops<Gimpl>::avgPlaquette(Umu);
|
||||
Real org_link_trace=WilsonLoops<Gimpl>::linkTrace(Umu);
|
||||
Real old_trace = org_link_trace;
|
||||
Real trG;
|
||||
|
||||
std::vector<GaugeMat> U(Nd,grid);
|
||||
GaugeMat dmuAmu(grid);
|
||||
|
||||
for(int i=0;i<maxiter;i++){
|
||||
for(int mu=0;mu<Nd;mu++) U[mu]= PeekIndex<LorentzIndex>(Umu,mu);
|
||||
//trG = SteepestDescentStep(U,alpha,dmuAmu);
|
||||
trG = FourierAccelSteepestDescentStep(U,alpha,dmuAmu);
|
||||
for(int mu=0;mu<Nd;mu++) PokeIndex<LorentzIndex>(Umu,U[mu],mu);
|
||||
// Monitor progress and convergence test
|
||||
// infrequently to minimise cost overhead
|
||||
if ( i %20 == 0 ) {
|
||||
Real plaq =WilsonLoops<Gimpl>::avgPlaquette(Umu);
|
||||
Real link_trace=WilsonLoops<Gimpl>::linkTrace(Umu);
|
||||
|
||||
std::cout << GridLogMessage << " Iteration "<<i<< " plaq= "<<plaq<< " dmuAmu " << norm2(dmuAmu)<< std::endl;
|
||||
|
||||
Real Phi = 1.0 - old_trace / link_trace ;
|
||||
Real Omega= 1.0 - trG;
|
||||
|
||||
|
||||
std::cout << GridLogMessage << " Iteration "<<i<< " Phi= "<<Phi<< " Omega= " << Omega<< " trG " << trG <<std::endl;
|
||||
if ( (Omega < Omega_tol) && ( ::fabs(Phi) < Phi_tol) ) {
|
||||
std::cout << GridLogMessage << "Converged ! "<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
old_trace = link_trace;
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
static Real SteepestDescentStep(std::vector<GaugeMat> &U,Real & alpha, GaugeMat & dmuAmu) {
|
||||
GridBase *grid = U[0]._grid;
|
||||
|
||||
std::vector<GaugeMat> A(Nd,grid);
|
||||
GaugeMat g(grid);
|
||||
|
||||
GaugeLinkToLieAlgebraField(U,A);
|
||||
ExpiAlphaDmuAmu(A,g,alpha,dmuAmu);
|
||||
|
||||
|
||||
Real vol = grid->gSites();
|
||||
Real trG = TensorRemove(sum(trace(g))).real()/vol/Nc;
|
||||
|
||||
SU<Nc>::GaugeTransform(U,g);
|
||||
|
||||
return trG;
|
||||
}
|
||||
|
||||
static Real FourierAccelSteepestDescentStep(std::vector<GaugeMat> &U,Real & alpha, GaugeMat & dmuAmu) {
|
||||
|
||||
GridBase *grid = U[0]._grid;
|
||||
|
||||
Real vol = grid->gSites();
|
||||
|
||||
FFT theFFT((GridCartesian *)grid);
|
||||
|
||||
LatticeComplex Fp(grid);
|
||||
LatticeComplex psq(grid); psq=zero;
|
||||
LatticeComplex pmu(grid);
|
||||
LatticeComplex one(grid); one = Complex(1.0,0.0);
|
||||
|
||||
GaugeMat g(grid);
|
||||
GaugeMat dmuAmu_p(grid);
|
||||
std::vector<GaugeMat> A(Nd,grid);
|
||||
|
||||
GaugeLinkToLieAlgebraField(U,A);
|
||||
|
||||
DmuAmu(A,dmuAmu);
|
||||
|
||||
theFFT.FFT_all_dim(dmuAmu_p,dmuAmu,FFT::forward);
|
||||
|
||||
//////////////////////////////////
|
||||
// Work out Fp = psq_max/ psq...
|
||||
//////////////////////////////////
|
||||
std::vector<int> latt_size = grid->GlobalDimensions();
|
||||
std::vector<int> coor(grid->_ndimension,0);
|
||||
for(int mu=0;mu<Nd;mu++) {
|
||||
|
||||
Real TwoPiL = M_PI * 2.0/ latt_size[mu];
|
||||
LatticeCoordinate(pmu,mu);
|
||||
pmu = TwoPiL * pmu ;
|
||||
psq = psq + 4.0*sin(pmu*0.5)*sin(pmu*0.5);
|
||||
}
|
||||
|
||||
Complex psqMax(16.0);
|
||||
Fp = psqMax*one/psq;
|
||||
|
||||
/*
|
||||
static int once;
|
||||
if ( once == 0 ) {
|
||||
std::cout << " Fp " << Fp <<std::endl;
|
||||
once ++;
|
||||
}*/
|
||||
|
||||
pokeSite(TComplex(1.0),Fp,coor);
|
||||
|
||||
dmuAmu_p = dmuAmu_p * Fp;
|
||||
|
||||
theFFT.FFT_all_dim(dmuAmu,dmuAmu_p,FFT::backward);
|
||||
|
||||
GaugeMat ciadmam(grid);
|
||||
Complex cialpha(0.0,-alpha);
|
||||
ciadmam = dmuAmu*cialpha;
|
||||
SU<Nc>::taExp(ciadmam,g);
|
||||
|
||||
Real trG = TensorRemove(sum(trace(g))).real()/vol/Nc;
|
||||
|
||||
SU<Nc>::GaugeTransform(U,g);
|
||||
|
||||
return trG;
|
||||
}
|
||||
|
||||
static void ExpiAlphaDmuAmu(const std::vector<GaugeMat> &A,GaugeMat &g,Real & alpha, GaugeMat &dmuAmu) {
|
||||
GridBase *grid = g._grid;
|
||||
Complex cialpha(0.0,-alpha);
|
||||
GaugeMat ciadmam(grid);
|
||||
DmuAmu(A,dmuAmu);
|
||||
ciadmam = dmuAmu*cialpha;
|
||||
SU<Nc>::taExp(ciadmam,g);
|
||||
}
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////
|
||||
// NB The FT for fields living on links has an extra phase in it
|
||||
// Could add these to the FFT class as a later task since this code
|
||||
// might be reused elsewhere ????
|
||||
////////////////////////////////////////////////////////////////
|
||||
static void InverseFourierTransformAmu(FFT &theFFT,const std::vector<GaugeMat> &Ap,std::vector<GaugeMat> &Ax) {
|
||||
GridBase * grid = theFFT.Grid();
|
||||
std::vector<int> latt_size = grid->GlobalDimensions();
|
||||
|
||||
ComplexField pmu(grid);
|
||||
ComplexField pha(grid);
|
||||
GaugeMat Apha(grid);
|
||||
|
||||
Complex ci(0.0,1.0);
|
||||
|
||||
for(int mu=0;mu<Nd;mu++){
|
||||
|
||||
Real TwoPiL = M_PI * 2.0/ latt_size[mu];
|
||||
LatticeCoordinate(pmu,mu);
|
||||
pmu = TwoPiL * pmu ;
|
||||
pha = exp(pmu * (0.5 *ci)); // e(ipmu/2) since Amu(x+mu/2)
|
||||
|
||||
Apha = Ap[mu] * pha;
|
||||
|
||||
theFFT.FFT_all_dim(Apha,Ax[mu],FFT::backward);
|
||||
}
|
||||
}
|
||||
static void FourierTransformAmu(FFT & theFFT,const std::vector<GaugeMat> &Ax,std::vector<GaugeMat> &Ap) {
|
||||
GridBase * grid = theFFT.Grid();
|
||||
std::vector<int> latt_size = grid->GlobalDimensions();
|
||||
|
||||
ComplexField pmu(grid);
|
||||
ComplexField pha(grid);
|
||||
Complex ci(0.0,1.0);
|
||||
|
||||
// Sign convention for FFTW calls:
|
||||
// A(x)= Sum_p e^ipx A(p) / V
|
||||
// A(p)= Sum_p e^-ipx A(x)
|
||||
|
||||
for(int mu=0;mu<Nd;mu++){
|
||||
Real TwoPiL = M_PI * 2.0/ latt_size[mu];
|
||||
LatticeCoordinate(pmu,mu);
|
||||
pmu = TwoPiL * pmu ;
|
||||
pha = exp(-pmu * (0.5 *ci)); // e(+ipmu/2) since Amu(x+mu/2)
|
||||
|
||||
theFFT.FFT_all_dim(Ax[mu],Ap[mu],FFT::backward);
|
||||
Ap[mu] = Ap[mu] * pha;
|
||||
}
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
int main (int argc, char ** argv)
|
||||
{
|
||||
std::vector<int> seeds({1,2,3,4});
|
||||
@ -264,22 +58,24 @@ int main (int argc, char ** argv)
|
||||
std::cout<< "*****************************************************************" <<std::endl;
|
||||
|
||||
LatticeGaugeField Umu(&GRID);
|
||||
LatticeGaugeField Urnd(&GRID);
|
||||
LatticeGaugeField Uorg(&GRID);
|
||||
LatticeColourMatrix g(&GRID); // Gauge xform
|
||||
|
||||
|
||||
SU3::ColdConfiguration(pRNG,Umu); // Unit gauge
|
||||
Uorg=Umu;
|
||||
Urnd=Umu;
|
||||
|
||||
SU3::RandomGaugeTransform(pRNG,Urnd,g); // Unit gauge
|
||||
|
||||
SU3::RandomGaugeTransform(pRNG,Umu,g); // Unit gauge
|
||||
Real plaq=WilsonLoops<PeriodicGimplR>::avgPlaquette(Umu);
|
||||
std::cout << " Initial plaquette "<<plaq << std::endl;
|
||||
|
||||
|
||||
|
||||
Real alpha=0.1;
|
||||
FourierAcceleratedGaugeFixer<PeriodicGimplR>::SteepestDescentGaugeFix(Umu,alpha,10000,1.0e-10, 1.0e-10);
|
||||
|
||||
Umu = Urnd;
|
||||
FourierAcceleratedGaugeFixer<PeriodicGimplR>::SteepestDescentGaugeFix(Umu,alpha,10000,1.0e-12, 1.0e-12,false);
|
||||
|
||||
plaq=WilsonLoops<PeriodicGimplR>::avgPlaquette(Umu);
|
||||
std::cout << " Final plaquette "<<plaq << std::endl;
|
||||
@ -288,14 +84,28 @@ int main (int argc, char ** argv)
|
||||
std::cout << " Norm Difference "<< norm2(Uorg) << std::endl;
|
||||
|
||||
|
||||
// std::cout<< "*****************************************************************" <<std::endl;
|
||||
// std::cout<< "* Testing Fourier accelerated fixing *" <<std::endl;
|
||||
// std::cout<< "*****************************************************************" <<std::endl;
|
||||
std::cout<< "*****************************************************************" <<std::endl;
|
||||
std::cout<< "* Testing Fourier accelerated fixing *" <<std::endl;
|
||||
std::cout<< "*****************************************************************" <<std::endl;
|
||||
Umu=Urnd;
|
||||
FourierAcceleratedGaugeFixer<PeriodicGimplR>::SteepestDescentGaugeFix(Umu,alpha,10000,1.0e-12, 1.0e-12,true);
|
||||
|
||||
// std::cout<< "*****************************************************************" <<std::endl;
|
||||
// std::cout<< "* Testing non-unit configuration *" <<std::endl;
|
||||
// std::cout<< "*****************************************************************" <<std::endl;
|
||||
plaq=WilsonLoops<PeriodicGimplR>::avgPlaquette(Umu);
|
||||
std::cout << " Final plaquette "<<plaq << std::endl;
|
||||
|
||||
std::cout<< "*****************************************************************" <<std::endl;
|
||||
std::cout<< "* Testing non-unit configuration *" <<std::endl;
|
||||
std::cout<< "*****************************************************************" <<std::endl;
|
||||
|
||||
SU3::HotConfiguration(pRNG,Umu); // Unit gauge
|
||||
|
||||
plaq=WilsonLoops<PeriodicGimplR>::avgPlaquette(Umu);
|
||||
std::cout << " Initial plaquette "<<plaq << std::endl;
|
||||
|
||||
FourierAcceleratedGaugeFixer<PeriodicGimplR>::SteepestDescentGaugeFix(Umu,alpha,10000,1.0e-12, 1.0e-12,true);
|
||||
|
||||
plaq=WilsonLoops<PeriodicGimplR>::avgPlaquette(Umu);
|
||||
std::cout << " Final plaquette "<<plaq << std::endl;
|
||||
|
||||
|
||||
Grid_finalize();
|
||||
|
@ -336,7 +336,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
std::cout << GridLogMessage << "norm cMmat : " << norm2(cMat)
|
||||
<< std::endl;
|
||||
cMat = expMat(cMat, ComplexD(1.0, 0.0));
|
||||
cMat = expMat(cMat,1.0);// ComplexD(1.0, 0.0));
|
||||
std::cout << GridLogMessage << "norm expMat: " << norm2(cMat)
|
||||
<< std::endl;
|
||||
peekSite(cm, cMat, mysite);
|
||||
|
@ -67,7 +67,7 @@ int main (int argc, char ** argv)
|
||||
LatticeFermion err(FGrid);
|
||||
LatticeGaugeField Umu(UGrid);
|
||||
|
||||
NerscField header;
|
||||
FieldMetaData header;
|
||||
std::string file("./ckpoint_lat.400");
|
||||
NerscIO::readConfiguration(Umu,header,file);
|
||||
|
||||
|
@ -133,8 +133,8 @@ int main (int argc, char ** argv)
|
||||
int Nconv;
|
||||
RealD eresid = 1.0e-6;
|
||||
|
||||
ImplicitlyRestartedLanczos<LatticeComplex> IRL(HermOp,X,Nk,Nm,eresid,Nit);
|
||||
ImplicitlyRestartedLanczos<LatticeComplex> ChebyIRL(HermOp,Cheby,Nk,Nm,eresid,Nit);
|
||||
ImplicitlyRestartedLanczos<LatticeComplex> IRL(HermOp,X,Nk,Nk,Nm,eresid,Nit);
|
||||
ImplicitlyRestartedLanczos<LatticeComplex> ChebyIRL(HermOp,Cheby,Nk,Nk,Nm,eresid,Nit);
|
||||
|
||||
LatticeComplex src(grid); gaussian(RNG,src);
|
||||
{
|
||||
|
@ -61,6 +61,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
// gauge field
|
||||
application.createModule<MGauge::Unit>("gauge");
|
||||
|
||||
// set fermion boundary conditions to be periodic space, antiperiodic time.
|
||||
std::string boundary = "1 1 1 -1";
|
||||
|
||||
for (unsigned int i = 0; i < flavour.size(); ++i)
|
||||
{
|
||||
// actions
|
||||
@ -69,6 +73,7 @@ int main(int argc, char *argv[])
|
||||
actionPar.Ls = 12;
|
||||
actionPar.M5 = 1.8;
|
||||
actionPar.mass = mass[i];
|
||||
actionPar.boundary = boundary;
|
||||
application.createModule<MAction::DWF>("DWF_" + flavour[i], actionPar);
|
||||
|
||||
// solvers
|
||||
|
@ -98,6 +98,10 @@ int main(int argc, char *argv[])
|
||||
gaugePar.file = configStem;
|
||||
application.createModule<MGauge::Load>("gauge", gaugePar);
|
||||
}
|
||||
|
||||
// set fermion boundary conditions to be periodic space, antiperiodic time.
|
||||
std::string boundary = "1 1 1 -1";
|
||||
|
||||
for (unsigned int i = 0; i < flavour.size(); ++i)
|
||||
{
|
||||
// actions
|
||||
@ -106,6 +110,7 @@ int main(int argc, char *argv[])
|
||||
actionPar.Ls = 16;
|
||||
actionPar.M5 = 1.8;
|
||||
actionPar.mass = mass[i];
|
||||
actionPar.boundary = boundary;
|
||||
application.createModule<MAction::DWF>("DWF_" + flavour[i], actionPar);
|
||||
|
||||
// solvers
|
||||
|
@ -63,6 +63,10 @@ int main(int argc, char *argv[])
|
||||
MSource::Point::Par ptPar;
|
||||
ptPar.position = "0 0 0 0";
|
||||
application.createModule<MSource::Point>("pt", ptPar);
|
||||
|
||||
// set fermion boundary conditions to be periodic space, antiperiodic time.
|
||||
std::string boundary = "1 1 1 -1";
|
||||
|
||||
for (unsigned int i = 0; i < flavour.size(); ++i)
|
||||
{
|
||||
// actions
|
||||
@ -71,6 +75,7 @@ int main(int argc, char *argv[])
|
||||
actionPar.Ls = 12;
|
||||
actionPar.M5 = 1.8;
|
||||
actionPar.mass = mass[i];
|
||||
actionPar.boundary = boundary;
|
||||
application.createModule<MAction::DWF>("DWF_" + flavour[i], actionPar);
|
||||
|
||||
// solvers
|
||||
|
@ -28,6 +28,38 @@ directory
|
||||
/* END LEGAL */
|
||||
#include <Grid/Grid.h>
|
||||
|
||||
namespace Grid{
|
||||
struct WFParameters: Serializable {
|
||||
GRID_SERIALIZABLE_CLASS_MEMBERS(WFParameters,
|
||||
int, steps,
|
||||
double, step_size,
|
||||
int, meas_interval,
|
||||
double, maxTau); // for the adaptive algorithm
|
||||
|
||||
|
||||
template <class ReaderClass >
|
||||
WFParameters(Reader<ReaderClass>& Reader){
|
||||
read(Reader, "WilsonFlow", *this);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct ConfParameters: Serializable {
|
||||
GRID_SERIALIZABLE_CLASS_MEMBERS(ConfParameters,
|
||||
std::string, conf_prefix,
|
||||
std::string, rng_prefix,
|
||||
int, StartConfiguration,
|
||||
int, EndConfiguration,
|
||||
int, Skip);
|
||||
|
||||
template <class ReaderClass >
|
||||
ConfParameters(Reader<ReaderClass>& Reader){
|
||||
read(Reader, "Configurations", *this);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
using namespace Grid;
|
||||
using namespace Grid::QCD;
|
||||
@ -42,22 +74,38 @@ int main(int argc, char **argv) {
|
||||
GridRedBlackCartesian RBGrid(latt_size, simd_layout, mpi_layout);
|
||||
|
||||
std::vector<int> seeds({1, 2, 3, 4, 5});
|
||||
GridSerialRNG sRNG;
|
||||
GridParallelRNG pRNG(&Grid);
|
||||
pRNG.SeedFixedIntegers(seeds);
|
||||
|
||||
LatticeGaugeField Umu(&Grid), Uflow(&Grid);
|
||||
SU<Nc>::HotConfiguration(pRNG, Umu);
|
||||
|
||||
typedef Grid::JSONReader Serialiser;
|
||||
Serialiser Reader("input.json");
|
||||
WFParameters WFPar(Reader);
|
||||
ConfParameters CPar(Reader);
|
||||
CheckpointerParameters CPPar(CPar.conf_prefix, CPar.rng_prefix);
|
||||
BinaryHmcCheckpointer<PeriodicGimplR> CPBin(CPPar);
|
||||
|
||||
for (int conf = CPar.StartConfiguration; conf <= CPar.EndConfiguration; conf+= CPar.Skip){
|
||||
|
||||
CPBin.CheckpointRestore(conf, Umu, sRNG, pRNG);
|
||||
|
||||
std::cout << std::setprecision(15);
|
||||
std::cout << GridLogMessage << "Plaquette: "
|
||||
std::cout << GridLogMessage << "Initial plaquette: "
|
||||
<< WilsonLoops<PeriodicGimplR>::avgPlaquette(Umu) << std::endl;
|
||||
|
||||
WilsonFlow<PeriodicGimplR> WF(200, 0.01);
|
||||
WilsonFlow<PeriodicGimplR> WF(WFPar.steps, WFPar.step_size, WFPar.meas_interval);
|
||||
|
||||
WF.smear(Uflow, Umu);
|
||||
WF.smear_adaptive(Uflow, Umu, WFPar.maxTau);
|
||||
|
||||
RealD WFlow_plaq = WilsonLoops<PeriodicGimplR>::avgPlaquette(Uflow);
|
||||
std::cout << GridLogMessage << "Plaquette: "<< WFlow_plaq << std::endl;
|
||||
RealD WFlow_TC = WilsonLoops<PeriodicGimplR>::TopologicalCharge(Uflow);
|
||||
RealD WFlow_T0 = WF.energyDensityPlaquette(Uflow);
|
||||
std::cout << GridLogMessage << "Plaquette "<< conf << " " << WFlow_plaq << std::endl;
|
||||
std::cout << GridLogMessage << "T0 "<< conf << " " << WFlow_T0 << std::endl;
|
||||
std::cout << GridLogMessage << "TopologicalCharge "<< conf << " " << WFlow_TC << std::endl;
|
||||
|
||||
std::cout<< GridLogMessage << " Admissibility check:\n";
|
||||
const double sp_adm = 0.067; // admissible threshold
|
||||
@ -73,6 +121,32 @@ int main(int argc, char **argv) {
|
||||
std::cout<< GridLogMessage << " (sp_admissible = "<< sp_adm <<")\n";
|
||||
//std::cout<< GridLogMessage << " sp_admissible - sp_max = "<<sp_adm-sp_max <<"\n";
|
||||
std::cout<< GridLogMessage << " sp_admissible - sp_ave = "<<sp_adm-sp_ave <<"\n";
|
||||
|
||||
}
|
||||
Grid_finalize();
|
||||
} // main
|
||||
|
||||
|
||||
/*
|
||||
Input file example
|
||||
|
||||
|
||||
JSON
|
||||
|
||||
{
|
||||
"WilsonFlow":{
|
||||
"steps": 200,
|
||||
"step_size": 0.01,
|
||||
"meas_interval": 50,
|
||||
"maxTau": 2.0
|
||||
},
|
||||
"Configurations":{
|
||||
"conf_prefix": "ckpoint_lat",
|
||||
"rng_prefix": "ckpoint_rng",
|
||||
"StartConfiguration": 3000,
|
||||
"EndConfiguration": 3000,
|
||||
"Skip": 5
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*/
|
@ -516,7 +516,7 @@ int main (int argc, char ** argv)
|
||||
LatticeColourMatrix U(UGrid);
|
||||
LatticeColourMatrix zz(UGrid);
|
||||
|
||||
NerscField header;
|
||||
FieldMetaData header;
|
||||
std::string file("./ckpoint_lat.4000");
|
||||
NerscIO::readConfiguration(Umu,header,file);
|
||||
|
||||
|
@ -54,7 +54,7 @@ int main (int argc, char ** argv)
|
||||
GridParallelRNG RNG5rb(FrbGrid); RNG5.SeedFixedIntegers(seeds5);
|
||||
|
||||
LatticeGaugeField Umu(UGrid);
|
||||
SU3::TepidConfiguration(RNG4, Umu);
|
||||
SU3::HotConfiguration(RNG4, Umu);
|
||||
|
||||
std::vector<LatticeColourMatrix> U(4,UGrid);
|
||||
for(int mu=0;mu<Nd;mu++){
|
||||
@ -92,16 +92,15 @@ int main (int argc, char ** argv)
|
||||
|
||||
|
||||
std::vector<RealD> eval(Nm);
|
||||
FermionField src(FrbGrid); gaussian(RNG5rb,src);
|
||||
FermionField src(FrbGrid);
|
||||
gaussian(RNG5rb,src);
|
||||
std::vector<FermionField> evec(Nm,FrbGrid);
|
||||
for(int i=0;i<1;i++){
|
||||
std::cout << i<<" / "<< Nm<< " grid pointer "<<evec[i]._grid<<std::endl;
|
||||
std::cout << GridLogMessage <<i<<" / "<< Nm<< " grid pointer "<<evec[i]._grid<<std::endl;
|
||||
};
|
||||
|
||||
int Nconv;
|
||||
IRL.calc(eval,evec,
|
||||
src,
|
||||
Nconv);
|
||||
IRL.calc(eval,evec,src,Nconv);
|
||||
|
||||
|
||||
Grid_finalize();
|
||||
|
@ -51,7 +51,7 @@ int main (int argc, char ** argv)
|
||||
typedef typename ImprovedStaggeredFermion5DR::ComplexField ComplexField;
|
||||
typename ImprovedStaggeredFermion5DR::ImplParams params;
|
||||
|
||||
const int Ls=4;
|
||||
const int Ls=8;
|
||||
|
||||
Grid_init(&argc,&argv);
|
||||
|
||||
@ -74,17 +74,19 @@ int main (int argc, char ** argv)
|
||||
|
||||
LatticeGaugeField Umu(UGrid); SU3::HotConfiguration(pRNG,Umu);
|
||||
|
||||
RealD mass=0.01;
|
||||
RealD mass=0.003;
|
||||
ImprovedStaggeredFermion5DR Ds(Umu,Umu,*FGrid,*FrbGrid,*UGrid,*UrbGrid,mass);
|
||||
MdagMLinearOperator<ImprovedStaggeredFermion5DR,FermionField> HermOp(Ds);
|
||||
|
||||
ConjugateGradient<FermionField> CG(1.0e-8,10000);
|
||||
BlockConjugateGradient<FermionField> BCG(1.0e-8,10000);
|
||||
MultiRHSConjugateGradient<FermionField> mCG(1.0e-8,10000);
|
||||
int blockDim = 0;
|
||||
BlockConjugateGradient<FermionField> BCGrQ(BlockCGrQ,blockDim,1.0e-8,10000);
|
||||
BlockConjugateGradient<FermionField> BCG (BlockCG,blockDim,1.0e-8,10000);
|
||||
BlockConjugateGradient<FermionField> mCG (CGmultiRHS,blockDim,1.0e-8,10000);
|
||||
|
||||
std::cout << GridLogMessage << "************************************************************************ "<<std::endl;
|
||||
std::cout << GridLogMessage << "****************************************************************** "<<std::endl;
|
||||
std::cout << GridLogMessage << " Calling 4d CG "<<std::endl;
|
||||
std::cout << GridLogMessage << "************************************************************************ "<<std::endl;
|
||||
std::cout << GridLogMessage << "****************************************************************** "<<std::endl;
|
||||
ImprovedStaggeredFermionR Ds4d(Umu,Umu,*UGrid,*UrbGrid,mass);
|
||||
MdagMLinearOperator<ImprovedStaggeredFermionR,FermionField> HermOp4d(Ds4d);
|
||||
FermionField src4d(UGrid); random(pRNG,src4d);
|
||||
@ -111,7 +113,7 @@ int main (int argc, char ** argv)
|
||||
std::cout << GridLogMessage << " Calling Block CG for "<<Ls <<" right hand sides" <<std::endl;
|
||||
std::cout << GridLogMessage << "************************************************************************ "<<std::endl;
|
||||
result=zero;
|
||||
BCG(HermOp,src,result);
|
||||
BCGrQ(HermOp,src,result);
|
||||
std::cout << GridLogMessage << "************************************************************************ "<<std::endl;
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user