From 34dc470db417d91d3edd4c7127295e9af7752231 Mon Sep 17 00:00:00 2001
From: Axel Modave <axel.modave@gmail.com>
Date: Wed, 18 Jun 2014 15:45:39 +0000
Subject: [PATCH] eigenSolver: add options in argument

---
 Solver/eigenSolver.cpp | 52 +++++++++++++++++++++++-------------------
 Solver/eigenSolver.h   |  3 ++-
 2 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/Solver/eigenSolver.cpp b/Solver/eigenSolver.cpp
index 291a9c8f1a..90f8089a3a 100644
--- a/Solver/eigenSolver.cpp
+++ b/Solver/eigenSolver.cpp
@@ -34,24 +34,24 @@ eigenSolver::eigenSolver(dofManager<double> *manager, std::string A,
 
 eigenSolver::eigenSolver(linearSystemPETSc<double> *A,linearSystemPETSc<double> *B, bool hermitian) : _A(A), _B(B), _hermitian(hermitian){}
 
-bool eigenSolver::solve(int numEigenValues, std::string which)
+bool eigenSolver::solve(int numEigenValues, std::string which, std::string method, double tolVal, int iterMax)
 {
   if(!_A) return false;
   Mat A = _A->getMatrix();
   Mat B = _B ? _B->getMatrix() : PETSC_NULL;
-
+  
   PetscInt N, M;
   _try(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
   _try(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
   _try(MatGetSize(A, &N, &M));
-
+  
   PetscInt N2, M2;
   if (_B) {
     _try(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
     _try(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
     _try(MatGetSize(B, &N2, &M2));
   }
-
+  
   // generalized eigenvalue problem A x - \lambda B x = 0
   EPS eps;
   _try(EPSCreate(PETSC_COMM_WORLD, &eps));
@@ -60,18 +60,24 @@ bool eigenSolver::solve(int numEigenValues, std::string which)
     _try(EPSSetProblemType(eps, _B ? EPS_GHEP : EPS_HEP));
   else
     _try(EPSSetProblemType(eps, _B ? EPS_GNHEP : EPS_NHEP));
-
+  
   // set some default options
   _try(EPSSetDimensions(eps, numEigenValues, PETSC_DECIDE, PETSC_DECIDE));
-  _try(EPSSetTolerances(eps, 1.e-7, 20));//1.e-7 20
-  _try(EPSSetType(eps, EPSKRYLOVSCHUR)); //default
-  //_try(EPSSetType(eps, EPSARNOLDI));
-  //_try(EPSSetType(eps, EPSARPACK));
-  //_try(EPSSetType(eps, EPSPOWER));
-
+  _try(EPSSetTolerances(eps, tolVal, iterMax));
+  if (method=="krylovschur")
+    _try(EPSSetType(eps, EPSKRYLOVSCHUR));
+  else if (method=="arnoldi")
+    _try(EPSSetType(eps, EPSARNOLDI));
+  else if (method=="arpack")
+    _try(EPSSetType(eps, EPSARPACK));
+  else if (method=="power")
+    _try(EPSSetType(eps, EPSPOWER));
+  else
+    Msg::Fatal("eigenSolver: method '%s' not available", method.c_str());
+  
   // override these options at runtime, petsc-style
   _try(EPSSetFromOptions(eps));
-
+  
   // force options specified directly as arguments
   if(numEigenValues)
     _try(EPSSetDimensions(eps, numEigenValues, PETSC_DECIDE, PETSC_DECIDE));
@@ -81,7 +87,7 @@ bool eigenSolver::solve(int numEigenValues, std::string which)
     _try(EPSSetWhichEigenpairs(eps, EPS_SMALLEST_REAL));
   else if(which == "largest")
     _try(EPSSetWhichEigenpairs(eps, EPS_LARGEST_MAGNITUDE));
-
+  
   // print info
   #if (SLEPC_VERSION_RELEASE == 0 || (SLEPC_VERSION_MAJOR > 3 || (SLEPC_VERSION_MAJOR == 3 && SLEPC_VERSION_MINOR >= 4)))
   EPSType type;
@@ -135,7 +141,7 @@ bool eigenSolver::solve(int numEigenValues, std::string which)
     _try(MatGetVecs(A, PETSC_NULL, &xr));
     _try(MatGetVecs(A, PETSC_NULL, &xi));
     Msg::Debug("         Re[EigenValue]          Im[EigenValue]"
-	       "          Relative error");
+         "          Relative error");
     for (int i = 0; i < nconv; i++){
       PetscScalar kr, ki;
       _try(EPSGetEigenpair(eps, i, &kr, &ki, xr, xi));
@@ -149,7 +155,7 @@ bool eigenSolver::solve(int numEigenValues, std::string which)
       PetscReal im = ki;
 #endif
       Msg::Debug("EIG %03d %s%.16e %s%.16e  %3.6e",
-		 i, (re < 0) ? "" : " ", re, (im < 0) ? "" : " ", im, error);
+     i, (re < 0) ? "" : " ", re, (im < 0) ? "" : " ", im, error);
 
       // store eigenvalues and eigenvectors
       _eigenValues.push_back(std::complex<double>(re, im));
@@ -185,24 +191,24 @@ bool eigenSolver::solve(int numEigenValues, std::string which)
 
 
 void eigenSolver::normalize_mode(double scale){
-	Msg::Info("Normalize all eigenvectors");
+  Msg::Info("Normalize all eigenvectors");
   for (unsigned int i=0; i<_eigenVectors.size(); i++){
-		double norm = 0.;
+    double norm = 0.;
     for (unsigned int j=0; j<_eigenVectors[i].size(); j++){
-			std::complex<double> val = _eigenVectors[i][j];
+      std::complex<double> val = _eigenVectors[i][j];
       double normval = std::abs(val);
       if (normval >norm)
-				norm = normval;
+        norm = normval;
     };
 
 
     if (norm == 0) {
-			Msg::Error("zero eigenvector");
+      Msg::Error("zero eigenvector");
       return;
-		};
+    };
 
- 		for (unsigned int j=0; j<_eigenVectors[i].size(); j++){
-    	_eigenVectors[i][j] *= (scale/norm);
+     for (unsigned int j=0; j<_eigenVectors[i].size(); j++){
+      _eigenVectors[i][j] *= (scale/norm);
     };
 
   };
diff --git a/Solver/eigenSolver.h b/Solver/eigenSolver.h
index 57c7b6b20e..98244a69f2 100644
--- a/Solver/eigenSolver.h
+++ b/Solver/eigenSolver.h
@@ -28,7 +28,8 @@ class eigenSolver{
               std::string B="", bool hermitian=true);
   eigenSolver(linearSystemPETSc<double> *A, linearSystemPETSc<double>* B = NULL,
               bool hermitian=true);
-  bool solve(int numEigenValues=0, std::string which="");
+  bool solve(int numEigenValues=0, std::string which="", std::string method="krylovschur",
+             double tolVal=1.e-7, int iterMax=20);
   int getNumEigenValues(){ return _eigenValues.size(); }
   std::complex<double> getEigenValue(int num){ return _eigenValues[num]; }
   std::vector<std::complex<double> > &getEigenVector(int num){ return _eigenVectors[num]; }
-- 
GitLab