#ifndef BFM_KRY4D_H #define BFM_KRY4D_H #include "Krylov.h" #include #include #include #include #include #include #include #include #include namespace BFM_Krylov{ //#include "dwf_4d.h" /** A 4d eigensolver. **/ template class Krylov_4d : public Krylov{ public: bfmDwf4d dop4d; bfm_qdp dop5d; int total_inner; int fivecount; LatticeFermion tmp_lf; SpinMatrix ident, Gamma5, Pp, Pm; Krylov_4d(bfm_qdp &dwf) : Krylov(dwf){this->prec = 0; this->prectype = 1;} ~Krylov_4d(){dop4d.end();dop5d.end();} void eigs_to_qdp( multi1d &con_vecs, multi1d &con_vals ); protected: void init(); void four_to_five(Fermion_t input[2], Fermion_t result5d[2]); void five_to_four(Fermion_t input5d[2], Fermion_t result[2], int sgn); void dwf_multiply(bfm_fermion input, bfm_fermion &result, bool dagger, int sgn); virtual void dwf_multiply(bfm_fermion input, bfm_fermion &result); virtual void herm_mult(Fermion_t input[2], bfm_fermion &result); }; template void Krylov_4d::eigs_to_qdp( multi1d &con_vecs, multi1d &con_vals ){ int Nev = this->evals.size(); con_vecs.resize(Nev); con_vals.resize(Nev); for(int i = 0; ievals[i]; this->bfm_to_qdp(this->bq[i], con_vecs[i]); } } template void Krylov_4d::init(){ if(!this->initialized){ this->Krylov_init(); QDPIO::cout << "Krylov4d: Initialising effective 5d DWF." << endl; //this->dwfa.solver = DWFrb4d; this->dwfa.precon_5d = this->prectype; this->dwfa.Ls = this->Ls; this->dwfa.residual = this->conv; dop5d.init(this->dwfa); #pragma omp parallel { omp_set_num_threads(dop5d.nthread); #pragma omp for for(int i=0;itmp = dop5d.threadedAllocFermion(); }} QDPIO::cout << "Krylov4d: Initialising 4d DWF for linalg" << endl; //this->dwfa.solver = HtCayleyTanh; this->dwfa.precon_5d = 0; this->dwfa.Ls = 1; this->dop.init(this->dwfa); total_inner = 0; ///4d initialize QDPIO::cout << "Krylov4d: Initialising effective 4d DWF object." << endl; //dop4d.init(toDouble(this->mq),toDouble(this->M5),(int)this->Ls,this->u, this->dwfa.residual); dop4d.init(this->dwfa.solver,toDouble(this->mq),toDouble(this->M5),(int)this->Ls,this->u, this->dwfa.residual, this->dwfa.max_iter); this->bq.resize(this->M); for(int m=0;mM;m++){this->init_fermion(this->bq[m]);} this->init_fermion(this->tmp1); this->init_fermion(this->tmp2); //if(!this->cont && !this->refine){ QDPIO::cout << "Krylov4d: Starting from scratch." << endl; LatticeFermion st; //gaussian(st); Fermion of = zero; SpinVector tspin = zero; Complex cno = cmplx(Real(1),Real(0)); for(int spn=0;spnqdp_to_bfm(st,this->bq[0]); double norm = sqrt( this->axpy_norm(this->bq[0],0.0,this->bq[0],this->bq[0]) ); this->axpby(this->bq[0], 1.0/norm, this->bq[0], 0.0, this->bq[0]); //} int sizebf; if(this->kr == lan){sizebf = 1;} //else if(this->kr == arn){sizebf = this->M;} this->bf.resize(sizebf); for(int i=0; i< sizebf; i++){ this->init_fermion(this->bf[i]); this->zero_fermion(this->bf[i]); } this->initialized=true; fivecount = 0; } } template void Krylov_4d::four_to_five(Fermion_t input[2], Fermion_t result5d[2]){ #pragma omp parallel { omp_set_num_threads(dop5d.nthread); #pragma omp for for(int i=0;idop.node_latt[3];x[3]++ ) { for ( x[2]=0; x[2]dop.node_latt[2];x[2]++ ) { for ( x[1]=0; x[1]dop.node_latt[1];x[1]++ ) { for ( x[0]=0; x[0]dop.node_latt[0];x[0]++ ) { sp = 0; site = x[0]+x[1]+x[2]+x[3]; cb4 = ((site)&0x1); cb5 = ((site+sp)&0x1); for ( int co=Nspinco/2;codop.bagel_idx(x,reim,co,Nspinco,1); b5[b5idx] = b[bidx]; }} sp = this->Ls - 1; cb4 = ((site)&0x1); cb5 = ((site+sp)&0x1); for ( int co=0;codop.bagel_idx(x,reim,co,Nspinco,1); b5[b5idx] = b[bidx]; }} }}}} } template void Krylov_4d::five_to_four(Fermion_t input5d[2], Fermion_t result[2], int sgn){ int x[4]; int Nspinco=12; int site, cb4, cb5; int sp, b5idx, bidx; S * b5; S * b; this->axpby(this->tmp1,0.0,this->tmp1,0.0,this->tmp1); this->axpby(this->tmp2,0.0,this->tmp2,0.0,this->tmp2); for ( x[3]=0; x[3]dop.node_latt[3];x[3]++ ) { for ( x[2]=0; x[2]dop.node_latt[2];x[2]++ ) { for ( x[1]=0; x[1]dop.node_latt[1];x[1]++ ) { for ( x[0]=0; x[0]dop.node_latt[0];x[0]++ ) { sp = 0; site = x[0]+x[1]+x[2]+x[3]; cb4 = ((site)&0x1); cb5 = ((site+sp)&0x1); for ( int co=Nspinco/2;codop.bagel_idx(x,reim,co,Nspinco,1); b[bidx] = sgn*b5[b5idx]; }} sp = this->Ls - 1; cb4 = ((site)&0x1); cb5 = ((site+sp)&0x1); for ( int co=0;codop.bagel_idx(x,reim,co,Nspinco,1); b[bidx] = b5[b5idx]; }} }}}} } template void Krylov_4d::dwf_multiply(bfm_fermion input, bfm_fermion &result, bool dagger, int sgn){ /* Fermion_t five[2], five_res[2]; #pragma omp parallel { omp_set_num_threads(dop5d.nthread); #pragma omp for for(int i=0;imvprod++; five_to_four(five_res, result, sgn); #pragma omp parallel { omp_set_num_threads(dop5d.nthread); #pragma omp for for(int i=0;ibfm_to_qdp(input,in); dop4d.Munprec(in,res,dagger); if(sgn==-1){ Gamma G5(15); SpinMatrix ident = Real(1.0); SpinMatrix Gamma5 = (G5 * ident); res = Gamma5 * res; } this->qdp_to_bfm(res,result); } template void Krylov_4d::dwf_multiply(bfm_fermion input, bfm_fermion &result){ bool dagger = false; if(this->D == DDAG){ dagger = true;} dwf_multiply(input, result, dagger, 1); } template void Krylov_4d::herm_mult(Fermion_t input[2], bfm_fermion &result){ if(this->D == G5D){ dwf_multiply(input, result, false, -1); } else if(this->D == DDAGD){ bfm_fermion Dq; this->init_fermion(Dq); dwf_multiply(input, Dq, false, 1); dwf_multiply(Dq, result, true, 1); this->free_fermion(Dq); } else{ QDPIO::cerr << "Don't know what to do with that operator" << endl; exit(1); } } template class Lanczos_4d : public Krylov_4d{ public: Lanczos_4d(bfm_qdp &dwf) : Krylov_4d(dwf){this->kr = lan;} void Initial_State(multi1d Eigs, multi1d val){ this->init(); if(this->cont){ QDPIO::cout << "Lanczos4d: continue " << this->bq.size() << endl; for(int i=0;iqdp_to_bfm(Eigs[i],this->bq[i]); this->H( this->Chebyshev( toDouble(real(val[i]) )) , i, i); } std::vector tevals(Eigs.size()); std::vector > tevecs(Eigs.size()); this->TestConv(Eigs.size(), tevals, tevecs); LatticeFermion tmp; gaussian(tmp); this->qdp_to_bfm(tmp,this->bf[0]); this->Gram(this->bf[0],this->bq,Eigs.size()); } else if(this->refine){ QDPIO::cout << "Lanczos4d: refining " << endl; LatticeFermion gg; gg = Eigs[0]; for(int i=1;iqdp_to_bfm(gg,this->bq[0]); } } }; /** An Arnoldi eigensolver. **/ /*template class Arnoldi_4d : public Krylov_4d, T, complex >{ public: Arnoldi_4d(bfm_qdp dwf, EigenDescr Ed, eigentype c, multi1d UU, multi1d Eigs, multi1d val) : Krylov_4d, T, complex >(dwf, Ed, c, UU, Eigs, val){ this->kr = arn; this->bf.resize(this->M); for(int i=0;iM;i++)this->init_fermion(this->bf[i]); } };*/ } #endif