CHROMA
syssolver_linop_OPTeigbicg.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Solve a A*psi=chi linear system by EigBiCG
3  */
4 
5 
6 #include "qdp-lapack_Complex.h"
7 #include "qdp-lapack_eigbicg.h"
8 #include "qdp-lapack_IncrEigbicg.h"
9 
12 
14 #include "containers.h"
15 
16 
17 namespace Chroma
18 {
19 
20  //! CG1 system solver namespace
21  namespace LinOpSysSolverOptEigBiCGEnv
22  {
23  //! Callback function
25  const std::string& path,
26  Handle< FermState< LatticeFermion, multi1d<LatticeColorMatrix>, multi1d<LatticeColorMatrix> > > state,
28  {
30  }
31 
32 #if 0
33  //! Callback function
35  XMLReader& xml_in,
36  const std::string& path,
38  {
40  }
41 #endif
42 
43  //! Name to be used
44  const std::string name("EIG_BiCG_INVERTER");
45 
46  //! Local registration flag
47  static bool registered = false;
48 
49  //! Register all the factories
50  bool registerAll()
51  {
52  bool success = true;
53  if (! registered)
54  {
56 // success &= Chroma::TheLinOpStagFermSystemSolverFactory::Instance().registerObject(name, createStagFerm);
57  registered = true;
58  }
59  return success;
60  }
61  }
62 
63 
64  //! Anonymous namespace holding method
65  namespace
66  {
67  template<typename T>
68  struct MatVecArg{
69  T XX ;
70  T YY ;
71  Handle< LinearOperator<T> > LinOp;
72  };
73 
74  //PLUS is the mutrix and MINUS is the dagger
75  template<typename R, typename T, PlusMinus isign>
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<R> *px = (RComplex<R> *) x;
82  RComplex<R> *py = (RComplex<R> *) y;
83 
84  //copy x into XX
85  LinAlg::CopyToLatFerm<T,R>(arg.XX,px,arg.LinOp->subset());
86  (*arg.LinOp)(arg.YY,arg.XX,isign) ;
87 
88  //copy back..
89  LinAlg::CopyFromLatFerm<T,R>(py,arg.YY,arg.LinOp->subset());
90  }
91 
92 
93  void IncrEigBiCG(int n, int lde,int nrhs, Complex_C* X, Complex_C* B,
94  int* ncurEvals, int ldh, Complex_C* evecsl,
95  Complex_C* evecsr, Complex_C* evals,
96  Complex_C* H,void (*matvec) (void*, void*, void*),
97  void (*mathvec)(void*, void*, void*),void* params,
98  float* AnormEst, Complex_C* work, Complex_C* VL,
99  int ldvl,Complex_C* VR, int ldvr,
100  Complex_C* ework, int esize,float tol,float* restartTol,
101  int maxit, char SRT_OPT, float epsi, int ConvTestOpt,
102  int plvl,int nev, int v_max,FILE* outputFile){
103  QDPIO::cout<<"IncrEigbicg_C will be called"<<std::endl ;
104  return IncrEigbicg_C(n, lde, nrhs, X, B,
105  ncurEvals, ldh,
106  evecsl, evecsr, evals, H,
107  matvec,mathvec,
108  params, AnormEst,
109  work, VL, ldvl, VR,
110  ldvr, ework, esize,
111  tol, restartTol,
112  maxit, SRT_OPT, epsi,
113  ConvTestOpt,
114  plvl, nev, v_max,
115  outputFile);
116  }
117 
118  void IncrEigBiCG(int n, int lde,int nrhs, Complex_Z* X, Complex_Z* B,
119  int* ncurEvals, int ldh, Complex_Z* evecsl,
120  Complex_Z* evecsr, Complex_Z* evals,
121  Complex_Z* H, void (*matvec) (void*, void*, void*),
122  void (*mathvec)(void*, void*, void*), void* params,
123  double *AnormEst, Complex_Z* work, Complex_Z* VL,
124  int ldvl, Complex_Z* VR, int ldvr, Complex_Z* ework,
125  int esize, double tol, double* restartTol,
126  int maxit, char SRT_OPT, double epsi, int ConvTestOpt,
127  int plvl, int nev, int v_max,FILE *outputFile){
128  QDPIO::cout<<"IncrEigbicg_Z will be called"<<std::endl ;
129  return IncrEigbicg_Z(n, lde, nrhs, X, B,
130  ncurEvals, ldh,
131  evecsl, evecsr, evals, H,
132  matvec,mathvec,
133  params, AnormEst,
134  work, VL, ldvl, VR,
135  ldvr, ework, esize,
136  tol, restartTol,
137  maxit, SRT_OPT, epsi,
138  ConvTestOpt,
139  plvl, nev, v_max,
140  outputFile);
141  }
142 
143  //! Solver the linear system
144  /*!
145  * \param psi solution ( Modify )
146  * \param chi source ( Read )
147  * \return syssolver results
148  */
149  template<typename T, typename F, typename C>
150  SystemSolverResults_t sysSolver(T& psi, const T& chi,
151  Handle< LinearOperator<T> > A,
152  const SysSolverOptEigBiCGParams& invParam)
153  {
154  START_CODE();
155 
156  SystemSolverResults_t res; // initialized by a constructor
157 
158  LinAlg::OptEigBiInfo<REAL>& EigBiInfo = TheNamedObjMap::Instance().getData< LinAlg::OptEigBiInfo<REAL> >(invParam.eigen_id);
159 
160  QDPIO::cout<<"EigBiInfo.N= "<<EigBiInfo.N<<std::endl ;
161  QDPIO::cout<<"EigBiInfo.lde= "<<EigBiInfo.lde<<std::endl ;
162  QDPIO::cout<<"EigBiInfo.ldh= "<<EigBiInfo.evals.size()<<std::endl ;
163  QDPIO::cout<<"EigBiInfo.ncurEvals= "<<EigBiInfo.ncurEvals<<std::endl ;
164  QDPIO::cout<<"EigBiInfo.restartTol= "<<EigBiInfo.restartTol<<std::endl ;
165 
166  Subset s = A->subset() ;
167 
168  C *X ;
169  C *B ;
170  C *work=NULL ;
171  C *VL=NULL ;
172  C *VR=NULL ;
173  C *ework=NULL ;
174 
175  /***** NO NEED FOR THIS ANY MORE
176  // OK, for now Weirdly enough psi and chi have to be
177  // explicit single precision, so downcast those...
178  // Most generically the single prec type of say a
179  // type T should be given by the QDP++ Type trait:
180  // SinglePrecType<T>::Type_t
181 
182  typename SinglePrecType<T>::Type_t psif = psi;
183  typename SinglePrecType<T>::Type_t chif = chi;
184  *****/
185 
186  if(s.hasOrderedRep()){
187  X = (C *) &psi.elem(s.start()).elem(0).elem(0).real();
188  B = (C *) &chi.elem(s.start()).elem(0).elem(0).real();
189  }
190  else{//need to copy
191  //X = allocate space for them
192  //B = allocate space for them...
193  QDPIO::cout<<"OPPS! I have not implemented OPT_EigBiCG for Linops with non contigius subset\n";
194  exit(1);
195  }
196 
197  C *evecsL = (C *) &EigBiInfo.evecsL[0] ;
198  C *evecsR = (C *) &EigBiInfo.evecsR[0] ;
199  C *evals = (C *) &EigBiInfo.evals[0] ;
200  C *H = (C *) &EigBiInfo.H[0] ;
201  MatVecArg<T> arg ;
202  arg.LinOp = A ;
203  int esize = invParam.esize*Layout::sitesOnNode()*Nc*Ns ;
204 
205  QDPIO::cout<<"OPT_EIGBICG_SYSSOLVER= "<<esize<<std::endl ;
206  //multi1d<C> ework(esize);
207  F resid = (F) invParam.RsdCG.elem().elem().elem().elem();
208  F AnormEst = invParam.NormAest.elem().elem().elem().elem();
209 
210  F restartTol;
211  if (EigBiInfo.ncurEvals < EigBiInfo.evals.size())
212  restartTol = 0.0; // Do not restart the first phase
213  else {
214  // set it to the user parameter:
215  restartTol = invParam.restartTol.elem().elem().elem().elem();
216 
217  // restartTol = EigInfo.restartTol; //or restart with tol as computed
218  }
219  F epsi = invParam.epsi.elem().elem().elem().elem() ;
220 
221  IncrEigBiCG(EigBiInfo.N, EigBiInfo.lde, 1, X, B,
222  &EigBiInfo.ncurEvals, EigBiInfo.evals.size(),
223  evecsL, evecsR, evals, H,
224  MatrixMatvec<F,T,PLUS>, // mat vec
225  MatrixMatvec<F,T,MINUS> ,// hermitian conjugate mat vec
226  (void *)&arg,
227  &AnormEst,
228  work,
229  VL, EigBiInfo.lde, VR, EigBiInfo.lde,
230  ework, esize,
231  resid, &restartTol,
232  invParam.MaxCG,
233  invParam.sort_option.c_str()[0],
234  epsi,
235  invParam.ConvTestOpt,
236  invParam.PrintLevel,
237  invParam.Neig, invParam.Nmax, stdout);
238 
239  // NO NEED OF THIS
240  // Copy result back
241  // psi = psif;
242 
243  T tt;
244  (*A)(tt,psi,PLUS);
245  QDPIO::cout<<"OPT_EIGBiCG_SYSSOLVER: True residual after solution : "<<sqrt(norm2(tt-chi,s))<<std::endl ;
246  QDPIO::cout<<"OPT_EIGBiCG_SYSSOLVER: norm of solution : "<<sqrt(norm2(psi,s))<<std::endl ;
247  QDPIO::cout<<"OPT_EIGBiCG_SYSSOLVER: norm of rhs : "<<sqrt(norm2(chi,s))<<std::endl ;
248 
249 
250 
251  if(!s.hasOrderedRep()){
252  QDPIO::cout<<"OPPS! I have no implemented OPT_EigBiCG for Linops with non contigius subset\n";
253  }
254  END_CODE();
255 
256  return res;
257  }
258 
259  } // anonymous namespace
260 
261 
262  //
263  // Wrappers
264  //
265 
266  // LatticeFermionF
267  template<>
268  SystemSolverResults_t
269  LinOpSysSolverOptEigBiCG<LatticeFermionF>::operator()(LatticeFermionF& psi, const LatticeFermionF& chi) const
270  {
271  return sysSolver<LatticeFermionF,float,Complex_C>(psi, chi, A, invParam);
272  }
273 
274  // LatticeFermionD
275  template<>
277  LinOpSysSolverOptEigBiCG<LatticeFermionD>::operator()(LatticeFermionD& psi, const LatticeFermionD& chi) const
278  {
279  return sysSolver<LatticeFermionD, double, Complex_Z>(psi, chi, A, invParam);
280  }
281 
282 #if 0
283 
284 
285  // Not quite ready yet for these - almost there
286  // LatticeStaggeredFermionF
287  template<>
289  LinOpSysSolverOptEigBiCG<LatticeStaggeredFermionF>::operator()(LatticeStaggeredFermionF& psi, const LatticeStaggeredFermionF& chi) const
290  {
291  return sysSolver(psi, chi, A, invParam);
292  }
293 
294  // LatticeStaggeredFermionD
295  template<>
296  SystemSolverResults_t
297  LinOpSysSolverOptEigBiCG<LatticeStaggeredFermionD>::operator()(LatticeStaggeredFermionD& psi, const LatticeStaggeredFermionD& chi) const
298  {
299  return sysSolver(psi, chi, A, invParam);
300  }
301 #endif
302 
303 }
Support class for fermion actions and linear operators.
Definition: state.h:94
Class for counted reference semantics.
Definition: handle.h:33
Solve a M*psi=chi linear system by biCG with eigenvectors.
SystemSolverResults_t operator()(T &psi, const T &chi) const
Solver the linear system.
static T & Instance()
Definition: singleton.h:432
Params params
unsigned n
Definition: ldumul_w.cc:36
int y
Definition: meslate.cc:35
int x
Definition: meslate.cc:34
SpinMatrix C()
C = Gamma(10)
Definition: barspinmat_w.cc:29
LinOpSystemSolver< LatticeStaggeredFermion > * createStagFerm(XMLReader &xml_in, const std::string &path, Handle< LinearOperator< LatticeStaggeredFermion > > A)
Callback function.
bool registerAll()
Register all the factories.
LinOpSystemSolver< 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_BiCG_INVERTER")
Name to be used.
static bool registered
Local registration flag.
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
@ 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)
::std::string string
Definition: gtest.h:1979
Holds return info from SystemSolver call.
Definition: syssolver.h:17
Handle< LinearOperator< T > > LinOp
Solve a M*psi=chi linear system by EigBiCG.
Register linop system solvers that solve M*psi=chi.
Factory for solving M*psi=chi where M is not hermitian or pos. def.
LatticeFermion T
Definition: t_clover.cc:11
static INTERNAL_PRECISION F