diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp
index 5268a3148653124b18f7145947c62dd075efe57b..60eb285d8e0e556db72ddb30381bc8edf1ab75d4 100644
--- a/Common/CommandLine.cpp
+++ b/Common/CommandLine.cpp
@@ -59,6 +59,7 @@ void PrintUsage(const char *name)
   Msg::Direct("  -1, -2, -3            Perform 1D, 2D or 3D mesh generation, then exit");
   Msg::Direct("  -refine               Perform uniform mesh refinement, then exit");
   Msg::Direct("  -part int             Partition after batch mesh generation");
+  Msg::Direct("  -renumber             Renumber the mesh elements after batch mesh generation");
   Msg::Direct("  -saveall              Save all elements (discard physical group definitions)");
   Msg::Direct("  -o file               Specify mesh output file name");
   Msg::Direct("  -format string        Set output mesh format (msh, msh1, msh2, unv, vrml, stl, mesh,");
@@ -170,10 +171,15 @@ void GetOptions(int argc, char *argv[])
         CTX::instance()->batch = 5;
         i++;
       }
+      else if(!strcmp(argv[i] + 1, "renumber")) {
+        CTX::instance()->batchAfterMesh = 1;
+	CTX::instance()->partitionOptions.renumber = 1;
+        i++;
+      }
       else if(!strcmp(argv[i] + 1, "part")) {
         i++;
         if(argv[i]){
-          CTX::instance()->batchAfterMesh = 1;
+	  CTX::instance()->batchAfterMesh =1 ;
           opt_mesh_partition_num(0, GMSH_SET, atoi(argv[i++]));
         }
         else
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index ae9e4b86c40ed71cbdae59eb6978ee2b2b1ac84b..fca933aaf72b6ab082fc8680f25fdf9860688d40 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -1109,7 +1109,7 @@ StringXNumber MeshOptions_Number[] = {
     "Number of hexahedra in the current mesh (read-only)" },
   { F, "NbNodes" , opt_mesh_nb_nodes , 0. , 
     "Number of nodes in the current mesh (read-only)" },
-  { F|O, "NbPartitions" , opt_mesh_partition_num, 4. ,
+  { F|O, "NbPartitions" , opt_mesh_partition_num, 1. ,
     "Number of partitions" },
   { F, "NbPrisms" , opt_mesh_nb_prisms , 0. , 
     "Number of prisms in the current mesh (read-only)" },
diff --git a/Common/Gmsh.cpp b/Common/Gmsh.cpp
index cbcb48aa248e40e56061e086b7361d30c50a0c82..25d5fe73b46005fc0ef35ba886e66a4a987abd1e 100644
--- a/Common/Gmsh.cpp
+++ b/Common/Gmsh.cpp
@@ -169,8 +169,10 @@ int GmshBatch()
     else if(CTX::instance()->batch == 5)
       RefineMesh(GModel::current(), CTX::instance()->mesh.secondOrderLinear);
 #if defined(HAVE_CHACO) || defined(HAVE_METIS)
-    if(CTX::instance()->batchAfterMesh == 1)
-      PartitionMesh(GModel::current(), CTX::instance()->partitionOptions);
+    if(CTX::instance()->batchAfterMesh == 1){
+      if (CTX::instance()->partitionOptions.num_partitions > 1)PartitionMesh(GModel::current(), CTX::instance()->partitionOptions);
+      if (CTX::instance()->partitionOptions.renumber)RenumberMesh(GModel::current(), CTX::instance()->partitionOptions);
+    }
 #endif
 #endif
     CreateOutputFile(CTX::instance()->outputFileName, CTX::instance()->mesh.format);
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index 4d2f3fde2ee2040ee621a9939f4c8dca633d2723..25f0f3cc864a4ef75b6ffd56d80b824e6cbbd731 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -1234,7 +1234,7 @@ void deMeshGFace::operator() (GFace *gf)
   gf->meshStatistics.nbTriangle = gf->meshStatistics.nbEdge = 0;
 }
 
-const int debugSurface = -1;
+int debugSurface = -1;
 
 void meshGFace::operator() (GFace *gf)
 {
diff --git a/Mesh/meshPartition.cpp b/Mesh/meshPartition.cpp
index 3b9cf5e2385764cf721d3ef234d1baa709a22da9..246839dbe3b98760407b0fcb9d14488795880ab0 100644
--- a/Mesh/meshPartition.cpp
+++ b/Mesh/meshPartition.cpp
@@ -52,6 +52,7 @@ extern "C" void METIS_PartGraphRecursive
 extern "C" void METIS_PartGraphKway
 (int *, idxtype *, idxtype *, idxtype *, idxtype *, int *, int *, int *, int *,
  int *, idxtype *);
+extern "C" void METIS_NodeND(int *n,int *xadj,int *adjncy,int *numflag,int *options,int *perm,int *iperm);
 
 
 /*==============================================================================
@@ -112,6 +113,34 @@ void MakeGraphDIM(const EntIter begin, const EntIter end,
 
 
 
+int RenumberMesh(GModel *const model, meshPartitionOptions &options, std::vector<MElement*> &numbered)
+{
+
+  Graph graph;
+  BoElemGrVec boElemGrVec;
+  int ier;
+  Msg::StatusBar(1, true, "Building graph...");
+  ier = MakeGraph(model, graph, &boElemGrVec);
+  Msg::StatusBar(1, true, "Renumbering graph...");
+  if(!ier) ier = RenumberGraph(graph, options);
+  if(ier) {
+    Msg::StatusBar(1, false, "Mesh");
+    return 1;
+  }
+
+  // create the numbering
+  numbered.clear();
+  const int n = graph.getNumVertex();
+  numbered.resize(n);
+  for(int i = 0; i != n; ++i) {
+    numbered[graph.partition[i]-1] = graph.element[i];
+  }
+
+  Msg::Info("Renumbering complete");
+  Msg::StatusBar(1, false, "Mesh");
+  return 0;
+}
+
 int PartitionMeshElements(std::vector<MElement*> &elements, meshPartitionOptions &options)
 {
   GModel *tmp_model = new GModel();
@@ -153,6 +182,80 @@ int PartitionMeshFace(std::list<GFace*> &cFaces, meshPartitionOptions &options)
   delete tmp_model;
   return 1;
 }
+int RenumberMeshElements( std::vector<MElement*> &elements, meshPartitionOptions &options ){
+  if (elements.size() < 3)return 1;
+  GModel *tmp_model = new GModel();
+  std::set<MVertex *> setv;
+  for (unsigned i=0;i<elements.size();++i)
+    for (int j=0;j<elements[i]->getNumVertices();j++)
+      setv.insert(elements[i]->getVertex(j));
+  if (elements[0]->getDim() == 2){
+    GFace *gf = new discreteFace(tmp_model, 1);
+    for (std::set<MVertex* >::iterator it = setv.begin(); it != setv.end(); it++)
+      gf->mesh_vertices.push_back(*it);
+    for (std::vector<MElement* >::iterator it = elements.begin(); it != elements.end(); it++){
+      if ((*it)->getType() == TYPE_TRI) 
+	gf->triangles.push_back((MTriangle*)(*it));
+      else if  ((*it)->getType() == TYPE_QUA) 
+	gf->quadrangles.push_back((MQuadrangle*)(*it));
+    }
+    tmp_model->add(gf);
+    RenumberMesh(tmp_model,options,elements);    
+    tmp_model->remove(gf);
+  }
+  else if (elements[0]->getDim() == 3){
+    GFace *gf = new discreteFace(tmp_model, 1);
+    for (std::set<MVertex* >::iterator it = setv.begin(); it != setv.end(); it++)
+      gf->mesh_vertices.push_back(*it);
+    for (std::vector<MElement* >::iterator it = elements.begin(); it != elements.end(); it++){
+      if ((*it)->getType() == TYPE_TRI) 
+	gf->triangles.push_back((MTriangle*)(*it));
+      else if  ((*it)->getType() == TYPE_QUA) 
+	gf->quadrangles.push_back((MQuadrangle*)(*it));
+    }
+    tmp_model->add(gf);
+  }
+  delete tmp_model;
+  return 1;
+}
+
+int RenumberMesh(GModel *const model, meshPartitionOptions &options)  
+{
+  
+  for (GModel::fiter it = model->firstFace() ; it != model->lastFace() ; ++it){
+    std::vector<MElement *> temp;
+
+    temp.insert(temp.begin(),(*it)->triangles.begin(),(*it)->triangles.end());
+    RenumberMeshElements (temp,options);
+    (*it)->triangles.clear();
+    for (int i=0;i<temp.size();i++) (*it)->triangles.push_back((MTriangle*)temp[i]);
+    
+    temp.clear();
+
+    temp.insert(temp.begin(),(*it)->quadrangles.begin(),(*it)->quadrangles.end());
+    RenumberMeshElements (temp,options);
+    (*it)->quadrangles.clear();
+    for (int i=0;i<temp.size();i++) (*it)->quadrangles.push_back((MQuadrangle*)temp[i]);
+  }
+  for (GModel::riter it = model->firstRegion() ; it != model->lastRegion() ; ++it){
+    std::vector<MElement *> temp;
+
+    temp.insert(temp.begin(),(*it)->tetrahedra.begin(),(*it)->tetrahedra.end());
+    RenumberMeshElements (temp,options);
+    (*it)->tetrahedra.clear();
+    for (int i=0;i<temp.size();i++) (*it)->tetrahedra.push_back((MTetrahedron*)temp[i]);
+
+    temp.clear();
+
+    temp.insert(temp.begin(),(*it)->hexahedra.begin(),(*it)->hexahedra.end());
+    RenumberMeshElements (temp,options);
+    (*it)->hexahedra.clear();
+    for (int i=0;i<temp.size();i++) (*it)->hexahedra.push_back((MHexahedron*)temp[i]);
+  }
+  return 1;
+}
+
+
 
 int PartitionMesh(GModel *const model, meshPartitionOptions &options)
 {
@@ -325,7 +428,7 @@ int PartitionGraph(Graph &graph, meshPartitionOptions &options)
              &options.num_partitions, metisOptions, &edgeCut,
              &graph.partition[graph.section[iSec]]);
           break;
-        }
+	}
       }
       catch(...) {
         Msg::Error("METIS threw an exception");
@@ -343,6 +446,41 @@ int PartitionGraph(Graph &graph, meshPartitionOptions &options)
   return ier;
 }
 
+int RenumberGraph(Graph &graph, meshPartitionOptions &options)
+{
+  int ier = 0;
+#ifdef HAVE_METIS
+  {
+    Msg::Info("Launching METIS graph renumberer");
+    // "C" numbering for Metis
+    {
+      int *p = &graph.adjncy[0];  //**Sections
+      for(int n = graph.adjncy.size(); n--;) --(*p++);
+    }
+    try {
+      int n = graph.getNumVertex();
+      int numflag = 0;
+      const int iSec = 0;
+      int options = 0;
+      int *perm = new int[n];
+      METIS_NodeND(&n, 
+		   &graph.xadj[graph.section[iSec]],
+		   &graph.adjncy[graph.section[iSec]], &numflag,&options,perm,&graph.partition[graph.section[iSec]]);
+      delete [] perm;
+    }
+    catch(...) {
+      Msg::Error("METIS threw an exception");
+      ier = 2;
+    }
+    // Number elements from 1
+    if(!ier) {
+      int *p = &graph.partition[0];  //**Sections
+      for(int n = graph.getNumVertex(); n--;) ++(*p++);
+    }
+  }
+#endif
+  return ier;
+}
 
 /*******************************************************************************
  *
diff --git a/Mesh/meshPartition.h b/Mesh/meshPartition.h
index ac97f350f873233139c7702a1727b302a32ce2ad..240e9e4b50330e8b7523f97b97922875cf86b5b6 100644
--- a/Mesh/meshPartition.h
+++ b/Mesh/meshPartition.h
@@ -23,7 +23,9 @@ struct meshPartitionOptions;
  ******************************************************************************/
 
 int PartitionGraph(Graph &graph, meshPartitionOptions &options);
+int RenumberGraph(Graph &graph, meshPartitionOptions &options);
 int PartitionMesh(GModel *const model, meshPartitionOptions &options);
+int RenumberMesh(GModel *const model, meshPartitionOptions &options);
 int PartitionMeshFace(std::list<GFace*> &cFaces, meshPartitionOptions &options);
 int PartitionMeshElements(std::vector<MElement*> &elements, meshPartitionOptions &options);
 bool PartitionZeroGenus(std::list<GFace*> &cFaces, int &nbParts);
diff --git a/Mesh/meshPartitionOptions.h b/Mesh/meshPartitionOptions.h
index 4488a8baa5387c4bd8525a8715bc11e102987e1b..05406a7715b44f5f4d547cdd2a0e7558da7c29de 100644
--- a/Mesh/meshPartitionOptions.h
+++ b/Mesh/meshPartitionOptions.h
@@ -14,6 +14,8 @@ struct meshPartitionOptions
                                         // 2 - METIS
   int num_partitions;
 
+  int renumber;
+
   bool createPartitionBoundaries;
 
 //--Chaco
@@ -82,7 +84,8 @@ struct meshPartitionOptions
   void setDefaults()
   {
     partitioner = 2;
-    num_partitions = 4;
+    num_partitions = 1;
+    renumber = 0;
     global_method = 1;
     architecture = 1;
     ndims_tot = 2;
diff --git a/Numeric/fullMatrix.h b/Numeric/fullMatrix.h
index c17881309e0edc37854c0eff365569d9ccd1aaca..dcbb2416a9aa5230eed6b3b68813879020b77d68 100644
--- a/Numeric/fullMatrix.h
+++ b/Numeric/fullMatrix.h
@@ -88,6 +88,12 @@ class fullVector
     }
     printf("\n");
   }
+  void binarySave (FILE *f) const{
+    fwrite (_data,sizeof(scalar),_r,f); 
+  }
+  void binaryLoad (FILE *f){
+    fread (_data,sizeof(scalar),_r,f); 
+  }
 };
 
 template <class scalar>
