mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-10-25 10:09:34 +01:00 
			
		
		
		
	Compare commits
	
		
			49 Commits
		
	
	
		
			e5bc679fef
			...
			FgridStagg
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 4ac85b3e8f | ||
|  | dd8cd8a8e8 | ||
|  | 0cccb3dc82 | ||
|  | 5d44346be3 | ||
|  | 3a754fcd51 | ||
|  | 137886c316 | ||
|  | ef61b549e6 | ||
|  | 3006663b9c | ||
|  | 0145685f96 | ||
|  | e73e4b4002 | ||
|  | caa6605b43 | ||
|  | 522c9248ae | ||
|  | 191fbf85fc | ||
|  | 93650f3a61 | ||
|  | cab4b4d063 | ||
|  | cf4b30b2dd | ||
|  | c51d0b4078 | ||
|  | 2f4cbeb4d5 | ||
|  | fb7c4fb815 | ||
|  | 00bb71e5af | ||
|  | cfed2c1ea0 | ||
|  | b1b15f0b70 | ||
|  | 927c7ae3ed | ||
|  | 05d04ceff8 | ||
|  | 8313367a50 | ||
|  | 5c479ce663 | ||
|  | 4bf9d65bf8 | ||
|  | 3a056c4dff | ||
|  | b0ba651654 | ||
|  | 25d4c175c3 | ||
|  | a8d7986e1c | ||
|  | 92ec509bfa | ||
|  | e80a87ff7f | ||
|  | 867fe93018 | ||
|  | 09651c3326 | ||
|  | f87f2a3f8b | ||
|  | a07556dd5f | ||
|  | f80a847aef | ||
|  | 93cb5d4e97 | ||
|  | 9e48b7dfda | ||
|  | d0c2c9c71f | ||
|  | c8cafa77ca | ||
|  | a3bcad3804 | ||
|  | 5a5b66292b | ||
|  | e63be32ad2 | ||
|  | 6aa106d906 | ||
|  | 33d59c8869 | ||
|  | a833fd8dbf | ||
|  | e9712bc7fb | 
| @@ -5,7 +5,7 @@ EIGEN_URL='http://bitbucket.org/eigen/eigen/get/3.3.3.tar.bz2' | ||||
| echo "-- deploying Eigen source..." | ||||
| wget ${EIGEN_URL} --no-check-certificate | ||||
| ./scripts/update_eigen.sh `basename ${EIGEN_URL}` | ||||
| rm `basename ${EIGEN_URL}` | ||||
| #rm `basename ${EIGEN_URL}` | ||||
|  | ||||
| echo '-- generating Make.inc files...' | ||||
| ./scripts/filelist | ||||
|   | ||||
| @@ -39,6 +39,10 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| #include <Grid/algorithms/approx/MultiShiftFunction.h> | ||||
| #include <Grid/algorithms/approx/Forecast.h> | ||||
|  | ||||
| #include <Grid/algorithms/densematrix/DenseMatrix.h> | ||||
| #include <Grid/algorithms/densematrix/Francis.h> | ||||
| #include <Grid/algorithms/densematrix/Householder.h> | ||||
|  | ||||
| #include <Grid/algorithms/iterative/ConjugateGradient.h> | ||||
| #include <Grid/algorithms/iterative/ConjugateResidual.h> | ||||
| #include <Grid/algorithms/iterative/NormalEquations.h> | ||||
| @@ -48,6 +52,8 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| #include <Grid/algorithms/iterative/BlockConjugateGradient.h> | ||||
| #include <Grid/algorithms/iterative/ConjugateGradientReliableUpdate.h> | ||||
| #include <Grid/algorithms/iterative/ImplicitlyRestartedLanczos.h> | ||||
| #include <Grid/algorithms/iterative/ImplicitlyRestartedLanczosCJ.h> | ||||
| #include <Grid/algorithms/iterative/SimpleLanczos.h> | ||||
| #include <Grid/algorithms/CoarsenedMatrix.h> | ||||
| #include <Grid/algorithms/FFT.h> | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
|  | ||||
| Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk> | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Chulwoo Jung <chulwoo@bnl.gov> | ||||
|  | ||||
|     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 | ||||
| @@ -330,7 +331,130 @@ namespace Grid { | ||||
| 	assert(0);// Never need with staggered | ||||
|       } | ||||
|     }; | ||||
|     template<class Matrix,class Field> using SchurStagOperator = SchurStaggeredOperator<Matrix,Field>; | ||||
| //    template<class Matrix,class Field> using SchurStagOperator = SchurStaggeredOperator<Matrix,Field>; | ||||
|     template<class Matrix,class Field> | ||||
| //      class SchurStagOperator :  public LinearOperatorBase<Field> { | ||||
|       class SchurStagOperator :  public SchurOperatorBase<Field> { | ||||
|     protected: | ||||
|       Matrix &_Mat; | ||||
|     public: | ||||
|       SchurStagOperator (Matrix &Mat): _Mat(Mat){}; | ||||
|       virtual  RealD Mpc      (const Field &in, Field &out) { | ||||
| 	Field tmp(in._grid); | ||||
| 	Field tmp2(in._grid); | ||||
|  | ||||
| 	_Mat.Mooee(in,out); | ||||
| 	_Mat.Mooee(out,tmp); | ||||
|  | ||||
| 	_Mat.Meooe(in,out); | ||||
| 	_Mat.Meooe(out,tmp2); | ||||
|  | ||||
| 	return axpy_norm(out,-1.0,tmp2,tmp); | ||||
|       } | ||||
|       virtual  RealD MpcDag   (const Field &in, Field &out){ | ||||
|  | ||||
| 	return Mpc(in,out); | ||||
|       } | ||||
| #if 0 | ||||
|       virtual void MpcDagMpc(const Field &in, Field &out,RealD &ni,RealD &no) { | ||||
| 	Field tmp(in._grid); | ||||
| 	ni=Mpc(in,tmp); | ||||
| 	no=MpcDag(tmp,out); | ||||
|       } | ||||
| #endif | ||||
|       void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){ | ||||
| 	n2 = Mpc(in,out); | ||||
| 	ComplexD dot = innerProduct(in,out); | ||||
| 	n1 = real(dot); | ||||
|       } | ||||
|       void HermOp(const Field &in, Field &out){ | ||||
| 	RealD n1,n2; | ||||
| 	HermOpAndNorm(in,out,n1,n2); | ||||
|       } | ||||
|       void Op     (const Field &in, Field &out){ | ||||
| 	Mpc(in,out); | ||||
|       } | ||||
|       void AdjOp     (const Field &in, Field &out){  | ||||
| 	MpcDag(in,out); | ||||
|       } | ||||
|       // Support for coarsening to a multigrid | ||||
|       void OpDiag (const Field &in, Field &out) { | ||||
| 	assert(0); // must coarsen the unpreconditioned system | ||||
|       } | ||||
|       void OpDir  (const Field &in, Field &out,int dir,int disp) { | ||||
| 	assert(0); | ||||
|       } | ||||
|  | ||||
|     }; | ||||
|  | ||||
| #if 0 | ||||
|   // This is specific to (Z)mobius fermions | ||||
|   template<class Matrix, class Field> | ||||
|     class KappaSimilarityTransform { | ||||
|   public: | ||||
| //    INHERIT_IMPL_TYPES(Matrix); | ||||
|     typedef typename Matrix::Coeff_t                     Coeff_t; | ||||
|     std::vector<Coeff_t> kappa, kappaDag, kappaInv, kappaInvDag; | ||||
|  | ||||
|     KappaSimilarityTransform (Matrix &zmob) { | ||||
|       for (int i=0;i<(int)zmob.bs.size();i++) { | ||||
| 	Coeff_t k = 1.0 / ( 2.0 * (zmob.bs[i] *(4 - zmob.M5) + 1.0) ); | ||||
| 	kappa.push_back( k ); | ||||
| 	kappaDag.push_back( conj(k) ); | ||||
| 	kappaInv.push_back( 1.0 / k ); | ||||
| 	kappaInvDag.push_back( 1.0 / conj(k) ); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   template<typename vobj> | ||||
|     void sscale(const Lattice<vobj>& in, Lattice<vobj>& out, Coeff_t* s) { | ||||
|     GridBase *grid=out._grid; | ||||
|     out.checkerboard = in.checkerboard; | ||||
|     assert(grid->_simd_layout[0] == 1); // should be fine for ZMobius for now | ||||
|     int Ls = grid->_rdimensions[0]; | ||||
|     parallel_for(int ss=0;ss<grid->oSites();ss++){ | ||||
|       vobj tmp = s[ss % Ls]*in._odata[ss]; | ||||
|       vstream(out._odata[ss],tmp); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   RealD sscale_norm(const Field& in, Field& out, Coeff_t* s) { | ||||
|     sscale(in,out,s); | ||||
|     return norm2(out); | ||||
|   } | ||||
|  | ||||
|   virtual RealD M       (const Field& in, Field& out) { return sscale_norm(in,out,&kappa[0]);   } | ||||
|   virtual RealD MDag    (const Field& in, Field& out) { return sscale_norm(in,out,&kappaDag[0]);} | ||||
|   virtual RealD MInv    (const Field& in, Field& out) { return sscale_norm(in,out,&kappaInv[0]);} | ||||
|   virtual RealD MInvDag (const Field& in, Field& out) { return sscale_norm(in,out,&kappaInvDag[0]);} | ||||
|  | ||||
|   }; | ||||
|  | ||||
|   template<class Matrix,class Field> | ||||
|     class SchurDiagTwoKappaOperator :  public SchurOperatorBase<Field> { | ||||
|   public: | ||||
|     KappaSimilarityTransform<Matrix, Field> _S; | ||||
|     SchurDiagTwoOperator<Matrix, Field> _Mat; | ||||
|  | ||||
|     SchurDiagTwoKappaOperator (Matrix &Mat): _S(Mat), _Mat(Mat) {}; | ||||
|  | ||||
|     virtual  RealD Mpc      (const Field &in, Field &out) { | ||||
|       Field tmp(in._grid); | ||||
|  | ||||
|       _S.MInv(in,out); | ||||
|       _Mat.Mpc(out,tmp); | ||||
|       return _S.M(tmp,out); | ||||
|  | ||||
|     } | ||||
|     virtual  RealD MpcDag   (const Field &in, Field &out){ | ||||
|       Field tmp(in._grid); | ||||
|  | ||||
|       _S.MDag(in,out); | ||||
|       _Mat.MpcDag(out,tmp); | ||||
|       return _S.MInvDag(tmp,out); | ||||
|     } | ||||
|   }; | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     ///////////////////////////////////////////////////////////// | ||||
|   | ||||
							
								
								
									
										137
									
								
								lib/algorithms/densematrix/DenseMatrix.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								lib/algorithms/densematrix/DenseMatrix.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     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 | ||||
|  | ||||
							
								
								
									
										525
									
								
								lib/algorithms/densematrix/Francis.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										525
									
								
								lib/algorithms/densematrix/Francis.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,525 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     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 | ||||
							
								
								
									
										242
									
								
								lib/algorithms/densematrix/Householder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								lib/algorithms/densematrix/Householder.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,242 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     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 | ||||
| @@ -60,6 +60,7 @@ namespace Grid { | ||||
|     } | ||||
|    | ||||
|     void operator() (const FieldD &src_d_in, FieldD &sol_d){ | ||||
|  | ||||
|       TotalInnerIterations = 0; | ||||
| 	 | ||||
|       GridStopWatch TotalTimer; | ||||
|   | ||||
							
								
								
									
										1222
									
								
								lib/algorithms/iterative/ImplicitlyRestartedLanczosCJ.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1222
									
								
								lib/algorithms/iterative/ImplicitlyRestartedLanczosCJ.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -7,6 +7,7 @@ | ||||
|     Copyright (C) 2015 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Chulwoo Jung <chulwoo@bnl.gov> | ||||
|  | ||||
|     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 | ||||
| @@ -164,7 +165,82 @@ namespace Grid { | ||||
|       std::cout<<GridLogMessage << "SchurRedBlackStaggered solver true unprec resid "<< std::sqrt(nr/ns) <<" nr "<< nr <<" ns "<<ns << std::endl; | ||||
|     }      | ||||
|   }; | ||||
|   template<class Field> using SchurRedBlackStagSolve = SchurRedBlackStaggeredSolve<Field>; | ||||
| //  template<class Field> using SchurRedBlackStagSolve = SchurRedBlackStaggeredSolve<Field>; | ||||
|   template<class Field> class SchurRedBlackStagSolve { | ||||
|   private: | ||||
|     OperatorFunction<Field> & _HermitianRBSolver; | ||||
|     int CBfactorise; | ||||
|   public: | ||||
|  | ||||
|     ///////////////////////////////////////////////////// | ||||
|     // Wrap the usual normal equations Schur trick | ||||
|     ///////////////////////////////////////////////////// | ||||
|   SchurRedBlackStagSolve(OperatorFunction<Field> &HermitianRBSolver, int cb)  : | ||||
|      _HermitianRBSolver(HermitianRBSolver), CBfactorise(cb) {} | ||||
|  | ||||
|     template<class Matrix> | ||||
|       void operator() (Matrix & _Matrix,const Field &in, Field &out){ | ||||
|  | ||||
|       // FIXME CGdiagonalMee not implemented virtual function | ||||
|       // FIXME use CBfactorise to control schur decomp | ||||
|       GridBase *grid = _Matrix.RedBlackGrid(); | ||||
|       GridBase *fgrid= _Matrix.Grid(); | ||||
|  | ||||
|       SchurStagOperator<Matrix,Field> _HermOpEO(_Matrix); | ||||
|       int Schur = CBfactorise; | ||||
|       int Other = 1 - CBfactorise; | ||||
|   | ||||
|       Field src_e(grid); | ||||
|       Field src_o(grid); | ||||
|       Field sol_e(grid); | ||||
|       Field sol_o(grid); | ||||
|       Field   tmp(grid); | ||||
|       Field  Mtmp(grid); | ||||
|       Field resid(fgrid); | ||||
|  | ||||
|       pickCheckerboard(Other,src_e,in); | ||||
|       pickCheckerboard(Schur ,src_o,in); | ||||
|       pickCheckerboard(Other,sol_e,out); | ||||
|       pickCheckerboard(Schur ,sol_o,out); | ||||
|      | ||||
|       ///////////////////////////////////////////////////// | ||||
|       // src_o = Mdag * (source_o - Moe MeeInv source_e) | ||||
|       ///////////////////////////////////////////////////// | ||||
|       _Matrix.MooeeInv(src_e,tmp);     assert(  tmp.checkerboard ==Other); | ||||
|       _Matrix.Meooe   (tmp,Mtmp);      assert( Mtmp.checkerboard ==Schur);      | ||||
|       tmp=src_o-Mtmp;                  assert(  tmp.checkerboard ==Schur);      | ||||
|  | ||||
| #if 0 | ||||
|       // get the right MpcDag | ||||
| //      _HermOpEO.MpcDag(tmp,src_o);     assert(src_o.checkerboard ==Schur);        | ||||
| #else | ||||
|       _Matrix.Mooee(tmp,src_o);     assert(src_o.checkerboard ==Schur); | ||||
| #endif | ||||
|       ////////////////////////////////////////////////////////////// | ||||
|       // Call the red-black solver | ||||
|       ////////////////////////////////////////////////////////////// | ||||
|       std::cout<<GridLogMessage << "SchurRedBlack solver calling the MpcDagMp solver" <<std::endl; | ||||
|       _HermitianRBSolver(_HermOpEO,src_o,sol_o);  assert(sol_o.checkerboard==Schur); | ||||
|  | ||||
|       /////////////////////////////////////////////////// | ||||
|       // sol_e = M_ee^-1 * ( src_e - Meo sol_o )... | ||||
|       /////////////////////////////////////////////////// | ||||
|       _Matrix.Meooe(sol_o,tmp);        assert(  tmp.checkerboard   ==Other); | ||||
|       src_e = src_e-tmp;               assert(  src_e.checkerboard ==Other); | ||||
|       _Matrix.MooeeInv(src_e,sol_e);   assert(  sol_e.checkerboard ==Other); | ||||
|       | ||||
|       setCheckerboard(out,sol_e); assert(  sol_e.checkerboard ==Other); | ||||
|       setCheckerboard(out,sol_o); assert(  sol_o.checkerboard ==Schur ); | ||||
|  | ||||
|       // Verify the unprec residual | ||||
|       _Matrix.M(out,resid);  | ||||
|       resid = resid-in; | ||||
|       RealD ns = norm2(in); | ||||
|       RealD nr = norm2(resid); | ||||
|  | ||||
|       std::cout<<GridLogMessage << "SchurRedBlackStag solver true unprec resid "<< std::sqrt(nr/ns) <<" nr "<< nr <<" ns "<<ns << std::endl; | ||||
|     }      | ||||
|   }; | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // Take a matrix and form a Red Black solver calling a Herm solver | ||||
| @@ -403,5 +479,77 @@ namespace Grid { | ||||
|     }      | ||||
|   }; | ||||
|  | ||||
|   template<class Field> class SchurRedBlackStagMixed { | ||||
|   private: | ||||
|     LinearFunction<Field> & _HermitianRBSolver; | ||||
|     int CBfactorise; | ||||
|   public: | ||||
|  | ||||
|     ///////////////////////////////////////////////////// | ||||
|     // Wrap the usual normal equations Schur trick | ||||
|     ///////////////////////////////////////////////////// | ||||
|   SchurRedBlackStagMixed(LinearFunction<Field> &HermitianRBSolver, int cb)  : | ||||
|      _HermitianRBSolver(HermitianRBSolver), CBfactorise(cb) {} | ||||
|  | ||||
|     template<class Matrix> | ||||
|       void operator() (Matrix & _Matrix,const Field &in, Field &out){ | ||||
|  | ||||
|       // FIXME CGdiagonalMee not implemented virtual function | ||||
|       // FIXME use CBfactorise to control schur decomp | ||||
|       GridBase *grid = _Matrix.RedBlackGrid(); | ||||
|       GridBase *fgrid= _Matrix.Grid(); | ||||
|  | ||||
|       SchurStagOperator<Matrix,Field> _HermOpEO(_Matrix); | ||||
|       int Schur = CBfactorise; | ||||
|       int Other = 1 - CBfactorise; | ||||
|   | ||||
|       Field src_e(grid); | ||||
|       Field src_o(grid); | ||||
|       Field sol_e(grid); | ||||
|       Field sol_o(grid); | ||||
|       Field   tmp(grid); | ||||
|       Field  Mtmp(grid); | ||||
|       Field resid(fgrid); | ||||
|  | ||||
|       pickCheckerboard(Other,src_e,in); | ||||
|       pickCheckerboard(Schur ,src_o,in); | ||||
|       pickCheckerboard(Other,sol_e,out); | ||||
|       pickCheckerboard(Schur ,sol_o,out); | ||||
|      | ||||
|       ///////////////////////////////////////////////////// | ||||
|       // src_o = Mdag * (source_o - Moe MeeInv source_e) | ||||
|       ///////////////////////////////////////////////////// | ||||
|       _Matrix.MooeeInv(src_e,tmp);     assert(  tmp.checkerboard ==Other); | ||||
|       _Matrix.Meooe   (tmp,Mtmp);      assert( Mtmp.checkerboard ==Schur);      | ||||
|       tmp=src_o-Mtmp;                  assert(  tmp.checkerboard ==Schur);      | ||||
|  | ||||
|       _Matrix.Mooee(tmp,src_o);     assert(src_o.checkerboard ==Schur); | ||||
|       ////////////////////////////////////////////////////////////// | ||||
|       // Call the red-black solver | ||||
|       ////////////////////////////////////////////////////////////// | ||||
|       std::cout<<GridLogMessage << "SchurRedBlack solver calling the MpcDagMp solver" <<std::endl; | ||||
| //      _HermitianRBSolver(_HermOpEO,src_o,sol_o);  assert(sol_o.checkerboard==Schur); | ||||
|       _HermitianRBSolver(src_o,sol_o);  assert(sol_o.checkerboard==Other); | ||||
|  | ||||
|       /////////////////////////////////////////////////// | ||||
|       // sol_e = M_ee^-1 * ( src_e - Meo sol_o )... | ||||
|       /////////////////////////////////////////////////// | ||||
|       _Matrix.Meooe(sol_o,tmp);        assert(  tmp.checkerboard   ==Other); | ||||
|       src_e = src_e-tmp;               assert(  src_e.checkerboard ==Other); | ||||
|       _Matrix.MooeeInv(src_e,sol_e);   assert(  sol_e.checkerboard ==Other); | ||||
|       | ||||
|       setCheckerboard(out,sol_e); assert(  sol_e.checkerboard ==Other); | ||||
|       setCheckerboard(out,sol_o); assert(  sol_o.checkerboard ==Schur ); | ||||
|  | ||||
|       // Verify the unprec residual | ||||
|       _Matrix.M(out,resid);  | ||||
|       resid = resid-in; | ||||
|       RealD ns = norm2(in); | ||||
|       RealD nr = norm2(resid); | ||||
|  | ||||
|       std::cout<<GridLogMessage << "SchurRedBlackStag solver true unprec resid "<< std::sqrt(nr/ns) <<" nr "<< nr <<" ns "<<ns << std::endl; | ||||
|     }      | ||||
|   }; | ||||
|  | ||||
| } | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										933
									
								
								lib/algorithms/iterative/SimpleLanczos.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										933
									
								
								lib/algorithms/iterative/SimpleLanczos.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,933 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid  | ||||
|  | ||||
|     Source file: ./lib/algorithms/iterative/ImplicitlyRestartedLanczos.h | ||||
|  | ||||
|     Copyright (C) 2015 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Chulwoo Jung <chulwoo@bnl.gov> | ||||
|  | ||||
|     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_LANC_H | ||||
| #define GRID_LANC_H | ||||
|  | ||||
| #include <string.h>		//memset | ||||
|  | ||||
| #ifdef USE_LAPACK | ||||
| #ifdef USE_MKL | ||||
| #include<mkl_lapack.h> | ||||
| #else | ||||
| void LAPACK_dstegr (char *jobz, char *range, int *n, double *d, double *e, | ||||
| 		    double *vl, double *vu, int *il, int *iu, double *abstol, | ||||
| 		    int *m, double *w, double *z, int *ldz, int *isuppz, | ||||
| 		    double *work, int *lwork, int *iwork, int *liwork, | ||||
| 		    int *info); | ||||
| //#include <lapacke/lapacke.h> | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #include <Grid/algorithms/densematrix/DenseMatrix.h> | ||||
| //#include <Grid/algorithms/iterative/EigenSort.h> | ||||
|  | ||||
| // eliminate temorary vector in calc() | ||||
| #define MEM_SAVE | ||||
|  | ||||
| namespace Grid | ||||
| { | ||||
|  | ||||
|   struct Bisection | ||||
|   { | ||||
|  | ||||
| #if 0 | ||||
|     static void get_eig2 (int row_num, std::vector < RealD > &ALPHA, | ||||
| 			  std::vector < RealD > &BETA, | ||||
| 			  std::vector < RealD > &eig) | ||||
|     { | ||||
|       int i, j; | ||||
|         std::vector < RealD > evec1 (row_num + 3); | ||||
|         std::vector < RealD > evec2 (row_num + 3); | ||||
|       RealD eps2; | ||||
|         ALPHA[1] = 0.; | ||||
|         BETHA[1] = 0.; | ||||
|       for (i = 0; i < row_num - 1; i++) | ||||
| 	{ | ||||
| 	  ALPHA[i + 1] = A[i * (row_num + 1)].real (); | ||||
| 	  BETHA[i + 2] = A[i * (row_num + 1) + 1].real (); | ||||
| 	} | ||||
|       ALPHA[row_num] = A[(row_num - 1) * (row_num + 1)].real (); | ||||
|         bisec (ALPHA, BETHA, row_num, 1, row_num, 1e-10, 1e-10, evec1, eps2); | ||||
|         bisec (ALPHA, BETHA, row_num, 1, row_num, 1e-16, 1e-16, evec2, eps2); | ||||
|  | ||||
|       // Do we really need to sort here? | ||||
|       int begin = 1; | ||||
|       int end = row_num; | ||||
|       int swapped = 1; | ||||
|       while (swapped) | ||||
| 	{ | ||||
| 	  swapped = 0; | ||||
| 	  for (i = begin; i < end; i++) | ||||
| 	    { | ||||
| 	      if (mag (evec2[i]) > mag (evec2[i + 1])) | ||||
| 		{ | ||||
| 		  swap (evec2 + i, evec2 + i + 1); | ||||
| 		  swapped = 1; | ||||
| 		} | ||||
| 	    } | ||||
| 	  end--; | ||||
| 	  for (i = end - 1; i >= begin; i--) | ||||
| 	    { | ||||
| 	      if (mag (evec2[i]) > mag (evec2[i + 1])) | ||||
| 		{ | ||||
| 		  swap (evec2 + i, evec2 + i + 1); | ||||
| 		  swapped = 1; | ||||
| 		} | ||||
| 	    } | ||||
| 	  begin++; | ||||
| 	} | ||||
|  | ||||
|       for (i = 0; i < row_num; i++) | ||||
| 	{ | ||||
| 	  for (j = 0; j < row_num; j++) | ||||
| 	    { | ||||
| 	      if (i == j) | ||||
| 		H[i * row_num + j] = evec2[i + 1]; | ||||
| 	      else | ||||
| 		H[i * row_num + j] = 0.; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     static void bisec (std::vector < RealD > &c, | ||||
| 		       std::vector < RealD > &b, | ||||
| 		       int n, | ||||
| 		       int m1, | ||||
| 		       int m2, | ||||
| 		       RealD eps1, | ||||
| 		       RealD relfeh, std::vector < RealD > &x, RealD & eps2) | ||||
|     { | ||||
|       std::vector < RealD > wu (n + 2); | ||||
|  | ||||
|       RealD h, q, x1, xu, x0, xmin, xmax; | ||||
|       int i, a, k; | ||||
|  | ||||
|       b[1] = 0.0; | ||||
|       xmin = c[n] - fabs (b[n]); | ||||
|       xmax = c[n] + fabs (b[n]); | ||||
|       for (i = 1; i < n; i++) | ||||
| 	{ | ||||
| 	  h = fabs (b[i]) + fabs (b[i + 1]); | ||||
| 	  if (c[i] + h > xmax) | ||||
| 	    xmax = c[i] + h; | ||||
| 	  if (c[i] - h < xmin) | ||||
| 	    xmin = c[i] - h; | ||||
| 	} | ||||
|       xmax *= 2.; | ||||
|  | ||||
|       eps2 = relfeh * ((xmin + xmax) > 0.0 ? xmax : -xmin); | ||||
|       if (eps1 <= 0.0) | ||||
| 	eps1 = eps2; | ||||
|       eps2 = 0.5 * eps1 + 7.0 * (eps2); | ||||
|       x0 = xmax; | ||||
|       for (i = m1; i <= m2; i++) | ||||
| 	{ | ||||
| 	  x[i] = xmax; | ||||
| 	  wu[i] = xmin; | ||||
| 	} | ||||
|  | ||||
|       for (k = m2; k >= m1; k--) | ||||
| 	{ | ||||
| 	  xu = xmin; | ||||
| 	  i = k; | ||||
| 	  do | ||||
| 	    { | ||||
| 	      if (xu < wu[i]) | ||||
| 		{ | ||||
| 		  xu = wu[i]; | ||||
| 		  i = m1 - 1; | ||||
| 		} | ||||
| 	      i--; | ||||
| 	    } | ||||
| 	  while (i >= m1); | ||||
| 	  if (x0 > x[k]) | ||||
| 	    x0 = x[k]; | ||||
| 	  while ((x0 - xu) > 2 * relfeh * (fabs (xu) + fabs (x0)) + eps1) | ||||
| 	    { | ||||
| 	      x1 = (xu + x0) / 2; | ||||
|  | ||||
| 	      a = 0; | ||||
| 	      q = 1.0; | ||||
| 	      for (i = 1; i <= n; i++) | ||||
| 		{ | ||||
| 		  q = | ||||
| 		    c[i] - x1 - | ||||
| 		    ((q != 0.0) ? b[i] * b[i] / q : fabs (b[i]) / relfeh); | ||||
| 		  if (q < 0) | ||||
| 		    a++; | ||||
| 		} | ||||
| //      printf("x1=%0.14e a=%d\n",x1,a); | ||||
| 	      if (a < k) | ||||
| 		{ | ||||
| 		  if (a < m1) | ||||
| 		    { | ||||
| 		      xu = x1; | ||||
| 		      wu[m1] = x1; | ||||
| 		    } | ||||
| 		  else | ||||
| 		    { | ||||
| 		      xu = x1; | ||||
| 		      wu[a + 1] = x1; | ||||
| 		      if (x[a] > x1) | ||||
| 			x[a] = x1; | ||||
| 		    } | ||||
| 		} | ||||
| 	      else | ||||
| 		x0 = x1; | ||||
| 	    } | ||||
| 	  printf ("x0=%0.14e xu=%0.14e k=%d\n", x0, xu, k); | ||||
| 	  x[k] = (x0 + xu) / 2; | ||||
| 	} | ||||
|     } | ||||
|   }; | ||||
|  | ||||
| ///////////////////////////////////////////////////////////// | ||||
| // Implicitly restarted lanczos | ||||
| ///////////////////////////////////////////////////////////// | ||||
|  | ||||
|  | ||||
|   template < class Field > class SimpleLanczos | ||||
|   { | ||||
|  | ||||
|     const RealD small = 1.0e-16; | ||||
|   public: | ||||
|     int lock; | ||||
|     int get; | ||||
|     int Niter; | ||||
|     int converged; | ||||
|  | ||||
|     int Nstop;			// Number of evecs checked for convergence | ||||
|     int Nk;			// Number of converged sought | ||||
|     int Np;			// Np -- Number of spare vecs in kryloc space | ||||
|     int Nm;			// Nm -- total number of vectors | ||||
|  | ||||
|  | ||||
|     RealD OrthoTime; | ||||
|  | ||||
|     RealD eresid; | ||||
|  | ||||
|     SortEigen < Field > _sort; | ||||
|  | ||||
|     LinearOperatorBase < Field > &_Linop; | ||||
|  | ||||
|     OperatorFunction < Field > &_poly; | ||||
|  | ||||
|     ///////////////////////// | ||||
|     // Constructor | ||||
|     ///////////////////////// | ||||
|     void init (void) | ||||
|     { | ||||
|     }; | ||||
|     void Abort (int ff, DenseVector < RealD > &evals, | ||||
| 		DenseVector < DenseVector < RealD > >&evecs); | ||||
|  | ||||
|     SimpleLanczos (LinearOperatorBase < Field > &Linop,	// op | ||||
| 		   OperatorFunction < Field > &poly,	// polynmial | ||||
| 		   int _Nstop,	// sought vecs | ||||
| 		   int _Nk,	// sought vecs | ||||
| 		   int _Nm,	// spare vecs | ||||
| 		   RealD _eresid,	// resid in lmdue deficit  | ||||
| 		   int _Niter):	// Max iterations | ||||
|       | ||||
|       _Linop (Linop), | ||||
|       _poly (poly), | ||||
|       Nstop (_Nstop), Nk (_Nk), Nm (_Nm), eresid (_eresid), Niter (_Niter) | ||||
|     { | ||||
|       Np = Nm - Nk; | ||||
|       assert (Np > 0); | ||||
|     }; | ||||
|  | ||||
|     ///////////////////////// | ||||
|     // Sanity checked this routine (step) against Saad. | ||||
|     ///////////////////////// | ||||
|     void RitzMatrix (DenseVector < Field > &evec, int k) | ||||
|     { | ||||
|  | ||||
|       if (1) | ||||
| 	return; | ||||
|  | ||||
|       GridBase *grid = evec[0]._grid; | ||||
|       Field w (grid); | ||||
|       std::cout << GridLogMessage << "RitzMatrix " << std::endl; | ||||
|       for (int i = 0; i < k; i++) | ||||
| 	{ | ||||
| 	  _Linop.HermOp (evec[i], w); | ||||
| //      _poly(_Linop,evec[i],w); | ||||
| 	  std::cout << GridLogMessage << "[" << i << "] "; | ||||
| 	  for (int j = 0; j < k; j++) | ||||
| 	    { | ||||
| 	      ComplexD in = innerProduct (evec[j], w); | ||||
| 	      if (fabs ((double) i - j) > 1) | ||||
| 		{ | ||||
| 		  if (abs (in) > 1.0e-9) | ||||
| 		    { | ||||
| 		      std::cout << GridLogMessage << "oops" << std::endl; | ||||
| 		      abort (); | ||||
| 		    } | ||||
| 		  else | ||||
| 		    std::cout << GridLogMessage << " 0 "; | ||||
| 		} | ||||
| 	      else | ||||
| 		{ | ||||
| 		  std::cout << GridLogMessage << " " << in << " "; | ||||
| 		} | ||||
| 	    } | ||||
| 	  std::cout << GridLogMessage << std::endl; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|     void step (DenseVector < RealD > &lmd, | ||||
| 	       DenseVector < RealD > &lme, | ||||
| 	       Field & last, Field & current, Field & next, uint64_t k) | ||||
|     { | ||||
|       if (lmd.size () <= k) | ||||
| 	lmd.resize (k + Nm); | ||||
|       if (lme.size () <= k) | ||||
| 	lme.resize (k + Nm); | ||||
|  | ||||
|  | ||||
| //      _poly(_Linop,current,next );   // 3. wk:=Avk−βkv_{k−1} | ||||
|       _Linop.HermOp (current, next);	// 3. wk:=Avk−βkv_{k−1} | ||||
|       if (k > 0) | ||||
| 	{ | ||||
| 	  next -= lme[k - 1] * last; | ||||
| 	} | ||||
| //      std::cout<<GridLogMessage << "<last|next>" << innerProduct(last,next) <<std::endl; | ||||
|  | ||||
|       ComplexD zalph = innerProduct (current, next);	// 4. αk:=(wk,vk) | ||||
|       RealD alph = real (zalph); | ||||
|  | ||||
|       next = next - alph * current;	// 5. wk:=wk−αkvk | ||||
| //      std::cout<<GridLogMessage << "<current|next>" << innerProduct(current,next) <<std::endl; | ||||
|  | ||||
|       RealD beta = normalise (next);	// 6. βk+1 := ∥wk∥2. If βk+1 = 0 then Stop | ||||
|       // 7. vk+1 := wk/βk+1 | ||||
| //       norm=beta; | ||||
|  | ||||
|       int interval = Nm / 100 + 1; | ||||
|       if ((k % interval) == 0) | ||||
| 	std:: | ||||
| 	  cout << GridLogMessage << k << " : alpha = " << zalph << " beta " << | ||||
| 	  beta << std::endl; | ||||
|       const RealD tiny = 1.0e-20; | ||||
|       if (beta < tiny) | ||||
| 	{ | ||||
| 	  std::cout << GridLogMessage << " beta is tiny " << beta << std:: | ||||
| 	    endl; | ||||
| 	} | ||||
|       lmd[k] = alph; | ||||
|       lme[k] = beta; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     void qr_decomp (DenseVector < RealD > &lmd, | ||||
| 		    DenseVector < RealD > &lme, | ||||
| 		    int Nk, | ||||
| 		    int Nm, | ||||
| 		    DenseVector < RealD > &Qt, RealD Dsh, int kmin, int kmax) | ||||
|     { | ||||
|       int k = kmin - 1; | ||||
|       RealD x; | ||||
|  | ||||
|       RealD Fden = 1.0 / hypot (lmd[k] - Dsh, lme[k]); | ||||
|       RealD c = (lmd[k] - Dsh) * Fden; | ||||
|       RealD s = -lme[k] * Fden; | ||||
|  | ||||
|       RealD tmpa1 = lmd[k]; | ||||
|       RealD tmpa2 = lmd[k + 1]; | ||||
|       RealD tmpb = lme[k]; | ||||
|  | ||||
|       lmd[k] = c * c * tmpa1 + s * s * tmpa2 - 2.0 * c * s * tmpb; | ||||
|       lmd[k + 1] = s * s * tmpa1 + c * c * tmpa2 + 2.0 * c * s * tmpb; | ||||
|       lme[k] = c * s * (tmpa1 - tmpa2) + (c * c - s * s) * tmpb; | ||||
|       x = -s * lme[k + 1]; | ||||
|       lme[k + 1] = c * lme[k + 1]; | ||||
|  | ||||
|       for (int i = 0; i < Nk; ++i) | ||||
| 	{ | ||||
| 	  RealD Qtmp1 = Qt[i + Nm * k]; | ||||
| 	  RealD Qtmp2 = Qt[i + Nm * (k + 1)]; | ||||
| 	  Qt[i + Nm * k] = c * Qtmp1 - s * Qtmp2; | ||||
| 	  Qt[i + Nm * (k + 1)] = s * Qtmp1 + c * Qtmp2; | ||||
| 	} | ||||
|  | ||||
|       // Givens transformations | ||||
|       for (int k = kmin; k < kmax - 1; ++k) | ||||
| 	{ | ||||
|  | ||||
| 	  RealD Fden = 1.0 / hypot (x, lme[k - 1]); | ||||
| 	  RealD c = lme[k - 1] * Fden; | ||||
| 	  RealD s = -x * Fden; | ||||
|  | ||||
| 	  RealD tmpa1 = lmd[k]; | ||||
| 	  RealD tmpa2 = lmd[k + 1]; | ||||
| 	  RealD tmpb = lme[k]; | ||||
|  | ||||
| 	  lmd[k] = c * c * tmpa1 + s * s * tmpa2 - 2.0 * c * s * tmpb; | ||||
| 	  lmd[k + 1] = s * s * tmpa1 + c * c * tmpa2 + 2.0 * c * s * tmpb; | ||||
| 	  lme[k] = c * s * (tmpa1 - tmpa2) + (c * c - s * s) * tmpb; | ||||
| 	  lme[k - 1] = c * lme[k - 1] - s * x; | ||||
|  | ||||
| 	  if (k != kmax - 2) | ||||
| 	    { | ||||
| 	      x = -s * lme[k + 1]; | ||||
| 	      lme[k + 1] = c * lme[k + 1]; | ||||
| 	    } | ||||
|  | ||||
| 	  for (int i = 0; i < Nk; ++i) | ||||
| 	    { | ||||
| 	      RealD Qtmp1 = Qt[i + Nm * k]; | ||||
| 	      RealD Qtmp2 = Qt[i + Nm * (k + 1)]; | ||||
| 	      Qt[i + Nm * k] = c * Qtmp1 - s * Qtmp2; | ||||
| 	      Qt[i + Nm * (k + 1)] = s * Qtmp1 + c * Qtmp2; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|  | ||||
| #ifdef USE_LAPACK | ||||
| #ifdef USE_MKL | ||||
| #define LAPACK_INT MKL_INT | ||||
| #else | ||||
| #define LAPACK_INT long long | ||||
| #endif | ||||
|     void diagonalize_lapack (DenseVector < RealD > &lmd, DenseVector < RealD > &lme, int N1,	// all | ||||
| 			     int N2,	// get | ||||
| 			     GridBase * grid) | ||||
|     { | ||||
|       const int size = Nm; | ||||
|       LAPACK_INT NN = N1; | ||||
|       double evals_tmp[NN]; | ||||
|       double DD[NN]; | ||||
|       double EE[NN]; | ||||
|       for (int i = 0; i < NN; i++) | ||||
| 	for (int j = i - 1; j <= i + 1; j++) | ||||
| 	  if (j < NN && j >= 0) | ||||
| 	    { | ||||
| 	      if (i == j) | ||||
| 		DD[i] = lmd[i]; | ||||
| 	      if (i == j) | ||||
| 		evals_tmp[i] = lmd[i]; | ||||
| 	      if (j == (i - 1)) | ||||
| 		EE[j] = lme[j]; | ||||
| 	    } | ||||
|       LAPACK_INT evals_found; | ||||
|       LAPACK_INT lwork = | ||||
| 	((18 * NN) > | ||||
| 	 (1 + 4 * NN + NN * NN) ? (18 * NN) : (1 + 4 * NN + NN * NN)); | ||||
|       LAPACK_INT liwork = 3 + NN * 10; | ||||
|       LAPACK_INT iwork[liwork]; | ||||
|       double work[lwork]; | ||||
|       LAPACK_INT isuppz[2 * NN]; | ||||
|       char jobz = 'N';		// calculate evals only | ||||
|       char range = 'I';		// calculate il-th to iu-th evals | ||||
|       //    char range = 'A'; // calculate all evals | ||||
|       char uplo = 'U';		// refer to upper half of original matrix | ||||
|       char compz = 'I';		// Compute eigenvectors of tridiagonal matrix | ||||
|       int ifail[NN]; | ||||
|       LAPACK_INT info; | ||||
| //  int total = QMP_get_number_of_nodes(); | ||||
| //  int node = QMP_get_node_number(); | ||||
| //  GridBase *grid = evec[0]._grid; | ||||
|       int total = grid->_Nprocessors; | ||||
|       int node = grid->_processor; | ||||
|       int interval = (NN / total) + 1; | ||||
|       double vl = 0.0, vu = 0.0; | ||||
|       LAPACK_INT il = interval * node + 1, iu = interval * (node + 1); | ||||
|       if (iu > NN) | ||||
| 	iu = NN; | ||||
|       double tol = 0.0; | ||||
|       if (1) | ||||
| 	{ | ||||
| 	  memset (evals_tmp, 0, sizeof (double) * NN); | ||||
| 	  if (il <= NN) | ||||
| 	    { | ||||
| 	      printf ("total=%d node=%d il=%d iu=%d\n", total, node, il, iu); | ||||
| #ifdef USE_MKL | ||||
| 	      dstegr (&jobz, &range, &NN, | ||||
| #else | ||||
| 	      LAPACK_dstegr (&jobz, &range, &NN, | ||||
| #endif | ||||
| 			     (double *) DD, (double *) EE, &vl, &vu, &il, &iu,	// these four are ignored if second parameteris 'A' | ||||
| 			     &tol,	// tolerance | ||||
| 			     &evals_found, evals_tmp, (double *) NULL, &NN, | ||||
| 			     isuppz, work, &lwork, iwork, &liwork, &info); | ||||
| 	      for (int i = iu - 1; i >= il - 1; i--) | ||||
| 		{ | ||||
| 		  printf ("node=%d evals_found=%d evals_tmp[%d] = %g\n", node, | ||||
| 			  evals_found, i - (il - 1), evals_tmp[i - (il - 1)]); | ||||
| 		  evals_tmp[i] = evals_tmp[i - (il - 1)]; | ||||
| 		  if (il > 1) | ||||
| 		    evals_tmp[i - (il - 1)] = 0.; | ||||
| 		} | ||||
| 	    } | ||||
| 	  { | ||||
| 	    grid->GlobalSumVector (evals_tmp, NN); | ||||
| 	  } | ||||
| 	} | ||||
| // cheating a bit. It is better to sort instead of just reversing it, but the document of the routine says evals are sorted in increasing order. qr gives evals in decreasing order. | ||||
|     } | ||||
| #undef LAPACK_INT | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     void diagonalize (DenseVector < RealD > &lmd, | ||||
| 		      DenseVector < RealD > &lme, | ||||
| 		      int N2, int N1, GridBase * grid) | ||||
|     { | ||||
|  | ||||
| #ifdef USE_LAPACK | ||||
|       const int check_lapack = 0;	// just use lapack if 0, check against lapack if 1 | ||||
|  | ||||
|       if (!check_lapack) | ||||
| 	return diagonalize_lapack (lmd, lme, N2, N1, grid); | ||||
|  | ||||
| //      diagonalize_lapack(lmd2,lme2,Nm2,Nm,Qt,grid); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
| #if 1 | ||||
|     static RealD normalise (Field & v) | ||||
|     { | ||||
|       RealD nn = norm2 (v); | ||||
|       nn = sqrt (nn); | ||||
|       v = v * (1.0 / nn); | ||||
|       return nn; | ||||
|     } | ||||
|  | ||||
|     void orthogonalize (Field & w, DenseVector < Field > &evec, int k) | ||||
|     { | ||||
|       double t0 = -usecond () / 1e6; | ||||
|       typedef typename Field::scalar_type MyComplex; | ||||
|       MyComplex ip; | ||||
|  | ||||
|       if (0) | ||||
| 	{ | ||||
| 	  for (int j = 0; j < k; ++j) | ||||
| 	    { | ||||
| 	      normalise (evec[j]); | ||||
| 	      for (int i = 0; i < j; i++) | ||||
| 		{ | ||||
| 		  ip = innerProduct (evec[i], evec[j]);	// are the evecs normalised? ; this assumes so. | ||||
| 		  evec[j] = evec[j] - ip * evec[i]; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
|       for (int j = 0; j < k; ++j) | ||||
| 	{ | ||||
| 	  ip = innerProduct (evec[j], w);	// are the evecs normalised? ; this assumes so. | ||||
| 	  w = w - ip * evec[j]; | ||||
| 	} | ||||
|       normalise (w); | ||||
|       t0 += usecond () / 1e6; | ||||
|       OrthoTime += t0; | ||||
|     } | ||||
|  | ||||
|     void setUnit_Qt (int Nm, DenseVector < RealD > &Qt) | ||||
|     { | ||||
|       for (int i = 0; i < Qt.size (); ++i) | ||||
| 	Qt[i] = 0.0; | ||||
|       for (int k = 0; k < Nm; ++k) | ||||
| 	Qt[k + k * Nm] = 1.0; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     void calc (DenseVector < RealD > &eval, const Field & src, int &Nconv) | ||||
|     { | ||||
|  | ||||
|       GridBase *grid = src._grid; | ||||
| //      assert(grid == src._grid); | ||||
|  | ||||
|       std:: | ||||
| 	cout << GridLogMessage << " -- Nk = " << Nk << " Np = " << Np << std:: | ||||
| 	endl; | ||||
|       std::cout << GridLogMessage << " -- Nm = " << Nm << std::endl; | ||||
|       std::cout << GridLogMessage << " -- size of eval   = " << eval. | ||||
| 	size () << std::endl; | ||||
|  | ||||
| //      assert(c.size() && Nm == eval.size()); | ||||
|  | ||||
|       DenseVector < RealD > lme (Nm); | ||||
|       DenseVector < RealD > lmd (Nm); | ||||
|  | ||||
|  | ||||
|       Field current (grid); | ||||
|       Field last (grid); | ||||
|       Field next (grid); | ||||
|  | ||||
|       Nconv = 0; | ||||
|  | ||||
|       RealD beta_k; | ||||
|  | ||||
|       // Set initial vector | ||||
|       // (uniform vector) Why not src?? | ||||
|       //      evec[0] = 1.0; | ||||
|       current = src; | ||||
|       std::cout << GridLogMessage << "norm2(src)= " << norm2 (src) << std:: | ||||
| 	endl; | ||||
|       normalise (current); | ||||
|       std:: | ||||
| 	cout << GridLogMessage << "norm2(evec[0])= " << norm2 (current) << | ||||
| 	std::endl; | ||||
|  | ||||
|       // Initial Nk steps | ||||
|       OrthoTime = 0.; | ||||
|       double t0 = usecond () / 1e6; | ||||
|       RealD norm;		// sqrt norm of last vector | ||||
|  | ||||
|       uint64_t iter = 0; | ||||
|  | ||||
|       bool initted = false; | ||||
|       std::vector < RealD > low (Nstop * 10); | ||||
|       std::vector < RealD > high (Nstop * 10); | ||||
|       RealD cont = 0.; | ||||
|       while (1) { | ||||
| 	  cont = 0.; | ||||
| 	  std::vector < RealD > lme2 (Nm); | ||||
| 	  std::vector < RealD > lmd2 (Nm); | ||||
| 	  for (uint64_t k = 0; k < Nm; ++k, iter++) { | ||||
| 	      step (lmd, lme, last, current, next, iter); | ||||
| 	      last = current; | ||||
| 	      current = next; | ||||
| 	    } | ||||
| 	  double t1 = usecond () / 1e6; | ||||
| 	  std::cout << GridLogMessage << "IRL::Initial steps: " << t1 - | ||||
| 	    t0 << "seconds" << std::endl; | ||||
| 	  t0 = t1; | ||||
| 	  std:: | ||||
| 	    cout << GridLogMessage << "IRL::Initial steps:OrthoTime " << | ||||
| 	    OrthoTime << "seconds" << std::endl; | ||||
|  | ||||
| 	  // getting eigenvalues | ||||
| 	  lmd2.resize (iter + 2); | ||||
| 	  lme2.resize (iter + 2); | ||||
| 	  for (uint64_t k = 0; k < iter; ++k) { | ||||
| 	      lmd2[k + 1] = lmd[k]; | ||||
| 	      lme2[k + 2] = lme[k]; | ||||
| 	    } | ||||
| 	  t1 = usecond () / 1e6; | ||||
| 	  std::cout << GridLogMessage << "IRL:: copy: " << t1 - | ||||
| 	    t0 << "seconds" << std::endl; | ||||
| 	  t0 = t1; | ||||
| 	  { | ||||
| 	    int total = grid->_Nprocessors; | ||||
| 	    int node = grid->_processor; | ||||
| 	    int interval = (Nstop / total) + 1; | ||||
| 	    int iu = (iter + 1) - (interval * node + 1); | ||||
| 	    int il = (iter + 1) - (interval * (node + 1)); | ||||
| 	    std::vector < RealD > eval2 (iter + 3); | ||||
| 	    RealD eps2; | ||||
| 	    Bisection::bisec (lmd2, lme2, iter, il, iu, 1e-16, 1e-10, eval2, | ||||
| 			      eps2); | ||||
| //        diagonalize(eval2,lme2,iter,Nk,grid); | ||||
| 	    RealD diff = 0.; | ||||
| 	    for (int i = il; i <= iu; i++) { | ||||
| 		if (initted) | ||||
| 		  diff = | ||||
| 		    fabs (eval2[i] - high[iu-i]) / (fabs (eval2[i]) + | ||||
| 						      fabs (high[iu-i])); | ||||
| 		if (initted && (diff > eresid)) | ||||
| 		  cont = 1.; | ||||
| 		if (initted) | ||||
| 		  printf ("eval[%d]=%0.14e %0.14e, %0.14e\n", i, eval2[i], | ||||
| 			  high[iu-i], diff); | ||||
| 		high[iu-i] = eval2[i]; | ||||
| 	      } | ||||
| 	    il = (interval * node + 1); | ||||
| 	    iu = (interval * (node + 1)); | ||||
| 	    Bisection::bisec (lmd2, lme2, iter, il, iu, 1e-16, 1e-10, eval2, | ||||
| 			      eps2); | ||||
| 	    for (int i = il; i <= iu; i++) { | ||||
| 		if (initted) | ||||
| 		  diff = | ||||
| 		    fabs (eval2[i] - low[i]) / (fabs (eval2[i]) + | ||||
| 						fabs (low[i])); | ||||
| 		if (initted && (diff > eresid)) | ||||
| 		  cont = 1.; | ||||
| 		if (initted) | ||||
| 		  printf ("eval[%d]=%0.14e %0.14e, %0.14e\n", i, eval2[i], | ||||
| 			  low[i], diff); | ||||
| 		low[i] = eval2[i]; | ||||
| 	      } | ||||
| 	    t1 = usecond () / 1e6; | ||||
| 	    std::cout << GridLogMessage << "IRL:: diagonalize: " << t1 - | ||||
| 	      t0 << "seconds" << std::endl; | ||||
| 	    t0 = t1; | ||||
| 	  } | ||||
|  | ||||
| 	  for (uint64_t k = 0; k < Nk; ++k) { | ||||
| //          eval[k] = eval2[k]; | ||||
| 	    } | ||||
| 	  if (initted) | ||||
| 	    { | ||||
| 	      grid->GlobalSumVector (&cont, 1); | ||||
| 	      if (cont < 1.) return; | ||||
| 	    } | ||||
| 	  initted = true; | ||||
| 	} | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|    There is some matrix Q such that for any vector y | ||||
|    Q.e_1 = y and Q is unitary. | ||||
| **/ | ||||
|     template < class T > | ||||
|       static T orthQ (DenseMatrix < T > &Q, DenseVector < T > y) | ||||
|     { | ||||
|       int N = y.size ();	//Matrix Size | ||||
|       Fill (Q, 0.0); | ||||
|       T tau; | ||||
|       for (int i = 0; i < N; i++) | ||||
| 	{ | ||||
| 	  Q[i][0] = y[i]; | ||||
| 	} | ||||
|       T sig = conj (y[0]) * y[0]; | ||||
|       T tau0 = fabs (sqrt (sig)); | ||||
|  | ||||
|       for (int j = 1; j < N; j++) | ||||
| 	{ | ||||
| 	  sig += conj (y[j]) * y[j]; | ||||
| 	  tau = abs (sqrt (sig)); | ||||
|  | ||||
| 	  if (abs (tau0) > 0.0) | ||||
| 	    { | ||||
|  | ||||
| 	      T gam = conj ((y[j] / tau) / tau0); | ||||
| 	      for (int k = 0; k <= j - 1; k++) | ||||
| 		{ | ||||
| 		  Q[k][j] = -gam * y[k]; | ||||
| 		} | ||||
| 	      Q[j][j] = tau0 / tau; | ||||
| 	    } | ||||
| 	  else | ||||
| 	    { | ||||
| 	      Q[j - 1][j] = 1.0; | ||||
| 	    } | ||||
| 	  tau0 = tau; | ||||
| 	} | ||||
|       return tau; | ||||
|     } | ||||
|  | ||||
| /** | ||||
| 	There is some matrix Q such that for any vector y | ||||
| 	Q.e_k = y and Q is unitary. | ||||
| **/ | ||||
|     template < class T > | ||||
|       static T orthU (DenseMatrix < T > &Q, DenseVector < T > y) | ||||
|     { | ||||
|       T tau = orthQ (Q, y); | ||||
|       SL (Q); | ||||
|       return tau; | ||||
|     } | ||||
|  | ||||
|  | ||||
| /** | ||||
| 	Wind up with a matrix with the first con rows untouched | ||||
|  | ||||
| say con = 2 | ||||
| 	Q is such that Qdag H Q has {x, x, val, 0, 0, 0, 0, ...} as 1st colum | ||||
| 	and the matrix is upper hessenberg | ||||
| 	and with f and Q appropriately modidied with Q is the arnoldi factorization | ||||
|  | ||||
| **/ | ||||
|  | ||||
|     template < class T > static void Lock (DenseMatrix < T > &H,	///Hess mtx      | ||||
| 					   DenseMatrix < T > &Q,	///Lock Transform | ||||
| 					   T val,	///value to be locked | ||||
| 					   int con,	///number already locked | ||||
| 					   RealD small, int dfg, bool herm) | ||||
|     { | ||||
|       //ForceTridiagonal(H); | ||||
|  | ||||
|       int M = H.dim; | ||||
|       DenseVector < T > vec; | ||||
|       Resize (vec, M - con); | ||||
|  | ||||
|       DenseMatrix < T > AH; | ||||
|       Resize (AH, M - con, M - con); | ||||
|       AH = GetSubMtx (H, con, M, con, M); | ||||
|  | ||||
|       DenseMatrix < T > QQ; | ||||
|       Resize (QQ, M - con, M - con); | ||||
|  | ||||
|       Unity (Q); | ||||
|       Unity (QQ); | ||||
|  | ||||
|       DenseVector < T > evals; | ||||
|       Resize (evals, M - con); | ||||
|       DenseMatrix < T > evecs; | ||||
|       Resize (evecs, M - con, M - con); | ||||
|  | ||||
|       Wilkinson < T > (AH, evals, evecs, small); | ||||
|  | ||||
|       int k = 0; | ||||
|       RealD cold = abs (val - evals[k]); | ||||
|       for (int i = 1; i < M - con; i++) | ||||
| 	{ | ||||
| 	  RealD cnew = abs (val - evals[i]); | ||||
| 	  if (cnew < cold) | ||||
| 	    { | ||||
| 	      k = i; | ||||
| 	      cold = cnew; | ||||
| 	    } | ||||
| 	} | ||||
|       vec = evecs[k]; | ||||
|  | ||||
|       ComplexD tau; | ||||
|       orthQ (QQ, vec); | ||||
|       //orthQM(QQ,AH,vec); | ||||
|  | ||||
|       AH = Hermitian (QQ) * AH; | ||||
|       AH = AH * QQ; | ||||
|  | ||||
|       for (int i = con; i < M; i++) | ||||
| 	{ | ||||
| 	  for (int j = con; j < M; j++) | ||||
| 	    { | ||||
| 	      Q[i][j] = QQ[i - con][j - con]; | ||||
| 	      H[i][j] = AH[i - con][j - con]; | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
|       for (int j = M - 1; j > con + 2; j--) | ||||
| 	{ | ||||
|  | ||||
| 	  DenseMatrix < T > U; | ||||
| 	  Resize (U, j - 1 - con, j - 1 - con); | ||||
| 	  DenseVector < T > z; | ||||
| 	  Resize (z, j - 1 - con); | ||||
| 	  T nm = norm (z); | ||||
| 	  for (int k = con + 0; k < j - 1; k++) | ||||
| 	    { | ||||
| 	      z[k - con] = conj (H (j, k + 1)); | ||||
| 	    } | ||||
| 	  normalise (z); | ||||
|  | ||||
| 	  RealD tmp = 0; | ||||
| 	  for (int i = 0; i < z.size () - 1; i++) | ||||
| 	    { | ||||
| 	      tmp = tmp + abs (z[i]); | ||||
| 	    } | ||||
|  | ||||
| 	  if (tmp < small / ((RealD) z.size () - 1.0)) | ||||
| 	    { | ||||
| 	      continue; | ||||
| 	    } | ||||
|  | ||||
| 	  tau = orthU (U, z); | ||||
|  | ||||
| 	  DenseMatrix < T > Hb; | ||||
| 	  Resize (Hb, j - 1 - con, M); | ||||
|  | ||||
| 	  for (int a = 0; a < M; a++) | ||||
| 	    { | ||||
| 	      for (int b = 0; b < j - 1 - con; b++) | ||||
| 		{ | ||||
| 		  T sum = 0; | ||||
| 		  for (int c = 0; c < j - 1 - con; c++) | ||||
| 		    { | ||||
| 		      sum += H[a][con + 1 + c] * U[c][b]; | ||||
| 		    }		//sum += H(a,con+1+c)*U(c,b);} | ||||
| 		  Hb[b][a] = sum; | ||||
| 		} | ||||
| 	    } | ||||
|  | ||||
| 	  for (int k = con + 1; k < j; k++) | ||||
| 	    { | ||||
| 	      for (int l = 0; l < M; l++) | ||||
| 		{ | ||||
| 		  H[l][k] = Hb[k - 1 - con][l]; | ||||
| 		} | ||||
| 	    }			//H(Hb[k-1-con][l] , l,k);}} | ||||
|  | ||||
| 	  DenseMatrix < T > Qb; | ||||
| 	  Resize (Qb, M, M); | ||||
|  | ||||
| 	  for (int a = 0; a < M; a++) | ||||
| 	    { | ||||
| 	      for (int b = 0; b < j - 1 - con; b++) | ||||
| 		{ | ||||
| 		  T sum = 0; | ||||
| 		  for (int c = 0; c < j - 1 - con; c++) | ||||
| 		    { | ||||
| 		      sum += Q[a][con + 1 + c] * U[c][b]; | ||||
| 		    }		//sum += Q(a,con+1+c)*U(c,b);} | ||||
| 		  Qb[b][a] = sum; | ||||
| 		} | ||||
| 	    } | ||||
|  | ||||
| 	  for (int k = con + 1; k < j; k++) | ||||
| 	    { | ||||
| 	      for (int l = 0; l < M; l++) | ||||
| 		{ | ||||
| 		  Q[l][k] = Qb[k - 1 - con][l]; | ||||
| 		} | ||||
| 	    }			//Q(Qb[k-1-con][l] , l,k);}} | ||||
|  | ||||
| 	  DenseMatrix < T > Hc; | ||||
| 	  Resize (Hc, M, M); | ||||
|  | ||||
| 	  for (int a = 0; a < j - 1 - con; a++) | ||||
| 	    { | ||||
| 	      for (int b = 0; b < M; b++) | ||||
| 		{ | ||||
| 		  T sum = 0; | ||||
| 		  for (int c = 0; c < j - 1 - con; c++) | ||||
| 		    { | ||||
| 		      sum += conj (U[c][a]) * H[con + 1 + c][b]; | ||||
| 		    }		//sum += conj( U(c,a) )*H(con+1+c,b);} | ||||
| 		  Hc[b][a] = sum; | ||||
| 		} | ||||
| 	    } | ||||
|  | ||||
| 	  for (int k = 0; k < M; k++) | ||||
| 	    { | ||||
| 	      for (int l = con + 1; l < j; l++) | ||||
| 		{ | ||||
| 		  H[l][k] = Hc[k][l - 1 - con]; | ||||
| 		} | ||||
| 	    }			//H(Hc[k][l-1-con] , l,k);}} | ||||
|  | ||||
| 	} | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|  | ||||
|   }; | ||||
|  | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										122
									
								
								lib/algorithms/iterative/bisec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								lib/algorithms/iterative/bisec.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| #include <math.h> | ||||
| #include <stdlib.h> | ||||
| #include <vector> | ||||
|  | ||||
| struct Bisection { | ||||
|  | ||||
| static void get_eig2(int row_num,std::vector<RealD> &ALPHA,std::vector<RealD> &BETA, std::vector<RealD> & eig) | ||||
| { | ||||
|   int i,j; | ||||
|   std::vector<RealD> evec1(row_num+3); | ||||
|   std::vector<RealD> evec2(row_num+3); | ||||
|   RealD eps2; | ||||
|   ALPHA[1]=0.; | ||||
|   BETHA[1]=0.; | ||||
|   for(i=0;i<row_num-1;i++) { | ||||
|     ALPHA[i+1] = A[i*(row_num+1)].real(); | ||||
|     BETHA[i+2] = A[i*(row_num+1)+1].real(); | ||||
|   } | ||||
|   ALPHA[row_num] = A[(row_num-1)*(row_num+1)].real(); | ||||
|   bisec(ALPHA,BETHA,row_num,1,row_num,1e-10,1e-10,evec1,eps2); | ||||
|   bisec(ALPHA,BETHA,row_num,1,row_num,1e-16,1e-16,evec2,eps2); | ||||
|  | ||||
|   // Do we really need to sort here? | ||||
|   int begin=1; | ||||
|   int end = row_num; | ||||
|   int swapped=1; | ||||
|   while(swapped) { | ||||
|     swapped=0; | ||||
|     for(i=begin;i<end;i++){ | ||||
|       if(mag(evec2[i])>mag(evec2[i+1]))	{ | ||||
| 	swap(evec2+i,evec2+i+1); | ||||
| 	swapped=1; | ||||
|       } | ||||
|     } | ||||
|     end--; | ||||
|     for(i=end-1;i>=begin;i--){ | ||||
|       if(mag(evec2[i])>mag(evec2[i+1]))	{ | ||||
| 	swap(evec2+i,evec2+i+1); | ||||
| 	swapped=1; | ||||
|       } | ||||
|     } | ||||
|     begin++; | ||||
|   } | ||||
|  | ||||
|   for(i=0;i<row_num;i++){ | ||||
|     for(j=0;j<row_num;j++) { | ||||
|       if(i==j) H[i*row_num+j]=evec2[i+1]; | ||||
|       else H[i*row_num+j]=0.; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void bisec(std::vector<RealD> &c,    | ||||
| 		  std::vector<RealD> &b, | ||||
| 		  int n, | ||||
| 		  int m1, | ||||
| 		  int m2, | ||||
| 		  RealD eps1, | ||||
| 		  RealD relfeh, | ||||
| 		  std::vector<RealD> &x, | ||||
| 		  RealD &eps2) | ||||
| { | ||||
|   std::vector<RealD> wu(n+2); | ||||
|  | ||||
|   RealD h,q,x1,xu,x0,xmin,xmax;  | ||||
|   int i,a,k; | ||||
|  | ||||
|   b[1]=0.0; | ||||
|   xmin=c[n]-fabs(b[n]); | ||||
|   xmax=c[n]+fabs(b[n]); | ||||
|   for(i=1;i<n;i++){ | ||||
|     h=fabs(b[i])+fabs(b[i+1]); | ||||
|     if(c[i]+h>xmax) xmax= c[i]+h; | ||||
|     if(c[i]-h<xmin) xmin= c[i]-h; | ||||
|   } | ||||
|   xmax *=2.; | ||||
|  | ||||
|   eps2=relfeh*((xmin+xmax)>0.0 ? xmax : -xmin); | ||||
|   if(eps1<=0.0) eps1=eps2; | ||||
|   eps2=0.5*eps1+7.0*(eps2); | ||||
|   x0=xmax; | ||||
|   for(i=m1;i<=m2;i++){ | ||||
|     x[i]=xmax; | ||||
|     wu[i]=xmin; | ||||
|   } | ||||
|  | ||||
|   for(k=m2;k>=m1;k--){ | ||||
|     xu=xmin; | ||||
|     i=k; | ||||
|     do{ | ||||
|       if(xu<wu[i]){ | ||||
| 	xu=wu[i]; | ||||
| 	i=m1-1; | ||||
|       } | ||||
|       i--; | ||||
|     }while(i>=m1); | ||||
|     if(x0>x[k]) x0=x[k]; | ||||
|     while((x0-xu)>2*relfeh*(fabs(xu)+fabs(x0))+eps1){ | ||||
|       x1=(xu+x0)/2; | ||||
|  | ||||
|       a=0; | ||||
|       q=1.0; | ||||
|       for(i=1;i<=n;i++){ | ||||
| 	q=c[i]-x1-((q!=0.0)? b[i]*b[i]/q:fabs(b[i])/relfeh); | ||||
| 	if(q<0) a++; | ||||
|       } | ||||
|       //			printf("x1=%e a=%d\n",x1,a); | ||||
|       if(a<k){ | ||||
| 	if(a<m1){ | ||||
| 	  xu=x1; | ||||
| 	  wu[m1]=x1; | ||||
| 	}else { | ||||
| 	  xu=x1; | ||||
| 	  wu[a+1]=x1; | ||||
| 	  if(x[a]>x1) x[a]=x1; | ||||
| 	} | ||||
|       }else x0=x1; | ||||
|     } | ||||
|     x[k]=(x0+xu)/2; | ||||
|   } | ||||
| } | ||||
| } | ||||
| @@ -102,7 +102,6 @@ void CartesianCommunicator::GlobalSumVector(ComplexD *c,int N) | ||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors,const CartesianCommunicator &parent)  | ||||
| { | ||||
|   _ndimension = processors.size(); | ||||
|   assert(_ndimension = parent._ndimension); | ||||
|    | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // split the communicator | ||||
| @@ -121,10 +120,22 @@ CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors, | ||||
|   std::vector<int> scoor(_ndimension); // coor of split within parent | ||||
|   std::vector<int> ssize(_ndimension); // coor of split within parent | ||||
|  | ||||
|   std::vector<int> pcoor(_ndimension,0);  | ||||
|   std::vector<int> pdims(_ndimension,1);  | ||||
|  | ||||
|   if(parent._processors.size()==4 && _ndimension==5){ | ||||
|       for(int i=0;i<4;i++) pcoor[i+1]=parent._processor_coor[i]; | ||||
|       for(int i=0;i<4;i++) pdims[i+1]=parent._processors[i]; | ||||
|   } else { | ||||
|       assert(_ndimension == parent._ndimension); | ||||
|       for(int i=0;i<_ndimension;i++) pcoor[i]=parent._processor_coor[i]; | ||||
|       for(int i=0;i<_ndimension;i++) pdims[i]=parent._processors[i]; | ||||
|   } | ||||
|  | ||||
|   for(int d=0;d<_ndimension;d++){ | ||||
|     ccoor[d] = parent._processor_coor[d] % processors[d]; | ||||
|     scoor[d] = parent._processor_coor[d] / processors[d]; | ||||
|     ssize[d] = parent._processors[d]/ processors[d]; | ||||
|     ccoor[d] = pcoor[d] % processors[d]; | ||||
|     scoor[d] = pcoor[d] / processors[d]; | ||||
|     ssize[d] = pdims[d] / processors[d]; | ||||
|   } | ||||
|   int crank,srank;  // rank within subcomm ; rank of subcomm within blocks of subcomms | ||||
|   Lexicographic::IndexFromCoor(ccoor,crank,processors); | ||||
|   | ||||
| @@ -415,6 +415,8 @@ void CayleyFermion5D<Impl>::SetCoefficientsInternal(RealD zolo_hi,std::vector<Co | ||||
|     assert(omega[i]!=Coeff_t(0.0)); | ||||
|     bs[i] = 0.5*(bpc/omega[i] + bmc); | ||||
|     cs[i] = 0.5*(bpc/omega[i] - bmc); | ||||
|     std::cout<<GridLogMessage << "CayleyFermion5D "<<i<<" bs="<<bs[i]<<" cs="<<cs[i]<< std::endl; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   //////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -61,8 +61,8 @@ Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| #include <Grid/qcd/action/fermion/MobiusFermion.h> | ||||
| #include <Grid/qcd/action/fermion/MobiusEOFAFermion.h> | ||||
| #include <Grid/qcd/action/fermion/ZMobiusFermion.h> | ||||
| #include <Grid/qcd/action/fermion/SchurDiagTwoKappa.h> | ||||
| #include <Grid/qcd/action/fermion/ScaledShamirFermion.h> | ||||
| //#include <Grid/qcd/action/fermion/SchurDiagTwoKappa.h> | ||||
| #include <Grid/qcd/action/fermion/MobiusZolotarevFermion.h> | ||||
| #include <Grid/qcd/action/fermion/ShamirZolotarevFermion.h> | ||||
| #include <Grid/qcd/action/fermion/OverlapWilsonCayleyTanhFermion.h> | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| #if 1 | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid  | ||||
| @@ -97,6 +98,117 @@ namespace Grid { | ||||
|     } | ||||
|   }; | ||||
|  | ||||
| #if 0 | ||||
|   /////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // Copied from DiagTwoSolve | ||||
|   /////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   template<class Field> class SchurRedBlackDiagTwoSolve { | ||||
|   private: | ||||
|     OperatorFunction<Field> & _HermitianRBSolver; | ||||
|     int CBfactorise; | ||||
|   public: | ||||
|  | ||||
|     ///////////////////////////////////////////////////// | ||||
|     // Wrap the usual normal equations Schur trick | ||||
|     ///////////////////////////////////////////////////// | ||||
|   SchurRedBlackDiagTwoSolve(OperatorFunction<Field> &HermitianRBSolver)  : | ||||
|      _HermitianRBSolver(HermitianRBSolver)  | ||||
|     {  | ||||
|       CBfactorise=0; | ||||
|     }; | ||||
|  | ||||
|     template<class Matrix> | ||||
|       void operator() (Matrix & _Matrix,const Field &in, Field &out){ | ||||
|  | ||||
|       // FIXME CGdiagonalMee not implemented virtual function | ||||
|       // FIXME use CBfactorise to control schur decomp | ||||
|       GridBase *grid = _Matrix.RedBlackGrid(); | ||||
|       GridBase *fgrid= _Matrix.Grid(); | ||||
|  | ||||
|       SchurDiagTwoOperator<Matrix,Field> _HermOpEO(_Matrix); | ||||
|   | ||||
|       Field src_e(grid); | ||||
|       Field src_o(grid); | ||||
|       Field sol_e(grid); | ||||
|       Field sol_o(grid); | ||||
|       Field   tmp(grid); | ||||
|       Field  Mtmp(grid); | ||||
|       Field resid(fgrid); | ||||
|  | ||||
|       pickCheckerboard(Even,src_e,in); | ||||
|       pickCheckerboard(Odd ,src_o,in); | ||||
|       pickCheckerboard(Even,sol_e,out); | ||||
|       pickCheckerboard(Odd ,sol_o,out); | ||||
|      | ||||
|       ///////////////////////////////////////////////////// | ||||
|       // src_o = Mdag * (source_o - Moe MeeInv source_e) | ||||
|       ///////////////////////////////////////////////////// | ||||
|       _Matrix.MooeeInv(src_e,tmp);     assert(  tmp.checkerboard ==Even); | ||||
|       _Matrix.Meooe   (tmp,Mtmp);      assert( Mtmp.checkerboard ==Odd);      | ||||
|       tmp=src_o-Mtmp;                  assert(  tmp.checkerboard ==Odd);      | ||||
|  | ||||
|       // get the right MpcDag | ||||
|       _HermOpEO.MpcDag(tmp,src_o);     assert(src_o.checkerboard ==Odd);        | ||||
|  | ||||
|       ////////////////////////////////////////////////////////////// | ||||
|       // Call the red-black solver | ||||
|       ////////////////////////////////////////////////////////////// | ||||
|       std::cout<<GridLogMessage << "SchurRedBlack solver calling the MpcDagMp solver" <<std::endl; | ||||
| //      _HermitianRBSolver(_HermOpEO,src_o,sol_o);  assert(sol_o.checkerboard==Odd); | ||||
|       _HermitianRBSolver(_HermOpEO,src_o,tmp);  assert(tmp.checkerboard==Odd); | ||||
|       _Matrix.MooeeInv(tmp,sol_o);        assert(  sol_o.checkerboard   ==Odd); | ||||
|  | ||||
|       /////////////////////////////////////////////////// | ||||
|       // sol_e = M_ee^-1 * ( src_e - Meo sol_o )... | ||||
|       /////////////////////////////////////////////////// | ||||
|       _Matrix.Meooe(sol_o,tmp);        assert(  tmp.checkerboard   ==Even); | ||||
|       src_e = src_e-tmp;               assert(  src_e.checkerboard ==Even); | ||||
|       _Matrix.MooeeInv(src_e,sol_e);   assert(  sol_e.checkerboard ==Even); | ||||
|       | ||||
|       setCheckerboard(out,sol_e); assert(  sol_e.checkerboard ==Even); | ||||
|       setCheckerboard(out,sol_o); assert(  sol_o.checkerboard ==Odd ); | ||||
|  | ||||
|       // Verify the unprec residual | ||||
|       _Matrix.M(out,resid);  | ||||
|       resid = resid-in; | ||||
|       RealD ns = norm2(in); | ||||
|       RealD nr = norm2(resid); | ||||
|  | ||||
|       std::cout<<GridLogMessage << "SchurRedBlackDiagTwoKappa solver true unprec resid "<< std::sqrt(nr/ns) <<" nr "<< nr <<" ns "<<ns << std::endl; | ||||
|     }      | ||||
|   }; | ||||
| #endif | ||||
| namespace QCD{ | ||||
|     // | ||||
|     // Determinant is det of middle factor | ||||
|     // This assumes Mee is indept of U. | ||||
|     // | ||||
|     // | ||||
|     template<class Impl> | ||||
|     class SchurDifferentiableDiagTwo:  public SchurDiagTwoOperator<FermionOperator<Impl>,typename Impl::FermionField>  | ||||
|       { | ||||
|       public: | ||||
|       INHERIT_IMPL_TYPES(Impl); | ||||
|  | ||||
|  	typedef FermionOperator<Impl> Matrix; | ||||
|  | ||||
| 	SchurDifferentiableDiagTwo (Matrix &Mat) : SchurDiagTwoOperator<Matrix,FermionField>(Mat) {}; | ||||
|     }; | ||||
| #if 0 | ||||
|     template<class Impl> | ||||
|     class SchurDifferentiableDiagTwoKappa :  public SchurDiagTwoKappaOperator<FermionOperator<Impl>,typename Impl::FermionField>  | ||||
|       { | ||||
|       public: | ||||
|       INHERIT_IMPL_TYPES(Impl); | ||||
|  | ||||
|  	typedef FermionOperator<Impl> Matrix; | ||||
|  | ||||
| 	SchurDifferentiableDiagTwoKappa (Matrix &Mat) : SchurDiagTwoKappaOperator<Matrix,FermionField>(Mat) {}; | ||||
|     }; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif | ||||
| #endif | ||||
|   | ||||
| @@ -140,6 +140,7 @@ namespace Grid{ | ||||
|  | ||||
|     }; | ||||
|  | ||||
|  | ||||
|   } | ||||
| } | ||||
| #endif | ||||
|   | ||||
| @@ -50,6 +50,7 @@ GridCartesian *SpaceTimeGrid::makeFourDimDWFGrid(const std::vector<int> & latt,c | ||||
| GridCartesian         *SpaceTimeGrid::makeFiveDimGrid(int Ls,const GridCartesian *FourDimGrid) | ||||
| { | ||||
|   int N4=FourDimGrid->_ndimension; | ||||
|   assert(N4==4); | ||||
|  | ||||
|   std::vector<int> latt5(1,Ls); | ||||
|   std::vector<int> simd5(1,1); | ||||
|   | ||||
| @@ -18,6 +18,10 @@ namespace Grid{ | ||||
|  | ||||
|     static inline void IndexFromCoor (const std::vector<int>& coor,int &index,const std::vector<int> &dims){ | ||||
|       int nd=dims.size(); | ||||
|       if(nd > coor.size())  { | ||||
| 	std::cout<< "coor.size "<<coor.size()<<" >dims.size "<<dims.size()<<std::endl;  | ||||
| 	assert(0); | ||||
| 	} | ||||
|       int stride=1; | ||||
|       index=0; | ||||
|       for(int d=0;d<nd;d++){ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user