diff --git a/Solver/function.cpp b/Solver/function.cpp
index 1f175c6c4e5f9a388d6f640c6739dd8c0d9d7f32..51bd67e50353c795ec097443c1c64c98e8d24484 100644
--- a/Solver/function.cpp
+++ b/Solver/function.cpp
@@ -631,3 +631,6 @@ functionConstant *function::getDT() {
     _dtFunction = functionConstantNew(0.);
   return _dtFunction;
 }
+function *getFunctionCoordinates(){
+  return functionCoordinates::get();
+}
diff --git a/Solver/function.h b/Solver/function.h
index b341fcce31fe3408860af32dbf8a845d9bc13417..945b4b11fb3eb3f6f3d4fac862a560012410b28a 100644
--- a/Solver/function.h
+++ b/Solver/function.h
@@ -242,4 +242,5 @@ class functionConstant : public function {
   }
   void set(double val); 
 };
+function *getFunctionCoordinates();
 #endif
diff --git a/Solver/linearSystem.cpp b/Solver/linearSystem.cpp
index f823902db4734496fa11961746cd017994f04df7..edc45772d0b021b02478299de9208a502e84d804 100644
--- a/Solver/linearSystem.cpp
+++ b/Solver/linearSystem.cpp
@@ -43,3 +43,9 @@ void linearSystem<double>::registerBindings(binding *b){
   linearSystemPETScRegisterBindings (b);
 #endif
 }
+
+void linearSystemBase::setParameter (std::string key, std::string value) {
+  if (isAllocated())
+    Msg::Error("this system is already allocated, parameters cannot be set");
+  _parameters[key] = value;
+}
diff --git a/Solver/linearSystem.h b/Solver/linearSystem.h
index bec6ac2bd4c181f1bfbae3f47abaf1e9c8f94545..687aa14d5ca1d7e37a23c68dcbe5a5b3ea9b3759 100644
--- a/Solver/linearSystem.h
+++ b/Solver/linearSystem.h
@@ -5,27 +5,35 @@
 
 #ifndef _LINEAR_SYSTEM_H_
 #define _LINEAR_SYSTEM_H_
+#include <map>
+#include <string>
 
 // A class that encapsulates a linear system solver interface :
 // building a sparse matrix, solving a linear system
 class binding;
+class linearSystemBase {
+  protected:
+  std::map<std::string, std::string> _parameters;
+  public :
+  virtual bool isAllocated() const = 0;
+  virtual void allocate(int nbRows) = 0;
+  virtual void clear() = 0;
+  virtual void zeroMatrix() = 0;
+  virtual void zeroRightHandSide() = 0;
+  virtual int systemSolve() = 0;
+  void setParameter (std::string key, std::string value);
+};
 
 template <class scalar>
-class linearSystem {
+class linearSystem : public linearSystemBase {
  public :
   linearSystem (){}
   virtual ~linearSystem (){}
-  virtual bool isAllocated() const = 0;
-  virtual void allocate(int nbRows) = 0;
-  virtual void clear() = 0;
   virtual void addToMatrix(int _row, int _col, const scalar &val) = 0;
   virtual void getFromMatrix(int _row, int _col, scalar &val) const = 0;
   virtual void addToRightHandSide(int _row, const scalar &val) = 0;
   virtual void getFromRightHandSide(int _row, scalar &val) const = 0;
   virtual void getFromSolution(int _row, scalar &val) const = 0;
-  virtual void zeroMatrix() = 0;
-  virtual void zeroRightHandSide() = 0;
-  virtual int systemSolve() = 0;
   static void registerBindings (binding*);
   virtual double normInfRightHandSide() const = 0;
 };
diff --git a/Solver/linearSystemPETSc.cpp b/Solver/linearSystemPETSc.cpp
index cad9f40901fcee78b94c88e798003a9c19038f71..876f9aa74bc115cf7e25a688ffedfd2a1248ebc6 100644
--- a/Solver/linearSystemPETSc.cpp
+++ b/Solver/linearSystemPETSc.cpp
@@ -3,6 +3,8 @@
 #if defined(HAVE_PETSC)
 #include "linearSystemPETSc.h"
 #include "fullMatrix.h"
+#include <stdlib.h>
+#include "GmshMessage.h"
 
 template <>
 void linearSystemPETSc<fullMatrix<PetscScalar> >::addToMatrix(int row, int col, const fullMatrix<PetscScalar> &val)
@@ -56,6 +58,7 @@ void linearSystemPETSc<fullMatrix<PetscScalar> >::getFromRightHandSide(int row,
   }
   _try(VecRestoreArray(_b, &tmp));
 }
