EigenvalueSolver.cxx
1 #ifndef SELDON_FILE_EIGENVALUE_SOLVER_CXX
2 
3 #include "EigenvalueSolver.hxx"
4 
5 namespace Seldon
6 {
7 
8  /******************
9  * Initialization *
10  ******************/
11 
12 
14  template<class T, class MatStiff, class MatMass>
16  {
17  eigenvalue_computation_mode = 1;
18  nb_eigenvalues_wanted = 0;
19  nb_add_eigenvalues = 0;
20  // default => we want largest eigenvalues by magnitude
21  type_spectrum_wanted = LARGE_EIGENVALUES;
22  type_sort_eigenvalues = SORTED_MODULUS;
23 
24  use_cholesky = false;
25  diagonal_mass = false;
26  stopping_criterion = 1e-6;
27  nb_maximum_iterations = 1000;
28  nb_prod = 0;
29  n_ = 0;
30 
31  shift = T(0);
32  shift_imag = T(0);
33 
34  nb_arnoldi_vectors = 0;
35  automatic_selection_arnoldi_vectors = true;
36 
37  print_level = 0;
38 
39  complex_system = false;
40  Mh = NULL;
41  Kh = NULL;
42 
43 #ifdef SELDON_WITH_MPI
44  // for parallel execution, default communicator : all the processors
45  comm = MPI_COMM_WORLD;
46 #endif
47 
48  type_solver = SOLVER_LOBPCG;
49  ortho_manager = ORTHO_DGKS;
50  nb_blocks = 2;
51  restart_number = 20;
52  }
53 
54 
56  template<class T, class MatStiff, class MatMass>
58  {
59  n_ = n;
60  nb_prod = 0;
61 
62  // counting the size of the global system for parallel computation
63  int nglob = n;
64 #ifdef SELDON_WITH_MPI
65  MPI_Allreduce(&n, &nglob, 1, MPI_INTEGER, MPI_SUM, comm);
66 #endif
67 
68  if (nb_eigenvalues_wanted >= (nglob - 2))
69  {
70  cout << "Too many wanted eigenvalues " << endl;
71  cout << nb_eigenvalues_wanted <<
72  " asked eigenvalues, but the rank of the matrix is lower than "
73  << n_ << endl;
74 
75  abort();
76  }
77 
78  if (automatic_selection_arnoldi_vectors)
79  nb_arnoldi_vectors = min(nglob, 2*nb_eigenvalues_wanted+2);
80 
81  //cout << "n = " << n << endl;
82  //cout << "nb_arnoldi_vectors = " << nb_arnoldi_vectors << endl;
83  }
84 
85 
87 
91  template<class T, class MatStiff, class MatMass>
93  InitMatrix(MatStiff& K)
94  {
95  Kh = &K;
96  Mh = NULL;
97  this->diagonal_mass = true;
98  if ( (!IsSymmetricMatrix(K))
99  && (!IsComplexMatrix(K)) && (shift_imag != T(0)) )
100  {
101  // for real unsymmetric problems, if sigma is complex
102  // we have to use mode 3 or 4 in Arpack => generalized problem
103  this->diagonal_mass = false;
104  }
105 
106  this->Init(K.GetM());
107  }
108 
109 
111 
115  template<class T, class MatStiff, class MatMass>
117  InitMatrix(MatStiff& K, MatMass& M)
118  {
119  Kh = &K;
120  Mh = &M;
121  this->diagonal_mass = false;
122  this->Init(K.GetM());
123  }
124 
125 
126  /*******************
127  * Basic functions *
128  *******************/
129 
130 
132  template<class T, class MatStiff, class MatMass>
134  {
135  return eigenvalue_computation_mode;
136  }
137 
138 
140  template<class T, class MatStiff, class MatMass>
142  {
143  eigenvalue_computation_mode = mode;
144  }
145 
146 
148  template<class T, class MatStiff, class MatMass>
150  {
151  return nb_eigenvalues_wanted;
152  }
153 
154 
156  template<class T, class MatStiff, class MatMass>
158  {
159  return nb_add_eigenvalues;
160  }
161 
162 
164  template<class T, class MatStiff, class MatMass>
166  {
167  return nb_blocks;
168  }
169 
170 
172  template<class T, class MatStiff, class MatMass>
174  {
175  nb_blocks = n;
176  }
177 
178 
180  template<class T, class MatStiff, class MatMass>
182  {
183  return restart_number;
184  }
185 
186 
188  template<class T, class MatStiff, class MatMass>
190  {
191  restart_number = m;
192  }
193 
194 
196  template<class T, class MatStiff, class MatMass>
198  {
199  return ortho_manager;
200  }
201 
202 
204  template<class T, class MatStiff, class MatMass>
206  {
207  return type_solver;
208  }
209 
210 
212  template<class T, class MatStiff, class MatMass>
214  {
215  type_solver = type;
216  }
217 
218 
219 #ifdef SELDON_WITH_MPI
220  template<class T, class MatStiff, class MatMass>
223  {
224  return comm;
225  }
226 
228  template<class T, class MatStiff, class MatMass>
229  void EigenProblem_Base<T, MatStiff, MatMass>::SetCommunicator(MPI_Comm& comm_)
230  {
231  comm = comm_;
232  }
233 #endif
234 
236  template<class T, class MatStiff, class MatMass>
238  {
239  nb_eigenvalues_wanted = n;
240  }
241 
242 
244  template<class T, class MatStiff, class MatMass>
246  {
247  nb_add_eigenvalues = n;
248  }
249 
250 
252  template<class T, class MatStiff, class MatMass>
254  {
255  return type_spectrum_wanted;
256  }
257 
258 
260  template<class T, class MatStiff, class MatMass>
262  {
263  return type_sort_eigenvalues;
264  }
265 
266 
268 
273  template<class T, class MatStiff, class MatMass>
275  {
276  return shift;
277  }
278 
279 
281 
287  template<class T, class MatStiff, class MatMass>
289  {
290  return shift_imag;
291  }
292 
293 
295  template<class T, class MatStiff, class MatMass>
297  {
298  shift = val;
299  }
300 
301 
303  template<class T, class MatStiff, class MatMass>
305  {
306  shift_imag = val;
307  }
308 
309 
311 
315  template<class T, class MatStiff, class MatMass>
317  SetTypeSpectrum(int type, const T& val, int type_sort)
318  {
319  type_spectrum_wanted = type;
320  shift = val;
321  type_sort_eigenvalues = type_sort;
322  }
323 
324 
326 
330  template<class T, class MatStiff, class MatMass>
332  SetTypeSpectrum(int type, const complex<T>& val, int type_sort)
333  {
334  // for real unsymmetric eigenproblems, you can
335  // specify a complex shift
336  type_spectrum_wanted = type;
337  shift = real(val);
338  shift_imag = imag(val);
339 
340  if (Kh != NULL)
341  {
342  if ( (!IsSymmetricMatrix(*Kh))
343  && (!IsComplexMatrix(*Kh)) && (shift_imag != T(0)) )
344  {
345  // for real unsymmetric problems, if sigma is complex
346  // we have to use mode 3 or 4 in Arpack => generalized problem
347  this->diagonal_mass = false;
348  }
349  }
350 
351  type_sort_eigenvalues = type_sort;
352  }
353 
354 
356  template<class T, class MatStiff, class MatMass>
359  {
360  return emin_interval;
361  }
362 
363 
365  template<class T, class MatStiff, class MatMass>
368  {
369  return emax_interval;
370  }
371 
372 
374  template<class T, class MatStiff, class MatMass>
376  ::SetIntervalSpectrum(double l0, double l1)
377  {
378  emin_interval = l0;
379  emax_interval = l1;
380  }
381 
382 
385  template<class T, class MatStiff, class MatMass>
388  {
389  use_cholesky = chol;
390  }
391 
392 
394  template<class T, class MatStiff, class MatMass>
397  {
398  return use_cholesky;
399  }
400 
401 
403  template<class T, class MatStiff, class MatMass>
405  {
406  diagonal_mass = diag;
407  }
408 
409 
411  template<class T, class MatStiff, class MatMass>
413  {
414  return diagonal_mass;
415  }
416 
417 
419  template<class T, class MatStiff, class MatMass>
422  {
423  stopping_criterion = eps;
424  }
425 
426 
428  template<class T, class MatStiff, class MatMass>
431  {
432  return stopping_criterion;
433  }
434 
435 
437  template<class T, class MatStiff, class MatMass>
439  {
440  nb_maximum_iterations = n;
441  }
442 
443 
445  template<class T, class MatStiff, class MatMass>
448  {
449  return nb_maximum_iterations;
450  }
451 
452 
455  template<class T, class MatStiff, class MatMass>
458  {
459  return nb_prod;
460  }
461 
462 
464  template<class T, class MatStiff, class MatMass>
466  {
467  return nb_arnoldi_vectors;
468  }
469 
470 
472  template<class T, class MatStiff, class MatMass>
474  {
475  automatic_selection_arnoldi_vectors = false;
476  nb_arnoldi_vectors = n;
477  }
478 
479 
481  template<class T, class MatStiff, class MatMass>
483  {
484  return n_;
485  }
486 
487 
489  template<class T, class MatStiff, class MatMass>
491  {
492  return n_;
493  }
494 
495 
497  template<class T, class MatStiff, class MatMass>
499  {
500  return print_level;
501  }
502 
503 
505  template<class T, class MatStiff, class MatMass>
507  {
508  print_level = lvl;
509  }
510 
511 
513  template<class T, class MatStiff, class MatMass>
515  {
516  nb_prod++;
517  if (print_level >= 3)
518  {
519  if (nb_prod%10 == 0)
520 #ifdef SELDON_WITH_MPI
521  if (comm.Get_rank() == 0)
522 #endif
523  cout<<" Iteration number " << nb_prod << endl;
524  }
525  else if (print_level >= 1)
526  {
527  if (nb_prod%100 == 0)
528 #ifdef SELDON_WITH_MPI
529  if (comm.Get_rank() == 0)
530 #endif
531  cout<<" Iteration number " << nb_prod << endl;
532  }
533  }
534 
535 
537  template<class T, class MatStiff, class MatMass>
539  {
540  cout << "InitMatrix has not been called" << endl;
541  abort();
542  }
543 
544 
546  template<class T, class MatStiff, class MatMass>
548  {
549  if (Kh != NULL)
550  {
551  if (IsSymmetricMatrix(*Kh))
552  {
553  if (Mh == NULL)
554  return true;
555  else
556  return IsSymmetricMatrix(*Mh);
557  }
558  }
559  else
560  PrintErrorInit();
561 
562  return false;
563  }
564 
565 
567  template<class T, class MatStiff, class MatMass>
569  {
570  if (Kh != NULL)
571  {
572  if (IsComplexMatrix(*Kh))
573  return false;
574  else
575  {
576  if (IsSymmetricMatrix(*Kh))
577  {
578  if (Mh == NULL)
579  return true;
580  else
581  {
582  if (IsComplexMatrix(*Mh))
583  return false;
584 
585  return IsSymmetricMatrix(*Mh);
586  }
587  }
588  }
589  }
590  else
591  PrintErrorInit();
592 
593  return false;
594  }
595 
596 
597  /*********************
598  * Mass matrix stuff *
599  *********************/
600 
601 
603  template<class T, class MatStiff, class MatMass>
605  {
606  for (int i = 0; i < sqrt_diagonal_mass.GetM(); i++)
607  sqrt_diagonal_mass(i) = sqrt(sqrt_diagonal_mass(i));
608  }
609 
610 
612  template<class T, class MatStiff, class MatMass> template<class T0>
615  {
616  for (int i = 0; i < X.GetM(); i++)
617  X(i) /= sqrt_diagonal_mass(i);
618  }
619 
620 
622  template<class T, class MatStiff, class MatMass> template<class T0>
625  {
626  for (int i = 0; i < X.GetM(); i++)
627  X(i) *= sqrt_diagonal_mass(i);
628  }
629 
630 
632  template<class T, class MatStiff, class MatMass>
635  {
636  if (Mh == NULL)
637  {
638  // M = identity
639  sqrt_diagonal_mass.Reallocate(this->n_);
640  sqrt_diagonal_mass.Fill(1.0);
641  }
642  else
643  {
644  sqrt_diagonal_mass.Reallocate(this->n_);
645  for (int i = 0; i < this->n_; i++)
646  sqrt_diagonal_mass(i) = (*Mh)(i, i);
647  }
648  }
649 
650 
652  template<class T, class MatStiff, class MatMass>
655  {
656  // nothing to do, we consider that mass matrix
657  // is already computed
658  }
659 
660 
662  template<class T, class MatStiff, class MatMass>
664  {
665  // mass matrix already computed in Mh
666  }
667 
668 
670  template<class T, class MatStiff, class MatMass>
673  {
674  if (Mh == NULL)
675  {
676  // default : mass matrix is identity (standard eigenvalue problem)
677  Seldon::Copy(X, Y);
678  }
679  else
680  Mlt(*Mh, X, Y);
681  }
682 
683 
684  /**************************
685  * Stiffness matrix stuff *
686  **************************/
687 
688 
690  template<class T, class MatStiff, class MatMass>
692  {
693  // nothing to do, already computed in Kh
694  }
695 
696 
698  template<class T, class MatStiff, class MatMass>
700  ComputeStiffnessMatrix(const T& a, const T& b)
701  {
702  // nothing to do, we use Kh and Mh for the matrix vector product
703  }
704 
705 
707  template<class T, class MatStiff, class MatMass>
710  {
711  if (Kh == NULL)
712  PrintErrorInit();
713  else
714  Mlt(*Kh, X, Y);
715  }
716 
717 
719  template<class T, class MatStiff, class MatMass>
721  MltStiffness(const T& coef_mass, const T& coef_stiff,
722  const Vector<T>& X, Vector<T>& Y)
723  {
724  if (Kh == NULL)
725  PrintErrorInit();
726  else
727  Mlt(*Kh, X, Y);
728 
729  if (coef_mass != T(0))
730  {
731  if (Mh == NULL)
732  for (int i = 0; i < Y.GetM(); i++)
733  Y(i) += coef_mass*X(i);
734  else
735  MltAdd(coef_mass, *Mh, X, coef_stiff, Y);
736  }
737  else
738  {
739  if (coef_stiff != T(1))
740  Mlt(coef_stiff, Y);
741  }
742  }
743 
744 
745 
746  /*************************
747  * Functions to overload *
748  *************************/
749 
750 
752 
756  template<class T, class MatStiff, class MatMass>
758  ComputeAndFactorizeStiffnessMatrix(const T& a, const T& b)
759  {
760  abort();
761  }
762 
763 
765 
769  template<class T, class MatStiff, class MatMass>
771  ComputeAndFactorizeStiffnessMatrix(const complex<T>& a, const complex<T>& b,
772  bool real_part)
773  {
774  abort();
775  }
776 
777 
779  template<class T, class MatStiff, class MatMass> template<class T0>
782  {
783  abort();
784  }
785 
786 
788  template<class T, class MatStiff, class MatMass>
789  template<class TransA, class T0>
791  ComputeSolution(const TransA&, const Vector<T0>& X, Vector<T0>& Y)
792  {
793  abort();
794  }
795 
796 
798  template<class T, class MatStiff, class MatMass>
800  {
801  abort();
802  }
803 
804 
806  template<class T, class MatStiff, class MatMass>
807  template<class TransStatus>
809  MltCholeskyMass(const TransStatus& TransA, Vector<T>& X)
810  {
811  abort();
812  }
813 
814 
816  template<class T, class MatStiff, class MatMass>
817  template<class TransStatus>
819  SolveCholeskyMass(const TransStatus& TransA, Vector<T>& X)
820  {
821  abort();
822  }
823 
824 
826  template<class T, class MatStiff, class MatMass>
828  {
829  sqrt_diagonal_mass.Clear();
830  }
831 
832 
833  /********************************************
834  * Modification of eigenvalues/eigenvectors *
835  ********************************************/
836 
837 
839 
845  template<class EigenPb, class Vector1, class Matrix1, class T0>
846  void ApplyScalingEigenvec(EigenPb& var, Vector1& eigen_values, Vector1& lambda_imag,
847  Matrix1& eigen_vectors,
848  const T0& shiftr, const T0& shifti)
849  {
850 
851  if (var.DiagonalMass())
852  {
853  // scaling to have true eigenvectors
854  for (int i = 0; i < var.sqrt_diagonal_mass.GetM(); i++)
855  for (int j = 0; j < eigen_vectors.GetN(); j++)
856  eigen_vectors(i,j) /= var.sqrt_diagonal_mass(i);
857  }
858  else if (var.UseCholeskyFactoForMass())
859  {
860  Vector<T0> Xcol(eigen_vectors.GetM());
861  for (int j = 0; j < eigen_vectors.GetN(); j++)
862  {
863  for (int i = 0; i < eigen_vectors.GetM(); i++)
864  Xcol(i) = eigen_vectors(i,j);
865 
866  var.SolveCholeskyMass(SeldonTrans, Xcol);
867  for (int i = 0; i < eigen_vectors.GetM(); i++)
868  eigen_vectors(i,j) = Xcol(i);
869  }
870  }
871 
872  if (var.GetComputationalMode() != var.REGULAR_MODE)
873  {
874  if ( (var.eigenvalue_computation_mode == var.INVERT_MODE)
875  && (var.GetTypeSpectrum() != var.CENTERED_EIGENVALUES))
876  {
877  // nothing to change
878  }
879  else if ((var.DiagonalMass())|| (var.UseCholeskyFactoForMass())
880  || (var.eigenvalue_computation_mode == var.INVERT_MODE))
881  {
882  // shift-invert mode, we have to modify eigenvalues
883  for (int i = 0; i < eigen_values.GetM(); i++)
884  {
885  if ((eigen_values(i) == 0) && (lambda_imag(i) == 0))
886  {
887  eigen_values(i) = 0;
888  lambda_imag(i) = 0;
889  }
890  else
891  {
892  complex<T0> val = 1.0/complex<T0>(eigen_values(i), lambda_imag(i))
893  + complex<T0>(shiftr, shifti);
894 
895  eigen_values(i) = real(val);
896  lambda_imag(i) = imag(val);
897  }
898  }
899 
900  }
901  else if (var.GetImagShiftValue() != T0(0))
902  {
903  int n = eigen_vectors.GetM();
904  Vector<T0> X(n), Ax(n), Mx(n), Y(n);
905  int j = 0;
906  Ax.Fill(T0(0));
907  Mx.Fill(T0(0));
908  while (j < eigen_values.GetM())
909  {
910  if (lambda_imag(j) == T0(0))
911  {
912  // real eigenvalue
913  // lambda is retrieved by computing Rayleigh quotient
914  for (int i = 0; i < eigen_vectors.GetM(); i++)
915  X(i) = eigen_vectors(i,j);
916 
917  var.MltMass(X, Mx);
918  var.MltStiffness(X, Ax);
919  eigen_values(j) = DotProd(X, Ax)/DotProd(X, Mx);
920 
921  // next eigenvalue
922  j++;
923  }
924  else
925  {
926  if (j == eigen_values.GetM() - 1)
927  {
928  eigen_values(j) = 0.0;
929  lambda_imag(j) = 0.0;
930 
931  break;
932  }
933 
934  // conjugate pair of eigenvalues
935  for (int i = 0; i < eigen_vectors.GetM(); i++)
936  {
937  X(i) = eigen_vectors(i, j);
938  Y(i) = eigen_vectors(i, j+1);
939  }
940 
941  // complex Rayleigh quotient
942  var.MltStiffness(X, Ax);
943  T0 numr = DotProd(X, Ax);
944  T0 numi = DotProd(Y, Ax);
945 
946  var.MltStiffness(Y, Ax);
947  numr += DotProd(Y, Ax);
948  numi -= DotProd(X, Ax);
949 
950  var.MltMass(X, Mx);
951  T0 denr = DotProd(X, Mx);
952  T0 deni = DotProd(Y, Mx);
953 
954  var.MltMass(Y, Mx);
955  denr += DotProd(Y, Mx);
956  deni -= DotProd(X, Mx);
957 
958  complex<T0> val = complex<T0>(numr, numi)/complex<T0>(denr, deni);
959 
960  eigen_values(j) = real(val);
961  eigen_values(j+1) = real(val);
962 
963  lambda_imag(j) = -imag(val);
964  lambda_imag(j+1) = imag(val);
965 
966  // next eigenvalue
967  j += 2;
968  }
969  }
970  }
971  }
972  }
973 
974 
976 
982  template<class EigenPb, class Vector1, class Matrix1, class T0>
983  void ApplyScalingEigenvec(EigenPb& var, Vector1& eigen_values, Vector1& lambda_imag,
984  Matrix1& eigen_vectors,
985  const complex<T0>& shiftr, const complex<T0>& shifti)
986  {
987 
988  if (var.DiagonalMass())
989  {
990  // scaling to have true eigenvectors
991  for (int i = 0; i < var.sqrt_diagonal_mass.GetM(); i++)
992  for (int j = 0; j < eigen_vectors.GetN(); j++)
993  eigen_vectors(i,j) /= var.sqrt_diagonal_mass(i);
994  }
995  else if (var.UseCholeskyFactoForMass())
996  {
997  Vector<complex<T0> > Xcol(eigen_vectors.GetM());
998  for (int j = 0; j < eigen_vectors.GetN(); j++)
999  {
1000  for (int i = 0; i < eigen_vectors.GetM(); i++)
1001  Xcol(i) = eigen_vectors(i,j);
1002 
1003  var.SolveCholeskyMass(SeldonTrans, Xcol);
1004  for (int i = 0; i < eigen_vectors.GetM(); i++)
1005  eigen_vectors(i,j) = Xcol(i);
1006  }
1007  }
1008 
1009  if (var.GetComputationalMode() != var.REGULAR_MODE)
1010  {
1011  if ( (var.eigenvalue_computation_mode == var.INVERT_MODE)
1012  && (var.GetTypeSpectrum() != var.CENTERED_EIGENVALUES))
1013  {
1014  // nothing to change
1015  }
1016  else if ((var.DiagonalMass())|| (var.UseCholeskyFactoForMass())
1017  || (var.eigenvalue_computation_mode == var.INVERT_MODE))
1018  {
1019  // shift-invert mode, we have to modify eigenvalues
1020  for (int i = 0; i < eigen_values.GetM(); i++)
1021  {
1022  complex<T0> val = 1.0/eigen_values(i) + shiftr;
1023 
1024  eigen_values(i) = val;
1025  }
1026 
1027  }
1028  }
1029  }
1030 
1031 
1032  /***********************
1033  * Sorting eigenvalues *
1034  ***********************/
1035 
1036 
1038  template<class T, class Storage1, class Storage2,
1039  class Alloc1, class Alloc2>
1040  void SortEigenvalues(Vector<T>& lambda_r, Vector<T>& lambda_i,
1043  int type_spectrum, int type_sort,
1044  const T& shift_r, const T& shift_i)
1045  {
1046  int n = min(lambda_r.GetM(), eigen_old.GetN());;
1047 
1048  IVect permutation(n);
1049  permutation.Fill();
1050  eigen_new.Reallocate(eigen_old.GetM(), n);
1051 
1052  // creating a vector that can be sorted
1053  Vector<T> L(n);
1054  if (type_spectrum == EigenProblem_Base<T>::CENTERED_EIGENVALUES)
1055  {
1056  // eigenvalues closest to shift are placed at beginning
1057  switch (type_sort)
1058  {
1060  {
1061  for (int i = 0; i < n; i++)
1062  L(i) = 1.0/abs(shift_r - lambda_r(i));
1063  }
1064  break;
1066  {
1067  for (int i = 0; i < n; i++)
1068  L(i) = 1.0/abs(shift_i - lambda_i(i));
1069  }
1070  break;
1072  {
1073  for (int i = 0; i < n; i++)
1074  L(i) = 1.0/abs(complex<T>(shift_r - lambda_r(i), shift_i - lambda_i(i)));
1075  }
1076  break;
1077  }
1078  }
1079  else
1080  {
1081  // smallest eigenvalues are placed at beginning
1082  switch (type_sort)
1083  {
1085  {
1086  for (int i = 0; i < n; i++)
1087  L(i) = abs(lambda_r(i));
1088  }
1089  break;
1091  {
1092  for (int i = 0; i < n; i++)
1093  L(i) = abs(lambda_i(i));
1094  }
1095  break;
1097  {
1098  for (int i = 0; i < n; i++)
1099  L(i) = abs(complex<T>(lambda_r(i), lambda_i(i)));
1100  }
1101  break;
1102  }
1103  }
1104 
1105  // sorting L, and retrieving permutation array
1106  Sort(L, permutation);
1107 
1108  // permuting eigenvalues and eigenvectors
1109  Vector<T> oldLambda_r = lambda_r, oldLambda_i = lambda_i;
1110  for (int i = 0; i < n; i++)
1111  {
1112  lambda_r(i) = oldLambda_r(permutation(i));
1113  lambda_i(i) = oldLambda_i(permutation(i));
1114  for (int j = 0; j < eigen_old.GetM(); j++)
1115  eigen_new(j, i) = eigen_old(j, permutation(i));
1116  }
1117 
1118  }
1119 
1120 
1122  template<class T, class Storage1, class Storage2,
1123  class Alloc1, class Alloc2>
1124  void SortEigenvalues(Vector<complex<T> >& lambda_r, Vector<complex<T> >& lambda_i,
1125  Matrix<complex<T>, General, Storage1, Alloc1>& eigen_old,
1126  Matrix<complex<T>, General, Storage2, Alloc2>& eigen_new,
1127  int type_spectrum, int type_sort,
1128  const complex<T>& shift_r, const complex<T>& shift_i)
1129  {
1130  // complex case, ignoring lambda_i and shift_i
1131  int n = min(lambda_r.GetM(), eigen_old.GetN());;
1132 
1133  IVect permutation(n);
1134  permutation.Fill();
1135  eigen_new.Reallocate(eigen_old.GetM(), n);
1136 
1137  // creating a vector that can be sorted
1138  Vector<T> L(n);
1139  if (type_spectrum == EigenProblem_Base<T>::CENTERED_EIGENVALUES)
1140  {
1141  // eigenvalues closest to shift are placed at beginning
1142  switch (type_sort)
1143  {
1145  {
1146  for (int i = 0; i < n; i++)
1147  L(i) = 1.0/abs(real(shift_r - lambda_r(i)));
1148  }
1149  break;
1151  {
1152  for (int i = 0; i < n; i++)
1153  L(i) = 1.0/abs(imag(shift_r - lambda_r(i)));
1154  }
1155  break;
1157  {
1158  for (int i = 0; i < n; i++)
1159  L(i) = 1.0/abs(shift_r - lambda_r(i));
1160  }
1161  break;
1162  }
1163  }
1164  else
1165  {
1166  // smallest eigenvalues are placed at beginning
1167  switch (type_sort)
1168  {
1170  {
1171  for (int i = 0; i < n; i++)
1172  L(i) = abs(real(lambda_r(i)));
1173  }
1174  break;
1176  {
1177  for (int i = 0; i < n; i++)
1178  L(i) = abs(imag(lambda_r(i)));
1179  }
1180  break;
1182  {
1183  for (int i = 0; i < n; i++)
1184  L(i) = abs(lambda_r(i));
1185  }
1186  break;
1187  }
1188  }
1189 
1190  // sorting L, and retrieving permutation array
1191  Sort(L, permutation);
1192 
1193  // permuting eigenvalues and eigenvectors
1194  Vector<complex<T> > oldLambda_r = lambda_r, oldLambda_i = lambda_i;
1195  for (int i = 0; i < n; i++)
1196  {
1197  lambda_r(i) = oldLambda_r(permutation(i));
1198  lambda_i(i) = oldLambda_i(permutation(i));
1199  for (int j = 0; j < eigen_old.GetM(); j++)
1200  eigen_new(j, i) = eigen_old(j, permutation(i));
1201  }
1202 
1203  }
1204 
1205 
1206  /*********************
1207  * DenseEigenProblem *
1208  *********************/
1209 
1210 
1212  template<class T, class Prop, class Storage,
1213  class Tmass, class PropM, class StorageM>
1216  Matrix<Tmass, PropM, StorageM> >()
1217  {
1218  }
1219 
1220 
1222  template<class T, class Prop, class Storage,
1223  class Tmass, class PropM, class StorageM>
1226  {
1227  if (this->Mh == NULL)
1228  {
1229  mat_chol.Reallocate(this->n_, this->n_);
1230  mat_chol.SetIdentity();
1231  }
1232  else
1233  {
1234  mat_chol = *(this->Mh);
1235  GetCholesky(mat_chol);
1236  Xchol_real.Reallocate(mat_chol.GetM());
1237  Xchol_imag.Reallocate(mat_chol.GetM());
1238  }
1239  }
1240 
1241 
1243  template<class T, class Prop, class Storage,
1244  class Tmass, class PropM, class StorageM>
1245  template<class TransStatus, class T0>
1247  MltCholeskyMass(const TransStatus& transA, Vector<T0>& X)
1248  {
1249  MltCholesky(transA, mat_chol, X);
1250  }
1251 
1252 
1254  template<class T, class Prop, class Storage,
1255  class Tmass, class PropM, class StorageM>
1256  template<class TransStatus, class T0>
1258  SolveCholeskyMass(const TransStatus& transA, Vector<T0>& X)
1259  {
1260  SolveCholesky(transA, mat_chol, X);
1261  }
1262 
1263 
1265  template<class T, class Prop, class Storage,
1266  class Tmass, class PropM, class StorageM>
1267  template<class TransStatus>
1269  MltCholeskyMass(const TransStatus& transA, Vector<complex<double> >& X)
1270  {
1271  for (int i = 0; i < X.GetM(); i++)
1272  {
1273  Xchol_real(i) = real(X(i));
1274  Xchol_imag(i) = imag(X(i));
1275  }
1276 
1277  MltCholesky(transA, mat_chol, Xchol_real);
1278  MltCholesky(transA, mat_chol, Xchol_imag);
1279 
1280  for (int i = 0; i < X.GetM(); i++)
1281  X(i) = complex<double>(Xchol_real(i), Xchol_imag(i));
1282  }
1283 
1284 
1286  template<class T, class Prop, class Storage,
1287  class Tmass, class PropM, class StorageM>
1288  template<class TransStatus>
1290  SolveCholeskyMass(const TransStatus& transA, Vector<complex<double> >& X)
1291  {
1292  for (int i = 0; i < X.GetM(); i++)
1293  {
1294  Xchol_real(i) = real(X(i));
1295  Xchol_imag(i) = imag(X(i));
1296  }
1297 
1298  SolveCholesky(transA, mat_chol, Xchol_real);
1299  SolveCholesky(transA, mat_chol, Xchol_imag);
1300 
1301  for (int i = 0; i < X.GetM(); i++)
1302  X(i) = complex<double>(Xchol_real(i), Xchol_imag(i));
1303  }
1304 
1305 
1307  template<class T, class Prop, class Storage,
1308  class Tmass, class PropM, class StorageM>
1311  {
1312  if (this->Kh == NULL)
1313  this->PrintErrorInit();
1314 
1315  this->complex_system = false;
1316  // computation of mat_lu = a M + b K
1317  mat_lu = *(this->Kh);
1318  Mlt(b, mat_lu);
1319  if (this->Mh == NULL)
1320  {
1321  for (int i = 0; i < this->n_; i++)
1322  mat_lu(i, i) += a;
1323  }
1324  else
1325  Add(a, *(this->Mh), mat_lu);
1326 
1327  // factorisation
1328  GetLU(mat_lu, pivot);
1329  }
1330 
1331 
1333  template<class T, class Prop, class Storage,
1334  class Tmass, class PropM, class StorageM>
1336  ComputeAndFactorizeStiffnessMatrix(const complex<T>& a, const complex<T>& b,
1337  bool real_part)
1338  {
1339  ComputeAndFactorizeComplexMatrix(a, b);
1340  }
1341 
1342 
1344  template<class T, class Prop, class Storage,
1345  class Tmass, class PropM, class StorageM>
1347  ComputeAndFactorizeComplexMatrix(const complex<double>& a, const complex<double>& b,
1348  bool real_part)
1349  {
1350  if (this->Kh == NULL)
1351  this->PrintErrorInit();
1352 
1353  this->complex_system = true;
1354  // inverse of (a M + b K), then we take real_part or imaginary part
1355  Matrix<complex<double>, Prop, Storage> InvMat(this->n_, this->n_);
1356  for (int i = 0; i < this->n_; i++)
1357  for (int j = 0; j < this->n_; j++)
1358  InvMat(i, j) = (*this->Kh)(i, j);
1359 
1360  Mlt(b, InvMat);
1361  if (this->Mh == NULL)
1362  {
1363  for (int i = 0; i < this->n_; i++)
1364  InvMat(i, i) += a;
1365  }
1366  else
1367  {
1368  for (int i = 0; i < this->n_; i++)
1369  for (int j = 0; j < this->n_; j++)
1370  InvMat(i, j) += a * (*this->Mh)(i, j);
1371  }
1372 
1373  // inverse
1374  GetInverse(InvMat);
1375 
1376  // then extracting real or imaginary part
1377  mat_lu.Reallocate(this->n_, this->n_);
1378  if (real_part)
1379  {
1380  for (int i = 0; i < this->n_; i++)
1381  for (int j = 0; j < this->n_; j++)
1382  mat_lu(i, j) = real(InvMat(i, j));
1383  }
1384  else
1385  {
1386  for (int i = 0; i < this->n_; i++)
1387  for (int j = 0; j < this->n_; j++)
1388  mat_lu(i, j) = imag(InvMat(i, j));
1389  }
1390  }
1391 
1392 
1394  template<class T, class Prop, class Storage,
1395  class Tmass, class PropM, class StorageM> template<class T0>
1398  const complex<T0>& b, bool real_p)
1399  {
1400  // this case should not appear
1401  cout << "Case not handled" << endl;
1402  abort();
1403  }
1404 
1405 
1407  template<class T, class Prop, class Storage,
1408  class Tmass, class PropM, class StorageM> template<class T0>
1411  {
1412  if (this->complex_system)
1413  Mlt(mat_lu, X, Y);
1414  else
1415  {
1416  Copy(X, Y);
1417  SolveLU(mat_lu, pivot, Y);
1418  }
1419  }
1420 
1421 
1423  template<class T, class Prop, class Storage,
1424  class Tmass, class PropM, class StorageM>
1425  template<class TransA, class T0>
1427  ComputeSolution(const TransA& transA, const Vector<T0>& X, Vector<T0>& Y)
1428  {
1429  if (this->complex_system)
1430  Mlt(transA, mat_lu, X, Y);
1431  else
1432  {
1433  Copy(X, Y);
1434  SolveLU(transA, mat_lu, pivot, Y);
1435  }
1436  }
1437 
1438 
1440  template<class T, class Prop, class Storage,
1441  class Tmass, class PropM, class StorageM>
1444  {
1446  Matrix<Tmass, PropM, StorageM> >::Clear();
1447 
1448  mat_lu.Clear();
1449  mat_chol.Clear();
1450  }
1451 
1452 
1453  /**********************
1454  * SparseEigenProblem *
1455  **********************/
1456 
1457 
1459  template<class T, class MatStiff, class MatMass>
1462  : EigenProblem_Base<T, MatStiff, MatMass>()
1463  {
1464  imag_solution = false;
1465  mat_lu.RefineSolution();
1466  mat_lu_cplx.RefineSolution();
1467  }
1468 
1469 
1471  template<class T, class MatStiff, class MatMass>
1473  {
1474  chol_facto_mass_matrix.SelectDirectSolver(type);
1475  }
1476 
1477 
1479  template<class T, class MatStiff, class MatMass>
1482  {
1483  if (this->Mh == NULL)
1484  this->PrintErrorInit();
1485 
1486  if (this->print_level > 0)
1487  chol_facto_mass_matrix.ShowMessages();
1488 
1489  MassValue x_test;
1490  FactorizeCholeskyMass(x_test, *this->Mh);
1491 
1492  if (this->print_level < 2)
1493  chol_facto_mass_matrix.HideMessages();
1494 
1495  Xchol_real.Reallocate(this->n_);
1496  Xchol_imag.Reallocate(this->n_);
1497  }
1498 
1499 
1501  template<class T, class MatStiff, class MatMass>
1502  template<class Storage, class Alloc>
1505  {
1506  chol_facto_mass_matrix.Factorize(M, true);
1507  }
1508 
1509 
1511  template<class T, class MatStiff, class MatMass>
1512  template<class T0, class T1, class Prop, class Storage, class Alloc>
1515  {
1516  cout << "Cholesky factorisation has not been implemented "
1517  << "for complex matrices" << endl;
1518  abort();
1519  }
1520 
1521 
1523  template<class T, class MatStiff, class MatMass>
1524  template<class TransStatus, class T0>
1526  MltCholeskyMass(const TransStatus& TransA, Vector<T0>& X)
1527  {
1528  chol_facto_mass_matrix.Mlt(TransA, X);
1529  }
1530 
1531 
1533  template<class T, class MatStiff, class MatMass>
1534  template<class TransStatus, class T0>
1536  SolveCholeskyMass(const TransStatus& TransA, Vector<T0>& X)
1537  {
1538  chol_facto_mass_matrix.Solve(TransA, X);
1539  }
1540 
1541 
1543  template<class T, class MatStiff, class MatMass>
1544  template<class TransStatus>
1546  MltCholeskyMass(const TransStatus& TransA, Vector<complex<double> >& X)
1547  {
1548  MassValue x_test;
1549  MltCholeskyMass(TransA, X, x_test);
1550  }
1551 
1552 
1554  template<class T, class MatStiff, class MatMass>
1555  template<class TransStatus>
1557  MltCholeskyMass(const TransStatus& TransA, Vector<complex<double> >& X,
1558  complex<double>&)
1559  {
1560  cout << "Cholesky factorisation has not been implemented "
1561  << "for complex matrices" << endl;
1562  abort();
1563  }
1564 
1565 
1567  template<class T, class MatStiff, class MatMass>
1568  template<class TransStatus>
1570  MltCholeskyMass(const TransStatus& TransA, Vector<complex<double> >& X, double&)
1571  {
1572  for (int i = 0; i < X.GetM(); i++)
1573  {
1574  Xchol_real(i) = real(X(i));
1575  Xchol_imag(i) = imag(X(i));
1576  }
1577 
1578  chol_facto_mass_matrix.Mlt(TransA, Xchol_real);
1579  chol_facto_mass_matrix.Mlt(TransA, Xchol_imag);
1580 
1581  for (int i = 0; i < X.GetM(); i++)
1582  X(i) = complex<double>(Xchol_real(i), Xchol_imag(i));
1583 
1584  }
1585 
1586 
1588  template<class T, class MatStiff, class MatMass>
1589  template<class TransStatus>
1591  SolveCholeskyMass(const TransStatus& TransA, Vector<complex<double> >& X)
1592  {
1593  MassValue x_test;
1594  SolveCholeskyMass(TransA, X, x_test);
1595  }
1596 
1597 
1599  template<class T, class MatStiff, class MatMass>
1600  template<class TransStatus>
1602  SolveCholeskyMass(const TransStatus& TransA, Vector<complex<double> >& X,
1603  complex<double>&)
1604  {
1605  cout << "Cholesky factorisation has not been "
1606  << "implemented for complex matrices" << endl;
1607  abort();
1608  }
1609 
1610 
1612  template<class T, class MatStiff, class MatMass>
1613  template<class TransStatus>
1615  SolveCholeskyMass(const TransStatus& TransA, Vector<complex<double> >& X, double&)
1616  {
1617  for (int i = 0; i < X.GetM(); i++)
1618  {
1619  Xchol_real(i) = real(X(i));
1620  Xchol_imag(i) = imag(X(i));
1621  }
1622 
1623  chol_facto_mass_matrix.Solve(TransA, Xchol_real);
1624  chol_facto_mass_matrix.Solve(TransA, Xchol_imag);
1625 
1626  for (int i = 0; i < X.GetM(); i++)
1627  X(i) = complex<double>(Xchol_real(i), Xchol_imag(i));
1628  }
1629 
1630 
1633  template<class T, class MatStiff, class MatMass>
1636  {
1637  this->complex_system = false;
1638  if (this->Kh == NULL)
1639  this->PrintErrorInit();
1640 
1641  if (this->print_level > 0)
1642  mat_lu.ShowMessages();
1643 
1644  // retrieving symmetry of mass matrix
1645  bool sym_mh = true;
1646  if (this->Mh != NULL)
1647  {
1648  if (!IsSymmetricMatrix(*this->Mh))
1649  sym_mh = false;
1650  }
1651 
1652  T zero; SetComplexZero(zero);
1653 
1654  if (b == zero)
1655  {
1656  // only mass matrix must be factorized
1657  if (sym_mh)
1658  {
1660  if (this->Mh == NULL)
1661  {
1662  A.Reallocate(this->n_, this->n_);
1663  A.SetIdentity();
1664  }
1665  else
1666  Copy(*(this->Mh), A);
1667 
1668  Mlt(a, A);
1669  mat_lu.Factorize(A);
1670  }
1671  else
1672  {
1674  Copy(*(this->Mh), A);
1675  Mlt(a, A);
1676  mat_lu.Factorize(A);
1677  }
1678  }
1679  else if (IsSymmetricMatrix(*this->Kh) && sym_mh)
1680  {
1681  // forming a M + b K and factorizing it when the result is symmetric
1683  Copy(*(this->Kh), A);
1684  Mlt(b, A);
1685  if (a != zero)
1686  {
1687  if (this->Mh == NULL)
1688  {
1689  for (int i = 0; i < this->n_; i++)
1690  A.AddInteraction(i, i, a);
1691  }
1692  else
1693  Add(a, *(this->Mh), A);
1694  }
1695 
1696  mat_lu.Factorize(A);
1697  }
1698  else
1699  {
1700  // forming a M + b K and factorizing it when the result is unsymmetric
1702  Copy(*(this->Kh), A);
1703  Mlt(b, A);
1704  if (a != zero)
1705  {
1706  if (this->Mh == NULL)
1707  {
1708  for (int i = 0; i < this->n_; i++)
1709  A.AddInteraction(i, i, a);
1710  }
1711  else
1712  Add(a, *(this->Mh), A);
1713  }
1714 
1715  mat_lu.Factorize(A);
1716  }
1717 
1718  if (this->print_level < 2)
1719  mat_lu.HideMessages();
1720  }
1721 
1722 
1724  template<class T, class MatStiff, class MatMass>
1727  const complex<T>& b,
1728  bool real_p)
1729  {
1730  ComputeAndFactorizeComplexMatrix(a, b, real_p);
1731  }
1732 
1733 
1735  template<class T, class MatStiff, class MatMass> template<class T0>
1738  const complex<T0>& b,
1739  bool real_p)
1740  {
1741  // this case should not appear
1742  cout << "Case not handled" << endl;
1743  abort();
1744  }
1745 
1746 
1748  template<class T, class MatStiff, class MatMass>
1750  ComputeAndFactorizeComplexMatrix(const complex<double>& a,
1751  const complex<double>& b,
1752  bool real_p)
1753  {
1754  this->complex_system = true;
1755  if (this->Kh == NULL)
1756  this->PrintErrorInit();
1757 
1758  imag_solution = !real_p;
1759 
1760  if (this->print_level > 0)
1761  mat_lu_cplx.ShowMessages();
1762 
1763  // retrieving symmetry of mass matrix
1764  bool sym_mh = true;
1765  if (this->Mh != NULL)
1766  {
1767  if (!IsSymmetricMatrix(*this->Mh))
1768  sym_mh = false;
1769  }
1770 
1771  complex<double> zero(0, 0);
1772 
1773  if (b == zero)
1774  {
1775  // only mass matrix must be factorized
1776  if (sym_mh)
1777  {
1779  if (this->Mh == NULL)
1780  {
1781  A.Reallocate(this->n_, this->n_);
1782  A.SetIdentity();
1783  }
1784  else
1785  Copy(*(this->Mh), A);
1786 
1787  Mlt(a, A);
1788  mat_lu_cplx.Factorize(A);
1789  }
1790  else
1791  {
1793  Copy(*(this->Mh), A);
1794  Mlt(a, A);
1795  mat_lu_cplx.Factorize(A);
1796  }
1797  }
1798  else if (IsSymmetricMatrix(*this->Kh) && sym_mh)
1799  {
1800  // forming a M + b K
1802  Copy(*(this->Kh), A);
1803  Mlt(b, A);
1804  if (a != zero)
1805  {
1806  if (this->Mh == NULL)
1807  {
1808  for (int i = 0; i < this->n_; i++)
1809  A.AddInteraction(i, i, a);
1810  }
1811  else
1812  Add(a, *(this->Mh), A);
1813  }
1814 
1815  mat_lu_cplx.Factorize(A);
1816  }
1817  else
1818  {
1819  // forming a M + b K
1821  Copy(*(this->Kh), A);
1822  Mlt(b, A);
1823  if (a != zero)
1824  {
1825  if (this->Mh == NULL)
1826  {
1827  for (int i = 0; i < this->n_; i++)
1828  A.AddInteraction(i, i, a);
1829  }
1830  else
1831  Add(a, *(this->Mh), A);
1832  }
1833 
1834  mat_lu_cplx.Factorize(A);
1835  }
1836 
1837  if (this->print_level < 2)
1838  mat_lu_cplx.HideMessages();
1839  }
1840 
1841 
1843  template<class T, class MatStiff, class MatMass> template<class T0>
1846  {
1847  if (this->complex_system)
1848  {
1849  ComputeComplexSolution(SeldonNoTrans, X, Y);
1850  }
1851  else
1852  {
1853  Copy(X, Y);
1854  mat_lu.Solve(Y);
1855  }
1856  }
1857 
1858 
1860  template<class T, class MatStiff, class MatMass>
1861  template<class TransA, class T0>
1863  ComputeSolution(const TransA& transA, const Vector<T0>& X, Vector<T0>& Y)
1864  {
1865  if (this->complex_system)
1866  {
1867  ComputeComplexSolution(transA, X, Y);
1868  }
1869  else
1870  {
1871  Copy(X, Y);
1872  mat_lu.Solve(transA, Y);
1873  }
1874  }
1875 
1876 
1878  template<class T, class MatStiff, class MatMass> template<class TransA>
1880  ComputeComplexSolution(const TransA& transA,
1881  const Vector<double>& X, Vector<double>& Y)
1882  {
1883  Vector<complex<T> > Xcplx(this->n_);
1884  for (int i = 0; i < this->n_; i++)
1885  Xcplx(i) = X(i);
1886 
1887  mat_lu_cplx.Solve(Xcplx);
1888 
1889  if (imag_solution)
1890  for (int i = 0; i < this->n_; i++)
1891  Y(i) = imag(Xcplx(i));
1892  else
1893  for (int i = 0; i < this->n_; i++)
1894  Y(i) = real(Xcplx(i));
1895 
1896  }
1897 
1898 
1900  template<class T, class MatStiff, class MatMass> template<class TransA>
1902  ComputeComplexSolution(const TransA& transA,
1903  const Vector<complex<double> >& X,
1904  Vector<complex<double> >& Y)
1905  {
1906  Copy(X, Y);
1907  mat_lu_cplx.Solve(transA, Y);
1908  }
1909 
1910 
1912  template<class T, class MatStiff, class MatMass>
1914  {
1915  mat_lu.Clear();
1916  mat_lu_cplx.Clear();
1917  chol_facto_mass_matrix.Clear();
1918  Xchol_real.Clear();
1919  Xchol_imag.Clear();
1920  }
1921 
1922 
1924  template<class T, class MatStiff>
1927  : EigenProblem_Base<T, MatStiff, Matrix<double, Symmetric, ArrayRowSymSparse> >()
1928  {
1929  }
1930 
1931 #ifndef SELDON_WITH_COMPILED_LIBRARY
1932  int TypeEigenvalueSolver::default_solver(0);
1933 #endif
1934 
1935 
1937  {
1938 #ifdef SELDON_WITH_ANASAZI
1939  return ANASAZI;
1940 #endif
1941 
1942 #ifdef SELDON_WITH_FEAST
1943  return FEAST;
1944 #endif
1945 
1946 #ifdef SELDON_WITH_ARPACK
1947  return ARPACK;
1948 #endif
1949 
1950  return -1;
1951  }
1952 
1953 
1954  template<class EigenPb, class Vector1, class Vector2,
1955  class T, class Prop, class Storage, class Alloc3>
1956  void GetEigenvaluesEigenvectors(EigenPb& var_eig, Vector1& lambda,
1957  Vector2& lambda_imag,
1959  {
1960  int type_solver = TypeEigenvalueSolver::default_solver;
1961  if (type_solver == TypeEigenvalueSolver::DEFAULT)
1963 
1964  if (type_solver == TypeEigenvalueSolver::ARPACK)
1965  {
1966 #ifdef SELDON_WITH_ARPACK
1967  T zero; SetComplexZero(zero);
1968  Matrix<T, General, ColMajor> eigen_old;
1969  FindEigenvaluesArpack(var_eig, lambda, lambda_imag, eigen_old);
1970 
1971  // eigenvalues are sorted by ascending order
1972  SortEigenvalues(lambda, lambda_imag, eigen_old,
1973  eigen_vec, var_eig.LARGE_EIGENVALUES,
1974  var_eig.GetTypeSorting(), zero, zero);
1975 #else
1976  cout << "Recompile with Arpack" << endl;
1977  abort();
1978 #endif
1979  }
1980  else if (type_solver == TypeEigenvalueSolver::ANASAZI)
1981  {
1982 #ifdef SELDON_WITH_ANASAZI
1983  T zero; SetComplexZero(zero);
1984  Matrix<T, General, ColMajor> eigen_old;
1985  FindEigenvaluesAnasazi(var_eig, lambda, lambda_imag, eigen_old);
1986 
1987  // eigenvalues are sorted by ascending order
1988  SortEigenvalues(lambda, lambda_imag, eigen_old,
1989  eigen_vec, var_eig.LARGE_EIGENVALUES,
1990  var_eig.GetTypeSorting(), zero, zero);
1991 #else
1992  cout << "Recompile with Anasazi" << endl;
1993  abort();
1994 #endif
1995  }
1996  else if (type_solver == TypeEigenvalueSolver::FEAST)
1997  {
1998 #ifdef SELDON_WITH_FEAST
1999  T zero; SetComplexZero(zero);
2000  Matrix<T, General, ColMajor> eigen_old;
2001  FindEigenvaluesFeast(var_eig, lambda, lambda_imag, eigen_old);
2002 
2003  // eigenvalues are sorted by ascending order
2004  SortEigenvalues(lambda, lambda_imag, eigen_old,
2005  eigen_vec, var_eig.LARGE_EIGENVALUES,
2006  var_eig.GetTypeSorting(), zero, zero);
2007 #else
2008  cout << "Recompile with MKL" << endl;
2009  abort();
2010 #endif
2011  }
2012  else
2013  {
2014  cout << "Recompile with eigenvalue solver" << endl;
2015  abort();
2016  }
2017 
2018  }
2019 
2020 }
2021 
2022 #define SELDON_FILE_EIGENVALUE_SOLVER_CXX
2023 #endif
Seldon::EigenProblem_Base::IsSymmetricProblem
bool IsSymmetricProblem() const
returns true if the matrix is symmetric
Definition: EigenvalueSolver.cxx:547
Seldon::EigenProblem_Base::IsHermitianProblem
bool IsHermitianProblem() const
returns true if the matrix is hermitian
Definition: EigenvalueSolver.cxx:568
Seldon::EigenProblem_Base::PrintErrorInit
void PrintErrorInit() const
prints error of initialization and aborts program
Definition: EigenvalueSolver.cxx:538
Seldon::EigenProblem_Base::GetTypeSpectrum
int GetTypeSpectrum() const
returns the spectrum desired (large, small eigenvalues, etc)
Definition: EigenvalueSolver.cxx:253
Seldon::DenseEigenProblem::MltCholeskyMass
void MltCholeskyMass(const TransStatus &transA, Vector< T0 > &X)
computation of L X or L^T X
Definition: EigenvalueSolver.cxx:1247
Seldon::EigenProblem_Base::Init
void Init(int n)
initialisation of the size of the eigenvalue problem
Definition: EigenvalueSolver.cxx:57
Seldon::SparseEigenProblem::ComputeComplexSolution
void ComputeComplexSolution(const TransA &, const Vector< double > &X, Vector< double > &Y)
solves (a M + b K) Y = X when a and b are complex
Definition: EigenvalueSolver.cxx:1880
Seldon::EigenProblem_Base::EigenProblem_Base
EigenProblem_Base()
default constructor
Definition: EigenvalueSolver.cxx:15
Seldon::SparseEigenProblem::mat_lu_cplx
SparseDirectSolver< Complexe > mat_lu_cplx
factorisation of complex system
Definition: EigenvalueSolver.hxx:409
Seldon::Copy
void Copy(const DistributedMatrix< complex< T >, Prop1, Storage1, Allocator1 > &A, DistributedMatrix< T, Prop2, Storage2, Allocator2 > &B)
converts a distributed matrix to another one
Definition: DistributedMatrixInline.cxx:344
Seldon::SparseEigenProblem::ComputeAndFactorizeComplexMatrix
void ComputeAndFactorizeComplexMatrix(const complex< T0 > &a, const complex< T0 > &b, bool real_p=true)
intermediary function
Definition: EigenvalueSolver.cxx:1737
Seldon::EigenProblem_Base::SetNbMaximumRestarts
void SetNbMaximumRestarts(int)
sets the restart parameter used in blocked solvers
Definition: EigenvalueSolver.cxx:189
Seldon::MatrixFreeEigenProblem::MatrixFreeEigenProblem
MatrixFreeEigenProblem()
default constructor
Definition: EigenvalueSolver.cxx:1926
Seldon::SparseEigenProblem::FactorizeCholeskyMass
void FactorizeCholeskyMass()
computes Cholesky factorisation of M from matrix M
Definition: EigenvalueSolver.cxx:1481
Seldon::EigenProblem_Base::GetLowerBoundInterval
double GetLowerBoundInterval() const
returns lower bound of the interval where eigenvalues are searched
Definition: EigenvalueSolver.cxx:358
Seldon::EigenProblem_Base::GetTypeSorting
int GetTypeSorting() const
returns how eigenvalues are sorted (real, imaginary part or modulus)
Definition: EigenvalueSolver.cxx:261
Seldon::DenseEigenProblem::ComputeSolution
void ComputeSolution(const Vector< T0 > &X, Vector< T0 > &Y)
solution of (a M + b K) Y = X
Definition: EigenvalueSolver.cxx:1410
Seldon::EigenProblem_Base::SetNbMaximumIterations
void SetNbMaximumIterations(int n)
sets the maximal number of iterations allowed for the iterative algorithm
Definition: EigenvalueSolver.cxx:438
Seldon::EigenProblem_Base::SetPrintLevel
void SetPrintLevel(int lvl)
sets the level of verbosity
Definition: EigenvalueSolver.cxx:506
Seldon::IsComplexMatrix
bool IsComplexMatrix(const Matrix< T, Prop, Storage, Allocator > &A)
returns true if the matrix is complex
Definition: Functions_BaseInline.cxx:794
Seldon::Vector
Definition: SeldonHeader.hxx:207
Seldon::EigenProblem_Base::ComputeAndFactorizeStiffnessMatrix
void ComputeAndFactorizeStiffnessMatrix(const T &a, const T &b)
computation of matrix a M + b K and factorisation of this matrix
Definition: EigenvalueSolver.cxx:758
Seldon::Vector2
Vector of vectors.
Definition: Vector2.hxx:53
Seldon::IsSymmetricMatrix
bool IsSymmetricMatrix(const Matrix< T, Prop, Storage, Allocator > &A)
returns true if the matrix is symmetric
Definition: Functions_BaseInline.cxx:778
Seldon::SparseEigenProblem::Clear
void Clear()
clears memory used by the object
Definition: EigenvalueSolver.cxx:1913
Seldon::EigenProblem_Base::GetComputationalMode
int GetComputationalMode() const
returns the spectral transformation used for evaluation of eigenvalues
Definition: EigenvalueSolver.cxx:133
Seldon::SortEigenvalues
void SortEigenvalues(Vector< T > &lambda_r, Vector< T > &lambda_i, Matrix< T, General, Storage1, Alloc1 > &eigen_old, Matrix< T, General, Storage2, Alloc2 > &eigen_new, int type_spectrum, int type_sort, const T &shift_r, const T &shift_i)
sorting eigenvalues
Definition: EigenvalueSolver.cxx:1040
Seldon::EigenProblem_Base::SetNbArnoldiVectors
void SetNbArnoldiVectors(int n)
sets the number of Arnoldi vectors to use
Definition: EigenvalueSolver.cxx:473
Seldon::DenseEigenProblem::Clear
void Clear()
clearing variables used for eigenvalue resolution
Definition: EigenvalueSolver.cxx:1443
Seldon::EigenProblem_Base::MltStiffness
void MltStiffness(const Vector< T > &X, Vector< T > &Y)
matrix vector product with stifness matrix Y = K X
Definition: EigenvalueSolver.cxx:709
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::EigenProblem_Base::ComputeStiffnessMatrix
void ComputeStiffnessMatrix()
computation of stiffness matrix K
Definition: EigenvalueSolver.cxx:691
Seldon::EigenProblem_Base::GetN
int GetN() const
returns number of columns
Definition: EigenvalueSolver.cxx:490
Seldon::EigenProblem_Base::ComputeDiagonalMass
void ComputeDiagonalMass()
computation of diagonal of mass matrix
Definition: EigenvalueSolver.cxx:634
Seldon::EigenProblem_Base::ComputeMassMatrix
void ComputeMassMatrix()
computation of mass matrix M
Definition: EigenvalueSolver.cxx:663
Seldon::FindEigenvaluesAnasazi
void FindEigenvaluesAnasazi(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: Anasazi.cxx:244
Seldon::SparseEigenProblem::SparseEigenProblem
SparseEigenProblem()
default constructor
Definition: EigenvalueSolver.cxx:1461
Seldon::EigenProblem_Base::SetEigensolverType
void SetEigensolverType(int type)
sets the solver used in Anasazi
Definition: EigenvalueSolver.cxx:213
Seldon::ArrayRowSymSparse
Definition: Storage.hxx:132
Seldon::SparseEigenProblem::MltCholeskyMass
void MltCholeskyMass(const TransStatus &transA, Vector< T0 > &X)
computes L X or L^T x if M = L L^T
Definition: EigenvalueSolver.cxx:1526
Seldon::EigenProblem_Base::SetNbAskedEigenvalues
void SetNbAskedEigenvalues(int n)
sets the number of eigenvalues to compute
Definition: EigenvalueSolver.cxx:237
Seldon::SparseEigenProblem::ComputeSolution
void ComputeSolution(const Vector< T0 > &X, Vector< T0 > &Y)
solves (a M + b K) Y = X with stored factorization
Definition: EigenvalueSolver.cxx:1845
Seldon::EigenProblem_Base::GetNbAskedEigenvalues
int GetNbAskedEigenvalues() const
returns the number of eigenvalues asked by the user
Definition: EigenvalueSolver.cxx:149
Seldon::EigenProblem_Base::SetStoppingCriterion
void SetStoppingCriterion(double eps)
modifies the stopping critertion
Definition: EigenvalueSolver.cxx:421
Seldon::TypeEigenvalueSolver::GetDefaultSolver
static int GetDefaultSolver()
returns the default eigenvalue solver (linear eigenproblem)
Definition: EigenvalueSolver.cxx:1936
Seldon::EigenProblem_Base::MltInvSqrtDiagonalMass
void MltInvSqrtDiagonalMass(Vector< T0 > &X)
multiplication of X by D^-1/2
Definition: EigenvalueSolver.cxx:614
Seldon::EigenProblem_Base::ComputeSolution
void ComputeSolution(const Vector< T0 > &X, Vector< T0 > &Y)
solving the linear system (a M + b K) Y = X
Definition: EigenvalueSolver.cxx:781
Seldon::EigenProblem_Base::IncrementProdMatVect
void IncrementProdMatVect()
increment of the number of matrix vector products
Definition: EigenvalueSolver.cxx:514
Seldon::EigenProblem_Base::SetNbAdditionalEigenvalues
void SetNbAdditionalEigenvalues(int n)
sets the number of additional eigenvalues
Definition: EigenvalueSolver.cxx:245
Seldon::EigenProblem_Base::SolveCholeskyMass
void SolveCholeskyMass(const TransStatus &transA, Vector< T > &X)
computation of L^-1 X or L^-T x if M = L L^T
Definition: EigenvalueSolver.cxx:819
Seldon::EigenProblem_Base::InitMatrix
void InitMatrix(MatStiff &)
initialization of a standard eigenvalue problem
Definition: EigenvalueSolver.cxx:93
Seldon::EigenProblem_Base::Clear
void Clear()
memory release
Definition: EigenvalueSolver.cxx:827
Seldon::EigenProblem_Base::FactorizeDiagonalMass
void FactorizeDiagonalMass()
computation of D^1/2 from D
Definition: EigenvalueSolver.cxx:604
Seldon::EigenProblem_Base::GetStoppingCriterion
double GetStoppingCriterion() const
returns the stopping criterion
Definition: EigenvalueSolver.cxx:430
Seldon::SparseEigenProblem::ComputeAndFactorizeStiffnessMatrix
void ComputeAndFactorizeStiffnessMatrix(const T &a, const T &b)
computes and factorizes a M + b K where M is the mass matrix and K the stiffness matrix
Definition: EigenvalueSolver.cxx:1635
Seldon::General
Definition: Properties.hxx:26
Seldon::EigenProblem_Base::MltMass
void MltMass(const Vector< T > &X, Vector< T > &Y)
matrix vector product with mass matrix Y = M X
Definition: EigenvalueSolver.cxx:672
Seldon::EigenProblem_Base::SetCholeskyFactoForMass
void SetCholeskyFactoForMass(bool chol=true)
indicates the use of Cholesky factorisation in order to solve a standard eigenvalue problem instead o...
Definition: EigenvalueSolver.cxx:387
Seldon::GetLU
void GetLU(Matrix< T0, Prop0, Storage0, Allocator0 > &A)
Returns the LU factorization of a matrix.
Definition: Functions_Matrix.cxx:2073
Seldon::EigenProblem_Base::DiagonalMass
bool DiagonalMass() const
returns true if the mass matrix is diagonal
Definition: EigenvalueSolver.cxx:412
Seldon::EigenProblem_Base::GetUpperBoundInterval
double GetUpperBoundInterval() const
returns upper bound of the interval where eigenvalues are searched
Definition: EigenvalueSolver.cxx:367
Seldon::EigenProblem_Base::SetIntervalSpectrum
void SetIntervalSpectrum(double, double)
sets the interval where eigenvalues are searched
Definition: EigenvalueSolver.cxx:376
Seldon::EigenProblem_Base::GetEigensolverType
int GetEigensolverType() const
returns the solver used in Anasazi
Definition: EigenvalueSolver.cxx:205
Seldon::EigenProblem_Base::GetImagShiftValue
T GetImagShiftValue() const
returns the imaginary part of shift value used
Definition: EigenvalueSolver.cxx:288
Seldon::DenseEigenProblem::DenseEigenProblem
DenseEigenProblem()
default constructor
Definition: EigenvalueSolver.cxx:1215
Seldon::EigenProblem_Base
Base class to solve an eigenvalue problem.
Definition: EigenvalueSolver.hxx:18
Seldon::EigenProblem_Base::GetM
int GetM() const
returns number of rows
Definition: EigenvalueSolver.cxx:482
Seldon::DenseEigenProblem::FactorizeCholeskyMass
void FactorizeCholeskyMass()
Cholesky factorisation of mass matrix.
Definition: EigenvalueSolver.cxx:1225
Seldon::EigenProblem_Base::SetNbBlocks
void SetNbBlocks(int)
returns the number of blocks used in blocked solvers
Definition: EigenvalueSolver.cxx:173
Seldon::EigenProblem_Base::GetNbAdditionalEigenvalues
int GetNbAdditionalEigenvalues() const
returns the additional number of eigenvalues
Definition: EigenvalueSolver.cxx:157
Seldon::EigenProblem_Base::SetTypeSpectrum
void SetTypeSpectrum(int type, const T &val, int type_sort=SORTED_MODULUS)
sets which eigenvalues are searched
Definition: EigenvalueSolver.cxx:317
Seldon::EigenProblem_Base::UseCholeskyFactoForMass
bool UseCholeskyFactoForMass() const
returns true if Cholesky factorisation has to be used for mass matrix
Definition: EigenvalueSolver.cxx:396
Seldon::EigenProblem_Base::SetDiagonalMass
void SetDiagonalMass(bool diag=true)
indicates that the mass matrix is diagonal
Definition: EigenvalueSolver.cxx:404
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::SparseEigenProblem::imag_solution
bool imag_solution
if true, we take imaginary part of (K - sigma M)^-1
Definition: EigenvalueSolver.hxx:418
Seldon::Symmetric
Definition: Properties.hxx:30
Seldon::EigenProblem_Base::GetPrintLevel
int GetPrintLevel() const
returns level of verbosity
Definition: EigenvalueSolver.cxx:498
Seldon::SparseEigenProblem::SolveCholeskyMass
void SolveCholeskyMass(const TransStatus &transA, Vector< T0 > &X)
computes L^-1 X or L^-T x if M = L L^T
Definition: EigenvalueSolver.cxx:1536
Seldon::EigenProblem_Base::GetShiftValue
T GetShiftValue() const
returns the shift value used
Definition: EigenvalueSolver.cxx:274
Seldon::DenseEigenProblem::SolveCholeskyMass
void SolveCholeskyMass(const TransStatus &transA, Vector< T0 > &X)
computation of L^-1 X or L^-T X
Definition: EigenvalueSolver.cxx:1258
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::EigenProblem_Base::MltCholeskyMass
void MltCholeskyMass(const TransStatus &transA, Vector< T > &X)
computation of L X or L^T x if M = L L^T
Definition: EigenvalueSolver.cxx:809
Seldon::EigenProblem_Base::GetNbMatrixVectorProducts
int GetNbMatrixVectorProducts() const
returns the number of matrix-vector products performed since last call to Init
Definition: EigenvalueSolver.cxx:457
Seldon::SparseEigenProblem::mat_lu
SparseDirectSolver< T > mat_lu
LU factorisation of sparse matrix.
Definition: EigenvalueSolver.hxx:406
Seldon::EigenProblem_Base::GetNbMaximumRestarts
int GetNbMaximumRestarts() const
returns the restart parameter used in blocked solvers
Definition: EigenvalueSolver.cxx:181
Seldon::EigenProblem_Base::ComputeMassForCholesky
void ComputeMassForCholesky()
computation of mass matrix
Definition: EigenvalueSolver.cxx:654
Seldon::DenseEigenProblem::ComputeAndFactorizeStiffnessMatrix
void ComputeAndFactorizeStiffnessMatrix(const T &a, const T &b)
computation and factorisation of a M + b K
Definition: EigenvalueSolver.cxx:1310
Seldon::EigenProblem_Base::GetNbBlocks
int GetNbBlocks() const
returns the number of blocks used in blocked solvers
Definition: EigenvalueSolver.cxx:165
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::EigenProblem_Base::GetOrthoManager
int GetOrthoManager() const
returns orthogonalization manager set in Anasazi
Definition: EigenvalueSolver.cxx:197
Seldon::EigenProblem_Base::SetComputationalMode
void SetComputationalMode(int mode)
sets the spectral transformation used for evaluation of eigenvalues
Definition: EigenvalueSolver.cxx:141
Seldon::DenseEigenProblem::ComputeAndFactorizeComplexMatrix
void ComputeAndFactorizeComplexMatrix(const complex< T0 > &a, const complex< T0 > &b, bool real_p=true)
computation and factorisation of a M + b K
Definition: EigenvalueSolver.cxx:1397
Seldon::EigenProblem_Base::SetShiftValue
void SetShiftValue(const T &)
Sets the real part of shift value.
Definition: EigenvalueSolver.cxx:296
Seldon::SparseEigenProblem::SelectCholeskySolver
void SelectCholeskySolver(int type)
sets Cholesky solver to use
Definition: EigenvalueSolver.cxx:1472
Seldon::EigenProblem_Base::SetImagShiftValue
void SetImagShiftValue(const T &)
Sets the imaginary part of shift value.
Definition: EigenvalueSolver.cxx:304
Seldon::EigenProblem_Base::GetNbArnoldiVectors
int GetNbArnoldiVectors() const
returns the number of Arnoldi vectors to use
Definition: EigenvalueSolver.cxx:465
Seldon::EigenProblem_Base::GetNbMaximumIterations
int GetNbMaximumIterations() const
returns the maximal number of iterations allowed for the iterative algorithm
Definition: EigenvalueSolver.cxx:447
Seldon::EigenProblem_Base::MltSqrtDiagonalMass
void MltSqrtDiagonalMass(Vector< T0 > &X)
multiplication of X by D^1/2
Definition: EigenvalueSolver.cxx:624
Seldon::EigenProblem_Base::FactorizeCholeskyMass
void FactorizeCholeskyMass()
computation of Cholesky factorisation of M from matrix M
Definition: EigenvalueSolver.cxx:799