CHROMA
eoprec_dwf_qprop_array_cg_dwf_lowmem_w.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /*! \file
3  * \brief 4D style even-odd preconditioned domain-wall fermion action
4  */
5 
6 #include "chroma_config.h"
7 #if defined(CHROMA_USE_CG_DWF_LOWMEM)
8 
9 
10 #ifndef __prec_dwf_qprop_array_cg_dwf_lowmem_w_h__
11 #define __prec_dwf_qprop_array_cg_dwf_lowmem_w_h__
12 
13 
15 #include "io/aniso_io.h"
17 
18 
19 namespace Chroma
20 {
21 
22  //! SSE Propagator DWF qpropT
23  /*! \ingroup qprop
24  *
25  * Propagator solver for DWF fermions
26  */
27  template< typename SinglePrecSolver, typename DoublePrecSolver >
28  class CGDWFQpropT : public SystemSolverArray<LatticeFermion>
29  {
30  public:
31  // Typedefs to save typing
32  typedef LatticeFermion T;
33  typedef multi1d<LatticeColorMatrix> P;
34  typedef multi1d<LatticeColorMatrix> Q;
35 
36 
37  //! Alternative constructor for compatibility
38  /*!
39  * \param m_q_ quark mass ( Read )
40  */
41  CGDWFQpropT(Handle< EvenOddPrecConstDetLinearOperatorArray<T,P,Q> > A_,
42  Handle< LinOpSystemSolverArray<T> > invA_, // throw away
43  Handle< FermState<T,P,Q> > state_,
44  const Real& OverMass_,
45  const Real& Mass_,
46  const AnisoParam_t& anisoParam_,
47  const GroupXML_t& invParam_) :
48  A(A_), OverMass(OverMass_), Mass(Mass_),
49  N5(A->size()), anisoParam(anisoParam_)
50  {init(state_, invParam_);}
51 
52  //! Need a real destructor
53  ~CGDWFQpropT() {fini();}
54 
55  //! Expected length of array index
56  int size() const {return N5;}
57 
58  //! Return the subset on which the operator acts
59  const Subset& subset() const {return all;}
60 
61  //! Solver the linear system
62  /*!
63  * \param psi quark propagator ( Modify )
64  * \param chi source ( Read )
65  * \return number of CG iterations
66  */
67  SystemSolverResults_t operator() (multi1d<LatticeFermion>& psi, const multi1d<LatticeFermion>& chi) const
68  {
69 
70  QDPIO::cout << "entering CGDWFQpropT::operator()" << std::endl;
71 
72  START_CODE();
73 
74  SystemSolverResults_t res;
75 
76  // init(); // only needed because 2 qpropT might be active - SSE CG does not allow this
77 
78  Real ff = where(anisoParam.anisoP, anisoParam.nu / anisoParam.xi_0, Real(1));
79 
80  // Apply SSE inverter
81  Real a5 = 1;
82  double M5 = toDouble(1 + a5*(1 + (Nd-1)*ff - OverMass));
83  double m_f = toDouble(Mass);
84  double out_eps;
85  int single_count = 0;
86  int double_count = 0;
87  res.n_count = 0;
88 
89  StopWatch swatch, swatch_total, swatch_solver;
90  {
91 #ifdef SINGLE_PREC_SOLVER
92  double rsd = toDouble(invParam.RsdCG);
93  double rsd_sq = rsd * rsd;
94  int max_iter = invParam.MaxCG;
95 
96  swatch_total.reset(); swatch_solver.reset();
97  swatch_total.start();
98 
99  // Init solver
100  std::string dwf_error_str = "single prec.";
101 
102  QDPIO::cout << "CGDWFQpropT: Initializing Single Precision Solver " << std::endl;
103  swatch.reset(); swatch.start();
104  int stat = single_prec_solver.init(lattice_size.slice(), NULL, NULL);
105  if ( stat != 0) {
106 
107  QDPIO::cerr << __func__ << ": error in SP solver init: " << dwf_error_str << " error code is " << stat << std::endl;
108  QDP_abort(1);
109  }
110  swatch.stop();
111  QDPIO::cout << "CGDWFQpropT: Single Prec Solver init took: " << swatch.getTimeInSeconds() << " seconds " << std::endl;
112 
113  // load the gauge
114  swatch.reset(); swatch.start();
115  single_prec_solver.loadGauge(&u, &v);
116  swatch.stop();
117  QDPIO::cout << "CGDWFQpropT: Single Precision Gauge Field Import took: " << swatch.getTimeInSeconds() << " seconds " << std::endl;
118 
119 
120  // Call the solver
121  QDPIO::cout << "CGDWFQpropT: Beginning Single Precision Solve" << std::endl;
122  swatch_solver.start();
123  single_prec_solver.cgSolver(psi, M5, m_f,
124  chi, psi, rsd_sq, max_iter, out_eps, single_count);
125  swatch_solver.stop();
126  // Delete the gauge
127  QDPIO::cout << "CGDWFQpropT: Deleting Single Precision Solver Gauge Field " << std::endl;
128  single_prec_solver.deleteGauge();
129 
130  QDPIO::cout << "CGDWFQPropT: Finalizing Single Precision Solver " << std::endl;
131  // Destroy the solver
132  single_prec_solver.fini();
133  swatch_total.stop();
134  double tot_time = swatch_total.getTimeInSeconds();
135  double sol_time = swatch_solver.getTimeInSeconds();
136 
137  QDPIO::cout << "CGDWFQPropT: Total solution time: " << tot_time << " Time in Single Prec Solver: " << sol_time << " Single Prec Overhead: " << 100.0*(tot_time-sol_time)/sol_time << "%" << std::endl;
138 
139  res.n_count += single_count;
140  }
141 #endif
142 #ifdef DOUBLE_PREC_SOLVER
143  {
144 
145  double rsd = toDouble(invParam.RsdCGRestart);
146  double rsd_sq = rsd * rsd;
147  int max_iter = invParam.MaxCGRestart;
148 
149  swatch_total.reset(); swatch_solver.reset();
150  swatch_total.start();
151 
152  // Init the solver
153  std::string dwf_error_str2 = "double prec.";
154 
155  QDPIO::cout << "CGDWFQpropT: Initializing Double Precision Solver " << std::endl;
156  swatch.reset(); swatch.start();
157  int stat2 = double_prec_solver.init(lattice_size.slice(), NULL, NULL);
158  if ( stat2 != 0) {
159  QDPIO::cerr << __func__ << ": error in DP solver init: " << dwf_error_str2 << " error code is " << stat2 << std::endl;
160  QDP_abort(1);
161  }
162  swatch.stop();
163  QDPIO::cout << "CGDWFQpropT: Double Prec Solver init took: " << swatch.getTimeInSeconds() << " seconds " << std::endl;
164 
165  // Load the gauge field
166  swatch.reset(); swatch.start();
167  double_prec_solver.loadGauge(&u, &v);
168  swatch.stop();
169  QDPIO::cout << "Double Precision Gauge Field Import took: " << swatch.getTimeInSeconds() << " seconds " << std::endl;
170 
171  // Do the solve
172  QDPIO::cout << "CGDWFQpropT: Beginning Double Precision Solve" << std::endl;
173  swatch_solver.start();
174  double_prec_solver.cgSolver(psi, M5, m_f,
175  chi, psi, rsd_sq, max_iter, out_eps, double_count);
176  swatch_solver.stop();
177 
178  // Delete the gauge field
179  double_prec_solver.deleteGauge();
180 
181  // Kill the solver
182  double_prec_solver.fini();
183  swatch_total.stop();
184  double tot_time = swatch_total.getTimeInSeconds();
185  double sol_time = swatch_solver.getTimeInSeconds();
186 
187  QDPIO::cout << "CGDWFQPropT: Total solution time: " << tot_time << " Time in Double Prec Solver: " << sol_time << " Double Prec Overhead: " << 100.0*(tot_time-sol_time)/sol_time << "%" << std::endl;
188 
189 
190  res.n_count += double_count;
191  }
192 #endif
193  QDPIO::cout << "CGDWFQpropT: Single Prec. Iters = " << single_count << " Double Prec. Iters = " << double_count << " Total Iters = " << res.n_count << std::endl;
194 
195  {
196  multi1d<LatticeFermion> r(N5);
197  A->unprecLinOp(r, psi, PLUS);
198  r -= chi;
199  res.resid = sqrt(norm2(r));
200  }
201 
202  QDPIO::cout << "exiting CGDWFQpropT::operator()" << std::endl;
203 
204  END_CODE();
205 
206  return res;
207  }
208 
209  protected:
210  //! Private internal initializer
211  void init(Handle< FermState<T,P,Q> > state, const GroupXML_t& inv)
212  {
213  QDPIO::cout << "entering CGDWFQpropT::init" << std::endl;
214 
215  if (Nd != 4 || Nc != 3) {
216 
217  QDPIO::cerr << "CGDWFQpropT: only supports Nd=4 and Nc=3" << std::endl;
218  QDP_abort(1);
219 
220  }
221 
222  // Read the XML for the CG params
223  try {
224 
225  std::istringstream is(inv.xml);
226  XMLReader paramtop(is);
227 
228  read(paramtop, inv.path, invParam);
229  }
230  catch (const std::string& e) {
231 
232  QDPIO::cerr << "CGDWFQpropT: only support a CG inverter" << std::endl;
233  QDP_abort(1);
234  }
235 
236  lattice_size.resize(Nd+1);
237  lattice_size[Nd] = N5;
238 
239  for(int i=0; i < Nd; ++i)
240  lattice_size[i] = Layout::lattSize()[i];
241 
242  if (N5 % 4 != 0) {
243 
244  QDPIO::cerr << "SSE qpropT only N5 that is multiple of 2" << std::endl;
245  QDP_abort(1);
246  }
247 
248  u.resize(Nd);
249  u = state->getLinks();
250 
251  if (anisoParam.anisoP) {
252 
253  Real ff = where(anisoParam.anisoP, anisoParam.nu / anisoParam.xi_0, Real(1));
254 
255  // Rescale the u fields by the anisotropy
256  for(int mu=0; mu < u.size(); ++mu) {
257 
258  if (mu != anisoParam.t_dir)
259  u[mu] *= ff;
260  }
261  }
262 
263  // Construct shifted gauge field
264  v.resize(Nd);
265  for (int i = 0; i < Nd; i++)
266  v[i] = shift(u[i], -1, i); // as viewed from the destination
267 
268  QDPIO::cout << "exiting CGDWFQpropT::init" << std::endl;
269  }
270 
271  //! Private internal destructor
272  void fini() {
273  QDPIO::cout << "CGDWFQpropT: calling destructor" << std::endl;
274  }
275 
276  private:
277 #ifdef SINGLE_PREC_SOLVER
278  mutable SinglePrecSolver single_prec_solver;
279 #endif
280 
281 #ifdef DOUBLE_PREC_SOLVER
282  mutable DoublePrecSolver double_prec_solver;
283 #endif
284 
285  Handle< EvenOddPrecConstDetLinearOperatorArray<T,P,Q> > A;
286  Real OverMass;
287  Real Mass;
288  int N5;
289  AnisoParam_t anisoParam;
290  SysSolverCGParams invParam;
291  multi1d<int> lattice_size;
292  multi1d<LatticeColorMatrix> u;
293  multi1d<LatticeColorMatrix> v;
294  };
295 
296 }
297 #endif
298 
299 #endif // CHROMA_USE_CG_DWF_LOWMEM
Anisotropy parameters.
multi1d< LatticeColorMatrix > P
SystemSolverResults_t operator()(multi1d< LatticeFermion > &psi, const multi1d< LatticeFermion > &chi) const
Solver the linear system.
multi1d< LatticeColorMatrix > Q
void fini()
Private internal destructor.
int size() const
Expected length of array index.
const Subset & subset() const
Return the subset on which the operator acts.
CGDWFQpropT(Handle< EvenOddPrecConstDetLinearOperatorArray< T, P, Q > > A_, Handle< LinOpSystemSolverArray< T > > invA_, Handle< FermState< T, P, Q > > state_, const Real &OverMass_, const Real &Mass_, const AnisoParam_t &anisoParam_, const GroupXML_t &invParam_)
Alternative constructor for compatibility.
~CGDWFQpropT()
Need a real destructor.
void init(Handle< FermState< T, P, Q > > state, const GroupXML_t &inv)
Private internal initializer.
Handle< EvenOddPrecConstDetLinearOperatorArray< T, P, Q > > A
int mu
Definition: cool.cc:24
Even-odd const determinant Wilson-like fermact.
void read(XMLReader &xml, const std::string &path, AsqtadFermActParams &param)
Read parameters.
Nd
Definition: meslate.cc:74
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
static multi1d< LatticeColorMatrix > u
Real rsd_sq
Definition: invbicg.cc:121
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()
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > state
Definition: pbg5p_w.cc:28
::std::string string
Definition: gtest.h:1979
Solve a CG1 system.