diff --git a/Common/GmshConfig.h.in b/Common/GmshConfig.h.in
index 2fadf56577858393c8583ca1b60c799dc2319d95..3b484fee7b53c20e474eb4bc9e541c891cc8c735 100644
--- a/Common/GmshConfig.h.in
+++ b/Common/GmshConfig.h.in
@@ -38,7 +38,7 @@
 #cmakedefine HAVE_OSMESA
 #cmakedefine HAVE_PETSC
 #cmakedefine HAVE_QT
-#cmakedefine HAVE_SLEPSC
+#cmakedefine HAVE_SLEPC
 #cmakedefine HAVE_SOLVER
 #cmakedefine HAVE_TAUCS
 #cmakedefine HAVE_TETGEN
diff --git a/Solver/CMakeLists.txt b/Solver/CMakeLists.txt
index 699c6edc02f67cf3445df34b25fbee8c770bcb08..48363d84575b286d01d5d05e7b3b64a1a2c45850 100644
--- a/Solver/CMakeLists.txt
+++ b/Solver/CMakeLists.txt
@@ -9,6 +9,7 @@ set(SRC
   elasticityTerm.cpp
   elasticitySolver.cpp
   SElement.cpp
+  eigenSolve.cpp
 )
 
 file(GLOB HDR RELATIVE ${CMAKE_SOURCE_DIR}/Solver *.h) 
diff --git a/Solver/dofManager.h b/Solver/dofManager.h
index 525281004bd4cc699dbbf4ed6ba27da37b66fbc5..20f7aa5a5ef59b38fc5146135632cb35a8f864d4 100644
--- a/Solver/dofManager.h
+++ b/Solver/dofManager.h
@@ -73,7 +73,7 @@ class dofManager{
   std::map<Dof, Dof> associatedWith;
     
   // linearSystems
-  std::map<const std::string, linearSystem<dataMat>* > _linearSystems;
+  std::map<const std::string, linearSystem<dataMat>*> _linearSystems;
   linearSystem<dataMat>* _current;
    
  public:
@@ -236,7 +236,12 @@ class dofManager{
   }  
   linearSystem<dataMat> *getLinearSystem(std::string &name)
   {
-    return _linearSystems[name];
+    typename std::map<const std::string, linearSystem<dataMat>*>::iterator it =
+      _linearSystems.find(name);
+    if(it != _linearSystems.end())
+      return it->second;
+    else
+      return 0;
   }
 };
 
diff --git a/Solver/eigenSolve.cpp b/Solver/eigenSolve.cpp
index 2a61b171621496799c48f903066394146a641a3b..d305f799b5a3d2c95b36604e157541223d9a520a 100644
--- a/Solver/eigenSolve.cpp
+++ b/Solver/eigenSolve.cpp
@@ -9,15 +9,16 @@
 
 #include <slepceps.h>
 
