#ifndef BFM_MATRIX_H #define BFM_MATRIX_H #include #include //#include //#include #include #include #include #include #include #include #include #include #include #include #define NUM_BFM_THREADS (64) namespace BFM_Krylov{ typedef Fermion_t bfm_fermion [2]; /** Do complex stuff to floats/doubles **/ inline float conj(float z){return z;} static float real(float z){return z;} static float imag(float z){return 0;} inline double conj(double z){return z;} static double real(double z){return z;} static double imag(double z){return 0;} /** Chroma complex to C++ complex(double) **/ template std::complex toComplex(QDP::Complex z){return std::complex(toDouble(real(z) ) , toDouble(imag(z) ) ); } template T toComplex(Real z){return (T)toDouble(z); } /** C++ complex(double) to Chroma complex **/ template QDP::Complex toComplex(T z){return cmplx(Real(real(z) ) , Real(imag(z) ) ); } /** Sign function **/ template T sign(T p){return ( p/abs(p) );} /** ***************************************** * * * Complex Vector operations * * * ***************************************** **/ /**Conj of a vector **/ template std::vector conj(const std::vector &p){ std::vector q(p.size()); for(int i=0;i T norm(const std::vector &p){ T sum = 0; for(int i=0;i T norm2(const std::vector &p){ T sum = 0; for(int i=0;i T trace(const std::vector &p){ T sum = 0; for(int i=0;i void fill(std::vector &p, const T c){ for(int i=0;i void normalize(std::vector &p){ T m = norm(p); if( abs(m) > 0.0) for(int i=0;i void print(const std::vector &p, const int w){ using namespace std; cout << fixed << setprecision(w) << setw(w) << "{ "; for(int i=0;i void print(const std::vector &p){ print(p,3); } /** print components of a vector of vectors in mathematica readable (matrix) form **/ template void print(const std::vector< std::vector > &Q){ using namespace std; int N = Q.size(); cout << fixed << setprecision(14) << setw(14) << "{ "; for(int i = 0;i void printSimpleReal(const std::vector< std::vector > &Q){ using namespace std; int N = Q.size(); cout << fixed << setprecision(3) << scientific; for(int i = 0;i std::vector times(std::vector p, const U s){ for(int i=0;i std::vector times(const U s, std::vector p){ for(int i=0;i T inner(const std::vector &a, const std::vector &b){ T m = 0.; for(int i=0;i std::vector add(const std::vector &a, const std::vector &b){ std::vector m(a.size()); for(int i=0;i std::vector sub(const std::vector &a, const std::vector &b){ std::vector m(a.size()); for(int i=0;i class Matrix { T* v; public: int dim; /// dimension void alloc_matrix(){ v = (T*)malloc(dim*dim*sizeof(T)); } void free_matrix(){ if(v != NULL) free(v); v = NULL; } /**Default**/ Matrix(void): v(NULL){ dim=0; } /** Construct new matrix unspecified entries**/ Matrix(const int d){ dim = d; alloc_matrix(); } Matrix(const Matrix &r): dim(r.dim){ alloc_matrix(); memcpy(v, r.v, dim*dim*sizeof(T)); } /** Construct new matrix entries all = val**/ Matrix(const int d, const T val){ dim = d; alloc_matrix(); if(val == 0.0) memset(v, 0, dim*dim*sizeof(T)); for(int i=0;i > &B){ dim = B.size(); alloc_matrix(); for(int i = 0; i x, const int i, const int j){ v[i+dim*j] = real(x); } /** Return value at position i, j **/ inline T operator() (const int i, const int j) const{ return v[i+dim*j]; } inline T& operator() (const int i, const int j){ return v[i+dim*j]; } /** Fill matricies with the value x **/ void Fill(const T x){ for(int i=0;i ( " < Transpose(){ Matrix C(dim); for(int i=0;i Hermitian() const{ Matrix C(dim); for(int i=0;i diag() const{ std::vector d(dim); for(int i=0;i LeftMult(const std::vector &B) const{ std::vector C(dim); for(int j=0;j inv_diag() const{ std::vector d(dim); for(int i=0;i operator+ (const Matrix &B) const{ Matrix C(dim); for(int i=0;i operator- (const Matrix &B) const{ Matrix C(dim); for(int i=0;i operator* (const T c) const{ Matrix C(dim); for(int i=0;i operator* (const Matrix &B) const{ Matrix C(dim); for(int i=0;i operator* (const std::vector &B){ std::vector C(dim); for(int i=0;i& operator=(const Matrix& B){ if(dim != B.dim){ free_matrix(); dim = B.dim; alloc_matrix(); } memcpy(v, B.v, dim*dim*sizeof(T)); return (*this); } /** Some version of Matrix norm **/ inline T Norm() const{ T norm = 0; for(int i=0;i abs(ld) ){ld = cf;} } return ld; } /** Look for entries on the leading subdiagonal that are smaller than 'small' **/ template int Chop_subdiag(const T norm, const int offset, const U small){ for(int l = dim - 1 - offset; l >= 1; l--){ if((U)abs( (*this)(l,l - 1)) < (U)small){ (*this)(l,l-1)=(U)0.0; return l; } } return 0; } /** Look for entries on the leading subdiagonal that are smaller than 'small' **/ template int Chop_symm_subdiag(const T norm, const int offset, const U small){ for(int l = dim - 1 - offset; l >= 1; l--){ if((U)abs( (*this)(l,l - 1) ) < (U)small){ (*this)(l,l - 1) = (U)0.0; (*this)(l - 1,l) = (U)0.0; return l; } } return 0; } /**Assign a submatrix to a larger one**/ void AssignSubMtx(const int row_st, const int row_end, const int col_st, const int col_end, const Matrix &S){ for(int i = row_st; i GetSubMtx(const int row_st, const int row_end, const int col_st, const int col_end) const{ Matrix H(row_end - row_st); if( (row_end - row_st) == (col_end - col_st) ){ for(int i = row_st; i > &S){ for(int i = row_st; i > GetSubMtxVec(const int row_st, const int row_end, const int col_st, const int col_end) const{ std::vector< std::vector > H(col_end - col_st); for(int i = col_st; i &B){ T C = 0; for(int i=0;i std::vector< std::vector > times(const std::vector< std::vector > &Q, const Matrix &R, const int M){ int N = Q[0].size(); std::vector > TMP(M); T sum; for(int i = 0;i std::vector< std::vector > times(const Matrix &R, const std::vector< std::vector > &Q, const int M){ int N = Q.size(); std::vector > TMP(N); T sum; for(int i = 0;i std::vector times(const std::vector &Q, const Matrix &R){ int N = Q.size(); std::vector TMP(N); T sum; for(int i = 0;i std::vector times(const std::vector< std::vector > &Q, const std::vector &R){ int N = Q[0].size(); int M = R.size(); std::vector S(N);T sum = 0; for(int i=0;i std::vector > times(const std::vector< std::vector > &Q, const std::vector< std::vector > &R){ int N = Q[0].size(); int M = Q.size(); int P = R.size(); std::vector< std::vector > S(P);T sum = 0; for(int i=0;i void Gram(std::vector > &q){ int M = q.size(); for(int j=0;j void CG_Matrix(const Matrix &A, const std::vector &source, std::vector &solution){ int N = A.dim; std::vector r(N), d(N), q(N), b(N), md(N); T delta_new, delta_old, delta_0, alpha, beta; int i = 0; Matrix AH(N); AH = A.Hermitian(); //this->D = DDAG_5D; //this->dwf_multiply(source, b); //this->axpy(solution, 0.0, b, b ); b = AH*source; solution = b; r = A*solution; r = AH*r; //this->D = DDAGD_5D; //this->herm_mult(solution, r); //delta_new = this->axpy_norm(r, -1.0, r, b ); r = sub(b,r); delta_new = norm2(r); delta_0 = delta_new; //this->axpy(d, 0.0, r, r ); d = r; int imax = 10000; while(i < imax && abs(sqrt(delta_new)) > (10e-8) ){ /*this->D = D_5D; this->dwf_multiply(d, md);*/ md = A*d; //alpha = this->axpy_norm(md,0,md,md); alpha = norm2(md); /*this->D = DDAG_5D; this->dwf_multiply(md, q);*/ q = AH*md; alpha = delta_new/alpha; //this->axpy(solution, alpha, d, solution); solution = add(solution, times(alpha,d) ); //beta = this->axpy_norm(r, -1.0*alpha, q, r); r = add(r, times(q,-1.0*alpha) ); beta = norm2(r); delta_old = delta_new; delta_new = beta; beta = delta_new/delta_old; //this->axpy(d, beta, d, r); d = add(r, times(beta,d) ); i++; } QDPIO::cout << "Matrix::Unpreconditioned CG converged in " << i << " iterations" << std::endl; /*this->D = D_5D; dwf_multiply(solution,r); */ r = A*solution; double diff = abs(norm( sub(r, source) ) ); QDPIO::cout << "Matrix::True residual = " << (diff) << std::endl; } static void Gram(LatticeFermion &r, multi1d &q, int N){ for(int i=0;i &q){ int N = q.size(); for(int i=0;i &q){ int M = q.size(); for(int j=0;j &q){ int M = q.size(); for(int j=0;j &q, const int M){ for(int j=0;j &q, const int M){ for(int j=0;j q Q template void times(multi1d &q, Matrix &Q){ multi1d S( q.size() ); for(int j=0;j q Q template void times(multi1d &q, const Matrix &Q, const int N){ multi1d S( N ); for(int j=0;j