CHROMA
syssolver_mdagm_OPTeigcg.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.h>
6 
7 #include "qdp-lapack_Complex.h"
8 #include "qdp-lapack_eigpcg.h"
9 #include "qdp-lapack_IncrEigpcg.h"
10 
13 
15 #include "containers.h"
16 
17 
18 namespace Chroma
19 {
20 
21  //! CG1 system solver namespace
22  namespace MdagMSysSolverOptEigCGEnv
23  {
24  //! Callback function
26  const std::string& path,
27  Handle< FermState< LatticeFermion, multi1d<LatticeColorMatrix>, multi1d<LatticeColorMatrix> > > state,
29  {
31  }
32 
33 #if 0
34  //! Callback function
36  XMLReader& xml_in,
37  const std::string& path,
39  {
41  }
42 #endif
43 
44  //! Name to be used
45  const std::string name("EIG_CG_INVERTER");
46 
47  //! Local registration flag
48  static bool registered = false;
49 
50  //! Register all the factories
51  bool registerAll()
52  {
53  bool success = true;
54  if (! registered)
55  {
57 // success &= Chroma::TheMdagMStagFermSystemSolverFactory::Instance().registerObject(name, createStagFerm);
58  registered = true;
59  }
60  return success;
61  }
62  }
63 
64 
65  //! Anonymous namespace holding method
66  namespace
67  {
68  template<typename T>
69  struct MatVecArg{
70  T XX ;
71  T YY ;
73  };
74 
75  template<typename T>
76  void MatrixMatvec(void *x, void *y, void *params) {
77 
78  MatVecArg<T> &arg = *((MatVecArg<T> *) params) ;
79 
80  //Works only in single precision CHROMA
81  RComplex<float> *px = (RComplex<float> *) x;
82  RComplex<float> *py = (RComplex<float> *) y;
83 
84  //XX.getF() = (Complex *) x ; //AN DOULEPSEI AUTO NA ME FTUSEIS
85  //YY.getF() = (Complex *) y ; //AN DOULEPSEI AUTO NA ME FTUSEIS
86 
87  //Alliws kanoume copy
88  //copy x into XX
89  Subset s = arg.MdagM->subset() ;
90  if(s.hasOrderedRep()){
91  /**
92  int one(1);
93  int VecSize = s.numSiteTable()*Nc*Ns ;
94  BLAS_DCOPY(&VecSize,
95  (double *)&arg.XX.elem(s.start()).elem(0).elem(0).real(),
96  &one,
97  (double *)x, &one);
98  **/
99  /**/
100  int count=0 ;
101  //can be done with ccopy for speed...
102  for(int i=s.start(); i <= s.end(); i++)
103  for(int ss(0);ss<Ns;ss++)
104  for(int c(0);c<Nc;c++){
105  arg.XX.elem(i).elem(ss).elem(c) = *(px+count);
106  count++;
107  }
108  /**/
109  }
110  else{
111  int i ;
112  const int *tab = s.siteTable().slice();
113  int count=0;
114  for(int x=0; x < s.numSiteTable(); ++x){
115  i = tab[x] ;
116  for(int ss(0);ss<Ns;ss++)
117  for(int c(0);c<Nc;c++){
118  arg.XX.elem(i).elem(ss).elem(c) = *(px+count);
119  count++;
120  }
121  }
122  }
123 
124 
125  (*arg.MdagM)(arg.YY,arg.XX,PLUS) ;
126  //T foo,boo;
127  //*(arg.MdagM)(boo,foo,PLUS) ;
128 
129  //copy back..
130  if(s.hasOrderedRep()){
131  int count=0 ;
132  //can be done with ccopy for speed...
133  for(int i=s.start(); i <= s.end(); i++)
134  for(int ss(0);ss<Ns;ss++)
135  for(int c(0);c<Nc;c++){
136  *(py+count) = arg.YY.elem(i).elem(ss).elem(c) ;
137  count++;
138  }
139  }
140  else{
141  int i ;
142  int count=0;
143  const int *tab = s.siteTable().slice();
144  for(int x=0; x < s.numSiteTable(); ++x){
145  i = tab[x] ;
146  for(int ss(0);ss<Ns;ss++)
147  for(int c(0);c<Nc;c++){
148  *(py+count) = arg.YY.elem(i).elem(ss).elem(c) ;
149  count++;
150  }
151  }
152  }
153  }
154 
155 
156  //! Solver the linear system
157  /*!
158  * \param psi solution ( Modify )
159  * \param chi source ( Read )
160  * \return syssolver results
161  */
162  template<typename T>
163  SystemSolverResults_t sysSolver(T& psi, const T& chi,
164  const LinearOperator<T>& A,
166  const SysSolverOptEigCGParams& invParam)
167  {
168 #ifndef QDP_IS_QDPJIT
169  START_CODE();
170 
171  SystemSolverResults_t res; // initialized by a constructor
172 
174 
175  QDPIO::cout<<"EigInfo.N= "<<EigInfo.N<<std::endl ;
176  QDPIO::cout<<"EigInfo.lde= "<<EigInfo.lde<<std::endl ;
177  QDPIO::cout<<"EigInfo.ldh= "<<EigInfo.evals.size()<<std::endl ;
178  QDPIO::cout<<"EigInfo.ncurEvals= "<<EigInfo.ncurEvals<<std::endl ;
179  QDPIO::cout<<"EigInfo.restartTol= "<<EigInfo.restartTol<<std::endl ;
180 
181  Subset s = A.subset() ;
182 
183  Complex_C *X ;
184  Complex_C *B ;
185  Complex_C *work=NULL ;
186  Complex_C *V=NULL ;
187  Complex_C *ework=NULL ;
188 
189  // OK, for now Weirdly enough psi and chi have to be
190  // explicit single precision, so downcast those...
191  // Most generically the single prec type of say a
192  // type T should be given by the QDP++ Type trait:
193  // SinglePrecType<T>::Type_t
194  typename SinglePrecType<T>::Type_t psif = psi;
195  typename SinglePrecType<T>::Type_t chif = chi;
196 
197  if(s.hasOrderedRep()){
198  X = (Complex_C *) &psif.elem(s.start()).elem(0).elem(0).real();
199  B = (Complex_C *) &chif.elem(s.start()).elem(0).elem(0).real();
200  }
201  else{//need to copy
202  //X = allocate space for them
203  //B = allocate space for them...
204  QDPIO::cout<<"OPPS! I have not implemented OPT_EigCG for Linops with non contigius subset\n";
205  exit(1);
206  }
207 
208  Complex_C *evecs = (Complex_C *) &EigInfo.evecs[0] ;
209  float *evals = (float *) &EigInfo.evals[0].elem() ;
210  Complex_C *H = (Complex_C *) &EigInfo.H[0] ;
211  Complex_C *HU = (Complex_C *) &EigInfo.HU[0] ;
212  MatVecArg<T> arg ;
213  arg.MdagM = MdagM ;
214  int esize = invParam.esize*Layout::sitesOnNode()*Nc*Ns ;
215 
216  QDPIO::cout<<"OPT_EIGCG_SYSSOLVER= "<<esize<<std::endl ;
217  //multi1d<Complex_C> ework(esize);
218  float resid = (float) invParam.RsdCG.elem().elem().elem().elem();
219  float AnormEst = invParam.NormAest.elem().elem().elem().elem();
220 
221  float restartTol;
222  if (EigInfo.ncurEvals < EigInfo.evals.size())
223  restartTol = 0.0; // Do not restart the first phase
224  else {
225  // set it to the user parameter:
226  restartTol = invParam.restartTol.elem().elem().elem().elem();
227 
228  // restartTol = EigInfo.restartTol; //or restart with tol as computed
229  }
230 
231  IncrEigpcg(EigInfo.N, EigInfo.lde, 1, X, B,
232  &EigInfo.ncurEvals, EigInfo.evals.size(),
233  evecs, evals, H, HU,
234  MatrixMatvec<T>, NULL, (void *)&arg, work, V,
235  ework, esize,
236  resid, &restartTol,
237  AnormEst, invParam.updateRestartTol,
238  invParam.MaxCG, invParam.PrintLevel,
239  invParam.Neig, invParam.Nmax, stdout);
240 
241  /* Update the restartTol in the EigInfo function */
242  EigInfo.restartTol = restartTol;
243 
244  // Copy result back
245  psi = psif;
246 
247  T tt;
248  (*MdagM)(tt,psi,PLUS);
249  QDPIO::cout<<"OPT_EICG_SYSSOLVER: True residual after solution : "<<sqrt(norm2(tt-chi,s))<<std::endl ;
250  QDPIO::cout<<"OPT_EICG_SYSSOLVER: norm of solution : "<<sqrt(norm2(psi,s))<<std::endl ;
251  QDPIO::cout<<"OPT_EICG_SYSSOLVER: norm of rhs : "<<sqrt(norm2(chi,s))<<std::endl ;
252 
253 
254 
255  if(!s.hasOrderedRep()){
256  QDPIO::cout<<"OPPS! I have no implemented OPT_EigCG for Linops with non contigius subset\n";
257  }
258  END_CODE();
259 
260  return res;
261 #else
263 
264  res.n_count = -1;
265  res.resid = Real(1000000);
266  QDPIO::cout << "This solver is not implemented over QDP-JIT." << std::endl;
267  QDP_abort(1);
268  return res;
269 
270 #endif
271  }
272 
273  } // anonymous namespace
274 
275 
276  //
277  // Wrappers
278  //
279 
280  // LatticeFermionF
281  template<>
283  MdagMSysSolverOptEigCG<LatticeFermionF>::operator()(LatticeFermionF& psi, const LatticeFermionF& chi) const
284  {
285  return sysSolver(psi, chi, *A, MdagM, invParam);
286  }
287 
288  // LatticeFermionD
289  template<>
291  MdagMSysSolverOptEigCG<LatticeFermionD>::operator()(LatticeFermionD& psi, const LatticeFermionD& chi) const
292  {
293  return sysSolver(psi, chi, *A, MdagM, invParam);
294  }
295 
296 #if 1
297 
298 
299  // Not quite ready yet for these - almost there
300  // LatticeStaggeredFermionF
301  template<>
303  MdagMSysSolverOptEigCG<LatticeStaggeredFermionF>::operator()(LatticeStaggeredFermionF& psi, const LatticeStaggeredFermionF& chi) const
304  {
305  return sysSolver(psi, chi, *A, MdagM, invParam);
306  }
307 
308  // LatticeStaggeredFermionD
309  template<>
311  MdagMSysSolverOptEigCG<LatticeStaggeredFermionD>::operator()(LatticeStaggeredFermionD& psi, const LatticeStaggeredFermionD& chi) const
312  {
313  return sysSolver(psi, chi, *A, MdagM, invParam);
314  }
315 #endif
316 
317 }
Support class for fermion actions and linear operators.
Definition: state.h:94
Class for counted reference semantics.
Definition: handle.h:33
multi1d< Complex > HU
Definition: containers.h:133
multi1d< Complex > H
Definition: containers.h:132
multi1d< Real > evals
Definition: containers.h:130
multi1d< LatticeFermion > evecs
Definition: containers.h:131
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
Params params
int y
Definition: meslate.cc:35
int x
Definition: meslate.cc:34
LinOpSystemSolver< LatticeStaggeredFermion > * createStagFerm(XMLReader &xml_in, const std::string &path, Handle< LinearOperator< LatticeStaggeredFermion > > A)
Callback function.
bool registerAll()
Register all the factories.
MdagMSystemSolver< LatticeFermion > * createFerm(XMLReader &xml_in, const std::string &path, Handle< FermState< LatticeFermion, multi1d< LatticeColorMatrix >, multi1d< LatticeColorMatrix > > > state, Handle< LinearOperator< LatticeFermion > > A)
Callback function.
static bool registered
Local registration flag.
const std::string name("EIG_CG_INVERTER")
Name to be used.
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
Double c
Definition: invbicg.cc:108
LinOpSysSolverMGProtoClover::T T
int i
Definition: pbg5p_w.cc:55
@ 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
multi1d< LatticeFermion > s(Ncb)
int count
Definition: octave.h:14
::std::string string
Definition: gtest.h:1979
Holds return info from SystemSolver call.
Definition: syssolver.h:17
Handle< LinearOperator< T > > MdagM
Solve a M^dag*M*psi=chi linear system by EigCG.
Register MdagM system solvers.
Factory for producing system solvers for MdagM*psi = chi.