CHROMA
syssolver_mdagm_eigcg_qdp.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Solve a M^dag*M*psi=chi linear system by EigCG
3  */
4 
5 #include <qdp-lapack.h>
6 
9 
14 
15 //for debugging
16 //#include "octave.h"
17 #define TEST_ALGORITHM
18 namespace Chroma
19 {
20 
21  //! CG1 system solver namespace
22  namespace MdagMSysSolverQDPEigCGEnv
23  {
24  //! Callback function
26  const std::string& path,
27  Handle< FermState< LatticeFermion, multi1d<LatticeColorMatrix>, multi1d<LatticeColorMatrix> > > state,
28 
30  {
32  }
33 
34 #if 0
35  //! Callback function
37  XMLReader& xml_in,
38  const std::string& path,
40  {
42  }
43 #endif
44 
45  //! Name to be used
46  const std::string name("EIG_CG_INVERTER");
47 
48  //! Local registration flag
49  static bool registered = false;
50 
51  //! Register all the factories
52  bool registerAll()
53  {
54  bool success = true;
55  if (! registered)
56  {
58 // success &= Chroma::TheMdagMStagFermSystemSolverFactory::Instance().registerObject(name, createStagFerm);
59  registered = true;
60  }
61  return success;
62  }
63  }
64 
65 
66  //! Anonymous namespace holding method
67  namespace
68  {
69  //! Solver the linear system
70  /*!
71  * \param psi solution ( Modify )
72  * \param chi source ( Read )
73  * \return syssolver results
74  */
75  template<typename T>
76  SystemSolverResults_t sysSolver(T& psi, const T& chi,
77  const LinearOperator<T>& A,
78  const LinearOperator<T>& MdagM,
79  const SysSolverEigCGParams& invParam)
80  {
81  START_CODE();
82 
84 
85  multi1d<Double> lambda ; //the eigenvalues
86  multi1d<T> evec(0); // The eigenvectors
87  SystemSolverResults_t res; // initialized by a constructor
88  int n_CG(0);
89  int flag(-1);//first time through
90  int restart(0);
91  Real restartTol = invParam.restartTol ;
92  StopWatch snoop;
93  while((flag==-1)||flag==3){
94  flag=0 ;
95  if(invParam.PrintLevel>0)
96  QDPIO::cout<<"GoodEvecs.Neig= "<<GoodEvecs.Neig<<std::endl;
97  if(GoodEvecs.Neig>0){//deflate if there avectors to deflate
98  if(invParam.PrintLevel>0){
99  snoop.reset();
100  snoop.start();
101  }
102  InvEigCG2Env::InitGuess(MdagM,psi,chi,GoodEvecs.eval.vec,GoodEvecs.evec.vec,GoodEvecs.Neig,n_CG);
103  if(invParam.PrintLevel>0) snoop.stop();
104  if(invParam.PrintLevel>0)
105  QDPIO::cout << "InitGuess: time = "
106  << snoop.getTimeInSeconds()
107  << " secs" << std::endl;
108  }
109  //if there is space for new
110  if((GoodEvecs.Neig)<GoodEvecs.evec.vec.size())
111  {
112 
113  evec.resize(0);//get in there with no evecs so that it computes new
114  res = InvEigCG2Env::InvEigCG2(MdagM, psi, chi, lambda, evec,
115  invParam.Neig, invParam.Nmax,
116  invParam.RsdCG, invParam.MaxCG,
117  invParam.PrintLevel);
118  res.n_count += n_CG ;
119 
120  snoop.reset();
121  snoop.start();
122  GoodEvecs.AddVectors(lambda, evec, MdagM.subset());
123  snoop.stop();
124  double Time = snoop.getTimeInSeconds() ;
125 
126  snoop.start();
127  normGramSchmidt(GoodEvecs.evec.vec,GoodEvecs.Neig-invParam.Neig,GoodEvecs.Neig,MdagM.subset());
128  normGramSchmidt(GoodEvecs.evec.vec,GoodEvecs.Neig-invParam.Neig,GoodEvecs.Neig,MdagM.subset());
129  snoop.stop();
130  Time += snoop.getTimeInSeconds() ;
131 
132  snoop.start();
133  LinAlg::Matrix<DComplex> Htmp(GoodEvecs.Neig) ;
134  //Only do the matrix elements for the new vectors
135  //InvEigCG2Env::SubSpaceMatrix(Htmp,MdagM,GoodEvecs.evec.vec,GoodEvecs.Neig);
136  /**/
138  GoodEvecs.evec.vec,
139  GoodEvecs.eval.vec,
140  GoodEvecs.Neig,
141  GoodEvecs.Neig-invParam.Neig);
142  /**/
143  char V = 'V' ; char U = 'U' ;
144  QDPLapack::zheev(V,U,Htmp.mat,lambda);
145  evec.resize(GoodEvecs.Neig) ;
146 
147  for(int k(0);k<GoodEvecs.Neig;k++){
148  GoodEvecs.eval[k] = lambda[k];
149  evec[k][MdagM.subset()] = zero ;
150  for(int j(0);j<GoodEvecs.Neig;j++)
151  evec[k][MdagM.subset()] += conj(Htmp(k,j))*GoodEvecs.evec[j] ;
152  }
153  snoop.stop();
154  Time += snoop.getTimeInSeconds() ;
155  if(invParam.PrintLevel>0){
156  QDPIO::cout << "Evec_Refinement: time = "
157  << Time
158  << " secs" << std::endl;
159 
160  //QDPIO::cout<<"GoodEvecs.Neig= "<<GoodEvecs.Neig<<std::endl;
161  }
162  for(int k(0);k<GoodEvecs.Neig;k++)
163  GoodEvecs.evec[k][MdagM.subset()] = evec[k] ;
164 
165  //Check the quality of eigenvectors
166  if(invParam.PrintLevel>4){
167  T Av ;
168  for(int k(0);k<GoodEvecs.Neig;k++){
169  MdagM(Av,GoodEvecs.evec[k],PLUS) ;
170  DComplex rq = innerProduct(GoodEvecs.evec[k],Av,MdagM.subset());
171  Av[MdagM.subset()] -= GoodEvecs.eval[k]*GoodEvecs.evec[k] ;
172  Double tt = sqrt(norm2(Av,MdagM.subset()));
173  QDPIO::cout<<"REFINE: error evec["<<k<<"] = "<<tt<<" " ;
174  QDPIO::cout<<"--- eval ="<<GoodEvecs.eval[k]<<" ";
175  tt = sqrt(norm2(GoodEvecs.evec[k],MdagM.subset()));
176  QDPIO::cout<<"--- rq ="<<real(rq)<<" ";
177  QDPIO::cout<<"--- norm = "<<tt<<std::endl ;
178  }
179  }
180  }// if there is space
181  else // call CG but ask it not to compute vectors
182  {
183  evec.resize(0);
184  n_CG = res.n_count ;
185  if(invParam.vPrecCGvecs ==0){
186  if(invParam.PrintLevel<2)// Call the CHROMA CG
187  res = InvCG2(A, chi, psi, restartTol, invParam.MaxCG);
188  else
190  psi,
191  chi,
192  lambda,
193  evec,
194  0, //Eigenvectors to keep
195  invParam.Nmax, // Max vectors to work with
196  restartTol, // CG residual...
197  invParam.MaxCG, // Max CG itterations
198  invParam.PrintLevel
199  );
200  }
201  else
203  GoodEvecs.eval.vec,
204  GoodEvecs.evec.vec,
205  invParam.vPrecCGvecStart,
206  invParam.vPrecCGvecStart+invParam.vPrecCGvecs,
207  restartTol, // CG residual
208  invParam.MaxCG // Max CG itterations
209  );
210  res.n_count += n_CG ;
211  if(toBool(restartTol!=invParam.RsdCG)){
212  restart++;//count the number of restarts
213  if(invParam.PrintLevel>0)
214  QDPIO::cout<<"Restart: "<<restart<<std::endl ;
215  flag=3 ; //restart
216  }
217  else{
218  flag=0; //stop restarting
219  }
220  restartTol *=restartTol ;
221  if(toBool(restartTol < invParam.RsdCG)){
222  restartTol = invParam.RsdCG;
223  }
224  }
225  }//while
226 
227  END_CODE();
228 
229  return res;
230  }
231 
232  } // anonymous namespace
233 
234 
235  //
236  // Wrappers
237  //
238 
239  // LatticeFermionF
240  template<>
242  MdagMSysSolverQDPEigCG<LatticeFermionF>::operator()(LatticeFermionF& psi, const LatticeFermionF& chi) const
243  {
244  return sysSolver(psi, chi, *A, *MdagM, invParam);
245  }
246 
247  // LatticeFermionD
248  template<>
250  MdagMSysSolverQDPEigCG<LatticeFermionD>::operator()(LatticeFermionD& psi, const LatticeFermionD& chi) const
251  {
252  return sysSolver(psi, chi, *A, *MdagM, invParam);
253  }
254 
255 #if 0
256  // Not quite ready yet for these - almost there
257  // LatticeStaggeredFermionF
258  template<>
260  MdagMSysSolverQDPEigCG<LatticeStaggeredFermionF>::operator()(LatticeStaggeredFermionF& psi, const LatticeStaggeredFermionF& chi) const
261  {
262  return sysSolver(psi, chi, *A, *MdagM, invParam);
263  }
264 
265  // LatticeStaggeredFermionD
266  template<>
268  MdagMSysSolverQDPEigCG<LatticeStaggeredFermionD>::operator()(LatticeStaggeredFermionD& psi, const LatticeStaggeredFermionD& chi) const
269  {
270  return sysSolver(psi, chi, *A, *MdagM, invParam);
271  }
272 #endif
273 
274 }
Support class for fermion actions and linear operators.
Definition: state.h:94
Class for counted reference semantics.
Definition: handle.h:33
This is a square matrix.
Definition: containers.h:328
Holds eigenvalues and eigenvectors.
Definition: containers.h:282
void AddVectors(const multi1d< Double > &e, const multi1d< T > &v, const Subset &s)
Definition: containers.h:309
Vectors< Double > eval
Definition: containers.h:284
Solve a M*psi=chi linear system by CG2 with eigenvectors.
SystemSolverResults_t operator()(T &psi, const T &chi) const
Solver the linear system.
static T & Instance()
Definition: singleton.h:432
void normGramSchmidt(multi1d< LatticeFermionF > &vec, int f, int t, const Subset &sub)
Gram-Schmidt with normalization.
SystemSolverResults_t InvCG2(const LinearOperator< LatticeFermionF > &M, const LatticeFermionF &chi, LatticeFermionF &psi, const Real &RsdCG, int MaxCG)
Conjugate-Gradient (CGNE) algorithm for a generic Linear Operator.
Definition: invcg2.cc:240
Conjugate-Gradient algorithm with eigenstd::vector acceleration.
Conjugate-Gradient algorithm for a generic Linear Operator.
unsigned j
Definition: ldumul_w.cc:35
BinaryReturn< C1, C2, FnInnerProduct >::Type_t innerProduct(const QDPSubType< T1, C1 > &s1, const QDPType< T2, C2 > &s2)
void SubSpaceMatrix(LinAlg::Matrix< DComplex > &H, const LinearOperator< LatticeFermionF > &A, const multi1d< LatticeFermionF > &evec, int Nvecs)
Definition: inv_eigcg2.cc:1156
SystemSolverResults_t InvEigCG2(const LinearOperator< LatticeFermionF > &A, LatticeFermionF &x, const LatticeFermionF &b, multi1d< Double > &eval, multi1d< LatticeFermionF > &evec, int Neig, int Nmax, const Real &RsdCG, int MaxCG, const int PrintLevel)
Definition: inv_eigcg2.cc:1172
SystemSolverResults_t vecPrecondCG(const LinearOperator< LatticeFermionF > &A, LatticeFermionF &x, const LatticeFermionF &b, const multi1d< Double > &eval, const multi1d< LatticeFermionF > &evec, int startV, int endV, const Real &RsdCG, int MaxCG)
Definition: inv_eigcg2.cc:1185
void InitGuess(const LinearOperator< LatticeFermionF > &A, LatticeFermionF &x, const LatticeFermionF &b, const multi1d< Double > &eval, const multi1d< LatticeFermionF > &evec, int &n_count)
Definition: inv_eigcg2.cc:1196
LinOpSystemSolver< LatticeStaggeredFermion > * createStagFerm(XMLReader &xml_in, const std::string &path, Handle< LinearOperator< LatticeStaggeredFermion > > A)
Callback function.
bool registerAll()
Register all the factories.
static bool registered
Local registration flag.
MdagMSystemSolver< LatticeFermion > * createFerm(XMLReader &xml_in, const std::string &path, Handle< FermState< LatticeFermion, multi1d< LatticeColorMatrix >, multi1d< LatticeColorMatrix > > > state, Handle< LinearOperator< LatticeFermion > > A)
Callback function.
const std::string name("EIG_CG_INVERTER")
Name to be used.
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
LinOpSysSolverMGProtoClover::T T
@ PLUS
Definition: chromabase.h:45
multi1d< LatticeFermion > chi(Ncb)
LatticeFermion psi
Definition: mespbg5p_w.cc:35
START_CODE()
A(A, psi, r, Ncb, PLUS)
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > state
Definition: pbg5p_w.cc:28
Double zero
Definition: invbicg.cc:106
int k
Definition: invbicg.cc:119
FloatingPoint< double > Double
Definition: gtest.h:7351
::std::string string
Definition: gtest.h:1979
Gram-Schmidt with normalization.
Params for EigCG inverter.
Holds return info from SystemSolver call.
Definition: syssolver.h:17
Handle< LinearOperator< T > > MdagM
Register MdagM system solvers.
Solve a M^dag*M*psi=chi linear system by EigCG.
Factory for producing system solvers for MdagM*psi = chi.
multi1d< LatticeColorMatrix > U