From 0c44894171fe78be70a50647895109182470be20 Mon Sep 17 00:00:00 2001
From: Jonathan Lambrechts <jonathan.lambrechts@uclouvain.be>
Date: Fri, 15 Jan 2010 12:41:32 +0000
Subject: [PATCH] dg : first working parallel version

---
 Numeric/fullMatrix.h           |   4 +
 Solver/CMakeLists.txt          |   1 +
 Solver/dgAlgorithm.cpp         |  13 ++-
 Solver/dgAlgorithm.h           |   1 -
 Solver/dgDofContainer.cpp      | 139 +++++++++++++++++++++++++
 Solver/dgDofContainer.h        |  34 +++++++
 Solver/dgGroupOfElements.cpp   |  71 ++++++++++++-
 Solver/dgGroupOfElements.h     |   8 ++
 Solver/dgSystemOfEquations.cpp | 181 +--------------------------------
 Solver/dgSystemOfEquations.h   |  31 +-----
 10 files changed, 266 insertions(+), 217 deletions(-)
 create mode 100644 Solver/dgDofContainer.cpp
 create mode 100644 Solver/dgDofContainer.h

diff --git a/Numeric/fullMatrix.h b/Numeric/fullMatrix.h
index dcbb2416a9..dcf652c6ca 100644
--- a/Numeric/fullMatrix.h
+++ b/Numeric/fullMatrix.h
@@ -224,6 +224,10 @@ class fullMatrix
   {
     for(int i = 0; i < _r * _c; i++) _data[i] = m;
   }
