PolynomialEigenvalueSolver.cxx
1 #ifndef SELDON_FILE_POLYNOMIAL_EIGENVALUE_SOLVER_CXX
2 
3 #include "PolynomialEigenvalueSolver.hxx"
4 
5 namespace Seldon
6 {
7  SlepcParamPep::SlepcParamPep()
8  {
9  type_solver = TOAR;
10  }
11 
12  int SlepcParamPep::GetEigensolverType() const
13  {
14  return type_solver;
15  }
16 
17  void SlepcParamPep::SetEigensolverType(int type)
18  {
19  type_solver = type;
20  }
21 
22 
23  /*******************************
24  * PolynomialEigenProblem_Base *
25  *******************************/
26 
28  template<class T>
30  {
31  use_spectral_transfo = false;
32  pol_degree = 0;
33  diagonal_mass = false;
34  }
35 
36 
38  template<class T>
40  {
41  return use_spectral_transfo;
42  }
43 
44 
46  template<class T>
48  {
49  use_spectral_transfo = t;
50  }
51 
52 
54  template<class T>
56  {
57  return slepc_param;
58  }
59 
60 
62  template<class T>
64  {
65  return feast_param;
66 
67  }
68 
70  template<class T>
72  {
73  return pol_degree;
74  }
75 
76 
78  template<class T>
80  {
81  diagonal_mass = diag;
82  }
83 
84 
86  template<class T>
88  {
89  return diagonal_mass;
90  }
91 
92 
94  template<class T>
96  {
97  cout << "ComputeOperator not overloaded" << endl;
98  abort();
99  }
100 
101 
103  template<class T>
105  {
106  cout << "MltOperator not overloaded" << endl;
107  abort();
108  }
109 
110 
112  template<class T>
114  {
115  cout << "FactorizeMass not overloaded" << endl;
116  abort();
117  }
118 
119 
121  template<class T>
123  ::SolveMass(const SeldonTranspose& trans, const Vector<T>& x, Vector<T>& y)
124  {
125  if (DiagonalMass())
126  for (int i = 0; i < x.GetM(); i++)
127  y(i) = x(i)*this->invDiag(i);
128  else
129  {
130  cout << "SolveMass not overloaded" << endl;
131  abort();
132  }
133  }
134 
135 
136  template<class T>
138  {
139  cout << "FactorizeOperator not overloaded" << endl;
140  abort();
141  }
142 
143 
144  template<class T>
145  void PolynomialEigenProblem_Base<T>
146  ::SolveOperator(const SeldonTranspose&, const Vector<T>& X, Vector<T>& Y)
147  {
148  cout << "SolveOperator not overloaded" << endl;
149  abort();
150  }
151 
152 
153  /**************************
154  * PolynomialEigenProblem *
155  **************************/
156 
157 
159  template<class T>
161  {
162  if (n == -1)
163  this->Init(op(0)->GetM());
164  else
165  this->Init(n);
166 
167  list_op = op;
168  this->pol_degree = list_op.GetM()-1;
169  }
170 
172  template<class T>
174  {
175  // default implementation : we store the coefficients, no matrix stored
176  if (num >= list_coef.GetM())
177  list_coef.Resize(num+1);
178 
179  list_coef(num) = coef;
180  }
181 
183  template<class T>
185  {
186  if (list_op.GetM() <= 0)
187  return;
188 
189  if (list_coef.GetM() == 0)
190  {
191  // no coeffients, the operator num is stored in list_op(num)
192  list_op(num)->MltVector(trans, X, Y);
193  return;
194  }
195 
196  // coefficients, the operator num is a linear combination of stored operators
197  T zero; SetComplexZero(zero);
198  T one; SetComplexOne(one);
199  if (list_coef(num)(0) != zero)
200  {
201  list_op(0)->MltVector(trans, X, Y);
202  Mlt(list_coef(num)(0), Y);
203  }
204  else
205  Y.Zero();
206 
207  for (int i = 1; i < list_op.GetM(); i++)
208  if (list_coef(num)(i) != zero)
209  list_op(i)->MltAddVector(list_coef(num)(i), trans, X, one, Y);
210  }
211 
212 
214  template<class T>
216  {
217  for (int i = 0; i < this->list_op.GetM(); i++)
218  if (!this->list_op(i)->IsSymmetric())
219  return false;
220 
221  return true;
222  }
223 
224 
226  template<class T>
228  {
229  // polynomial eigenvalue problem => hermitian not possible
230  return false;
231  }
232 
233 
234  /*******************************
235  * PolynomialDenseEigenProblem *
236  *******************************/
237 
238  template<class T, class Prop, class Storage>
240  {
241  Vector<VirtualMatrix<T>* > op0(op.GetM());
242  for (int i = 0; i < op0.GetM(); i++)
243  op0(i) = op(i);
244 
246  list_mat = op;
247  }
248 
249  template<class T, class Prop, class Storage>
251  {
252  if (this->DiagonalMass())
253  {
254  T one; SetComplexOne(one);
255  this->invDiag.Reallocate(this->n_);
256  Matrix<T, Prop, Storage>& M = *list_mat(this->pol_degree);
257  for (int i = 0; i < this->n_; i++)
258  this->invDiag(i) = one / M(i, i);
259  }
260  else
261  {
262  mat_lu = *list_mat(this->pol_degree);
263  GetLU(mat_lu, pivot);
264  }
265  }
266 
267  template<class T, class Prop, class Storage>
269  ::SolveMass(const SeldonTranspose& trans, const Vector<T>& x, Vector<T>& y)
270  {
271  if (this->DiagonalMass())
272  for (int i = 0; i < x.GetM(); i++)
273  y(i) = x(i)*this->invDiag(i);
274  else
275  {
276  if (!trans.NoTrans())
277  {
278  cout << "Not implemented" << endl;
279  abort();
280  }
281 
282  y = x;
283  SolveLU(mat_lu, pivot, y);
284  }
285  }
286 
287  template<class T, class Prop, class Storage>
289  {
290  T zero; SetComplexZero(zero);
291  if (coef(0) == zero)
292  {
293  mat_lu.Reallocate(this->n_, this->n_);
294  mat_lu.Zero();
295  }
296  else
297  {
298  mat_lu = *list_mat(0);
299  Mlt(coef(0), mat_lu);
300  }
301 
302  for (int k = 1; k < list_mat.GetM(); k++)
303  if (coef(k) != zero)
304  Add(coef(k), *list_mat(k), mat_lu);
305 
306  GetLU(mat_lu, pivot);
307  }
308 
309  template<class T, class Prop, class Storage>
310  void PolynomialDenseEigenProblem<T, Prop, Storage>
311  ::SolveOperator(const SeldonTranspose& trans, const Vector<T>& X, Vector<T>& Y)
312  {
313  if (!trans.NoTrans())
314  {
315  cout << "Not implemented" << endl;
316  abort();
317  }
318 
319  Y = X;
320  SolveLU(mat_lu, pivot, Y);
321  }
322 
323 
324  /*********************************
325  * PolynomialSparseEigenProblem *
326  *********************************/
327 
328  template<class T, class MatStiff, class MatMass>
329  PolynomialSparseEigenProblem<T, MatStiff, MatMass>::PolynomialSparseEigenProblem()
330  {
331  Mh = NULL;
332  ProcSharingRows = NULL;
333  SharingRowNumbers = NULL;
334  nodl_scalar_ = nb_unknowns_scal_ = 0;
335  nloc = 0;
336  }
337 
338  template<class T, class MatStiff, class MatMass>
339  int PolynomialSparseEigenProblem<T, MatStiff, MatMass>::RetrieveLocalNumbers(MatStiff& K)
340  {
341  nloc = K.GetM();
342 
343 #ifdef SELDON_WITH_MPI
344  try
345  {
346  DistributedMatrix_Base<typename MatStiff::entry_type>& A
347  = dynamic_cast<DistributedMatrix_Base<typename MatStiff::entry_type>& >(K);
348 
349  MPI_Comm comm = A.GetCommunicator();
350  this->SetCommunicator(comm);
351  int nb_proc;
352  MPI_Comm_size(comm, &nb_proc);
353 
354  // only one processor => sequential case
355  if (nb_proc <= 1)
356  return -1;
357 
358  // parallel case
359  int m = A.GetLocalM();
360  const IVect& OverlapRow = A.GetOverlapRowNumber();
361  int noverlap = OverlapRow.GetM();
362  int n = m - noverlap;
363  local_col_numbers.Reallocate(n);
364  Vector<bool> OverlappedRow(m); OverlappedRow.Fill(false);
365  for (int i = 0; i < noverlap; i++)
366  OverlappedRow(OverlapRow(i)) = true;
367 
368  int ncol = 0;
369  for (int i = 0; i < m; i++)
370  if (!OverlappedRow(i))
371  local_col_numbers(ncol++) = i;
372 
373  ProcSharingRows = &A.GetProcessorSharingRows();
374  SharingRowNumbers = &A.GetSharingRowNumbers();
375  nodl_scalar_ = A.GetNodlScalar();
376  nb_unknowns_scal_ = A.GetNbScalarUnknowns();
377 
378  return n;
379  }
380  catch (const std::bad_cast&)
381  {
382  // a sequential matrix has been provided
383  this->SetCommunicator(MPI_COMM_SELF);
384 
385  local_col_numbers.Clear();
386  }
387 #endif
388 
389  return -1;
390  }
391 
392  template<class T, class MatStiff, class MatMass>
393  void PolynomialSparseEigenProblem<T, MatStiff, MatMass>::InitMatrix(Vector<MatStiff*>& K, MatMass& M)
394  {
395  int n = RetrieveLocalNumbers(*K(0));
396  distributed = false;
397  if (n >= 0)
398  distributed = true;
399 
400  Vector<VirtualMatrix<T>* > list_op(K.GetM() + 1);
401  for (int i = 0; i < K.GetM(); i++)
402  list_op(i) = K(i);
403 
404  list_op(K.GetM()) = &M;
406 
407  Kh.Reallocate(K.GetM());
408  for (int i = 0; i < K.GetM(); i++)
409  Kh(i) = K(i);
410 
411  Mh = &M;
412  }
413 
414  template<class T, class MatStiff, class MatMass>
416  {
417  if (this->DiagonalMass())
418  {
419  T one; SetComplexOne(one);
420  this->invDiag.Reallocate(nloc);
421  for (int i = 0; i < nloc; i++)
422  this->invDiag(i) = (*Mh)(i, i);
423 
424  // D is assembled for distributed matrices
425  if (distributed)
426  {
427 #ifdef SELDON_WITH_MPI
428  Vector<T> M(this->invDiag);
429  AssembleVector(M, MPI_SUM, *ProcSharingRows, *SharingRowNumbers,
430  this->comm, nodl_scalar_, nb_unknowns_scal_, 15);
431 
432  this->invDiag.Reallocate(local_col_numbers.GetM());
433  for (int i = 0; i < local_col_numbers.GetM(); i++)
434  this->invDiag(i) = one / M(local_col_numbers(i));
435 #endif
436  }
437  else
438  for (int i = 0; i < nloc; i++)
439  this->invDiag(i) = one / this->invDiag(i);
440  }
441  else
442  {
443  mat_lu.Factorize(*Mh);
444  }
445  }
446 
447  template<class T, class MatStiff, class MatMass>
449  ::SolveMass(const SeldonTranspose& trans, const Vector<T>& x, Vector<T>& y)
450  {
451  if (this->DiagonalMass())
452  for (int i = 0; i < x.GetM(); i++)
453  y(i) = x(i)*this->invDiag(i);
454  else
455  this->SolveOperator(trans, x, y);
456 
457  }
458 
459  template<class T, class MatStiff, class MatMass>
461  {
462  MatStiff A;
463  T zero; SetComplexZero(zero);
464  A = *Kh(0);
465  Mlt(coef(0), A);
466  for (int k = 1; k < Kh.GetM(); k++)
467  if (coef(k) != zero)
468  Add(coef(k), *Kh(k), A);
469 
470  Add(coef(Kh.GetM()), *Mh, A);
471 
472  mat_lu.Factorize(A);
473  }
474 
475  template<class T, class MatStiff, class MatMass>
476  void PolynomialSparseEigenProblem<T, MatStiff, MatMass>
477  ::SolveOperator(const SeldonTranspose& trans, const Vector<T>& x, Vector<T>& y)
478  {
479  Vector<T> X(nloc);
480  if (distributed)
481  {
482  X.Zero();
483  for (int i = 0; i < this->n_; i++)
484  X(local_col_numbers(i)) = x(i);
485  }
486  else
487  X = x;
488 
489  mat_lu.Solve(trans, X, false);
490  if (distributed)
491  {
492  for (int i = 0; i < this->n_; i++)
493  y(i) = X(local_col_numbers(i));
494  }
495  else
496  y = X;
497  }
498 
500  template<class T, class MatStiff, class MatMass>
502  {
503  if (Kh.GetM() <= 0)
504  return;
505 
506  Vector<T> X, Y;
507  if (distributed)
508  {
509 #ifdef SELDON_WITH_MPI
510  X.Reallocate(nloc); Y.Reallocate(nloc);
511  X.Zero();
512  for (int i = 0; i < this->n_; i++)
513  X(local_col_numbers(i)) = x(i);
514 
515  AssembleVector(X, MPI_SUM, *ProcSharingRows, *SharingRowNumbers,
516  this->comm, nodl_scalar_, nb_unknowns_scal_, 17);
517 
518  if (this->list_coef.GetM() == 0)
519  this->list_op(num)->MltVector(trans, X, Y);
520  else
521  {
522  // coefficients, the operator num is a linear combination of stored operators
523  T zero; SetComplexZero(zero);
524  T one; SetComplexOne(one);
525  if (this->list_coef(num)(0) != zero)
526  {
527  this->list_op(0)->MltVector(trans, X, Y);
528  Mlt(this->list_coef(num)(0), Y);
529  }
530  else
531  Y.Zero();
532 
533  for (int i = 1; i < this->list_op.GetM(); i++)
534  if (this->list_coef(num)(i) != zero)
535  this->list_op(i)->MltAddVector(this->list_coef(num)(i), trans, X, one, Y);
536  }
537 
538  for (int i = 0; i < this->n_; i++)
539  y(i) = Y(local_col_numbers(i));
540 #endif
541  }
542  else
543  PolynomialEigenProblem<T>::MltOperator(num, trans, x, y);
544  }
545 
546 
548  template<class T, class MatStiff, class MatMass>
550  {
551  if (distributed)
552  {
553 #ifdef SELDON_WITH_MPI
554  this->AssembleEigenvectors(eigen_vec, local_col_numbers, ProcSharingRows,
555  SharingRowNumbers, nloc, nodl_scalar_, nb_unknowns_scal_);
556 #endif
557  }
558  }
559 
560 
561  template<class T, class Prop, class Storage>
562  void GetEigenvaluesEigenvectors(PolynomialEigenProblem_Base<T>& var_eig,
563  Vector<T>& lambda, Vector<T>& lambda_imag,
564  Matrix<T, Prop, Storage>& eigen_vec,
565  int type_solver)
566  {
567  if (type_solver == TypeEigenvalueSolver::DEFAULT)
569 
570  if (type_solver == TypeEigenvalueSolver::FEAST)
571  {
572 #ifdef SELDON_WITH_FEAST
573  T zero; SetComplexZero(zero);
575  FindEigenvaluesFeast(var_eig, lambda, lambda_imag, eigen_old);
576 
577  // eigenvalues are sorted by ascending order
578  SortEigenvalues(lambda, lambda_imag, eigen_old,
579  eigen_vec, var_eig.LARGE_EIGENVALUES,
580  var_eig.GetTypeSorting(), zero, zero);
581 #else
582  cout << "Recompile with MKL or Feast" << endl;
583  abort();
584 #endif
585  }
586  else if (type_solver == TypeEigenvalueSolver::SLEPC)
587  {
588 #ifdef SELDON_WITH_SLEPC
589  T zero; SetComplexZero(zero);
590  Matrix<T, General, ColMajor> eigen_old;
591  FindEigenvaluesSlepc(var_eig, lambda, lambda_imag, eigen_old);
592 
593  // eigenvalues are sorted by ascending order
594  SortEigenvalues(lambda, lambda_imag, eigen_old,
595  eigen_vec, var_eig.LARGE_EIGENVALUES,
596  var_eig.GetTypeSorting(), zero, zero);
597 #else
598  cout << "Recompile with Slepc" << endl;
599  abort();
600 #endif
601  }
602  else
603  {
604  cout << "Recompile with eigenvalue solver" << endl;
605  abort();
606  }
607 
608  }
609 
610 }
611 
612 #define SELDON_FILE_POLYNOMIAL_EIGENVALUE_SOLVER_CXX
613 #endif
Seldon::SeldonTranspose
Definition: MatrixFlag.hxx:32
Seldon::PolynomialDenseEigenProblem::FactorizeMass
void FactorizeMass()
to overload
Definition: PolynomialEigenvalueSolver.cxx:250
Seldon::PolynomialSparseEigenProblem
implementation of sparse polynomial eigenvalue solver
Definition: PolynomialEigenvalueSolver.hxx:119
Seldon::PolynomialEigenProblem::MltOperator
void MltOperator(int num, const SeldonTranspose &, const Vector< T > &X, Vector< T > &Y)
Computes Y = A X where A is the operator num.
Definition: PolynomialEigenvalueSolver.cxx:184
Seldon::PolynomialSparseEigenProblem::SolveMass
void SolveMass(const SeldonTranspose &, const Vector< T > &x, Vector< T > &y)
to overload for non-diagonal mass
Definition: PolynomialEigenvalueSolver.cxx:449
Seldon::PolynomialEigenProblem_Base::GetSlepcParameters
SlepcParamPep & GetSlepcParameters()
returns object storing slepc parameters
Definition: PolynomialEigenvalueSolver.cxx:55
Seldon::PolynomialEigenProblem_Base::SolveMass
virtual void SolveMass(const SeldonTranspose &, const Vector< T > &x, Vector< T > &y)
to overload for non-diagonal mass
Definition: PolynomialEigenvalueSolver.cxx:123
Seldon::Vector< T >
Seldon::PolynomialEigenProblem_Base::FactorizeMass
virtual void FactorizeMass()
to overload
Definition: PolynomialEigenvalueSolver.cxx:113
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::PolynomialEigenProblem::IsHermitianProblem
bool IsHermitianProblem() const
returns true if the problem is hermitian
Definition: PolynomialEigenvalueSolver.cxx:227
Seldon::Matrix< T, Prop, Storage >
Seldon::PolynomialSparseEigenProblem::MltOperator
void MltOperator(int num, const SeldonTranspose &, const Vector< T > &X, Vector< T > &Y)
Computes Y = A X where A is the operator num.
Definition: PolynomialEigenvalueSolver.cxx:501
Seldon::PolynomialEigenProblem_Base::GetFeastParameters
FeastParam & GetFeastParameters()
returns object storing Feast parameters
Definition: PolynomialEigenvalueSolver.cxx:63
Seldon::PolynomialEigenProblem_Base::DiagonalMass
bool DiagonalMass()
returns true if the mass is diagonal
Definition: PolynomialEigenvalueSolver.cxx:87
Seldon::PolynomialEigenProblem::InitMatrix
void InitMatrix(const Vector< VirtualMatrix< T > * > &op, int n=-1)
inits the operators of the polynomial
Definition: PolynomialEigenvalueSolver.cxx:160
Seldon::PolynomialEigenProblem::ComputeOperator
void ComputeOperator(int num, const Vector< T > &coef)
computes the operator with coefficients stored in coef
Definition: PolynomialEigenvalueSolver.cxx:173
Seldon::PolynomialEigenProblem::IsSymmetricProblem
bool IsSymmetricProblem() const
returns true if the problem is symmetric
Definition: PolynomialEigenvalueSolver.cxx:215
Seldon::SlepcParamPep::type_solver
int type_solver
which solver ?
Definition: PolynomialEigenvalueSolver.hxx:10
Seldon::PolynomialSparseEigenProblem::DistributeEigenvectors
void DistributeEigenvectors(Matrix< T, General, ColMajor > &eigen_vec)
changes final eigenvectors if needed
Definition: PolynomialEigenvalueSolver.cxx:549
Seldon::GetLU
void GetLU(Matrix< T0, Prop0, Storage0, Allocator0 > &A)
Returns the LU factorization of a matrix.
Definition: Functions_Matrix.cxx:2073
Seldon::PolynomialDenseEigenProblem::SolveMass
void SolveMass(const SeldonTranspose &, const Vector< T > &x, Vector< T > &y)
to overload for non-diagonal mass
Definition: PolynomialEigenvalueSolver.cxx:269
Seldon::TypeEigenvalueSolver::GetDefaultPolynomialSolver
static int GetDefaultPolynomialSolver()
returns the default eigenvalue solver (polynomial eigenproblem)
Definition: VirtualEigenvalueSolver.cxx:3649
Seldon::PolynomialDenseEigenProblem
implementation of polynomial eigenvalue solver for dense problem
Definition: PolynomialEigenvalueSolver.hxx:93
Seldon::PolynomialSparseEigenProblem::FactorizeMass
void FactorizeMass()
to overload
Definition: PolynomialEigenvalueSolver.cxx:415
Seldon::PolynomialEigenProblem_Base
Base class for polynomial eigenvalue solver.
Definition: PolynomialEigenvalueSolver.hxx:25
Seldon::PolynomialEigenProblem_Base::ComputeOperator
virtual void ComputeOperator(int num, const Vector< T > &coef)
to overload
Definition: PolynomialEigenvalueSolver.cxx:95
Seldon::PolynomialEigenProblem_Base::SetDiagonalMass
void SetDiagonalMass(bool diag=true)
sets a diagonal mass
Definition: PolynomialEigenvalueSolver.cxx:79
Seldon::PolynomialEigenProblem_Base::SetSpectralTransformation
void SetSpectralTransformation(bool t=true)
enables a spectral transformation
Definition: PolynomialEigenvalueSolver.cxx:47
Seldon::PolynomialEigenProblem_Base::GetPolynomialDegree
int GetPolynomialDegree() const
returns the polynomial degree
Definition: PolynomialEigenvalueSolver.cxx:71
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::FeastParam
parameters for Feast package
Definition: VirtualEigenvalueSolver.hxx:165
Seldon::PolynomialEigenProblem_Base::UseSpectralTransformation
bool UseSpectralTransformation() const
returns true if a spectral transformation has to be used
Definition: PolynomialEigenvalueSolver.cxx:39
Seldon::VirtualMatrix
Abstract base class for all matrices.
Definition: Matrix_Base.hxx:42
Seldon::PolynomialEigenProblem_Base::MltOperator
virtual void MltOperator(int num, const SeldonTranspose &, const Vector< T > &X, Vector< T > &Y)
to overload
Definition: PolynomialEigenvalueSolver.cxx:104
Seldon::PolynomialEigenProblem_Base::PolynomialEigenProblem_Base
PolynomialEigenProblem_Base()
default constructor
Definition: PolynomialEigenvalueSolver.cxx:29
Seldon::SlepcParamPep
Parameters for Slepc package.
Definition: PolynomialEigenvalueSolver.hxx:6
Seldon::GeneralEigenProblem_Base::GetTypeSorting
int GetTypeSorting() const
returns how eigenvalues are sorted (real, imaginary part or modulus)
Definition: VirtualEigenvalueSolver.cxx:301