diff --git a/davidson.h b/davidson.h index b1c5d0c..21669a3 100644 --- a/davidson.h +++ b/davidson.h @@ -33,7 +33,7 @@ namespace LA { //Note that for efficiency in a direct CI case the diagonalof() should cache its result -//@@@should work for complex hermitian-only too, but was not tested yet (maybe somwhere complex conjugation will have to be added) +//works for complex hermitian-only too, but does not converge sowell for more than 1 root //@@@ for large krylov spaces >200 it can occur 'convergence problem in sygv/syev in diagonalize()' //@@@options: left eigenvectors by matrix transpose, overridesymmetric (for nrmat) //@@@small matrix gdiagonalize - shift complex roots up (option to gdiagonalize?) @@ -158,12 +158,19 @@ else typename LA_traits::normtype eival_n=r[nroot]; oldnroot=nroot; typename LA_traits::normtype test=std::abs(smallV(krylovsize,nroot)); +//std::cout <<"NROOT = "<eps) nroot=std::min(nroot,iroot); + if(test>eps) nroot=std::min(nroot,iroot); //return to previous root if(verbose && iroot<=std::max(oldnroot,nroot)) { std::cout <<"Davidson: iter="<::normtype vnorm2; if(!incore) s0->get(vec2,j); do { - T ab = vec1*(incore?v0[j]:vec2) /smallS(j,j); + // For COMPLEX the order matters, the first one gets conjuagted, changed vec1 to the right! + T ab = (incore?v0[j]:vec2)*vec1 /smallS(j,j); vec1.axpy(-ab,incore?v0[j]:vec2); vnorm2 = vec1.norm(); if(vnorm2==0) diff --git a/t.cc b/t.cc index b5f17c5..5e65b65 100644 --- a/t.cc +++ b/t.cc @@ -1137,7 +1137,7 @@ if(0) { int n,m; cin>>n >>m; -NRSMat a(n,n); +NRSMat a(n); NRVec rr(n); for(int i=0;i > r(m); +NRVec > *eivecs = new NRVec >[m]; +davidson(a,r,eivecs,NULL,m,true,1e-6,true,10*n,n*10); + +cout <<"Davidson energies " < &a, const char trans, const T alpha, const NRVec &x); void gemv(const T beta, const NRSMat &a, const char trans /**< just for compatibility reasons */, const T alpha, const NRVec &x); @@ -1073,10 +1073,25 @@ inline const T NRVec::operator*(const NRVec &rhs) const { NOT_GPU(rhs); T dot(0); - for(register int i=0; i::is_complex()) for(register int i=0; i::conjugate(v[i])*rhs.v[i]; + else for(register int i=0; i +inline const T NRVec::dot(const T *a, const int stride , bool conjugate) const +{ + NOT_GPU(*this); + T dot(0); + if(LA_traits::is_complex() && conjugate) for(register int i=0; i::conjugate(v[i])*a[i*stride]; + else for(register int i=0; i NRVec >::operator*(const * @return \f$\sum_{i=1}^N\vec{x}_{i}\cdot y_{\mathrm{stride}\cdot(i-1) + 1}\f$ ******************************************************************************/ template<> -inline const double NRVec::dot(const double *y, const int stride) const { +inline const double NRVec::dot(const double *y, const int stride, bool conjugate) const { NOT_GPU(*this); - return cblas_ddot(nn, y, stride, v, 1); + return cblas_ddot(nn,v, 1,y,stride); } /***************************************************************************//** @@ -1813,10 +1828,11 @@ inline const double NRVec::dot(const double *y, const int stride) const * @return \f$\sum_{i=1}^N\vec{x}_{i}\cdot \overbar{y_{\mathrm{stride}\cdot(i-1) + 1}}\f$ ******************************************************************************/ template<> -inline const std::complex NRVec >::dot(const std::complex *y, const int stride) const { +inline const std::complex NRVec >::dot(const std::complex *y, const int stride, bool conjugate) const { std::complex dot; NOT_GPU(*this); - cblas_zdotc_sub(nn, y, stride, v, 1, &dot); + if(conjugate) cblas_zdotc_sub(nn, v,1,y, stride, &dot); + else cblas_zdotc_sub(nn, v,1,y, stride, &dot); return dot; }