NonLinearEigenvalueSolver.cxx
1 #ifndef SELDON_FILE_NON_LINEAR_EIGENVALUE_SOLVER_CXX
2 
3 #include "NonLinearEigenvalueSolver.hxx"
4 
5 namespace Seldon
6 {
7 #ifdef SELDON_WITH_MPI
8 #ifdef SELDON_WITH_SLEPC
9 
10  SlepcParamNep::SlepcParamNep()
11  {
12  type_solver = NLEIGS;
13  use_command_line_options = false;
14  a_sp = 0.1; b_sp = 10.0; c_sp = 0.1; d_sp = 10.0;
15  full_basis = false;
16  locking_variant = true;
17  restart = 0.5;
18  tol_interpol = -1.0;
19  degree_interpol = -1;
20  use_default_petsc_solver = false;
21  }
22 
23  int SlepcParamNep::GetEigensolverType() const
24  {
25  return type_solver;
26  }
27 
28  void SlepcParamNep::SetEigensolverType(int type)
29  {
30  type_solver = type;
31  }
32 
33  double SlepcParamNep::GetLrMin() const
34  {
35  return a_sp;
36  }
37 
38  double SlepcParamNep::GetLrMax() const
39  {
40  return b_sp;
41  }
42 
43  double SlepcParamNep::GetLiMin() const
44  {
45  return c_sp;
46  }
47 
48  double SlepcParamNep::GetLiMax() const
49  {
50  return d_sp;
51  }
52 
53  void SlepcParamNep::SetIntervalRegion(double a, double b, double c, double d)
54  {
55  a_sp = a; b_sp = b; c_sp = c; d_sp = d;
56  }
57 
58  bool SlepcParamNep::InsideRegion(const complex<double>& z) const
59  {
60  if ((real(z) >= a_sp) && (real(z) <= b_sp)
61  && (imag(z) >= c_sp) && (imag(z) <= d_sp))
62  return true;
63 
64  return false;
65  }
66 
67  void SlepcParamNep::EnableCommandLineOptions(bool yes)
68  {
69  use_command_line_options = yes;
70  }
71 
72  bool SlepcParamNep::UseCommandLineOptions() const
73  {
74  return use_command_line_options;
75  }
76 
77  void SlepcParamNep::SetDefaultPetscSolver(bool yes)
78  {
79  use_default_petsc_solver = yes;
80  }
81 
82  bool SlepcParamNep::UseDefaultPetscSolver() const
83  {
84  return use_default_petsc_solver;
85  }
86 
87  void SlepcParamNep::SetFullBasis(bool yes)
88  {
89  full_basis = yes;
90  }
91 
92  bool SlepcParamNep::FullBasis() const
93  {
94  return full_basis;
95  }
96 
97  void SlepcParamNep::SetLockingVariant(bool yes)
98  {
99  locking_variant = yes;
100  }
101 
102  bool SlepcParamNep::LockingVariant() const
103  {
104  return locking_variant;
105  }
106 
107  void SlepcParamNep::SetInterpolationDegree(int p)
108  {
109  degree_interpol = p;
110  }
111 
112  int SlepcParamNep::GetInterpolationDegree() const
113  {
114  return degree_interpol;
115  }
116 
117  void SlepcParamNep::SetInterpolationTolerance(double eps)
118  {
119  tol_interpol = eps;
120  }
121 
122  double SlepcParamNep::GetInterpolationTolerance() const
123  {
124  return tol_interpol;
125  }
126 
127  void SlepcParamNep::SetRestartNleigs(double r)
128  {
129  restart = r;
130  }
131 
132  double SlepcParamNep::GetRestartNleigs() const
133  {
134  return restart;
135  }
136 
137  void SlepcParamNep::SetRKShifts(const Vector<Petsc_Scalar>& s)
138  {
139  shifts = s;
140  }
141 
142  const Vector<Petsc_Scalar>& SlepcParamNep::GetRKShifts() const
143  {
144  return shifts;
145  }
146 
147 
148  /******************************
149  * NonLinearEigenProblem_Base *
150  ******************************/
151 
152 
154  template<class T>
155  NonLinearEigenProblem_Base<T>::NonLinearEigenProblem_Base()
156  {
157  exact_preconditioning = false;
158  explicit_matrix = false;
159  nb_split_matrix = 0;
160  this->automatic_selection_arnoldi_vectors = false; // we let Slepc decide
161  this->nb_arnoldi_vectors = 0;
162  }
163 
164 
166  template<class T>
167  SlepcParamNep& NonLinearEigenProblem_Base<T>::GetSlepcParameters()
168  {
169  return slepc_param;
170  }
171 
172 
174  template<class T>
175  void NonLinearEigenProblem_Base<T>::SetExactPreconditioning(bool yes)
176  {
177  exact_preconditioning = yes;
178  }
179 
180 
182  template<class T>
183  bool NonLinearEigenProblem_Base<T>::ExactPreconditioning() const
184  {
185  return exact_preconditioning;
186  }
187 
188 
190  template<class T>
191  const Vector<T>& NonLinearEigenProblem_Base<T>::GetSingularities() const
192  {
193  return singular_points;
194  }
195 
196 
198  template<class T>
199  void NonLinearEigenProblem_Base<T>::SetSingularities(const Vector<T>& s)
200  {
201  singular_points = s;
202  }
203 
204 
206  template<class T>
207  void NonLinearEigenProblem_Base<T>::SetExplicitMatrix(bool yes)
208  {
209  explicit_matrix = yes;
210  }
211 
212 
214  template<class T>
215  bool NonLinearEigenProblem_Base<T>::ExplicitMatrix() const
216  {
217  return explicit_matrix;
218  }
219 
220 
222  template<class T>
223  void NonLinearEigenProblem_Base<T>::SetSplitMatrices(int n)
224  {
225  nb_split_matrix = n;
226  numer_pol_split.Reallocate(n);
227  denom_pol_split.Reallocate(n);
228  }
229 
230 
232  template<class T>
233  bool NonLinearEigenProblem_Base<T>::UseSplitMatrices() const
234  {
235  if (nb_split_matrix > 1)
236  return true;
237 
238  return false;
239  }
240 
241 
243  template<class T>
244  int NonLinearEigenProblem_Base<T>::GetNbSplitMatrices() const
245  {
246  return nb_split_matrix;
247  }
248 
249 
251  template<class T>
252  void NonLinearEigenProblem_Base<T>::SetNumeratorSplitFct(int i, const Vector<T>& coef)
253  {
254  numer_pol_split(i) = coef;
255  }
256 
257 
259  template<class T>
260  void NonLinearEigenProblem_Base<T>::SetDenominatorSplitFct(int i, const Vector<T>& coef)
261  {
262  denom_pol_split(i) = coef;
263  }
264 
265 
267  template<class T>
268  const Vector<T>& NonLinearEigenProblem_Base<T>::GetNumeratorSplitFct(int i)
269  {
270  return numer_pol_split(i);
271  }
272 
273 
275  template<class T>
276  const Vector<T>& NonLinearEigenProblem_Base<T>::GetDenominatorSplitFct(int i)
277  {
278  return denom_pol_split(i);
279  }
280 
281 
283  template<class T>
284  void NonLinearEigenProblem_Base<T>::CheckValueL(const T& L)
285  {
286  if (isinf(abs(L)) || isnan(abs(L)))
287  {
288  cout << "Invalid value for L : " << L << endl;
289  abort();
290  }
291  }
292 
293 
295  template<class T>
296  void NonLinearEigenProblem_Base<T>::ComputeOperator(const T& L)
297  {
298  cout << "ComputeOperator not overloaded" << endl;
299  abort();
300  }
301 
302 
304  template<class T>
305  void NonLinearEigenProblem_Base<T>::MltOperator(const T& L, const SeldonTranspose&, const Vector<T>& X, Vector<T>& Y)
306  {
307  cout << "MltOperator not overloaded" << endl;
308  abort();
309  }
310 
311 
313  template<class T>
314  void NonLinearEigenProblem_Base<T>::ComputeOperatorExplicit(const T& L, DistributedMatrix<T, General, ArrayRowSparse>& A)
315  {
316  cout << "ComputeOperatorExplicit not overloaded" << endl;
317  abort();
318 
319  }
320 
322  template<class T>
323  void NonLinearEigenProblem_Base<T>::ComputeJacobian(const T& L)
324  {
325  cout << "ComputeJacobian not overloaded" << endl;
326  abort();
327  }
328 
330  template<class T>
331  void NonLinearEigenProblem_Base<T>::MltJacobian(const T& L, const SeldonTranspose&, const Vector<T>& X, Vector<T>& Y)
332  {
333  cout << "MltJacobian not overloaded" << endl;
334  abort();
335  }
336 
338  template<class T>
339  void NonLinearEigenProblem_Base<T>::ComputeJacobianExplicit(const T& L, DistributedMatrix<T, General, ArrayRowSparse>& A)
340  {
341  cout << "ComputeOperatorExplicit not overloaded" << endl;
342  abort();
343 
344  }
345 
347  template<class T>
348  void NonLinearEigenProblem_Base<T>::ComputePreconditioning(const T& L)
349  {
350  cout << "ComputePreconditioning not overloaded" << endl;
351  abort();
352  }
353 
355  template<class T>
356  void NonLinearEigenProblem_Base<T>::ComputePreconditioning(const Vector<T>& L, const Vector<T>& coef)
357  {
358  cout << "ComputePreconditioning not overloaded" << endl;
359  abort();
360  }
361 
362 
365  template<class T>
366  void NonLinearEigenProblem_Base<T>::ComputeSplitPreconditioning(const Vector<int>& num, const Vector<T>& coef)
367  {
368  cout << "ComputeSplitPreconditioning not overloaded" << endl;
369  abort();
370  }
371 
372 
374  template<class T>
375  void NonLinearEigenProblem_Base<T>::ComputeExplicitPreconditioning(DistributedMatrix<T, General, ArrayRowSparse>& A)
376  {
377  cout << "ComputeExplicitPreconditioning not overloaded" << endl;
378  abort();
379  }
380 
382  template<class T>
383  void NonLinearEigenProblem_Base<T>::ApplyPreconditioning(const SeldonTranspose&, const Vector<T>& X, Vector<T>& Y)
384  {
385  cout << "ApplyPreconditioning not overloaded" << endl;
386  abort();
387  }
388 
390  template<class T>
391  void NonLinearEigenProblem_Base<T>
392  ::ComputeOperatorSplitExplicit(int i, DistributedMatrix<T, General, ArrayRowSparse>& A)
393  {
394  cout << "ComputeOperatorSplitExplicit not overloaded" << endl;
395  abort();
396  }
397 
399  template<class T>
400  void NonLinearEigenProblem_Base<T>
401  ::MltOperatorSplit(int i, const SeldonTranspose&, const Vector<T>& X, Vector<T>& Y)
402  {
403  cout << "MltOperatorSplit not overloaded" << endl;
404  abort();
405  }
406 
407 
408  /************************************
409  * SplitSparseNonLinearEigenProblem *
410  ************************************/
411 
413  template<class T, class Prop, class Storage>
414  void SplitSparseNonLinearEigenProblem<T, Prop, Storage>::CheckPresenceMatrix() const
415  {
416  if (vec_Ai == NULL)
417  {
418  cout << "Matrices A_i not initialized" << endl;
419  cout << "Did you call InitMatrix ? " << endl;
420  abort();
421  }
422  }
423 
424 
426  template<class T, class Prop, class Storage>
427  SplitSparseNonLinearEigenProblem<T, Prop, Storage>::SplitSparseNonLinearEigenProblem()
428  {
429  distributed = false;
430  vec_Ai = NULL; nloc = 0;
431  this->exact_preconditioning = true; // direct solver => preconditioning is exact
432  }
433 
434 
436  template<class T, class Prop, class Storage>
437  void SplitSparseNonLinearEigenProblem<T, Prop, Storage>
438  ::InitMatrix(Vector<DistributedMatrix<T, Prop, Storage> >& A,
439  const Vector<Vector<T> >& numer, const Vector<Vector<T> >& denom)
440  {
441  this->SetSplitMatrices(A.GetM());
442  this->vec_Ai = &A;
443  this->numer_pol_split = numer;
444  this->denom_pol_split = denom;
445  this->mat_lu.Clear();
446 
447  this->SetCommunicator(A(0).GetCommunicator());
448  int nb_proc;
449  MPI_Comm_size(this->comm, &nb_proc);
450  if (nb_proc <= 1)
451  {
452  distributed = false;
453  local_col_numbers.Clear();
454  this->Init(A(0).GetM());
455  }
456  else
457  {
458  distributed = true;
459  // checking that all matrices have the same rows
460  for (int i = 1; i < A.GetM(); i++)
461  if (!A(0).SameDistributedRows(A(i)))
462  {
463  cout << "Matrices A_i must have the same distributed rows" << endl;
464  cout << "Matrix " << i << " is different" << endl;
465  abort();
466  }
467 
468  // counting the number of local columns
469  int m = A(0).GetLocalM(); nloc = m;
470  const IVect& OverlapRow = A(0).GetOverlapRowNumber();
471  int noverlap = OverlapRow.GetM();
472  int n = m - noverlap;
473 
474  // filling local_col_numbers
475  local_col_numbers.Reallocate(n);
476  Vector<bool> OverlappedRow(m); OverlappedRow.Fill(false);
477  for (int i = 0; i < noverlap; i++)
478  OverlappedRow(OverlapRow(i)) = true;
479 
480  int ncol = 0;
481  for (int i = 0; i < m; i++)
482  if (!OverlappedRow(i))
483  local_col_numbers(ncol++) = i;
484 
485  // other data needed to assemble vectors
486  ProcSharingRows = &A(0).GetProcessorSharingRows();
487  SharingRowNumbers = &A(0).GetSharingRowNumbers();
488  nodl_scalar_ = A(0).GetNodlScalar();
489  nb_unknowns_scal_ = A(0).GetNbScalarUnknowns();
490 
491  this->Init(n);
492  }
493  }
494 
495 
497  template<class T, class Prop, class Storage>
498  SparseDistributedSolver<T>& SplitSparseNonLinearEigenProblem<T, Prop, Storage>
499  ::GetDirectSolver()
500  {
501  return mat_lu;
502  }
503 
504 
506  template<class T, class Prop, class Storage>
507  bool SplitSparseNonLinearEigenProblem<T, Prop, Storage>::IsSymmetricProblem() const
508  {
509  CheckPresenceMatrix();
510  for (int i = 0; i < vec_Ai->GetM(); i++)
511  if (!(*vec_Ai)(i).IsSymmetric())
512  return false;
513 
514  return true;
515  }
516 
517 
519  template<class T, class Prop, class Storage>
520  void SplitSparseNonLinearEigenProblem<T, Prop, Storage>
521  ::ComputeSplitPreconditioning(const Vector<int>& numL, const Vector<T>& coef)
522  {
523  DistributedMatrix<T, Prop, Storage> A;
524  A = (*vec_Ai)(numL(0)); Mlt(coef(0), A);
525  for (int i = 1; i < numL.GetM(); i++)
526  Add(coef(i), (*vec_Ai)(numL(i)), A);
527 
528  if (this->print_level >= 2)
529  mat_lu.ShowMessages();
530 
531  mat_lu.Factorize(A);
532  mat_lu.HideMessages();
533  }
534 
535 
537  template<class T, class Prop, class Storage>
538  void SplitSparseNonLinearEigenProblem<T, Prop, Storage>
539  ::ComputeExplicitPreconditioning(DistributedMatrix<T, General, ArrayRowSparse>& A)
540  {
541  if (distributed)
542  {
543  cout << "not implemented" << endl;
544  abort();
545  }
546 
547  if (this->print_level >= 2)
548  mat_lu.ShowMessages();
549 
550  mat_lu.Factorize(A);
551  mat_lu.HideMessages();
552  }
553 
554 
556  template<class T, class Prop, class Storage>
557  void SplitSparseNonLinearEigenProblem<T, Prop, Storage>
558  ::ApplyPreconditioning(const SeldonTranspose& trans, const Vector<T>& X, Vector<T>& Y)
559  {
560  if (distributed)
561  {
562  Vector<T> Xd(nloc); Xd.Zero();
563  for (int i = 0; i < this->n_; i++)
564  Xd(local_col_numbers(i)) = X(i);
565 
566  mat_lu.Solve(trans, Xd, false);
567 
568  for (int i = 0; i < this->n_; i++)
569  Y(i) = Xd(local_col_numbers(i));
570  }
571  else
572  {
573  Y = X;
574  mat_lu.Solve(trans, Y);
575  }
576  }
577 
578 
580  template<class T, class Prop, class Storage>
581  void SplitSparseNonLinearEigenProblem<T, Prop, Storage>
582  ::ComputeOperatorSplitExplicit(int i, DistributedMatrix<T, General, ArrayRowSparse>& A)
583  {
584  if (distributed)
585  {
586  cout << "not implemented" << endl;
587  abort();
588  }
589 
590  Copy((*vec_Ai)(i), A);
591  }
592 
593 
595  template<class T, class Prop, class Storage>
596  void SplitSparseNonLinearEigenProblem<T, Prop, Storage>
597  ::MltOperatorSplit(int i, const SeldonTranspose& trans, const Vector<T>& X, Vector<T>& Y)
598  {
599  if (distributed)
600  {
601  Vector<T> Xd(nloc), Yd(nloc); Xd.Zero();
602  for (int i = 0; i < this->n_; i++)
603  Xd(local_col_numbers(i)) = X(i);
604 
605  AssembleVector(Xd, MPI_SUM, *ProcSharingRows, *SharingRowNumbers,
606  this->comm, nodl_scalar_, nb_unknowns_scal_, 18);
607 
608  Mlt(trans, (*vec_Ai)(i), Xd, Yd);
609 
610  for (int i = 0; i < this->n_; i++)
611  Y(i) = Yd(local_col_numbers(i));
612  }
613  else
614  Mlt(trans, (*vec_Ai)(i), X, Y);
615  }
616 
617 
619  template<class T, class Prop, class Storage>
620  void SplitSparseNonLinearEigenProblem<T, Prop, Storage>::DistributeEigenvectors(Matrix<T, General, ColMajor>& eigen_vec)
621  {
622  if (distributed)
623  {
624  this->AssembleEigenvectors(eigen_vec, local_col_numbers, ProcSharingRows,
625  SharingRowNumbers, nloc, nodl_scalar_, nb_unknowns_scal_);
626  }
627  }
628 
629  template<class T, class Prop, class Storage>
630  void GetEigenvaluesEigenvectors(NonLinearEigenProblem_Base<T>& var_eig,
631  Vector<T>& lambda, Vector<T>& lambda_imag,
632  Matrix<T, Prop, Storage>& eigen_vec,
633  int type_solver)
634  {
635  if (type_solver == TypeEigenvalueSolver::DEFAULT)
637 
638  if (type_solver == TypeEigenvalueSolver::SLEPC)
639  {
640 #ifdef SELDON_WITH_SLEPC
641  T zero; SetComplexZero(zero);
642  Matrix<T, General, ColMajor> eigen_old;
643  FindEigenvaluesSlepc(var_eig, lambda, lambda_imag, eigen_old);
644 
645  // eigenvalues are sorted by ascending order
646  SortEigenvalues(lambda, lambda_imag, eigen_old,
647  eigen_vec, var_eig.LARGE_EIGENVALUES,
648  var_eig.GetTypeSorting(), zero, zero);
649 #else
650  cout << "Recompile with Slepc" << endl;
651  abort();
652 #endif
653  }
654  else
655  {
656  cout << "Recompile with eigenvalue solver" << endl;
657  abort();
658  }
659 
660  }
661 
662 #endif
663 #endif
664 
665 }
666 
667 #define SELDON_FILE_POLYNOMIAL_EIGENVALUE_SOLVER_CXX
668 #endif
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::TypeEigenvalueSolver::GetDefaultNonLinearSolver
static int GetDefaultNonLinearSolver()
returns the default eigenvalue solver (non-linear eigenproblem)
Definition: VirtualEigenvalueSolver.cxx:3664
Seldon
Seldon namespace.
Definition: Array.cxx:24