Arpack.cxx
1 // Copyright (C) 2011 Marc DuruflĂ©
2 //
3 // This file is part of the linear-algebra library Seldon,
4 // http://seldon.sourceforge.net/.
5 //
6 // Seldon is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your option)
9 // any later version.
10 //
11 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
14 // more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with Seldon. If not, see http://www.gnu.org/licenses/.
18 
19 #ifndef SELDON_FILE_ARPACK_CXX
20 
21 #include "Arpack.hxx"
22 
23 namespace Seldon
24 {
25 
27 
32 #ifdef SELDON_WITH_VIRTUAL
33  template<class T>
34  void FindEigenvaluesArpack(EigenProblem_Base<T>& var,
35  Vector<T>& eigen_values,
36  Vector<T>& lambda_imag,
37  Matrix<T, General, ColMajor>& eigen_vectors)
38 #else
39  template<class EigenProblem, class T, class Allocator1,
40  class Allocator2, class Allocator3>
41  void FindEigenvaluesArpack(EigenProblem& var,
42  Vector<T, VectFull, Allocator1>& eigen_values,
45 #endif
46  {
47  // declaration (and initialization) of all the variables needed by CallArpack
48  int ido = 0, n = var.GetM();
49  char bmat;
50  string which("LM");
51  switch (var.GetTypeSorting())
52  {
53  case EigenProblem_Base<T>::SORTED_REAL : which = "LR"; break;
54  case EigenProblem_Base<T>::SORTED_IMAG : which = "LI"; break;
55  case EigenProblem_Base<T>::SORTED_MODULUS : which = "LM"; break;
56  }
57 
58  if (var.GetTypeSpectrum() == var.SMALL_EIGENVALUES)
59  {
60  switch (var.GetTypeSorting())
61  {
62  case EigenProblem_Base<T>::SORTED_REAL : which = "SR"; break;
63  case EigenProblem_Base<T>::SORTED_IMAG : which = "SI"; break;
64  case EigenProblem_Base<T>::SORTED_MODULUS : which = "SM"; break;
65  }
66  }
67 
68  // initializing of computation
69  int nev = var.GetNbAskedEigenvalues();
70  double tol = var.GetStoppingCriterion();
71 
72  Vector<T> resid;
73  int ncv = var.GetNbArnoldiVectors();
75  int ldv = n;
76 
77  IVect iparam(11), ipntr(14);
78  iparam.Fill(0); ipntr.Fill(0);
79  int ishift = 1, nb_max_iter = var.GetNbMaximumIterations();
80  int sym = 0;
81  if (var.IsSymmetricProblem())
82  sym = 1;
83 
84  int non_sym = 0;
85  int sym_mode = sym;
86  iparam(0) = ishift;
87  iparam(2) = nb_max_iter;
88  iparam(3) = 1;
89 
90  int lworkl = 3*ncv*ncv + 6*ncv, info(0);
91  Vector<T> workd, workl, Xh, Yh, Zh;
92  Vector<double> rwork;
93 
94  T shiftr = var.GetShiftValue(), shifti = var.GetImagShiftValue();
95 
96 #ifdef SELDON_WITH_VIRTUAL
97  typename ClassComplexType<T>::Tcplx shift_complex, cone;
98  SetComplexOne(cone);
99  var.GetComplexShift(shiftr, shifti, shift_complex);
100 #endif
101 
102  T zero, one;
103  SetComplexZero(zero);
104  SetComplexOne(one);
105 
106  // mass matrix for diagonal case, and Cholesky case
107  int print_level = var.GetPrintLevel();
108 
109 #ifdef SELDON_WITH_MPI
110  MPI_Comm& comm = var.GetCommunicator();
111  int comm_f = MPI_Comm_c2f(comm);
112  int rank_proc; MPI_Comm_rank(comm, &rank_proc);
113 #else
114  int comm_f(0);
115 #endif
116 
117  // checking if computation mode is compatible with the spectrum
118  // the used wants to find
119  if (var.GetComputationalMode() == var.REGULAR_MODE)
120  {
121  if (var.GetTypeSpectrum() == var.CENTERED_EIGENVALUES)
122  {
123  cout << "You can not use regular mode to find "
124  << "eigenvalues closest to a given value" << endl;
125  cout << "Try to use shifted mode for example "<<endl;
126  abort();
127  }
128  }
129  else
130  {
131  if ((var.GetTypeSpectrum() != var.CENTERED_EIGENVALUES) &&
132  (var.GetComputationalMode() != var.INVERT_MODE))
133  {
134  cout << "To find large or small eigenvalues, use a regular mode" << endl;
135  abort();
136  }
137 
138  if (var.GetComputationalMode() == var.IMAG_SHIFTED_MODE)
139  {
140  cout << "Currently not working" << endl;
141  abort();
142  }
143 
144  if ( (var.GetComputationalMode() == var.BUCKLING_MODE)
145  || (var.GetComputationalMode() == var.CAYLEY_MODE) )
146  {
147  if ( !var.IsSymmetricProblem() || IsComplexNumber(zero))
148  {
149  cout << "Cayley or Bucking mode are reserved for real symmetric "
150  << "generalized eigenproblems " << endl;
151  abort();
152  }
153  }
154  else
155  {
156  if (shifti != zero)
157  {
158  if (var.DiagonalMass() || var.UseCholeskyFactoForMass())
159  {
160  cout << "Complex shifts for unsymmetric real problems are "
161  << "not relevant for diagonal or Cholesky-factorized"
162  << " mass " << endl;
163  cout << "Specify a general mass matrix" << endl;
164  cout << "Diagonal = " << var.DiagonalMass() <<
165  ", Cholesky : " << var.UseCholeskyFactoForMass() << endl;
166 
167  abort();
168  }
169  }
170  }
171  }
172 
173 
174  // we want to find eigenvalues of the generalized problem
175  // K U = lambda M U
176 
177  // A first solution is to compute a cholesky factorization of M = L L^t
178  // the system is transformed into
179  // L^-1 K L^-T V = lambda V
180  // with V = L^T U
181  // we can use then regular or shifted mode for this standard problem
182  // Similarly, if matrix M is diagonal, we have the standard problem
183  // D^-1/2 K D^-1/2 V = lambda V
184  // with V = D^1/2 U
185 
186  // a second solution is to consider the generalized problem
187  if (var.DiagonalMass() || var.UseCholeskyFactoForMass())
188  {
189  // solving a standard eigenvalue problem
190  if (print_level >= 2)
191 #ifdef SELDON_WITH_MPI
192  if (rank_proc == 0)
193 #endif
194  cout << "We solve a standard eigenvalue problem " << endl;
195 
196  // we can reduce to a standard problem
197  // we consider S = M^{-1/2} K M^{-1/2}
198  // if matrix M is diagonal
199  // and S = L^-1 K L^-T if Cholesky factorisation of matrix
200  // M = L L^T is used
201  bmat = 'I';
202  if (var.DiagonalMass())
203  {
204  // computation of M
205  var.ComputeDiagonalMass();
206 
207  // computation of M^{-1/2}
208  var.FactorizeDiagonalMass();
209  }
210  else
211  {
212  // computation of M for Cholesky factorisation
213  var.ComputeMassForCholesky();
214 
215  // computation of Cholesky factorisation M = L L^T
216  var.FactorizeCholeskyMass();
217  }
218 
219  if (var.GetComputationalMode() == var.REGULAR_MODE)
220  {
221  shiftr = zero;
222  // regular mode -> mode 1 for arpack
223  iparam(6) = 1;
224 
225  // computation of the stiffness matrix
226  var.ComputeStiffnessMatrix();
227 
228  // Initialization of variables
229  v.Reallocate(n, ncv);
230  workd.Reallocate(3*n);
231  workl.Reallocate(lworkl);
232  Xh.Reallocate(n);
233  Yh.Reallocate(n);
234  rwork.Reallocate(ncv);
235  resid.Reallocate(n);
236  resid.Fill(zero);
237  v.Fill(zero);
238  workd.Fill(zero);
239  workl.Fill(zero);
240  rwork.Fill(0.0);
241  Xh.Fill(zero);
242  Yh.Fill(zero);
243 
244  if (print_level >= 2)
245 #ifdef SELDON_WITH_MPI
246  if (rank_proc == 0)
247 #endif
248  cout << "Starting Arpack iterations..." << endl;
249 
250  bool test_loop = true;
251  while (test_loop)
252  {
253  CallArpack(comm_f, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv,
254  iparam, ipntr, sym, workd, workl, lworkl, rwork, info);
255 
256  if ((ido == -1)||(ido == 1))
257  {
258  // matrix vector product with M^-1/2 K M^-1/2
259  // or L^-1 K L^-T
260  for (int i = 0; i < n; i++)
261  Xh(i) = workd(ipntr(0)+i-1);
262 
263  if (var.DiagonalMass())
264  var.MltInvSqrtDiagonalMass(Xh);
265  else
266  var.SolveCholeskyMass(SeldonTrans, Xh);
267 
268  var.MltStiffness(Xh, Yh);
269  var.IncrementProdMatVect();
270 
271  if (var.DiagonalMass())
272  var.MltInvSqrtDiagonalMass(Yh);
273  else
274  {
275  var.SolveCholeskyMass(SeldonNoTrans, Yh);
276  var.IncrementLinearSolves();
277  }
278 
279  for (int i = 0; i < n; i++)
280  workd(ipntr(1)+i-1) = Yh(i);
281 
282  }
283  else
284  test_loop = false;
285 
286  }
287  }
288  else
289  {
290  // shifted mode, we compute a factorization of (K - \sigma M)
291  // where \sigma is the shift
292  // shifted mode for regular problem -> mode 1 for arpack
293  iparam(6) = 1;
294 
295  // computation and factorization of K - sigma M
296  var.ComputeAndFactorizeStiffnessMatrix(-shiftr, one);
297 
298  // Initialization of variables
299  v.Reallocate(n, ncv);
300  workd.Reallocate(3*n);
301  workl.Reallocate(lworkl);
302  Xh.Reallocate(n);
303  Yh.Reallocate(n);
304  rwork.Reallocate(ncv);
305  resid.Reallocate(n);
306  resid.Fill(zero);
307  v.Fill(zero);
308  workd.Fill(zero);
309  workl.Fill(zero);
310  rwork.Fill(0.0);
311  Xh.Fill(zero);
312  Yh.Fill(zero);
313 
314  if (print_level >= 2)
315 #ifdef SELDON_WITH_MPI
316  if (rank_proc == 0)
317 #endif
318  cout << "Starting Arpack iterations..." << endl;
319 
320  bool test_loop = true;
321  while (test_loop)
322  {
323  CallArpack(comm_f, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv,
324  iparam, ipntr, sym, workd, workl, lworkl, rwork, info);
325 
326  if ((ido == -1)||(ido == 1))
327  {
328  // matrix vector product M^1/2 (K - sigma M)^-1 M^1/2 X
329  // or L^T (K - sigma M)^-1 L X
330  for (int i = 0; i < n; i++)
331  Xh(i) = workd(ipntr(0)+i-1);
332 
333  if (var.DiagonalMass())
334  var.MltSqrtDiagonalMass(Xh);
335  else
336  var.MltCholeskyMass(SeldonNoTrans, Xh);
337 
338  var.ComputeSolution(Xh, Yh);
339  var.IncrementLinearSolves();
340 
341  if (var.DiagonalMass())
342  var.MltSqrtDiagonalMass(Yh);
343  else
344  {
345  var.MltCholeskyMass(SeldonTrans, Yh);
346  var.IncrementLinearSolves();
347  }
348 
349  for (int i = 0; i < n; i++)
350  workd(ipntr(1)+i-1) = Yh(i);
351  }
352  else
353  test_loop = false;
354 
355  }
356  }
357  }
358  else
359  {
360  // generalized problem
361  bmat = 'G';
362  // different computational modes available in Arpack :
363  if (var.GetComputationalMode() == var.INVERT_MODE)
364  {
365  // we consider standard problem M^-1 K U = lambda U
366  // drawback : the matrix is non-symmetric
367  // even if K and M are symmetric
368  bmat = 'I';
369 
370  if (var.GetTypeSpectrum() != var.CENTERED_EIGENVALUES)
371  {
372  // => regular mode for matrix M^-1 K
373  iparam(6) = 1;
374 
375  // computation and factorisation of mass matrix
376  var.ComputeAndFactorizeStiffnessMatrix(one, zero);
377 
378  // computation of stiffness matrix
379  var.ComputeStiffnessMatrix();
380  }
381  else
382  {
383  if (shifti != zero)
384  {
385  // shifted mode for generalized eigenvalue problem -> mode 3 for arpack
386  iparam(6) = 3;
387 
388  // computation and factorization of (K - sigma M)^-1
389 #ifdef SELDON_WITH_VIRTUAL
390  var.ComputeAndFactorizeStiffnessMatrix(-shift_complex, cone,
392 #else
393  var.ComputeAndFactorizeStiffnessMatrix(-complex<T>(shiftr, shifti),
394  complex<T>(one, zero), true);
395 #endif
396 
397  var.ComputeStiffnessMatrix();
398  }
399  else
400  {
401  // => regular mode for matrix (M^-1 K - sigma I)^-1
402  // = (K - sigma M)^-1 M
403  iparam(6) = 1;
404 
405  // computation and factorization of (K - sigma M)
406  var.ComputeAndFactorizeStiffnessMatrix(-shiftr, one);
407 
408  }
409 
410  // computation of M
411  var.ComputeMassMatrix();
412  }
413 
414  // Initialization of variables
415  v.Reallocate(n, ncv);
416  workd.Reallocate(3*n);
417  workl.Reallocate(lworkl);
418  Xh.Reallocate(n);
419  Yh.Reallocate(n);
420  Zh.Reallocate(n);
421  rwork.Reallocate(ncv);
422  resid.Reallocate(n);
423  resid.Fill(zero);
424  v.Fill(zero);
425  workd.Fill(zero);
426  workl.Fill(zero);
427  rwork.Fill(0.0);
428  Xh.Fill(zero);
429  Yh.Fill(zero);
430  Zh.Fill(zero);
431 
432  if (print_level >= 2)
433 #ifdef SELDON_WITH_MPI
434  if (rank_proc == 0)
435 #endif
436  cout << "Starting Arpack iterations..." << endl;
437 
438  bool test_loop = true;
439  sym_mode = 0;
440  while (test_loop)
441  {
442  CallArpack(comm_f, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv,
443  iparam, ipntr, non_sym, workd, workl, lworkl, rwork, info);
444 
445  if ((ido == -1)||(ido == 1))
446  {
447  // computation of (K - sigma M)^-1 M X
448  if ((iparam(6) == 3) && (ido == 1))
449  for (int i = 0; i < n; i++)
450  Xh(i) = workd(ipntr(2)+i-1);
451  else
452  for (int i = 0; i < n; i++)
453  Xh(i) = workd(ipntr(0)+i-1);
454 
455  if (var.GetTypeSpectrum() != var.CENTERED_EIGENVALUES)
456  {
457  var.MltStiffness(Xh, Zh);
458  var.ComputeSolution(Zh, Yh);
459  var.IncrementProdMatVect();
460  var.IncrementLinearSolves();
461  }
462  else
463  {
464  var.MltMass(Xh, Zh);
465  var.ComputeSolution(Zh, Yh);
466  var.IncrementProdMatVect();
467  var.IncrementLinearSolves();
468  }
469 
470  for (int i = 0; i < n; i++)
471  workd(ipntr(1)+i-1) = Yh(i);
472  }
473  else if (ido == 2)
474  {
475  // computation of M X (Identity)
476  for (int i = 0; i < n; i++)
477  workd(ipntr(1)+i-1) = workd(ipntr(0)+i-1);
478  }
479  else
480  test_loop = false;
481  }
482  }
483  else if (var.GetComputationalMode() == var.REGULAR_MODE)
484  {
485  // regular mode for generalized eigenvalue problem -> mode 2 for arpack
486  iparam(6) = 2;
487  bmat = 'G';
488 
489  // factorization of the mass matrix
490  var.ComputeAndFactorizeStiffnessMatrix(one, zero);
491 
492  // computation of stiffness and mass matrix
493  var.ComputeStiffnessMatrix();
494  var.ComputeMassMatrix();
495 
496  // Initialization of variables
497  v.Reallocate(n, ncv);
498  workd.Reallocate(3*n);
499  workl.Reallocate(lworkl);
500  Xh.Reallocate(n);
501  Yh.Reallocate(n);
502  Zh.Reallocate(n);
503  rwork.Reallocate(ncv);
504  resid.Reallocate(n);
505  resid.Fill(zero);
506  v.Fill(zero);
507  workd.Fill(zero);
508  workl.Fill(zero);
509  rwork.Fill(0.0);
510  Xh.Fill(zero);
511  Yh.Fill(zero);
512  Zh.Fill(zero);
513 
514  if (print_level >= 2)
515 #ifdef SELDON_WITH_MPI
516  if (rank_proc == 0)
517 #endif
518  cout << "Starting Arpack iterations..." << endl;
519 
520  bool test_loop = true;
521  while (test_loop)
522  {
523  CallArpack(comm_f, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv,
524  iparam, ipntr, sym, workd, workl, lworkl, rwork, info);
525 
526  if ((ido == -1)||(ido == 1))
527  {
528  // computation of M^-1 K X and K X
529  for (int i = 0; i < n; i++)
530  Xh(i) = workd(ipntr(0)+i-1);
531 
532  var.MltStiffness(Xh, Zh);
533  var.ComputeSolution(Zh, Yh);
534  var.IncrementProdMatVect();
535  var.IncrementLinearSolves();
536 
537  for (int i = 0; i < n; i++)
538  {
539  workd(ipntr(0)+i-1) = Zh(i);
540  workd(ipntr(1)+i-1) = Yh(i);
541  }
542  }
543  else if (ido == 2)
544  {
545  // computation of M X
546  for (int i = 0; i < n; i++)
547  Xh(i) = workd(ipntr(0)+i-1);
548 
549  var.MltMass(Xh, Yh);
550  var.IncrementProdMatVect();
551 
552  for (int i = 0; i < n; i++)
553  workd(ipntr(1)+i-1) = Yh(i);
554  }
555  else
556  test_loop = false;
557 
558  }
559  }
560  else if ((var.GetComputationalMode() == var.SHIFTED_MODE)
561  || (var.GetComputationalMode() == var.IMAG_SHIFTED_MODE) )
562  {
563  // shifted mode for generalized eigenvalue problem -> mode 3 for arpack
564  iparam(6) = 3;
565 
566  // computation and factorization of (K - sigma M)^-1
567  if (shifti != zero)
568  {
569 #ifdef SELDON_WITH_VIRTUAL
570  if (var.GetComputationalMode() == var.SHIFTED_MODE)
571  var.ComputeAndFactorizeStiffnessMatrix(-shift_complex, cone,
573  else
574  {
575  iparam(6) = 4;
576  var.ComputeAndFactorizeStiffnessMatrix(-shift_complex, cone,
578  }
579 #else
580  if (var.GetComputationalMode() == var.SHIFTED_MODE)
581  var.ComputeAndFactorizeStiffnessMatrix(-complex<T>(shiftr, shifti),
582  complex<T>(one, zero), true);
583  else
584  {
585  iparam(6) = 4;
586  var.ComputeAndFactorizeStiffnessMatrix(-complex<T>(shiftr, shifti),
587  complex<T>(one, zero), false);
588  }
589 #endif
590 
591  var.ComputeStiffnessMatrix();
592  }
593  else
594  var.ComputeAndFactorizeStiffnessMatrix(-shiftr, one);
595 
596  // computation of mass matrix
597  var.ComputeMassMatrix();
598 
599  // Initialization of variables
600  v.Reallocate(n, ncv);
601  workd.Reallocate(3*n);
602  workl.Reallocate(lworkl);
603  Xh.Reallocate(n);
604  Yh.Reallocate(n);
605  Zh.Reallocate(n);
606  rwork.Reallocate(ncv);
607  resid.Reallocate(n);
608  resid.Fill(zero);
609  v.Fill(zero);
610  workd.Fill(zero);
611  workl.Fill(zero);
612  rwork.Fill(0.0);
613  Xh.Fill(zero);
614  Yh.Fill(zero);
615  Zh.Fill(zero);
616 
617  if (print_level >= 2)
618 #ifdef SELDON_WITH_MPI
619  if (rank_proc == 0)
620 #endif
621  cout << "Starting Arpack iterations..." << endl;
622 
623  bool test_loop = true;
624  while (test_loop)
625  {
626  CallArpack(comm_f, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv,
627  iparam, ipntr, sym, workd, workl, lworkl, rwork, info);
628 
629  if ((ido == -1)||(ido == 1))
630  {
631  // computation of Real( (K - sigma M)^-1 M) X
632  // or Imag( (K - sigma M)^-1 M) X
633  // if ido == 1, M X is already computed and available
634  if (ido == -1)
635  {
636  for (int i = 0; i < n; i++)
637  Zh(i) = workd(ipntr(0)+i-1);
638 
639  var.MltMass(Zh, Xh);
640  var.IncrementProdMatVect();
641  }
642  else
643  for (int i = 0; i < n; i++)
644  Xh(i) = workd(ipntr(2)+i-1);
645 
646  var.ComputeSolution(Xh, Yh);
647  var.IncrementLinearSolves();
648  for (int i = 0; i < n; i++)
649  workd(ipntr(1)+i-1) = Yh(i);
650 
651  }
652  else if (ido == 2)
653  {
654  // computation of M X
655  for (int i = 0; i < n; i++)
656  Xh(i) = workd(ipntr(0)+i-1);
657 
658  var.MltMass(Xh, Yh);
659  var.IncrementProdMatVect();
660 
661  for (int i = 0; i < n; i++)
662  workd(ipntr(1)+i-1) = Yh(i);
663 
664  }
665  else
666  test_loop = false;
667 
668  }
669  }
670  else if (var.GetComputationalMode() == var.BUCKLING_MODE)
671  {
672  // buckling mode for generalized eigenvalue problem -> mode 4 for arpack
673  iparam(6) = 4;
674 
675  // computation and factorisation of (K - sigma M)
676  var.ComputeAndFactorizeStiffnessMatrix(-shiftr, one);
677 
678  // computation of matrix K
679  var.ComputeStiffnessMatrix();
680 
681  // Initialization of variables
682  v.Reallocate(n, ncv);
683  workd.Reallocate(3*n);
684  workl.Reallocate(lworkl);
685  Xh.Reallocate(n);
686  Yh.Reallocate(n);
687  Zh.Reallocate(n);
688  rwork.Reallocate(ncv);
689  resid.Reallocate(n);
690  resid.Fill(zero);
691  v.Fill(zero);
692  workd.Fill(zero);
693  workl.Fill(zero);
694  rwork.Fill(0.0);
695  Xh.Fill(zero);
696  Yh.Fill(zero);
697  Zh.Fill(zero);
698 
699  if (print_level >= 2)
700 #ifdef SELDON_WITH_MPI
701  if (rank_proc == 0)
702 #endif
703  cout << "Starting Arpack iterations..." << endl;
704 
705  bool test_loop = true;
706  while (test_loop)
707  {
708  CallArpack(comm_f, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv,
709  iparam, ipntr, sym, workd, workl, lworkl, rwork, info);
710 
711  if ((ido == -1)||(ido == 1))
712  {
713  // computation of (K - sigma M)^-1 K X or (K - sigma M)^-1 X
714  if (ido == -1)
715  {
716  for (int i = 0; i < n; i++)
717  Zh(i) = workd(ipntr(0)+i-1);
718 
719  var.MltStiffness(Zh, Xh);
720  var.IncrementProdMatVect();
721  }
722  else
723  for (int i = 0; i < n; i++)
724  Xh(i) = workd(ipntr(2)+i-1);
725 
726  var.ComputeSolution(Xh, Yh);
727  var.IncrementLinearSolves();
728 
729  for (int i = 0; i < n; i++)
730  workd(ipntr(1)+i-1) = Yh(i);
731  }
732  else if (ido == 2)
733  {
734  // computation of K X
735  for (int i = 0; i < n; i++)
736  Xh(i) = workd(ipntr(0)+i-1);
737 
738  var.MltStiffness(Xh, Yh);
739  var.IncrementProdMatVect();
740 
741  for (int i = 0; i < n; i++)
742  workd(ipntr(1)+i-1) = Yh(i);
743  }
744  else
745  test_loop = false;
746 
747  }
748  }
749  else if (var.GetComputationalMode() == var.CAYLEY_MODE)
750  {
751  // shifted mode for generalized eigenvalue problem -> mode 5 for arpack
752  iparam(6) = 5;
753 
754  // computation and factorization of (K - sigma M)
755  var.ComputeAndFactorizeStiffnessMatrix(-shiftr, one);
756 
757  // computation of M and (K + sigma M)
758  var.ComputeMassMatrix();
759  var.ComputeStiffnessMatrix(shiftr, one);
760 
761  // Initialization of variables
762  v.Reallocate(n, ncv);
763  workd.Reallocate(3*n);
764  workl.Reallocate(lworkl);
765  Xh.Reallocate(n);
766  Yh.Reallocate(n);
767  Zh.Reallocate(n);
768  rwork.Reallocate(ncv);
769  resid.Reallocate(n);
770  resid.Fill(zero);
771  v.Fill(zero);
772  workd.Fill(zero);
773  workl.Fill(zero);
774  rwork.Fill(0.0);
775  Xh.Fill(zero);
776  Yh.Fill(zero);
777  Zh.Fill(zero);
778 
779  if (print_level >= 2)
780 #ifdef SELDON_WITH_MPI
781  if (rank_proc == 0)
782 #endif
783  cout << "Starting Arpack iterations..." << endl;
784 
785  bool test_loop = true;
786  while (test_loop)
787  {
788  CallArpack(comm_f, ido, bmat, n, which, nev, tol, resid, ncv, v, ldv,
789  iparam, ipntr, sym, workd, workl, lworkl, rwork, info);
790 
791  if ((ido == -1)||(ido == 1))
792  {
793  // computation of (K - sigma M)^-1 (K + sigma M) X
794  for (int i = 0; i < n; i++)
795  Zh(i) = workd(ipntr(0)+i-1);
796 
797  var.MltStiffness(shiftr, one, Zh, Xh);
798  var.ComputeSolution(Xh, Yh);
799  var.IncrementProdMatVect();
800  var.IncrementLinearSolves();
801 
802  for (int i = 0; i < n; i++)
803  workd(ipntr(1)+i-1) = Yh(i);
804  }
805  else if (ido == 2)
806  {
807  // computation of M X
808  for (int i = 0; i < n; i++)
809  Xh(i) = workd(ipntr(0)+i-1);
810 
811  var.MltMass(Xh, Yh);
812  var.IncrementProdMatVect();
813 
814  for (int i = 0; i < n; i++)
815  workd(ipntr(1)+i-1) = Yh(i);
816  }
817  else
818  test_loop = false;
819 
820  }
821  }
822  }
823 
824  if (info != 0)
825  {
826  if (info == 1)
827  {
828  cout << "Maximum number of iterations reached" << endl;
829  cout << "Try again with a larger number of iterations"
830  << " or with a less restrictive stopping criterion" << endl;
831 
832  throw SolverMaximumIterationError("FindEigenvaluesArpack", "Maximum number of iterations reached");
833  }
834  else
835  {
836  cout << "Error during the computation of eigenvalues, info = "
837  << info << endl;
838  cout << "Look at documentation of ARPACK " << endl;
839 
840  throw SolverDivergenceError("FindEigenvaluesArpack", "The solver diverged");
841  }
842  }
843 
844  Xh.Clear();
845  Yh.Clear();
846  Zh.Clear();
847 
848  if ((Norm2(resid) == 0) && (n > ncv))
849  {
850  cout << "This eigenvalue problem rises an unknown bug in Arpack " << endl;
851  cout << "Is the mass matrix or stiffness matrix null ?" << endl;
852  cout << "Null eigenvalues are found." << endl;
853  throw SolverDivergenceError("FindEigenvaluesArpack", "The solver diverged");
854  }
855 
856  // we recover eigenvalues and eigenvectors
857  int nconv = nev+1+var.GetNbAdditionalEigenvalues();
858  eigen_values.Reallocate(nconv);
859  eigen_vectors.Reallocate(n, nconv);
860  eigen_values.Fill(zero);
861  eigen_vectors.Fill(zero);
862  lambda_imag.Reallocate(nconv);
863  lambda_imag.Fill(zero);
864 
865  char howmny = 'A';
866  IVect selec(ncv); selec.Zero();
867  int rvec = 1;
868  int ldz = n;
869  if (print_level >= 2)
870 #ifdef SELDON_WITH_MPI
871  if (rank_proc == 0)
872 #endif
873  cout << "recovering eigenvalues ..." << endl;
874 
875  CallArpack(comm_f, rvec, howmny, selec, eigen_values, lambda_imag, eigen_vectors,
876  ldz, shiftr, shifti, bmat, n, which, nev, tol, resid, ncv,
877  v, ldv, iparam, ipntr, sym_mode, workd, workl, lworkl, rwork, info);
878 
879  if (print_level >= 2)
880 #ifdef SELDON_WITH_MPI
881  if (rank_proc == 0)
882 #endif
883  cout << "end recover " << endl;
884 
885  eigen_values.Resize(nev);
886  lambda_imag.Resize(nev);
887  eigen_vectors.Resize(n, nev);
888  ApplyScalingEigenvec(var, eigen_values, lambda_imag, eigen_vectors,
889  shiftr, shifti);
890 
891  var.Clear();
892  }
893 
894 
895  /*************************************************************************
896  * Overload of CallArpack function to call the correct Arpack subroutine *
897  *************************************************************************/
898 
899 
901  template<class T, class Allocator1, class Allocator2,
902  class Allocator3, class Allocator4, class Alloc5>
903  void CallArpack(int comm, int& ido, char& bmat, int& n, string& which, int& nev,
904  T& tol, Vector<T, VectFull, Allocator1>& resid,
906  int& ldv, Vector<int>& iparam, Vector<int>& ipntr, int sym,
909  int& lworkl, Vector<T, VectFull, Alloc5>& rwork, int& info)
910  {
911  if (sym)
912  {
913  if ((which == "SR") || (which == "SI"))
914  which = "SA";
915 
916  if ((which == "LR") || (which == "LI"))
917  which = "LA";
918 
919  // real symmetric
920  // call of dsaupd/ssaupd
921 #ifdef SELDON_WITH_MPI
922  saupd(comm, ido, bmat, n, &which[0], nev, tol, resid.GetData(),
923  ncv, v.GetData(), ldv, iparam.GetData(), ipntr.GetData(),
924  workd.GetData(), workl.GetData(), lworkl, info);
925 #else
926  saupd(ido, bmat, n, &which[0], nev, tol, resid.GetData(),
927  ncv, v.GetData(), ldv, iparam.GetData(), ipntr.GetData(),
928  workd.GetData(), workl.GetData(), lworkl, info);
929 #endif
930  }
931  else
932  {
933  // real non-symmetric
934  // call of dnaupd/snaupd
935 #ifdef SELDON_WITH_MPI
936  naupd(comm, ido, bmat, n, &which[0], nev, tol, resid.GetData(),
937  ncv, v.GetData(), ldv, iparam.GetData(), ipntr.GetData(),
938  workd.GetData(), workl.GetData(), lworkl, info);
939 #else
940  naupd(ido, bmat, n, &which[0], nev, tol, resid.GetData(),
941  ncv, v.GetData(), ldv, iparam.GetData(), ipntr.GetData(),
942  workd.GetData(), workl.GetData(), lworkl, info);
943 #endif
944  }
945  }
946 
947 
949  template<class Allocator1, class Allocator2,
950  class Allocator3, class Allocator4, class Alloc5>
951  void CallArpack(int comm, int& ido, char& bmat, int& n,
952  string& which, int& nev, double& tol,
953  Vector<complex<double>, VectFull, Allocator1>& resid, int& ncv,
954  Matrix<complex<double>, General, ColMajor, Allocator2>& v,
955  int& ldv, Vector<int>& iparam, Vector<int>& ipntr, int sym,
956  Vector<complex<double>, VectFull, Allocator3>& workd,
957  Vector<complex<double>, VectFull, Allocator4>& workl,
958  int& lworkl, Vector<double, VectFull, Alloc5>& rwork, int& info)
959  {
960  // complex
961  // call of znaupd
962 #ifdef SELDON_WITH_MPI
963  pznaupd_(&comm, &ido, &bmat, &n, &which[0], &nev, &tol, resid.GetDataVoid(),
964  &ncv, v.GetDataVoid(), &ldv, iparam.GetData(), ipntr.GetData(),
965  workd.GetDataVoid(), workl.GetDataVoid(), &lworkl, rwork.GetData(), &info);
966 #else
967  znaupd_(&ido, &bmat, &n, &which[0], &nev, &tol, resid.GetDataVoid(),
968  &ncv, v.GetDataVoid(), &ldv, iparam.GetData(), ipntr.GetData(),
969  workd.GetDataVoid(), workl.GetDataVoid(), &lworkl, rwork.GetData(), &info);
970 #endif
971  }
972 
973 
975  template<class T, class Allocator1, class Allocator2,
976  class Allocator3, class Allocator4, class Allocator5,
977  class Allocator6, class Allocator7, class Alloc8>
978  void CallArpack(int comm, int& rvec, char& howmny, Vector<int>& selec,
982  int& ldz, T& shiftr, T& shifti, char& bmat, int& n,
983  string& which, int& nev, T& tol,
986  int& ldv, Vector<int>& iparam, Vector<int>& ipntr,
987  int sym, Vector<T, VectFull, Allocator6>& workd,
989  int& lworkl, Vector<T, VectFull, Alloc8>& rwork, int& info)
990  {
991  if (sym)
992  {
993  // real symmetric
994  // call of dseupd
995 #ifdef SELDON_WITH_MPI
996  seupd(comm, rvec, howmny, selec.GetData(), lambda.GetData(), eigen_vec.GetData(),
997  ldz, shiftr, bmat, n, &which[0], nev, tol, resid.GetData(), ncv,
998  v.GetData(), ldv, iparam.GetData(), ipntr.GetData(),
999  workd.GetData(), workl.GetData(), lworkl, info);
1000 #else
1001  seupd(rvec, howmny, selec.GetData(), lambda.GetData(), eigen_vec.GetData(),
1002  ldz, shiftr, bmat, n, &which[0], nev, tol, resid.GetData(), ncv,
1003  v.GetData(), ldv, iparam.GetData(), ipntr.GetData(),
1004  workd.GetData(), workl.GetData(), lworkl, info);
1005 #endif
1006  }
1007  else
1008  {
1009  Vector<double> workev(3*ncv);
1010  // real non-symmetric
1011  // call of dneupd
1012 #ifdef SELDON_WITH_MPI
1013  neupd(comm, rvec, howmny, selec.GetData(), lambda.GetData(),
1014  lambda_i.GetData(), eigen_vec.GetData(), ldz, shiftr, shifti,
1015  workev.GetData(), bmat, n, &which[0], nev, tol,
1016  resid.GetData(), ncv, v.GetData(), ldv, iparam.GetData(),
1017  ipntr.GetData(), workd.GetData(), workl.GetData(), lworkl, info);
1018 #else
1019  neupd(rvec, howmny, selec.GetData(), lambda.GetData(),
1020  lambda_i.GetData(), eigen_vec.GetData(), ldz, shiftr, shifti,
1021  workev.GetData(), bmat, n, &which[0], nev, tol,
1022  resid.GetData(), ncv, v.GetData(), ldv, iparam.GetData(),
1023  ipntr.GetData(), workd.GetData(), workl.GetData(), lworkl, info);
1024 #endif
1025  }
1026  }
1027 
1028 
1030  template<class Allocator1, class Allocator2, class Allocator3,
1031  class Allocator4, class Allocator5, class Allocator6,
1032  class Allocator7, class Alloc8>
1033  void CallArpack(int comm, int& rvec, char& howmny, Vector<int>& selec,
1034  Vector<complex<double>, VectFull, Allocator1>& lambda,
1035  Vector<complex<double>, VectFull, Allocator2>& lambda_i,
1036  Matrix<complex<double>, General, ColMajor, Allocator3>& eigen_vectors,
1037  int& ldz, complex<double>& shiftr, complex<double>& shifti,
1038  char& bmat, int& n, string& which, int& nev, double& tol,
1039  Vector<complex<double>, VectFull, Allocator4>& resid,
1040  int& ncv, Matrix<complex<double>, General, ColMajor, Allocator5>& v,
1041  int& ldv, Vector<int>& iparam, Vector<int>& ipntr, int sym,
1042  Vector<complex<double>, VectFull, Allocator6>& workd,
1043  Vector<complex<double>, VectFull, Allocator7>& workl,
1044  int& lworkl, Vector<double, VectFull, Alloc8>& rwork, int& info)
1045  {
1046  // complex
1047  // call of zneupd
1048  Vector<complex<double> > workev(2*ncv);
1049  workev.Zero();
1050 #ifdef SELDON_WITH_MPI
1051  pzneupd_(&comm, &rvec, &howmny, selec.GetData(), lambda.GetDataVoid(),
1052  eigen_vectors.GetDataVoid(), &ldz, &shiftr, workev.GetDataVoid(),
1053  &bmat, &n, &which[0], &nev, &tol, resid.GetDataVoid(),
1054  &ncv, v.GetDataVoid(), &ldv, iparam.GetData(),
1055  ipntr.GetData(), workd.GetDataVoid(), workl.GetDataVoid(),
1056  &lworkl, rwork.GetData(), &info);
1057 #else
1058  zneupd_(&rvec, &howmny, selec.GetData(), lambda.GetDataVoid(),
1059  eigen_vectors.GetDataVoid(), &ldz, &shiftr, workev.GetDataVoid(),
1060  &bmat, &n, &which[0], &nev, &tol, resid.GetDataVoid(),
1061  &ncv, v.GetDataVoid(), &ldv, iparam.GetData(),
1062  ipntr.GetData(), workd.GetDataVoid(), workl.GetDataVoid(),
1063  &lworkl, rwork.GetData(), &info);
1064 #endif
1065  }
1066 
1067 }
1068 
1069 #define SELDON_FILE_ARPACK_CXX
1070 #endif
Seldon::seupd
void seupd(ARPACK_LOGICAL rvec, char HowMny, ARPACK_LOGICAL *select, ARPACK_DOUBLEREAL *d, ARPACK_DOUBLEREAL *Z, ARPACK_INTEGER ldz, ARPACK_DOUBLEREAL sigma, char bmat, ARPACK_INTEGER n, char *which, ARPACK_INTEGER nev, ARPACK_DOUBLEREAL tol, ARPACK_DOUBLEREAL *resid, ARPACK_INTEGER ncv, ARPACK_DOUBLEREAL *V, ARPACK_INTEGER ldv, ARPACK_INTEGER *iparam, ARPACK_INTEGER *ipntr, ARPACK_DOUBLEREAL *workd, ARPACK_DOUBLEREAL *workl, ARPACK_INTEGER lworkl, ARPACK_INTEGER &info)
Postprocessing for symmetric problems in double precision.
Definition: ArpackInline.cxx:161
Seldon::Norm2
ClassComplexType< T >::Treal Norm2(const VectorExpression< T, E > &X)
returns 2-norm of an expression with vectors
Definition: Functions_BaseInline.cxx:153
Seldon::Vector
Definition: SeldonHeader.hxx:207
Seldon::SolverDivergenceError
Definition: Errors.hxx:171
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::VectFull
Definition: StorageInline.cxx:74
Seldon::IsComplexNumber
bool IsComplexNumber(const T &number)
Returns true for a complex number.
Definition: CommonInline.cxx:293
Seldon::EigenProblem_Base::GetNbAskedEigenvalues
int GetNbAskedEigenvalues() const
returns the number of eigenvalues asked by the user
Definition: EigenvalueSolver.cxx:149
Seldon::saupd
void saupd(ARPACK_INTEGER &ido, char bmat, ARPACK_INTEGER n, char *which, ARPACK_INTEGER nev, ARPACK_DOUBLEREAL &tol, ARPACK_DOUBLEREAL *resid, ARPACK_INTEGER ncv, ARPACK_DOUBLEREAL *V, ARPACK_INTEGER ldv, ARPACK_INTEGER *iparam, ARPACK_INTEGER *ipntr, ARPACK_DOUBLEREAL *workd, ARPACK_DOUBLEREAL *workl, ARPACK_INTEGER lworkl, ARPACK_INTEGER &info)
Symmetric problems in double precision.
Definition: ArpackInline.cxx:136
Seldon::neupd
void neupd(ARPACK_LOGICAL rvec, char HowMny, ARPACK_LOGICAL *select, ARPACK_DOUBLEREAL *dr, ARPACK_DOUBLEREAL *di, ARPACK_DOUBLEREAL *Z, ARPACK_INTEGER ldz, ARPACK_DOUBLEREAL sigmar, ARPACK_DOUBLEREAL sigmai, ARPACK_DOUBLEREAL *workv, char bmat, ARPACK_INTEGER n, char *which, ARPACK_INTEGER nev, ARPACK_DOUBLEREAL tol, ARPACK_DOUBLEREAL *resid, ARPACK_INTEGER ncv, ARPACK_DOUBLEREAL *V, ARPACK_INTEGER ldv, ARPACK_INTEGER *iparam, ARPACK_INTEGER *ipntr, ARPACK_DOUBLEREAL *workd, ARPACK_DOUBLEREAL *workl, ARPACK_INTEGER lworkl, ARPACK_INTEGER &info)
Postprocessing for non-symmetric problems in double precision.
Definition: ArpackInline.cxx:221
Seldon::naupd
void naupd(ARPACK_INTEGER &ido, char bmat, ARPACK_INTEGER n, char *which, ARPACK_INTEGER nev, ARPACK_DOUBLEREAL &tol, ARPACK_DOUBLEREAL *resid, ARPACK_INTEGER ncv, ARPACK_DOUBLEREAL *V, ARPACK_INTEGER ldv, ARPACK_INTEGER *iparam, ARPACK_INTEGER *ipntr, ARPACK_DOUBLEREAL *workd, ARPACK_DOUBLEREAL *workl, ARPACK_INTEGER lworkl, ARPACK_INTEGER &info)
Non-symmetric problems in double precision.
Definition: ArpackInline.cxx:192
Seldon::General
Definition: Properties.hxx:26
Seldon::EigenProblem_Base
Base class to solve an eigenvalue problem.
Definition: EigenvalueSolver.hxx:18
Seldon::CallArpack
void CallArpack(int comm, int &ido, char &bmat, int &n, string &which, int &nev, T &tol, Vector< T, VectFull, Allocator1 > &resid, int &ncv, Matrix< T, General, ColMajor, Allocator2 > &v, int &ldv, Vector< int > &iparam, Vector< int > &ipntr, int sym, Vector< T, VectFull, Allocator3 > &workd, Vector< T, VectFull, Allocator4 > &workl, int &lworkl, Vector< T, VectFull, Alloc5 > &rwork, int &info)
calling arpack routine
Definition: Arpack.cxx:903
Seldon::FindEigenvaluesArpack
void FindEigenvaluesArpack(EigenProblem &var, Vector< T, VectFull, Allocator1 > &eigen_values, Vector< T, VectFull, Allocator2 > &lambda_imag, Matrix< T, General, ColMajor, Allocator3 > &eigen_vectors)
computation of eigenvalues and related eigenvectors
Definition: Arpack.cxx:41
Seldon::SolverMaximumIterationError
Definition: Errors.hxx:163
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::ApplyScalingEigenvec
void ApplyScalingEigenvec(EigenPb &var, Vector1 &eigen_values, Vector1 &lambda_imag, Matrix1 &eigen_vectors, const T0 &shiftr, const T0 &shifti)
modification of eigenvectors to take into account scaling by mass matrix
Definition: EigenvalueSolver.cxx:846
Seldon::ColMajor
Definition: Storage.hxx:33