diff --git a/davidson.h b/davidson.h index 9adfbc8..5e46254 100644 --- a/davidson.h +++ b/davidson.h @@ -1,9 +1,14 @@ +#include "vec.h" +#include "smat.h" +#include "mat.h" +#include "sparsemat.h" +#include "nonclass.h" //Davidson diagonalization of real symmetric matrix -//matrix can be any class which provides nrows(), diagonalof() and operator*(const NRVec) methods +//matrix can be any class which has nrows(), ncols(), diagonalof() and NRVec::gemv() available //does not even have to be explicitly stored - direct CI //n<0 highest eigenvalues, n>0 lowest eigenvalues -template -extern void davidson(const matrix &a, NRVec *vecs /*input-output*/, T *vals, const int n=1, const double eps=1e-10); +export template +extern void davidson(const Matrix &bigmat, NRVec *eivecs /*input-output*/, NRVec &eivals, int nroots=1, const double accur=1e-6, int nits=50, const int ndvdmx = 500, const bool incore=1); diff --git a/mat.cc b/mat.cc index bafef93..895a04d 100644 --- a/mat.cc +++ b/mat.cc @@ -34,6 +34,25 @@ NRMat & NRMat::operator=(const T &a) +//get diagonal; for compatibility with large matrices do not return newly created object +template +void NRMat::diagonalof(NRVec &r) const +{ +#ifdef DEBUG + if (nn != mm) laerror("diagonalof() non-square matrix"); + if (r.size() != nn) laerror("diagonalof() incompatible vector"); +#endif + +#ifdef MATPTR + for (int i=0; i< nn; i++) r[i] = v[i][i]; +#else + {int i,j; for (i=j=0; j< nn; ++j, i+=nn+1) r[j] = v[i];} +#endif + +} + + + // M += a template NRMat & NRMat::operator+=(const T &a) @@ -750,7 +769,7 @@ INSTANTIZE(int) INSTANTIZE(char) -export template +export template ostream& operator<<(ostream &s, const NRMat &x) { int i,j,n,m; @@ -764,7 +783,7 @@ ostream& operator<<(ostream &s, const NRMat &x) return s; } -export template +export template istream& operator>>(istream &s, NRMat &x) { int i,j,n,m; diff --git a/mat.h b/mat.h index c808c9d..ecd5310 100644 --- a/mat.h +++ b/mat.h @@ -58,6 +58,7 @@ public: const NRVec operator*(const NRVec &rhs) const; // Mat * Vec const NRVec rsum() const; //sum of rows const NRVec csum() const; //sum of columns + void diagonalof(NRVec &) const; //get diagonal inline T* operator[](const int i); //subscripting: pointer to row i inline const T* operator[](const int i) const; inline T& operator()(const int i, const int j); // (i,j) subscripts @@ -348,21 +349,22 @@ NRMat::~NRMat() template NRMat & NRMat::operator=(const NRMat &rhs) { - if (this == &rhs) return *this; - if (count) { - if (--(*count) ==0 ) { + if (this !=&rhs) + { + if (count) + if (--(*count) ==0 ) { #ifdef MATPTR delete[] (v[0]); #endif delete[] v; delete count; - } + } v = rhs.v; nn = rhs.nn; mm = rhs.mm; count = rhs.count; if (count) (*count)++; - } + } return *this; } diff --git a/nonclass.cc b/nonclass.cc index 4d7e16f..ef87064 100644 --- a/nonclass.cc +++ b/nonclass.cc @@ -186,12 +186,14 @@ extern "C" void FORNAME(dsyev)(const char *JOBZ, const char *UPLO, const int *N, // a will contain eigenvectors (columns if corder==1), w eigenvalues void diagonalize(NRMat &a, NRVec &w, const bool eivec, - const bool corder) + const bool corder, int n) { - int n = a.nrows(); - if (n != a.ncols()) laerror("diagonalize() call with non-square matrix"); + int m = a.nrows(); + if (m != a.ncols()) laerror("diagonalize() call with non-square matrix"); if (a.nrows() != w.size()) laerror("inconsistent dimension of eigenvalue vector in diagonalize()"); + if(n==0) n=m; + if(n<0||n>m) laerror("actual dimension out of range in diagonalize"); a.copyonwrite(); w.copyonwrite(); @@ -204,10 +206,10 @@ void diagonalize(NRMat &a, NRVec &w, const bool eivec, double WORKX; // First call is to determine size of workspace - FORNAME(dsyev)(&vectors, &U, &n, a, &n, w, (double *)&WORKX, &LWORK, &r ); + FORNAME(dsyev)(&vectors, &U, &n, a, &m, w, (double *)&WORKX, &LWORK, &r ); LWORK = (int)WORKX; double *WORK = new double[LWORK]; - FORNAME(dsyev)(&vectors, &U, &n, a, &n, w, WORK, &LWORK, &r ); + FORNAME(dsyev)(&vectors, &U, &n, a, &m, w, WORK, &LWORK, &r ); delete[] WORK; if (vectors == 'V' && corder) a.transposeme(); @@ -216,6 +218,7 @@ void diagonalize(NRMat &a, NRVec &w, const bool eivec, } + extern "C" void FORNAME(dspev)(const char *JOBZ, const char *UPLO, const int *N, double *AP, double *W, double *Z, const int *LDZ, double *WORK, int *INFO); @@ -526,18 +529,23 @@ double trace2(const NRSMat &a, const NRSMat &b, //generalized diagonalization, eivecs will be in columns of a -void gendiagonalize(NRMat &a, NRVec &w, NRMat b) +//counts with actual dimension smaller than allocated dimension + +void gendiagonalize(NRMat &a, NRVec &w, NRMat b, int n) { if(a.nrows()!=a.ncols() || a.nrows()!=w.size() || a.nrows()!=b.nrows() || b.nrows()!=b.ncols() ) laerror("incompatible Mats in gendiagonalize"); a.copyonwrite(); w.copyonwrite(); b.copyonwrite(); -int n=w.size(); -NRVec dl(n); +int m=w.size(); +NRVec dl(m); int i,j; double x; +if(n==0) n=m; +if(n<0 || n>m) laerror("actual dimension in gendiagonalize out of range"); + //transform the problem to usual diagonalization /* c @@ -620,7 +628,7 @@ for(j=0; j=0; --i)//component loop { - if(i &a, const NRMat &b, bool trb=0); \ extern T trace2(const NRSMat &a, const NRSMat &b, const bool diagscaled=0);\ extern void linear_solve(NRMat &a, NRMat *b, double *det=0); \ extern void linear_solve(NRSMat &a, NRMat *b, double *det=0); \ -extern void diagonalize(NRMat &a, NRVec &w, const bool eivec=1, const bool corder=1); \ +extern void diagonalize(NRMat &a, NRVec &w, const bool eivec=1, const bool corder=1, int n=0); \ extern void diagonalize(NRSMat &a, NRVec &w, NRMat *v, const bool corder=1);\ extern void singular_decomposition(NRMat &a, NRMat *u, NRVec &s,\ NRMat *v, const bool corder=1); @@ -72,7 +75,7 @@ extern NRMat matrixfunction(NRMat a, complex (*f)(const //generalized diagonalization of symmetric matrix with symmetric positive definite metric matrix b -extern void gendiagonalize(NRMat &a, NRVec &w, NRMat b); +extern void gendiagonalize(NRMat &a, NRVec &w, NRMat b, const int n=0); //functions on matrices inline NRMat sqrt(const NRSMat &a) { return matrixfunction(a,&sqrt); } @@ -98,3 +101,4 @@ const NRMat inverse(NRMat a, T *det=0) return result; } +#endif diff --git a/smat.cc b/smat.cc index b4ca579..1e04085 100644 --- a/smat.cc +++ b/smat.cc @@ -34,7 +34,7 @@ NRSMat::NRSMat(const NRMat &rhs) -// assing to diagonal +// assign to diagonal template NRSMat & NRSMat::operator=(const T &a) { @@ -43,6 +43,17 @@ NRSMat & NRSMat::operator=(const T &a) return *this; } +//get diagonal +template +void NRSMat::diagonalof(NRVec &r) const +{ +#ifdef DEBUG +if(r.size()!=nn) laerror("incompatible vector in diagonalof()"); +#endif + for (int i=0; i const NRSMat NRSMat::operator-() const @@ -71,7 +82,7 @@ void NRSMat::fprintf(FILE *file, const char *format, const int modulo) const } // read matrix from the file with specific format -template +template void NRSMat::fscanf(FILE *f, const char *format) { int n, m; @@ -268,7 +279,7 @@ void NRSMat< complex >::axpy(const complex alpha, } -export template +export template ostream& operator<<(ostream &s, const NRSMat &x) { int i,j,n; @@ -282,7 +293,7 @@ ostream& operator<<(ostream &s, const NRSMat &x) } -export template +export template istream& operator>>(istream &s, NRSMat &x) { int i,j,n,m; diff --git a/smat.h b/smat.h index 0d860a0..2b09cb4 100644 --- a/smat.h +++ b/smat.h @@ -43,6 +43,7 @@ public: const NRMat operator*(const NRMat &rhs) const; // SMat*Mat const T dot(const NRSMat &rhs) const; // Smat.Smat const NRVec operator*(const NRVec &rhs) const; + void diagonalof(NRVec &) const; //get diagonal inline const T& operator[](const int ij) const; inline T& operator[](const int ij); inline const T& operator()(const int i, const int j) const; diff --git a/sparsemat.cc b/sparsemat.cc index d29c601..80dd2f7 100644 --- a/sparsemat.cc +++ b/sparsemat.cc @@ -484,6 +484,24 @@ for(i=0;i +void SparseMat::diagonalof(NRVec &r) const +{ +#ifdef DEBUG +if(nn!=mm) laerror("diagonalof() non-square sparse matrix"); +#endif +matel *l=list; +r=(T)0; +while(l) + { + if(l->row == l->col) r[l->row]+= l->elem; + l= l->next; + } +} + + //constructor dense matrix from sparse export template NRMat::NRMat(const SparseMat &rhs) diff --git a/sparsemat.h b/sparsemat.h index e05acb7..34dbb93 100644 --- a/sparsemat.h +++ b/sparsemat.h @@ -1,3 +1,6 @@ +#ifndef _SPARSEMAT_H_ +#define _SPARSEMAT_H_ + //for vectors and dense matrices we shall need #include "la.h" @@ -85,6 +88,7 @@ public: inline const SparseMat operator-(const SparseMat &rhs) const {return SparseMat(*this) -= rhs;} //must not be symmetric+general const NRVec multiplyvector(const NRVec &rhs, const bool transp=0) const; //sparse matrix * dense vector optionally transposed inline const NRVec operator*(const NRVec &rhs) const {return multiplyvector(rhs);} //sparse matrix * dense vector + void diagonalof(NRVec &) const; //get diagonal const SparseMat operator*(const SparseMat &rhs) const; void gemm(const T beta, const SparseMat &a, const char transa, const SparseMat &b, const char transb, const T alpha);//this := alpha*op( A )*op( B ) + beta*this, if this is symemtric, only half will be added onto it const T dot(const SparseMat &rhs) const; //supervector dot product @@ -219,4 +223,4 @@ while(l) return *this; } - +#endif diff --git a/t.cc b/t.cc index 5504ec9..262ed7b 100644 --- a/t.cc +++ b/t.cc @@ -6,6 +6,7 @@ #include "sparsemat.h" #include "matexp.h" #include "fourindex.h" +#include "davidson.h" extern void test(const NRVec &x); @@ -489,7 +490,7 @@ for(int n=8; n<=1024*1024;n+=n) } } -if(1) +if(0) { int n; cin>>n; @@ -536,7 +537,7 @@ if(0) { const int n=3; NRMat a(n,n); -for(int i=0;i amat,bmat; +cin >>amat; +cin >>bmat; +NRVec v(amat.nrows()); +gendiagonalize(amat,v,bmat,2); +cout <>n >>m; +NRMat a(n,n); +NRVec rr(n); +for(int i=0;i aa=a; +cout < r(m); +NRVec *eivecs = new NRVec[m]; +davidson(a,eivecs,r,m); + +cout < *p = new NRVec[1000]; +NRVec q(10); q=1.; +p[500]|=q; +} diff --git a/vec.h b/vec.h index b2e0e88..1d5ea3d 100644 --- a/vec.h +++ b/vec.h @@ -521,7 +521,7 @@ void NRVec::resize(const int n) } -// assignmet with a physical copy +// assignmet with a physical (deep) copy template NRVec & NRVec::operator|=(const NRVec &rhs) {