diff --git a/CMakeLists.txt b/CMakeLists.txt
index ec17db2c02c06df4bdbea44b14b782dec89410d6..19d637042ca2d547001748b3f8545301b2deac2b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -74,6 +74,7 @@ set(GMSH_API
     Mesh/meshGFaceDelaunayInsertion.h
   Post/PView.h Post/PViewData.h Plugin/PluginManager.h
   Graphics/drawContext.h
+  Solver/dofManager.h Solver/elasticityTerm.h Solver/termOfFormulation.h 
   contrib/kbipack/gmp_normal_form.h contrib/kbipack/gmp_matrix.h 
     contrib/kbipack/gmp_blas.h
   contrib/DiscreteIntegration/DILevelset.h)
@@ -476,19 +477,21 @@ if(ENABLE_MED OR ENABLE_CGNS)
 endif(ENABLE_MED OR ENABLE_CGNS)
 
 if(ENABLE_TAUCS)
-  find_library(TAUCS_LIB taucs)
+  find_library(TAUCS_LIB taucs PATHS ENV CASROOT 
+               PATH_SUFFIXES lib)
   if(TAUCS_LIB)
+   find_path(TAUCS_INC "taucs.h" PATHS ENV CASROOT PATH_SUFFIXES src 
+              include)
+   if(TAUCS_INC)
     set(HAVE_TAUCS TRUE)
     list(APPEND CONFIG_OPTIONS "Taucs")
     list(APPEND EXTERNAL_LIBRARIES ${TAUCS_LIB})
+    list(APPEND EXTERNAL_INCLUDES ${TAUCS_INC})
+   endif(TAUCS_INC)
   endif(TAUCS_LIB)
 endif(ENABLE_TAUCS)
 
-if(ENABLE_SOLVER)
-  add_subdirectory(Solver)
-  set(HAVE_SOLVER TRUE)
-  list(APPEND CONFIG_OPTIONS "Solver")
-endif(ENABLE_SOLVER)
+add_subdirectory(Solver)
 
 if(ENABLE_OCC)
   if(WIN32)
@@ -621,7 +624,7 @@ if(EXTERNAL_INCLUDES)
 endif(EXTERNAL_INCLUDES)
 
 # we could specify include dirs more selectively, but this is simpler
