diff --git a/Solver/dgAlgorithm.cpp b/Solver/dgAlgorithm.cpp
index 447be9837702b26c603a91fbb924cae8d4d865d7..6fe53fa02be80617b4987fddb6ae3b20a80e8ea6 100644
--- a/Solver/dgAlgorithm.cpp
+++ b/Solver/dgAlgorithm.cpp
@@ -9,34 +9,48 @@ void dgAlgorithm::residualVolume ( dofManager &dof, // the DOF manager (maybe us
 				   const dgConservationLaw &claw,   // the conservation law
 				   const groupOfElements & group ) // the residual
 { 
-  // get the solution at quadrature points
-  fullMatrix<double> solutionQp (group.getNbElements() * group.getNbFields(), group.getNbIntegrationPoints());
-  // solutionQp  ( NbE x NbFields , NbQuad)
-  // collocation ( NbNod , NbQuad)
-  // solution    ( NbE x NbFields, nbNodes)
-  group.getSolution().mult ( group.getCollocationMatrix() , solutionQp); 
+  // ----- 1 ----  get the solution at quadrature points
+  // ----- 1.1 --- allocate a matrix of size (nbFields * nbElements, nbQuadraturePoints) 
+  fullMatrix<double> solutionQP (group.getNbElements() * group.getNbFields(), group.getNbIntegrationPoints());
+  // ----- 1.2 --- multiply the solution by the collocation matrix
+  group.getSolution().mult ( group.getCollocationMatrix() , solutionQP); 
+  // ----- 1.3 --- if the conservation law is diffusive, compute the gradients too
+  fullMatrix<double> *gradientSolutionQP= 0;
+  if (claw.diffusiveFlux()){
+     gradientSolutionQP = new  fullMatrix<double> (group.getNbElements() * group.getNbFields() * 3, group.getNbIntegrationPoints());
+     group.getGradientOfSolution().mult ( group.getCollocationMatrix() , solutionQP); 
+  }
   
-  // for all elements of the group,
-  // compute all fluxes, both diffusive and convective, in reference coordinates
+
+  // ----- 2 ----  compute all fluxes (diffusive and convective) at integration points
+  // ----- 2.1 --- allocate elementary fluxes (compued in XYZ coordinates)
   fullMatrix<double> fConv[3] = {fullMatrix<double>( group.getNbIntegrationPoints(), group.nbFields() ),
 				 fullMatrix<double>( group.getNbIntegrationPoints(), group.nbFields() ),
 				 fullMatrix<double>( group.getNbIntegrationPoints(), group.nbFields() )};
   fullMatrix<double> fDiff[3] = {fullMatrix<double>( group.getNbIntegrationPoints(), group.nbFields() ),
 				 fullMatrix<double>( group.getNbIntegrationPoints(), group.nbFields() ),
 				 fullMatrix<double>( group.getNbIntegrationPoints(), group.nbFields() )};
+  // ----- 2.2 --- allocate parametric fluxes (compued in UVW coordinates) for all elements at all integration points
   fullMatrix<double> Fuvw[3] = {fullMatrix<double> (group.getNbElements() * group.getNbFields(), group.getNbIntegrationPoints()),
 				fullMatrix<double> (group.getNbElements() * group.getNbFields(), group.getNbIntegrationPoints()),
 				fullMatrix<double> (group.getNbElements() * group.getNbFields(), group.getNbIntegrationPoints())};
-  // for all elements of the group
+  // ----- 2.3 --- iterate on elements
   for (int iElement=0 ; iElement<group.getNbElements() ;++iElement) {        
-    dgElement DGE = group.getDGElement(iElement);
-    // compute convective and diffusive fluxes in XYZ coordinates
+    // ----- 2.3.1 --- build a small object that contains elementary solution, jacobians, gmsh element
+    fullMatrix<double> solutionQPe (solutionQP, iElement*claw.nbFields(),claw.nbFields() );
+    fullMatrix<double> *gradSolutionQPe;
+    if (claw.diffusiveFlux()) gradSolutionQPe = new fullMatrix<double>(*gradSolutionQP, 3*iElement*claw.nbFields(),3*claw.nbFields() );      
+    else gradSolutionQPe = new fullMatrix<double>
+    dgElement DGE( group.getElement(iElement), solutionQPe, *gradSolutionQPe, group.getIntegrationPointsMatrix());
+    // ----- 2.3.2 --- compute fluxes in XYZ coordinates
     if (claw.convectiveFlux()) (*claw.convectiveFlux())(DGE,fConv);
     if (claw.diffusiveFlux()) (*claw.diffusiveFlux())(DGE,fDiff);
     
+    // ----- 2.3.3 --- compute fluxes in UVW coordinates
     for (int iUVW=0;iUVW<group.getDimUVW();iUVW++) {
-      // proxy to the elementary values
+    // ----- 2.3.3.1 --- get a proxy on the big local flux matrix
       fullMatrix<double> fuvwe(Fuvw[iUVW], iElement*claw.nbFields(),claw.nbFields());
+      // ----- 2.3.3.1 --- compute \vec{f}^{UVW} =\vec{f}^{XYZ} J^{-1} and multiply bt detJ
       for (int iXYZ=0;iXYZ<group.getDimXYZ();iXYZ++) {
 	for (int iPt =0; iPt< group.getNbIntegrationPoints(); iPt++) {
 	  // get the right inv jacobian matrix dU/dX element
@@ -52,8 +66,7 @@ void dgAlgorithm::residualVolume ( dofManager &dof, // the DOF manager (maybe us
       } 
     }
   }
-  // finally, premultiply with the redistribution matrices
-  // this is the "heavy load" part
+  // ----- 3 ---- do the redistribution at nodes using as many BLAS3 operations as there are local coordinates
   for (int iUVW=0;iUVW<group.getDimUVW();iUVW++)
-    group.getResidual().dgemm(group.getCollocationMatrix(iUVW), Fuvw[iUVW]);
+    group.getResidual().dgemm(group.getRedistributionMatrix(iUVW), Fuvw[iUVW]);
 }
diff --git a/Solver/dgGroupOfElements.h b/Solver/dgGroupOfElements.h
index 6f1922ad9ac7f8d613cb3ce5a2fa9de935f7eacd..3f793ea486915ac5b544a2ddd1bf95946bee76cf 100644
--- a/Solver/dgGroupOfElements.h
+++ b/Solver/dgGroupOfElements.h
@@ -20,13 +20,14 @@ class functionSpace;
 
 class dgElement {
   MElement *_element;
-  const fullMatrix<double> &_solution, &_detJ, &_integration;
+  // solution at points
+  const fullMatrix<double> &_solution, &_integration, &_gradients;
 public:
-  dgElement (MElement *e, 
-	     const fullMatrix<double> &sol,
-	     const fullMatrix<double> &detJ,
-	     const fullMatrix<double> &integ)
-    : _element(e), _solution(sol), _detJ(detJ), _integration(integ)
+  dgElement (MElement *e, const fullMatrix<double> &sol, const fullMatrix<double> &integ)
+    : _element(e), _solution(sol), _integration(integ), _gradients(sol)
+  {}
+  dgElement (MElement *e, const fullMatrix<double> &sol, const fullMatrix<double> &grads, const fullMatrix<double> &integ)
+    : _element(e), _solution(sol), _integration(integ), _gradients(grad)
   {}
 };
 
@@ -49,6 +50,8 @@ class dgGroupOfElements {
   fullMatrix<double> *_redistributionFluxes[3];
   // redistribution for the source term
   fullMatrix<double> *_redistributionSource;
+  // the "finite element" gradient of the solution for this group (not owned)
+  fullMatrix<double> *_gradSolution;
   // the solution for this group (not owned)
   fullMatrix<double> *_solution;
   // the residual for this group (not owned)
@@ -62,16 +65,18 @@ class dgGroupOfElements {
 public:
   dgGroupOfElements (const std::vector<MElement*> &e, int pOrder);
   virtual ~dgGroupOfElements ();
-  inline dgElement getDGElement(int i) const {return dgElement(_elements[i], getSolution(i), getMapping(i), *_integration);}
   inline int getNbElements() const {return _elements.size();}
   inline int getNbFields() const {return _nbFields;}
   inline int getNbNodes() const {return _collocation.size1();}
   inline int getNbIntegrationPoints() const {return _collocation.size2();}
   inline int getDimUVW () const {return _dimUVW;}
   inline int getDimXYZ () const {return _dimXYZ;}
+  inline const MElement* getElement (int iElement) const {return _elements[iElement];}  
+  inline const fullMatrix<double> & getIntegrationPointsMatrix () const {return *_integration;}
   inline const fullMatrix<double> & getCollocationMatrix () const {return *_collocation;}
   inline const fullMatrix<double> & getRedistributionMatrix (int i) const {return *_redistribution[i];}
   inline const fullMatrix<double> & getSolution () const {return *_solution;}
+  inline const fullMatrix<double> & getGradientOfSolution () const {return *_gradSolution;}
   // get a proxy on the solution for element iElement
   inline fullMatrix<double> & getSolution (int iElement) const {return fullMatrix<double>(*_solution, iElement*_nbFields, _nbFields);}
   inline const fullMatrix<double> & getResidual () const {return *_solution;}