+  inline void setAll(const fullMatrix<scalar> &m) 
+  {
+    for(int i = 0; i < _r * _c; i++) _data[i] = m._data[i];
+  }
   inline void scale(const double s)
   {
     if(s == 0.)
diff --git a/Solver/CMakeLists.txt b/Solver/CMakeLists.txt
index aaea186caf..3392ddca02 100644
--- a/Solver/CMakeLists.txt
+++ b/Solver/CMakeLists.txt
@@ -20,6 +20,7 @@ set(SRC
   dgConservationLawWaveEquation.cpp
   dgConservationLawPerfectGas.cpp
   dgSlopeLimiter.cpp
+  dgDofContainer.cpp
   function.cpp
   functionDerivator.cpp
   luaFunction.cpp
diff --git a/Solver/dgAlgorithm.cpp b/Solver/dgAlgorithm.cpp
index 498f37b4bb..462ea79ade 100644
--- a/Solver/dgAlgorithm.cpp
+++ b/Solver/dgAlgorithm.cpp
@@ -259,7 +259,6 @@ void dgAlgorithm::rungeKutta (const dgConservationLaw &claw,			// conservation l
 			      double h,				         // time-step
 			      dgDofContainer &sol,
 			      dgDofContainer &resd,
-            dgSystemOfEquations *syst,
 			      dgLimiter *limiter,
 			      int orderRK
             )				        // order of RK integrator
@@ -281,8 +280,8 @@ void dgAlgorithm::rungeKutta (const dgConservationLaw &claw,			// conservation l
 
   int nbFields = claw.nbFields();
 
-  dgDofContainer K   (groups,claw);
-  dgDofContainer Unp (groups,claw);
+  dgDofContainer K   (groups,nbFields);
+  dgDofContainer Unp (groups,nbFields);
 
   K._data->scale(0.0);
   K._data->axpy(*(sol._data));
@@ -298,7 +297,7 @@ void dgAlgorithm::rungeKutta (const dgConservationLaw &claw,			// conservation l
     if (limiter){
       limiter->apply(K, groups);
     }
-    syst->scatter(&K);
+    K.scatter();
     this->residual(claw,groups,K._dataProxys,resd._dataProxys);
     K._data->scale(0.);
     for(int k=0; k < groups.getNbElementGroups(); k++) {
@@ -408,11 +407,11 @@ void dgAlgorithm::multirateRungeKutta (const dgConservationLaw &claw,			// conse
    dgDofContainer **K;
    K=new dgDofContainer*[nStages];
    for(int i=0;i<nStages;i++){
-     K[i]=new dgDofContainer(groups,claw);
+     K[i]=new dgDofContainer(groups,nbFields);
      K[i]->_data->scale(0.0);
    }
-   dgDofContainer Unp (groups,claw);
-   dgDofContainer tmp (groups,claw);
+   dgDofContainer Unp (groups,nbFields);
+   dgDofContainer tmp (groups,nbFields);
 
    Unp._data->scale(0.0);
    Unp._data->axpy(*(sol._data));
diff --git a/Solver/dgAlgorithm.h b/Solver/dgAlgorithm.h
index c3dd4aa656..206bfcfd75 100644
--- a/Solver/dgAlgorithm.h
+++ b/Solver/dgAlgorithm.h
@@ -45,7 +45,6 @@ class dgAlgorithm {
 		   double h,	
 		   dgDofContainer &residu,
 		   dgDofContainer &sol,
-       dgSystemOfEquations *syst,
 		   dgLimiter *limiter=NULL,
 		   int orderRK=4);
   static void computeElementaryTimeSteps ( //dofManager &dof, // the DOF manager (maybe useless here)
diff --git a/Solver/dgDofContainer.cpp b/Solver/dgDofContainer.cpp
new file mode 100644
index 0000000000..9d20e7ba14
--- /dev/null
+++ b/Solver/dgDofContainer.cpp
@@ -0,0 +1,139 @@
+#include "GmshConfig.h"
+#include "dgDofContainer.h"
+#include "dgGroupOfElements.h"
+#ifdef HAVE_MPI
+#include "mpi.h"
+#endif
+dgDofContainer::dgDofContainer (dgGroupCollection &groups, int nbFields):
+  _groups(groups)
+{
+  _dataSize = 0;
+  _dataSizeGhost=0;
+  _totalNbElements = 0;
+  _parallelStructureExists = false;
+  _nbFields = nbFields;
+  for (int i=0; i< _groups.getNbElementGroups();i++){
+    int nbNodes    = _groups.getElementGroup(i)->getNbNodes();
+    int nbElements = _groups.getElementGroup(i)->getNbElements();
+    _totalNbElements +=nbElements;
+    _dataSize += nbNodes*_nbFields*nbElements;
+  }
+
+  // allocate the big vectors
+  _data      = new fullVector<double>(_dataSize);
+  // create proxys for each group
+  int offset = 0;
+  _dataProxys.resize(_groups.getNbElementGroups()+_groups.getNbGhostGroups());
+  for (int i=0;i<_groups.getNbElementGroups();i++){    
+    dgGroupOfElements *group = _groups.getElementGroup(i);
+    int nbNodes    = group->getNbNodes();
+    int nbElements = group->getNbElements();
+    _dataProxys[i] = new fullMatrix<double> (&(*_data)(offset),nbNodes, _nbFields*nbElements);
+    offset += nbNodes*_nbFields*nbElements;
+  }  
+
+  //ghosts
+  
+  int totalNbElementsGhost =0;
+  for (int i=0; i<_groups.getNbGhostGroups(); i++){
+    int nbNodes    = _groups.getGhostGroup(i)->getNbNodes();
+    int nbElements = _groups.getGhostGroup(i)->getNbElements();
+    totalNbElementsGhost +=nbElements;
+    _dataSizeGhost += nbNodes*_nbFields*nbElements;
+  }
+
+  _dataProxys.resize(_groups.getNbElementGroups()+_groups.getNbGhostGroups());
+  _ghostData = new fullVector<double>(_dataSizeGhost);
+  offset=0;
+  for (int i=0;i<_groups.getNbGhostGroups();i++){    
+    dgGroupOfElements *group = _groups.getGhostGroup(i);
+    int nbNodes    = group->getNbNodes();
+    int nbElements = group->getNbElements();
+    _dataProxys[i+_groups.getNbElementGroups()] = new fullMatrix<double> (&(*_ghostData)(offset),nbNodes, _nbFields*nbElements);
+    offset += nbNodes*_nbFields*nbElements;
+  }  
+
+}
+
+dgDofContainer::~dgDofContainer (){
+  if(_parallelStructureExists) {
+    delete []countSend;
+    delete []countRecv;
+    delete []shiftSend;
+    delete []shiftRecv;
+    delete []groupShiftRecv;
+    delete []sendBuf;
+    delete []recvBuf;
+  }
+  if (!_dataSize)return;
+  for (int i=0;i<_dataProxys.size();++i) delete _dataProxys[i];
+  delete _data;
+  delete _ghostData;
+}
+
+void dgDofContainer::buildParallelStructure(){
+  if (_parallelStructureExists)
+    return;
+
+  // MPI all2all buffers
+  countSend = new int[Msg::GetCommSize()];
+  shiftSend = new int[Msg::GetCommSize()];
+  countRecv = new int[Msg::GetCommSize()];
+  shiftRecv = new int[Msg::GetCommSize()];
+  groupShiftRecv = new int[_groups.getNbGhostGroups()];
+  for(int i=0;i<Msg::GetCommSize();i++){
+    countSend[i]=0;
+    countRecv[i]=0;
+    for(size_t j=0;j<_groups.getNbImageElementsOnPartition(i);j++){
+      countSend[i] += _groups.getElementGroup(_groups.getImageElementGroup(i,j))->getNbNodes()*_nbFields;
+    }
+  }
+  for(size_t i=0; i<_groups.getNbGhostGroups(); i++){
+    dgGroupOfElements *group = _groups.getGhostGroup(i);
+    groupShiftRecv[i] = countRecv[group->getGhostPartition()];
+    countRecv[group->getGhostPartition()]+=group->getNbElements()*group->getNbNodes()*_nbFields;
+  }
+  shiftSend[0] = shiftRecv[0]=0;
+  int totalSend = countSend[0];
+  int totalRecv = countRecv[0];
+  for(size_t i=1; i<Msg::GetCommSize(); i++){
+    shiftSend[i] = shiftSend[i-1]+countSend[i-1];
+    shiftRecv[i] = shiftRecv[i-1]+countRecv[i-1];
+    totalSend += countSend[i];
+    totalRecv += countRecv[i];
+  }
+  for(size_t i=0; i<_groups.getNbGhostGroups(); i++){
+    dgGroupOfElements *group = _groups.getGhostGroup(i);
+    groupShiftRecv[i] += shiftRecv[group->getGhostPartition()];
+  }
+  sendBuf = new double[totalSend];
+  recvBuf = new double[totalRecv];
+
+  _parallelStructureExists = true;
+}
+
+void dgDofContainer::scatter() {
+  if(!_parallelStructureExists)
+    buildParallelStructure();
+  //1) fill
+  int index=0;
+  for(int i=0;i<Msg::GetCommSize();i++){
+    for(size_t j=0;j<_groups.getNbImageElementsOnPartition(i);j++){
+      fullMatrix<double> &sol = getGroupProxy(_groups.getImageElementGroup(i,j));
+      int eid = _groups.getImageElementPositionInGroup(i,j);
+      for(int l=0;l<_nbFields;l++) {
+        for(int k=0;k<sol.size1();k++) {
+          sendBuf[index++] = sol(k, eid *_nbFields+l);
+        }
+      }
+    }
+  }
+  //2) send
+  MPI_Alltoallv(sendBuf,countSend,shiftSend,MPI_DOUBLE,recvBuf,countRecv,shiftRecv,MPI_DOUBLE,MPI_COMM_WORLD);
+  //3) distribute
+  for(int i=0; i< _groups.getNbGhostGroups();i++) {
+    fullMatrix<double> &sol = getGroupProxy(i+_groups.getNbElementGroups());
+    fullMatrix<double> recvProxy (recvBuf + groupShiftRecv[i], sol.size1(), sol.size2());
+    sol.setAll(recvProxy);
+  }
+}
diff --git a/Solver/dgDofContainer.h b/Solver/dgDofContainer.h
new file mode 100644
index 0000000000..7d4298507d
--- /dev/null
+++ b/Solver/dgDofContainer.h
@@ -0,0 +1,34 @@
+#ifndef _DG_DOF_CONTAINER_H_
+#define _DG_DOF_CONTAINER_H_
+
+#include <vector>
+#include "fullMatrix.h"
+class dgGroupCollection;
+
+struct dgDofContainer {
+private:
+  dgDofContainer (const dgDofContainer&);  
+  int _totalNbElements; 
+  int _nbFields;
+  dgGroupCollection &_groups;
+  int _dataSizeGhost; 
+  fullVector<double> * _ghostData;
+  inline int getDataSize(){return _dataSize;}
+  // parallel
+  void buildParallelStructure();
+  bool _parallelStructureExists;
+  int *countSend,*countRecv,*shiftSend,*shiftRecv,*groupShiftRecv;
+  double *sendBuf, *recvBuf;
+public:
+  //todo move those 3 to private
+  fullVector<double> * _data; // the full data itself
+  std::vector<fullMatrix<double> *> _dataProxys; // proxys 
+  int _dataSize; // the full data size i.e. concerning all groups (not ghost, see bellow)
+
+  inline fullMatrix<double> &getGroupProxy(int gId){ return *(_dataProxys[gId]); }
+  dgDofContainer (dgGroupCollection &groups, int nbFields);
+  ~dgDofContainer ();  
+  int getNbElements() {return _totalNbElements;}
+  void scatter();
+};
+#endif
diff --git a/Solver/dgGroupOfElements.cpp b/Solver/dgGroupOfElements.cpp
index a1867f108e..16c6ac338b 100644
--- a/Solver/dgGroupOfElements.cpp
+++ b/Solver/dgGroupOfElements.cpp
@@ -1,3 +1,4 @@
+#include "GmshConfig.h"
 #include "dgGroupOfElements.h"
 #include "MElement.h"
 #include "polynomialBasis.h"
@@ -7,6 +8,9 @@
 #include "MLine.h"
 #include "MPoint.h"
 #include "GModel.h"
+#ifdef HAVE_MPI
+#include "mpi.h"
+#endif
 
 static fullMatrix<double> * dgGetIntegrationRule (MElement *e, int p){
   int npts;
@@ -515,7 +519,6 @@ dgGroupOfFaces::dgGroupOfFaces (const dgGroupOfElements &elGroup1, const dgGroup
         }
       }
       
-      printf("groupe mixte %d %d elements %d faces\n",elGroup1.getNbElements(),elGroup2.getNbElements(),_faces.size());
       break;
     }
     case 3 : {
@@ -681,8 +684,10 @@ void dgGroupCollection::buildGroups(GModel *model, int dim, int order)
         }else{
           std::multimap<MElement*, short>::iterator ghost=ghostsCells.lower_bound(el);
           while(ghost!= ghostsCells.end() && ghost->first==el){
-            nghosts+=(abs(ghost->second)-1==Msg::GetCommRank());
-            ghostElements[el->getPartition()-1][el->getType()].push_back(el);
+            if(abs(ghost->second)-1==Msg::GetCommRank()){
+              ghostElements[el->getPartition()-1][el->getType()].push_back(el);
+              nghosts+=1;
+            }
             ghost++;
           }
         }
@@ -750,7 +755,65 @@ void dgGroupCollection::buildGroups(GModel *model, int dim, int order)
         delete gof;
     }
   }
-  printf("nbGhostGroups : %i nbElementsGroups : %i\n",getNbGhostGroups(), getNbElementGroups());
+
+  // build the ghosts structure
+  int *nGhostElements = new int[Msg::GetCommSize()];
+  int *nParentElements = new int[Msg::GetCommSize()];
+  for (int i=0;i<Msg::GetCommSize();i++) {
+    nGhostElements[i]=0;
+  }
+  for (size_t i = 0; i< getNbGhostGroups(); i++){
+    dgGroupOfElements *group = getGhostGroup(i);
+    nGhostElements[group->getGhostPartition()] += group->getNbElements();
+  }
+  #ifdef HAVE_MPI
+  MPI_Alltoall(nGhostElements,1,MPI_INT,nParentElements,1,MPI_INT,MPI_COMM_WORLD); 
+  #else
+  nParentElements[0]=nGhostElements[0];
+  #endif
+  int *shiftSend = new int[Msg::GetCommSize()];
+  int *shiftRecv = new int[Msg::GetCommSize()];
+  int *curShiftSend = new int[Msg::GetCommSize()];
+  int totalSend=0,totalRecv=0;
+  for(int i= 0; i<Msg::GetCommSize();i++){
+    shiftSend[i] = (i==0 ? 0 : shiftSend[i-1]+nGhostElements[i-1]);
+    curShiftSend[i] = shiftSend[i];
+    shiftRecv[i] = (i==0 ? 0 : shiftRecv[i-1]+nParentElements[i-1]);
+    totalSend += nGhostElements[i];
+    totalRecv += nParentElements[i];
+  }
+
+  int *idSend = new int[totalSend];
+  int *idRecv = new int[totalRecv];
+  for (int i = 0; i<getNbGhostGroups(); i++){
+    dgGroupOfElements *group = getGhostGroup(i);
+    int part = group->getGhostPartition();
+    for (int j=0; j< group->getNbElements() ; j++){
+      idSend[curShiftSend[part]++] = group->getElement(j)->getNum();
+    }
+  }
+  MPI_Alltoallv(idSend,nGhostElements,shiftSend,MPI_INT,idRecv,nParentElements,shiftRecv,MPI_INT,MPI_COMM_WORLD);
+  //create a Map elementNum :: group, position in group
+  std::map<int, std::pair<int,int> > elementMap;
+  for(size_t i = 0; i< getNbElementGroups(); i++) {
+    dgGroupOfElements *group = getElementGroup(i);
+    for(int j=0; j< group->getNbElements(); j++){
+      elementMap[group->getElement(j)->getNum()]=std::pair<int,int>(i,j);
+    }
+  }
+  _elementsToSend.resize(Msg::GetCommSize());
+  for(int i = 0; i<Msg::GetCommSize();i++){
+    _elementsToSend[i].resize(nParentElements[i]);
+    for(int j=0;j<nParentElements[i];j++){
+      int num = idRecv[shiftRecv[i]+j];
+      _elementsToSend[i][j]=elementMap[num];
+    }
+  }
+  delete []idRecv;
+  delete []idSend;
+  delete []curShiftSend;
+  delete []shiftSend;
+  delete []shiftRecv;
 }
 
 dgGroupCollection::~dgGroupCollection() {
diff --git a/Solver/dgGroupOfElements.h b/Solver/dgGroupOfElements.h
index 7c0f177772..55f742daa4 100644
--- a/Solver/dgGroupOfElements.h
+++ b/Solver/dgGroupOfElements.h
@@ -188,6 +188,10 @@ class dgGroupCollection {
   std::vector<dgGroupOfFaces*> _faceGroups; //interface
   std::vector<dgGroupOfFaces*> _boundaryGroups; //boundary
   std::vector<dgGroupOfElements*> _ghostGroups; //ghost volume
+
+  //{group,id} of the elements to send to each partition for a scatter operation
+  std::vector< std::vector<std::pair<int,int> > >_elementsToSend;
+
   public:
   inline int getNbElementGroups() const {return _elementGroups.size();}
   inline int getNbFaceGroups() const {return _faceGroups.size();}
@@ -198,6 +202,10 @@ class dgGroupCollection {
   inline dgGroupOfFaces *getBoundaryGroup(int i) const {return _boundaryGroups[i];}
   inline dgGroupOfElements *getGhostGroup(int i) const {return _ghostGroups[i];}
 
+  inline int getNbImageElementsOnPartition(int partId) const {return _elementsToSend[partId].size();}
+  inline int getImageElementGroup(int partId, int i) const {return _elementsToSend[partId][i].first;}
+  inline int getImageElementPositionInGroup(int partId, int i) const {return _elementsToSend[partId][i].second;}
+
   void buildGroups (GModel *model,int dimension, int order);
   ~dgGroupCollection();
 };
diff --git a/Solver/dgSystemOfEquations.cpp b/Solver/dgSystemOfEquations.cpp
index ddd220d488..405537ccc1 100644
--- a/Solver/dgSystemOfEquations.cpp
+++ b/Solver/dgSystemOfEquations.cpp
@@ -100,68 +100,13 @@ void dgSystemOfEquations::L2Projection (std::string functionName){
 void dgSystemOfEquations::setup(){
   if (!_claw) throw;
   _groups.buildGroups(_gm,_dimension,_order);
-  // build the ghosts structure
-  int *nGhostElements = new int[Msg::GetCommSize()];
-  int *nParentElements = new int[Msg::GetCommSize()];
-  for (int i=0;i<Msg::GetCommSize();i++) {
-    nGhostElements[i]=0;
-  }
-  for (size_t i = 0; i< _groups.getNbGhostGroups(); i++){
-    dgGroupOfElements *group=_groups.getGhostGroup(i);
-    nGhostElements[group->getGhostPartition()] += group->getNbElements();
-  }
-  #ifdef HAVE_MPI
-  MPI_Alltoall(nGhostElements,1,MPI_INT,nParentElements,1,MPI_INT,MPI_COMM_WORLD); 
-  #else
-  nParentElements[0]=nGhostElements[0];
-  #endif
-  shiftSend = new int[Msg::GetCommSize()];
-  shiftRecv = new int[Msg::GetCommSize()];
-  int *curShiftSend = new int[Msg::GetCommSize()];
-  totalSend=0,totalRecv=0;
-  for(int i= 0; i<Msg::GetCommSize();i++){
-    shiftSend[i] = (i==0 ? 0 : shiftSend[i-1]+nGhostElements[i-1]);
-    curShiftSend[i] = shiftSend[i];
-    shiftRecv[i] = (i==0 ? 0 : shiftRecv[i-1]+nParentElements[i-1]);
-    totalSend+=nGhostElements[i];
-    totalRecv+=nParentElements[i];
-  }
-
-  int *idSend = new int[totalSend];
-  int *idRecv = new int[totalRecv];
-  for (int i = 0; i< _groups.getNbGhostGroups(); i++){
-    dgGroupOfElements *group = _groups.getGhostGroup(i);
-    int part = group->getGhostPartition();
-    for (int j=0; j< group->getNbElements() ; j++){
-      idSend[curShiftSend[part]++] = group->getElement(j)->getNum();
-    }
-  }
-  MPI_Alltoallv(idSend,nGhostElements,shiftSend,MPI_INT,idRecv,nParentElements,shiftRecv,MPI_INT,MPI_COMM_WORLD);
-  //create a Map elementNum :: group, position in group
-  std::map<int, std::pair<int,int> > elementMap;
-  for(size_t i = 0; i< _groups.getNbElementGroups(); i++) {
-    dgGroupOfElements *group = _groups.getElementGroup(i);
-    for(int j=0; j< group->getNbElements(); j++){
-      elementMap[group->getElement(j)->getNum()]=std::pair<int,int>(i,j);
-    }
-  }
-  _elementsToSend.resize(Msg::GetCommSize());
-  for(int i = 0; i<Msg::GetCommSize();i++){
-    _elementsToSend[i].resize(nParentElements[i]);
-    for(int j=0;j<nParentElements[i];j++){
-      int num = idRecv[shiftRecv[i]+j];
-      _elementsToSend[i][j]=elementMap[num];
-    }
-  }
-  // compute the total size of the soution
-  delete curShiftSend;
-  _solution = new dgDofContainer(_groups,*_claw);
-  _rightHandSide = new dgDofContainer(_groups,*_claw);
+  _solution = new dgDofContainer(_groups,_claw->nbFields());
+  _rightHandSide = new dgDofContainer(_groups,_claw->nbFields());
 }
 
 
 double dgSystemOfEquations::RK44(double dt){
-  _algo->rungeKutta(*_claw,_groups, dt,  *_solution, *_rightHandSide, this);
+  _algo->rungeKutta(*_claw,_groups, dt,  *_solution, *_rightHandSide);
   return _solution->_data->norm();
 }
 
@@ -184,13 +129,13 @@ double dgSystemOfEquations::computeInvSpectralRadius(){
 
 double dgSystemOfEquations::RK44_limiter(double dt){
   dgLimiter *sl = new dgSlopeLimiter(_claw);
-  _algo->rungeKutta(*_claw,_groups, dt,  *_solution, *_rightHandSide,this, sl);
+  _algo->rungeKutta(*_claw,_groups, dt,  *_solution, *_rightHandSide, sl);
   delete sl;
   return _solution->_data->norm();
 }
 
 double dgSystemOfEquations::ForwardEuler(double dt){
-  _algo->rungeKutta(*_claw, _groups, dt,  *_solution, *_rightHandSide,this, NULL,1);
+  _algo->rungeKutta(*_claw, _groups, dt,  *_solution, *_rightHandSide, NULL,1);
   return _solution->_data->norm();
 }
 double dgSystemOfEquations::multirateRK43(double dt){
@@ -293,121 +238,5 @@ void dgSystemOfEquations::export_solution_as_is (const std::string &name){
   delete pv;
 }
 
-dgDofContainer::dgDofContainer (dgGroupCollection &groups, const dgConservationLaw &claw):
-  _groups(groups)
-{
-  _dataSize = 0;
-  _dataSizeGhost=0;
-  totalNbElements = 0;
-  int totalNbElementsGhost =0;
-  nbFields = claw.nbFields();
-  for (int i=0; i< _groups.getNbElementGroups();i++){
-    int nbNodes    = _groups.getElementGroup(i)->getNbNodes();
-    int nbElements = _groups.getElementGroup(i)->getNbElements();
-    totalNbElements +=nbElements;
-    _dataSize += nbNodes*nbFields*nbElements;
-  }
-  for (int i=0; i<_groups.getNbGhostGroups(); i++){
-    int nbNodes    = _groups.getGhostGroup(i)->getNbNodes();
-    int nbElements = _groups.getGhostGroup(i)->getNbElements();
-    totalNbElementsGhost +=nbElements;
-    _dataSizeGhost += nbNodes*nbFields*nbElements;
-  }
-
-  // allocate the big vectors
-  _data      = new fullVector<double>(_dataSize);
-  _ghostData = new fullVector<double>(_dataSizeGhost);
-  // create proxys for each group
-  int offset = 0;
-  _dataProxys.resize(_groups.getNbElementGroups()+_groups.getNbGhostGroups());
-  for (int i=0;i<_groups.getNbElementGroups();i++){    
-    dgGroupOfElements *group = _groups.getElementGroup(i);
-    int nbNodes    = group->getNbNodes();
-    int nbElements = group->getNbElements();
-    _dataProxys[i] = new fullMatrix<double> (&(*_data)(offset),nbNodes, nbFields*nbElements);
-    offset += nbNodes*nbFields*nbElements;
-  }  
-  offset=0;
-  for (int i=0;i<_groups.getNbGhostGroups();i++){    
-    dgGroupOfElements *group = _groups.getGhostGroup(i);
-    int nbNodes    = group->getNbNodes();
-    int nbElements = group->getNbElements();
-    _dataProxys[i+_groups.getNbElementGroups()] = new fullMatrix<double> (&(*_ghostData)(offset),nbNodes, nbFields*nbElements);
-    offset += nbNodes*nbFields*nbElements;
-  }  
-}
-
-dgDofContainer::~dgDofContainer (){
-  if (!_dataSize)return;
-  for (int i=0;i<_dataProxys.size();++i) delete _dataProxys[i];
-  delete _data;
-}
 
-void dgSystemOfEquations::scatter(dgDofContainer *vector){
-  //1) count
-  int *countS=new int[Msg::GetCommSize()];
-  int *shiftS=new int[Msg::GetCommSize()];
-  int *countR=new int[Msg::GetCommSize()];
-  int *shiftR=new int[Msg::GetCommSize()];
-  for(int i=0;i<Msg::GetCommSize();i++){
-    countS[i]=0;
-    countR[i]=0;
-    for(size_t j=0;j<_elementsToSend[i].size();j++){
-      countS[i] += _groups.getElementGroup(_elementsToSend[i][j].first)->getNbNodes()*_claw->nbFields();
-    }
-  }
-  for(size_t i=0; i<_groups.getNbGhostGroups(); i++){
-    dgGroupOfElements *group = _groups.getGhostGroup(i);
-    countR[group->getGhostPartition()]+=group->getNbElements()*group->getNbNodes()*_claw->nbFields();
-  }
-  shiftS[0]=shiftR[0]=0;
-  int totalS=countS[0];
-  int totalR=countR[0];
-  for(size_t i=1; i<Msg::GetCommSize(); i++){
-    shiftS[i]=shiftS[i-1]+countS[i-1];
-    shiftR[i]=shiftR[i-1]+countR[i-1];
-    totalS+=countS[i];
-    totalR+=countR[i];
-  }
-  double *send=new double[totalS];
-  double *recv=new double[totalR];
-  //2) fill
-  int index=0;
-  for(int i=0;i<Msg::GetCommSize();i++){
-    for(size_t j=0;j<_elementsToSend[i].size();j++){
-      int gid = _elementsToSend[i][j].first;
-      int eid = _elementsToSend[i][j].second;
-      fullMatrix<double> &sol=vector->getGroupProxy(gid);
-      for(int l=0;l<_claw->nbFields();l++){
-        for(int k=0;k<sol.size1();k++){
-          send[index++] = sol(k,eid*_claw->nbFields()+l);
-          //send[index++] = _groups.getElementGroup(gid)->getElement(eid)->getNum()*9+l*3+k;
-        }
-      }
-    }
-  }
-  
-  //3) send
-  MPI_Alltoallv(send,countS,shiftS,MPI_DOUBLE,recv,countR,shiftR,MPI_DOUBLE,MPI_COMM_WORLD);
-  //4) distribute
-  for(int i=0; i< _groups.getNbGhostGroups();i++){
-    fullMatrix<double>&sol = vector->getGroupProxy(i+_groups.getNbElementGroups());
-    int part = _groups.getGhostGroup(i)->getGhostPartition();
-    int ndof = sol.size1()*sol.size2();
-    for(int j=0;j<sol.size2();j++){
-      for(int k=0;k<sol.size1();k++){
-        sol(k,j)=recv[shiftR[part]++];
-        //int a=(int)recv[shiftR[part]++];
-        //int b= _groups.getGhostGroup(i)->getElement(j/3)->getNum()*9+3*(j%3)+k;
-        ///*if(a!=b)*/printf("%i %i\n",a,b);
-      }
-    }
-  }
-  delete countS;
-  delete countR;
-  delete shiftS;
-  delete shiftR;
-  delete send;
-  delete recv;
-}
 
diff --git a/Solver/dgSystemOfEquations.h b/Solver/dgSystemOfEquations.h
index 81182a3cfb..e8d89dff59 100644
--- a/Solver/dgSystemOfEquations.h
+++ b/Solver/dgSystemOfEquations.h
@@ -10,39 +10,13 @@
 #include "dgConservationLaw.h"
 #include "Gmsh.h"
 #include "dgLimiter.h"
+#include "dgDofContainer.h"
 
-struct dgDofContainer {
-private:
-  dgDofContainer (const dgDofContainer&);  
-  int totalNbElements; 
-  int nbFields;
-  dgGroupCollection &_groups;
-public:
-  int _dataSize; // the full data size i.e. concerning all groups (not ghost, see bellow)
-  int _dataSizeGhost; 
-  std::vector<fullMatrix<double> *> _dataProxys; // proxys 
-  fullVector<double> * _data; // the full data itself
-  fullVector<double> * _ghostData;
-  inline int getDataSize(){return _dataSize;}
-  inline fullMatrix<double> &getGroupProxy(int gId){ return *(_dataProxys[gId]); }
-  dgDofContainer (dgGroupCollection &groups, const dgConservationLaw &claw);
-  ~dgDofContainer ();  
-  int getNbElements() {return totalNbElements;}
-};
 
 class binding;
 
 
 class dgSystemOfEquations {
-//////////////
-  //parallel section, should be moved to a new class
-  int *shiftSend,*shiftRecv;
-  int *nGhostElements,*nParentElements;
-  int totalSend, totalRecv;
-  public :
-  void scatter(dgDofContainer *solution);
-  std::vector< std::vector<std::pair<int,int> > >_elementsToSend; //{group,id} of the elements to send to each proc
-//////////////
   private:
   // the mesh and the model
   GModel *_gm;
@@ -78,8 +52,7 @@ public:
   static void registerBindings(binding *b);
 
   inline const fullMatrix<double> getSolutionProxy (int iGroup, int iElement){
-    return fullMatrix<double> ( *_solution->_dataProxys [iGroup] ,
-				iElement * _claw->nbFields(),_claw->nbFields());
+    return fullMatrix<double> ( _solution->getGroupProxy(iGroup), iElement * _claw->nbFields(),_claw->nbFields());
   }
   void export_solution_as_is (const std::string &fileName);
   void saveSolution (std::string fileName) ;
-- 
GitLab