-include_directories(Common Fltk Geo Graphics Mesh Numeric Parser Plugin
+include_directories(Common Fltk Geo Graphics Mesh Solver Numeric Parser Plugin
   Post Qt contrib/ANN/include contrib/Chaco/main contrib/DiscreteIntegration
   contrib/MathEx contrib/Metis contrib/NativeFileChooser contrib/Netgen 
   contrib/Netgen/libsrc/include contrib/Netgen/libsrc/interface
diff --git a/Mesh/gmshSmoothHighOrder.cpp b/Mesh/gmshSmoothHighOrder.cpp
index 27da5e0937268030cf9371e601e350d149e98129..5bf38803ce60b4caa38fa9f21b3914090d0a2ce2 100644
--- a/Mesh/gmshSmoothHighOrder.cpp
+++ b/Mesh/gmshSmoothHighOrder.cpp
@@ -17,15 +17,14 @@
 #include "HighOrder.h"
 #include "meshGFaceOptimize.h"
 #include "gmshSmoothHighOrder.h"
-#include "gmshAssembler.h"
-#include "gmshLaplace.h"
-#include "gmshElasticity.h"
-#include "gmshLinearSystemGmm.h"
-#include "gmshLinearSystemCSR.h"
 #include "GFace.h"
 #include "GRegion.h"
 #include "Context.h"
 #include "Numeric.h"
+#include "dofManager.h"
+#include "elasticityTerm.h"
+#include "linearSystemTAUCS.h"
+#include "linearSystemGMM.h"
 
 #define SQU(a)      ((a)*(a))
 
@@ -44,6 +43,17 @@ static double shapeMeasure(MElement *e)
   return d1;
 }
 
+double angle3Points(MVertex *p1, MVertex *p2, MVertex *p3)
+{
+  SVector3 a(p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z());
+  SVector3 b(p3->x() - p2->x(), p3->y() - p2->y(), p3->z() - p2->z());
+  SVector3 c = crossprod(a, b);
+  double sinA = c.norm();
+  double cosA = dot(a, b);
+  //  printf("%d %d %d -> %g %g\n",p1->iD,p2->iD,p3->iD,cosA,sinA);
+  return atan2 (sinA, cosA);  
+}
+
 void gmshHighOrderSmoother::moveTo(MVertex *v,  
                                    const std::map<MVertex*, SVector3> &m) const
 {
@@ -98,7 +108,7 @@ struct p2data{
          gmshHighOrderSmoother *_s)
     : gf(_gf), t1(_t1), t2(_t2), n12(_n12), s(_s)
   {
-    gmshElasticityTerm el(0, 1.e3, .3333);
+    gsolver::elasticityTerm el(0, 1.e3, .3333,1);
     s->moveToStraightSidedLocation(t1);
     s->moveToStraightSidedLocation(t2);
     m1 = new  gmshMatrix<double>(3 * t1->getNumVertices(),
@@ -126,7 +136,7 @@ struct pNdata{
          gmshHighOrderSmoother *_s)
     : gf(_gf), t1(_t1), t2(_t2), n(_n), s(_s)
   {
-    gmshElasticityTerm el(0, 1.e3, .3333);
+    gsolver::elasticityTerm el(0, 1.e3, .3333,1);
     s->moveToStraightSidedLocation(t1);
     s->moveToStraightSidedLocation(t2);
     m1 = new  gmshMatrix<double>(3 * t1->getNumVertices(),
@@ -418,12 +428,16 @@ void gmshHighOrderSmoother::computeMetricVector(GFace *gf,
 
 void gmshHighOrderSmoother::smooth_metric(std::vector<MElement*>  & all, GFace *gf)
 {
-  gmshLinearSystemGmm<double> *lsys = new gmshLinearSystemGmm<double>;
+#ifdef HAVE_TAUCS__
+  gsolver::linearSystemCSRTaucs<double> *lsys = new gsolver::linearSystemCSRTaucs<double>;
+#else
+  gsolver::linearSystemCSRGmm<double> *lsys = new gsolver::linearSystemCSRGmm<double>;
   lsys->setNoisy(1);
   lsys->setGmres(1);
-  lsys->setPrec(1.e-9);
-  gmshAssembler<double> myAssembler(lsys);
-  gmshElasticityTerm El(0, 1.0, .333, getTag());
+  lsys->setPrec(5.e-8);
+#endif
+  gsolver::dofManager<double,double> myAssembler(lsys);
+  gsolver::elasticityTerm El(0, 1.0, .333, getTag());
   
   std::vector<MElement*> layer, v;
 
@@ -528,9 +542,9 @@ void gmshHighOrderSmoother::smooth_metric(std::vector<MElement*>  & all, GFace *
 
 double gmshHighOrderSmoother::smooth_metric_(std::vector<MElement*>  & v, 
                                              GFace *gf, 
-                                             gmshAssembler<double> &myAssembler,
+                                             gsolver::dofManager<double,double> &myAssembler,
                                              std::set<MVertex*> &verticesToMove,
-                                             gmshElasticityTerm &El)
+                                             gsolver::elasticityTerm &El)
 {
   std::set<MVertex*>::iterator it;
 
@@ -558,15 +572,13 @@ double gmshHighOrderSmoother::smooth_metric_(std::vector<MElement*>  & v,
       for (int j = 0; j < n2; j++){
         MVertex *vR;
         int iCompR, iFieldR;
-        El.getLocalDofR(e, j, &vR, &iCompR, &iFieldR);
-        myAssembler.assemble(vR, iCompR, iFieldR,-R2(j));
+	gsolver::Dof RDOF = El.getLocalDofR(e, j);
+        myAssembler.assemble(RDOF,-R2(j));
         for (int k = 0; k < n2; k++){
           MVertex *vC;
           int iCompC, iFieldC;
-          El.getLocalDofC(e, k, &vC, &iCompC, &iFieldC);
-          myAssembler.assemble(vR, iCompR, iFieldR, 
-                               vC, iCompC, iFieldC, 
-                               K22(j, k));
+          gsolver::Dof CDOF = El.getLocalDofC(e, k);
+          myAssembler.assemble(RDOF,CDOF,K22(j, k));
         }
       }
     }
@@ -594,12 +606,16 @@ double gmshHighOrderSmoother::smooth_metric_(std::vector<MElement*>  & v,
 
 void gmshHighOrderSmoother::smooth(std::vector<MElement*> &all)
 {
-  gmshLinearSystemCSRGmm<double> *lsys = new gmshLinearSystemCSRGmm<double>;
+#ifdef HAVE_TAUCS
+  gsolver::linearSystemCSRTaucs<double> *lsys = new gsolver::linearSystemCSRTaucs<double>;
+#else
+  gsolver::linearSystemCSRGmm<double> *lsys = new gsolver::linearSystemCSRGmm<double>;
   lsys->setNoisy(1);
   lsys->setGmres(1);
   lsys->setPrec(5.e-8);
-  gmshAssembler<double> myAssembler(lsys);
-  gmshElasticityTerm El(0, 1.0, .333, getTag());
+#endif
+  gsolver::dofManager<double,double> myAssembler(lsys);
+  gsolver::elasticityTerm El(0, 1.0, .333, getTag());
   
   std::vector<MElement*> layer, v;
   double minD;
@@ -681,7 +697,8 @@ void gmshHighOrderSmoother::smooth(std::vector<MElement*> &all)
 
     // assembly of the elasticity term on the
     // set of elements
-    El.addToMatrix(myAssembler, v);
+    for (int i=0;i<v.size();i++)
+      El.addToMatrix(myAssembler, v[i]);
     
     // solve the system
     lsys->systemSolve();
@@ -1297,557 +1314,3 @@ void  gmshHighOrderSmoother::smooth_pNpoint(GFace *gf)
 }
 
 
-////////////////////////////////////////////////////////////////////////////////
-// OLD STUFF : STILL USED ?
-////////////////////////////////////////////////////////////////////////////////
-
-bool straightLine(std::vector<MVertex*> &l, MVertex *n1, MVertex *n2)
-{
-  // x = a * t + b
-  // x1 = b
-  // x2 = a + b
-  for(unsigned int i = 0; i < l.size(); i++){
-    MVertex *v = l[i];
-    double b = n1->x();
-    double a = n2->x() - b;
-    double t = (v->x() - b) / a;
-    double by = n1->y();
-    double ay = n2->y() - by;
-    double y = ay * t + by;
-    if(fabs(y-v->y()) > 1.e-07 * CTX::instance()->lc){
-      return false;      
-    }
-  }
-  return true;
-}
-
-void getMinMaxJac (MTriangle *t, double &minJ, double &maxJ)
-{
-  double mat[2][3];  
-  int n = 3;
-  t->getPrimaryJacobian(0, 0, 0, mat);
-   //t->getJacobian(0, 0, 0, mat);
-  double v1[3] = {mat[0][0], mat[0][1], mat[0][2]};
-  double v2[3] = {mat[1][0], mat[1][1], mat[1][2]};
-  double normal1[3], normal[3];
-  prodve(v1, v2, normal1);
-  double nn = sqrt(SQU(normal1[0]) + SQU(normal1[1]) + SQU(normal1[2]));
-  for(int i = 0; i < n; i++){
-    for(int k = 0; k < n - i; k++){
-      t->getJacobian((double)i / (n - 1), (double)k / (n - 1), 0, mat);
-      double v1b[3] = {mat[0][0], mat[0][1], mat[0][2]};
-      double v2b[3] = {mat[1][0], mat[1][1], mat[1][2]};
-      prodve(v1b, v2b, normal);
-      double sign; 
-      prosca(normal1, normal, &sign);
-      double det = norm3(normal) * (sign > 0 ? 1. : -1.) / nn;
-      minJ = std::min(1. / det, std::min(det, minJ));
-      maxJ = std::max(det, maxJ);
-    }
-  }
-}
-
-struct smoothVertexDataHO{
-  MVertex *v;
-  GFace *gf;
-  std::vector<MTriangle*> ts;
-}; 
-
-struct smoothVertexDataHON{
-  std::vector<MVertex*> v;
-  GFace *gf;
-  std::vector<MTriangle*> ts;
-}; 
-
-double smoothing_objective_function_HighOrder(double U, double V, MVertex *v, 
-                                              std::vector<MTriangle*> &ts, GFace *gf)
-{
-  GPoint gp = gf->point(U, V);
-  const double oldX = v->x();
-  const double oldY = v->y();
-  const double oldZ = v->z();
-
-  v->x() = gp.x();
-  v->y() = gp.y();
-  v->z() = gp.z();
-
-  double minJ =  1.e22;
-  double maxJ = -1.e22;
-  for (unsigned int i = 0; i < ts.size(); i++){
-    getMinMaxJac (ts[i], minJ, maxJ);
-  }
-  v->x() = oldX;
-  v->y() = oldY;
-  v->z() = oldZ;
-  
-  return -minJ;
-}
-
-
-void deriv_smoothing_objective_function_HighOrder(double U, double V, 
-                                                  double &F, double &dFdU,
-                                                  double &dFdV, void *data)
-{
-  smoothVertexDataHO *svd = (smoothVertexDataHO*)data;
-  MVertex *v = svd->v;
-  const double LARGE = -1.e5;
-  const double SMALL = 1./LARGE;
-  F   = smoothing_objective_function_HighOrder(U, V, v, svd->ts, svd->gf);
-  double F_U = smoothing_objective_function_HighOrder(U + SMALL, V, v, svd->ts, svd->gf);
-  double F_V = smoothing_objective_function_HighOrder(U, V + SMALL, v, svd->ts, svd->gf);
-  dFdU = (F_U - F) * LARGE;
-  dFdV = (F_V - F) * LARGE;
-}
-
-double smooth_obj_HighOrder(double U, double V, void *data)
-{
-  smoothVertexDataHO *svd = (smoothVertexDataHO*)data;
-  return  smoothing_objective_function_HighOrder(U, V, svd->v, svd->ts, svd->gf); 
-}
-
-double smooth_obj_HighOrderN(double *uv, void *data)
-{
-  smoothVertexDataHON *svd = (smoothVertexDataHON*)data;
-  double oldX[10],oldY[10],oldZ[10];
-  for (unsigned int i = 0; i < svd->v.size(); i++){
-    GPoint gp = svd->gf->point(uv[2 * i], uv[2 * i + 1]);
-    oldX[i] = svd->v[i]->x();
-    oldY[i] = svd->v[i]->y();
-    oldZ[i] = svd->v[i]->z();
-    svd->v[i]->x() = gp.x();
-    svd->v[i]->y() = gp.y();
-    svd->v[i]->z() = gp.z();
-  }
-  double minJ =  1.e22;
-  double maxJ = -1.e22;
-  for(unsigned int i = 0; i < svd->ts.size(); i++){
-    getMinMaxJac (svd->ts[i], minJ, maxJ);
-  }
-  for(unsigned int i = 0; i < svd->v.size(); i++){
-    svd->v[i]->x() = oldX[i];
-    svd->v[i]->y() = oldY[i];
-    svd->v[i]->z() = oldZ[i];
-  }
-  return -minJ;
-}
-
-void deriv_smoothing_objective_function_HighOrderN(double *uv, double *dF, 
-                                                   double &F, void *data)
-{
-  const double LARGE = -1.e2;
-  const double SMALL = 1. / LARGE;
-  smoothVertexDataHON *svd = (smoothVertexDataHON*)data;
-  F = smooth_obj_HighOrderN(uv, data);
-  for (unsigned int i = 0; i < svd->v.size(); i++){
-    uv[i] += SMALL;
-    dF[i] = (smooth_obj_HighOrderN(uv, data) - F) * LARGE;
-    uv[i] -= SMALL;
-  }
-}
-
-void optimizeNodeLocations(GFace *gf, smoothVertexDataHON &vdN, double eps = .2)
-{
-  if(!vdN.v.size()) return;
-  double uv[20];
-  for (unsigned int i = 0; i < vdN.v.size(); i++){
-    if (!vdN.v[i]->getParameter(0, uv[2 * i])){
-      Msg::Error("Node location optimization failed");
-      return;
-    }
-    if (!vdN.v[i]->getParameter(1, uv[2 * i + 1])){
-      Msg::Error("Node location optimization failed");
-      return;
-    }
-  }
-
-  double F = -smooth_obj_HighOrderN(uv, &vdN);
-  if (F < eps){
-    Msg::Error("Fletcher-Reeves minimizer routine must be reimplemented");
-    // double val = 0.;
-    //minimize_N(2 * vdN.v.size(), smooth_obj_HighOrderN, 
-    //          deriv_smoothing_objective_function_HighOrderN, 
-    //          &vdN, 1, uv, val);
-    double Fafter = -smooth_obj_HighOrderN(uv, &vdN);
-    printf("%12.5E %12.5E\n", F, Fafter);
-    if (F < Fafter){
-      for (unsigned int i = 0; i < vdN.v.size(); i++){
-        vdN.v[i]->setParameter(0, uv[2 * i]);
-        vdN.v[i]->setParameter(1, uv[2 * i + 1]);
-        GPoint gp = gf->point(uv[2 * i], uv[2 * i + 1]);
-        vdN.v[i]->x() = gp.x();
-        vdN.v[i]->y() = gp.y();
-        vdN.v[i]->z() = gp.z();
-      }
-    }     
-  }
-}
-
-double angle3Points(MVertex *p1, MVertex *p2, MVertex *p3)
-{
-  SVector3 a(p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z());
-  SVector3 b(p3->x() - p2->x(), p3->y() - p2->y(), p3->z() - p2->z());
-  SVector3 c = crossprod(a, b);
-  double sinA = c.norm();
-  double cosA = dot(a, b);
-  //  printf("%d %d %d -> %g %g\n",p1->iD,p2->iD,p3->iD,cosA,sinA);
-  return atan2 (sinA, cosA);  
-}
-
-// A curvilinear edge smooth and swap
-
-typedef std::map<std::pair<MVertex*, MVertex*>, std::vector<MElement*> > edge2tris;
-
-void localHarmonicMapping(GModel *gm, 
-                          MTriangle *t1 , 
-                          MTriangle *t2,
-                          MVertex *n1,
-                          MVertex *n2,
-                          MVertex *n3,
-                          MVertex *n4,
-//                        SPoint2 &np1,
-//                        SPoint2 &np2,
-//                        SPoint2 &np3,
-//                        SPoint2 &np4,
-                          std::vector<MVertex*> &e1,
-                          std::vector<MVertex*> &e2,
-                          std::vector<MVertex*> &e3,
-                          std::vector<MVertex*> &e4,
-//                        std::vector<SPoint2> &ep1,
-//                        std::vector<SPoint2> &ep2,
-//                        std::vector<SPoint2> &ep3,
-//                        std::vector<SPoint2> &ep4
-                          std::vector<MVertex*> &e) {
-  
-  gmshLinearSystemGmm<double> *lsys = new gmshLinearSystemGmm<double>;
-  gmshAssembler<double> myAssembler(lsys);
-  gmshFunction<double> f(1.0);
-  gmshLaplaceTerm Laplace(gm, &f, 0);
-  
-  myAssembler.fixVertex ( n1 , 0 , 0 , -1.0);
-  myAssembler.fixVertex ( n2 , 0 , 0 , -1.0);
-  myAssembler.fixVertex ( n3 , 0 , 0 ,  1.0);
-  myAssembler.fixVertex ( n4 , 0 , 0 ,  1.0);
-  for (unsigned int i = 0; i < e1.size(); i++) myAssembler.fixVertex(e1[i], 0, 0, -1.0);
-  for (unsigned int i = 0; i < e3.size(); i++) myAssembler.fixVertex(e3[i], 0, 0,  1.0);
-  Laplace.addToMatrix(myAssembler,t1); 
-  Laplace.addToMatrix(myAssembler,t2);   
-  lsys->systemSolve();
-
-  gmshLinearSystemGmm<double> *lsys1 = new gmshLinearSystemGmm<double>;
-  gmshAssembler<double> myAssembler1(lsys1);
-  gmshLaplaceTerm Laplace1(gm, &f, 1);
-  
-  myAssembler1.fixVertex ( n2 , 0 , 1 , -1.0);
-  myAssembler1.fixVertex ( n3 , 0 , 1 , -1.0);
-  myAssembler1.fixVertex ( n4 , 0 , 1 ,  1.0);
-  myAssembler1.fixVertex ( n1 , 0 , 1 ,  1.0);
-  for (unsigned int i = 0; i < e2.size(); i++) myAssembler1.fixVertex(e2[i], 0, 1, -1.0);
-  for (unsigned int i = 0; i < e4.size(); i++) myAssembler1.fixVertex(e4[i], 0, 1,  1.0);  
-  Laplace1.addToMatrix(myAssembler1,t1); 
-  Laplace1.addToMatrix(myAssembler1,t2);   
-  lsys1->systemSolve();
-
-  // now we have the stable high order harmonic mapping 
-  // we have to find points locations of vertices in e
-  // that have coordinates (\xi, \xi) 
-
-  // this can be done by evaluating the 
-
-  for (unsigned int i = 0; i < e.size();  i++){
-    MVertex *v = e[i];
-    const double U =  myAssembler.getDofValue  (v, 0 ,0);
-    const double V =  myAssembler1.getDofValue (v, 0 ,1);
-    printf("point %g %g -> %g %g\n",v->x(),v->y(),U,V);
-    // we are in t1
-    //if (U >= V){
-    //const double ut = U;
-    //}
-  }
-
-
-  delete lsys ;  
-  delete lsys1;  
-}
-
-void optimizeHighOrderMeshInternalNodes(GFace *gf)
-{
-  for(unsigned int i = 0; i < gf->triangles.size(); i++){
-    MTriangle *t = gf->triangles[i];
-    smoothVertexDataHON vdN;
-    int start = t->getNumVertices() - t->getNumFaceVertices();
-    for (int j=start;j<t->getNumVertices();j++)
-      vdN.v.push_back(t->getVertex(j));
-    vdN.gf = gf;
-    vdN.ts.push_back(t);
-    optimizeNodeLocations(gf, vdN, .9);
-  }
-}
-
-bool optimizeHighOrderMesh(GFace *gf, edgeContainer &edgeVertices)
-{
-  v2t_cont adjv;
-  buildVertexToTriangle(gf->triangles, adjv);
-
-  typedef std::map<std::pair<MVertex*, MVertex*>, std::vector<MElement*> > edge2tris;
-  edge2tris e2t;
-  for(unsigned int i = 0; i < gf->triangles.size(); i++){
-    MTriangle *t = gf->triangles[i];
-    for(int j = 0; j < t->getNumEdges(); j++){
-      MEdge edge = t->getEdge(j);
-      std::pair<MVertex*, MVertex*> p(edge.getMinVertex(), edge.getMaxVertex());
-      e2t[p].push_back(t);
-    }
-  }
-
-  for(edge2tris::iterator it = e2t.begin(); it != e2t.end(); ++it){
-    std::pair<MVertex*, MVertex*> edge = it->first;
-    std::vector<MVertex*> e;
-    std::vector<MElement*> triangles = it->second;
-    if(triangles.size() == 2){
-      MVertex *n2 = edge.first; 
-      MVertex *n4 = edge.second;
-      MTriangle *t1 = (MTriangle*)triangles[0];
-      MTriangle *t2 = (MTriangle*)triangles[1];
-      if(n2 < n4)
-        e = edgeVertices[std::make_pair<MVertex*, MVertex*> (n2, n4)];
-      else
-        e = edgeVertices[std::make_pair<MVertex*, MVertex*> (n4, n2)];
-
-      if (e.size() < 5){
-        smoothVertexDataHON vdN;
-        vdN.v = e;
-        vdN.gf = gf;
-        vdN.ts.clear();
-        vdN.ts.push_back(t1);
-        vdN.ts.push_back(t2);   
-        optimizeNodeLocations(gf, vdN);
-      }
-    }
-  }
-
-  return true;
-}
-
-static void parametricCoordinates(MVertex *v, GFace *gf, double &uu, double &vv)
-{
-  SPoint2 param;
-  reparamMeshVertexOnFace(v, gf, param);
-  uu = param[0];
-  vv = param[1];
-}
-
-static void getParametricCoordnates ( GFace *gf, 
-                                      std::vector<MVertex*> &e,
-                                      std::vector<SPoint2> &param)
-{
-  param.clear();
-  for (unsigned int i = 0; i < e.size(); i++){
-    double U,V;
-    parametricCoordinates(e[i] , gf, U, V); 
-    param.push_back(SPoint2(U,V));
-  }
-}
-
-static void curvilinearEdgeSwap (GFace *gf, 
-                                 //                              int nPts,
-                                 edgeContainer &edgeVertices,
-                                 edge2tris::iterator &it,
-                                 edge2tris &e2t)
-{
-  std::pair<MVertex*, MVertex*> edge = it->first;
-  std::vector<MElement*> triangles   = it->second;
-  if(triangles.size() == 2){
-      MVertex *n2 = edge.first; 
-      MVertex *n4 = edge.second;
-      MTriangle *t1 = (MTriangle*)triangles[0];
-      MTriangle *t2 = (MTriangle*)triangles[1];
-      MVertex *n1 = t1->getOtherVertex(n2, n4);
-      MVertex *n3 = t2->getOtherVertex(n2, n4);
-      std::vector<MVertex*> e1 = edgeVertices[std::make_pair<MVertex*, MVertex*>(std::min(n1, n2),std::max(n1, n2))];
-      std::vector<MVertex*> e2 = edgeVertices[std::make_pair<MVertex*, MVertex*>(std::min(n2, n3),std::max(n2, n3))];
-      std::vector<MVertex*> e3 = edgeVertices[std::make_pair<MVertex*, MVertex*>(std::min(n3, n4),std::max(n3, n4))];
-      std::vector<MVertex*> e4 = edgeVertices[std::make_pair<MVertex*, MVertex*>(std::min(n4, n1),std::max(n4, n1))];
-      std::vector<MVertex*> e  = edgeVertices[std::make_pair<MVertex*, MVertex*>(std::min(n2, n4),std::max(n2, n4))];
-      //      std::vector<MVertex*> enew; 
-      //      MLine temp (n1,n3);
-      // should not add the nodes n the GFace here
-      //      getEdgeVertices(gf,&temp, enew, false, nPts);
-      // get the parametric coordinates of the 
-      std::vector<SPoint2> ep1;  getParametricCoordnates (gf,e1,ep1);
-      std::vector<SPoint2> ep2;  getParametricCoordnates (gf,e2,ep2);
-      std::vector<SPoint2> ep3;  getParametricCoordnates (gf,e3,ep3);
-      std::vector<SPoint2> ep4;  getParametricCoordnates (gf,e4,ep4);
-      std::vector<SPoint2> ep;  getParametricCoordnates (gf,e ,ep );
-      //      std::vector<SPoint2> epnew;  getParametricCoordnates (gf,enew,epnew);      
-      localHarmonicMapping(gf->model(),t1,t2,n1,n2,n3,n4,e1,e2,e3,e4,e); 
-  }
-}
-
-bool smoothInternalEdgesb(GFace *gf, edgeContainer &edgeVertices)
-{
-  typedef std::map<std::pair<MVertex*, MVertex*>, std::vector<MElement*> > edge2tris;
-  edge2tris e2t;
-  for(unsigned int i = 0; i < gf->triangles.size(); i++){
-    MTriangle *t = gf->triangles[i];
-    for(int j = 0; j < t->getNumEdges(); j++){
-      MEdge edge = t->getEdge(j);
-      std::pair<MVertex*, MVertex*> p(edge.getMinVertex(), edge.getMaxVertex());
-      e2t[p].push_back(t);
-    }
-  }
-
-  for(edge2tris::iterator it = e2t.begin(); it != e2t.end(); ++it){
-    curvilinearEdgeSwap (gf,edgeVertices,it,e2t);
-  }
-  return true;
-}
-
-bool smoothInternalEdges(GFace *gf, edgeContainer &edgeVertices)
-{
-  typedef std::map<std::pair<MVertex*, MVertex*>, std::vector<MElement*> > edge2tris;
-  edge2tris e2t;
-  for(unsigned int i = 0; i < gf->triangles.size(); i++){
-    MTriangle *t = gf->triangles[i];
-    for(int j = 0; j < t->getNumEdges(); j++){
-      MEdge edge = t->getEdge(j);
-      std::pair<MVertex*, MVertex*> p(edge.getMinVertex(), edge.getMaxVertex());
-      e2t[p].push_back(t);
-    }
-  }
-
-  bool success = false;
-
-  const int NBST = 10;
-
-  for(edge2tris::iterator it = e2t.begin(); it != e2t.end(); ++it){
-    std::pair<MVertex*, MVertex*> edge = it->first;
-    std::vector<MVertex*> e1, e2, e3, e4, e;
-    std::vector<MElement*> triangles = it->second;
-    if(triangles.size() == 2){
-      MVertex *n2 = edge.first; 
-      MVertex *n4 = edge.second;
-      MTriangle *t1 = (MTriangle*)triangles[0];
-      MTriangle *t2 = (MTriangle*)triangles[1];
-      MVertex *n1 = t1->getOtherVertex(n2, n4);
-      MVertex *n3 = t2->getOtherVertex(n2, n4);
-      
-      double ang1 = angle3Points(n1,n2,n3);
-      double ang2 = angle3Points(n2,n3,n4);
-      double ang3 = angle3Points(n3,n4,n1);
-      double ang4 = angle3Points(n4,n1,n2);
-      const double angleLimit = 3*M_PI/4.;
-
-      if (ang1 < angleLimit && ang2 < angleLimit && ang3 < angleLimit && ang4 < angleLimit){
-        if(n1 < n2)
-          e1 = edgeVertices[std::make_pair<MVertex*, MVertex*>(n1, n2)];
-        else
-          e1 = edgeVertices[std::make_pair<MVertex*, MVertex*>(n2, n1)];
-        if(n2 < n3)
-          e2 = edgeVertices[std::make_pair<MVertex*, MVertex*>(n2, n3)];
-        else
-          e2 = edgeVertices[std::make_pair<MVertex*, MVertex*>(n3, n2)];
-        if(n3 < n4)
-          e3 = edgeVertices[std::make_pair<MVertex*, MVertex*>(n3, n4)];
-        else
-          e3 = edgeVertices[std::make_pair<MVertex*, MVertex*>(n4, n3)];
-        if(n4 < n1)
-          e4 = edgeVertices[std::make_pair<MVertex*, MVertex*>(n4, n1)];
-        else
-          e4 = edgeVertices[std::make_pair<MVertex*, MVertex*>(n1, n4)];
-        if(n2 < n4)
-          e = edgeVertices[std::make_pair<MVertex*, MVertex*>(n2, n4)];
-        else
-          e = edgeVertices[std::make_pair<MVertex*, MVertex*>(n4, n2)];
-        
-        if((!straightLine(e1, n1, n2) || !straightLine(e2, n2, n3) ||
-            !straightLine(e3, n3, n4) || !straightLine(e4, n4, n1))){
-          
-          double Unew[NBST][10],Vnew[NBST][10];
-          double Xold[10],Yold[10],Zold[10];
-          
-          for(unsigned int i = 0; i < e.size(); i++){
-            Xold[i] = e[i]->x();
-            Yold[i] = e[i]->y();
-            Zold[i] = e[i]->z();
-          }
-          
-          double minJ = 1.e22;
-          double maxJ = -1.e22;       
-          getMinMaxJac (t1, minJ, maxJ);
-          getMinMaxJac (t2, minJ, maxJ);
-          int kopt = -1; 
-          for (int k=0;k<NBST;k++){
-            double relax = (k+1)/(double)NBST;
-            for(unsigned int i = 0; i < e.size(); i++){
-              double v = (double)(i + 1) / (e.size() + 1);
-              double u = 1. - v;
-              MVertex *vert  = (n2 < n4) ? e[i] : e[e.size() - i - 1];
-              MVertex *vert1 = (n1 < n2) ? e1[e1.size() - i - 1] : e1[i];
-              MVertex *vert3 = (n3 < n4) ? e3[i] : e3[e3.size() - i - 1];
-              MVertex *vert4 = (n4 < n1) ? e4[e4.size() - i - 1] : e4[i];
-              MVertex *vert2 = (n2 < n3) ? e2[i] : e2[e2.size() - i - 1];           
-              double U1,V1,U2,V2,U3,V3,U4,V4,U,V,nU1,nV1,nU2,nV2,nU3,nV3,nU4,nV4;
-              parametricCoordinates(vert , gf, U, V);
-              parametricCoordinates(vert1, gf, U1, V1);
-              parametricCoordinates(vert2, gf, U2, V2);
-              parametricCoordinates(vert3, gf, U3, V3);
-              parametricCoordinates(vert4, gf, U4, V4);
-              parametricCoordinates(n1, gf, nU1, nV1);
-              parametricCoordinates(n2, gf, nU2, nV2);
-              parametricCoordinates(n3, gf, nU3, nV3);
-              parametricCoordinates(n4, gf, nU4, nV4);
-              
-              Unew[k][i] = U + relax * ((1.-u) * U4 + u * U2 +
-                                        (1.-v) * U1 + v * U3 -
-                                        ((1.-u)*(1.-v) * nU1 
-                                         + u * (1.-v) * nU2 
-                                         + u * v * nU3 
-                                         + (1.-u) * v * nU4) - U);
-              Vnew[k][i] = V + relax * ((1.-u) * V4 + u * V2 +
-                                        (1.-v) * V1 + v * V3 -
-                                        ((1.-u)*(1.-v) * nV1 
-                                         + u * (1.-v) * nV2 
-                                         + u * v * nV3 
-                                         + (1.-u) * v * nV4) - V);
-              GPoint gp = gf->point(Unew[k][i],Vnew[k][i]);
-              vert->x() = gp.x();
-              vert->y() = gp.y();
-              vert->z() = gp.z();
-            }
-            double minJloc = 1.e22;
-            double maxJloc = -1.e22;          
-            getMinMaxJac(t1, minJloc, maxJloc);
-            getMinMaxJac(t2, minJloc, maxJloc);
-            //    printf("relax = %g min %g max %g\n",relax,minJloc,maxJloc);
-            
-            if (minJloc > minJ){
-              kopt = k;
-              minJ = minJloc;
-            }
-          }
-          //    kopt = 1;
-          if (kopt == -1){
-            for(unsigned int i = 0; i < e.size(); i++){
-              e[i]->x() = Xold[i];
-              e[i]->y() = Yold[i];
-              e[i]->z() = Zold[i];
-            }      
-          }
-          else{
-            success = true;
-            for(unsigned int i = 0; i < e.size(); i++){
-              MVertex *vert  = (n2 < n4) ? e[i] : e[e.size() - i - 1];
-              vert->setParameter(0,Unew[kopt][i]);
-              vert->setParameter(1,Vnew[kopt][i]);
-              GPoint gp = gf->point(Unew[kopt][i],Vnew[kopt][i]);
-              vert->x() = gp.x();
-              vert->y() = gp.y();
-              vert->z() = gp.z();
-            }      
-          }
-        }
-      }
-    }
-  }    
-  return success;
-}
diff --git a/Mesh/gmshSmoothHighOrder.h b/Mesh/gmshSmoothHighOrder.h
index 998b761162c45ce7af9cf5f32e103f35486d7a08..00d549f03cf157f9de0559da5ca97118601cd473 100644
--- a/Mesh/gmshSmoothHighOrder.h
+++ b/Mesh/gmshSmoothHighOrder.h
@@ -10,13 +10,13 @@
 #include <vector>
 #include "SVector3.h"
 #include "GmshMatrix.h"
+#include "dofManager.h"
+#include "elasticityTerm.h"
 
 class MVertex;
 class MElement;
 class GFace;
 class GRegion;
-template<class T> class gmshAssembler;
-class gmshElasticityTerm;
 
 class gmshHighOrderSmoother 
 {
@@ -38,9 +38,9 @@ public:
   }  
   void smooth ( std::vector<MElement*> & );
   double smooth_metric_ ( std::vector<MElement*> &, GFace *gf,
-                          gmshAssembler<double> &myAssembler,
+                          gsolver::dofManager<double,double> &myAssembler,
                           std::set<MVertex*> &verticesToMove,
-                          gmshElasticityTerm &El);
+                          gsolver::elasticityTerm &El);
   void smooth_metric ( std::vector<MElement*> &, GFace *gf );
   void smooth ( GFace* , bool metric = false);
   void smooth_p2point ( GFace* );
diff --git a/Numeric/gmshLinearSystemCSR.cpp b/Numeric/gmshLinearSystemCSR.cpp
index d43f67887359b071b0728ab9e89961cf9e13145c..a435c03ebc0bd64d20752b4b8e37bda648b39f6e 100644
--- a/Numeric/gmshLinearSystemCSR.cpp
+++ b/Numeric/gmshLinearSystemCSR.cpp
@@ -334,32 +334,3 @@ int gmshLinearSystemCSRGmm<double>::checkSystem()
 }
 #endif
 
-#if defined(HAVE_TAUCS)
-#include "taucs.h"
-template<>
-int gmshLinearSystemCSRTaucs<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*)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
index 735d6139aa71e5d4916b994e9ad6b7e19d31fe44..0256182a76c14962af4474584aeb0da9359a045f 100644
--- a/Numeric/gmshLinearSystemCSR.h
+++ b/Numeric/gmshLinearSystemCSR.h
@@ -159,23 +159,4 @@ class gmshLinearSystemCSRGmm : public gmshLinearSystemCSR<scalar> {
 
 };
 
-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");
-    return 0;
-  }
-#endif
-};
-
 #endif
diff --git a/Solver/dofManager.h b/Solver/dofManager.h
index f3fda9a1869e5ab4b028a85d27120cacaa0ab9f5..be55ad186c0ddc6c70ab2e963858008e8846c18a 100644
--- a/Solver/dofManager.h
+++ b/Solver/dofManager.h
@@ -73,7 +73,7 @@ namespace gsolver {
   private:
   public:
     dofManager(linearSystem<dataMat> *l) : _current(l){
-      _linearSystems["default"]= l;
+      _linearSystems["A"]= l;
     }
     inline void fixDof(long int ent, int type, const dataVec & value)
     {
diff --git a/Solver/linearSystemCSR.cpp b/Solver/linearSystemCSR.cpp
index 5817c1aacffa687112ae16de3e25c3d65a2708cc..5405999d17bcaa3ae5bdaeb7000c5af9f2b184bf 100644
--- a/Solver/linearSystemCSR.cpp
+++ b/Solver/linearSystemCSR.cpp
@@ -13,6 +13,7 @@
 #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;
@@ -74,7 +75,7 @@ namespace gsolver {
     }
   }
   
-  void CSRList_Add(CSRList_T *liste, void *data)
+  void CSRList_Add(gsolver::CSRList_T *liste, void *data)
   {
     liste->n++;
     
diff --git a/Solver/linearSystemTAUCS.cpp b/Solver/linearSystemTAUCS.cpp
index 4101ca97900c0a8b0561726a51a349259f2d4c2a..b767a37dca9b003af66b219b218dc18cb2fa2250 100644
--- a/Solver/linearSystemTAUCS.cpp
+++ b/Solver/linearSystemTAUCS.cpp
@@ -24,7 +24,7 @@ namespace gsolver {
 		   scalar *a);
   
   template<>
-  int linearSystemCSRTaucs_<double>::systemSolve()
+  int linearSystemCSRTaucs<double>::systemSolve()
   {
     if(!sorted){
       sortColumns(_b->size(),
@@ -46,6 +46,7 @@ namespace gsolver {
     myVeryCuteTaucsMatrix.flags = TAUCS_SYMMETRIC | TAUCS_LOWER | TAUCS_DOUBLE; 
     
     char* options[] = { "taucs.factor.LLT=true", NULL };  
+    Msg::Info("TAUCS solves %d unknowns", _b->size());
     int result = taucs_linsolve(&myVeryCuteTaucsMatrix, 
 				NULL, 
 				1,