diff --git a/Numeric/gmshLinearSystemCSR.cpp b/Numeric/gmshLinearSystemCSR.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b5defc796c031548d7d23a04fceb76db1ebc6bc0
--- /dev/null
+++ b/Numeric/gmshLinearSystemCSR.cpp
@@ -0,0 +1,345 @@
+#include "GmshConfig.h"
+#include "GmshMessage.h"
+#include "gmshLinearSystemCSR.h"
+
+#define SWAP(a,b)  temp=(a);(a)=(b);(b)=temp;
+#define SWAPI(a,b) tempi=(a);(a)=(b);(b)=tempi;
+
+// #if defined(HAVE_TAUCS)
+// #include "taucs.h"
+// #endif
+
+// #if defined(HAVE_GMM)
+// #include <gmm.h>
+// #include <gmm_interface.h>
+// #endif
+
+
+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 gmshLinearSystemCSR<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 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"
+template<>
+int gmshLinearSystemCSRGmm<double> :: systemSolve()
+{
+  sortColumns(_b->size(),
+	      CSRList_Nbr(a_),
+	      (INDEX_TYPE *) ptr_->array,
+	      (INDEX_TYPE *) jptr_->array, 
+	      (INDEX_TYPE *) ai_->array, 
+	      (double*) a_->array);
+  sorted = true;
+
+  //  for (int i=0;i<_b->size();i++)
+  //    printf("%d ",((INDEX_TYPE *) jptr_->array)[i]);
+  //  printf("\n");
+
+  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
+
+#if defined(HAVE_TAUCSw)
+#include "taucs.h"
+template<>
+int gmshLinearSystemCSRTaucs<double> :: systemSolve()
+{
+  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*)jptr_->array;
+  myVeryCuteTaucsMatrix.colptr = (INDEX_TYPE*)ai_->array;
+  myVeryCuteTaucsMatrix.values.d = (double*) a_->array;
+  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");
+  }  
+  return 1;
+}
+#endif
diff --git a/Numeric/gmshLinearSystemCSR.h b/Numeric/gmshLinearSystemCSR.h
new file mode 100644
index 0000000000000000000000000000000000000000..2b8a1fb5438c5713d3c091c6b6e876f1f8f33105
--- /dev/null
+++ b/Numeric/gmshLinearSystemCSR.h
@@ -0,0 +1,169 @@
+// 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 _GMSH_LINEAR_SYSTEM_TAUCS_H_
+#define _GMSH_LINEAR_SYSTEM_TAUCS_H_
+
+// Interface to TAUCS
+
+#include "GmshConfig.h"
+#include "GmshMessage.h"
+#include "gmshLinearSystem.h"
+
+#include <vector>
+
+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 gmshLinearSystemCSR : public gmshLinearSystem<scalar> {
+ protected:
+  bool sorted;
+  char *something;
+  CSRList_T *a_,*ai_,*ptr_,*jptr_; 
+  std::vector<scalar> *_b, *_x;
+ public:
+  gmshLinearSystemCSR()
+  : a_(0),sorted(false) {}
+  virtual bool isAllocated() const { return a_ != 0; }
+  virtual void allocate(int) ;
+  virtual ~gmshLinearSystemCSR()
+  {
+    allocate(0);
+  }
+  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 (il == 0)  printf("NOT FOUND %d %d %d\n",il,ic,n);
+    
+    if(!something[il]) {
+      jptr[il] = n;
+      something[il] = 1;      
+    }
+    else ptr[position_] = n;
+
+/*     for (int i=0;i<_b->size();i++)printf("%d ",something[i]?jptr[i]:-1); */
+/*     printf("\n"); */
+/*     for (int i=0;i<CSRList_Nbr(ai_);i++)printf("(%d %d %g)",ai[i],ptr[i],a[i]); */
+/*     printf("\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 gmshLinearSystemCSRGmm : public gmshLinearSystemCSR<scalar> {
+ private:
+  double _prec;
+  int _noisy, _gmres;
+ public:
+  gmshLinearSystemCSRGmm()
+    : _prec(1.e-8), _noisy(0), _gmres(0) {}
+  virtual ~gmshLinearSystemCSRGmm()
+    {}
+  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");
+  }
+#endif
+};
+
+template <class scalar>
+class gmshLinearSystemCSRTaucs : public gmshLinearSystemCSR<scalar> {
+ private:
+ public:
+  gmshLinearSystemCSRTaucs()
+    {}
+  virtual ~gmshLinearSystemCSRTaucs()
+    {}
+  virtual int systemSolve() 
+#if defined(HAVE_TAUCS)
+    ;
+#else
+  {
+    Msg::Error("Taucs is not available in this version of Gmsh");
+  }
+#endif
+};
+
+
+#endif