diff --git a/diis.h b/diis.h index 668a37c..6feb1bf 100644 --- a/diis.h +++ b/diis.h @@ -25,15 +25,15 @@ class DIIS public: DIIS(const int n, const bool core=1); ~DIIS(); - Te extrapolate(T &vec); //vec is input/output; returns square residual norm + typename LA_traits::normtype extrapolate(T &vec); //vec is input/output; returns square residual norm }; template -DIIS::DIIS(const int n, const bool core) : dim(n), incore(core), bmat(n+1,n+1) +DIIS::DIIS(const int n, const bool core) : dim(n), incore(core), bmat(n,n) { st=incore?NULL: new AuxStorage; stor= incore? new T[dim] : NULL; -bmat= (Te)0; for(int i=1; i<=n; ++i) bmat(0,i) = (Te)-1; +bmat= (Te)0; for(int i=1; i -typename DIIS::Te DIIS::extrapolate(T &vec) +typename LA_traits::normtype DIIS::extrapolate(T &vec) { //if dim exceeded, shift if(aktdim==dim) { cyclicshift=(cyclicshift+1)%dim; - for(int i=1; iput(vec,(aktdim-1+cyclicshift)%dim); -//calculate overlaps -bmat(aktdim,aktdim)= vec.dot(vec); -if(incore) - for(int i=1; i::normtype)1000000000; + +//calculate difference; +vec.copyonwrite(); +if(incore) vec -= stor[(aktdim-2+cyclicshift)%dim]; else { - T tmp=vec; //copy dimensions - for(int i=1; iget(tmp,(aktdim-2+cyclicshift)%dim); + vec -= tmp; + } + +//calculate overlaps of differences (if storage is cheap, they could rather be stored than recomputed) +typename LA_traits::normtype norm=vec.norm(); +bmat(aktdim-1,aktdim-1)= norm*norm; +if(incore) + for(int i=1; iget(tmp2,(0+cyclicshift)%dim); + for(int i=1; iget(tmp,(i+cyclicshift)%dim); + tmp2 -= tmp; + bmat(i,aktdim-1)= -vec.dot(tmp2); + tmp2=tmp; } } //prepare rhs-solution vector -NRVec rhs(dim+1); +NRVec rhs(dim); rhs= (Te)0; rhs[0]= (Te)-1; //solve for coefficients { NRSMat amat=bmat; -linear_solve(amat,rhs,NULL,aktdim+1); +linear_solve(amat,rhs,NULL,aktdim); } //build the new linear combination -vec.copyonwrite(); -vec *= rhs[aktdim]; +vec = (Te)0; if(incore) - for(int i=1; iget(tmp,(i+cyclicshift)%dim); vec.axpy(rhs[i],tmp); } } -return rhs[0]; +return norm; }