diff --git a/Solver/TESTCASES/CylinderEddies.lua b/Solver/TESTCASES/CylinderEddies.lua
new file mode 100644
index 0000000000000000000000000000000000000000..cd73f5cf70b3b8a22126b1ed28576d79de2aa293
--- /dev/null
+++ b/Solver/TESTCASES/CylinderEddies.lua
@@ -0,0 +1,79 @@
+MACH = .05;
+RHO  = 1.0;
+PRES = 1./(MACH*RHO*RHO*1.4*1.4) 
+V = 1.0 
+SOUND = V/MACH
+
+--[[ 
+     Function for initial conditions
+--]]
+function free_stream( XYZ, FCT )
+  for i=0,XYZ:size1()-1 do
+    FCT:set(i,0,RHO) 
+    FCT:set(i,1,RHO*V) 
+    FCT:set(i,2,0.0) 
+    FCT:set(i,3, 0.5*RHO*V*V+PRES/0.4) 
+  end
+end
+
+--[[ 
+     Example of a lua program driving the DG code
+--]]
+
+order = 3
+
+FS = functionLua(4, 'free_stream', {'XYZ'}):getName()
+
+-- diffusivity
+mu=fullMatrix(1,1);
+mu:set(0,0,0.03)
+kappa=fullMatrix(1,1);
+kappa:set(0,0,0.03)
+
+print'*** Loading the mesh and the model ***'
+myModel   = GModel  ()
+myModel:load ('cyl.geo')	
+myModel:load ('cyl.msh')
+
+print'*** Create a dg solver ***'
+DG = dgSystemOfEquations (myModel)
+DG:setOrder(order)
+law=dgPerfectGasLaw2d()
+
+law:setViscosityAndThermalConductivity(functionConstant(mu):getName(),functionConstant(kappa):getName());
+
+DG:setConservationLaw(law)
+law:addBoundaryCondition('Cylinder',law:newNonSlipWallBoundary())
+law:addBoundaryCondition('Box'     ,law:newOutsideValueBoundary(FS))
+
+DG:setup()
+
+print'*** setting the initial solution ***'
+
+DG:L2Projection(FS)
+
+--print'*** export ***'
+
+DG:exportSolution('output/cyl_0')
+
+print'*** solve ***'
+
+CFL = 2.1;
+dt = CFL * DG:computeInvSpectralRadius();
+print('DT = ',dt)
+T = 0;
+for i=1,10000 do
+    dt = CFL * DG:computeInvSpectralRadius();    
+    norm = DG:RK44(dt)
+    T = T + dt
+    if (i % 1 == 0) then 
+       print('*** ITER ***',i,norm,dt,T)
+    end
+    if (i % 100 == 0) then 
+       DG:exportSolution(string.format("output/cyl-%06d", i)) 
+    end
+end
+
+print'*** done ***'
+
+
diff --git a/Solver/TESTCASES/RayleighTaylor.lua b/Solver/TESTCASES/RayleighTaylor.lua
new file mode 100644
index 0000000000000000000000000000000000000000..f58f88d7762b500864b89a6165e864a1292a835b
--- /dev/null
+++ b/Solver/TESTCASES/RayleighTaylor.lua
@@ -0,0 +1,103 @@
+ATWOOD = .5
+RHO1 = 1.0
+RHO2 = RHO1 * (1.+ATWOOD)/(1.-ATWOOD) 
+taper  = 6.0
+--Mach number of perturbation
+machnum =0.1              
+GAMMA = 1.4
+-- Min speed of sound is at top where p=1, rho=2 
+epsilon_z= machnum * math.sqrt(GAMMA*1.0/2.0)
+epsilon_xy= -epsilon_z*taper/16.0    
+BANDWIDTH = 0.005;
+PI = 3.14159
+
+--[[ 
+     Function for initial conditions
+--]]
+function initial_condition( XYZ, FCT )
+  for i=0,XYZ:size1()-1 do
+    X = XYZ:get(i,0)-.125
+    Y = XYZ:get(i,1)
+    RHO = 1;
+    if Y > 0.0 then
+      RHO = 2
+    end
+-- smooth version
+    RHO = 1.0 + (math.atan (Y/BANDWIDTH) / PI + 0.5)
+
+    PRES = 2 - RHO*Y;
+    vx = epsilon_xy * math.sin(X/0.25 * 2*PI) * math.cos(Y*PI) * math.pow(math.cos(Y*PI),taper-1.0);
+    vy = epsilon_z  * math.cos(X/0.25 * 2*PI) * math.pow(math.cos(Y*PI),taper);
+    FCT:set(i,0,RHO) 
+    FCT:set(i,1,RHO*vx) 
+    FCT:set(i,2,RHO*vy) 
+    FCT:set(i,3, 0.5*RHO*(vx*vx+vy*vy)+PRES/0.4) 
+  end
+end
+
+--[[ 
+     Example of a lua program driving the DG code
+--]]
+
+order = 4
+print'*** Loading the mesh and the model ***'
+myModel   = GModel  ()
+ myModel:load ('rect.geo')	
+if (order == 1) then
+   myModel:load ('rect.msh')
+elseif (order == 2) then
+   myModel:load ('rect2.msh')
+elseif (order == 3) then
+   myModel:load ('rect2.msh')
+elseif (order == 4) then
+   myModel:load ('rect4.msh')
+end
+
+print'*** Create a dg solver ***'
+DG = dgSystemOfEquations (myModel)
+DG:setOrder(order)
+law=dgPerfectGasLaw2d()
+
+g=fullMatrix(4,1);
+g:set(0,0,0)
+g:set(1,0,0)
+g:set(2,0,-1.)
+g:set(3,0,0)
+
+law:setSource(functionConstant(g):getName())
+DG:setConservationLaw(law)
+law:addBoundaryCondition('Walls',law:newSlipWallBoundary())
+FS = functionLua(4, 'initial_condition', {'XYZ'}):getName()
+law:addBoundaryCondition('Top',law:newOutsideValueBoundary(FS))
+
+DG:setup()
+
+print'*** setting the initial solution ***'
+
+DG:L2Projection(FS)
+DG:limitSolution()
+
+--print'*** export ***'
+
+DG:exportSolution('output/rt_0')
+
+print'*** solve ***'
+
+LC = 0.1*.1
+dt = .0003;
+print('DT=',dt)
+
+for i=1,10000 do
+--    norm = DG:RK44_limiter(dt)
+    norm = DG:RK44(dt)
+    if (i % 10 == 0) then 
+       print('*** ITER ***',i,norm)
+    end
+    if (i % 100 == 0) then 
+       DG:exportSolution(string.format("output/rt-%06d", i)) 
+    end
+end
+
+print'*** done ***'
+
+
diff --git a/Solver/TESTCASES/cyl.geo b/Solver/TESTCASES/cyl.geo
new file mode 100644
index 0000000000000000000000000000000000000000..efd6f094efcc21fcfb8cdd95d2e2d96b2bcd9706
--- /dev/null
+++ b/Solver/TESTCASES/cyl.geo
@@ -0,0 +1,25 @@
+a = .1;
+b = .5;
+Point(1) = {0, 0, 0, a};
+Point(2) = {1, 0, 0, a};
+Point(3) = {-1, 0, 0, a};
+Point(4) = {0, 1, 0, a};
+Point(5) = {0, -1, 0, a};
+Point(6) = {-5, -5, 0, b};
+Point(7) = {-5, 5, 0, b};
+Point(8) = {15, 5, 0, b};
+Point(9) = {15, -5, 0, b};
+Circle(1) = {4, 1, 2};
+Circle(2) = {2, 1, 5};
+Circle(3) = {5, 1, 3};
+Circle(4) = {3, 1, 4};
+Line(5) = {7, 8};
+Line(6) = {8, 9};
+Line(7) = {9, 6};
+Line(8) = {6, 7};
+Line Loop(9) = {6, 7, 8, 5};
+Line Loop(10) = {1, 2, 3, 4};
+Plane Surface(11) = {9, 10};
+Physical Surface("Air") = {11};
+Physical Line("Cylinder") = {4, 1, 2, 3};
+Physical Line("Box") = {5, 6, 7, 8};
diff --git a/Solver/TESTCASES/rect.geo b/Solver/TESTCASES/rect.geo
new file mode 100644
index 0000000000000000000000000000000000000000..7deb863a25bf03481ba53710aa435a9b9be0b603
--- /dev/null
+++ b/Solver/TESTCASES/rect.geo
@@ -0,0 +1,25 @@
+Point(1) = {-.125, 0, 0, .05};
+Point(2) = {.125, 0, 0, .05};
+Point(3) = {.125, .5, 0, .05};
+Point(4) = {-.125, .5, 0, .05};
+Point(5) = {-.125, -.5, 0, .05};
+Point(6) = {.125, -.5, 0, .05};
+Line(1) = {5, 1};
+Line(2) = {1, 2};
+Line(3) = {2, 6};
+Line(4) = {6, 5};
+Line(5) = {1, 4};
+Line(6) = {4, 3};
+Line(7) = {3, 2};
+Line Loop(8) = {7, -2, 5, 6};
+Plane Surface(9) = {8};
+Line Loop(10) = {3, 4, 1, 2};
+Plane Surface(11) = {10};
+Physical Surface("sprut") = {11, 9};
+Physical Line("Walls") = {5, 7, 3, 4, 1};
+Physical Line("Top") = {6};
+Transfinite Line {5, 7, 1, 3} = 100 Using Progression 1;
+Transfinite Line {6, 4, 2} = 50 Using Progression 1;
+Transfinite Surface {9} Alternated;
+Transfinite Surface {11} Alternated;
+Recombine Surface {9, 11};
diff --git a/Solver/dgAlgorithm.cpp b/Solver/dgAlgorithm.cpp
index a86a0d4305f7da8090feaf1670215968bcee8253..24a9de318ef0394b1b952c03ca66c3fd8403f57d 100644
--- a/Solver/dgAlgorithm.cpp
+++ b/Solver/dgAlgorithm.cpp
@@ -9,6 +9,7 @@
 #include "MEdge.h"
 #include "function.h"
 #include "dgLimiter.h"
