Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

eigen_wilson.C

Go to the documentation of this file.
00001 #include <config.h>
00002 
00003 CPS_START_NAMESPACE
00008 //--------------------------------------------------------------------
00009 //  CVS keywords
00010 //
00011 //  $Author: chulwoo $
00012 //  $Source: /space/cvs/cps/cps++/src/util/dirac_op/d_op_wilson_types/eigen_wilson.C,v $
00013 //  $State: Exp $
00014 //
00015 //--------------------------------------------------------------------
00016 /*  Compute the spectrol flow using the Ritz functional minimization */
00017 /*  routine, if desired in the Kalkreuter-Simma algorithm */
00018 
00019 /*  Compute low lying eigenvalues of the hermitian (but not pos. def.) */
00020 /*  matrix RitzEigMat using the Ritz functional minimization routine, */
00021 /*  if desired in the Kalkreuter-Simma algorithm */
00022 
00023 /*  psi         Eigenvectors                    (Modify) */
00024 /*  lambda_H    Eigenvalues                     (Write) */
00025 /*  valid_eig   flag for valid eigenvalues      (Write) */
00026 /*  eig_arg     Argument structure              (Read) */
00027 /*  NCG_tot     Total number of CG iter         (Return value) */
00028 
00029 /*  Parameters in eig_arg */
00030 /*  N_eig       Eigenvalue number               (Read) */
00031 /*  N_min       Minimal CG iterations           (Read) */
00032 /*  N_max       Maximal CG iterations           (Read) */
00033 /*  Kalk_Sim    Use Kalkreuter-Simma criterion  (Read) */
00034 /*  n_renorm    Renormalize every n_renorm iter.        (Read) */
00035 /*  N_KS_max    Max number of Kalkreuter-Simma iterations       (Read) */
00036 /*  RsdR_a      (absolute) residue              (Read) */
00037 /*  RsdR_r      (relative) residue              (Read) */
00038 /*  Rsdlam      relative accuracy of lambda     (Read) */
00039 /*  Cv_fact     "Convergence factor" required   (Read) */
00040 /*  n_KS        total number of Kalkreuter-Simma iterations     (Write) */
00041 /*  ProjApsiP   flag for projecting A.psi       (Read) */
00042 
00043 /*  n_valid     number of valid eigenvalues     (Write) */
00044 
00045 CPS_END_NAMESPACE
00046 #include <util/dirac_op.h>
00047 #include <util/lattice.h>
00048 #include <util/smalloc.h>
00049 #include <util/vector.h>
00050 #include <util/gjp.h>
00051 #include <comms/glb.h>
00052 #include <util/verbose.h>
00053 #include <util/error.h>
00054 #include <util/qcdio.h>
00055 #include <math.h>
00056 CPS_START_NAMESPACE
00057 void MatHermElements( DiracOpWilsonTypes * dirac_op,
00058                       Vector ** psi, int n_vec, int f_size, 
00059                       Float * diag, Complex * off_diag );
00060 
00061 inline void PrintDot(char *fname, char *vname, Vector *tmp, int f_size){
00062 //      printf("%s: %s=%e\n",fname,vname,tmp->ReDotProductGlbSum(tmp, f_size));
00063 }
00064 
00065 /*
00066   A normalised gram-shcmidt orthoganalisation the input vectors
00067   should be normalised
00068 */
00069 
00070 inline Float Norm( Vector* psi, int f_size )
00071 {
00072   Float norm( sqrt(psi->NormSqGlbSum(f_size)) );
00073 //  printf("Norm=%e\n",norm);
00074   psi->VecTimesEquFloat(1.0/norm,f_size);
00075   return norm;
00076 }
00077 
00078 Float GramSchmNorm( Vector* psi, 
00079                     Vector* vec, 
00080                     int f_size  )
00081 {
00082   const Complex xp(vec->CompDotProductGlbSum(psi, f_size));
00083   psi->CTimesV1PlusV2  (-xp, vec, psi, f_size);
00084   return Norm(psi,f_size); 
00085 }
00086 
00087 
00088 
00089 int DiracOpWilsonTypes::RitzEig(Vector **psi, Float lambda_H[], int valid_eig[], EigArg *eig_arg)
00090 {
00091   char *fname = "RitzEig(V**,V**,I)";
00092   VRB.Func(cname,fname);
00093 
00094 
00095   // Initialise constants
00096   const Float RsdR_a  ( eig_arg->RsdR_a    );
00097   const Float RsdR_r  ( eig_arg->RsdR_r    );
00098   const Float Rsdlam  ( eig_arg->Rsdlam    );
00099   const Float Cv_fact ( eig_arg->Cv_fact   );
00100   const int N_eig     ( eig_arg->N_eig     );
00101   const int N_min     ( eig_arg->N_min     );
00102   const int N_max     ( eig_arg->N_max     );
00103   const int n_renorm  ( eig_arg->n_renorm  );
00104   const int MaxCG     ( eig_arg->MaxCG     );
00105   const int ProjApsiP ( eig_arg->ProjApsiP );
00106 
00107   int Kalk_Sim ( eig_arg->Kalk_Sim  );
00108   int N_KS_max ( eig_arg->N_KS_max  );
00109 
00110  
00111 // Flash the LED and then turn it off
00112 //------------------------------------------------------------------
00113   VRB.LedFlash(cname,fname,3);
00114   VRB.LedOff(cname,fname);
00115   VRB.Func(cname,fname);
00116 
00117 
00118 // Print out input parameters
00119 //------------------------------------------------------------------
00120   VRB.Input(cname,fname,
00121             "mass = %g\n",IFloat(eig_arg->mass));
00122   VRB.Input(cname,fname,
00123             "N_eig = %d\n",N_eig);
00124 
00125 
00126 //------------------------------------------------------------------
00127 // Initializations
00128 //------------------------------------------------------------------
00129   // can't do a kal-sim if I only have one eigenvector
00130   if (N_eig == 1)    Kalk_Sim = 0;
00131 
00132   if (Kalk_Sim == 0)    N_KS_max = 0;
00133 
00134   // Determine machine accuracy
00135   Float acc = 2.0e-6;
00136   acc *= acc;
00137   Float rsdl_sq = Rsdlam * Rsdlam;
00138   rsdl_sq = (rsdl_sq > acc) ? rsdl_sq : acc;
00139   Float rsdl_zero = 10.0 * rsdl_sq;
00140 
00141 
00142 // Set the node checkerboard size of the fermion field
00143 //------------------------------------------------------------------
00144   const int f_size = RitzLatSize();
00145 
00146   // Local vars 
00147   Float lambda_t, del_lamb;
00148   int j, n, ij, NCG_tot, n_KS;
00149   int i;
00150   int n_jacob;
00151 
00152   
00153   Float * lambda = lambda_H;
00154 
00155    /*
00156     we are going to pass lambda^2 back to the calling function
00157     the calling function has lambda_H[N_eig...2N_eig-1] reserved so
00158     we let lambda_old point to lambda_H[N_eig], and lambda^2 will 
00159     be put there automatically
00160   */
00161 
00162   Float *lambda_old = & lambda_H[N_eig]; 
00163    
00164 // Set the node checkerboard size of the fermion field
00165 //------------------------------------------------------------------
00166   Complex *off_diag (0x0);
00167   if (N_eig > 1)
00168   {
00169     off_diag = (Complex *) smalloc(cname,fname, "off_diag", N_eig*(N_eig-1)/2 * sizeof(Complex));
00170 
00171     for(int i=0; i < N_eig*(N_eig-1)/2; ++i)
00172       off_diag[i] = 0.0;
00173   }
00174 
00175   NCG_tot = 0;
00176 
00177   /* Note: psi will be normalized in Ritz! */
00178 
00179   for(n=0; n < N_eig; ++n)
00180   {
00181     lambda_old[n] = 1.0;
00182     valid_eig[n] = 0;
00183   }
00184 
00185   del_lamb = 1.0;
00186 
00187   if (Kalk_Sim == 1)
00188     {
00189       /* while (del_lamb > Rsdlam) */
00190       for(n_KS = 1; n_KS <= N_KS_max && del_lamb > Rsdlam; n_KS++)
00191         {
00192           ij = 0;
00193           for(n = 1, i = 0; n <= N_eig; n++, i++)
00194             {
00195               /* 
00196                  call the ritz. This call will return a negative number
00197                  in the case of an error. In this case the only error is
00198                  hitting the max_cg, in which case it will return -1;
00199               */
00200               int ncnt =  Ritz(psi, n, lambda_t, RsdR_a, RsdR_r, Rsdlam, 0.0 /*rsdl_sq*/,
00201                                n_renorm, Kalk_Sim, N_min, N_max, Cv_fact, MaxCG,
00202                                ProjApsiP);
00203 
00204               // pass the error "up"
00205               if ( ncnt < 0 ) { if ( off_diag !=0x0 ) { sfree(off_diag); } ; return ncnt; }
00206 
00207               NCG_tot += ncnt;
00208               VRB.Result(cname,fname ,"PCNTINFO KS=%d n_eig=%d ncnt=%d\n", n_KS, n, ncnt);
00209 
00210               lambda[i] = lambda_t;
00211               VRB.Debug(cname,fname,"yes KS: lambda[%d] = %g\n",i,(IFloat)lambda[i]);
00212 
00213               Vector *tmp = (Vector *) smalloc(f_size * sizeof(Float));
00214               if(tmp == 0)
00215                 ERR.Pointer(cname,fname, "tmp");
00216               VRB.Smalloc(cname,fname, "tmp", tmp, f_size * sizeof(Float));
00217 
00218               RitzMat(tmp, psi[i]);
00219 
00220               for(j = 0; j < i; j++)
00221                 off_diag[ij++] = psi[j]->CompDotProductGlbSum(tmp, f_size);
00222 
00223               VRB.Sfree(cname,fname, "tmp", tmp);
00224               sfree(tmp);
00225             }
00226 
00227           n_jacob = Jacobi(psi, N_eig, lambda, off_diag, RsdR_a, 50);
00228 
00229           VRB.Result(cname, fname, "NCG_tot=%d\n", NCG_tot);
00230 
00231           for(i = 0; i < N_eig; i++)
00232             VRB.Result(cname,fname,"KS=%d: lambda[%d] = %g\n",n_KS,i,(IFloat)(lambda[i]));
00233 
00234           /*
00235           lambda_old[0] -= lambda[0];
00236           lambda_t = fabs(lambda_old[0]);
00237           if (lambda_t > rsdl_sq)
00238             {
00239               del_lamb = fabs(lambda_t / lambda[0]);
00240             }
00241           else
00242             del_lamb = 0.0;
00243           
00244           lambda_old[0] = lambda[0];
00245           for(i = 1; i < N_eig; i++)
00246             {
00247               lambda_old[i] -= lambda[i];
00248               lambda_t = fabs(lambda_old[i]);
00249               if (lambda_t > rsdl_sq)
00250                 {
00251                   lambda_t = fabs(lambda_t / lambda[i]);
00252                   if (lambda_t > del_lamb)
00253                     del_lamb = lambda_t;
00254                 }
00255               lambda_old[i] = lambda[i];
00256             }
00257         }
00258           */
00259 
00260           //calculate the maximum of the relative changes of the eigenvalues
00261           
00262           if ( n_KS == 1 ) 
00263             {
00264               for(i = 0; i < N_eig; i++) lambda_old[i] = lambda[i];
00265             }
00266           else 
00267             {
00268               del_lamb = 0.0;
00269               for(i = 0; i < N_eig; i++)
00270                 {
00271                   lambda_t   = fabs((lambda_old[i]-lambda[i])/lambda[i]);
00272                   if   (lambda_t > del_lamb)
00273                     del_lamb = lambda_t;
00274                   lambda_old[i]=lambda[i];
00275                 }
00276             }
00277         }
00278       
00279 
00280       // check to see if maxed out on KS steps.
00281 
00282       if (n_KS >= N_KS_max) {
00283           /* 
00284              want to be able to recover from this in alg_eig (by
00285              moving onto the next mass, so just return a negative
00286              value for the iteration number and cope with the problem
00287              higer up. Choose -2 so as to not clash with the error code
00288              from the ritz call
00289           */
00290         VRB.Warn(cname,fname,"NONConversion_warning: n_KS = %d  N_KS_max = %d\n",
00291                  n_KS,N_KS_max);
00292         
00293         if ( off_diag !=0x0 ) { sfree(off_diag); }
00294         return -2;
00295       }
00296 
00297     /* We have just found the eigenv of  H^2 */
00298     /* Diagonalize again for  H.v = lambda.v */
00299 
00300       /*
00301     Vector *tmp = (Vector *) smalloc(cname,fname, "tmp", tmp, f_size * sizeof(Float));
00302 
00303     ij = 0;
00304     for(i = 0; i < N_eig; i++)
00305     {
00306       RitzEigMat(tmp, psi[i]);
00307 
00308       lambda_H[i] = psi[i]->ReDotProductGlbSum(tmp, f_size);
00309       lambda_old[i] = fabs(lambda_H[i]);
00310 
00311       for(j = 0; j < i; j++)
00312         off_diag[ij++] = psi[j]->CompDotProductGlbSum(tmp, f_size);
00313     }
00314 
00315     sfree(cname,fname, "tmp", tmp);
00316 
00317       */
00318 
00319 
00320   }
00321   else  /* Kalk_Sim == NO */
00322   {
00323     ij = 0;
00324     for(n = 1, i = 0; n <= N_eig; n++, i++)
00325     {
00326       NCG_tot += Ritz(psi, n, lambda_t, RsdR_a, RsdR_r, Rsdlam, 0.0 /*rsdl_sq*/,
00327                       n_renorm, 0, 0, 0, Cv_fact, MaxCG, ProjApsiP);
00328 
00329 //      printf("lambda_old[%d]=%e\n",i,lambda_t);
00330       lambda_old[i] = lambda_t;
00331       VRB.Debug(cname,fname,"no KS: lambda[%d] = %g\n",i,(IFloat)lambda_old[i]);
00332 
00333       /* We have just found the eigenv of  H^2 */
00334       /* Diagonalize again for  H.v = lambda.v */
00335       /*
00336       Vector *tmp = (Vector *) smalloc(f_size * sizeof(Float));
00337       if(tmp == 0)
00338         ERR.Pointer(cname,fname, "tmp");
00339       VRB.Smalloc(cname,fname, "tmp", tmp, f_size * sizeof(Float));
00340 
00341       RitzEigMat(tmp, psi[i]);
00342         
00343       lambda_H[i] = psi[i]->ReDotProductGlbSum(tmp, f_size);
00344       lambda_old[i] = fabs(lambda_H[i]);
00345 
00346       for(j = 0; j < i; j++)
00347         off_diag[ij++] = psi[j]->CompDotProductGlbSum(tmp, f_size);
00348 
00349       VRB.Sfree(cname,fname, "tmp", tmp);
00350       sfree(tmp);
00351       */
00352     }
00353   }
00354 
00355 
00356 
00357   /*
00358     We have just found the eigenv of  H^2 
00359     Diagonalize again for  H.v = lambda.v 
00360     (1) by the projection:   [1  \pm  H / sqrt(lambda^2)] .  v
00361 
00362     Currently select only one eigen vector from degenerated eigenvectors
00363     by the projection. 
00364   */
00365 
00366   /*
00367     calculates \psi^{\dagger} D_H \psi and puts the diagonal in lambda_H
00368     and the off_diagonal in off_diag
00369   */
00370   MatHermElements(this, psi, N_eig, f_size, lambda_H, off_diag); 
00371 
00372 
00373   /* 
00374      start off considering all the eigenvectors
00375      as possibly valid
00376   */
00377   for (i=0;i<N_eig;i++) { valid_eig[i] = 1; }
00378 
00379 
00380 
00381  /*
00382     then iteratively remove the eigenvectors that
00383     are invalid ( only count the elements of the
00384     jacobi matrix between valid eigenvectors ) 
00385   */
00386   
00387   bool looping(true);
00388 
00389   while ( looping )
00390     {
00391       looping = false;
00392       for (i=0;i<N_eig;i++)
00393         {
00394           if ( valid_eig[i] )
00395             {
00396               int xy(0),x,y;
00397               const Float rEig2( 1/lambda_old[i] );
00398               Float sum        (lambda_H[i]*lambda_H[i] * rEig2);
00399               // loop over all off-diagonal element and pick up all those
00400               // of the correct row
00401               for (x=0;x<N_eig;x++)
00402                 {
00403                   for (y=0;y<x;y++)
00404                     {
00405                       if ( ( x==i && valid_eig[y] ) || ( y==i && valid_eig[x] ) )
00406                         {
00407                           Float value( off_diag[xy].abs() );
00408                           sum+=value*value*rEig2;
00409                         }
00410                       xy++;
00411                     }
00412                 }
00413               // sum should now have the sum of the squares of the elements
00414               // of row i of the matrix. If this deviates from 1 then we have 
00415               // some missing eigenvectors
00416               if ( sum < 0.98 )
00417                 {
00418                   valid_eig[i] = 0;
00419                   // tagged a new invalid eigenvalue -> need
00420                   // a new iteration to take this into account
00421                   looping = true;
00422                 }
00423             } // if valid_eig
00424         } // loop over eignevalue
00425     } // while ( looping )
00426 
00427   /*
00428     dump these out to the eigenvector output file so
00429     we can check for degeneracy
00430   */
00431 
00432   {
00433     int ij = 0;
00434     int i, j;
00435     FILE* fp(Fopen(eig_arg->fname,"a"));
00436     Fprintf(fp,"Eig2 before projection/jacobi\n");
00437 //    printf("Eig2 before projection/jacobi\n");
00438     for(i = 0; i < N_eig; i++)
00439       {
00440         Fprintf(fp,"%i %e %i\n",i,lambda_old[i],valid_eig[i]);
00441       }
00442     for(i = 0; i < N_eig; i++) 
00443       {
00444         Fprintf(fp,"Jacobi matrix: %i %i %e\n",i,i,(float)lambda_H[i]);
00445         for(j = 0; j < i; j++)
00446           {
00447             Fprintf(fp,"Jacobi matrix: %i %i %e %e\n"
00448                     ,i
00449                     ,j
00450                     ,off_diag[ij].real()
00451                     ,off_diag[ij].imag()   );
00452             ij++;
00453           }
00454       }
00455     Fclose(fp);
00456   }
00457     
00458   int N_dp(0);
00459   for(i=0;i<N_eig;i++)
00460     {
00461       if ( valid_eig[i] == 1 ) N_dp++;
00462       else { break; }
00463     }
00464   // invalidate the rest of the eigenvectors
00465   VRB.Flow(cname,fname,"N_dp=%d\n",N_dp);
00466   for (i++;i<N_eig;i++) { valid_eig[i] = 0; }
00467   
00468   //allocate tmp vector
00469   Vector *tmp = (Vector *) smalloc(f_size * sizeof(Float));
00470   if(tmp == 0) ERR.Pointer("",fname, "tmp");
00471   Vector *tmp2 = (Vector *) smalloc(f_size * sizeof(Float));
00472   if(tmp2 == 0) ERR.Pointer("",fname, "tmp2");
00473   
00474   while ( N_dp < N_eig )
00475     {
00476       valid_eig[N_dp] = 1;
00477       
00478       const Float lam(sqrt(fabs(lambda_old[N_dp])));
00479       VRB.Flow(cname,fname,"lam=%e\n",lam);
00480             
00481       // tmp=  (HemiteMatrix) .  psi[N_dp] 
00482       RitzEigMat(tmp,psi[N_dp]);
00483       PrintDot(fname,"psi[N_sp]",psi[N_dp],f_size);
00484       PrintDot(fname,"tmp",tmp,f_size);
00485 
00486       const Float proj(tmp->ReDotProductGlbSum(psi[N_dp], f_size));
00487       VRB.Flow(cname,fname,"proj=%e\n",proj);
00488       
00489       Float sign(1);
00490       if ( proj <  0 ) { sign = -1; }
00491 
00492             
00493       tmp2->FTimesV1PlusV2( sign/lam, tmp, psi[N_dp], f_size );
00494       PrintDot(fname,"tmp2",tmp2,f_size);
00495       Rcomplex snorm(0,0),onorm(0,0);
00496       for (i=0;i<N_dp;i++)
00497         {
00498           snorm+=tmp2->CompDotProductGlbSum(psi[i],f_size);
00499         }
00500       tmp->FTimesV1PlusV2( -sign/lam, tmp, psi[N_dp], f_size );
00501       PrintDot(fname,"tmp",tmp,f_size);
00502       for (i=0;i<N_dp;i++)
00503         {
00504           onorm+=tmp->CompDotProductGlbSum(psi[i],f_size);
00505         }
00506       if ( onorm.norm() > snorm.norm() )
00507         {
00508           psi[N_dp]->CopyVec( tmp2, f_size );
00509         }
00510       else
00511         {
00512           psi[N_dp]->CopyVec( tmp, f_size );
00513         }
00514       Norm(psi[N_dp],f_size);
00515       PrintDot(fname,"psi[N_sp]",psi[N_dp],f_size);
00516       N_dp++;
00517     }
00518 //  printf("GramSchm");
00519   for (i=0;i<N_eig;i++)
00520     {
00521       for(j=i+1;j<N_eig;j++)
00522         {
00523           GramSchmNorm(psi[j],psi[i],f_size);
00524           PrintDot(fname,"psi[i]",psi[i],f_size);
00525           PrintDot(fname,"psi[j]",psi[j],f_size);
00526         }
00527     }
00528 
00529   
00530 
00531   sfree(tmp);
00532   sfree(tmp2);
00533   
00534   /*
00535     Diagonalize again for  H.v = lambda.v 
00536     (2)  by the Jacobi diagonalization
00537     do Jacobi diagonalization only using 0..N_dp vector 
00538   */
00539   int min_dim(0);
00540   for(i=0;i<N_eig;i++){ if(valid_eig[i]) min_dim++; }
00541   
00542   /*
00543     re-calculates \psi^{\dagger} D_H \psi and puts the diagonal in lambda_H
00544     and the off_diagonal in off_diag
00545   */
00546   
00547   MatHermElements(this, psi, min_dim, f_size, lambda_H, off_diag); 
00548   
00549   {  
00550     int ij = 0;
00551     int i, j;
00552     FILE* fp(Fopen(eig_arg->fname,"a"));
00553     Fprintf(fp,"Jacobi matrix after projection\n");
00554 //    printf("Jacobi matrix after projection\n");
00555     for(i = 0; i < N_eig; i++) 
00556       {
00557         Fprintf(fp,"Jacobi matrix: %i %i %e\n",i,i,(float)lambda_H[i]);
00558         for(j = 0; j < i; j++)
00559           {
00560             Fprintf(fp,"Jacobi matrix: %i %i %e %e\n"
00561                     ,i
00562                     ,j
00563                     ,off_diag[ij].real()
00564                     ,off_diag[ij].imag()   );
00565             ij++;
00566           }
00567       }
00568     Fclose(fp);
00569   }
00570   
00571   n_jacob = Jacobi(psi, min_dim, lambda_H, off_diag, 1.0e-5, 50);
00572 
00573   if(N_eig>1) sfree(off_diag);
00574 
00575 
00576   // end of calculation, dump some valuable information.
00577   
00578   VRB.Result(cname,fname,"Final Jacobi: n_jacob=%d  NCG=%d\n", 
00579              n_jacob,NCG_tot); 
00580   
00581   for(n = 0; n < N_eig; n++)
00582     VRB.Result(cname,fname,"lambda_HH[%d] = %g\n",n,(float)lambda_old[n]);
00583   for(n = 0; n < N_eig; n++)
00584     VRB.Result(cname,fname,"lambda_H[%d] = %g\n",n,(float)lambda_H[n]);
00585   
00586 
00587   return NCG_tot;
00588 
00589 
00590 
00591 
00592 #if 0
00593   // ################ OLD VERSION OF CODE ############
00594   // Check for a common failure mode. If all goes well, the eigenvalues
00595   // should be in increasing order out of Jacobi. Sometimes, the last one
00596   // is not since it didn't converge well enough, or there are nearby 
00597   // eigenvalues. The last one then will often have too small of an eigenvalue
00599   if (N_eig > 2)
00600   {
00601     lambda_t = lambda_old[N_eig-1] - lambda_old[N_eig-2] + Rsdlam;
00602     dummy = lambda_old[N_eig-2] - lambda_old[N_eig-3] + Rsdlam;
00603     if (lambda_t < 0.0 && dummy > 0.0)
00604     {
00605       n = N_eig - 1;
00606     }
00607     else
00608       n = N_eig;
00609   }
00610   else
00611     n = N_eig;
00612 
00613   dummy = sqrt(Rsdlam);
00614 
00615   if (N_eig > 1)
00616   {
00617     n_jacob = Jacobi(psi, n, lambda_H, off_diag, RsdR_a, 50);
00618 
00619     /* Label eigenvalues okay, or not */
00620     n_valid = 0;
00621     for(n = 0; n < N_eig; n++)
00622     {
00623       valid_eig[n] = 0;
00624       lambda_t = lambda_H[n]*lambda_H[n];
00625       if( lambda_t < rsdl_zero )
00626       {
00627         for(j = n_valid; j < N_eig; j++)
00628           if( lambda[j] < rsdl_zero )
00629           {
00630             valid_eig[n] = 1;
00631             n_valid++;
00632             break;
00633           }
00634       }
00635       else
00636       {
00637         for(j = n_valid; j < N_eig; j++)
00638         {
00639           del_lamb = fabs(lambda[j] - lambda_t);
00640           if( del_lamb < dummy*lambda[j] )
00641           {
00642             valid_eig[n] = 1;
00643             n_valid++;
00644             break;
00645           }
00646         }
00647       }
00648     }
00649     
00650     VRB.Result(cname,fname,"Final Jacobi: n_jacob=%d n_valid=%d NCG=%d\n",
00651                n_jacob,n_valid,NCG_tot); 
00652     for(n = 0; n < N_eig; n++)
00653       VRB.Result(cname,fname,"lambda_old[%d] = %g\n",n,(IFloat)lambda_old[n]);
00654     for(n = 0; n < N_eig; n++)
00655       VRB.Result(cname,fname,"lambda_H[%d] = %g\n",n,(IFloat)lambda_H[n]);
00656     for(n = 0; n < N_eig; n++)
00657       VRB.Result(cname,fname,"valid_eig[%d] = %d\n",n,valid_eig[n]);
00658 
00659     VRB.Sfree(cname,fname, "off_diag", off_diag);
00660     sfree(off_diag);
00661   }
00662   else  /* N_eig = 1 */
00663   {
00664     del_lamb = fabs(lambda_H[0] * lambda_H[0] - lambda[0]);
00665     if( del_lamb < dummy*lambda[0] )
00666     {
00667       valid_eig[0] = 1;
00668       n_valid = 1;
00669     }
00670     else
00671     {
00672       valid_eig[0] = 0;
00673       n_valid = 0;
00674     }
00675 
00676     VRB.Result(cname,fname,"Final Result: n_valid=%d  NCG=%d\n",n_valid,NCG_tot); 
00677     for(n = 0; n < N_eig; n++)
00678       VRB.Result(cname,fname,"lambda[%d] = %g\n",n,(IFloat)lambda[n]);
00679     for(n = 0; n < N_eig; n++)
00680       VRB.Result(cname,fname,"lambda_H[%d] = %g\n",n,(IFloat)lambda_H[n]);
00681     for(n = 0; n < N_eig; n++)
00682       VRB.Result(cname,fname,"valid_eig[%d] = %d\n",n,valid_eig[n]);
00683   }
00684 
00685   VRB.Sfree(cname,fname, "lambda_old", lambda_old);
00686   sfree(lambda_old);
00687   VRB.Sfree(cname,fname, "lambda", lambda);
00688   sfree(lambda);
00689 
00690 
00691 // Flash the LED and then turn it on
00692 //------------------------------------------------------------------
00693   VRB.FuncEnd(cname,fname);
00694   VRB.LedFlash(cname,fname,2);
00695   VRB.LedOn(cname,fname);
00696       
00697   return NCG_tot;
00698 
00699 #endif  // OLD CODE END
00700 }
00701 
00702 
00703 
00704 //-------------------------------------------------------------------
00705 // Calculate the Matrix elements for the hermitian dirac operator.
00706 // only the real part of the diagonal(the imaginary part should be 0.0
00707 // and half of the complex off-diagonal elements are calculated.
00708 //-------------------------------------------------------------------
00709 void MatHermElements( DiracOpWilsonTypes * dirac_op,
00710                       Vector ** psi, int n_vec, int f_size, 
00711                       Float * diag, Complex * off_diag ){
00712 
00713   char * fname  = "MatHermElements";
00714   Vector *tmp = (Vector *) smalloc("DiracOpWilsonTypes",fname,"tmp",f_size * sizeof(Float));
00715 //  if(tmp == 0) ERR.Pointer("",fname, "tmp");
00716   
00717   int ij = 0;
00718   int i, j;
00719 
00720   for(i = 0; i < n_vec; i++) {
00721       dirac_op->RitzEigMat(tmp, psi[i]);
00722       diag[i] = psi[i]->ReDotProductGlbSum(tmp, f_size);
00723 #if 0
00724       Float *tmp_p = (Float*)tmp;
00725       for(j = 0; j < 10; j++)
00726         printf("tmp[%d]=%e\n",j,*(tmp_p+j));
00727       tmp_p = (Float*)psi[i];
00728       for(j = 0; j < 10; j++)
00729         printf("psi[%d][%d]=%e\n",i,j,*(tmp_p+j));
00730       printf("%s: diag[%d]=%e\n",fname,i,diag[i]);
00731 #endif
00732       PrintDot(fname,"psi[i]",psi[i],f_size);
00733       PrintDot(fname,"tmp",tmp,f_size);
00734       for(j = 0; j < i; j++){
00735         off_diag[ij++] = psi[j]->CompDotProductGlbSum(tmp, f_size);
00736 #if 0
00737         tmp_p = (Float*) off_diag+ij;
00738         printf("%s: off_diag[%d]=%e %e\n",fname,ij-1,*tmp_p, *(tmp_p+1));
00739 #endif
00740       }
00741   }
00742 
00743   sfree(tmp);
00744 }
00745 
00746 
00747 
00748 CPS_END_NAMESPACE

Generated on Sat Oct 10 14:11:29 2009 for Columbia Physics System by  doxygen 1.3.9.1