QUDA  v1.1.0
A library for QCD on GPUs
quda_arpack_interface.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <iostream>
5 #include <vector>
6 #include <algorithm>
7 
8 #include <quda_internal.h>
10 #include <eigensolve_quda.h>
11 #include <color_spinor_field.h>
12 #include <blas_quda.h>
13 #include <util_quda.h>
14 
15 // ARPACK INTERAFCE ROUTINES
16 //--------------------------------------------------------------------------
17 
18 #if (defined(QMP_COMMS) || defined(MPI_COMMS))
19 #include <mpi.h>
20 #include "mpi_comm_handle.h"
21 #endif
22 
23 namespace quda
24 {
25 
26 #ifdef ARPACK_LIB
27 
28  void arpackErrorHelpNAUPD();
29  void arpackErrorHelpNEUPD();
30 
31  void arpack_solve(std::vector<ColorSpinorField *> &h_evecs, std::vector<Complex> &h_evals, const DiracMatrix &mat,
32  QudaEigParam *eig_param, TimeProfile &profile)
33  {
34  // Create Eigensolver object for member function use
35  EigenSolver *eig_solver = EigenSolver::create(eig_param, mat, profile);
36 
37  profile.TPSTART(QUDA_PROFILE_INIT);
38 
39 // ARPACK logfile name
40 #ifdef ARPACK_LOGGING
41  char *arpack_logfile = eig_param->arpack_logfile;
42 #endif
43  if (getVerbosity() >= QUDA_SUMMARIZE) {
44  printfQuda("**** START ARPACK SOLUTION ****\n");
45 #ifndef ARPACK_LOGGING
46  printfQuda("Arpack logging not enabled.\n");
47 #else
48  printfQuda("Output directed to %s\n", arpack_logfile);
49 #endif
50  }
51 
52  // Construct parameters and memory allocation
53  //---------------------------------------------------------------------------------
54 
55  // MPI objects
56 #if (defined(QMP_COMMS) || defined(MPI_COMMS))
57  int *fcomm_ = nullptr;
58  MPI_Fint mpi_comm_fort = MPI_Comm_c2f(MPI_COMM_HANDLE);
59  fcomm_ = static_cast<int *>(&mpi_comm_fort);
60 #endif
61 
62  // all FORTRAN communication uses underscored
63  int ido_ = 0;
64  int info_ = 1; // if 0, use random vector. If 1, initial residual lives in resid_
65  int *ipntr_ = (int *)safe_malloc(14 * sizeof(int));
66  int *iparam_ = (int *)safe_malloc(11 * sizeof(int));
67  int n_ = h_evecs[0]->Volume() * h_evecs[0]->Nspin() * h_evecs[0]->Ncolor();
68  int n_ev_ = eig_param->n_ev;
69  int n_kr_ = eig_param->n_kr;
70  int ldv_ = h_evecs[0]->Volume() * h_evecs[0]->Nspin() * h_evecs[0]->Ncolor();
71  int lworkl_ = (3 * n_kr_ * n_kr_ + 5 * n_kr_) * 2;
72  int rvec_ = 1;
73  int max_iter = eig_param->max_restarts * (n_kr_ - n_ev_) + n_ev_;
74  int *h_evals_sorted_idx = (int *)safe_malloc(n_kr_ * sizeof(int));
75 
76  // Assign values to ARPACK params
77  iparam_[0] = 1;
78  iparam_[2] = max_iter;
79  iparam_[3] = 1;
80  iparam_[6] = 1;
81 
82  // ARPACK problem type to be solved
83  char howmny = 'P';
84  char bmat = 'I';
85  char spectrum[3];
86 
87  // Part of the spectrum to be computed.
88  switch (eig_param->spectrum) {
89  case QUDA_SPECTRUM_SR_EIG: strcpy(spectrum, "SR"); break;
90  case QUDA_SPECTRUM_LR_EIG: strcpy(spectrum, "LR"); break;
91  case QUDA_SPECTRUM_SM_EIG: strcpy(spectrum, "SM"); break;
92  case QUDA_SPECTRUM_LM_EIG: strcpy(spectrum, "LM"); break;
93  case QUDA_SPECTRUM_SI_EIG: strcpy(spectrum, "SI"); break;
94  case QUDA_SPECTRUM_LI_EIG: strcpy(spectrum, "LI"); break;
95  default: errorQuda("Unexpected spectrum type %d", eig_param->spectrum);
96  }
97 
98  bool reverse = false;
99  if (strncmp("S", spectrum, 1) == 0 && eig_param->use_poly_acc) {
100  // Smallest eig requested by use, largest will requested from ARPACK
101  // due to poly acc
102  reverse = true;
103  spectrum[0] = 'L';
104  }
105 
106  double tol_ = eig_param->tol;
107  double *mod_h_evals_sorted = (double *)safe_malloc(n_kr_ * sizeof(double));
108 
109  // ARPACK workspace
110  Complex I(0.0, 1.0);
111  Complex *resid_ = (Complex *)safe_malloc(ldv_ * sizeof(Complex));
112 
113  // Use initial guess?
114  if (info_ > 0) {
115  for (int a = 0; a < ldv_; a++) resid_[a] = I;
116  }
117 
118  Complex sigma_ = 0.0;
119  Complex *w_workd_ = (Complex *)safe_malloc(3 * ldv_ * sizeof(Complex));
120  Complex *w_workl_ = (Complex *)safe_malloc(lworkl_ * sizeof(Complex));
121  Complex *w_workev_ = (Complex *)safe_malloc(2 * n_kr_ * sizeof(Complex));
122  double *w_rwork_ = (double *)safe_malloc(n_kr_ * sizeof(double));
123  int *select_ = (int *)safe_malloc(n_kr_ * sizeof(int));
124 
125  Complex *h_evecs_ = (Complex *)safe_malloc(n_kr_ * ldv_ * sizeof(Complex));
126  Complex *h_evals_ = (Complex *)safe_malloc(n_ev_ * sizeof(Complex));
127  std::vector<ColorSpinorField *> h_evecs_arpack;
128 
129  for (int i = 0; i < n_kr_; i++) {
130  // create container wrapping the vectors returned from ARPACK
131  ColorSpinorParam param(*h_evecs[0]);
135  param.gammaBasis = QUDA_UKQCD_GAMMA_BASIS;
136  param.v = (Complex *)h_evecs_ + i * ldv_;
137  h_evecs_arpack.push_back(ColorSpinorField::Create(param));
138  }
139 
140  int iter_count = 0;
141 
142  bool allocate = true;
143  ColorSpinorField *h_v = nullptr;
144  ColorSpinorField *d_v = nullptr;
145  ColorSpinorField *h_v2 = nullptr;
146  ColorSpinorField *d_v2 = nullptr;
147  ColorSpinorField *resid = nullptr;
148 
149 #ifdef ARPACK_LOGGING
150  // ARPACK log routines
151  // Code added to print the log of ARPACK
152  int arpack_log_u = 9999;
153 
154 #if (defined(QMP_COMMS) || defined(MPI_COMMS))
155  if (arpack_logfile != NULL && (comm_rank() == 0)) {
156  ARPACK(initlog)(&arpack_log_u, arpack_logfile, strlen(arpack_logfile));
157  int msglvl0 = 9, msglvl3 = 9;
158  ARPACK(pmcinitdebug)
159  (&arpack_log_u, // logfil
160  &msglvl3, // mcaupd
161  &msglvl3, // mcaup2
162  &msglvl0, // mcaitr
163  &msglvl3, // mceigh
164  &msglvl0, // mcapps
165  &msglvl0, // mcgets
166  &msglvl3 // mceupd
167  );
168  if (getVerbosity() >= QUDA_SUMMARIZE) {
169  printfQuda("eigenSolver: Log info:\n");
170  printfQuda("ARPACK verbosity set to mcaup2=3 mcaupd=3 mceupd=3; \n");
171  printfQuda("output is directed to %s\n", arpack_logfile);
172  }
173  }
174 #else
175  if (arpack_logfile != NULL) {
176  ARPACK(initlog)(&arpack_log_u, arpack_logfile, strlen(arpack_logfile));
177  int msglvl0 = 9, msglvl3 = 9;
178  ARPACK(mcinitdebug)
179  (&arpack_log_u, // logfil
180  &msglvl3, // mcaupd
181  &msglvl3, // mcaup2
182  &msglvl0, // mcaitr
183  &msglvl3, // mceigh
184  &msglvl0, // mcapps
185  &msglvl0, // mcgets
186  &msglvl3 // mceupd
187  );
188  if (getVerbosity() >= QUDA_SUMMARIZE) {
189  printfQuda("eigenSolver: Log info:\n");
190  printfQuda("ARPACK verbosity set to mcaup2=3 mcaupd=3 mceupd=3; \n");
191  printfQuda("output is directed to %s\n", arpack_logfile);
192  }
193  }
194 
195 #endif
196 #endif
197 
198  profile.TPSTOP(QUDA_PROFILE_INIT);
199 
200  // Start ARPACK routines
201  //---------------------------------------------------------------------------------
202 
203  do {
204 
205  profile.TPSTART(QUDA_PROFILE_ARPACK);
206 
207  // Interface to arpack routines
208  //----------------------------
209 #if (defined(QMP_COMMS) || defined(MPI_COMMS))
210  ARPACK(pznaupd)
211  (fcomm_, &ido_, &bmat, &n_, spectrum, &n_ev_, &tol_, resid_, &n_kr_, h_evecs_, &n_, iparam_, ipntr_, w_workd_,
212  w_workl_, &lworkl_, w_rwork_, &info_, 1, 2);
213 
214  if (info_ != 0) {
215  arpackErrorHelpNAUPD();
216  errorQuda("\nError in pznaupd info = %d. Exiting.", info_);
217  }
218 #else
219  ARPACK(znaupd)
220  (&ido_, &bmat, &n_, spectrum, &n_ev_, &tol_, resid_, &n_kr_, h_evecs_, &n_, iparam_, ipntr_, w_workd_, w_workl_,
221  &lworkl_, w_rwork_, &info_, 1, 2);
222  if (info_ != 0) {
223  arpackErrorHelpNAUPD();
224  errorQuda("\nError in znaupd info = %d. Exiting.", info_);
225  }
226 #endif
227 
228  profile.TPSTOP(QUDA_PROFILE_ARPACK);
229 
230  // If this is the first iteration, we allocate CPU and GPU memory for QUDA
231  if (allocate) {
232  ColorSpinorParam param(*h_evecs[0]);
236  param.gammaBasis = QUDA_UKQCD_GAMMA_BASIS;
237 
238  // Fortran arrays start at 1. The C++ pointer is therefore the Fortran pointer
239  // less one, hence ipntr[0] - 1 to specify the correct address.
240  param.v = w_workd_ + (ipntr_[0] - 1);
242  // Adjust the position of the start of the array.
243  param.v = w_workd_ + (ipntr_[1] - 1);
245 
246  // create device field temporaries
248  param.create = QUDA_ZERO_FIELD_CREATE;
249  param.setPrecision(param.Precision(), param.Precision(), true);
250 
254  allocate = false;
255  }
256 
257  if (ido_ == 99 || info_ == 1) break;
258 
259  if (ido_ == -1 || ido_ == 1) {
260 
261  profile.TPSTART(QUDA_PROFILE_D2H);
262 
263  *d_v = *h_v;
264 
265  profile.TPSTOP(QUDA_PROFILE_D2H);
266  profile.TPSTART(QUDA_PROFILE_COMPUTE);
267 
268  // apply matrix-vector operation here:
269  eig_solver->chebyOp(mat, *d_v2, *d_v);
270 
271  profile.TPSTOP(QUDA_PROFILE_COMPUTE);
272  profile.TPSTART(QUDA_PROFILE_H2D);
273 
274  *h_v2 = *d_v2;
275 
276  profile.TPSTOP(QUDA_PROFILE_H2D);
277  }
278 
279  if (getVerbosity() >= QUDA_VERBOSE)
280  printfQuda("Arpack Iteration %s: %d\n", eig_param->use_poly_acc ? "(with poly acc) " : "", iter_count);
281  iter_count++;
282 
283  } while (99 != ido_ && iter_count < max_iter);
284 
285  // Subspace calulated sucessfully. Compute n_ev eigenvectors and values
286 
287  if (getVerbosity() >= QUDA_SUMMARIZE) {
288  printfQuda("Finish: iter=%04d info=%d ido=%d\n", iter_count, info_, ido_);
289  printfQuda("Computing eigenvectors\n");
290  }
291 
292  profile.TPSTART(QUDA_PROFILE_ARPACK);
293 
294  // Interface to arpack routines
295  //----------------------------
296 #if (defined(QMP_COMMS) || defined(MPI_COMMS))
297  ARPACK(pzneupd)
298  (fcomm_, &rvec_, &howmny, select_, h_evals_, h_evecs_, &n_, &sigma_, w_workev_, &bmat, &n_, spectrum, &n_ev_, &tol_,
299  resid_, &n_kr_, h_evecs_, &n_, iparam_, ipntr_, w_workd_, w_workl_, &lworkl_, w_rwork_, &info_, 1, 1, 2);
300  if (info_ == -15) {
301  arpackErrorHelpNEUPD();
302  errorQuda("\nError in pzneupd info = %d. You likely need to\n"
303  "increase the maximum ARPACK iterations. Exiting.",
304  info_);
305  } else if (info_ != 0) {
306  arpackErrorHelpNEUPD();
307  errorQuda("\nError in pzneupd info = %d. Exiting.", info_);
308  }
309 #else
310  ARPACK(zneupd)
311  (&rvec_, &howmny, select_, h_evals_, h_evecs_, &n_, &sigma_, w_workev_, &bmat, &n_, spectrum, &n_ev_, &tol_, resid_,
312  &n_kr_, h_evecs_, &n_, iparam_, ipntr_, w_workd_, w_workl_, &lworkl_, w_rwork_, &info_, 1, 1, 2);
313  if (info_ == -15) {
314  arpackErrorHelpNEUPD();
315  errorQuda("\nError in zneupd info = %d. You likely need to\n"
316  "increase the maximum ARPACK iterations. Exiting.",
317  info_);
318  } else if (info_ != 0) {
319  arpackErrorHelpNEUPD();
320  errorQuda("\nError in zneupd info = %d. Exiting.", info_);
321  }
322 #endif
323 
324  profile.TPSTOP(QUDA_PROFILE_ARPACK);
325 
326  // Print additional convergence information.
327  if ((info_) == 1) {
328  if (getVerbosity() >= QUDA_SUMMARIZE) printfQuda("Maximum number of iterations reached.\n");
329  } else {
330  if (info_ == 3) {
331  errorQuda("ARPACK Error: No shifts could be applied during implicit\n");
332  errorQuda("Arnoldi update.\n");
333  }
334  }
335 #ifdef ARPACK_LOGGING
336 #if (defined(QMP_COMMS) || defined(MPI_COMMS))
337  if (comm_rank() == 0) {
338  if (arpack_logfile != NULL) { ARPACK(finilog)(&arpack_log_u); }
339  }
340 #else
341  if (arpack_logfile != NULL) ARPACK(finilog)(&arpack_log_u);
342 #endif
343 #endif
344 
345  if (getVerbosity() >= QUDA_SUMMARIZE) printfQuda("Checking eigenvalues\n");
346 
347  int nconv = iparam_[4];
348 
349  // Sort the eigenvalues in absolute ascending order
350  std::vector<std::pair<double, int>> evals_sorted;
351  for (int j = 0; j < nconv; j++) { evals_sorted.push_back(std::make_pair(h_evals_[j].real(), j)); }
352 
353  // Sort the array by value (first in the pair)
354  // and the index (second in the pair) will come along
355  // for the ride.
356  std::sort(evals_sorted.begin(), evals_sorted.end());
357  if (reverse) std::reverse(evals_sorted.begin(), evals_sorted.end());
358 
359  // print out the computed Ritz values and their error estimates
360  for (int j = 0; j < nconv; j++) {
361  if (getVerbosity() >= QUDA_SUMMARIZE)
362  printfQuda("RitzValue[%04d] = %+.16e %+.16e Residual: %+.16e\n", j, real(h_evals_[evals_sorted[j].second]),
363  imag(h_evals_[evals_sorted[j].second]),
364  std::abs(*(w_workl_ + ipntr_[10] - 1 + evals_sorted[j].second)));
365  }
366 
367  // Compute Eigenvalues from Eigenvectors.
368  for (int i = 0; i < nconv; i++) {
369  int idx = evals_sorted[i].second;
370 
371  profile.TPSTART(QUDA_PROFILE_D2H);
372  *d_v = *h_evecs_arpack[idx];
373  profile.TPSTOP(QUDA_PROFILE_D2H);
374 
375  profile.TPSTART(QUDA_PROFILE_COMPUTE);
376  // d_v2 = M*v
377  eig_solver->matVec(mat, *d_v2, *d_v);
378 
379  // lambda = v^dag * M*v
380  h_evals_[idx] = blas::cDotProduct(*d_v, *d_v2);
381 
382  Complex unit(1.0, 0.0);
383  Complex m_lambda(-h_evals_[idx]);
384 
385  // d_v = ||M*v - lambda*v||
386  blas::caxpby(unit, *d_v2, m_lambda, *d_v);
387  double L2norm = blas::norm2(*d_v);
388 
389  profile.TPSTOP(QUDA_PROFILE_COMPUTE);
390 
391  if (getVerbosity() >= QUDA_SUMMARIZE)
392  printfQuda("EigValue[%04d] = %+.16e %+.16e Residual: %.16e\n", i, real(h_evals_[idx]), imag(h_evals_[idx]),
393  sqrt(L2norm));
394  }
395 
396  // copy back eigenvalues using the sorting index
397  for (int i = 0; i < nconv; i++) h_evals[i] = h_evals_[evals_sorted[i].second];
398 
399  // copy back eigenvectors using the sorting index
400  for (int i = 0; i < nconv; i++) *h_evecs[i] = *h_evecs_arpack[evals_sorted[i].second];
401 
402  profile.TPSTART(QUDA_PROFILE_FREE);
403 
404  // cleanup
405  host_free(h_evals_);
406  for (int i = 0; i < n_kr_; i++) delete h_evecs_arpack[i];
407  host_free(h_evecs_);
408  host_free(ipntr_);
409  host_free(iparam_);
410  host_free(mod_h_evals_sorted);
411  host_free(h_evals_sorted_idx);
412  host_free(resid_);
413  host_free(w_workd_);
414  host_free(w_workl_);
415  host_free(w_workev_);
416  host_free(w_rwork_);
417  host_free(select_);
418 
419  delete h_v;
420  delete h_v2;
421  delete d_v;
422  delete d_v2;
423  delete resid;
424  delete eig_solver;
425 
426  profile.TPSTOP(QUDA_PROFILE_FREE);
427  }
428 
429  void arpackErrorHelpNAUPD()
430  {
431  printfQuda("Error help NAUPD\n");
432  printfQuda("INFO Integer. (INPUT/OUTPUT)\n");
433  printfQuda(" If INFO .EQ. 0, a randomly initial residual vector is used.\n");
434  printfQuda(" If INFO .NE. 0, RESID contains the initial residual vector,\n");
435  printfQuda(" possibly from a previous run.\n");
436  printfQuda(" Error flag on output.\n");
437  printfQuda(" = 0: Normal exit.\n");
438  printfQuda(" = 1: Maximum number of iterations taken.\n");
439  printfQuda(" All possible eigenvalues of OP has been found. IPARAM(5)\n");
440  printfQuda(" returns the number of wanted converged Ritz values.\n");
441  printfQuda(" = 2: No longer an informational error. Deprecated starting\n");
442  printfQuda(" with release 2 of ARPACK.\n");
443  printfQuda(" = 3: No shifts could be applied during a cycle of the\n");
444  printfQuda(" Implicitly restarted Arnoldi iteration. One possibility\n");
445  printfQuda(" is to increase the size of NCV relative to NEV.\n");
446  printfQuda(" See remark 4 below.\n");
447  printfQuda(" = -1: N must be positive.\n");
448  printfQuda(" = -2: NEV must be positive.\n");
449  printfQuda(" = -3: NCV-NEV >= 1 and less than or equal to N.\n");
450  printfQuda(" = -4: The maximum number of Arnoldi update iteration\n");
451  printfQuda(" must be greater than zero.\n");
452  printfQuda(" = -5: WHICH must be 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'\n");
453  printfQuda(" = -6: BMAT must be one of 'I' or 'G'.\n");
454  printfQuda(" = -7: Length of private work array is not sufficient.\n");
455  printfQuda(" = -8: Error return from LAPACK eigenvalue calculation;\n");
456  printfQuda(" = -9: Starting vector is zero.\n");
457  printfQuda(" = -10: IPARAM(7) must be 1,2,3.\n");
458  printfQuda(" = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible.\n");
459  printfQuda(" = -12: IPARAM(1) must be equal to 0 or 1.\n");
460  printfQuda(" = -9999: Could not build an Arnoldi factorization.\n");
461  printfQuda(" User input error highly likely. Please\n");
462  printfQuda(" check actual array dimensions and layout.\n");
463  printfQuda(" IPARAM(5) returns the size of the current Arnoldi\n");
464  printfQuda(" factorization.\n");
465  }
466 
467  void arpackErrorHelpNEUPD()
468  {
469  printfQuda("Error help NEUPD\n");
470  printfQuda("INFO Integer. (OUTPUT)\n");
471  printfQuda(" Error flag on output.\n");
472  printfQuda(" = 0: Normal exit.\n");
473  printfQuda(" = 1: The Schur form computed by LAPACK routine csheqr\n");
474  printfQuda(" could not be reordered by LAPACK routine ztrsen.\n");
475  printfQuda(" Re-enter subroutine zneupd with IPARAM(5)=NCV and\n");
476  printfQuda(" increase the size of the array D to have\n");
477  printfQuda(" dimension at least dimension NCV and allocate at\n");
478  printfQuda(" least NCV\n");
479  printfQuda(" columns for Z. NOTE: Not necessary if Z and V share\n");
480  printfQuda(" the same space. Please notify the authors if this\n");
481  printfQuda(" error occurs.\n");
482  printfQuda(" = -1: N must be positive.\n");
483  printfQuda(" = -2: NEV must be positive.\n");
484  printfQuda(" = -3: NCV-NEV >= 1 and less than or equal to N.\n");
485  printfQuda(" = -5: WHICH must be 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'\n");
486  printfQuda(" = -6: BMAT must be one of 'I' or 'G'.\n");
487  printfQuda(" = -7: Length of private work WORKL array is inufficient.\n");
488  printfQuda(" = -8: Error return from LAPACK eigenvalue calculation.\n");
489  printfQuda(" This should never happened.\n");
490  printfQuda(" = -9: Error return from calculation of eigenvectors.\n");
491  printfQuda(" Informational error from LAPACK routine ztrevc.\n");
492  printfQuda(" = -10: IPARAM(7) must be 1,2,3\n");
493  printfQuda(" = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible.\n");
494  printfQuda(" = -12: HOWMNY = 'S' not yet implemented\n");
495  printfQuda(" = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true.\n");
496  printfQuda(" = -14: ZNAUPD did not find any eigenvalues to sufficient\n");
497  printfQuda(" accuracy.\n");
498  printfQuda(" = -15: ZNEUPD got a different count of the number of\n");
499  printfQuda(" converged Ritz values than ZNAUPD got. This\n");
500  printfQuda(" indicates the user probably made an error in\n");
501  printfQuda(" passing data from ZNAUPD to ZNEUPD or that the\n");
502  printfQuda(" data was modified before entering ZNEUPD\n");
503  }
504 
505 #else
506 
507  void arpack_solve(std::vector<ColorSpinorField *> &h_evecs, std::vector<Complex> &h_evals, const DiracMatrix &mat,
508  QudaEigParam *eig_param, TimeProfile &profile)
509  {
510  errorQuda("(P)ARPACK has not been enabled for this build");
511  }
512 #endif
513 
514 } // namespace quda
static ColorSpinorField * Create(const ColorSpinorParam &param)
static EigenSolver * create(QudaEigParam *eig_param, const DiracMatrix &mat, TimeProfile &profile)
Creates the eigensolver using the parameters given and the matrix.
int comm_rank(void)
void mat(void *out, void **link, void *in, int dagger_bit, int mu, QudaPrecision sPrecision, QudaPrecision gPrecision)
@ QUDA_CUDA_FIELD_LOCATION
Definition: enum_quda.h:326
@ QUDA_CPU_FIELD_LOCATION
Definition: enum_quda.h:325
@ QUDA_SUMMARIZE
Definition: enum_quda.h:266
@ QUDA_VERBOSE
Definition: enum_quda.h:267
@ QUDA_UKQCD_GAMMA_BASIS
Definition: enum_quda.h:369
@ QUDA_SPECTRUM_LM_EIG
Definition: enum_quda.h:147
@ QUDA_SPECTRUM_SM_EIG
Definition: enum_quda.h:148
@ QUDA_SPECTRUM_LR_EIG
Definition: enum_quda.h:149
@ QUDA_SPECTRUM_SR_EIG
Definition: enum_quda.h:150
@ QUDA_SPECTRUM_SI_EIG
Definition: enum_quda.h:152
@ QUDA_SPECTRUM_LI_EIG
Definition: enum_quda.h:151
@ QUDA_SPACE_SPIN_COLOR_FIELD_ORDER
Definition: enum_quda.h:351
@ QUDA_ZERO_FIELD_CREATE
Definition: enum_quda.h:361
@ QUDA_REFERENCE_FIELD_CREATE
Definition: enum_quda.h:363
#define safe_malloc(size)
Definition: malloc_quda.h:106
#define host_free(ptr)
Definition: malloc_quda.h:115
void caxpby(const Complex &a, ColorSpinorField &x, const Complex &b, ColorSpinorField &y)
double norm2(const ColorSpinorField &a)
Complex cDotProduct(ColorSpinorField &, ColorSpinorField &)
void arpack_solve(std::vector< ColorSpinorField * > &h_evecs, std::vector< Complex > &h_evals, const DiracMatrix &mat, QudaEigParam *eig_param, TimeProfile &profile)
The QUDA interface function. One passes two allocated arrays to hold the the eigenmode data,...
std::complex< double > Complex
Definition: quda_internal.h:86
__host__ __device__ ValueType sqrt(ValueType x)
Definition: complex_quda.h:120
@ QUDA_PROFILE_INIT
Definition: timer.h:106
@ QUDA_PROFILE_COMPUTE
Definition: timer.h:108
@ QUDA_PROFILE_ARPACK
Definition: timer.h:118
@ QUDA_PROFILE_FREE
Definition: timer.h:111
@ QUDA_PROFILE_H2D
Definition: timer.h:104
@ QUDA_PROFILE_D2H
Definition: timer.h:105
__host__ __device__ ValueType abs(ValueType x)
Definition: complex_quda.h:125
QudaGaugeParam param
Definition: pack_test.cpp:18
QudaEigSpectrumType spectrum
Definition: quda.h:466
QudaBoolean use_poly_acc
Definition: quda.h:419
double tol
Definition: quda.h:479
char arpack_logfile[512]
Definition: quda.h:494
int n_ev
Definition: quda.h:469
int max_restarts
Definition: quda.h:485
int n_kr
Definition: quda.h:471
QudaFieldLocation location
Definition: quda.h:33
#define printfQuda(...)
Definition: util_quda.h:114
QudaVerbosity getVerbosity()
Definition: util_quda.cpp:21
#define errorQuda(...)
Definition: util_quda.h:120