diff --git a/Numeric/fullMatrix.h b/Numeric/fullMatrix.h
index 023995badfffa3c0cc3effc14801ab8fbc988096..427a9b532104bbd940b263e0dfee7e3dfc6f681a 100644
--- a/Numeric/fullMatrix.h
+++ b/Numeric/fullMatrix.h
@@ -91,6 +91,10 @@ class fullMatrix
     _own_data = true;
     scale(0.);
   }
+  fullMatrix(int r, int c, double *data) : _r(r), _c(c), _data(data),_own_data(false)
+  {
+    scale(0.);
+  }
   fullMatrix(const fullMatrix<scalar> &other) : _r(other._r), _c(other._c)
   {
     _data = new scalar[_r * _c];
@@ -106,12 +110,13 @@ class fullMatrix
     if(this != &other){
       _r = other._r; 
       _c = other._c;
-      if (_data) delete[] _data;
+      if (_data && _own_data) delete[] _data;
       if ((_r==0)||(_c==0))
         _data=0;
       else
       {
         _data = new scalar[_r * _c];
+        _own_data=true;
         for(int i = 0; i < _r * _c; ++i) _data[i] = other._data[i];
       }
     }
diff --git a/Solver/dgAlgorithm.cpp b/Solver/dgAlgorithm.cpp
index b4e51694ff118e341a57d6a6e464a7dc4d278fdb..a0346fb8a74eacc80d33463be5c01eb7dfac23e7 100644
--- a/Solver/dgAlgorithm.cpp
+++ b/Solver/dgAlgorithm.cpp
@@ -76,12 +76,11 @@ void dgAlgorithm::residualVolume ( //dofManager &dof, // the DOF manager (maybe
     if (claw.sourceTerm()){
       fullMatrix<double> source(Source, iElement*claw.nbFields(),claw.nbFields());
       (*claw.sourceTerm())(DGE,&source); 
-      //we assume constant mass matrix and constant mapping for now
-      /*for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) {
+      for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) {
         const double detJ = group.getDetJ (iElement, iPt);
         for (int k=0;k<nbFields;k++)
           source(iPt,k) *= detJ;
-      }*/
+      }
     }
     delete gradSolutionQPe;
   }
@@ -94,3 +93,36 @@ void dgAlgorithm::residualVolume ( //dofManager &dof, // the DOF manager (maybe
     residual.gemm(group.getSourceRedistributionMatrix(),Source);
   }
 }
+
+void dgAlgorithm::residualInterface ( //dofManager &dof, // the DOF manager (maybe useless here)
+				   const dgConservationLaw &claw,   // the conservation law
+				   const dgGroupOfFaces &group, 
+           const fullMatrix<double> &solution, // solution !! at faces nodes
+           fullMatrix<double> &residual // residual !! at faces nodes
+           )
+{ 
+  int nbFields = claw.nbFields();
+  // ----- 1 ----  get the solution at quadrature points
+  fullMatrix<double> solutionQP (group.getNbIntegrationPoints(),group.getNbElements() * nbFields);
+  group.getCollocationMatrix().mult(solution, solutionQP); 
+  // ----- 2 ----  compute normal fluxes  at integration points
+  fullMatrix<double> NormalFluxQP ( group.getNbIntegrationPoints(), group.getNbElements()*nbFields*2);
+  for (int iFace=0 ; iFace<group.getNbElements() ;++iFace) {
+    // ----- 2.3.1 --- build a small object that contains elementary solution, jacobians, gmsh element
+    fullMatrix<double> solutionQPLeft (solutionQP, iFace*2*nbFields, nbFields );
+    fullMatrix<double> solutionQPRight (solutionQP, (iFace*2+1)*nbFields, nbFields );
+    fullMatrix<double> normalFluxQP (NormalFluxQP, iFace*2*nbFields, nbFields*2);
+    dgFace DGF( group.getFace(iFace), group.getElementLeft(iFace), group.getElementRight(iFace),
+                solutionQPLeft, solutionQPRight, group.getIntegrationPointsMatrix());
+    // ----- 2.3.2 --- compute fluxes
+    (*claw.riemannSolver())(DGF,&normalFluxQP);
+    for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) {
+      const double detJ = group.getDetJ (iFace, iPt);
+      for (int k=0;k<nbFields*2;k++) {
+        normalFluxQP(iPt,k) *= detJ;
+      }
+    }
+  }
+  // ----- 3 ---- do the redistribution at face nodes using BLAS3
+  residual.gemm(group.getRedistributionMatrix(),NormalFluxQP);
+}
diff --git a/Solver/dgAlgorithm.h b/Solver/dgAlgorithm.h
index 745cd42e5b980d367524d4f7e7ce9710a85b4ff0..555b745c4246fd817aca13bbfd30d1e087dc1f1b 100644
--- a/Solver/dgAlgorithm.h
+++ b/Solver/dgAlgorithm.h
@@ -14,9 +14,11 @@ class dgAlgorithm {
 				   const dgGroupOfElements & group, 
            const fullMatrix<double> &solution,
            fullMatrix<double> &residual);
