#include #include // exit() #include #include #include #include #include #include // #include #include #include // read and write control flags, #include // close(). These are needed for io parts to // compile on PCs #include #include #include #include #include #include //YA #include #include #include #define VOLFMT QIO_VOLFMT CPS_START_NAMESPACE //eig_int_CG. by Qi Liu void invert_H_matrix(Rcomplex *data, int n) { int actualsize=n; if (actualsize <= 0) return; // sanity check if (actualsize == 1) {data[0]=1.0/data[0];return;} // must be of dimension >= 2 for (int i=1; i < actualsize; i++) data[i] /= data[0]; // normalize row 0 for (int i=1; i < actualsize; i++) { for (int j=i; j < actualsize; j++) { // do a column of L Rcomplex sum = 0.0; for (int k = 0; k < i; k++) sum += data[j*actualsize+k] * data[k*actualsize+i]; data[j*actualsize+i] -= sum; } if (i == actualsize-1) continue; for (int j=i+1; j < actualsize; j++) { // do a row of U Rcomplex sum = 0.0; for (int k = 0; k < i; k++) sum += data[i*actualsize+k]*data[k*actualsize+j]; data[i*actualsize+j] = (data[i*actualsize+j]-sum) / data[i*actualsize+i]; } } for ( int i = 0; i < actualsize; i++ ) // invert L for ( int j = i; j < actualsize; j++ ) { Rcomplex x = 1.0; if ( i != j ) { x = 0.0; for ( int k = i; k < j; k++ ) x -= data[j*actualsize+k]*data[k*actualsize+i]; } data[j*actualsize+i] = x / data[j*actualsize+j]; } for ( int i = 0; i < actualsize; i++ ) // invert U for ( int j = i; j < actualsize; j++ ) { if ( i == j ) continue; Rcomplex sum = 0.0; for ( int k = i; k < j; k++ ) sum += data[k*actualsize+j]*( (i==k) ? 1.0 : data[i*actualsize+k] ); data[i*actualsize+j] = -sum; } for ( int i = 0; i < actualsize; i++ ) // final inversion for ( int j = 0; j < actualsize; j++ ) { Rcomplex sum = 0.0; for ( int k = ((i>j)?i:j); k < actualsize; k++ ) sum += ((j==k)?1.0:data[j*actualsize+k])*data[k*actualsize+i]; data[j*actualsize+i] = sum; } } void QPropW::eig_Run(Vector **V, const int vec_len, Float *M, Float max_eig, const int nev, const int m, float **U, Rcomplex *H, const int max_def_len, int &def_len, const Float *restart, const int restart_len, const bool always_restart, const int do_rerun, const Float precision) { char *fname = "eig_Run()"; VRB.Func(cname, fname); // Set the node size of the full (non-checkerboarded) fermion field //---------------------------------------------------------------- //size_t f_size = GJP.VolNodeSites() * Lat.FsiteSize()/GJP.SnodeSites(); int iter; Float true_res; if(def_len>max_def_len) { VRB.Warn(cname,fname,"def_len>max_def_len, reset to equal"); def_len=max_def_len; } int Nspins = 4; // Number of spin components to be done // Flag set if sequential propagator int seq_src = ((SrcType()==PROT_U_SEQ)|| (SrcType()==PROT_D_SEQ)|| (SrcType()==MESSEQ) ); if (DoHalfFermion()) Nspins = 2; // does prop exist? Assume it does not. int do_cg = 1; /**************************************************************** The code below is temporarily isolated for purposes of merging with CPS main branch, 12/09/04, Oleg Loktik -------------------- Quarantine starts -------------------------- if (pfs_file_exists(Arg.file)){ // read data into prop RestoreQProp(Arg.file,PROP); // Only restores stuff into prop // multiply source by 1/2(1+gamma_t). If the propagator // on disk is half fermion it does nothing. Otherwise it gets // converted to the half fermion propagator. if (Arg.DoHalfFermion) for (int s(0);s0)low=(int *)smalloc(2*nev*sizeof(int)); Rcomplex *invH=(Rcomplex *)smalloc(max_def_len*max_def_len*sizeof(Rcomplex)); Vector *AU=(Vector *)fmalloc(cname,fname,"AU",vec_len * sizeof(Float)); Lattice& Lat = this->AlgLattice() ; for (int spn=0; spn < Nspins; spn++) for (int col=0; col < GJP.Colors(); col++) { // initial guess (Zero) sol.ZeroSource(); if(!do_rerun){ SetSource(src,spn,col); // store the source if (qp_arg.save_prop) { for(int index(0); index < GJP.VolNodeSites(); ++index) for(int mm(0); mm < 4; ++ mm) for(int cc(0); cc < GJP.Colors(); ++cc){ // now same ordering as propagator [volume][spin][color][solution_spin][solution_color][ReIm] *(save_source + 288*index + 72*mm + 24*cc + 6*spn + 2*col) = src[24*index + 6*mm + 2*cc]; *(save_source + 288*index + 72*mm + 24*cc + 6*spn + 2*col + 1) = src[24*index + 6*mm + 2*cc+1]; } } } else{ // rerun for(int index(0); index < GJP.VolNodeSites(); ++index){ WilsonMatrix *tmp_mat= (WilsonMatrix *) save_source+index; src.CopyWilsonMatSink(index, spn, col,*tmp_mat); } } if ((DoHalfFermion())&&(!seq_src)) // Rotate to chiral basis src.DiracToChiral(); // Get the prop VRB.Debug(cname,fname,"Before CG in QpropW.Run() \n"); //calculate invH from H (def_len*def_len matrix) if(def_len>0) { //initialize H if necessary if(nev == 0){ Vector *temp=(Vector *)fmalloc(cname,fname,"temp",vec_len * sizeof(Float)); DiracOpDwf dwf_aux(Lat, NULL, NULL, &(qp_arg.cg),CNV_FRM_NO); for(int i=0;i(&c_r, &c_i, U[j], (Float *)AU,vec_len); glb_sum_five(&c_r); glb_sum_five(&c_i); H[j*max_def_len+i]=Complex(c_r,c_i); } for(int j=0;jReDotProductGlbSum(AU,vec_len); } sfree(temp); } // Hinv for(int i=0;i0 && def_leni;j--) { if(M[low[j]]1e-30 && def_len=rank] to zero { //update H //U[def_len]->CopyVec(V[low[i]],vec_len); fvptr = (Float *)V[low[i]]; for(int ii=0;iiCompDotProductGlbSum(AU,vec_len); for(int j=0;j(&c_r, &c_i, U[j], (Float *)AU,vec_len); glb_sum_five(&c_r); glb_sum_five(&c_i); H[j*max_def_len+def_len]=Complex(c_r,c_i); } for(int j=0;jReDotProductGlbSum(AU,vec_len); def_len++; } } } //gauge fix solution FixSol(sol); if (StoreMidprop()) FixSol(midsol); // Collect solutions in propagator. LoadRow(spn,col,sol,midsol); if (DoHalfFermion()) {// copy spin 0 to spin 1 and spin 2 to spin 3 int spn2 = spn + 2; if (seq_src) { LoadRow(spn2,col,sol,midsol); } else { // Regular propagator zero the extra components src.ZeroSource(); LoadRow(spn2,col,src,src); } } if (common_arg->results != 0) { FILE *fp; if ((fp = Fopen((char *)common_arg->results, "a")) == NULL) { ERR.FileA(cname,fname, (char *)common_arg->results); } Fprintf(fp, "Cg iters = %d true residual = %e\n", iter, (Float)true_res); Fclose(fp); } } // End spin-color loop sfree(invH); sfree(AU); if(nev>0)sfree(low); // Rotate the source indices to Chiral basis if needed if ((DoHalfFermion())&&(!seq_src)) { for (int s=0;sresults != 0){ FILE *fp; if( (fp = Fopen((char *)common_arg->results, "a")) == NULL ) { ERR.FileA(cname,fname, (char *)common_arg->results); } Fprintf(fp,"Conserved Axial w_spect\n"); for(int t=0; tresults != 0){ FILE *fp1; if( (fp1 = Fopen((char *)common_arg->results, "a")) == NULL ) { ERR.FileA(cname,fname, (char *)common_arg->results); } Fprintf(fp1,"J5q Pion Contraction\n"); for(int t=0; t precision){ errCnt += 1.0; sumerr+=diff; VRB.Result(cname,fname,"mismatch propagator: index %i snk %i %i src %i %i\n %f: (%f,%f) <-> (%f,%f)\n", index, s_snk,c_snk,s_src,c_src, diff, tmp_calc.real(), tmp_calc.imag(), tmp_read.real(), tmp_read.imag() ); } } } glb_sum_five(&errCnt); glb_sum_five(&sumerr); Float averr=sumerr/errCnt; if( fabs(errCnt) > 0.){ VRB.Result(cname,fname," ReRun prop. with TOTAL NUMBER OF ERRORS: %f\n",errCnt); VRB.Result(cname,fname," Average error: %e\n",averr); VRB.Result(cname,fname," The precision is set at: %e\n",precision); } else { VRB.Result(cname,fname," ReRun prop. successfully!\n"); VRB.Result(cname,fname," The precision is set at: %e\n",precision); } } if (qp_arg.save_prop || do_rerun ) sfree(read_prop); } // Do conjugate gradient void QPropW::eig_CG(Vector **V, const int vec_len, Float *M, const int nev, const int m, float **U, Rcomplex *invH, const int def_len, const Float *restart,const int restart_len, FermionVectorTp& source, FermionVectorTp& sol, FermionVectorTp& midsol, int& iter, Float& true_res) { char *fname = "eig_CG(source&, sol&, midsol&, int&, Float&)"; VRB.Func(cname, fname); /* CgArg cg_arg; cg_arg.mass = 0.03; cg_arg.max_num_iter = 1000; cg_arg.stop_rsd = 1.0e-8; */ Lattice& Lat = AlgLattice(); // Set the node size of the full (non-checkerboarded) fermion field //---------------------------------------------------------------- int ls = GJP.SnodeSites(); int ls_glb = GJP.SnodeSites()*GJP.Snodes(); size_t f_size = GJP.VolNodeSites() * Lat.FsiteSize()/GJP.SnodeSites(); size_t f_size_5d = f_size * ls; // Do inversion //---------------------------------------------------------------- if (Lat.Fclass() == F_CLASS_DWF) { Vector *src_4d = (Vector*)source.data(); Vector *sol_4d = (Vector*)sol.data(); Vector *midsol_4d = (Vector*)midsol.data(); Vector *src_5d = (Vector*)smalloc(f_size_5d * sizeof(IFloat)); Vector *sol_5d = (Vector*)smalloc(f_size_5d * sizeof(IFloat)); if (src_5d == 0) ERR.Pointer(cname,fname, "src_5d"); VRB.Smalloc(cname,fname, "src_5d", src_5d, f_size_5d * sizeof(IFloat)); if (sol_5d == 0) ERR.Pointer(cname,fname, "sol_5d"); VRB.Smalloc(cname,fname, "sol_5d", sol_5d, f_size_5d * sizeof(IFloat)); //Get the lattice form the Alg base class Lattice& Lat = this->AlgLattice() ; Lat.Ffour2five(src_5d, src_4d, 0, ls_glb-1); Lat.Ffour2five(sol_5d, sol_4d, ls_glb-1, 0); iter = Lat.eig_FmatInv(V, vec_len, M, nev,m,U,invH, def_len, restart, restart_len, sol_5d, src_5d, &(qp_arg.cg), &true_res, CNV_FRM_YES, PRESERVE_NO); /**************************************************************** The code below is temporarily isolated for purposes of merging with CPS main branch, 12/09/04, Oleg Loktik -------------------- Quarantine starts -------------------------- iter = Lat.FmatInv4dSrc(sol_5d, src_5d, 0, ls_glb-1, &(Arg.cg), &true_res, CNV_FRM_YES, PRESERVE_NO); -------------------- End of quarantine -------------------------*/ //----------------------------------------------------------------- // TY Add Start if(qp_arg.save_ls_prop) for(int nls(0);nls