+#include "meshPartition.h"
 
 /*
   compute 
@@ -62,6 +63,7 @@ void dgAlgorithm::residualVolume ( //dofManager &dof, // the DOF manager (maybe
   for (int iElement=0 ; iElement<group.getNbElements() ;++iElement) {
     // ----- 2.3.1 --- build a small object that contains elementary solution, jacobians, gmsh element
     solutionQPe.setAsProxy(solutionQP, iElement*nbFields, nbFields );
+    
     if(gradientSolutionQPe.somethingDependOnMe()){
       dPsiDx.setAsProxy(group.getDPsiDx(),iElement*group.getNbNodes(),group.getNbNodes());
       dofs.setAsProxy(solution, nbFields*iElement, nbFields);
@@ -86,7 +88,7 @@ void dgAlgorithm::residualVolume ( //dofManager &dof, // the DOF manager (maybe
               if(convectiveFlux)
                 fuvwe(iPt,k) += ( (*convectiveFlux)(iPt,iXYZ*nbFields+k)) * factor;
               if(diffusiveFlux){
-                fuvwe(iPt,k) += ( (*diffusiveFlux)(iPt,iXYZ*nbFields+k)) * factor;
+		fuvwe(iPt,k) += ( (*diffusiveFlux)(iPt,iXYZ*nbFields+k)) * factor;
               }
             }
           }
@@ -202,7 +204,7 @@ void dgAlgorithm::residualInterface ( //dofManager &dof, // the DOF manager (may
       dPsiRightDx.mult(dofsRight, gradientSolutionRight.set());
     }
 
-    // B3 ) compute fluxes
+    // B3 ) compute fluxes    
     if (diffusiveFluxLeft) {
       for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) {
         const double detJ = group.getDetJ (iFace, iPt);
@@ -211,9 +213,9 @@ void dgAlgorithm::residualInterface ( //dofManager &dof, // the DOF manager (may
         const fullMatrix<double> &dfr = (*diffusiveFluxRight)();
         for (int k=0;k<nbFields;k++) { 
           double meanNormalFlux =
-              ((dfl(iPt,k*3  )+dfr(iPt,k*3  )) * normals(0,iPt)
-              +(dfl(iPt,k*3+1)+dfr(iPt,k*3+1)) * normals(1,iPt)
-              +(dfl(iPt,k*3+2)+dfr(iPt,k*3+2)) * normals(2,iPt))/2;
+              ((dfl(iPt,k+nbFields*0 )+dfr(iPt,k+nbFields*0)) * normals(0,iPt)
+              +(dfl(iPt,k+nbFields*1 )+dfr(iPt,k+nbFields*1)) * normals(1,iPt)
+              +(dfl(iPt,k+nbFields*2 )+dfr(iPt,k+nbFields*2)) * normals(2,iPt))/2;
           double minl = std::min(group.getElementVolumeLeft(iFace),
                                  group.getElementVolumeRight(iFace)
                                 )/group.getInterfaceSurface(iFace);
@@ -467,6 +469,7 @@ void dgAlgorithm::residualBoundary ( //dofManager &dof, // the DOF manager (mayb
 				     )
 { 
   int nbFields = claw.nbFields();
+  int nbNodesLeft = group.getGroupLeft().getNbNodes();
   const dgBoundaryCondition *boundaryCondition = claw.getBoundaryCondition(group.getBoundaryTag());
   // ----- 1 ----  get the solution at quadrature points
   fullMatrix<double> solutionQP (group.getNbIntegrationPoints(),group.getNbElements() * nbFields);
@@ -475,33 +478,73 @@ void dgAlgorithm::residualBoundary ( //dofManager &dof, // the DOF manager (mayb
   fullMatrix<double> NormalFluxQP ( group.getNbIntegrationPoints(), group.getNbElements()*nbFields);
 
   dataCacheMap cacheMapLeft(group.getNbIntegrationPoints());
+  fullMatrix<double> &DPsiLeftDx = group.getDPsiLeftDxMatrix();
   // provided dataCache
   dataCacheDouble &uvw=cacheMapLeft.provideData("UVW");
   dataCacheDouble &solutionQPLeft = cacheMapLeft.provideData("Solution");
+  dataCacheDouble &gradientSolutionLeft = cacheMapLeft.provideData("SolutionGradient");
   dataCacheDouble &normals = cacheMapLeft.provideData("Normals");
   dataCacheElement &cacheElementLeft = cacheMapLeft.getElement();
+  gradientSolutionLeft.set(fullMatrix<double>(group.getNbIntegrationPoints()*3,nbFields));
   // required data
+  // inviscid
   dataCacheDouble *boundaryTerm = boundaryCondition->newBoundaryTerm(cacheMapLeft);
-  fullMatrix<double> normalFluxQP;
+  // viscous
+  dataCacheDouble *diffusiveFluxLeft = claw.newDiffusiveFlux(cacheMapLeft);
+  dataCacheDouble *maximumDiffusivityLeft = claw.newMaximumDiffusivity(cacheMapLeft);
+  dataCacheDouble *neumann   = boundaryCondition->newDiffusiveNeumannBC(cacheMapLeft);
+  dataCacheDouble *dirichlet = boundaryCondition->newDiffusiveDirichletBC(cacheMapLeft);
+
+  fullMatrix<double> normalFluxQP,dPsiLeftDx,dofsLeft;
+
+  int p = group.getGroupLeft().getOrder();
+  int dim = group.getGroupLeft().getElement(0)->getDim();
 
   for (int iFace=0 ; iFace<group.getNbElements() ;++iFace) {
     normalFluxQP.setAsProxy(NormalFluxQP, iFace*nbFields, nbFields);
     // ----- 2.3.1 --- provide the data to the cacheMap
     solutionQPLeft.setAsProxy(solutionQP, iFace*nbFields, nbFields);
     normals.setAsProxy(group.getNormals(),iFace*group.getNbIntegrationPoints(),group.getNbIntegrationPoints());
+    // proxies needed to compute the gradient of the solution and the IP term
+    dPsiLeftDx.setAsProxy(DPsiLeftDx,iFace*nbNodesLeft,nbNodesLeft);
+    dofsLeft.setAsProxy(solutionLeft, nbFields*group.getElementLeftId(iFace), nbFields);
+
     uvw.setAsProxy(group.getIntegrationOnElementLeft(iFace));
     cacheElementLeft.set(group.getElementLeft(iFace));
 
-    // ----- 2.3.2 --- compute fluxes
+    // compute the gradient of the solution
+    if(gradientSolutionLeft.somethingDependOnMe()){
+      dPsiLeftDx.mult(dofsLeft, gradientSolutionLeft.set());
+    }
+
+    // ----- 2.3.2 --- compute inviscid contribution
     for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) {
       const double detJ = group.getDetJ (iFace, iPt);
       for (int k=0;k<nbFields;k++)
         normalFluxQP(iPt,k) = (*boundaryTerm)(iPt,k)*detJ;
     }
+
+    if (diffusiveFluxLeft) {
+      for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) {
+        const double detJ = group.getDetJ (iFace, iPt);
+        //just for the lisibility :
+        for (int k=0;k<nbFields;k++) { 
+          double minl = group.getElementVolumeLeft(iFace)/group.getInterfaceSurface(iFace);
+          double nu = (*maximumDiffusivityLeft)(iPt,0);
+	  double mu = (p+1)*(p+dim)/dim*nu/minl;
+          double solutionJumpPenalty = (solutionQPLeft(iPt,k)-(*dirichlet)(iPt,k))/2*mu;
+          normalFluxQP(iPt,k) -= ((*neumann)(iPt,k)+solutionJumpPenalty)*detJ;
+        }
+      }
+    }    
+
+
   }
   // ----- 3 ---- do the redistribution at face nodes using BLAS3
   residual.gemm(group.getRedistributionMatrix(),NormalFluxQP);
   delete boundaryTerm;
+  if (dirichlet) delete dirichlet;
+  if (neumann) delete neumann;
 }
 
 /*
@@ -520,6 +563,20 @@ void dgAlgorithm::partitionGroup(dgGroupOfElements &eGroup,
 }
 */
 