-  void residualInterface ( /*dofManager &dof,*/
-			   const dgConservationLaw &law,
-			   const dgGroupOfFaces & group);
+   void residualInterface ( //dofManager &dof, // the DOF manager (maybe useless here)
+				   const dgConservationLaw &claw,   // the conservation law
+				   const dgGroupOfFaces & group, 
+           const fullMatrix<double> &solution, // ! at face nodes
+           fullMatrix<double> &residual); // ! at face nodes
   void residualBoundaryConditions ( /*dofManager &dof,*/
 				    const dgConservationLaw &law,
 				    const dgGroupOfElements & group);
diff --git a/Solver/dgGroupOfElements.cpp b/Solver/dgGroupOfElements.cpp
index e2f102bca491faf0c265524278a9c790ae389c84..420b6b667fcde6db3e579738ae4ea91815fda80c 100644
--- a/Solver/dgGroupOfElements.cpp
+++ b/Solver/dgGroupOfElements.cpp
@@ -48,16 +48,24 @@ dgGroupOfElements::dgGroupOfElements(const std::vector<MElement*> &e, int polyOr
     )
 {
   // this is the biggest piece of data ... the mappings
-  _mapping = new fullMatrix<double> (_elements.size(), 10 * _integration->size1());
+  int nbNodes = _fs.coefficients.size1();
+  _redistributionFluxes[0] = new fullMatrix<double> (nbNodes,_integration->size1());
+  _redistributionFluxes[1] = new fullMatrix<double> (nbNodes,_integration->size1());
+  _redistributionFluxes[2] = new fullMatrix<double> (nbNodes,_integration->size1());
+  _redistributionSource = new fullMatrix<double> (nbNodes,_integration->size1());
+  _collocation = new fullMatrix<double> (_integration->size1(),nbNodes);
+  _mapping = new fullMatrix<double> (e.size(), 10 * _integration->size1());
+  _imass = new fullMatrix<double> (nbNodes,nbNodes*e.size()); 
+  double g[256][3],f[256];
   for (int i=0;i<_elements.size();i++){
     MElement *e = _elements[i];
+    fullMatrix<double> imass(*_imass,nbNodes*i,nbNodes);
     for (int j=0;j< _integration->size1() ; j++ ){
+      _fs.f((*_integration)(j,0), (*_integration)(j,1), (*_integration)(j,2), f);
       double jac[3][3],ijac[3][3],detjac;
       (*_mapping)(i,10*j + 9) =  
-	e->getJacobian ((*_integration)(j,0),
-			(*_integration)(j,1),
-			(*_integration)(j,2),
-			jac);
+        e->getJacobian ((*_integration)(j,0), (*_integration)(j,1), (*_integration)(j,2), jac);
+      const double weight = (*_integration)(j,3);
       detjac=inv3x3(jac,ijac);
       (*_mapping)(i,10*j + 0) = ijac[0][0]; 
       (*_mapping)(i,10*j + 1) = ijac[0][1]; 
@@ -69,19 +77,17 @@ dgGroupOfElements::dgGroupOfElements(const std::vector<MElement*> &e, int polyOr
       (*_mapping)(i,10*j + 7) = ijac[2][1]; 
       (*_mapping)(i,10*j + 8) = ijac[2][2]; 
       (*_mapping)(i,10*j + 9) = detjac; 
+      for (int k=0;k<_fs.coefficients.size1();k++){ 
+        for (int l=0;l<_fs.coefficients.size1();l++) { 
+          imass(k,l) += f[k]*f[l]*weight*detjac;
+        }
+      }
     }
+    imass.invertInPlace();
   }
   // redistribution matrix
   // quadrature weight x parametric gradients in quadrature points
 
-  _redistributionFluxes[0] = new fullMatrix<double> (_fs.coefficients.size1(),_integration->size1());
-  _redistributionFluxes[1] = new fullMatrix<double> (_fs.coefficients.size1(),_integration->size1());
-  _redistributionFluxes[2] = new fullMatrix<double> (_fs.coefficients.size1(),_integration->size1());
-  _redistributionSource = new fullMatrix<double> (_fs.coefficients.size1(),_integration->size1());
-  _collocation = new fullMatrix<double> (_integration->size1(),_fs.coefficients.size1());
-  _imass = new fullMatrix<double> (_fs.coefficients.size1(),_fs.coefficients.size1()); 
-
-  double g[256][3],f[256];
   for (int j=0;j<_integration->size1();j++) {
     _fs.df((*_integration)(j,0),
 	   (*_integration)(j,1),
@@ -96,12 +102,8 @@ dgGroupOfElements::dgGroupOfElements(const std::vector<MElement*> &e, int polyOr
       (*_redistributionFluxes[2])(k,j) = g[k][2] * weight;
       (*_redistributionSource)(k,j) = f[k] * weight;
       (*_collocation)(j,k) = f[k];
-      for (int l=0;l<_fs.coefficients.size1();l++) { 
-        (*_imass)(k,l) += f[k]*f[l]*weight;
-      }
     }
   }
-  _imass->invertInPlace();
 }
 
 dgGroupOfElements::~dgGroupOfElements(){
@@ -123,17 +125,17 @@ void dgGroupOfFaces::createFaceElements (const std::vector<MFace> &topo_faces){
   for (int i=0;i<topo_faces.size();i++){
     // compute closures for the interpolation
     int ithFace, sign, rot;
-    _left[i]->getFaceInfo (topo_faces[i], ithFace, sign, rot);
+    getElementLeft(i)->getFaceInfo (topo_faces[i], ithFace, sign, rot);
     _closuresLeft.push_back(&(_fsLeft->getFaceClosure(ithFace, sign, rot)));
-    _right[i]->getFaceInfo (topo_faces[i], ithFace, sign, rot);
+    getElementRight(i)->getFaceInfo (topo_faces[i], ithFace, sign, rot);
     _closuresRight.push_back(&(_fsRight->getFaceClosure(ithFace, sign, rot)));        
     // compute the face element that correspond to the geometrical closure
     // get the vertices of the face
     std::vector<MVertex*> _vertices;
-    const std::vector<int> & geomClosure = _right[i]->getFunctionSpace()->getFaceClosure(ithFace, sign, rot);
+    const std::vector<int> & geomClosure = getElementRight(i)->getFunctionSpace()->getFaceClosure(ithFace, sign, rot);
     for (int j=0; j<geomClosure.size() ; j++){
       int iNod = geomClosure[j];
-      MVertex *v = _left[i]->getVertex(iNod);
+      MVertex *v = getElementLeft(i)->getVertex(iNod);
       _vertices.push_back(v);
     }
     // triangular face
@@ -186,16 +188,16 @@ void dgGroupOfFaces::createEdgeElements (const std::vector<MEdge> &topo_edges){
   // compute all closures
   for (int i=0;i<topo_edges.size();i++){
     int ithEdge, sign;
-    _left[i]->getEdgeInfo (topo_edges[i], ithEdge, sign);
+    getElementLeft(i)->getEdgeInfo (topo_edges[i], ithEdge, sign);
     _closuresLeft.push_back(&(_fsLeft->getEdgeClosure(ithEdge, sign)));
-    _right[i]->getEdgeInfo (topo_edges[i], ithEdge, sign);
+    getElementRight(i)->getEdgeInfo (topo_edges[i], ithEdge, sign);
     _closuresRight.push_back(&(_fsRight->getEdgeClosure(ithEdge, sign)));    
     // get the vertices of the edge
-    const std::vector<int> & geomClosure = _right[i]->getFunctionSpace()->getEdgeClosure(ithEdge, sign);
+    const std::vector<int> & geomClosure = getElementRight(i)->getFunctionSpace()->getEdgeClosure(ithEdge, sign);
     std::vector<MVertex*> _vertices;
     for (int j=0; j<geomClosure.size() ; j++){
       int iNod = geomClosure[j];
-      MVertex *v = _left[i]->getVertex(iNod);
+      MVertex *v = getElementLeft(i)->getVertex(iNod);
       _vertices.push_back(v);
     }
     switch(_vertices.size()){
@@ -222,20 +224,22 @@ void dgGroupOfFaces::init(int pOrder) {
 }
 
 dgGroupOfFaces::dgGroupOfFaces (const std::vector<MFace> &topo_faces, 		  
-				const std::vector<MElement*> &l, 
-				const std::vector<MElement*> &r,
-				int pOrder) : _left(l), _right(r),
-        _fsLeft(_left[0]->getFunctionSpace (pOrder)), _fsRight (_right[0]->getFunctionSpace (pOrder))
+        const std::vector<dgGroupOfElements*> group_list,
+				const std::vector<std::pair<int,int> > &l, 
+				const std::vector<std::pair<int,int> > &r,
+				int pOrder) : _group_list(group_list),_left(l), _right(r),
+        _fsLeft(getElementLeft(0)->getFunctionSpace (pOrder)), _fsRight (getElementRight(0)->getFunctionSpace (pOrder))
 {
   createFaceElements (topo_faces);
   init(pOrder);
 }
 
 dgGroupOfFaces::dgGroupOfFaces (const std::vector<MEdge> &topo_edges, 		  
-				const std::vector<MElement*> &l, 
-				const std::vector<MElement*> &r,
-				int pOrder) : _left(l), _right(r),
-        _fsLeft(_left[0]->getFunctionSpace (pOrder)), _fsRight (_right[0]->getFunctionSpace (pOrder))
+        const std::vector<dgGroupOfElements*> group_list,
+				const std::vector<std::pair<int,int> > &l, 
+				const std::vector<std::pair<int,int> > &r,
+				int pOrder) : _group_list(group_list),_left(l), _right(r),
+        _fsLeft(getElementLeft(0)->getFunctionSpace (pOrder)), _fsRight (getElementRight(0)->getFunctionSpace (pOrder))
 {
   createEdgeElements (topo_edges);
   init(pOrder);
diff --git a/Solver/dgGroupOfElements.h b/Solver/dgGroupOfElements.h
index 61fc87e429054d8fbbffa542792e37f464c7a78a..2b34680d6c53ce28713439131345d9230f42942c 100644
--- a/Solver/dgGroupOfElements.h
+++ b/Solver/dgGroupOfElements.h
@@ -55,6 +55,7 @@ class dgGroupOfElements {
   fullMatrix<double> *_redistributionFluxes[3];
   // redistribution for the source term
   fullMatrix<double> *_redistributionSource;
+  // inverse mass matrix of all elements
   fullMatrix<double> *_imass;
   // dimension of the parametric space and of the real space
   // may be different if the domain is a surface in 3D (manifold)
@@ -75,24 +76,35 @@ public:
   inline const fullMatrix<double> & getCollocationMatrix () const {return *_collocation;}
   inline const fullMatrix<double> & getFluxRedistributionMatrix (int i) const {return *_redistributionFluxes[i];}
   inline const fullMatrix<double> & getSourceRedistributionMatrix () const {return *_redistributionSource;}
-  inline const fullMatrix<double> & getInverseMassMatrix () const {return *_imass;}
   inline double getDetJ (int iElement, int iGaussPoint) const {return (*_mapping)(iElement, 10*iGaussPoint + 9);}
   inline double getInvJ (int iElement, int iGaussPoint, int i, int j) const {return (*_mapping)(iElement, 10*iGaussPoint + i + 3*j);}
-  inline fullMatrix<double> getMapping (int iElement) const {return fullMatrix<double>(*_mapping, iElement, 1);}
+  inline fullMatrix<double> getInverseMassMatrix (int iElement) const {return fullMatrix<double>(*_imass,iElement*getNbNodes(),getNbNodes());}
+  inline const fullMatrix<double> getMapping (int iElement) const {return fullMatrix<double>(*_mapping, iElement, 1);}
 };
 
-/*class dgFace {
+class dgFace {
   int nbGaussPoints;
   MElement *_left, *_right;
   MElement *_face;
   double *_normals;
-  double *_detJ;
-  int *_closureLeft,*_closureRight;
+  const fullMatrix<double> *_solutionRight, *_solutionLeft, *_integration;
 public:
-  dgFace ();
+  dgFace (MElement *face,MElement *left, MElement *right,
+    const fullMatrix<double> &solRight,
+    const fullMatrix<double> &solLeft,
+    const fullMatrix<double> &integration
+    ) : _left(left), _right(right), _face(face),_solutionRight(&solRight),_solutionLeft(&solLeft),_integration(&integration)
+  {}
+  inline const fullMatrix<double> &solutionRight() const { return *_solutionRight; }
+  inline const fullMatrix<double> &solutionLeft() const { return *_solutionLeft; }
+  inline const fullMatrix<double> &integration() const { return *_integration; }
+  inline MElement *left() const { return _left;}
+  inline MElement *right() const { return _right;}
+  inline MElement *face() const { return _face;}
 };
-*/
+
 class dgGroupOfFaces {
+  std::vector<dgGroupOfElements*> _group_list;
   void createFaceElements (const std::vector<MFace> &topo_faces);
   void createEdgeElements (const std::vector<MEdge> &topo_faces);
   void computeFaceNormals();
@@ -100,7 +112,8 @@ class dgGroupOfFaces {
   // the group has always the same types for left and right
   const functionSpace *_fsLeft,*_fsRight, *_fsFace;
   // N elements in the group
-  std::vector<MElement*> _left, _right, _faces;
+  std::vector<std::pair<int,int> >_left, _right;
+  std::vector<MElement *>_faces;
   // Ni integration points, matrix of size Ni x 3 (u,v,weight)
   fullMatrix<double> *_integration;
   // there is a finite number of combinations of orientations, senses
@@ -122,15 +135,30 @@ class dgGroupOfFaces {
   //common part of the 3 constructors
   void init(int pOrder);
 public:
+  inline MElement* getElementLeft (int i) const {return _group_list[_left[i].first]->getElement(_left[i].second);}  
+  inline MElement* getElementRight (int i) const {return _group_list[_right[i].first]->getElement(_right[i].second);}  
+  inline MElement* getFace (int iElement) const {return _faces[iElement];}  
+  const std::vector<int> * getClosureLeft(int iFace) const{ return _closuresLeft[iFace];}
+  const std::vector<int> * getClosureRight(int iFace) const{ return _closuresRight[iFace];}
   dgGroupOfFaces (const std::vector<MFace> &faces, 		  
-		  const std::vector<MElement*> &l, 
-		  const std::vector<MElement*> &r,
+      const std::vector<dgGroupOfElements*> group_list,
+		  const std::vector<std::pair<int,int> > &l, 
+		  const std::vector<std::pair<int,int> > &r,
 		  int pOrder);
   dgGroupOfFaces (const std::vector<MEdge> &edges, 		  
-		  const std::vector<MElement*> &l, 
-		  const std::vector<MElement*> &r,
+      const std::vector<dgGroupOfElements*> group_list,
+		  const std::vector<std::pair<int,int> > &l, 
+		  const std::vector<std::pair<int,int> > &r,
 		  int pOrder);
   virtual ~dgGroupOfFaces ();
+  //this part is common with dgGroupOfElements, we should try polymorphism
+  inline int getNbElements() const {return _faces.size();}
+  inline int getNbNodes() const {return _collocation->size1();}
+  inline int getNbIntegrationPoints() const {return _collocation->size1();}
+  inline const fullMatrix<double> & getCollocationMatrix () const {return *_collocation;}
+  inline const fullMatrix<double> & getIntegrationPointsMatrix () const {return *_integration;}
+  inline const fullMatrix<double> & getRedistributionMatrix () const {return *_redistribution;}
+  inline double getDetJ (int iElement, int iGaussPoint) const {return (*_detJac)(iElement, iGaussPoint);}
 };
 
 
diff --git a/Solver/dgMainTest.cc b/Solver/dgMainTest.cc
index f93e71a079742bba2304ae82afccf7368357f22b..cc0ea70b0f7c678f7c18e069dfc7577b70d902a6 100644
--- a/Solver/dgMainTest.cc
+++ b/Solver/dgMainTest.cc
@@ -8,26 +8,33 @@
 
 
 #include "MElement.h"
-void print (const char *filename, std::vector<MElement *> &els, double *v);
-std::vector<MElement *> get_all_tri(GModel *model);
-
+void print (const char *filename,const dgGroupOfElements &els, double *v);
+void buildGroupAllTri(GModel *model, int order, //in
+                         std::vector<dgGroupOfElements*> &elements, //out
+                         std::vector<dgGroupOfFaces*> &faces); //out
 
 int main(int argc, char **argv){
   GmshMergeFile("input/mesh1.msh");
-  std::vector<MElement *> all_tri=get_all_tri(GModel::current());
-  dgGroupOfElements group(all_tri,1);
-  fullMatrix<double> sol(3,all_tri.size());
-  fullMatrix<double> residu(3,all_tri.size());
+  std::vector<dgGroupOfElements*> elements;
+  std::vector<dgGroupOfFaces*> faces;
+  buildGroupAllTri(GModel::current(),1,elements,faces);
+  int nbNodes=elements[0]->getNbNodes();
+  fullMatrix<double> sol(nbNodes,elements[0]->getNbElements());
+  fullMatrix<double> residu(nbNodes,elements[0]->getNbElements());
   dgAlgorithm algo;
   dgConservationLaw *law = dgNewConservationLawAdvection();
-  algo.residualVolume(*law,group,sol,residu);
-  sol.gemm(group.getInverseMassMatrix(),residu);
-  print("test.pos",all_tri,&sol(0,0));
+  algo.residualVolume(*law,*elements[0],sol,residu);
+  for(int i=0;i<elements[0]->getNbElements();i++) {
+    fullMatrix<double> residuEl(residu,i,1);
+    fullMatrix<double> solEl(sol,i,1);
+    solEl.gemm(elements[0]->getInverseMassMatrix(i),residuEl);
+  }
+  print("test.pos",*elements[0],&sol(0,0));
 }
 
-
-
-std::vector<MElement *> get_all_tri(GModel *model){
+void buildGroupAllTri(GModel *model, int order, //in
+                         std::vector<dgGroupOfElements*> &elements, //out
+                         std::vector<dgGroupOfFaces*> &faces){ //out
   std::vector<GEntity*> entities;
   model->getEntities(entities);
   std::vector<MElement *> all_tri;
@@ -36,15 +43,14 @@ std::vector<MElement *> get_all_tri(GModel *model){
     for (int iel=0; iel<(*itent)->getNumMeshElements(); iel++)
       all_tri.push_back((*itent)->getMeshElement(iel));
   }
-  return all_tri;
+  elements.push_back(new dgGroupOfElements(all_tri,order));
 }
 
-void print (const char *filename, std::vector<MElement *> &els, double *v) {
+void print (const char *filename,const dgGroupOfElements &els, double *v) {
   FILE *file = fopen(filename,"w");
   fprintf(file,"View \"%s\" {\n", filename);
-  int i=0;
-  for(std::vector<MElement *>::iterator itel= els.begin();itel!=els.end();itel++){
-    MElement *el = *itel;
+  for(int iel=0;iel<els.getNbElements();iel++){
+    MElement *el = els.getElement(iel);
     fprintf(file,"ST (");
     for (int iv=0; iv<el->getNumVertices(); iv++) {
       MVertex *vertex = el->getVertex(iv);
@@ -53,7 +59,7 @@ void print (const char *filename, std::vector<MElement *> &els, double *v) {
     }
     fprintf(file,"{");
     for (int iv=0; iv<el->getNumVertices(); iv++)
-      fprintf(file,"%e%c ",v[i++],iv==el->getNumVertices()-1?'}':',');
+      fprintf(file,"%e%c ",*(v++),iv==el->getNumVertices()-1?'}':',');
     fprintf(file,";\n");
   }
   fprintf(file,"};");