QUDA  v1.1.0
A library for QCD on GPUs
invert_test.cpp
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <time.h>
4 #include <math.h>
5 #include <string.h>
6 
7 // QUDA headers
8 #include <quda.h>
9 #include <color_spinor_field.h> // convenient quark field container
10 
11 // External headers
12 #include <misc.h>
13 #include <host_utils.h>
14 #include <command_line_params.h>
15 #include <dslash_reference.h>
16 
17 #define MAX(a, b) ((a) > (b) ? (a) : (b))
18 
20 {
21  printfQuda("running the following test:\n");
22  printfQuda("prec prec_sloppy multishift matpc_type recon recon_sloppy solve_type S_dimension T_dimension "
23  "Ls_dimension dslash_type normalization\n");
24  printfQuda(
25  "%6s %6s %d %12s %2s %2s %10s %3d/%3d/%3d %3d %2d %14s %8s\n",
29 
30  if (inv_multigrid) {
31  printfQuda("MG parameters\n");
32  printfQuda(" - number of levels %d\n", mg_levels);
33  for (int i = 0; i < mg_levels - 1; i++) {
34  printfQuda(" - level %d number of null-space vectors %d\n", i + 1, nvec[i]);
35  printfQuda(" - level %d number of pre-smoother applications %d\n", i + 1, nu_pre[i]);
36  printfQuda(" - level %d number of post-smoother applications %d\n", i + 1, nu_post[i]);
37  }
38 
39  printfQuda("MG Eigensolver parameters\n");
40  for (int i = 0; i < mg_levels; i++) {
41  if (low_mode_check || mg_eig[i]) {
42  printfQuda(" - level %d solver mode %s\n", i + 1, get_eig_type_str(mg_eig_type[i]));
43  printfQuda(" - level %d spectrum requested %s\n", i + 1, get_eig_spectrum_str(mg_eig_spectrum[i]));
45  printfQuda(" - eigenvector block size %d\n", mg_eig_block_size[i]);
46  printfQuda(" - level %d number of eigenvectors requested n_conv %d\n", i + 1, nvec[i]);
47  printfQuda(" - level %d size of eigenvector search space %d\n", i + 1, mg_eig_n_ev[i]);
48  printfQuda(" - level %d size of Krylov space %d\n", i + 1, mg_eig_n_kr[i]);
49  printfQuda(" - level %d solver tolerance %e\n", i + 1, mg_eig_tol[i]);
50  printfQuda(" - level %d convergence required (%s)\n", i + 1, mg_eig_require_convergence[i] ? "true" : "false");
51  printfQuda(" - level %d Operator: daggered (%s) , norm-op (%s)\n", i + 1,
52  mg_eig_use_dagger[i] ? "true" : "false", mg_eig_use_normop[i] ? "true" : "false");
53  if (mg_eig_use_poly_acc[i]) {
54  printfQuda(" - level %d Chebyshev polynomial degree %d\n", i + 1, mg_eig_poly_deg[i]);
55  printfQuda(" - level %d Chebyshev polynomial minumum %e\n", i + 1, mg_eig_amin[i]);
56  if (mg_eig_amax[i] <= 0)
57  printfQuda(" - level %d Chebyshev polynomial maximum will be computed\n", i + 1);
58  else
59  printfQuda(" - level %d Chebyshev polynomial maximum %e\n", i + 1, mg_eig_amax[i]);
60  }
61  printfQuda("\n");
62  }
63  }
64  }
65 
66  if (inv_deflate) {
67  printfQuda("\n Eigensolver parameters\n");
68  printfQuda(" - solver mode %s\n", get_eig_type_str(eig_type));
69  printfQuda(" - spectrum requested %s\n", get_eig_spectrum_str(eig_spectrum));
70  if (eig_type == QUDA_EIG_BLK_TR_LANCZOS) printfQuda(" - eigenvector block size %d\n", eig_block_size);
71  printfQuda(" - number of eigenvectors requested %d\n", eig_n_conv);
72  printfQuda(" - size of eigenvector search space %d\n", eig_n_ev);
73  printfQuda(" - size of Krylov space %d\n", eig_n_kr);
74  printfQuda(" - solver tolerance %e\n", eig_tol);
75  printfQuda(" - convergence required (%s)\n", eig_require_convergence ? "true" : "false");
76  if (eig_compute_svd) {
77  printfQuda(" - Operator: MdagM. Will compute SVD of M\n");
78  printfQuda(" - ***********************************************************\n");
79  printfQuda(" - **** Overriding any previous choices of operator type. ****\n");
80  printfQuda(" - **** SVD demands normal operator, will use MdagM ****\n");
81  printfQuda(" - ***********************************************************\n");
82  } else {
83  printfQuda(" - Operator: daggered (%s) , norm-op (%s)\n", eig_use_dagger ? "true" : "false",
84  eig_use_normop ? "true" : "false");
85  }
86  if (eig_use_poly_acc) {
87  printfQuda(" - Chebyshev polynomial degree %d\n", eig_poly_deg);
88  printfQuda(" - Chebyshev polynomial minumum %e\n", eig_amin);
89  if (eig_amax <= 0)
90  printfQuda(" - Chebyshev polynomial maximum will be computed\n");
91  else
92  printfQuda(" - Chebyshev polynomial maximum %e\n\n", eig_amax);
93  }
94  }
95 
96  printfQuda("Grid partition info: X Y Z T\n");
97  printfQuda(" %d %d %d %d\n", dimPartitioned(0), dimPartitioned(1), dimPartitioned(2),
98  dimPartitioned(3));
99 }
100 
101 int main(int argc, char **argv)
102 {
104  // Parse command line options
105  auto app = make_app();
111  try {
112  app->parse(argc, argv);
113  } catch (const CLI::ParseError &e) {
114  return app->exit(e);
115  }
116 
117  if (inv_deflate && inv_multigrid) {
118  printfQuda("Error: Cannot use both deflation and multigrid preconditioners on top level solve.\n");
119  exit(0);
120  }
121 
122  // If a value greater than 1 is passed, heavier masses will be constructed
123  // and the multi-shift solver will be called
124  if (multishift > 1) {
125  // set a correct default for the multi-shift solver
127  }
128 
129  // Set values for precisions via the command line.
131 
132  // initialize QMP/MPI, QUDA comms grid and RNG (host_utils.cpp)
133  initComms(argc, argv, gridsize_from_cmdline);
134 
139  printfQuda("dslash_type %d not supported\n", dslash_type);
140  exit(0);
141  }
142 
143  if (inv_multigrid) {
144  // Only these fermions are supported with MG
147  printfQuda("dslash_type %d not supported for MG\n", dslash_type);
148  exit(0);
149  }
150 
151  // Only these solve types are supported with MG
153  printfQuda("Solve_type %d not supported with MG. Please use QUDA_DIRECT_SOLVE or QUDA_DIRECT_PC_SOLVE\n\n",
154  solve_type);
155  exit(0);
156  }
157  }
158 
159  // Set QUDA's internal parameters
164  QudaInvertParam mg_inv_param = newQudaInvertParam();
165  QudaEigParam mg_eig_param[mg_levels];
166  QudaEigParam eig_param = newQudaEigParam();
167 
168  if (inv_multigrid) {
169 
172  // Set sub structures
173  mg_param.invert_param = &mg_inv_param;
174  for (int i = 0; i < mg_levels; i++) {
175  if (mg_eig[i]) {
176  mg_eig_param[i] = newQudaEigParam();
177  setMultigridEigParam(mg_eig_param[i], i);
178  mg_param.eig_param[i] = &mg_eig_param[i];
179  } else {
180  mg_param.eig_param[i] = nullptr;
181  }
182  }
183  // Set MG
184  setMultigridParam(mg_param);
185  } else {
187  }
188 
189  if (inv_deflate) {
190  setEigParam(eig_param);
191  inv_param.eig_param = &eig_param;
192  } else {
193  inv_param.eig_param = nullptr;
194  }
195 
196  // All parameters have been set. Display the parameters via stdout
198 
199  // Initialize the QUDA library
201 
202  // params corresponds to split grid
207 
208  int num_sub_partition = grid_partition[0] * grid_partition[1] * grid_partition[2] * grid_partition[3];
209  bool use_split_grid = num_sub_partition > 1;
210 
211  // set parameters for the reference Dslash, and prepare fields to be loaded
215  } else {
217  }
218 
219  // Allocate host side memory for the gauge field.
220  //----------------------------------------------------------------------------
221  void *gauge[4];
222  // Allocate space on the host (always best to allocate and free in the same scope)
223  for (int dir = 0; dir < 4; dir++) gauge[dir] = malloc(V * gauge_site_size * host_gauge_data_type_size);
224  constructHostGaugeField(gauge, gauge_param, argc, argv);
225  // Load the gauge field to the device
226  loadGaugeQuda((void *)gauge, &gauge_param);
227 
228  // Allocate host side memory for clover terms if needed.
229  //----------------------------------------------------------------------------
230  void *clover = nullptr;
231  void *clover_inv = nullptr;
232  // Allocate space on the host (always best to allocate and free in the same scope)
234  clover = malloc(V * clover_site_size * host_clover_data_type_size);
235  clover_inv = malloc(V * clover_site_size * host_spinor_data_type_size);
236  constructHostCloverField(clover, clover_inv, inv_param);
237  if (inv_multigrid) {
238  // This line ensures that if we need to construct the clover inverse (in either the smoother or the solver) we do so
241  }
242  }
243  // Load the clover terms to the device
244  loadCloverQuda(clover, clover_inv, &inv_param);
245  if (inv_multigrid) {
246  // Restore actual solve_type we want to do
248  }
249  }
250 
251  // Now QUDA is initialised and the fields are loaded, we may setup the preconditioner
252  void *mg_preconditioner = nullptr;
253  if (inv_multigrid) {
254  if (use_split_grid) { errorQuda("Split grid does not work with MG yet."); }
255  mg_preconditioner = newMultigridQuda(&mg_param);
256  inv_param.preconditioner = mg_preconditioner;
257  }
258 
259  // Compute plaquette as a sanity check
260  double plaq[3];
261  plaqQuda(plaq);
262  printfQuda("Computed plaquette is %e (spatial = %e, temporal = %e)\n", plaq[0], plaq[1], plaq[2]);
263 
264  // Vector construct START
265  //-----------------------------------------------------------------------------------
266  std::vector<quda::ColorSpinorField *> in(Nsrc);
267  std::vector<quda::ColorSpinorField *> out(Nsrc);
268  std::vector<quda::ColorSpinorField *> out_multishift(multishift * Nsrc);
269  quda::ColorSpinorField *check;
270  quda::ColorSpinorParam cs_param;
272  check = quda::ColorSpinorField::Create(cs_param);
273  std::vector<std::vector<void *>> _hp_multi_x(Nsrc, std::vector<void *>(multishift));
274 
275  // QUDA host array for internal checks and malloc
276  // Vector construct END
277  //-----------------------------------------------------------------------------------
278 
279  // Quark masses
280  std::vector<double> masses(multishift);
281 
282  // QUDA invert test BEGIN
283  //----------------------------------------------------------------------------
284  if (multishift > 1) {
285  if (use_split_grid) { errorQuda("Split grid does not work with multishift yet."); }
287  for (int i = 0; i < multishift; i++) {
288  // Set masses and offsets
289  masses[i] = 0.06 + i * i * 0.01;
290  inv_param.offset[i] = 4 * masses[i] * masses[i];
291  // Set tolerances for the heavy quarks, these can be set independently
292  // (functions of i) if desired
295  // Allocate memory and set pointers
296  for (int n = 0; n < Nsrc; n++) {
297  out_multishift[n * multishift + i] = quda::ColorSpinorField::Create(cs_param);
298  _hp_multi_x[n][i] = out_multishift[n * multishift + i]->V();
299  }
300  }
301  }
302 
303  std::vector<double> time(Nsrc);
304  std::vector<double> gflops(Nsrc);
305  std::vector<int> iter(Nsrc);
306 
307  auto *rng = new quda::RNG(quda::LatticeFieldParam(gauge_param), 1234);
308  rng->Init();
309 
310  std::vector<quda::ColorSpinorField *> _h_b(Nsrc, nullptr);
311  std::vector<quda::ColorSpinorField *> _h_x(Nsrc, nullptr);
312 
313  for (int i = 0; i < Nsrc; i++) {
314  // Populate the host spinor with random numbers.
315  in[i] = quda::ColorSpinorField::Create(cs_param);
316  in[i]->Source(QUDA_RANDOM_SOURCE);
317  out[i] = quda::ColorSpinorField::Create(cs_param);
318  }
319 
320  if (!use_split_grid) {
321 
322  for (int i = 0; i < Nsrc; i++) {
323  // If deflating, preserve the deflation space between solves
325  // Perform QUDA inversions
326  if (multishift > 1) {
327  invertMultiShiftQuda(_hp_multi_x[i].data(), in[i]->V(), &inv_param);
328  } else {
329  invertQuda(out[i]->V(), in[i]->V(), &inv_param);
330  }
331 
332  time[i] = inv_param.secs;
333  gflops[i] = inv_param.gflops / inv_param.secs;
334  iter[i] = inv_param.iter;
335  printfQuda("Done: %i iter / %g secs = %g Gflops\n\n", inv_param.iter, inv_param.secs,
337  }
338  } else {
340  inv_param.num_src_per_sub_partition = Nsrc / num_sub_partition;
341  // Host arrays for solutions, sources, and check
342  std::vector<void *> _hp_x(Nsrc);
343  std::vector<void *> _hp_b(Nsrc);
344  for (int i = 0; i < Nsrc; i++) {
345  _hp_x[i] = out[i]->V();
346  _hp_b[i] = in[i]->V();
347  }
348  // Run split grid
351  invertMultiSrcCloverQuda(_hp_x.data(), _hp_b.data(), &inv_param, (void *)gauge, &gauge_param, clover, clover_inv);
352  } else {
353  invertMultiSrcQuda(_hp_x.data(), _hp_b.data(), &inv_param, (void *)gauge, &gauge_param);
354  }
356  inv_param.iter /= comm_size() / num_sub_partition;
358  inv_param.gflops /= comm_size() / num_sub_partition;
360  printfQuda("Done: %d sub-partitions - %i iter / %g secs = %g Gflops\n\n", num_sub_partition, inv_param.iter,
362  }
363 
364  // QUDA invert test COMPLETE
365  //----------------------------------------------------------------------------
366 
367  rng->Release();
368  delete rng;
369 
370  // free the multigrid solver
371  if (inv_multigrid) destroyMultigridQuda(mg_preconditioner);
372 
373  // Compute performance statistics
374  if (Nsrc > 1 && !use_split_grid) performanceStats(time, gflops, iter);
375 
376  // Perform host side verification of inversion if requested
377  if (verify_results) {
378  for (int i = 0; i < Nsrc; i++) {
379  verifyInversion(out[i]->V(), _hp_multi_x[i].data(), in[i]->V(), check->V(), gauge_param, inv_param, gauge, clover,
380  clover_inv);
381  }
382  }
383 
384  // Clean up memory allocations
385  delete check;
386  if (multishift > 1) {
387  for (auto p : out_multishift) { delete p; }
388  }
389 
390  for (auto p : in) { delete p; }
391  for (auto p : out) { delete p; }
392 
393  freeGaugeQuda();
394  for (int dir = 0; dir < 4; dir++) free(gauge[dir]);
395 
397  freeCloverQuda();
398  if (clover) free(clover);
399  if (clover_inv) free(clover_inv);
400  }
401 
402  // finalize the QUDA library
403  endQuda();
404  finalizeComms();
405 
406  return 0;
407 }
static ColorSpinorField * Create(const ColorSpinorParam &param)
Class declaration to initialize and hold CURAND RNG states.
Definition: random_quda.h:23
int comm_size(void)
void comm_allreduce_int(int *data)
void comm_allreduce_max(double *data)
void comm_allreduce(double *data)
bool inv_multigrid
QudaSolveType solve_type
int eig_poly_deg
QudaEigType eig_type
quda::mgarray< int > mg_eig_poly_deg
quda::mgarray< QudaEigType > mg_eig_type
QudaReconstructType link_recon_sloppy
int eig_n_ev
std::shared_ptr< QUDAApp > make_app(std::string app_description, std::string app_name)
double eig_tol
QudaReconstructType link_recon
quda::mgarray< bool > mg_eig
int device_ordinal
bool eig_compute_svd
int & ydim
void add_multigrid_option_group(std::shared_ptr< QUDAApp > quda_app)
bool eig_use_poly_acc
std::array< int, 4 > grid_partition
bool verify_results
quda::mgarray< int > nu_post
quda::mgarray< int > nu_pre
quda::mgarray< int > mg_eig_n_kr
quda::mgarray< double > mg_eig_amin
int eig_block_size
double eig_amax
quda::mgarray< int > nvec
void add_eofa_option_group(std::shared_ptr< QUDAApp > quda_app)
bool eig_use_dagger
bool inv_deflate
quda::mgarray< QudaEigSpectrumType > mg_eig_spectrum
int & zdim
QudaSolutionType solution_type
QudaDslashType dslash_type
bool eig_use_normop
quda::mgarray< bool > mg_eig_use_dagger
bool low_mode_check
quda::mgarray< int > mg_eig_n_ev
int eig_n_kr
int mg_levels
quda::mgarray< double > mg_eig_amax
void add_eigen_option_group(std::shared_ptr< QUDAApp > quda_app)
int eig_n_conv
QudaMatPCType matpc_type
int multishift
QudaEigSpectrumType eig_spectrum
quda::mgarray< bool > mg_eig_use_poly_acc
int Nsrc
quda::mgarray< double > mg_eig_tol
void add_deflation_option_group(std::shared_ptr< QUDAApp > quda_app)
quda::mgarray< bool > mg_eig_use_normop
QudaPrecision prec
int Lsdim
bool eig_require_convergence
int & tdim
quda::mgarray< bool > mg_eig_require_convergence
quda::mgarray< int > mg_eig_block_size
int & xdim
void add_comms_option_group(std::shared_ptr< QUDAApp > quda_app)
double eig_amin
std::array< int, 4 > gridsize_from_cmdline
QudaMassNormalization normalization
QudaPrecision prec_sloppy
int V
Definition: host_utils.cpp:37
void setDims(int *)
Definition: host_utils.cpp:315
QudaGaugeParam gauge_param
Definition: covdev_test.cpp:26
QudaInvertParam inv_param
Definition: covdev_test.cpp:27
void verifyInversion(void *spinorOut, void *spinorIn, void *spinorCheck, QudaGaugeParam &gauge_param, QudaInvertParam &inv_param, void **gauge, void *clover, void *clover_inv)
@ QUDA_RANDOM_SOURCE
Definition: enum_quda.h:376
@ QUDA_WILSON_DSLASH
Definition: enum_quda.h:90
@ QUDA_TWISTED_CLOVER_DSLASH
Definition: enum_quda.h:100
@ QUDA_MOBIUS_DWF_DSLASH
Definition: enum_quda.h:95
@ QUDA_CLOVER_WILSON_DSLASH
Definition: enum_quda.h:91
@ QUDA_TWISTED_MASS_DSLASH
Definition: enum_quda.h:99
@ QUDA_DOMAIN_WALL_DSLASH
Definition: enum_quda.h:93
@ QUDA_MOBIUS_DWF_EOFA_DSLASH
Definition: enum_quda.h:96
@ QUDA_CLOVER_HASENBUSCH_TWIST_DSLASH
Definition: enum_quda.h:92
@ QUDA_DOMAIN_WALL_4D_DSLASH
Definition: enum_quda.h:94
@ QUDA_BOOLEAN_FALSE
Definition: enum_quda.h:460
@ QUDA_BOOLEAN_TRUE
Definition: enum_quda.h:461
@ QUDA_EIG_BLK_TR_LANCZOS
Definition: enum_quda.h:138
@ QUDA_MATPCDAG_MATPC_SOLUTION
Definition: enum_quda.h:161
@ QUDA_DIRECT_SOLVE
Definition: enum_quda.h:167
@ QUDA_DIRECT_PC_SOLVE
Definition: enum_quda.h:169
#define gauge_site_size
Definition: face_gauge.cpp:34
void constructHostCloverField(void *clover, void *clover_inv, QudaInvertParam &inv_param)
Definition: host_utils.cpp:186
size_t host_gauge_data_type_size
Definition: host_utils.cpp:65
int dimPartitioned(int dim)
Definition: host_utils.cpp:376
void initComms(int argc, char **argv, std::array< int, 4 > &commDims)
Definition: host_utils.cpp:255
size_t host_spinor_data_type_size
Definition: host_utils.cpp:66
void setQudaMgSolveTypes()
Definition: host_utils.cpp:81
void finalizeComms()
Definition: host_utils.cpp:292
void performanceStats(std::vector< double > &time, std::vector< double > &gflops, std::vector< int > &iter)
void setQudaDefaultMgTestParams()
Definition: host_utils.cpp:89
size_t host_clover_data_type_size
Definition: host_utils.cpp:67
void dw_setDims(int *X, const int L5)
Definition: host_utils.cpp:353
void setQudaPrecisions()
Definition: host_utils.cpp:69
void constructHostGaugeField(void **gauge, QudaGaugeParam &gauge_param, int argc, char **argv)
Definition: host_utils.cpp:166
void constructWilsonTestSpinorParam(quda::ColorSpinorParam *cs_param, const QudaInvertParam *inv_param, const QudaGaugeParam *gauge_param)
Definition: host_utils.cpp:207
#define clover_site_size
Definition: host_utils.h:11
void setWilsonGaugeParam(QudaGaugeParam &gauge_param)
Definition: set_params.cpp:37
void setMultigridInvertParam(QudaInvertParam &inv_param)
Definition: set_params.cpp:600
void setEigParam(QudaEigParam &eig_param)
Definition: set_params.cpp:263
void setMultigridEigParam(QudaEigParam &eig_param, int level)
Definition: set_params.cpp:712
void setMultigridParam(QudaMultigridParam &mg_param)
Definition: set_params.cpp:326
int main(int argc, char **argv)
void display_test_info()
Definition: invert_test.cpp:19
void setInvertParam(QudaInvertParam &invertParam, QudaInvertArgs_t &inv_args, int external_precision, int quda_precision, double kappa, double reliable_delta)
const char * get_matpc_str(QudaMatPCType type)
Definition: misc.cpp:200
const char * get_prec_str(QudaPrecision prec)
Definition: misc.cpp:26
const char * get_solve_str(QudaSolveType type)
Definition: misc.cpp:231
const char * get_eig_spectrum_str(QudaEigSpectrumType type)
Definition: misc.cpp:154
const char * get_dslash_str(QudaDslashType type)
Definition: misc.cpp:118
const char * get_eig_type_str(QudaEigType type)
Definition: misc.cpp:171
const char * get_mass_normalization_str(QudaMassNormalization type)
Definition: misc.cpp:186
const char * get_recon_str(QudaReconstructType recon)
Definition: misc.cpp:68
Main header file for the QUDA library.
void invertMultiSrcQuda(void **_hp_x, void **_hp_b, QudaInvertParam *param, void *h_gauge, QudaGaugeParam *gauge_param)
Perform the solve like @invertQuda but for multiple rhs by spliting the comm grid into sub-partitions...
void * newMultigridQuda(QudaMultigridParam *param)
void plaqQuda(double plaq[3])
QudaGaugeParam newQudaGaugeParam(void)
void invertMultiSrcCloverQuda(void **_hp_x, void **_hp_b, QudaInvertParam *param, void *h_gauge, QudaGaugeParam *gauge_param, void *h_clover, void *h_clovinv)
Really the same with @invertMultiSrcQuda but for clover-style fermions, by accepting pointers to dire...
void invertMultiShiftQuda(void **_hp_x, void *_hp_b, QudaInvertParam *param)
void freeGaugeQuda(void)
void initQuda(int device)
QudaMultigridParam newQudaMultigridParam(void)
void loadGaugeQuda(void *h_gauge, QudaGaugeParam *param)
void loadCloverQuda(void *h_clover, void *h_clovinv, QudaInvertParam *inv_param)
void freeCloverQuda(void)
QudaInvertParam newQudaInvertParam(void)
QudaEigParam newQudaEigParam(void)
void endQuda(void)
void destroyMultigridQuda(void *mg_instance)
Free resources allocated by the multigrid solver.
void invertQuda(void *h_x, void *h_b, QudaInvertParam *param)
QudaBoolean preserve_deflation
Definition: quda.h:431
int X[4]
Definition: quda.h:35
QudaSolveType solve_type
Definition: quda.h:229
double gflops
Definition: quda.h:277
double tol_hq
Definition: quda.h:140
double tol_hq_offset[QUDA_MAX_MULTI_SHIFT]
Definition: quda.h:206
int num_offset
Definition: quda.h:186
int split_grid[QUDA_MAX_DIM]
Definition: quda.h:195
int num_src_per_sub_partition
Definition: quda.h:190
double secs
Definition: quda.h:278
double offset[QUDA_MAX_MULTI_SHIFT]
Definition: quda.h:200
double tol_offset[QUDA_MAX_MULTI_SHIFT]
Definition: quda.h:203
void * eig_param
Definition: quda.h:306
double tol
Definition: quda.h:138
void * preconditioner
Definition: quda.h:300
QudaEigParam * eig_param[QUDA_MAX_MG_LEVEL]
Definition: quda.h:553
QudaSolveType smoother_solve_type[QUDA_MAX_MG_LEVEL]
Definition: quda.h:662
QudaInvertParam * invert_param
Definition: quda.h:551
#define printfQuda(...)
Definition: util_quda.h:114
#define errorQuda(...)
Definition: util_quda.h:120