diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9fda9a6f626f0384078b4709770dfe1f5affd9a7..5bebeb67592241af5792190b0c9ee252b4f6bac3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,6 +38,7 @@ option(ENABLE_OSMESA "Use OSMesa for offscreen rendering" OFF)
 option(ENABLE_PARSER "Build the GEO file parser" ON)
 option(ENABLE_POST "Build the post-processing module" ON)
 option(ENABLE_QT "Build QT GUI" OFF)
+option(ENABLE_SOLVER "Build Gmsh with the gsolver finite element library" OFF)
 option(ENABLE_TAUCS "Enable Taucs linear algebra solver" ON)
 option(ENABLE_TETGEN "Enable Tetgen mesh generator" ON)
 option(ENABLE_TETGEN_NEW "Enable experimental version of Tetgen" OFF)
@@ -59,7 +60,7 @@ set(GMSH_API
     Numeric/gmshAssembler.h Numeric/gmshTermOfFormulation.h 
     Numeric/gmshLaplace.h Numeric/gmshElasticity.h Numeric/gmshLinearSystem.h
     Numeric/gmshLinearSystemGmm.h Numeric/gmshLinearSystemFull.h 
-    Numeric/gmshFunction.h
+    Numeric/gmshLinearSystemCSR.h Numeric/gmshFunction.h
   Geo/GModel.h Geo/GEntity.h Geo/GPoint.h Geo/GVertex.h Geo/GEdge.h 
     Geo/GFace.h Geo/GRegion.h Geo/GEdgeLoop.h Geo/GEdgeCompound.h 
     Geo/GFaceCompound.h Geo/GRegionCompound.h Geo/MVertex.h Geo/MEdge.h 
@@ -483,6 +484,12 @@ if(ENABLE_TAUCS)
   endif(TAUCS_LIB)
 endif(ENABLE_TAUCS)
 
+if(ENABLE_SOLVER)
+  add_subdirectory(Solver)
+  set(HAVE_GSOLVER TRUE)
+  list(APPEND CONFIG_OPTIONS "gsolver")
+endif(ENABLE_NETGEN)
+
 if(ENABLE_OCC)
   if(WIN32)
     set(OCC_SYS_NAME win32)
diff --git a/Numeric/gmshLinearSystemCSR.h b/Numeric/gmshLinearSystemCSR.h
index 63d536dd0e19e2a1500dedf18c7e47b191aef0ec..735d6139aa71e5d4916b994e9ad6b7e19d31fe44 100644
--- a/Numeric/gmshLinearSystemCSR.h
+++ b/Numeric/gmshLinearSystemCSR.h
@@ -45,7 +45,7 @@ class gmshLinearSystemCSR : public gmshLinearSystem<scalar> {
   {
     allocate(0);
   }
-  void addToMatrix ( int il, int ic, double val) 
+  virtual void addToMatrix ( int il, int ic, double val) 
   {
     //    if (sorted)throw;
 
diff --git a/Numeric/gmshLinearSystemGmm.h b/Numeric/gmshLinearSystemGmm.h
index 10b1326521d9f455801e379babf7e86143bd10ce..afffe4ce9c85f1ebaa231b9e46d6442ca63fdc6d 100644
--- a/Numeric/gmshLinearSystemGmm.h
+++ b/Numeric/gmshLinearSystemGmm.h
@@ -81,8 +81,8 @@ class gmshLinearSystemGmm : public gmshLinearSystem<scalar> {
   void setGmres(int n){ _gmres = n; }
   virtual int systemSolve() 
   {
-    //gmm::ilutp_precond<gmm::row_matrix<gmm::wsvector<scalar> > > P(*_a, 15, 0.);
-    gmm::ildltt_precond<gmm::row_matrix<gmm::wsvector<scalar> > > P(*_a, 10, 1.e-10);
+    //gmm::ilutp_precond<gmm::row_matrix<gmm::wsvector<scalar> > > P(*_a, 25, 0.);
+    gmm::ildltt_precond<gmm::row_matrix<gmm::wsvector<scalar> > > P(*_a, 30, 1.e-10);
     gmm::iteration iter(_prec);
     iter.set_noisy(_noisy);
     if(_gmres) gmm::gmres(*_a, *_x, *_b, P, 100, iter);
diff --git a/Solver/CMakeLists.txt b/Solver/CMakeLists.txt
index f903ef6583175287b1b2a16882fed8b29df7d8a0..cc7b83f2f4805df8d3a43fd8bd39617d714cb01d 100644
--- a/Solver/CMakeLists.txt
+++ b/Solver/CMakeLists.txt
@@ -4,7 +4,9 @@
 # bugs and problems to <gmsh@geuz.org>.
 
 set(SRC
-  dofManager.cpp
+  linearSystemCSR.cpp
+  linearSystemTAUCS.cpp
+  elasticityTerm.cpp
 )
 
 append_gmsh_src(Solver "${SRC}")
diff --git a/Solver/dofManager.cpp b/Solver/dofManager.cpp
deleted file mode 100644
index 61ee97b1e99354bd340dd269379f601a9c8296e5..0000000000000000000000000000000000000000
--- a/Solver/dofManager.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "dofManager.h"
-
-template <>
-double DofManager<double, double>::getDofValue(long int entity, int type) const
-{
-  return 1.2345;
-  /*
-     if("find in fixed")
-       return ...
-     else if("find in init")
-       return ...
-     else if("find in constraint")
-       ...
-     else
-       ...
-  */
-}
-
-template <>
-void DofManager<double, double>::createFixedDof(long int entity, int type, 
-                                                const double &value)
-{
-  fixed[Dof(entity, type)] = value;
-}
diff --git a/Solver/dofManager.h b/Solver/dofManager.h
index 51e6bae57cb7468a570515e27cd5133e7c1f9724..f39bf62ed78cad49eb2d668b42430d40e5e9b777 100644
--- a/Solver/dofManager.h
+++ b/Solver/dofManager.h
@@ -9,74 +9,165 @@
 #include <vector>
 #include <string>
 #include <map>
-
-class gmshLinearSystem;
-
-class Dof{
- private:
-  // v(x) = \sum_f \sum_i v_{fi} s^f_i(x)
-  long int _entity; // "i": node, edge, group, etc.
-  int _type; // "f": basis function type index, etc.
-
- public:
+#include "MVertex.h"
+#include "linearSystem.h"
+
+namespace gsolver {
+
+  class Dof{
+  private:
+    // v(x) = \sum_f \sum_i v_{fi} s^f_i(x)
+    long int _entity; // "i": node, edge, group, etc.
+    int _type; // "f": basis function type index, etc.
+    
+  public:
   Dof(long int entity, int type) : _entity(entity), _type(type) {}
-  inline long int getEntity() const { return _entity; }
-  inline int getType() const { return _type; }
-};
-
-template<class dataVec, class dataMat>
-class DofAffineConstraint{
- public:
-  std::vector<std::pair<Dof, dataMat> > linear;
-  dataVec shift;
-};
-
-// data=float, double, complex<double>, smallVec<double>, smallVec<complex<double> >...
-template <class dataVec, class dataMat>
-class DofManager{
- private:
-  // general affine constraint on sub-blocks, treated by adding
-  // equations:
-  //   dataMat * DofVec = \sum_i dataMat_i * DofVec_i + dataVec
-  std::map<std::pair<Dof, dataMat>, DofAffineConstraint> constraint;
-
-  // fixations on full blocks, treated by eliminating equations:
-  //   DofVec = dataVec
-  std::map<Dof, dataVec> fixed, initial;
-
-  // numbering of unknown dof blocks
-  std::map<Dof, long int> unknown;
-
-  // associatations
-  std::map<Dof, Dof> associatedWith;
-
- private:
-  // linear system(s):
-  std::vector<gmshLinearSystem<dataMat>*> linearSystems;
-
- public:
-  DofManager(/* linAlgOptions &opt */){}
-  dataVec getDofValue(long int entity, int type) const;
-  void createFixedDof(long int entity, int type, const dataVec &value);
-};
-
-/*
-class termOfFormulation{
- public:
-  // hard-coded OR not!
-};
-
-class field{
- private:
-  std::string _name;
-
-  // unique mapping between dofs and names:
-  static std::map<int, std::string> _names;
-  static int typeFromName(std::string name);
-  static std::string nameFromType(int type);
-
-  // size of a dof block
-  static int blockSizeFromType(int type);
-
-  // doit pouvoir etre evalu
-
+    inline long int getEntity() const { return _entity; }
+    inline int getType() const { return _type; }
+    static int createTypeWithTwoInts( int i1, int i2 ){
+      return i1 + 10000 * i2;
+    }
+    static void getTwoIntsFromType( int t, int &i1, int &i2){
+      i1 = t % 10000;
+      i2 = t / 10000;
+    }
+    bool operator < ( const Dof & other){
+      if (_entity < other._entity)return true;
+      if (_entity > other._entity)return false;
+      if (_type < other._type)return true;
+      return false;
+    }
+  };
+
+
+  template<class dataVec, class dataMat>
+    class DofAffineConstraint{
+  public:
+    std::vector<std::pair<Dof, dataMat> > linear;
+    dataVec shift;
+  };
+  
+  // data=float, double, complex<double>, smallVec<double>, smallVec<complex<double> >...
+  template <class dataVec, class dataMat>
+    class dofManager{
+  private:
+    // general affine constraint on sub-blocks, treated by adding
+    // equations:
+    //   dataMat * DofVec = \sum_i dataMat_i * DofVec_i + dataVec
+    //std::map<std::pair<Dof, dataMat>, DofAffineConstraint> constraints;
+    
+    // fixations on full blocks, treated by eliminating equations:
+    //   DofVec = dataVec    
+    std::map<Dof, dataVec> fixed, initial;
+    
+    // numbering of unknown dof blocks
+    std::map<Dof, long int> unknown;
+    
+    // associatations
+    std::map<Dof, Dof> associatedWith;
+    
+    // linearSystems
+    std::map<std::string, linearSystem<dataMat>* > _linearSystems;
+    linearSystem<dataMat>* _current;  
+    
+  private:
+  public:
+    dofManager(linearSystem<dataMat> *l) : _current(l){
+      _linearSystems.push_back(l);
+    }
+    inline void fixDof(long int ent, int type, const dataVec & value)
+    {
+      fixed [Dof(ent, type)] = value;
+    }
+    inline void fixVertex(MVertex*v, int iComp, int iField, const dataVec & value)
+    {
+      fixDof (v->getNum(), Dof::createTypeWithTwoInts(iComp, iField ),value);
+    }
+    inline void numberDof(long int ent, int type){
+      Dof key (ent, type);
+      if (fixed.find(key) != fixed.end()) return;
+      //      if (constraints.find(key) != constraints.end()) return;
+      std::map<Dof, int> :: iterator it = unknown.find(key);
+      if (it == unknown.end()){
+	unsigned int size = unknown.size();
+	unknown[key] = size;
+      }
+    }
+    inline void numberVertex(MVertex*v, int iComp, int iField){
+      numberDof(v->getNum(), Dof::createTypeWithTwoInts(iComp,iField ));
+    }
+    inline dataVec getDofValue(int ent, int type) const
+    {
+      Dof key (ent, type);
+      {
+	typename std::map<Dof, dataVec>::const_iterator it = fixed.find(key);
+	if (it != fixed.end()) return it->second;
+      }
+      {
+	std::map<Dof, int>::const_iterator it = unknown.find(key);
+	if (it != unknown.end())
+	  return _current->getFromSolution(it->second);
+      }
+      return dataVec(0.0);
+    }
+    inline dataVec getVertexValue(MVertex *v, int iComp, int iField) const
+    {
+      getDofValue(v->getNum(), Dof::createTypeWithTwoInts(iComp,iField ));
+    }
+    
+    inline void assemble(const Dof &R, const Dof &C, const dataMat &value)
+    {
+      if (!_current->isAllocated()) _current->allocate(unknown.size());
+      
+      std::map<Dof, int>::iterator itR = unknown.find(R);
+      if (itR != unknown.end()){
+	std::map<Dof, int>::iterator itC = unknown.find(C);
+	if (itC != unknown.end()){
+	  _current->addToMatrix(itR->second, itC->second, value);
+	}
+	else{
+	  typename std::map<Dof,  dataVec>::iterator itFixed = fixed.find(C);
+	  if (itFixed != fixed.end()){
+	    _current->addToRightHandSide(itR->second, -value*itFixed->second);
+	  }
+	}
+      }
+    }
+
+    inline void assemble(int entR, int typeR, int entC, int typeC, const dataMat &value)
+    {
+      assemble (Dof(entR,typeR),Dof(entC,typeC), value);
+    }
+    
+    inline void assembleVertex(MVertex *vR, int iCompR, int iFieldR,
+			       MVertex *vC, int iCompC, int iFieldC,
+			       const dataMat &value){
+      assemble (vR->getNum(), Dof::createTypeWithTwoInts(iCompR,iFieldR),
+		vC->getNum(), Dof::createTypeWithTwoInts(iCompC,iFieldC),
+		value);
+    } 
+    
+    inline void assemble(const Dof &R, const dataMat &value)
+    {
+      if (!_current->isAllocated())_current->allocate(unknown.size());
+      std::map<Dof, int>::iterator itR = unknown.find(R);
+      if (itR != unknown.end()){
+	_current->addToRightHandSide(itR->second, value);
+      }
+    }
+    inline void assemble(int entR, int typeR, const dataMat &value)
+    {
+      assemble(Dof(entR,typeR));
+    }
+    int sizeOfR() const { return unknown.size(); }
+    int sizeOfF() const { return fixed.size(); }
+    void systemSolve(){
+      _current->systemSolve();
+    }  
+    void systemClear(){
+      _current->zeroMatrix();
+      _current->zeroRightHandSide();
+    }  
+  };
+}
+#endif
diff --git a/Solver/elasticityTerm.cpp b/Solver/elasticityTerm.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1545d4cf00d88348b97be30040de3157ce176d99
--- /dev/null
+++ b/Solver/elasticityTerm.cpp
@@ -0,0 +1,104 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "elasticityTerm.h"
+#include "Numeric.h"
+
+namespace gsolver {
+  void elasticityTerm::elementMatrix(MElement *e, gmshMatrix<double> &m) const
+  {
+    int nbNodes = e->getNumVertices();
+    int integrationOrder = 3 * (e->getPolynomialOrder() - 1) ;
+    int npts;
+    IntPt *GP;
+    double jac[3][3];
+    double invjac[3][3];
+    double Grads[256][3], grads[100][3];
+    e->getIntegrationPoints(integrationOrder, &npts, &GP);
+    
+    m.set_all(0.);
+    
+    double FACT = _E / (1 + _nu);
+    double C11 = FACT * (1 - _nu) / (1 - 2 * _nu);
+    double C12 = FACT * _nu / (1 - 2 * _nu);
+    double C44 = (C11 - C12) / 2;
+    const double C[6][6] =
+      { {C11, C12, C12,    0,   0,   0}, 
+	{C12, C11, C12,    0,   0,   0}, 
+	{C12, C12, C11,    0,   0,   0}, 
+	{  0,   0,   0,  C44,   0,   0},
+	{  0,   0,   0,    0, C44,   0}, 
+	{  0,   0,   0,    0,   0, C44} };
+    
+    gmshMatrix<double> H(6, 6);
+    gmshMatrix<double> B(6, 3 * nbNodes);
+    gmshMatrix<double> BTH(3 * nbNodes, 6);
+    gmshMatrix<double> BT(3 * nbNodes, 6);
+    for (int i = 0; i < 6; i++)
+      for (int j = 0; j < 6; j++)
+	H(i, j) = C[i][j];
+    
+    for (int i = 0; i < npts; i++){
+      const double u = GP[i].pt[0];
+      const double v = GP[i].pt[1];
+      const double w = GP[i].pt[2];
+      const double weight = GP[i].weight;
+      const double detJ = e->getJacobian(u, v, w, jac);
+      e->getGradShapeFunctions(u, v, w, grads);
+      inv3x3(jac, invjac);
+      B.set_all(0.);
+      BT.set_all(0.);
+      for (int j = 0; j < nbNodes; j++){
+	Grads[j][0] = invjac[0][0] * grads[j][0] + invjac[0][1] * grads[j][1] + 
+	  invjac[0][2] * grads[j][2];
+	Grads[j][1] = invjac[1][0] * grads[j][0] + invjac[1][1] * grads[j][1] + 
+	  invjac[1][2] * grads[j][2];
+	Grads[j][2] = invjac[2][0] * grads[j][0] + invjac[2][1] * grads[j][1] + 
+	  invjac[2][2] * grads[j][2];
+	
+	BT(j, 0) = B(0, j) = Grads[j][0];
+	BT(j, 3) = B(3, j) = Grads[j][1];
+	BT(j, 4) = B(4, j) = Grads[j][2];
+	
+	BT(j + nbNodes, 1) = B(1, j + nbNodes) = Grads[j][1];
+	BT(j + nbNodes, 3) = B(3, j + nbNodes) = Grads[j][0];
+	BT(j + nbNodes, 5) = B(5, j + nbNodes) = Grads[j][2];
+	
+	BT(j + 2 * nbNodes, 2) = B(2, j + 2 * nbNodes) = Grads[j][2];
+	BT(j + 2 * nbNodes, 4) = B(4, j + 2 * nbNodes) = Grads[j][0];
+	BT(j + 2 * nbNodes, 5) = B(5, j + 2 * nbNodes) = Grads[j][1];
+      }
+      BTH.set_all(0.);
+      BTH.gemm(BT, H); 
+      m.gemm(BTH, B, weight * detJ, 1.);
+    } 
+  }
+  
+  void elasticityTerm::elementVector(MElement *e, gmshVector<double> &m) const{
+    int nbNodes = e->getNumVertices();
+    int integrationOrder = 2 * e->getPolynomialOrder();
+    int npts;
+    IntPt *GP;
+    double jac[3][3];
+    double ff[256];
+    e->getIntegrationPoints(integrationOrder, &npts, &GP);
+    
+    m.scale(0.);
+    
+    for (int i = 0; i < npts; i++){
+      const double u = GP[i].pt[0];
+      const double v = GP[i].pt[1];
+      const double w = GP[i].pt[2];
+      const double weight = GP[i].weight;
+      const double detJ = e->getJacobian(u, v, w, jac);
+      e->getShapeFunctions(u, v, w, ff);
+      for (int j = 0; j < nbNodes; j++){
+	m(j)           += _volumeForce.x() *ff[j] * weight * detJ *.5;
+	m(j+nbNodes)   += _volumeForce.y() *ff[j] * weight * detJ *.5;
+	m(j+2*nbNodes) += _volumeForce.z() *ff[j] * weight * detJ *.5;
+      }
+    } 
+  }
+}
diff --git a/Solver/elasticityTerm.h b/Solver/elasticityTerm.h
new file mode 100644
index 0000000000000000000000000000000000000000..a6a9fbc3f38d4424713454d1d7dcb9b01010e99e
--- /dev/null
+++ b/Solver/elasticityTerm.h
@@ -0,0 +1,43 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _ELASTICITY_H_
+#define _ELASTICITY_H_
+
+#include "termOfFormulation.h"
+#include "Gmsh.h"
+#include "GModel.h"
+#include "MElement.h"
+#include "GmshMatrix.h"
+
+namespace gsolver {
+  class elasticityTerm : public femTerm<double,double> {
+  protected:
+    double _E, _nu;
+    int _iField;
+    SVector3 _volumeForce;
+ public:
+    // element matrix size : 3 dofs per vertex
+    virtual int sizeOfR(MElement *e) const { return 3 * e->getNumVertices(); }
+    virtual int sizeOfC(MElement *e) const { return 3 * e->getNumVertices(); }
+    // order dofs in the local matrix :
+    // dx1, dx2 ... dxn, dy1, ..., dyn, dz1, ... dzn 
+    Dof getLocalDofR(MElement *e, int iRow) const 
+    {
+      int iCompR = iRow / e->getNumVertices();
+      int ithLocalVertex = iRow % e->getNumVertices();
+      return Dof (e->getVertex(ithLocalVertex)->getNum(),
+		  Dof::createTypeWithTwoInts(iCompR, _iField));
+    }
+  public:
+    elasticityTerm(GModel *gm, double E, double nu, int iField = 1) : 
+      femTerm<double,double>(gm), _E(E), _nu(nu), _iField(iField){}
+    void setVector(const SVector3 &f) {_volumeForce = f;}
+    void elementMatrix(MElement *e, gmshMatrix<double> &m) const;
+    void elementVector(MElement *e, gmshVector<double> &m) const;
+  };
+}
+
+#endif
diff --git a/Solver/linearSystem.h b/Solver/linearSystem.h
new file mode 100644
index 0000000000000000000000000000000000000000..e274702104443a949fe896bcfffb958c62fa7d98
--- /dev/null
+++ b/Solver/linearSystem.h
@@ -0,0 +1,30 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _LINEAR_SYSTEM_H_
+#define _LINEAR_SYSTEM_H_
+
+// A class that encapsulates a linear system solver interface :
+// building a sparse matrix, solving a linear system
+namespace gsolver {
+  template <class scalar>
+    class linearSystem {
+  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, scalar val) = 0;
+    virtual scalar getFromMatrix(int _row, int _col) const = 0;
+    virtual void addToRightHandSide(int _row, scalar val) = 0;
+    virtual scalar getFromRightHandSide(int _row) const = 0;
+    virtual scalar getFromSolution(int _row) const = 0;
+    virtual void zeroMatrix() = 0;
+    virtual void zeroRightHandSide() = 0;
+    virtual int systemSolve() = 0;
+  };
+}
+#endif
diff --git a/Solver/linearSystemCSR.cpp b/Solver/linearSystemCSR.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5817c1aacffa687112ae16de3e25c3d65a2708cc
--- /dev/null
+++ b/Solver/linearSystemCSR.cpp
@@ -0,0 +1,316 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "GmshConfig.h"
+#include "GmshMessage.h"
+#include "linearSystemCSR.h"
+
+#define SWAP(a,b)  temp=(a);(a)=(b);(b)=temp;
+#define SWAPI(a,b) tempi=(a);(a)=(b);(b)=tempi;
+namespace gsolver {
+  void *CSRMalloc(size_t size)
+  {
+    void *ptr;
+    if (!size) return(NULL);
+    ptr = malloc(size);
+    return(ptr);
+  }
+  
+  void *CSRRealloc(void *ptr, size_t size)
+  {
+    if (!size) return(NULL);
+    ptr = realloc(ptr,size);
+    return(ptr);
+  }
+  
+  void CSRList_Realloc(CSRList_T *liste,int n)
+  {
+    char* temp;
+    if (n <= 0) return;
+    if (liste->array == NULL) {
+      liste->nmax = ((n - 1) / liste->incr + 1) * liste->incr;
+      liste->array = (char *)CSRMalloc(liste->nmax * liste->size);
+    }
+    else {
+      if (n > liste->nmax) {
+	liste->nmax = ((n - 1) / liste->incr + 1) * liste->incr;
+	temp = (char *)CSRRealloc(liste->array, liste->nmax * liste->size);
+	liste->array = temp;
+      }
+    }
+  }
+  
+  
+  CSRList_T *CSRList_Create(int n, int incr, int size)
+  {
+    CSRList_T *liste;
+    
+    if (n <= 0)  n = 1 ;
+    if (incr <= 0) incr = 1;
+    
+    liste = (CSRList_T *)CSRMalloc(sizeof(CSRList_T));
+    
+    liste->nmax    = 0;
+    liste->incr    = incr;
+    liste->size    = size;
+    liste->n       = 0;
+    liste->isorder = 0;
+    liste->array   = NULL;
+    
+    CSRList_Realloc(liste,n);
+    return(liste);
+  }
+  
+  void CSRList_Delete(CSRList_T *liste)
+  {
+    if (liste != 0) {
+      free(liste->array);
+      free(liste);
+    }
+  }
+  
+  void CSRList_Add(CSRList_T *liste, void *data)
+  {
+    liste->n++;
+    
+    CSRList_Realloc(liste,liste->n);
+    liste->isorder = 0;
+    memcpy(&liste->array[(liste->n - 1) * liste->size],data,liste->size);
+  }
+  
+  int CSRList_Nbr(CSRList_T *liste)
+  {
+    return(liste->n);
+  }
+  
+  template<>
+  void linearSystemCSR<double>::allocate(int _nbRows)
+  {
+    if(a_) {
+      CSRList_Delete(a_);
+      CSRList_Delete(ai_);
+      CSRList_Delete(ptr_);
+      CSRList_Delete(jptr_);
+      delete _x;
+      delete _b;
+      delete something;
+    }
+    
+    if(_nbRows == 0){
+      a_ = 0; 
+      ai_ = 0; 
+      ptr_ = 0; 
+      jptr_ = 0; 
+      _b = 0;
+      _x = 0;
+      something = 0;
+      return;
+    }
+    
+    a_    = CSRList_Create (_nbRows, _nbRows, sizeof(double));
+    ai_   = CSRList_Create (_nbRows, _nbRows, sizeof(INDEX_TYPE));
+    ptr_  = CSRList_Create (_nbRows, _nbRows, sizeof(INDEX_TYPE));
+    jptr_ = CSRList_Create (_nbRows+1, _nbRows, sizeof(INDEX_TYPE));
+    
+    something = new char[_nbRows];
+    
+    for (int i=0;i<_nbRows;i++)something[i] = 0;
+    
+    _b = new std::vector<double>(_nbRows);
+    _x = new std::vector<double>(_nbRows);
+  }
+  
+  const int NSTACK   = 50;
+  const unsigned int M_sort2  = 7;
+  
+  static void free_ivector(int *v, long nl, long nh)
+  {
+    // free an int vector allocated with ivector() 
+    free((char*)(v+nl-1));
+  }
+  
+  static int *ivector(long nl, long nh)
+  {
+    // allocate an int vector with subscript range v[nl..nh] 
+    int *v;  
+    v=(int *)malloc((size_t) ((nh-nl+2)*sizeof(int)));
+    if (!v) fprintf(stderr, "allocation failure in ivector()\n");
+    return v-nl+1;
+  }
+  
+  static int cmpij(INDEX_TYPE ai,INDEX_TYPE aj,INDEX_TYPE bi,INDEX_TYPE bj)
+  {
+    if(ai<bi)return -1;
+    if(ai>bi)return 1;
+    if(aj<bj)return -1;
+    if(aj>bj)return 1;
+    return 0;
+  }
+  
+  template <class scalar>
+  void _sort2_xkws(unsigned long n, double arr[], INDEX_TYPE ai[], INDEX_TYPE aj[])
+  {
+    unsigned long i,ir=n,j,k,l=1;
+    int *istack,jstack=0;
+    INDEX_TYPE tempi;
+    scalar a,temp;
+    int    b,c;
+    
+    istack=ivector(1,NSTACK);
+    for (;;) {
+      if (ir-l < M_sort2) {
+	for (j=l+1;j<=ir;j++) {
+	  a=arr[j -1];
+	  b=ai[j -1];
+	  c=aj[j -1];
+	  for (i=j-1;i>=1;i--) {
+	    if (cmpij(ai[i -1],aj[i -1],b,c) <= 0) break;
+	    arr[i+1 -1]=arr[i -1];
+	    ai[i+1 -1]=ai[i -1];
+	    aj[i+1 -1]=aj[i -1];
+	  }
+	  arr[i+1 -1]=a;
+	  ai[i+1 -1]=b;
+	  aj[i+1 -1]=c;
+	}
+	if (!jstack) {
+	  free_ivector(istack,1,NSTACK);
+	  return;
+	}
+	ir=istack[jstack];
+	l=istack[jstack-1];
+	jstack -= 2;
+      } 
+      else {
+	k=(l+ir) >> 1;
+	SWAP(arr[k -1],arr[l+1 -1])
+	  SWAPI(ai[k -1],ai[l+1 -1])
+	  SWAPI(aj[k -1],aj[l+1 -1])
+	  if (cmpij(ai[l+1 -1],aj[l+1 -1],ai[ir -1],aj[ir -1])>0){
+	    SWAP(arr[l+1 -1],arr[ir -1])
+	      SWAPI(ai[l+1 -1],ai[ir -1])
+	      SWAPI(aj[l+1 -1],aj[ir -1])
+	      }
+	if (cmpij(ai[l -1],aj[l -1],ai[ir -1],aj[ir -1])>0){
+	  SWAP(arr[l -1],arr[ir -1])
+	    SWAPI(ai[l -1],ai[ir -1])
+	    SWAPI(aj[l -1],aj[ir -1])
+	    }
+	if (cmpij(ai[l+1 -1],aj[l+1 -1],ai[l -1],aj[l -1])>0){
+	  SWAP(arr[l+1 -1],arr[l -1])
+	    SWAPI(ai[l+1 -1],ai[l -1])
+	    SWAPI(aj[l+1 -1],aj[l -1])
+	    }
+	i=l+1;
+	j=ir;
+	a=arr[l -1];
+	b=ai[l -1];
+	c=aj[l -1];
+	for (;;) {
+	  do i++; while (cmpij(ai[i -1],aj[i -1],b,c) < 0);
+	  do j--; while (cmpij(ai[j -1],aj[j -1],b,c) > 0);
+	  if (j < i) break;
+	  SWAP(arr[i -1],arr[j -1])
+	    SWAPI(ai[i -1],ai[j -1])
+	    SWAPI(aj[i -1],aj[j -1])
+	    }
+	arr[l -1]=arr[j -1];
+	arr[j -1]=a;
+	ai[l -1]=ai[j -1];
+	ai[j -1]=b;
+	aj[l -1]=aj[j -1];
+	aj[j -1]=c;
+	jstack += 2;
+	if (jstack > NSTACK) {
+	  Msg::Fatal("NSTACK too small while sorting the columns of the matrix");
+	  throw;
+	}
+	if (ir-i+1 >= j-l) {
+	  istack[jstack]=ir;
+	  istack[jstack-1]=i;
+	  ir=j-1;
+	} 
+	else {
+	  istack[jstack]=j-1;
+	  istack[jstack-1]=l;
+	  l=i;
+	}
+      }
+    }
+  }
+  
+  template <class scalar>
+  void sortColumns(int NbLines, 
+		   int nnz, 
+		   INDEX_TYPE *ptr, 
+		   INDEX_TYPE *jptr, 
+		   INDEX_TYPE *ai, 
+		   scalar *a)
+  {
+    // replace pointers by lines
+    int *count = new int [NbLines];
+    
+    for(int i=0;i<NbLines;i++){
+      count[i] = 0;
+      INDEX_TYPE _position =  jptr[i];
+      while(1){
+	count[i]++;
+	INDEX_TYPE _position_temp = _position;
+	_position = ptr[_position];
+	ptr[_position_temp] = i;
+	if (_position == 0) break;
+      }
+    }   
+    _sort2_xkws<double>(nnz,a,ptr,ai);   
+    jptr[0] = 0;
+    for(int i=1;i<=NbLines;i++){
+      jptr[i] = jptr[i-1] + count[i-1];
+    }
+    
+    for(int i=0;i<NbLines;i++){
+      for (int j= jptr[i] ; j<jptr[i+1]-1 ; j++){
+	ptr[j] = j+1;
+      }
+      ptr[jptr[i+1]] = 0;
+    }
+    
+    delete[] count;
+  }
+}
+  
+#if defined(HAVE_GMM)
+#include "gmm.h"
+namespace gsolver {
+  template<>
+  int linearSystemCSRGmm<double>::systemSolve()
+  {
+    if (!sorted)
+      sortColumns(_b->size(),
+		  CSRList_Nbr(a_),
+		  (INDEX_TYPE *) ptr_->array,
+		  (INDEX_TYPE *) jptr_->array, 
+		  (INDEX_TYPE *) ai_->array, 
+		  (double*) a_->array);
+    sorted = true;
+    
+    gmm::csr_matrix_ref<double*,INDEX_TYPE *,INDEX_TYPE *, 0>  
+      ref((double*)a_->array, (INDEX_TYPE *) ai_->array,
+	  (INDEX_TYPE *)jptr_->array, _b->size(), _b->size());
+    gmm::csr_matrix<double,0> M;
+    M.init_with(ref);
+    
+    gmm::ildltt_precond<gmm::csr_matrix<double, 0> > P(M, 10, 1.e-10);
+    gmm::iteration iter(_prec);
+    iter.set_noisy(_noisy);
+    if(_gmres) gmm::gmres(M, *_x, *_b, P, 100, iter);
+    else gmm::cg(M, *_x, *_b, P, iter);
+    return 1;
+  }
+}
+#endif
+
diff --git a/Solver/linearSystemCSR.h b/Solver/linearSystemCSR.h
new file mode 100644
index 0000000000000000000000000000000000000000..1dcaae4e714292fe419aa299ef9477afedfe487a
--- /dev/null
+++ b/Solver/linearSystemCSR.h
@@ -0,0 +1,144 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _LINEAR_SYSTEM_CSR_H_
+#define _LINEAR_SYSTEM_CSR_H_
+
+#include <vector>
+#include "GmshConfig.h"
+#include "GmshMessage.h"
+#include "linearSystem.h"
+
+namespace gsolver {  
+  typedef int INDEX_TYPE ;  
+  typedef struct {
+    int nmax;
+    int size;
+    int incr;
+    int n;
+    int isorder;
+    char *array;
+  } CSRList_T;
+  
+  void CSRList_Add(CSRList_T *liste, void *data);
+  int  CSRList_Nbr(CSRList_T *liste);
+  
+  template <class scalar>
+  class linearSystemCSR : public linearSystem<scalar> {
+  protected:
+    bool sorted;
+    char *something;
+    CSRList_T *a_,*ai_,*ptr_,*jptr_; 
+    std::vector<scalar> *_b, *_x;
+  public:
+    linearSystemCSR()
+      : sorted(false), a_(0) {}
+    virtual bool isAllocated() const { return a_ != 0; }
+    virtual void allocate(int) ;
+    virtual void clear()
+    {
+      allocate(0);
+    }
+    virtual ~linearSystemCSR()
+    {
+      allocate(0);
+    }
+    virtual void addToMatrix ( int il, int ic, double val) 
+    {
+      //    if (sorted)throw;
+      
+      INDEX_TYPE  *jptr  = (INDEX_TYPE*) jptr_->array;
+      INDEX_TYPE  *ptr   = (INDEX_TYPE*) ptr_->array;
+      INDEX_TYPE  *ai    = (INDEX_TYPE*) ai_->array;
+      scalar      *a     = ( scalar * ) a_->array;
+      
+      INDEX_TYPE  position_ = jptr[il];
+      
+      if(something[il]) {
+	while(1){
+	  if(ai[position_] == ic){
+	    a[position_] += val;
+	    //      if (il == 0)    printf("FOUND %d %d %d\n",il,ic,position_);
+	    return;
+	  }
+	  if (ptr[position_] == 0)break;
+	  position_ = ptr[position_];
+	}
+      }  
+      
+      INDEX_TYPE zero = 0;
+      CSRList_Add (a_, &val);
+      CSRList_Add (ai_, &ic);
+      CSRList_Add (ptr_, &zero);
+      // The pointers may have been modified
+      // if there has been a reallocation in CSRList_Add  
+      
+      ptr = (INDEX_TYPE*) ptr_->array;
+      ai  = (INDEX_TYPE*) ai_->array;
+      a   = (scalar*) a_->array;
+      
+      INDEX_TYPE n = CSRList_Nbr(a_) - 1;
+      
+      if(!something[il]) {
+	jptr[il] = n;
+	something[il] = 1;      
+      }
+      else ptr[position_] = n;
+    }
+    
+    virtual scalar getFromMatrix (int _row, int _col) const
+    {
+      throw;
+    }
+    virtual void addToRightHandSide(int _row, scalar _val) 
+    {
+      if(_val != 0.0) (*_b)[_row] += _val;
+    }
+    virtual scalar getFromRightHandSide(int _row) const 
+    {
+      return (*_b)[_row];
+    }
+    virtual scalar getFromSolution(int _row) const
+    {
+      return (*_x)[_row];
+    }
+    virtual void zeroMatrix()
+    {
+      int N=CSRList_Nbr(a_);
+      scalar *a = (scalar*) a_->array;
+      for (int i=0;i<N;i++)a[i]=0;
+    }
+    virtual void zeroRightHandSide() 
+    {
+      for(unsigned int i = 0; i < _b->size(); i++) (*_b)[i] = 0.;
+    }
+  };
+
+  template <class scalar>
+  class linearSystemCSRGmm : public linearSystemCSR<scalar> {
+  private:
+    double _prec;
+    int _noisy, _gmres;
+  public:
+    linearSystemCSRGmm()
+      : _prec(1.e-8), _noisy(0), _gmres(0) {}
+    virtual ~linearSystemCSRGmm()
+    {}
+    void setPrec(double p){ _prec = p; }
+    void setNoisy(int n){ _noisy = n; }
+    void setGmres(int n){ _gmres = n; }
+    virtual int systemSolve() 
+#if defined(HAVE_GMM)
+      ;
+#else
+    {
+      Msg::Error("Gmm++ is not available in this version of Gmsh");
+      return 0;
+    }
+#endif
+  };
+}
+
+#endif
diff --git a/Solver/linearSystemFull.h b/Solver/linearSystemFull.h
new file mode 100644
index 0000000000000000000000000000000000000000..85ab46429434241497842b5a14839346a4532114
--- /dev/null
+++ b/Solver/linearSystemFull.h
@@ -0,0 +1,85 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _LINEAR_SYSTEM_FULL_H_
+#define _LINEAR_SYSTEM_FULL_H_
+
+// Interface to a linear system with a FULL matrix
+
+#include "GmshMessage.h"
+#include "linearSystem.h"
+#include "GmshMatrix.h"
+#include <stdlib.h>
+#include <set>
+
+namespace gsolver {
+  template <class scalar>
+  class linearSystemFull : public linearSystem<scalar> {
+  private:
+    gmshMatrix<scalar> *_a;
+    gmshVector<scalar> *_b, *_x;
+  public :
+    linearSystemFull() : _a(0), _b(0), _x(0){}
+    virtual bool isAllocated() const { return _a != 0; }
+    virtual void allocate(int _nbRows)
+    {
+      clear();
+      _a = new gmshMatrix<scalar>(_nbRows, _nbRows);
+      _b = new gmshVector<scalar>(_nbRows);
+      _x = new gmshVector<scalar>(_nbRows);
+    }
+    
+    virtual ~linearSystemFull()
+    {
+      clear();
+    }
+    
+    virtual void clear()
+    {
+      if(_a){
+	delete _a;
+	delete _b;
+	delete _x;
+      }
+      _a = 0;
+    }
+    virtual void addToMatrix(int _row, int _col, scalar _val)
+    {
+      if(_val != 0.0) (*_a)(_row, _col) += _val;
+    }
+    virtual scalar getFromMatrix(int _row, int _col) const
+    {
+      return (*_a)(_row, _col);
+    }
+    virtual void addToRightHandSide(int _row, scalar _val)
+    {
+      if(_val != 0.0) (*_b)(_row) += _val;
+    }
+    virtual scalar getFromRightHandSide(int _row) const 
+    {
+      return (*_b)(_row);
+    }
+    virtual scalar getFromSolution(int _row) const 
+    {
+      return (*_x)(_row);
+    }
+    virtual void zeroMatrix() 
+    {
+      _a->set_all(0.);
+    }
+    virtual void zeroRightHandSide()
+    {
+      for(int i = 0; i < _b->size(); i++) (*_b)(i) = 0.;
+    }
+    virtual int systemSolve() 
+    {
+      if (_b->size())
+	_a->lu_solve(*_b, *_x);
+      // _x->print("********* mySol");
+      return 1;
+    }
+  };
+}
+#endif
diff --git a/Solver/linearSystemGMM.h b/Solver/linearSystemGMM.h
new file mode 100644
index 0000000000000000000000000000000000000000..822d28fc67079d164089b8a8a9d71a465c818076
--- /dev/null
+++ b/Solver/linearSystemGMM.h
@@ -0,0 +1,122 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _LINEAR_SYSTEM_GMM_H_
+#define _LINEAR_SYSTEM_GMM_H_
+
+// Interface to GMM++
+
+#include "GmshConfig.h"
+#include "GmshMessage.h"
+#include "linearSystem.h"
+
+#if defined(HAVE_GMM)
+#include <gmm.h>
+namespace gsolver {
+  template <class scalar>
+  class linearSystemGmm : public linearSystem<scalar> {
+  private:
+    gmm::row_matrix<gmm::wsvector<scalar> > *_a;
+    std::vector<scalar> *_b, *_x;
+    double _prec;
+    int _noisy, _gmres;
+  public:
+    linearSystemGmm()
+      : _a(0), _b(0), _x(0), _prec(1.e-8), _noisy(0), _gmres(0) {}
+    virtual bool isAllocated() const { return _a != 0; }
+    virtual void allocate(int _nbRows)
+    {
+      clear();
+      _a = new gmm::row_matrix< gmm::wsvector<scalar> >(_nbRows, _nbRows);
+      _b = new std::vector<scalar>(_nbRows);
+      _x = new std::vector<scalar>(_nbRows);
+    }
+    virtual ~linearSystemGmm()
+    {
+      clear();
+    }
+    
+    virtual void clear()
+    {
+      if (_a){
+	delete _a;
+	delete _b;
+	delete _x;
+      }
+      _a = 0;
+    }
+    virtual void  addToMatrix(int _row, int _col, scalar _val) 
+    {
+      if(_val != 0.0) (*_a)(_row, _col) += _val;
+    }
+    virtual scalar getFromMatrix (int _row, int _col) const
+    {
+      return (*_a)(_row, _col);
+    }
+    virtual void addToRightHandSide(int _row, scalar _val) 
+    {
+      if(_val != 0.0) (*_b)[_row] += _val;
+    }
+    virtual scalar getFromRightHandSide(int _row) const 
+    {
+      return (*_b)[_row];
+    }
+    virtual scalar getFromSolution(int _row) const
+    {
+      return (*_x)[_row];
+    }
+    virtual void zeroMatrix()
+    {
+      gmm::clear(*_a);
+    }
+    virtual void zeroRightHandSide() 
+    {
+      for(unsigned int i = 0; i < _b->size(); i++) (*_b)[i] = 0.;
+    }
+    void setPrec(double p){ _prec = p; }
+    void setNoisy(int n){ _noisy = n; }
+    void setGmres(int n){ _gmres = n; }
+    virtual int systemSolve() 
+    {
+      //gmm::ilutp_precond<gmm::row_matrix<gmm::wsvector<scalar> > > P(*_a, 25, 0.);
+      gmm::ildltt_precond<gmm::row_matrix<gmm::wsvector<scalar> > > P(*_a, 30, 1.e-10);
+      gmm::iteration iter(_prec);
+      iter.set_noisy(_noisy);
+      if(_gmres) gmm::gmres(*_a, *_x, *_b, P, 100, iter);
+      else gmm::cg(*_a, *_x, *_b, P, iter);
+      return 1;
+    }
+  };
+}
+
+#else
+
+namespace gsolver {
+  template <class scalar>
+  class linearSystemGmm : public linearSystem<scalar> {
+  public :
+    linearSystemGmm()
+    {
+      Msg::Error("Gmm++ is not available in this version of Gmsh");
+    }
+    virtual bool isAllocated() const { return false; }
+    virtual void allocate(int nbRows) {}
+    virtual void addToMatrix(int _row, int _col, scalar val) {}
+    virtual scalar getFromMatrix(int _row, int _col) const { return 0.; }
+    virtual void addToRightHandSide(int _row, scalar val) {}
+    virtual scalar getFromRightHandSide(int _row) const { return 0.; }
+    virtual scalar getFromSolution(int _row) const { return 0.; }
+    virtual void zeroMatrix() {}
+    virtual void zeroRightHandSide() {}
+    virtual int systemSolve() { return 0; }
+    void setPrec(double p){}
+    virtual void clear(){}
+    void setNoisy(int n){}
+    void setGmres(int n){}
+  }; 
+}
+#endif
+
+#endif
diff --git a/Solver/linearSystemTAUCS.cpp b/Solver/linearSystemTAUCS.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4101ca97900c0a8b0561726a51a349259f2d4c2a
--- /dev/null
+++ b/Solver/linearSystemTAUCS.cpp
@@ -0,0 +1,62 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "linearSystemTAUCS.h"
+
+#if defined(HAVE_TAUCS)
+extern "C" {
+#include "taucs.h"
+}
+
+namespace gsolver {
+  template <class scalar>
+  void sortColumns(int NbLines, 
+		   int nnz, 
+		   INDEX_TYPE *ptr, 
+		   INDEX_TYPE *jptr, 
+		   INDEX_TYPE *ai, 
+		   scalar *a);
+  
+  template<>
+  int linearSystemCSRTaucs_<double>::systemSolve()
+  {
+    if(!sorted){
+      sortColumns(_b->size(),
+		  CSRList_Nbr(a_),
+		  (INDEX_TYPE *) ptr_->array,
+		  (INDEX_TYPE *) jptr_->array, 
+		  (INDEX_TYPE *) ai_->array, 
+		  (double*) a_->array);
+    }
+    sorted = true;
+    
+    taucs_ccs_matrix myVeryCuteTaucsMatrix;
+    myVeryCuteTaucsMatrix.n = myVeryCuteTaucsMatrix.m =  _b->size();
+    //myVeryCuteTaucsMatrix.rowind = (INDEX_TYPE*)ptr_->array;
+    //myVeryCuteTaucsMatrix.colptr = (INDEX_TYPE*)ai_->array;
+    myVeryCuteTaucsMatrix.rowind = (INDEX_TYPE*)ai_->array;
+    myVeryCuteTaucsMatrix.colptr = (INDEX_TYPE*)jptr_->array;
+    myVeryCuteTaucsMatrix.values.d = (double*) a_->array;
+    myVeryCuteTaucsMatrix.flags = TAUCS_SYMMETRIC | TAUCS_LOWER | TAUCS_DOUBLE; 
+    
+    char* options[] = { "taucs.factor.LLT=true", NULL };  
+    int result = taucs_linsolve(&myVeryCuteTaucsMatrix, 
+				NULL, 
+				1, 
+				&(*_x)[0],
+				&(*_b)[0],
+				options,
+				NULL);                         
+    if (result != TAUCS_SUCCESS){
+      Msg::Error("Taucs Was Not Successfull %d",result);
+    }  
+    return 1;
+  }
+}
+#endif
diff --git a/Solver/linearSystemTAUCS.h b/Solver/linearSystemTAUCS.h
new file mode 100644
index 0000000000000000000000000000000000000000..73a43686bd1e5e382f797a664ce63fced449cce8
--- /dev/null
+++ b/Solver/linearSystemTAUCS.h
@@ -0,0 +1,34 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _LINEAR_SYSTEM_TAUCS_H_
+#define _LINEAR_SYSTEM_TAUCS_H_
+
+#include "linearSystemCSR.h"
+
+namespace gsolver {
+  template <class scalar>
+    class linearSystemCSRTaucs : public linearSystemCSR<scalar> {
+  private:
+  public:
+    linearSystemCSRTaucs()
+      {}
+    virtual ~linearSystemCSRTaucs()
+      {}
+    virtual void addToMatrix ( int il, int ic, double val) {
+      if (il <= ic)
+	linearSystemCSR<scalar>::addToMatrix(il,ic,val);
+    }
+
+    virtual int systemSolve() 
+#if defined(HAVE_TAUCS)
+;
+#else
+    {throw;}
+#endif
+  };
+}
+
+#endif
diff --git a/Solver/termOfFormulation.h b/Solver/termOfFormulation.h
new file mode 100644
index 0000000000000000000000000000000000000000..7eaa77d9593762cbeff3ee19ebcaa348e852afbe
--- /dev/null
+++ b/Solver/termOfFormulation.h
@@ -0,0 +1,137 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _TERM_OF_FORMULATION_H_
+#define _TERM_OF_FORMULATION_H_
+
+#include <math.h>
+#include <map>
+#include <vector>
+#include "GmshMatrix.h"
+#include "gmshFunction.h"
+#include "dofManager.h"
+#include "GModel.h"
+#include "MElement.h"
+
+namespace gsolver {
+  // a nodal finite element term : variables are always defined at nodes
+  // of the mesh
+  template<class dataVec, class dataMat>
+  class femTerm {
+  protected:
+    GModel *_gm;
+  public:
+    // return the number of columns of the element matrix
+    virtual int sizeOfC(MElement*) const = 0;
+    // return the number of rows of the element matrix
+    virtual int sizeOfR(MElement*) const = 0;
+    // in a given element, return the dof associated to a given row (column)
+    // of the local element matrix
+    virtual Dof getLocalDofR(MElement *e, int iRow) const = 0;
+    // default behavior : symmetric
+    virtual Dof getLocalDofC(MElement *e, int iCol) const
+    {getLocalDofR(e, iCol);}
+  public:
+    femTerm(GModel *gm) : _gm(gm) {}
+    virtual ~femTerm (){}
+    virtual void elementMatrix(MElement *e, gmshMatrix<dataMat> &m) const = 0;
+    virtual void elementVector(MElement *e, gmshVector<dataVec> &m) const {
+      m.scale(0.0);
+    }
+    void addToMatrix(dofManager<dataVec,dataMat> &dm, GEntity *ge) const
+    {
+      for(unsigned int i = 0; i < ge->getNumMeshElements(); i++){
+	MElement *e = ge->getMeshElement(i);
+	addToMatrix(dm, e);
+      }
+    }
+    void addToMatrix(dofManager<dataVec,dataMat> &dm, MElement *e) const
+    {
+      const int nbR = sizeOfR(e);
+      const int nbC = sizeOfC(e);
+      gmshMatrix<dataMat> localMatrix(nbR, nbC);
+      elementMatrix(e, localMatrix);
+      addToMatrix(dm, localMatrix, e);
+    }
+    void addToMatrix(dofManager<dataVec,dataMat> &dm, 
+		     gmshMatrix<dataMat> &localMatrix, 
+		     MElement *e) const
+    {
+      const int nbR = localMatrix.size1();
+      const int nbC = localMatrix.size2();
+      for (int j = 0; j < nbR; j++){
+	Dof R = getLocalDofR(e, j);
+	for (int k = 0; k < nbC; k++){
+	  Dof C = getLocalDofC(e, k);
+	  dm.assemble(R,C, localMatrix(j, k));
+	}
+      }
+    }
+    void dirichletNodalBC(int physical,
+			  int dim,
+			  int comp,
+			  int field,
+			  const gmshFunction<dataVec> &e,
+			  dofManager<dataVec,dataMat> &dm)
+    {
+      std::vector<MVertex *> v;
+      GModel *m = _gm;
+      m->getMeshVerticesForPhysicalGroup(dim, physical, v);
+      for (unsigned int i = 0; i < v.size(); i++)
+	dm.fixVertex(v[i], comp, field, e(v[i]->x(), v[i]->y(), v[i]->z()));
+    }
+    void neumannNodalBC(int physical,
+			int dim,
+			int comp,
+			int field,
+			const gmshFunction<dataVec> &e,
+			dofManager<dataVec,dataMat> &dm)
+    {
+      std::map<int, std::vector<GEntity*> > groups[4];
+      GModel *m = _gm;
+      m->getPhysicalGroups(groups);
+      std::map<int, std::vector<GEntity*> >::iterator it = groups[dim].find(physical);  
+      if (it == groups[dim].end()) return;
+      double jac[3][3];
+      double sf[256];
+      for (unsigned int i = 0; i < it->second.size(); ++i){
+	GEntity *ge = it->second[i];
+	for (unsigned int j = 0; j < ge->getNumMeshElements(); j++){
+	  MElement *e = ge->getMeshElement(j);
+	  int integrationOrder = 2 * e->getPolynomialOrder();
+	  int nbNodes = e->getNumVertices();
+	  int npts;
+	  IntPt *GP;
+	  e->getIntegrationPoints(integrationOrder, &npts, &GP);  
+	  for (int ip = 0; ip < npts; ip++){
+	    const double u = GP[ip].pt[0];
+	    const double v = GP[ip].pt[1];
+	    const double w = GP[ip].pt[2];
+	    const double weight = GP[ip].weight;
+	    const double detJ = e->getJacobian(u, v, w, jac);
+	    SPoint3 p; e->pnt(u, v, w, p);
+	    e->getShapeFunctions(u, v, w, sf);
+	    const dataVec FCT = fct(p.x(), p.y(), p.z());
+	    for (int k = 0; k < nbNodes; k++){
+	     dm.assemble(e->getVertex(k), comp, field, detJ * weight * sf[k] * FCT);
+	    }
+	  }
+	}
+      }
+    }
+    void addToRightHandSide (dofManager<dataVec,dataMat> &dm, GEntity *ge) const {
+      for(unsigned int i = 0; i < ge->getNumMeshElements(); i++){
+	MElement *e = ge->getMeshElement (i);
+	int nbR = sizeOfR(e);
+	gmshVector<dataVec> V (nbR);
+	elementVector (e, V);
+	// assembly
+	for (int j=0;j<nbR;j++)dm.assemble(getLocalDofR(e,j),V[j]);
+      }
+    }
+  }; // end of class definition
+}// end of namespace
+
+#endif