+
 template<>
 void linearSystemPETSc<fullMatrix<PetscScalar> >::getFromSolution(int row, fullMatrix<PetscScalar> &val) const
 {
@@ -75,6 +78,9 @@ void linearSystemPETSc<fullMatrix<PetscScalar> >::getFromSolution(int row, fullM
 template<>
 void linearSystemPETSc<fullMatrix<PetscScalar> >::allocate(int nbRows) 
 {
+  _blockSize = strtol (_parameters["blockSize"].c_str(), NULL, 10);
+  if (_blockSize == 0)
+    Msg::Error ("'blockSize' parameters must be set for linearSystemPETScBlock");
   clear();
   _try(MatCreate(PETSC_COMM_WORLD, &_a)); 
   _try(MatSetSizes(_a, PETSC_DECIDE, PETSC_DECIDE, nbRows * _blockSize, nbRows * _blockSize));
@@ -108,10 +114,9 @@ void linearSystemPETScRegisterBindings(binding *b)
   cm->setArgNames(NULL);
   cb = b->addClass<linearSystemPETSc<fullMatrix<PetscScalar> > >("linearSystemPETScBlock");
   cb->setDescription("A linear system solver, based on PETSc");
-  cm = cb->setConstructor<linearSystemPETSc<fullMatrix<PetscScalar> >, int>();
-  cm->setDescription ("A new PETScBlock<PetscScalar> solver (we probably should get rid of the blockSize argument)");
+  cm = cb->setConstructor<linearSystemPETSc<fullMatrix<PetscScalar> > >();
+  cm->setDescription ("A new PETScBlock<PetscScalar> solver");
   cb->setParentClass<linearSystem<fullMatrix<PetscScalar> > >();
-  cm->setArgNames("blockSize", NULL);
 #endif // FIXME
 
 }
diff --git a/Solver/linearSystemPETSc.h b/Solver/linearSystemPETSc.h
index b2c1568a0cf6462dc771245ffc61aed51af184ec..c2f049277bac95b3ffda755b37d13bbeabad6539 100644
--- a/Solver/linearSystemPETSc.h
+++ b/Solver/linearSystemPETSc.h
@@ -45,13 +45,32 @@
 template <class scalar>
 class linearSystemPETSc : public linearSystem<scalar> {
   int _blockSize; // for block Matrix
-  bool _isAllocated;
+  bool _isAllocated, _kspAllocated;
   Mat _a;
   Vec _b, _x;
+  KSP _ksp;
   void _try(int ierr) const { CHKERRABORT(PETSC_COMM_WORLD, ierr); }
+  void _kspCreate() {
+    _try(KSPCreate(PETSC_COMM_WORLD, &_ksp));
+    PC pc;
+    _try(KSPGetPC(_ksp, &pc));
+    // set some default options
+    _try(PCSetType(pc, PCILU));
+    _try(PCFactorSetMatOrderingType(pc, MATORDERING_RCM));
+    _try(PCFactorSetLevels(pc, 1));
+    _try(KSPSetTolerances(_ksp, 1.e-8, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
+    // override the default options with the ones from the option
+    // database (if any)
+    _try(KSPSetFromOptions(_ksp));
+    _kspAllocated = true;
+  }
  public:
-  linearSystemPETSc(int blockSize = -1) : _isAllocated(false) {_blockSize = blockSize;}
-  virtual ~linearSystemPETSc(){ clear(); }
+  linearSystemPETSc() : _isAllocated(false) {_blockSize = 0; _kspAllocated = false;}
+  virtual ~linearSystemPETSc(){ 
+    clear(); 
+    if (_kspAllocated)
+      _try (KSPDestroy (_ksp));
+  }
   virtual bool isAllocated() const { return _isAllocated; }
   virtual void allocate(int nbRows)
   {
@@ -132,36 +151,39 @@ class linearSystemPETSc : public linearSystem<scalar> {
   }
   virtual void zeroMatrix()
   {
-    _try(MatZeroEntries(_a));
+    if (_isAllocated) {
+      _try(MatAssemblyBegin(_a, MAT_FINAL_ASSEMBLY));
+      _try(MatAssemblyEnd(_a, MAT_FINAL_ASSEMBLY));
+      _try(MatZeroEntries(_a));
+    }
   }
   virtual void zeroRightHandSide()
   {
-    _try(VecZeroEntries(_b));
+    if (_isAllocated) {
+      _try(VecAssemblyBegin(_b));
+      _try(VecAssemblyEnd(_b));
+      _try(VecZeroEntries(_b));
+    }
   }
-  virtual int systemSolve()
+  int systemSolve()
   {
+    if (!_kspAllocated)
+      _kspCreate();
+    if (linearSystem<scalar>::_parameters["matrix_reuse"] == "same_sparsity")
+      _try(KSPSetOperators(_ksp, _a, _a, SAME_NONZERO_PATTERN));
+    else if (linearSystem<scalar>::_parameters["matrix_reuse"] == "same_matrix")
+      _try(KSPSetOperators(_ksp, _a, _a, SAME_PRECONDITIONER));
+    else 
+      _try(KSPSetOperators(_ksp, _a, _a, DIFFERENT_NONZERO_PATTERN));
     _try(MatAssemblyBegin(_a, MAT_FINAL_ASSEMBLY));
     _try(MatAssemblyEnd(_a, MAT_FINAL_ASSEMBLY));
     _try(VecAssemblyBegin(_b));
     _try(VecAssemblyEnd(_b));
-    KSP ksp;
-    _try(KSPCreate(PETSC_COMM_WORLD, &ksp));
-    _try(KSPSetOperators(ksp, _a, _a, DIFFERENT_NONZERO_PATTERN));
-    PC pc;
-    _try(KSPGetPC(ksp, &pc));
-    // set some default options
-    _try(PCSetType(pc, PCILU));
-    _try(PCFactorSetMatOrderingType(pc, MATORDERING_RCM));
-    _try(PCFactorSetLevels(pc, 1));
-    _try(KSPSetTolerances(ksp, 1.e-8, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
-    // override the default options with the ones from the option
-    // database (if any)
-    _try(KSPSetFromOptions(ksp));
-    _try(KSPSolve(ksp, _b, _x));
-    _try(KSPView(ksp, PETSC_VIEWER_STDOUT_SELF));
-    PetscInt its;
-    _try(KSPGetIterationNumber(ksp, &its));
-    Msg::Info("%d iterations", its);
+    _try(KSPSolve(_ksp, _b, _x));
+    //_try(KSPView(ksp, PETSC_VIEWER_STDOUT_SELF));
+    //PetscInt its;
+    //_try(KSPGetIterationNumber(ksp, &its));
+    //Msg::Info("%d iterations", its);
     return 1;
   }
   Mat &getMatrix(){ return _a; }