QUDA  0.9.0
solver.cpp
Go to the documentation of this file.
1 #include <quda_internal.h>
2 #include <invert_quda.h>
3 #include <multigrid.h>
4 #include <cmath>
5 
6 namespace quda {
7 
8  static void report(const char *type) {
9  if (getVerbosity() >= QUDA_VERBOSE) printfQuda("Creating a %s solver\n", type);
10  }
11 
12  // solver factory
14  DiracMatrix &matPrecon, TimeProfile &profile)
15  {
16  Solver *solver=0;
17 
19  errorQuda("Explicit preconditoner not supported for %d solver", param.inv_type);
20 
22  errorQuda("Explicit preconditoner not supported for %d preconditioner", param.inv_type_precondition);
23 
24  switch (param.inv_type) {
25  case QUDA_CG_INVERTER:
26  report("CG");
27  solver = new CG(mat, matSloppy, param, profile);
28  break;
30  report("BiCGstab");
31  solver = new BiCGstab(mat, matSloppy, matPrecon, param, profile);
32  break;
33  case QUDA_GCR_INVERTER:
34  report("GCR");
35  if (param.preconditioner && param.maxiter == 11) { // FIXME - dirty hack
36  MG *mg = static_cast<MG*>(param.preconditioner);
37  solver = new GCR(mat, *(mg), matSloppy, matPrecon, param, profile);
38  } else if (param.preconditioner) {
40  // FIXME dirty hack to ensure that preconditioner precision set in interface isn't used in the outer GCR-MG solver
42  solver = new GCR(mat, *(mg->mg), matSloppy, matPrecon, param, profile);
43  } else {
44  solver = new GCR(mat, matSloppy, matPrecon, param, profile);
45  }
46  break;
47  case QUDA_MR_INVERTER:
48  report("MR");
49  solver = new MR(mat, matSloppy, param, profile);
50  break;
51  case QUDA_SD_INVERTER:
52  report("SD");
53  solver = new SD(mat, param, profile);
54  break;
55  case QUDA_XSD_INVERTER:
56 #ifdef MULTI_GPU
57  report("XSD");
58  solver = new XSD(mat, param, profile);
59 #else
60  errorQuda("Extended Steepest Descent is multi-gpu only");
61 #endif
62  break;
63  case QUDA_PCG_INVERTER:
64  report("PCG");
65  solver = new PreconCG(mat, matSloppy, matPrecon, param, profile);
66  break;
67  case QUDA_MPCG_INVERTER:
68  report("MPCG");
69  solver = new MPCG(mat, param, profile);
70  break;
72  report("MPBICGSTAB");
73  solver = new MPBiCGstab(mat, param, profile);
74  break;
76  report("BICGSTABL");
77  solver = new BiCGstabL(mat, matSloppy, param, profile);
78  break;
80  report("EIGCG");
81  solver = new IncEigCG(mat, matSloppy, matPrecon, param, profile);
82  break;
84  report("INC EIGCG");
85  solver = new IncEigCG(mat, matSloppy, matPrecon, param, profile);
86  break;
88  report("GMRESDR");
89  if (param.preconditioner) {
91  // FIXME dirty hack to ensure that preconditioner precision set in interface isn't used in the outer GCR-MG solver
93  solver = new GMResDR(mat, *(mg->mg), matSloppy, matPrecon, param, profile);
94  } else {
95  solver = new GMResDR(mat, matSloppy, matPrecon, param, profile);
96  }
97  break;
98  case QUDA_CGNE_INVERTER:
99  report("CGNE");
100  solver = new CGNE(mat, matSloppy, param, profile);
101  break;
102  case QUDA_CGNR_INVERTER:
103  report("CGNR");
104  solver = new CGNR(mat, matSloppy, param, profile);
105  break;
106  default:
107  errorQuda("Invalid solver type %d", param.inv_type);
108  }
109 
110  return solver;
111  }
112 
113 
115  for (int i = 0; i < param.num_src; i++) {
116  (*this)(out.Component(i), in.Component(i));
119  }
120  }
121 
122  double Solver::stopping(const double &tol, const double &b2, QudaResidualType residual_type) {
123 
124  double stop=0.0;
125  if ( (residual_type & QUDA_L2_ABSOLUTE_RESIDUAL) &&
126  (residual_type & QUDA_L2_RELATIVE_RESIDUAL) ) {
127  // use the most stringent stopping condition
128  double lowest = (b2 < 1.0) ? b2 : 1.0;
129  stop = lowest*tol*tol;
130  } else if (residual_type & QUDA_L2_ABSOLUTE_RESIDUAL) {
131  stop = tol*tol;
132  } else {
133  stop = b2*tol*tol;
134  }
135 
136  return stop;
137  }
138 
139  bool Solver::convergence(const double &r2, const double &hq2, const double &r2_tol,
140  const double &hq_tol) {
141  //printf("converge: L2 %e / %e and HQ %e / %e\n", r2, r2_tol, hq2, hq_tol);
142 
143  // check the heavy quark residual norm if necessary
144  if ( (param.residual_type & QUDA_HEAVY_QUARK_RESIDUAL) && (hq2 > hq_tol) )
145  return false;
146 
147  // check the L2 relative residual norm if necessary
149  (param.residual_type & QUDA_L2_ABSOLUTE_RESIDUAL)) && (r2 > r2_tol) )
150  return false;
151 
152  return true;
153  }
154 
155 //
156  bool Solver::convergenceHQ(const double &r2, const double &hq2, const double &r2_tol,
157  const double &hq_tol) {
158  //printf("converge: L2 %e / %e and HQ %e / %e\n", r2, r2_tol, hq2, hq_tol);
159 
160  // check the heavy quark residual norm if necessary
161  if ( (param.residual_type & QUDA_HEAVY_QUARK_RESIDUAL) && (hq2 > hq_tol) )
162  return false;
163 
164  return true;
165  }
166 
167  bool Solver::convergenceL2(const double &r2, const double &hq2, const double &r2_tol,
168  const double &hq_tol) {
169  //printf("converge: L2 %e / %e and HQ %e / %e\n", r2, r2_tol, hq2, hq_tol);
170 
171  // check the L2 relative residual norm if necessary
173  (param.residual_type & QUDA_L2_ABSOLUTE_RESIDUAL)) && (r2 > r2_tol) )
174  return false;
175 
176  return true;
177  }
178 
179  void Solver::PrintStats(const char* name, int k, const double &r2,
180  const double &b2, const double &hq2) {
181  if (getVerbosity() >= QUDA_VERBOSE) {
183  printfQuda("%s: %d iterations, <r,r> = %e, |r|/|b| = %e, heavy-quark residual = %e\n",
184  name, k, r2, sqrt(r2/b2), hq2);
185  } else {
186  printfQuda("%s: %d iterations, <r,r> = %e, |r|/|b| = %e\n",
187  name, k, r2, sqrt(r2/b2));
188  }
189  }
190 
191  if (std::isnan(r2)) errorQuda("Solver appears to have diverged");
192  }
193 
194  void Solver::PrintSummary(const char *name, int k, const double &r2, const double &b2) {
195  if (getVerbosity() >= QUDA_SUMMARIZE) {
196  if (param.compute_true_res) {
198  printfQuda("%s: Convergence at %d iterations, L2 relative residual: iterated = %e, true = %e, heavy-quark residual = %e\n",
199  name, k, sqrt(r2/b2), param.true_res, param.true_res_hq);
200  } else {
201  printfQuda("%s: Convergence at %d iterations, L2 relative residual: iterated = %e, true = %e\n",
202  name, k, sqrt(r2/b2), param.true_res);
203  }
204  } else {
206  printfQuda("%s: Convergence at %d iterations, L2 relative residual: iterated = %e, heavy-quark residual = %e\n",
207  name, k, sqrt(r2/b2), param.true_res_hq);
208  } else {
209  printfQuda("%s: Convergence at %d iterations, L2 relative residual: iterated = %e\n", name, k, sqrt(r2/b2));
210  }
211  }
212  }
213  }
214 
215 
216  bool MultiShiftSolver::convergence(const double *r2, const double *r2_tol, int n) const {
217 
218  for (int i=0; i<n; i++) {
219  // check the L2 relative residual norm if necessary
221  (param.residual_type & QUDA_L2_ABSOLUTE_RESIDUAL)) && (r2[i] > r2_tol[i]) && r2_tol[i] != 0.0)
222  return false;
223  }
224 
225  return true;
226  }
227 
228 } // namespace quda
bool convergence(const double &r2, const double &hq2, const double &r2_tol, const double &hq_tol)
Definition: solver.cpp:139
static double stopping(const double &tol, const double &b2, QudaResidualType residual_type)
Definition: solver.cpp:122
enum QudaResidualType_s QudaResidualType
QudaInverterType inv_type
Definition: invert_quda.h:19
QudaVerbosity getVerbosity()
Definition: util_quda.cpp:20
SolverParam & param
Definition: invert_quda.h:732
#define errorQuda(...)
Definition: util_quda.h:90
__host__ __device__ ValueType sqrt(ValueType x)
Definition: complex_quda.h:105
bool convergenceL2(const double &r2, const double &hq2, const double &r2_tol, const double &hq_tol)
Definition: solver.cpp:167
TimeProfile & profile
Definition: invert_quda.h:329
QudaInverterType inv_type_precondition
Definition: invert_quda.h:25
QudaGaugeParam param
Definition: pack_test.cpp:17
bool convergence(const double *r2, const double *r2_tol, int n) const
Definition: solver.cpp:216
void PrintSummary(const char *name, int k, const double &r2, const double &b2)
Definition: solver.cpp:194
double tol
Definition: test_util.cpp:1647
QudaResidualType residual_type
Definition: invert_quda.h:47
double true_res_hq_offset[QUDA_MAX_MULTI_SHIFT]
Definition: invert_quda.h:151
cpuColorSpinorField * in
static Solver * create(SolverParam &param, DiracMatrix &mat, DiracMatrix &matSloppy, DiracMatrix &matPrecon, TimeProfile &profile)
Definition: solver.cpp:13
double true_res_offset[QUDA_MAX_MULTI_SHIFT]
Definition: invert_quda.h:145
QudaPrecision precision_precondition
Definition: invert_quda.h:118
virtual void solve(ColorSpinorField &out, ColorSpinorField &in)
Definition: solver.cpp:114
SolverParam & param
Definition: invert_quda.h:328
cpuColorSpinorField * out
static void report(const char *type)
Definition: eig_solver.cpp:7
void * preconditioner
Definition: invert_quda.h:31
void PrintStats(const char *, int k, const double &r2, const double &b2, const double &hq2)
Definition: solver.cpp:179
#define printfQuda(...)
Definition: util_quda.h:84
QudaPrecision precision_sloppy
Definition: invert_quda.h:115
bool convergenceHQ(const double &r2, const double &hq2, const double &r2_tol, const double &hq_tol)
Definition: solver.cpp:156
void mat(void *out, void **link, void *in, int dagger_bit, int mu, QudaPrecision sPrecision, QudaPrecision gPrecision)