-eigenSolve::eigenSolve(dofManager *manager, const char *A, const char *B)
+eigenSolve::eigenSolve(dofManager<double, double> *manager, std::string A, 
+                       std::string B) : _A(0), _B(0)
 {
-  if(A){
-    _A = manager->getLinearSystem(A);
-    if(!_A) Msg::Error("Could not find system A");
+  if(A.size()){
+    _A = dynamic_cast<linearSystemPETSc<double>*>(manager->getLinearSystem(A));
+    if(!_A) Msg::Error("Could not find PETSc system '%s'", A.c_str());
   }
-  if(B){
-    _B = manager->getLinearSystem(B);
-    if(!_B) Msg::Error("Could not find system B");
+  if(B.size()){
+    _B = dynamic_cast<linearSystemPETSc<double>*>(manager->getLinearSystem(B));
+    if(!_B) Msg::Error("Could not find PETSc system '%s'", B.c_str());
   }
 }
 
@@ -25,41 +26,63 @@ void eigenSolve::solve()
 {
   if(!_A) return;
   Mat A = _A->getMatrix();
-  Mat B = _B ? _b->getMatrix() : PETSC_NULL;
+  Mat B = _B ? _B->getMatrix() : PETSC_NULL;
+
+  _try(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
+  _try(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
+  PetscInt N, M;
+  _try(MatGetSize(A, &N, &M));
 
   // treatment of a generalized eigenvalue problem A x - \lambda B x = 0
   EPS eps;
   _try(EPSCreate(PETSC_COMM_WORLD, &eps));
   _try(EPSSetOperators(eps, A, B));
-  _try(EPSSetProblemType(eps, EPS_GNHEP));
+  // FIXME: check if hermitian (EPS_HEP or EPS_GHEP)
+  _try(EPSSetProblemType(eps, _B ? EPS_GNHEP : EPS_NHEP));
+
+  // set options
+  _try(EPSSetWhichEigenpairs(eps, EPS_LARGEST_MAGNITUDE));
+  //_try(EPSSetWhichEigenpairs(eps, EPS_SMALLEST_MAGNITUDE));
+  //_try(EPSSetTarget(eps, 2.)); // find eigenvalues close to given target
+  PetscInt nev = 2; // number of eigenvalues to compute
+  PetscInt mpd = nev; // max dim allowed for the projected problem
+  PetscInt ncv = nev + mpd; // max dim of the subspace to be used by the solver
+  _try(EPSSetDimensions(eps, nev, ncv, mpd));
 
-  // set solver parameters at runtime
+  // override options at runtime, petsc-style
   _try(EPSSetFromOptions(eps));
+
+  // print info
+  const EPSType type;
+  _try(EPSGetType(eps, &type));
+  Msg::Info("SLEPc solution method: %s", type);
+  _try(EPSGetDimensions(eps, &nev, &ncv, &mpd));
+  Msg::Info("SLEPc number of requested eigenvalues: %d", nev);
+  PetscReal tol;
+  PetscInt maxit;
+  _try(EPSGetTolerances(eps, &tol, &maxit));
+  Msg::Info("SLEPc stopping condition: tol=%g, maxit=%d", tol, maxit);
  	
   Msg::Info("SLEPc solving...");
   _try(EPSSolve(eps));
+
   int its;
   _try(EPSGetIterationNumber(eps, &its));
-  Msg::Info("Number of iterations of the method: %d", its);
+  EPSConvergedReason reason;
+  _try(EPSGetConvergedReason(eps, &reason));
+  if(reason == EPS_CONVERGED_TOL)
+    Msg::Info("SLEPc converged in %d iterations", its);
+  else if(reason == EPS_DIVERGED_ITS)
+    Msg::Error("SLEPc did not converge in %d iterations", its);
+  else if(reason == EPS_DIVERGED_BREAKDOWN)
+    Msg::Error("SLEPc generic breakdown in method");
+  else if(reason == EPS_DIVERGED_NONSYMMETRIC)
+    Msg::Error("The operator is nonsymmetric");
   
-  // get some information from the solver and display it
-  EPSType type;
-  _try(EPSGetType(eps, &type));
-  Msg::Info("Solution method: %s", type);
-  int nev;
-  _try(EPSGetDimensions(eps, &nev, PETSC_NULL));
-  Msg::Info("Number of requested eigenvalues: %d", nev);
-  PetscReal tol;
-  int maxit;
-  _try(EPSGetTolerances(eps, &tol, &maxit));
-  Msg::Info("Stopping condition: tol=%.4g, maxit=%d", tol, maxit);
-   
   // get number of converged approximate eigenpairs
-  int nconv;
+  PetscInt nconv;
   _try(EPSGetConverged(eps, &nconv));
-  Msg::Info("Number of converged eigenpairs: %d", nconv);
-
-  Msg::Info("Re[Eigenvalue] Im[Eigenvalue] Rel. error = ||Ax - eig*Bx||/||eig*x||");
+  Msg::Info("SLEPc number of converged eigenpairs: %d", nconv);
 
   // if number of converged solutions is greated than requested
   // discarded surplus solutions
@@ -71,7 +94,11 @@ void eigenSolve::solve()
   Vec xr, xi;
   _try(MatGetVecs(A, PETSC_NULL, &xr));
   _try(MatGetVecs(A, PETSC_NULL, &xi));
+  Msg::Info("         Re[EigenValue]          Im[EigenValue]"
+            "          Relative error");
   for (int i = nconv - 1; i > nconv - nev - 1; i--){
+    std::vector<std::complex<double> > ev(N);
+
     PetscScalar kr, ki;
     _try(EPSGetEigenpair(eps, i, &kr, &ki, xr, xi));
     PetscReal error;
@@ -83,14 +110,19 @@ void eigenSolve::solve()
     PetscReal re = kr;
     PetscReal im = ki;
 #endif
-    // Output eigenvalues
-    Msg::Info("EIG %03d  %s  %.16e  %s  %.16e  %3.6e", 
-              (nconv-i), (re<0)? "" : " ", re, (im<0)? "" : " ", im,  error);
+    // Output eigenvalues and relative error (= ||Ax - eig*Bx||/||eig*x||)
+    Msg::Info("EIG %03d %s%.16e %s%.16e  %3.6e", (nconv - i), 
+              (re < 0) ? "" : " ", re, (im < 0) ? "" : " ", im, error);
+    _eigenValues.push_back(std::complex<double>(re, im));
 
     // Output eigenvector
-    PetscScalar *real_tmp, *imag_tmp;
-    _try(VecGetArray(xr, &real_tmp));
-    _try(VecGetArray(xi, &imag_tmp));
+    PetscScalar *tmpr, *tmpi;
+    _try(VecGetArray(xr, &tmpr));
+    _try(VecGetArray(xi, &tmpi));
+    for(int i = 0; i < N; i++)
+      ev[i] = std::complex<double>(PetscRealPart(tmpr[i]), 
+                                   PetscRealPart(tmpi[i]));
+    _eigenVectors.push_back(ev);
   }
   
   // Free work space
diff --git a/Solver/eigenSolve.h b/Solver/eigenSolve.h
index 1e02ce35c7ba179e54e939ba28487a78a1498599..1ee5299f30fae60592654667f2efc9dad79fdb6d 100644
--- a/Solver/eigenSolve.h
+++ b/Solver/eigenSolve.h
@@ -6,6 +6,7 @@
 #ifndef _EIGEN_SOLVE_H_
 #define _EIGEN_SOLVE_H_
 
+#include <string>
 #include <complex>
 #include "GmshConfig.h"
 #include "GmshMessage.h"
@@ -13,19 +14,20 @@
 
 #if defined(HAVE_SLEPC)
 
+#include "linearSystemPETSc.h"
 #include <slepc.h>
 
 class eigenSolve{
  private:
-  linearSolver *_A, *_B;
+  linearSystemPETSc<double> *_A, *_B;
   std::vector<std::complex<double> > _eigenValues;
   std::vector<std::vector<std::complex<double> > > _eigenVectors;
   void _try(int ierr) const { CHKERRABORT(PETSC_COMM_WORLD, ierr); }
  public:
-  eigenSolve(dofManager<double, double> *manager, const char *A, 
-             const char *B=0);
-  solve();
-  std::complex<double> getEigenValue(int num){ return _eigenValuesp[num]; }
+  eigenSolve(dofManager<double, double> *manager, std::string A, 
+             std::string B="");
+  void solve();
+  std::complex<double> getEigenValue(int num){ return _eigenValues[num]; }
   std::vector<std::complex<double> > &getEigenVector(int num){ return _eigenVectors[num]; }
 };
 
@@ -35,11 +37,11 @@ class eigenSolve{
  private:
   std::vector<std::complex<double> > _dummy;
  public:
-  eigenSolve(dofManager<double, double> *manager, const char *A, 
-             const char *B=0){}
-  void solve(){}{ Msg::Error("Eigen solver requires SLEPc"); }
+  eigenSolve(dofManager<double, double> *manager, std::string A, 
+             std::string B=""){}
+  void solve(){ Msg::Error("Eigen solver requires SLEPc"); }
   std::complex<double> getEigenValue(int num){ return 0.; }
-  std::vector<complex<double> > &getEigenVector(int num){ return _dummy; }
+  std::vector<std::complex<double> > &getEigenVector(int num){ return _dummy; }
 };
 
 #endif
diff --git a/Solver/linearSystemCSR.cpp b/Solver/linearSystemCSR.cpp
index 3f83b68c98f6acee7cb8b41290d0fb5646772573..4bceac89cab8bf2a9ca6605962e13a1763621c84 100644
--- a/Solver/linearSystemCSR.cpp
+++ b/Solver/linearSystemCSR.cpp
@@ -6,10 +6,10 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <time.h>
 #include "GmshConfig.h"
 #include "GmshMessage.h"
 #include "linearSystemCSR.h"
+#include "OS.h"
 
 #define SWAP(a, b)  temp = (a); (a) = (b); (b) = temp;
 #define SWAPI(a, b) tempi = (a); (a) = (b); (b) = tempi;
@@ -343,7 +343,7 @@ int linearSystemCSRTaucs<double>::systemSolve()
   myVeryCuteTaucsMatrix.flags = TAUCS_SYMMETRIC | TAUCS_LOWER | TAUCS_DOUBLE;
 
   char* options[] = { "taucs.factor.LLT=true", NULL };
-  clock_t t1 = clock();
+  double t1 = Cpu();
   int result = taucs_linsolve(&myVeryCuteTaucsMatrix,
                               NULL,
                               1,
@@ -351,9 +351,8 @@ int linearSystemCSRTaucs<double>::systemSolve()
                               &(*_b)[0],
                               options,
                               NULL);
-  clock_t t2 = clock();
-  Msg::Info("TAUCS has solved %d unknowns in %8.3f seconds",
-            _b->size(), (double)(t2 - t1) / CLOCKS_PER_SEC);
+  double t2 = Cpu();
+  Msg::Info("TAUCS has solved %d unknowns in %8.3f seconds", _b->size(), t2 - t1);
   if (result != TAUCS_SUCCESS){
     Msg::Error("Taucs Was Not Successfull %d", result);
   }