+//static void partitionGroup (std::vector<MElement *>,){
+//}
+
+// this function creates groups of elements
+// First, groups of faces are created on every physical group
+// of dimension equal to the dimension of the problem minus one
+// Then, groups of elements are created 
+//  -) Elements of different types are separated
+//  -) Then those groups are split into partitions
+//  -) Finally, those groups are re-numbered 
+// Finally, group of interfaces are created
+//  -) Groups of faces internal to a given group
+//  -) Groups of faces between groups.
+ 
 void dgAlgorithm::buildGroups(GModel *model, int dim, int order,
     std::vector<dgGroupOfElements*> &eGroups,
     std::vector<dgGroupOfFaces*> &fGroups,
@@ -558,10 +615,15 @@ void dgAlgorithm::buildGroups(GModel *model, int dim, int order,
         allElements[entity->getMeshElement(iel)->getType()].push_back(entity->getMeshElement(iel));
     }
   }
+  
+
   // do a group of elements for every element type that is present in the mesh
   Msg::Info("%d groups of elements",allElements.size());
-  for (std::map<int, std::vector<MElement *> >::iterator it = allElements.begin(); it !=allElements.end() ; ++it)
+  for (std::map<int, std::vector<MElement *> >::iterator it = allElements.begin(); it !=allElements.end() ; ++it){
+    
     eGroups.push_back(new dgGroupOfElements(it->second,order));
+  }
+
 
   for (int i=0;i<eGroups.size();i++){
     // create a group of faces on the boundary for every group ef elements
@@ -612,40 +674,41 @@ void dgAlgorithm::residual( const dgConservationLaw &claw,
   //volume term
   for(size_t i=0;i<eGroups.size() ; i++) {
     residu[i]->scale(0);
+    
     residualVolume(claw,*eGroups[i],*solution[i],*residu[i]);
   }
   //  residu[0]->print("Volume");
   //interface term
   for(size_t i=0;i<fGroups.size() ; i++) {
-      dgGroupOfFaces &faces = *fGroups[i];
-      int iGroupLeft = -1, iGroupRight = -1;
-      for(size_t j=0;j<eGroups.size() ; j++) {
-	if (eGroups[j] == &faces.getGroupLeft())iGroupLeft = j;
-	if (eGroups[j] == &faces.getGroupRight())iGroupRight= j;
-      }
-      fullMatrix<double> solInterface(faces.getNbNodes(),faces.getNbElements()*2*nbFields);
-      fullMatrix<double> residuInterface(faces.getNbNodes(),faces.getNbElements()*2*nbFields);
-      faces.mapToInterface(nbFields, *solution[iGroupLeft], *solution[iGroupRight], solInterface);
-      residualInterface(claw,faces,solInterface,*solution[iGroupLeft], *solution[iGroupRight],residuInterface);
-      faces.mapFromInterface(nbFields, residuInterface, *residu[iGroupLeft], *residu[iGroupRight]);
+    dgGroupOfFaces &faces = *fGroups[i];
+    int iGroupLeft = -1, iGroupRight = -1;
+    for(size_t j=0;j<eGroups.size() ; j++) {
+      if (eGroups[j] == &faces.getGroupLeft())iGroupLeft = j;
+      if (eGroups[j] == &faces.getGroupRight())iGroupRight= j;
     }
-    //  residu[0]->print("Interfaces");
-    //boundaries
-    for(size_t i=0;i<bGroups.size() ; i++) {
-      dgGroupOfFaces &faces = *bGroups[i];
-      int iGroupLeft = -1, iGroupRight = -1;
-      for(size_t j=0;j<eGroups.size() ; j++) {
-	if (eGroups[j] == &faces.getGroupLeft())iGroupLeft = j;
-	if (eGroups[j] == &faces.getGroupRight())iGroupRight= j;
-      }
-      fullMatrix<double> solInterface(faces.getNbNodes(),faces.getNbElements()*nbFields);
-      fullMatrix<double> residuInterface(faces.getNbNodes(),faces.getNbElements()*nbFields);
-      faces.mapToInterface(nbFields, *solution[iGroupLeft], *solution[iGroupRight], solInterface);
-      residualBoundary(claw,faces,solInterface,*solution[iGroupLeft],residuInterface);
-      faces.mapFromInterface(nbFields, residuInterface, *residu[iGroupLeft], *residu[iGroupRight]);
+    fullMatrix<double> solInterface(faces.getNbNodes(),faces.getNbElements()*2*nbFields);
+    fullMatrix<double> residuInterface(faces.getNbNodes(),faces.getNbElements()*2*nbFields);
+    faces.mapToInterface(nbFields, *solution[iGroupLeft], *solution[iGroupRight], solInterface);
+    residualInterface(claw,faces,solInterface,*solution[iGroupLeft], *solution[iGroupRight],residuInterface);
+    faces.mapFromInterface(nbFields, residuInterface, *residu[iGroupLeft], *residu[iGroupRight]);
+  }
+  //  residu[0]->print("Interfaces");
+  //boundaries
+  for(size_t i=0;i<bGroups.size() ; i++) {
+    dgGroupOfFaces &faces = *bGroups[i];
+    int iGroupLeft = -1, iGroupRight = -1;
+    for(size_t j=0;j<eGroups.size() ; j++) {
+      if (eGroups[j] == &faces.getGroupLeft())iGroupLeft = j;
+      if (eGroups[j] == &faces.getGroupRight())iGroupRight= j;
     }
+    fullMatrix<double> solInterface(faces.getNbNodes(),faces.getNbElements()*nbFields);
+    fullMatrix<double> residuInterface(faces.getNbNodes(),faces.getNbElements()*nbFields);
+    faces.mapToInterface(nbFields, *solution[iGroupLeft], *solution[iGroupRight], solInterface);
+    residualBoundary(claw,faces,solInterface,*solution[iGroupLeft],residuInterface);
+    faces.mapFromInterface(nbFields, residuInterface, *residu[iGroupLeft], *residu[iGroupRight]);
+  }
 
-    //  residu[0]->print("Boundaries");
+  //  residu[0]->print("Boundaries");
 }
 
 void dgAlgorithm::computeElementaryTimeSteps ( //dofManager &dof, // the DOF manager (maybe useless here)
diff --git a/Solver/dgConservationLaw.cpp b/Solver/dgConservationLaw.cpp
index 937866f44fb3fbad503bf9444137cc3ea279da0f..853b6756bbff9af99428e0e3c16a1f8599298010 100644
--- a/Solver/dgConservationLaw.cpp
+++ b/Solver/dgConservationLaw.cpp
@@ -1,23 +1,22 @@
 #include "dgConservationLaw.h"
 #include "function.h"
 class dgBoundaryConditionOutsideValue : public dgBoundaryCondition {
-  dgConservationLaw &_claw;
   std::string _outsideValueFunctionName;
   class term : public dataCacheDouble {
     dataCacheMap cacheMapRight; // new cacheMap to  pass to the Riemann solver
     dataCacheDouble &solutionRight;
     dataCacheDouble &outsideValue;
     dataCacheDouble *riemannSolver;
-    dgConservationLaw &_claw;
+    dgConservationLaw *_claw;
     public:
-    term(dgConservationLaw &claw, dataCacheMap &cacheMapLeft,const std::string outsideValueFunctionName):
-      dataCacheDouble(cacheMapLeft.getNbEvaluationPoints(),claw.nbFields()),
+    term(dgConservationLaw *claw, dataCacheMap &cacheMapLeft,const std::string outsideValueFunctionName):
+      dataCacheDouble(cacheMapLeft.getNbEvaluationPoints(),claw->nbFields()),
       cacheMapRight(cacheMapLeft.getNbEvaluationPoints()),
       solutionRight(cacheMapRight.provideData("Solution")),
       outsideValue(cacheMapLeft.get(outsideValueFunctionName,this)),
       _claw(claw)
     {
-      riemannSolver=_claw.newRiemannSolver(cacheMapLeft,cacheMapRight);
+      riemannSolver=_claw->newRiemannSolver(cacheMapLeft,cacheMapRight);
       riemannSolver->addMeAsDependencyOf(this);
     }
 
@@ -31,7 +30,7 @@ class dgBoundaryConditionOutsideValue : public dgBoundaryCondition {
     }
   };
   public:
-  dgBoundaryConditionOutsideValue(dgConservationLaw &claw,const std::string outsideValueFunctionName): _claw(claw),
+  dgBoundaryConditionOutsideValue(dgConservationLaw *claw,const std::string outsideValueFunctionName): dgBoundaryCondition(claw),
     _outsideValueFunctionName(outsideValueFunctionName)
   { }
   dataCacheDouble *newBoundaryTerm(dataCacheMap &cacheMapLeft) const {
@@ -40,18 +39,17 @@ class dgBoundaryConditionOutsideValue : public dgBoundaryCondition {
 };
 
 class dgBoundarySymmetry : public dgBoundaryCondition {
-  dgConservationLaw &_claw;
   class term : public dataCacheDouble {
     dataCacheDouble *riemannSolver;
-    dgConservationLaw &_claw;
-    public:
-    term(dgConservationLaw &claw, dataCacheMap &cacheMapLeft):
-      dataCacheDouble(cacheMapLeft.getNbEvaluationPoints(),claw.nbFields()), _claw(claw)
+    dgConservationLaw *_claw;
+  public:
+    term(dgConservationLaw *claw, dataCacheMap &cacheMapLeft):
+      dataCacheDouble(cacheMapLeft.getNbEvaluationPoints(),claw->nbFields()), _claw(claw)
     {
-      riemannSolver=_claw.newRiemannSolver(cacheMapLeft,cacheMapLeft);
+      riemannSolver=_claw->newRiemannSolver(cacheMapLeft,cacheMapLeft);
       riemannSolver->addMeAsDependencyOf(this);
     }
-
+    
     void _eval() {
       if(riemannSolver){
         for(int i=0;i<_value.size1(); i++)
@@ -60,39 +58,93 @@ class dgBoundarySymmetry : public dgBoundaryCondition {
       }
     }
   };
-  public:
-  dgBoundarySymmetry(dgConservationLaw &claw): _claw(claw) {}
+public:
+  dgBoundarySymmetry(dgConservationLaw *claw): dgBoundaryCondition(claw) {}
   dataCacheDouble *newBoundaryTerm(dataCacheMap &cacheMapLeft) const {
     return new term(_claw,cacheMapLeft);
   }
 };
 
 class dgBoundaryCondition0Flux : public dgBoundaryCondition {
-  dgConservationLaw &_claw;
   class term : public dataCacheDouble {
-    public:
-    term(dgConservationLaw &claw,dataCacheMap &cacheMapLeft):
-    dataCacheDouble(cacheMapLeft.getNbEvaluationPoints(),claw.nbFields()) {}
+  public:
+    term(dgConservationLaw *claw,dataCacheMap &cacheMapLeft):
+      dataCacheDouble(cacheMapLeft.getNbEvaluationPoints(),claw->nbFields()) {}
     void _eval() {
     }
   };
-  public:
-  dgBoundaryCondition0Flux(dgConservationLaw &claw): _claw(claw) {}
+public:
+  dgBoundaryCondition0Flux(dgConservationLaw *claw): dgBoundaryCondition(claw) {}
   dataCacheDouble *newBoundaryTerm(dataCacheMap &cacheMapLeft) const {
     return new term(_claw,cacheMapLeft);
   }
 };
 
 dgBoundaryCondition *dgConservationLaw::newSymmetryBoundary() {
-  return new dgBoundarySymmetry(*this);
+  return new dgBoundarySymmetry(this);
 }
 dgBoundaryCondition *dgConservationLaw::newOutsideValueBoundary(const std::string outsideValueFunctionName) {
-  return new dgBoundaryConditionOutsideValue(*this,outsideValueFunctionName);
+  return new dgBoundaryConditionOutsideValue(this,outsideValueFunctionName);
 }
 dgBoundaryCondition *dgConservationLaw::new0FluxBoundary() {
-  return new dgBoundaryCondition0Flux(*this);
+  return new dgBoundaryCondition0Flux(this);
 }
 
+
+class dgBoundaryCondition::dirichlet_ : public dataCacheDouble {
+  dataCacheDouble &sol;
+public:
+  dirichlet_(dataCacheMap &cacheMap):
+    sol(cacheMap.get("Solution",this)){}
+  void _eval () { 
+    int nQP = sol().size1();
+    if(_value.size1() != nQP)
+      _value = fullMatrix<double>(nQP,sol().size2());
+    for(int i=0; i< nQP; i++) 
+      for (int k=0;k<sol().size2();k++) 
+	_value(i,k) = sol(i,k);
+  }
+};
+
+class dgBoundaryCondition::neumann_ : public dataCacheDouble {
+  dgConservationLaw *_claw;
+  dataCacheDouble &sol,&normals;
+  dataCacheDouble *diffusiveFlux;
+public:
+  neumann_(dataCacheMap &cacheMap, dgConservationLaw *claw):
+    _claw (claw),
+    sol(cacheMap.get("Solution",this)),
+    normals(cacheMap.get("Normals",this)){
+    diffusiveFlux=_claw->newDiffusiveFlux(cacheMap);
+    if (diffusiveFlux)diffusiveFlux->addMeAsDependencyOf(this);
+  }
+  void _eval () { 
+    int nQP = sol().size1();
+    if(_value.size1() != nQP)
+      _value = fullMatrix<double>(nQP,sol().size2());
+    
+    const fullMatrix<double> &dfl = (*diffusiveFlux)();
+    
+    for(int i=0; i< nQP; i++) {
+      for (int k=0;k<sol().size2();k++) { 
+	_value(i,k) = 
+	  dfl(i,k+sol().size2()*0) *normals(0,i) +
+	  dfl(i,k+sol().size2()*1) *normals(1,i) +
+	  dfl(i,k+sol().size2()*2) *normals(2,i);
+      }
+    }
+  }
+  ~neumann_ () {if (diffusiveFlux)delete diffusiveFlux;}
+};
+
+dataCacheDouble *dgBoundaryCondition::newDiffusiveDirichletBC(dataCacheMap &cacheMapLeft) const {
+  return new dirichlet_(cacheMapLeft);
+}
+dataCacheDouble *dgBoundaryCondition::newDiffusiveNeumannBC(dataCacheMap &cacheMapLeft) const {
+  return new dgBoundaryCondition::neumann_(cacheMapLeft, _claw);
+}
+
+
 #include "Bindings.h"
 
 void dgConservationLaw::registerBindings(binding *b){
diff --git a/Solver/dgConservationLaw.h b/Solver/dgConservationLaw.h
index 2bc50dc249558680184dc570257d51bdd5b5cd22..b93a2777846e6b15074650471c6f7b1295816e6d 100644
--- a/Solver/dgConservationLaw.h
+++ b/Solver/dgConservationLaw.h
@@ -14,9 +14,16 @@ class dgConservationLaw;
 class binding;
 
 class dgBoundaryCondition {
+  class neumann_;
+  class dirichlet_;
+ protected:
+  dgConservationLaw *_claw;
  public:
+  dgBoundaryCondition (dgConservationLaw *claw)  : _claw(claw){}
   virtual ~dgBoundaryCondition () {}
   virtual dataCacheDouble *newBoundaryTerm(dataCacheMap &cacheMapLeft) const = 0;
+  virtual dataCacheDouble *newDiffusiveNeumannBC(dataCacheMap &cacheMapLeft) const;
+  virtual dataCacheDouble *newDiffusiveDirichletBC(dataCacheMap &cacheMapLeft) const;
   static void registerBindings(binding *b);
 };
 
diff --git a/Solver/dgConservationLawPerfectGas.cpp b/Solver/dgConservationLawPerfectGas.cpp
index 8e221b7e4ecaf24be1064d0f79ed88e937b8858f..9160134f075f33120a58ad0fd4ee22540123b53a 100644
--- a/Solver/dgConservationLawPerfectGas.cpp
+++ b/Solver/dgConservationLawPerfectGas.cpp
@@ -1,6 +1,10 @@
 #include "dgConservationLawPerfectGas.h"
 #include "function.h"
 
+/*
+\rho \left(\frac{\partial \mathbf{v}}{\partial t} + \mathbf{v} \cdot \nabla \mathbf{v}\right) = -\nabla p + \mu \nabla^2 \mathbf{v} + \left( \tfrac13 \mu + \mu^v) \nabla (\nabla \cdot \mathbf{v} \right) + \rho \mathbf{f} 
+*/
+
 const double GAMMA = 1.4;
 static inline void _ROE2D (const double &_GAMMA,
 			   const double &nx,  
@@ -169,6 +173,89 @@ class dgPerfectGasLaw2d::advection : public dataCacheDouble {
   }
 };
 
+class dgPerfectGasLaw2d::diffusion : public dataCacheDouble {
+  dataCacheDouble &sol,&grad,&mu,&kappa;
+  public:
+  diffusion(dataCacheMap &cacheMap, 
+	    const std::string &muFunctionName,
+	    const std::string &kappaFunctionName ):
+    sol(cacheMap.get("Solution",this)),
+    grad(cacheMap.get("SolutionGradient",this)),
+    mu(cacheMap.get(muFunctionName,this)),
+    kappa(cacheMap.get(kappaFunctionName,this))
+  {};
+  void _eval () { 
+    const int nQP = sol().size1();      
+    if(_value.size1() != nQP)
+      _value=fullMatrix<double>(nQP,12);
+
+    for (size_t k = 0 ; k < nQP; k++ ){
+      const double muk    = mu(k,0);
+      const double kappak = kappa(k,0);      
+      //      printf("%g %g grad rho (%g %g)\n",muk,kappak,grad(k*3+0,0),grad(k*3+1,0));
+    // find gradients of primitive variables    
+      const double overRho = 1./sol(k,0);
+      const double u = sol(k,1) * overRho;
+      const double v = sol(k,2) * overRho;
+      // grad v    
+      const double dudx = (grad(k*3+0,1) - grad(k*3+0,0) * u) * overRho;
+      const double dudy = (grad(k*3+1,1) - grad(k*3+1,0) * u) * overRho;
+      const double dvdx = (grad(k*3+0,2) - grad(k*3+0,0) * v) * overRho;
+      const double dvdy = (grad(k*3+1,2) - grad(k*3+1,0) * v) * overRho;    
+      // shear stress tensor - Newtonian fluid without bulk viscosity
+      
+      const double tauxx = muk * (dudx - dvdy);
+      const double tauxy = muk * (dudy + dvdx);
+      const double tauyy = - tauxx;
+    
+      _value(k,1) = -tauxx;
+      _value(k,2) = -tauxy;
+    
+      _value(k,1+4) = -tauxy;
+      _value(k,2+4) = -tauyy;    
+      // heat flux
+    
+      const double kOverRhoCv = kappak * overRho; 
+      const double Ek = u * u + v * v;
+      const double eMinus= sol(k,3) * overRho - Ek;
+    
+      // k grad T
+      
+      _value(k,3)      = -kOverRhoCv*(grad(k*3+0,3) - eMinus*grad(k*3+0,0) - (grad(k*3+0,1)*u + grad(k*3+0,2)*v));
+      _value(k,3+4)    = -kOverRhoCv*(grad(k*3+1,3) - eMinus*grad(k*3+1,0) - (grad(k*3+1,1)*u + grad(k*3+1,2)*v));
+      
+      // v . tau - momentum dissipation
+      
+      _value(k,3)      -= (u * tauxx + v * tauxy);
+      _value(k,3+4)    -= (u * tauxy + v * tauyy);         
+      
+      //      printf("%g %g %g %g %g %g %g %g \n",_value(k,0),_value(k,1),_value(k,2),_value(k,3),_value(k,4),_value(k,5),_value(k,6),_value(k,7));
+      
+    }
+  }
+};
+
+class dgPerfectGasLaw2d::source : public dataCacheDouble {
+  dataCacheDouble &sol,&s;
+public:
+  source(dataCacheMap &cacheMap, const std::string &sourceFunctionName):
+    sol(cacheMap.get("Solution",this)),
+    s(cacheMap.get(sourceFunctionName,this))
+  {};
+  void _eval () { 
+    const int nQP = sol().size1();      
+    if(_value.size1() != nQP)
+      _value=fullMatrix<double>(nQP,4);
+    for (size_t k = 0 ; k < nQP; k++ ){
+      _value(k,0) = sol(k,0)*s(0,0);
+      _value(k,1) = sol(k,0)*s(0,1);
+      _value(k,2) = sol(k,0)*s(0,2);
+      _value(k,3) = sol(k,0)*s(0,3);
+    }
+  }
+};
+
+
 class dgPerfectGasLaw2d::riemann : public dataCacheDouble {
   dataCacheDouble &normals, &solL, &solR;
   public:
@@ -180,7 +267,7 @@ class dgPerfectGasLaw2d::riemann : public dataCacheDouble {
   void _eval () { 
     int nQP = solL().size1();
     if(_value.size1() != nQP)
-      _value = fullMatrix<double>(nQP,8);
+      _value = fullMatrix<double>(nQP,12);
 
     for(int i=0; i< nQP; i++) {
       const double solLeft [4] = {solL(i,0),solL(i,1),solL(i,2),solL(i,3)};
@@ -201,6 +288,55 @@ class dgPerfectGasLaw2d::riemann : public dataCacheDouble {
     }
   }
 };
+
+class dgPerfectGasLaw2d::maxConvectiveSpeed : public dataCacheDouble {
+  dataCacheDouble &sol;
+  public:
+  maxConvectiveSpeed(dataCacheMap &cacheMap):
+    sol(cacheMap.get("Solution",this))
+  {
+  };
+  void _eval () {
+    int nQP = sol().size1();
+    if(_value.size1() != nQP)
+      _value=fullMatrix<double>(nQP,1);
+    for(int i=0; i< nQP; i++) {
+      const double rhov2 = (sol(i,1)*sol(i,1) + sol(i,2)*sol(i,2))/sol(i,0);
+      const double p = (GAMMA-1.0)*(sol(i,3) - 0.5 * rhov2);
+      //      printf("p = %g %g %g %g %g\n",p,_value(i,0),_value(i,1),_value(i,2),_value(i,3));
+      const double c = sqrt(GAMMA*p/sol(i,0));
+      _value(i,0) = c+sqrt(rhov2/sol(i,0));
+    }
+  }
+};
+
+class dgPerfectGasLaw2d::maxDiffusivity : public dataCacheDouble {
+  dataCacheDouble &sol,&mu,&kappa;
+  public:
+  maxDiffusivity(dataCacheMap &cacheMap, const std::string &muFunctionName, const std::string &kappaFunctionName ):
+    sol(cacheMap.get("Solution",this)),
+    mu(cacheMap.get(muFunctionName,this)),
+    kappa(cacheMap.get(kappaFunctionName,this))
+  {
+  };
+  void _eval () {
+    int nQP = sol().size1();
+    if(_value.size1() != nQP)
+      _value=fullMatrix<double>(nQP,1);
+    for(int i=0; i< nQP; i++) {
+      _value(i,0) = std::max(mu(i,0),kappa(i,0));
+    }
+  }
+};
+
+
+dataCacheDouble *dgPerfectGasLaw2d::newMaximumDiffusivity( dataCacheMap &cacheMap) const {
+  return _muFunctionName.empty() ? NULL : new maxDiffusivity(cacheMap,_muFunctionName,_kappaFunctionName);
+}
+
+dataCacheDouble *dgPerfectGasLaw2d::newMaxConvectiveSpeed( dataCacheMap &cacheMap) const {
+  return new maxConvectiveSpeed(cacheMap);
+}
 dataCacheDouble *dgPerfectGasLaw2d::newConvectiveFlux( dataCacheMap &cacheMap) const {
   return new advection(cacheMap);
 }
@@ -208,24 +344,38 @@ dataCacheDouble *dgPerfectGasLaw2d::newRiemannSolver( dataCacheMap &cacheMapLeft
   return new riemann(cacheMapLeft, cacheMapRight);
 }
 dataCacheDouble *dgPerfectGasLaw2d::newDiffusiveFlux( dataCacheMap &cacheMap) const {
-  return 0;
+  if (_muFunctionName.empty() || _kappaFunctionName.empty())
+    return 0;
+  else
+    return new diffusion(cacheMap,_muFunctionName,_kappaFunctionName);
 }
 dataCacheDouble *dgPerfectGasLaw2d::newSourceTerm (dataCacheMap &cacheMap) const {
-  return 0;
+  if (_sourceFunctionName.empty())
+    return 0;
+  else
+    return new source(cacheMap,_sourceFunctionName);    
 }
+
 dgPerfectGasLaw2d::dgPerfectGasLaw2d() 
 {
   _nbf = 4; // \rho \rho u \rho v \rho e
 }
 
-
+//-------------------------------------------------------------------------------
+// A class for slip and non slip walls
+// could easily add moving walls ...
+//-------------------------------------------------------------------------------
 class dgBoundaryConditionPerfectGasLaw2dWall : public dgBoundaryCondition {
+  int _type;
   class term : public dataCacheDouble {
     dataCacheDouble &sol,&normals;
-    public:
+  public:
+//-------------------------------------------------------------------------------
+// NON VISCOUS BOUNDARY FLUX
+//-------------------------------------------------------------------------------
     term(dataCacheMap &cacheMap):
-    sol(cacheMap.get("Solution",this)),
-    normals(cacheMap.get("Normals",this)){}
+      sol(cacheMap.get("Solution",this)),
+      normals(cacheMap.get("Normals",this)){}
     void _eval () { 
       int nQP = sol().size1();
       if(_value.size1() != nQP)
@@ -240,8 +390,13 @@ class dgBoundaryConditionPerfectGasLaw2dWall : public dgBoundaryCondition {
 				    sol(i,1) - 2 * vn  * nx,
 				    sol(i,2) - 2 * vn  * ny,
 				    sol(i,3)};
-	//	double FLUX[4] ;
-	//	_ROE2D (GAMMA,nx,ny,solLeft,solRight,FLUX);
+	double FLUX[4] ;
+	_ROE2D (GAMMA,nx,ny,solLeft,solRight,FLUX);
+	_value(i,0) = FLUX[0];
+	_value(i,1) = FLUX[1];
+	_value(i,2) = FLUX[2];
+	_value(i,3) = FLUX[3];
+	/*
 	const double q11 = sol(i,1)*sol(i,1)/sol(i,0);
 	const double q22 = sol(i,2)*sol(i,2)/sol(i,0);
 	const double p = (GAMMA-1)*sol(i,3) - 0.5*(GAMMA-1)*(q11+q22);
@@ -249,72 +404,153 @@ class dgBoundaryConditionPerfectGasLaw2dWall : public dgBoundaryCondition {
 	_value(i,1) = -p*nx;//FLUX[1];
 	_value(i,2) = -p*ny;//FLUX[2];
 	_value(i,3) = 0.0;//FLUX[3];
+	*/
       }
     }
   };
-  public:
-  dgBoundaryConditionPerfectGasLaw2dWall(){}
-  dataCacheDouble *newBoundaryTerm(dataCacheMap &cacheMapLeft) const {
-    return new term(cacheMapLeft);
-  }
-};
-dgBoundaryCondition *dgPerfectGasLaw2d::newWallBoundary() const {
-  return new dgBoundaryConditionPerfectGasLaw2dWall();
-}
 
-#if 0 // JF : I commented this out as I think this equivalent to the generic OutsideValue condition
-can you confirm and remove it ?
-class dgBoundaryConditionPerfectGasLaw2dFreeStream : public dgBoundaryCondition {
-  class term : public dataCacheDouble {
-    dataCacheDouble &sol,&normals,&freeStream;
+//-------------------------------------------------------------------------------
+// Non Slip Dirichlet BC --
+// What to put on the right side of the IP (no velocity, same density) 
+// Assume Adiabatic Wall --> no heat transfer -> \partial_n T = 0
+// So, we use the same temperature as inside
+//-------------------------------------------------------------------------------
+  class dirichletNonSlip : public dataCacheDouble {
+    dataCacheDouble &sol;
     public:
-    term(dataCacheMap &cacheMap, const std::string & freeStreamName):
-    sol(cacheMap.get("Solution",this)),
-    normals(cacheMap.get("Normals",this)),
-    freeStream(cacheMap.get(freeStreamName,this)){}
+    dirichletNonSlip(dataCacheMap &cacheMap):
+    sol(cacheMap.get("Solution",this)){}
     void _eval () { 
       int nQP = sol().size1();
       if(_value.size1() != nQP)
 	_value = fullMatrix<double>(nQP,4);
       
       for(int i=0; i< nQP; i++) {
-	const double nx = normals(0,i);
-	const double ny = normals(1,i);
-	const double solLeft [4] = {sol(i,0),sol(i,1),sol(i,2),sol(i,3)};
-	const double solRight[4] = {freeStream(i,0),
-				    freeStream(i,1),
-				    freeStream(i,2),
-				    freeStream(i,3)};
-	double FLUX[4] ;
-	_ROE2D (GAMMA,nx,ny,solLeft,solRight,FLUX);
-	/*
-	printf("SOLL %g %g %g %g\n",solLeft[0],solLeft[1],solLeft[2], solLeft[3]);
-	printf("SOLR %g %g %g %g\n",solRight[0],solRight[1],solRight[2], solRight[3]);
-	printf("N    %g %g\n",nx,ny);
-	printf("FLUX %g %g %g %g\n",FLUX[0],FLUX[1],FLUX[2],FLUX[3]);
-	*/
-	_value(i,0) = FLUX[0];
-	_value(i,1) = FLUX[1];
-	_value(i,2) = FLUX[2];
-	_value(i,3) = FLUX[3];
+	_value(i,0) = sol(i,0);
+	_value(i,1) = 0.0;
+	_value(i,2) = 0.0;
+	_value(i,3) = sol(i,3) - 0.5 * (sol(i,1) * sol(i,1) + sol(i,2) * sol(i,2))/sol(i,0);
       }
     }
   };
+
+//-------------------------------------------------------------------------------
+// Non Slip Neumann BC --
+// Compute normal diffusive fluxes at the boundary
+// Assume Adiabatic Wall --> no heat transfer -> no flux for component 3 (in 2D)
+//-------------------------------------------------------------------------------
+
+  class neumannNonSlip : public dataCacheDouble {
+    dgConservationLaw *_claw;
+    dataCacheDouble &sol,&normals;
+    dataCacheDouble *diffusiveFlux;
   public:
-  std::string _freeStreamName;
-  dgBoundaryConditionPerfectGasLaw2dFreeStream(std::string & freeStreamName)
-    : _freeStreamName(freeStreamName){}
-  dataCacheDouble *newBoundaryTerm(dataCacheMap &cacheMapLeft) const {
-    return new term(cacheMapLeft,_freeStreamName);
-  }
+    neumannNonSlip(dataCacheMap &cacheMap, dgConservationLaw *claw):
+      _claw (claw),
+      sol(cacheMap.get("Solution",this)),
+      normals(cacheMap.get("Normals",this)){
+      diffusiveFlux=_claw->newDiffusiveFlux(cacheMap);
+      if (diffusiveFlux)diffusiveFlux->addMeAsDependencyOf(this);
+    }
+    void _eval () { 
+      int nQP = sol().size1();
+      if(_value.size1() != nQP)
+	_value = fullMatrix<double>(nQP,4);
+
+      const fullMatrix<double> &dfl = (*diffusiveFlux)();
+
+      for(int i=0; i< nQP; i++) {
+	for (int k=0;k<3;k++) { 
+          _value(i,k) = 
+	    dfl(i,k+4*0) *normals(0,i) +
+	    dfl(i,k+4*1) *normals(1,i) +
+	    dfl(i,k+4*2) *normals(2,i);
+	}
+	_value(i,3) = 0.0; 
+      }
+    }
+    ~neumannNonSlip () {if (diffusiveFlux)delete diffusiveFlux;}
+  };
+
+//-------------------------------------------------------------------------------
+// Slip Wall Dirichlet BC --
+// Assume zero derivatives of all variables --> put the same as inside 
+//-------------------------------------------------------------------------------
+
+  class dirichletSlip : public dataCacheDouble {
+    dataCacheDouble &sol;
+    public:
+    dirichletSlip(dataCacheMap &cacheMap):
+    sol(cacheMap.get("Solution",this)){}
+    void _eval () { 
+      int nQP = sol().size1();
+      if(_value.size1() != nQP)
+	_value = fullMatrix<double>(nQP,sol().size2());
+      
+      for(int i=0; i< nQP; i++) {
+	for(int k=0; k< sol().size2(); k++) {
+	  _value(i,k) = sol(i,k);
+	}
+      }
+    }
+  };
+
+//-------------------------------------------------------------------------------
+// Slip Wall or Symmetry Neumann BC -- assume NO FLUXES AT ALL
+//-------------------------------------------------------------------------------
+
+  class neumannSlip : public dataCacheDouble {
+    dgConservationLaw *_claw;
+    dataCacheDouble &sol,&normals;
+  public:
+    neumannSlip(dataCacheMap &cacheMap, dgConservationLaw *claw):
+      _claw (claw),
+      sol(cacheMap.get("Solution",this)),
+      normals(cacheMap.get("Normals",this)){
+    }
+    void _eval () { 
+      int nQP = sol().size1();
+      if(_value.size1() != nQP)
+	_value = fullMatrix<double>(nQP,4);
+      _value.setAll(0.0);
+    }
+  };
+
+  public:
+    dgBoundaryConditionPerfectGasLaw2dWall(int type, dgPerfectGasLaw2d *claw):_type(type), dgBoundaryCondition(claw){}
+    dataCacheDouble *newBoundaryTerm(dataCacheMap &cacheMapLeft) const {
+      return new term(cacheMapLeft);
+    }
+    dataCacheDouble *newDiffusiveDirichletBC(dataCacheMap &cacheMapLeft) const {
+      switch(_type){
+      case 1 : return new dirichletSlip(cacheMapLeft);
+      case 2 : return new dirichletNonSlip(cacheMapLeft);
+      }
+    }
+    dataCacheDouble *newDiffusiveNeumannBC(dataCacheMap &cacheMapLeft) const {
+      switch(_type){
+      case 1 : return new neumannSlip(cacheMapLeft,_claw);
+      case 2 : return new neumannNonSlip(cacheMapLeft,_claw);
+      }
+    }
 };
-#endif
+
+dgBoundaryCondition *dgPerfectGasLaw2d::newWallBoundary()  {
+  return new dgBoundaryConditionPerfectGasLaw2dWall(2, this);
+}
+dgBoundaryCondition *dgPerfectGasLaw2d::newSlipWallBoundary()  {
+  return new dgBoundaryConditionPerfectGasLaw2dWall(1, this);
+}
 
 #include "Bindings.h"
 void dgPerfectGasLaw2dRegisterBindings (binding *b){
   classBinding *cb = b->addClass<dgPerfectGasLaw2d>("dgPerfectGasLaw2d");
   methodBinding *cm;
   cb->addMethod("newWallBoundary",&dgPerfectGasLaw2d::newWallBoundary);
+  cb->addMethod("newNonSlipWallBoundary",&dgPerfectGasLaw2d::newWallBoundary);
+  cb->addMethod("newSlipWallBoundary",&dgPerfectGasLaw2d::newSlipWallBoundary);
+  cb->addMethod("setSource",&dgPerfectGasLaw2d::setSource);
+  cb->addMethod("setViscosityAndThermalConductivity",&dgPerfectGasLaw2d::setViscosityAndThermalConductivity);
   cb->setConstructor<dgPerfectGasLaw2d>();
   cb->setParentClass<dgConservationLaw>();
 }
diff --git a/Solver/dgConservationLawPerfectGas.h b/Solver/dgConservationLawPerfectGas.h
index c53ff8c057d001a3b642873c3d5ad7f8bd402e2d..75e43d9a2c716868b1017da666c118780b462cbc 100644
--- a/Solver/dgConservationLawPerfectGas.h
+++ b/Solver/dgConservationLawPerfectGas.h
@@ -2,16 +2,37 @@
 #define _DG_CONSERVATION_LAW_PERFECT_GAS_H_
 #include "dgConservationLaw.h"
 class dgPerfectGasLaw2d : public dgConservationLaw {
-  // perfect gas law, GAMMA is the only parameter
   class advection;
+  class diffusion;
   class riemann;
+  class source;
+  class maxConvectiveSpeed;
+  class maxDiffusivity;
+  // the name of the functions for 
+  // viscosity (_muFunctionName)
+  // thermal conductivity (_kappaFunctionName)
+  std::string _kappaFunctionName,_muFunctionName;
+  std::string _sourceFunctionName;
+
   public:
+  dataCacheDouble *newMaxConvectiveSpeed( dataCacheMap &cacheMap) const;
+  dataCacheDouble *newMaximumDiffusivity( dataCacheMap &cacheMap) const;
   dataCacheDouble *newConvectiveFlux( dataCacheMap &cacheMap) const;
   dataCacheDouble *newRiemannSolver( dataCacheMap &cacheMapLeft, dataCacheMap &cacheMapRight) const;
   dataCacheDouble *newDiffusiveFlux( dataCacheMap &cacheMap) const;
   dataCacheDouble *newSourceTerm (dataCacheMap &cacheMap) const;
-  dgPerfectGasLaw2d();
-  dgBoundaryCondition *newWallBoundary()const ;
+  dgPerfectGasLaw2d();  
+  dgBoundaryCondition *newWallBoundary() ;
+  dgBoundaryCondition *newSlipWallBoundary() ;
+  // sets some coefficients 
+  void setViscosityAndThermalConductivity (std::string a, std::string b){
+    _muFunctionName = a;
+    _kappaFunctionName = b;
+  }
+  // sets some coefficients 
+  void setSource(std::string a){
+    _sourceFunctionName = a;
+  }
 };
 class binding;
 void dgPerfectGasLaw2dRegisterBindings(binding *b);
diff --git a/Solver/dgConservationLawShallowWater2d.cpp b/Solver/dgConservationLawShallowWater2d.cpp
index 5a1e4b68d132571db7aec41c6a268eacaf3ed126..b0fe3019c2208778b8f8d661ccc62765067d136c 100644
--- a/Solver/dgConservationLawShallowWater2d.cpp
+++ b/Solver/dgConservationLawShallowWater2d.cpp
@@ -117,7 +117,7 @@ class dgConservationLawShallowWater2d::boundaryWall : public dgBoundaryCondition
     }
   };
   public:
-  boundaryWall(){}
+  boundaryWall(dgConservationLaw *claw) : dgBoundaryCondition(claw){}
   dataCacheDouble *newBoundaryTerm(dataCacheMap &cacheMapLeft) const {
     return new term(cacheMapLeft);
   }
@@ -137,7 +137,7 @@ dataCacheDouble *dgConservationLawShallowWater2d::newSourceTerm (dataCacheMap &c
 }
 
 dgBoundaryCondition *dgConservationLawShallowWater2d::newBoundaryWall(){
-  return new boundaryWall();
+  return new boundaryWall(this);
 }
 
 #include "Bindings.h"
diff --git a/Solver/dgConservationLawWaveEquation.cpp b/Solver/dgConservationLawWaveEquation.cpp
index 893da29c76f7ebd86480fc9d12508d5b19c48183..e7c27a94b790c8e6032bb37aa822477a6fd7335b 100644
--- a/Solver/dgConservationLawWaveEquation.cpp
+++ b/Solver/dgConservationLawWaveEquation.cpp
@@ -126,13 +126,13 @@ class dgBoundaryConditionWaveEquationWall : public dgBoundaryCondition {
     }
   };
   public:
-  dgBoundaryConditionWaveEquationWall(int DIM):_DIM(DIM){}
+  dgBoundaryConditionWaveEquationWall(int DIM, dgConservationLaw *claw):_DIM(DIM),dgBoundaryCondition(claw){}
   dataCacheDouble *newBoundaryTerm(dataCacheMap &cacheMapLeft) const {
     return new term(cacheMapLeft,_DIM);
   }
 };
-dgBoundaryCondition *dgConservationLawWaveEquation::newBoundaryWall()const{
-  return new dgBoundaryConditionWaveEquationWall(_DIM);
+dgBoundaryCondition *dgConservationLawWaveEquation::newBoundaryWall(){
+  return new dgBoundaryConditionWaveEquationWall(_DIM, this);
 }
 
 #include "Bindings.h"
diff --git a/Solver/dgConservationLawWaveEquation.h b/Solver/dgConservationLawWaveEquation.h
index ee3498acdd00ded72aecc1712a91e7c0b7c2ab38..0202905d09a34ffa14a68b8d23b316be2cc33e04 100644
--- a/Solver/dgConservationLawWaveEquation.h
+++ b/Solver/dgConservationLawWaveEquation.h
@@ -14,7 +14,7 @@ class dgConservationLawWaveEquation : public dgConservationLaw {
   dataCacheDouble *newDiffusiveFlux( dataCacheMap &cacheMap) const ;
   dataCacheDouble *newSourceTerm (dataCacheMap &cacheMap) const ;
   dataCacheDouble *newMaxConvectiveSpeed (dataCacheMap &cacheMap) const;
-  dgBoundaryCondition *newBoundaryWall () const;
+  dgBoundaryCondition *newBoundaryWall () ;
   dgConservationLawWaveEquation(int DIM);
   static const char *className;
   static const char *parentClassName;
diff --git a/Solver/dgSystemOfEquations.cpp b/Solver/dgSystemOfEquations.cpp
index 211c9c684428eba7285a85032f97e1d3ed199a56..f8350962bb529f5a9f6d8eb34f32ce62ba74f36f 100644
--- a/Solver/dgSystemOfEquations.cpp
+++ b/Solver/dgSystemOfEquations.cpp
@@ -69,6 +69,8 @@ void dgSystemOfEquations::registerBindings(binding *b){
   cb->addMethod("computeInvSpectralRadius",&dgSystemOfEquations::computeInvSpectralRadius);
   cb->addMethod("RK44_limiter",&dgSystemOfEquations::RK44_limiter);
   cb->addMethod("multirateRK43",&dgSystemOfEquations::multirateRK43);
+  cb->addMethod("saveSolution",&dgSystemOfEquations::saveSolution);
+  cb->addMethod("loadSolution",&dgSystemOfEquations::loadSolution);
 }
 
 // do a L2 projection
@@ -143,6 +145,18 @@ dgSystemOfEquations::~dgSystemOfEquations(){
   }
 }
 
+void dgSystemOfEquations::saveSolution (const std::string &name) const{
+  FILE *f = fopen (name.c_str(),"wb");
+  _solution->_data->binarySave(f);
+  fclose(f);
+}
+
+void dgSystemOfEquations::loadSolution (const std::string &name){
+  FILE *f = fopen (name.c_str(),"rb");
+  _solution->_data->binaryLoad(f);
+  fclose(f);
+}
+
 void dgSystemOfEquations::export_solution_as_is (const std::string &name){
   // the elementnodedata::export does not work !!
 
diff --git a/Solver/dgSystemOfEquations.h b/Solver/dgSystemOfEquations.h
index edc36dddf71bafa1f5ede84d035e2e6c01800939..5799445d4d253de7cd3aa0ac7b15fa17e2a14282 100644
--- a/Solver/dgSystemOfEquations.h
+++ b/Solver/dgSystemOfEquations.h
@@ -71,6 +71,8 @@ public:
 				iElement * _claw->nbFields(),_claw->nbFields());
   }
   void export_solution_as_is (const std::string &fileName);
+  void saveSolution (const std::string &fileName) const;
+  void loadSolution (const std::string &fileName);
   ~dgSystemOfEquations();
 private:
 };
diff --git a/benchmarks/2d/square.geo b/benchmarks/2d/square.geo
index 88dbb82010bc3abe731410df352f0df65a5b9c95..4ef669b84647aa5c773b28f5cc0c6e2212ecfe6f 100644
--- a/benchmarks/2d/square.geo
+++ b/benchmarks/2d/square.geo
@@ -11,5 +11,5 @@ Line(4) = {1, 2};
 Line Loop(5) = {1, 2, 3, 4};
 Plane Surface(10) = {5};
 
-Compound Surface(-11)={10};
+//Compound Surface(-11)={10};