diff --git a/src/common/aka_grid_tmpl.hh b/src/common/aka_grid_tmpl.hh
index 1bcad788d..3c815bbb4 100644
--- a/src/common/aka_grid_tmpl.hh
+++ b/src/common/aka_grid_tmpl.hh
@@ -1,396 +1,396 @@
 /**
  * @file   aka_grid_inline_impl.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Jul 28 15:27:55 2011
  *
  * @brief
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 RegularGrid<T>::RegularGrid(UInt dimension, Real * lower_bounds,
 			    Real * upper_bounds, Real * spacing) : dimension(dimension) {
 
   //  UInt total_nb_cells = 1;
   total_nb_cells = 1;
   this->dimension = dimension;
 
   std::fill_n(this->upper_bounds, 3, 0);
   std::fill_n(this->lower_bounds, 3, 0);
   std::fill_n(this->spacing, 3, 0);
   std::fill_n(this->nb_cells, 3, 0);
 
   for (UInt i = 0; i < dimension; ++i) {
     // +2 to add an extra cell on each side
 
     this->nb_cells[i] = UInt(std::ceil((upper_bounds[i] - lower_bounds[i]) / spacing[i]) + 2);
     this->lower_bounds[i] = lower_bounds[i] - spacing[i];
     this->upper_bounds[i] = this->lower_bounds[i] + this->nb_cells[i] * spacing[i];
 
     this->spacing[i]      = spacing[i];
 
     total_nb_cells *= this->nb_cells[i];
   }
   this->data.resize(total_nb_cells);
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 class RegularGrid<T>::Cell {
 public:
   Cell() {
     id = 0;
     position[0] = position[1] = position[2] = 0;
     grid = NULL;
   }
 
   Cell(const RegularGrid<T> & grid) : grid(&grid) { id = 0; std::fill_n(position, 3, 0); }
 
   Cell(const Cell & cell) {
     if(&cell != this) {
       id = cell.id;
       position[0] = cell.position[0];
       position[1] = cell.position[1];
       position[2] = cell.position[2];
       grid = cell.grid;
     }
   }
 
   Cell & operator=(const Cell & cell) {
     if(&cell != this) {
       id = cell.id;
       position[0] = cell.position[0];
       position[1] = cell.position[1];
       position[2] = cell.position[2];
       grid = cell.grid;
     }
     return *this;
   }
 
   bool operator==(const Cell & cell) const { return id == cell.id; }
   bool operator!=(const Cell & cell) const { return id != cell.id; }
 
   inline void updateID() {
     id = 0;
     for (UInt i = grid->getDimension() - 1; i > 0; --i) {
       id += position[i];
       id *= grid->getNbCells(i - 1);
     }
     id += position[0];
   }
 
   friend class RegularGrid<T>;
   friend class GridSynchronizer;
 private:
   const RegularGrid<T> * grid;
 
   UInt id;
   UInt position[3];
 };
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline typename RegularGrid<T>::iterator RegularGrid<T>::beginCell(const typename RegularGrid<T>::Cell & cell) {
   return data(cell.id).begin();
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline typename RegularGrid<T>::iterator RegularGrid<T>::endCell(const typename RegularGrid<T>::Cell cell) {
   return data(cell.id).end();
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline typename RegularGrid<T>::const_iterator RegularGrid<T>::beginCell(const typename RegularGrid<T>::Cell & cell) const {
   return data(cell.id).begin();
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline typename RegularGrid<T>::const_iterator RegularGrid<T>::endCell(const typename RegularGrid<T>::Cell & cell) const {
   return data(cell.id).end();
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void RegularGrid<T>::insert(const T & d, const types::RVector & position) {
   UInt num_cell = getCell(position).id;
   AKANTU_DEBUG_ASSERT(num_cell < total_nb_cells,
 		      "The position is not in the grid (" << num_cell
 		      << " > " << total_nb_cells << ") : " << position);
   data(num_cell).push_back(d);
 }
 
 // /* -------------------------------------------------------------------------- */
 // template<typename T>
 // void RegularGrid<T>::count(const types::RVector & position) {
 //   Cell cell = getCell(position);
 //   UInt num_cell = cell.id;
 //   // std::cout << num_cell << " - "
 //   // 	    << cell.position[0] << ", " << cell.position[1] << ", " << cell.position[2] << " : "
 //   // 	    << position[0] << ", " << position[1] << ", " << position[2]
 //   // 	    << std::endl;
 //   data.rowOffset(num_cell)++;
 // }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline typename RegularGrid<T>::Cell RegularGrid<T>::getCell(const types::RVector & position) const {
   Cell cell(*this);
   for (UInt i = 0; i < dimension; ++i) {
     cell.position[i] = getCell(position(i), i);
   }
 
   cell.updateID();
 
   return cell;
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline UInt RegularGrid<T>::getCell(Real position, UInt direction) const {
   return UInt(std::floor((position - lower_bounds[direction]) / spacing[direction]));
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 struct RegularGrid<T>::neighbor_cells_iterator : private std::iterator<std::forward_iterator_tag, UInt> {
   neighbor_cells_iterator(const RegularGrid & grid,
 			  const Cell & cell,
 			  bool end) : cell(cell), grid(grid) {
     std::fill_n(position_start, 3, -1);
     std::fill_n(position_end  , 3,  1);
 
     for (UInt i = 0; i < 3; ++i) {
       if((grid.getNbCells(i) == 0) ||                  // no cells in this direction
 	 (cell.position[i] == 0))                      // first cell in this direction
 	position_start[i] = 0;
 
       if((grid.getNbCells(i) == 0) ||                  // no cells in this direction
 	 (cell.position[i] == grid.getNbCells(i) - 1)) // last cell in this direction
 	position_end[i] = 0;
       position[i] = end ? position_end[i] : position_start[i];
     }
 
     updateIt();
     if(end) { (this->it)++; }
   };
 
   neighbor_cells_iterator(const neighbor_cells_iterator & it) :  cell(it.cell),
 								 it(it.it),
 								 grid(it.grid) {
     std::copy(it.position      , it.position       + 3, position      );
     std::copy(it.position_start, it.position_start + 3, position_start);
     std::copy(it.position_end  , it.position_end   + 3, position_end  );
   };
 
   neighbor_cells_iterator& operator++() {
     bool last = false;
     if(position[0] < position_end[0]) {
       position[0]++;
     } else {
       position[0] = position_start[0];
       if(position[1] < position_end[1]) {
 	position[1]++;
       } else {
 	position[1] = position_start[1];
 	if(position[2] < position_end[2]) {
 	  position[2]++;
 	} else {
 	  last = true;
 	}
       }
     }
 
     if(last) ++it;
     else {
       updateIt();
     }
     return *this;
   };
 
   neighbor_cells_iterator operator++(int) { neighbor_cells_iterator tmp(*this); operator++(); return tmp; };
   bool operator==(const neighbor_cells_iterator& rhs) { return cell == rhs.cell && it = rhs.it; };
   bool operator!=(const neighbor_cells_iterator& rhs) { return cell != rhs.cell || it != rhs.it; };
 
   Cell operator*() {
     Cell cur_cell(grid);
     for (UInt i = 0; i < 3; ++i) cur_cell.position[i] = cell.position[i] + position[i];
     cur_cell.updateID();
     return cur_cell;
   };
 
 private:
   void updateIt() {
     it = 0;
     for (UInt i = 0; i < 3; ++i) it = it * 3 + (position[i] + 1);
   }
 
 private:
   //  UInt cur_cell; //current position of the iterator
   const Cell & cell; //central cell
   UInt it; // number representing the current neighbor in base 3;
 
   Int position_start[3], position_end[3], position[3];
 
   const RegularGrid & grid;
 };
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline typename RegularGrid<T>::neighbor_cells_iterator RegularGrid<T>::beginNeighborCells(const typename RegularGrid<T>::Cell & cell) {
   return neighbor_cells_iterator(*this, cell, false);
 }
 
 template<typename T>
 inline typename RegularGrid<T>::neighbor_cells_iterator RegularGrid<T>::endNeighborCells(const typename RegularGrid<T>::Cell & cell) {
   return neighbor_cells_iterator(*this, cell, true);
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void RegularGrid<T>::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   stream << space << "RegularGrid<" << debug::demangle(typeid(T).name()) << "> [" << std::endl;
   stream << space << " + dimension    : " << this->dimension << std::endl;
   stream << space << " + lower_bounds : {"
 	 << this->lower_bounds[0] << ", "
 	 << this->lower_bounds[1] << ", "
 	 << this->lower_bounds[2] << "}" << std::endl;
   stream << space << " + upper_bounds : {"
 	 << this->upper_bounds[0] << ", "
 	 << this->upper_bounds[1] << ", "
 	 << this->upper_bounds[2] << "}" << std::endl;
   stream << space << " + spacing      : {"
 	 << this->spacing[0] << ", "
 	 << this->spacing[1] << ", "
 	 << this->spacing[2] << "}" << std::endl;
   stream << space << " + nb_cells     : " << this->total_nb_cells << " - {"
 	 << this->nb_cells[0] << ", "
 	 << this->nb_cells[1] << ", "
 	 << this->nb_cells[2] << "}" << std::endl;
   stream << space << "]" << std::endl;
 
 }
 
 
 /* -------------------------------------------------------------------------- */
 __END_AKANTU__
 #include "mesh.hh"
 __BEGIN_AKANTU__
 
 template<typename T>
 void RegularGrid<T>::saveAsMesh(Mesh & mesh) const {
   Vector<Real> & nodes = const_cast<Vector<Real> &>(mesh.getNodes());
   UInt nb_nodes = 1;
 
 
   for (UInt i = 0; i < dimension; ++i) {
     nb_nodes *= (nb_cells[i] + 1);
   }
   nodes.resize(nb_nodes);
 
   if(dimension == 1) {
     for (UInt n = 0; n < nb_nodes; ++n) {
-      nodes.at(n, 0) = n * spacing[0] + lower_bounds[0];
+      nodes(n, 0) = n * spacing[0] + lower_bounds[0];
     }
 
     mesh.addConnectivityType(_segment_2);
     Vector<UInt> & connectivity = const_cast<Vector<UInt> &>(mesh.getConnectivity(_segment_2));
     connectivity.resize(total_nb_cells);
 
     for (UInt e = 0; e < nb_cells[0]; ++e) {
       connectivity(e, 0) = e;
       connectivity(e, 1) = e + 1;
     }
   }
 
   if(dimension == 2) {
     UInt nnx = nb_cells[0] + 1;
     UInt nny = nb_cells[1] + 1;
 
     for (UInt nx = 0; nx < nnx; ++nx) {
       for (UInt ny = 0; ny < nny; ++ny) {
 	UInt n = nx * nny + ny;
 	nodes(n, 0) = nx * spacing[0] + lower_bounds[0];
 	nodes(n, 1) = ny * spacing[1] + lower_bounds[1];
       }
     }
 
     mesh.addConnectivityType(_quadrangle_4);
     Vector<UInt> & connectivity = const_cast<Vector<UInt> &>(mesh.getConnectivity(_quadrangle_4));
     connectivity.resize(total_nb_cells);
     for (UInt ex = 0; ex < nb_cells[0]; ++ex) {
       for (UInt ey = 0; ey < nb_cells[1]; ++ey) {
 	UInt e = (ex * nb_cells[1] + ey);
 	connectivity(e, 0) = ex       * nny + ey;
 	connectivity(e, 1) = (ex + 1) * nny + ey;
 	connectivity(e, 2) = (ex + 1) * nny + ey + 1;
 	connectivity(e, 3) = ex       * nny + ey + 1;
       }
     }
   }
 
   if(dimension == 3) {
     UInt nnx = nb_cells[0] + 1;
     UInt nny = nb_cells[1] + 1;
     UInt nnz = nb_cells[2] + 1;
 
     for (UInt nx = 0; nx < nnx; ++nx) {
       for (UInt ny = 0; ny < nny; ++ny) {
 	for (UInt nz = 0; nz < nnz; ++nz) {
 	  UInt n = (nx * nny + ny) * nnz + nz;
 	  nodes(n, 0) = nx * spacing[0] + lower_bounds[0];
 	  nodes(n, 1) = ny * spacing[1] + lower_bounds[1];
 	  nodes(n, 2) = nz * spacing[2] + lower_bounds[2];
 	}
       }
     }
 
     mesh.addConnectivityType(_hexahedron_8);
     Vector<UInt> & connectivity = const_cast<Vector<UInt> &>(mesh.getConnectivity(_hexahedron_8));
     connectivity.resize(total_nb_cells);
     for (UInt ex = 0; ex < nb_cells[0]; ++ex) {
       for (UInt ey = 0; ey < nb_cells[1]; ++ey) {
 	for (UInt ez = 0; ez < nb_cells[2]; ++ez) {
 	  UInt e = (ex * nb_cells[1] + ey) * nb_cells[2] + ez;
 	  connectivity(e, 0) = (ex     * nny + ey  ) * nnz + ez;
 	  connectivity(e, 1) = ((ex+1) * nny + ey  ) * nnz + ez;
 	  connectivity(e, 2) = ((ex+1) * nny + ey+1) * nnz + ez;
 	  connectivity(e, 3) = (ex     * nny + ey+1) * nnz + ez;
 	  connectivity(e, 4) = (ex     * nny + ey  ) * nnz + ez+1;
 	  connectivity(e, 5) = ((ex+1) * nny + ey  ) * nnz + ez+1;
 	  connectivity(e, 6) = ((ex+1) * nny + ey+1) * nnz + ez+1;
 	  connectivity(e, 7) = (ex     * nny + ey+1) * nnz + ez+1;
 	}
       }
     }
   }
 }
diff --git a/src/common/aka_vector.hh b/src/common/aka_vector.hh
index aac3d72d9..9ab2ba20c 100644
--- a/src/common/aka_vector.hh
+++ b/src/common/aka_vector.hh
@@ -1,369 +1,364 @@
 /**
  * @file   aka_vector.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Jun 17 10:04:55 2010
  *
  * @brief  class of vectors
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_VECTOR_HH__
 #define __AKANTU_VECTOR_HH__
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 /* -------------------------------------------------------------------------- */
 #include <typeinfo>
 #include <vector>
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 class Matrix;
 
 /// class that afford to store vectors in static memory
 class VectorBase {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   VectorBase(const ID & id = "");
 
   virtual ~VectorBase();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// get the amount of space allocated in bytes
   inline UInt getMemorySize() const;
 
   /// set the size to zero without freeing the allocated space
   inline void empty();
 
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   AKANTU_GET_MACRO(AllocatedSize, allocated_size, UInt);
 
   AKANTU_GET_MACRO(Size, size, UInt);
 
   AKANTU_GET_MACRO(NbComponent, nb_component, UInt);
 
   AKANTU_GET_MACRO(ID, id, const ID &);
 
   AKANTU_GET_MACRO(Tag, tag, const std::string &);
   AKANTU_SET_MACRO(Tag, tag, const std::string &);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// id of the vector
   ID id;
 
   /// the size allocated
   UInt allocated_size;
 
   /// the size used
   UInt size;
 
   /// number of components
   UInt nb_component;
 
   /// size of the stored type
   UInt size_of_type;
 
   /// User defined tag
   std::string tag;
 };
 
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 namespace types {
   class Matrix;
   template<typename T> class Vector;
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T, bool is_scal = is_scalar<T>::value >
 class Vector : public VectorBase {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   typedef T                  value_type;
   typedef value_type &       reference;
   typedef value_type *       pointer_type;
   typedef const value_type & const_reference;
 
   /// Allocation of a new vector
   inline Vector(UInt size = 0, UInt nb_component = 1,
 		const ID & id = "");
 
   /// Allocation of a new vector with a default value
   Vector(UInt size, UInt nb_component,
   	 const value_type def_values[], const ID & id = "");
 
   /// Allocation of a new vector with a default value
   Vector(UInt size, UInt nb_component,
 	 const_reference value, const ID & id = "");
 
   /// Copy constructor (deep copy if deep=true)
   Vector(const Vector<value_type, is_scal>& vect, bool deep = true, const ID & id = "");
 
   /// Copy constructor (deep copy)
   Vector(const std::vector<value_type> & vect);
 
 
   virtual inline ~Vector();
 
   /* ------------------------------------------------------------------------ */
   /* Iterator                                                                 */
   /* ------------------------------------------------------------------------ */
   /// \todo protected: does not compile with intel  check why
 public:
   template <class R, class IR = R, bool issame = is_same<IR, T>::value >
   class iterator_internal;
 public:
   /* ------------------------------------------------------------------------ */
   // template<typename R, int fps = 0> class iterator : public iterator_internal<R> {};
   // template<typename R, int fps = 0> class const_iterator : public iterator_internal<const R> {};
   /* ------------------------------------------------------------------------ */
   //template<class R> using iterator = iterator_internal<R>;
 
   template<typename R = T>
   class iterator : public iterator_internal<R> {
   public:
     typedef iterator_internal<R> parent;
     typedef typename parent::value_type	       value_type;
     typedef typename parent::pointer	       pointer;
     typedef typename parent::reference	       reference;
     typedef typename parent::difference_type   difference_type;
     typedef typename parent::iterator_category iterator_category;
   public:
     iterator() : parent() {};
     iterator(pointer_type data, UInt offset) : parent(data, offset) {};
     iterator(pointer warped) : parent(warped) {};
     iterator(const iterator & it) : parent(it) {};
     iterator(const parent & it) : parent(it) {};
 
     inline iterator operator+(difference_type n)
     { return parent::operator+(n);; }
     inline iterator operator-(difference_type n)
     { return parent::operator-(n);; }
     inline difference_type operator-(const iterator & b)
     { return parent::operator-(b); }
 
     inline iterator & operator++()
     { parent::operator++(); return *this; };
     inline iterator & operator--()
     { parent::operator--(); return *this; };
     inline iterator & operator+=(const UInt n)
     { parent::operator+=(n); return *this; }
   };
 
   /* ------------------------------------------------------------------------ */
   //template<class R> using const_iterator = iterator_internal<const R, R>;
 
   template<typename R = T>
   class const_iterator : public iterator_internal<const R, R> {
   public:
     typedef iterator_internal<const R, R> parent;
     typedef typename parent::value_type	       value_type;
     typedef typename parent::pointer	       pointer;
     typedef typename parent::reference	       reference;
     typedef typename parent::difference_type   difference_type;
     typedef typename parent::iterator_category iterator_category;
   public:
     const_iterator() : parent() {};
     const_iterator(pointer_type data, UInt offset) : parent(data, offset) {};
     const_iterator(pointer warped) : parent(warped) {};
     const_iterator(const parent & it) : parent(it) {};
 
     inline const_iterator operator+(difference_type n)
     { return parent::operator+(n); }
     inline const_iterator operator-(difference_type n)
     { return parent::operator-(n); }
     inline difference_type operator-(const const_iterator & b)
     { return parent::operator-(b); }
 
     inline const_iterator & operator++()
     { parent::operator++(); return *this; };
     inline const_iterator & operator--()
     { parent::operator--(); return *this; };
     inline const_iterator & operator+=(const UInt n)
     { parent::operator+=(n); return *this; }
 
   };
 
   inline iterator<T> begin();
   inline iterator<T> end();
   inline const_iterator<T> begin() const;
   inline const_iterator<T> end() const;
 
   inline iterator< types::Vector<T> > begin(UInt n);
   inline iterator< types::Vector<T> > end(UInt n);
   inline const_iterator< types::Vector<T> > begin(UInt n) const;
   inline const_iterator< types::Vector<T> > end(UInt n) const;
 
   inline iterator< types::Matrix > begin(UInt m, UInt n);
   inline iterator< types::Matrix > end(UInt m, UInt n);
   inline const_iterator< types::Matrix > begin(UInt m, UInt n) const;
   inline const_iterator< types::Matrix > end(UInt m, UInt n) const;
 
   /// /!\ to use with caution
   inline iterator< types::Matrix > begin_reinterpret(UInt m, UInt n,
 						     UInt size, UInt nb_component);
   inline iterator< types::Matrix > end_reinterpret(UInt m, UInt n, UInt size, UInt nb_component);
   inline const_iterator< types::Matrix > begin_reinterpret(UInt m, UInt n,
 							   UInt size, UInt nb_component) const;
   inline const_iterator< types::Matrix > end_reinterpret(UInt m, UInt n,
 							 UInt size, UInt nb_component) const;
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
-  /// get jth componemt of the ith tuple in read-only
-  inline const_reference get(UInt i, UInt j = 0) const;
-  /// get jth component of the ith tuple
-  inline reference at(UInt i, UInt j = 0);
-
   /// add an  element at  the end  of the vector  with the  value value  for all
   /// component
   inline void push_back(const_reference value);
 
   /// add an element at the end of the vector
   inline void push_back(const value_type new_elem[]);
 
   template<typename Ret>
   inline void push_back(const iterator<Ret> & it);
 
   /**
    * remove an element and move the last one in the hole
    * /!\ change the order in the vector
    */
   inline void erase(UInt i);
 
   template<typename R>
   inline void erase(const iterator<R> & it);
 
 
   /// change the size of the vector and allocate more memory if needed
   void resize(UInt size);
 
   /// change the number of components by interlacing data
   void extendComponentsInterlaced(UInt multiplicator, UInt stride);
 
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   //  Vector<T, is_scal>& operator=(const Vector<T, is_scal>& vect);
 
   /// search elem in the vector, return  the position of the first occurrence or
   /// -1 if not found
   Int find(const_reference elem) const;
   Int find(T elem[]) const;
 
   /// set a vvector to 0
   inline void clear() { std::fill_n(values, size*nb_component, T()); };
 
   /// copy the content of an other vector
   void copy(const Vector<T, is_scal> & vect);
 
   /// give the address of the memory allocated for this vector
   T * storage() const { return values; };
 
 protected:
   /// perform the allocation for the constructors
   void allocate(UInt size, UInt nb_component = 1);
 
   /// resize without initializing the memory
   void resizeUnitialized(UInt new_size);
 
   /* ------------------------------------------------------------------------ */
   /* Operators                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   Vector<T, is_scal> & operator-=(const Vector<T, is_scal> & vect);
   Vector<T, is_scal> & operator+=(const Vector<T, is_scal> & vect);
   Vector<T, is_scal> & operator*=(const T & alpha);
 
   inline reference operator()(UInt i, UInt j = 0);
   inline const_reference operator()(UInt i, UInt j = 0) const;
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   UInt getSize() const{ return this->size; };
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 public:
   /// array of values
   T * values; // /!\ very dangerous
 
 };
 
 __END_AKANTU__
 
 #include "aka_types.hh"
 __BEGIN_AKANTU__
 
 #include "aka_vector_tmpl.hh"
 
 /* -------------------------------------------------------------------------- */
 /* Inline Functions Vector<T, is_scal>                                                 */
 /* -------------------------------------------------------------------------- */
 template <typename T, bool is_scal>
 inline std::ostream & operator<<(std::ostream & stream, const Vector<T, is_scal> & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 /* -------------------------------------------------------------------------- */
 /* Inline Functions VectorBase                                                */
 /* -------------------------------------------------------------------------- */
 inline std::ostream & operator<<(std::ostream & stream, const VectorBase & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 
 __END_AKANTU__
 
 
 #endif /* __AKANTU_VECTOR_HH__ */
diff --git a/src/common/aka_vector_tmpl.hh b/src/common/aka_vector_tmpl.hh
index a6d25cdb3..76947a0b9 100644
--- a/src/common/aka_vector_tmpl.hh
+++ b/src/common/aka_vector_tmpl.hh
@@ -1,902 +1,846 @@
 /**
  * @file   aka_vector_inline_impl.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Jul 15 00:09:33 2010
  *
  * @brief  Inline functions of the classes Vector<T> and VectorBase
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 /* Inline Functions Vector<T>                                                 */
 /* -------------------------------------------------------------------------- */
 
 __END_AKANTU__
 
 #include <memory>
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline T & Vector<T, is_scal>::operator()(UInt i, UInt j) {
   AKANTU_DEBUG_ASSERT(size > 0,
 		      "The vector \"" << id << "\" is empty");
   AKANTU_DEBUG_ASSERT((i < size) && (j < nb_component),
 		      "The value at position [" << i << "," << j
 		      << "] is out of range in vector \"" << id << "\"");
   return values[i*nb_component + j];
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline const T & Vector<T, is_scal>::operator()(UInt i, UInt j) const {
   AKANTU_DEBUG_ASSERT(size > 0,
 		      "The vector \"" << id << "\" is empty");
   AKANTU_DEBUG_ASSERT((i < size) && (j < nb_component),
 		      "The value at position [" << i << "," << j
 		      << "] is out of range in vector \"" << id << "\"");
   return values[i*nb_component + j];
 }
 
-
-/* -------------------------------------------------------------------------- */
-template <class T, bool is_scal>
-inline T & Vector<T, is_scal>::at(UInt i, UInt j) {
-  AKANTU_DEBUG_IN();
-  AKANTU_DEBUG_ASSERT(size > 0,
-		      "The vector is empty");
-  AKANTU_DEBUG_ASSERT((i < size) && (j < nb_component),
-		      "The value at position [" << i << "," << j
-		      << "] is out of range");
-
-  AKANTU_DEBUG_OUT();
-  return values[i*nb_component + j];
-}
-
-/* -------------------------------------------------------------------------- */
-template <class T, bool is_scal>
-inline const T & Vector<T, is_scal>::get(UInt i, UInt j) const{
-  AKANTU_DEBUG_IN();
-  AKANTU_DEBUG_ASSERT(size > 0,
-		      "The vector is empty");
-  AKANTU_DEBUG_ASSERT((i < size) && (j < nb_component),
-		      "The value at position [" << i << "," << j
-		      << "] is out of range");
-
-  AKANTU_DEBUG_OUT();
-  return values[i*nb_component + j];
-}
-
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline void Vector<T, is_scal>::push_back(const T & value) {
-  //  AKANTU_DEBUG_IN();
   UInt pos = size;
 
   resizeUnitialized(size+1);
 
-  /// @todo see if with std::uninitialized_fill it allow to build vector of objects
-
   std::uninitialized_fill_n(values + pos * nb_component, nb_component, value);
-
-  // for (UInt i = 0; i < nb_component; ++i) {
-  //   values[pos*nb_component + i] = value;
-  // }
-
-  //  AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline void Vector<T, is_scal>::push_back(const T new_elem[]) {
-  //  AKANTU_DEBUG_IN();
   UInt pos = size;
 
   resizeUnitialized(size+1);
 
   T * tmp = values + nb_component * pos;
   std::uninitialized_copy(new_elem, new_elem + nb_component, tmp);
-
-  // for (UInt i = 0; i < nb_component; ++i) {
-  //   values[pos*nb_component + i] = new_elem[i];
-  // }
-  //  AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 template<class Ret>
 inline void Vector<T, is_scal>::push_back(const Vector<T, is_scal>::iterator<Ret> & it) {
   UInt pos = size;
 
   resizeUnitialized(size+1);
 
   T * tmp = values + nb_component * pos;
   T * new_elem = it.data();
   std::uninitialized_copy(new_elem, new_elem + nb_component, tmp);
 }
 
 /* -------------------------------------------------------------------------- */
 
 
 
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline void Vector<T, is_scal>::erase(UInt i){
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT((size > 0),
 		      "The vector is empty");
   AKANTU_DEBUG_ASSERT((i < size),
-		      "The element at position [" << i << "] is out of range");
+		      "The element at position [" << i << "] is out of range (" << i << ">=" << size << ")");
 
 
   if(i != (size - 1)) {
     for (UInt j = 0; j < nb_component; ++j) {
       values[i*nb_component + j] = values[(size-1)*nb_component + j];
     }
   }
 
   resize(size - 1);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Vector<T, is_scal> & Vector<T, is_scal>::operator-=(const Vector<T, is_scal> & vect) {
   AKANTU_DEBUG_ASSERT((size == vect.size) && (nb_component == vect.nb_component),
 		      "The too vector don't have the same sizes");
 
   T * a = values;
   T * b = vect.values;
   for (UInt i = 0; i < size*nb_component; ++i) {
     *a -= *b;
     ++a;++b;
   }
 
   return *this;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Vector<T, is_scal> & Vector<T, is_scal>::operator+=(const Vector<T, is_scal> & vect) {
   AKANTU_DEBUG_ASSERT((size == vect.size) && (nb_component == vect.nb_component),
 		      "The too vector don't have the same sizes");
 
   T * a = values;
   T * b = vect.values;
   for (UInt i = 0; i < size*nb_component; ++i) {
     *a++ += *b++;
   }
 
   return *this;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Vector<T, is_scal> & Vector<T, is_scal>::operator*=(const T & alpha) {
   T * a = values;
   for (UInt i = 0; i < size*nb_component; ++i) {
     *a++ *= alpha;
   }
 
   return *this;
 }
 
 /* -------------------------------------------------------------------------- */
-/* Functions Vector<T, is_scal>                                                        */
+/* Functions Vector<T, is_scal>                                               */
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Vector<T, is_scal>::Vector (UInt size,
 			    UInt nb_component,
 			    const ID & id) :
   VectorBase(id), values(NULL) {
   AKANTU_DEBUG_IN();
   allocate(size, nb_component);
 
   if(!is_scal) {
     T val = T();
     std::uninitialized_fill(values, values + size*nb_component, val);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Vector<T, is_scal>::Vector (UInt size,
 			    UInt nb_component,
 			    const T def_values[],
 			    const ID & id) :
   VectorBase(id), values(NULL) {
   AKANTU_DEBUG_IN();
   allocate(size, nb_component);
 
   T * tmp = values;
 
   for (UInt i = 0; i < size; ++i) {
     tmp = values + nb_component * i;
     std::uninitialized_copy(def_values, def_values + nb_component, tmp);
-    // for (UInt j = 0; j < nb_component; ++j) {
-    //   values[i*nb_component + j] = def_values[j];
-    // }
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Vector<T, is_scal>::Vector (UInt size,
 			    UInt nb_component,
 			    const T & value,
 			    const ID & id) :
   VectorBase(id), values(NULL) {
   AKANTU_DEBUG_IN();
   allocate(size, nb_component);
 
   std::uninitialized_fill_n(values, size*nb_component, value);
 
-  // for (UInt i = 0; i < nb_component*size; ++i) {
-  //   values[i] = value;
-  // }
-
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Vector<T, is_scal>::Vector(const Vector<T, is_scal> & vect,
 			   bool deep,
 			   const ID & id) {
   AKANTU_DEBUG_IN();
   this->id = (id == "") ? vect.id : id;
 
   if (deep) {
     allocate(vect.size, vect.nb_component);
     T * tmp = values;
     std::uninitialized_copy(vect.values, vect.values + size * nb_component, tmp);
-    // for (UInt i = 0; i < size; ++i) {
-    //   for (UInt j = 0; j < nb_component; ++j) {
-    // 	values[i*nb_component + j] = vect.values[i*nb_component + j];
-    //   }
-    // }
   } else {
     this->values = vect.values;
     this->size = vect.size;
     this->nb_component = vect.nb_component;
     this->allocated_size = vect.allocated_size;
     this->size_of_type = vect.size_of_type;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Vector<T, is_scal>::Vector(const std::vector<T>& vect) {
   AKANTU_DEBUG_IN();
   this->id = "";
 
   allocate(vect.size(), 1);
   T * tmp = values;
   std::uninitialized_copy(&(vect[0]), &(vect[size-1]), tmp);
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Vector<T, is_scal>::~Vector () {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG(dblAccessory, "Freeing "
 	       << allocated_size*nb_component*sizeof(T) / 1024.
 	       << "kB (" << id <<")");
 
   if(values){
     if(!is_scal)
       for (UInt i = 0; i < size * nb_component; ++i) {
 	T * obj = values+i;
 	obj->~T();
       }
     free(values);
   }
   size = allocated_size = 0;
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 void Vector<T, is_scal>::allocate(UInt size,
 				  UInt nb_component) {
   AKANTU_DEBUG_IN();
   if (size == 0){
     values = NULL;
   } else {
     values = static_cast<T*>(malloc(nb_component * size * sizeof(T)));
     AKANTU_DEBUG_ASSERT(values != NULL,
 			"Cannot allocate "
 			<< nb_component * size * sizeof(T) / 1024.
 			<< "kB (" << id <<")");
   }
 
   if (values == NULL) {
     this->size = this->allocated_size = 0;
   } else {
     AKANTU_DEBUG(dblAccessory, "Allocated "
 		 << size * nb_component * sizeof(T) / 1024.
 		 << "kB (" << id <<")");
     this->size = this->allocated_size = size;
   }
 
   this->size_of_type = sizeof(T);
   this->nb_component = nb_component;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 void Vector<T, is_scal>::resize(UInt new_size) {
   UInt old_size = size;
 
   T * old_values = values;
   if(new_size < size) {
     for (UInt i = new_size * nb_component; i < size * nb_component; ++i) {
       T * obj = old_values+i;
       obj->~T();
     }
   }
 
   resizeUnitialized(new_size);
 
 
   T val = T();
   if(size > old_size)
     std::uninitialized_fill(values + old_size*nb_component, values + size*nb_component, val);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 void Vector<T, is_scal>::resizeUnitialized(UInt new_size) {
   //  AKANTU_DEBUG_IN();
   // free some memory
   if(new_size <= allocated_size) {
     if(allocated_size - new_size > AKANTU_MIN_ALLOCATION) {
       AKANTU_DEBUG(dblAccessory, "Freeing "
 		   << (allocated_size - size)*nb_component*sizeof(T) / 1024.
 		   << "kB (" << id <<")");
 
       // Normally there are no allocation problem when reducing an array
       T * tmp_ptr = static_cast<T*>(realloc(values, new_size * nb_component * sizeof(T)));
       if(new_size != 0 && tmp_ptr == NULL) {
 	AKANTU_DEBUG_ERROR("Cannot free data (" << id << ")"
 			   << " [current allocated size : " << allocated_size << " | "
 			   << "requested size : " << new_size << "]");
       }
       values = tmp_ptr;
       allocated_size = new_size;
     }
 
     size = new_size;
 
     //    AKANTU_DEBUG_OUT();
     return;
   }
 
   // allocate more memory
   UInt size_to_alloc = (new_size - allocated_size < AKANTU_MIN_ALLOCATION) ?
     allocated_size + AKANTU_MIN_ALLOCATION : new_size;
 
   T *tmp_ptr = static_cast<T*>(realloc(values, size_to_alloc * nb_component * sizeof(T)));
   AKANTU_DEBUG_ASSERT(tmp_ptr != NULL,
 		     "Cannot allocate "
 		      << size_to_alloc * nb_component * sizeof(T) / 1024.
 		      << "kB");
   if (tmp_ptr == NULL) {
     AKANTU_DEBUG_ERROR("Cannot allocate more data (" << id << ")"
 		       << " [current allocated size : " << allocated_size << " | "
 		       << "requested size : " << new_size << "]");
   }
 
   AKANTU_DEBUG(dblAccessory, "Allocating "
 	       << (size_to_alloc - allocated_size)*nb_component*sizeof(T) / 1024.
 	       << "kB");
 
   allocated_size = size_to_alloc;
   size = new_size;
   values = tmp_ptr;
 
   //  AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 void Vector<T, is_scal>::extendComponentsInterlaced(UInt multiplicator,
 						    UInt block_size) {
   AKANTU_DEBUG_IN();
 
   if (multiplicator == 1) return;
 
   AKANTU_DEBUG_ASSERT(multiplicator > 1,
   		      "invalid multiplicator");
   AKANTU_DEBUG_ASSERT(nb_component%block_size == 0,
 		      "stride must divide actual number of components");
 
   values = static_cast<T*>(realloc(values, nb_component*multiplicator*size* sizeof(T)));
 
   UInt new_component = nb_component/block_size * multiplicator;
 
   for (UInt i = 0,k=size-1; i < size; ++i,--k) {
     for (UInt j = 0; j < new_component; ++j) {
       UInt m = new_component - j -1;
       UInt n = m/multiplicator;
       for (UInt l = 0,p=block_size-1;  l < block_size; ++l,--p) {
 	values[k*nb_component*multiplicator+m*block_size+p] =
 	  values[k*nb_component+n*block_size+p];
       }
     }
   }
 
   nb_component = nb_component * multiplicator;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Int Vector<T, is_scal>::find(const T & elem) const {
   AKANTU_DEBUG_IN();
   UInt i = 0;
   for (; (i < size) && (values[i] != elem); ++i);
 
   AKANTU_DEBUG_OUT();
   return (i == size) ? -1 : (Int) i;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Int Vector<T, is_scal>::find(T elem[]) const {
   AKANTU_DEBUG_IN();
   T * it = values;
   UInt i = 0;
   for (;i < size; ++i) {
     if(*it == elem[0]) {
       T * cit = it;
       UInt c = 0;
       for(; (c < nb_component) && (*cit == elem[c]); ++c, ++cit);
       if(c == nb_component) {
 	AKANTU_DEBUG_OUT();
 	return i;
       }
     }
     it += nb_component;
   }
   return -1;
 }
 
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 void Vector<T, is_scal>::copy(const Vector<T, is_scal>& vect) {
   AKANTU_DEBUG_IN();
 
   if(AKANTU_DEBUG_TEST(dblWarning))
     if(vect.nb_component != nb_component) {
       AKANTU_DEBUG(dblWarning, "The two vectors do not have the same number of components");
     }
   //  this->id = vect.id;
   resize((vect.size * vect.nb_component) / nb_component);
 
   T * tmp = values;
   std::uninitialized_copy(vect.values, vect.values + size * nb_component, tmp);
   //  memcpy(this->values, vect.values, vect.size * vect.nb_component * sizeof(T));
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 void Vector<T, is_scal>::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   Real real_size = allocated_size * nb_component * size_of_type / 1024.0;
 
   std::streamsize prec        = stream.precision();
   std::ios_base::fmtflags ff  = stream.flags();
 
   stream.setf (std::ios_base::showbase);
   stream.precision(2);
 
   stream << space << "Vector<" << debug::demangle(typeid(T).name()) << "> [" << std::endl;
   stream << space << " + id             : " << this->id << std::endl;
   stream << space << " + size           : " << this->size << std::endl;
   stream << space << " + nb_component   : " << this->nb_component << std::endl;
   stream << space << " + allocated size : " << this->allocated_size << std::endl;
   stream << space << " + memory size    : "
 	 << real_size << "kB" << std::endl;
   if(!AKANTU_DEBUG_LEVEL_IS_TEST())
     stream << space << " + address        : " << std::hex << this->values
 	   << std::dec << std::endl;
 
   stream.precision(prec);
   stream.flags(ff);
 
   if(AKANTU_DEBUG_TEST(dblDump)) {
     stream << space << " + values         : {";
     for (UInt i = 0; i < this->size; ++i) {
       stream << "{";
       for (UInt j = 0; j < this->nb_component; ++j) {
 	stream << this->values[i*nb_component + j];
 	if(j != this->nb_component - 1) stream << ", ";
       }
       stream << "}";
       if(i != this->size - 1) stream << ", ";
     }
     stream << "}" << std::endl;
   }
   stream << space << "]" << std::endl;
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* Inline Functions VectorBase                                                */
 /* -------------------------------------------------------------------------- */
 
 inline UInt VectorBase::getMemorySize() const {
  return allocated_size * nb_component * size_of_type;
 }
 
 inline void VectorBase::empty() {
   size = 0;
 }
 
 /* -------------------------------------------------------------------------- */
 /* Iterators                                                                  */
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 template<class R, class IR, bool is_r_scal>
 class Vector<T, is_scal>::iterator_internal {
 public:
   typedef R                               value_type;
   typedef R*                              pointer;
   typedef R&                              reference;
   typedef IR                              internal_value_type;
   typedef IR*                             internal_pointer;
   typedef std::ptrdiff_t                  difference_type;
   typedef std::random_access_iterator_tag iterator_category;
 
 public:
   iterator_internal() : offset(0), initial(NULL), ret(NULL) {};
 
   iterator_internal(pointer_type data, UInt offset)  :
     offset(offset),
     initial(data),
     ret(new value_type(data)) {
     AKANTU_DEBUG_ASSERT(offset == ret->size(),
 			"The iterator_internal is not compatible with the type "
 			<< typeid(value_type).name());
   }
 
   iterator_internal(pointer warped)  : offset(warped->size()),
 				       initial(warped->storage()),
 				       ret(const_cast<internal_pointer>(warped)) {
   }
 
   iterator_internal(const iterator_internal & it) {
     if(this != &it) {
       this->offset = it.offset;
       this->initial = it.initial;
       this->ret = new internal_value_type(*it.ret);
     }
   }
 
   virtual ~iterator_internal() { delete ret; };
 
   inline iterator_internal & operator=(const iterator_internal & it) {
     if(this != &it) {
       this->offset = it.offset;
       this->initial = it.initial;
       if(this->ret) this->ret->shallowCopy(*it.ret);
       else this->ret = new internal_value_type(*it.ret);
     }
     return *this;
   }
 
   inline reference operator*() { return *ret; };
   inline pointer operator->() { return ret; };
   inline iterator_internal & operator++() { ret->values += offset; return *this; };
   inline iterator_internal & operator--() { ret->values -= offset; return *this; };
 
   inline iterator_internal & operator+=(const UInt n) { ret->values += offset * n; return *this; }
   inline iterator_internal & operator-=(const UInt n) { ret->values -= offset * n; return *this; }
 
   inline reference operator[](const UInt n) { ret->values = initial + n*offset; return *ret; }
 
   inline bool operator==(const iterator_internal & other) { return (*this).ret->values == other.ret->values; }
   inline bool operator!=(const iterator_internal & other) { return (*this).ret->values != other.ret->values; }
   inline bool operator <(const iterator_internal & other) { return (*this).ret->values  < other.ret->values; }
   inline bool operator<=(const iterator_internal & other) { return (*this).ret->values <= other.ret->values; }
   inline bool operator> (const iterator_internal & other) { return (*this).ret->values >  other.ret->values; }
   inline bool operator>=(const iterator_internal & other) { return (*this).ret->values >= other.ret->values; }
 
   inline iterator_internal operator+(difference_type n) { iterator_internal tmp(*this); tmp += n; return tmp; }
   inline iterator_internal operator-(difference_type n) { iterator_internal tmp(*this); tmp -= n; return tmp; }
 
 
   inline difference_type operator-(const iterator_internal & b) { return ret->values - b.ret->values; }
 
 
   inline pointer_type data() const {
     return ret->storage();
   }
 
 protected:
   UInt offset;
   pointer_type initial;
   internal_pointer ret;
 };
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline Vector<T, is_scal>::iterator< types::Vector<T> > Vector<T, is_scal>::begin(UInt n) {
   AKANTU_DEBUG_ASSERT(nb_component == n,
 		      "The iterator is not compatible with the type Vector("
 		      << n<< ")");
   return iterator< types::Vector<T> >(new types::Vector<T>(values, n));
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline Vector<T, is_scal>::iterator< types::Vector<T> > Vector<T, is_scal>::end(UInt n) {
   AKANTU_DEBUG_ASSERT(nb_component == n,
 		      "The iterator is not compatible with the type Vector("
 		      << n<< ")");
   return iterator< types::Vector<T> >(new types::Vector<T>(values + nb_component * size,
 							   n));
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline Vector<T, is_scal>::const_iterator< types::Vector<T> > Vector<T, is_scal>::begin(UInt n) const {
   AKANTU_DEBUG_ASSERT(nb_component == n,
 		      "The iterator is not compatible with the type Vector("
 		      << n<< ")");
   return const_iterator< types::Vector<T> >(new types::Vector<T>(values, n));
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline Vector<T, is_scal>::const_iterator< types::Vector<T> > Vector<T, is_scal>::end(UInt n) const {
   AKANTU_DEBUG_ASSERT(nb_component == n,
 		      "The iterator is not compatible with the type Vector("
 		      << n<< ")");
   return const_iterator< types::Vector<T> >(new types::Vector<T>(values + nb_component * size,
 							   n));
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline Vector<Real>::iterator<types::Matrix> Vector<Real>::begin(UInt m, UInt n) {
   AKANTU_DEBUG_ASSERT(nb_component == n*m,
 		      "The iterator is not compatible with the type Matrix("
 		      << m << "," << n<< ")");
   return iterator< types::Matrix >(new types::Matrix(values, m, n));
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline Vector<Real>::iterator<types::Matrix> Vector<Real>::end(UInt m, UInt n) {
   AKANTU_DEBUG_ASSERT(nb_component == n*m,
 		      "The iterator is not compatible with the type Matrix("
 		      << m << "," << n<< ")");
   return iterator<types::Matrix>(new types::Matrix(values + nb_component * size, m, n));
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline Vector<Real>::const_iterator<types::Matrix> Vector<Real>::begin(UInt m, UInt n) const {
   AKANTU_DEBUG_ASSERT(nb_component == n*m,
 		      "The iterator is not compatible with the type Matrix("
 		      << m << "," << n<< ")");
   return const_iterator< types::Matrix >(new types::Matrix(values, m, n));
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline Vector<Real>::const_iterator<types::Matrix> Vector<Real>::end(UInt m, UInt n) const {
   AKANTU_DEBUG_ASSERT(nb_component == n*m,
 		      "The iterator is not compatible with the type Matrix("
 		      << m << "," << n<< ")");
   return const_iterator<types::Matrix>(new types::Matrix(values + nb_component * size, m, n));
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline Vector<Real>::iterator< types::Matrix >
 Vector<Real>::begin_reinterpret(UInt m, UInt n,
 				__attribute__((unused)) UInt size,
 				__attribute__((unused)) UInt nb_component) {
   AKANTU_DEBUG_ASSERT(nb_component * size == this->nb_component * this->size,
 		      "The new values for size (" << size
 		      << ") and nb_component (" << nb_component <<
 		      ") are not compatible with the one of this vector");
 
   AKANTU_DEBUG_ASSERT(nb_component == n*m,
 		      "The iterator is not compatible with the type Matrix("
 		      << m << "," << n<< ")");
 
   return iterator< types::Matrix >(new types::Matrix(values + nb_component * 0, m, n));
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline Vector<Real>::iterator< types::Matrix >
 Vector<Real>::end_reinterpret(UInt m, UInt n,
 			      UInt size,
 			      UInt nb_component) {
   AKANTU_DEBUG_ASSERT(nb_component * size == this->nb_component * this->size,
 		      "The new values for size (" << size
 		      << ") and nb_component (" << nb_component <<
 		      ") are not compatible with the one of this vector");
 
   AKANTU_DEBUG_ASSERT(nb_component == n*m,
 		      "The iterator is not compatible with the type Matrix("
 		      << m << "," << n<< ")");
 
   return iterator<types::Matrix>(new types::Matrix(values + nb_component * size, m, n));
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline Vector<Real>::const_iterator< types::Matrix >
 Vector<Real>::begin_reinterpret(UInt m, UInt n,
 				__attribute__((unused)) UInt size,
 				__attribute__((unused)) UInt nb_component) const {
   AKANTU_DEBUG_ASSERT(nb_component * size == this->nb_component * this->size,
 		      "The new values for size (" << size
 		      << ") and nb_component (" << nb_component <<
 		      ") are not compatible with the one of this vector");
 
   AKANTU_DEBUG_ASSERT(nb_component == n*m,
 		      "The iterator is not compatible with the type Matrix("
 		      << m << "," << n<< ")");
 
   return const_iterator< types::Matrix >(new types::Matrix(values + nb_component * 0, m, n));
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline Vector<Real>::const_iterator< types::Matrix >
 Vector<Real>::end_reinterpret(UInt m, UInt n,
 			      UInt size,
 			      UInt nb_component) const {
   AKANTU_DEBUG_ASSERT(nb_component * size == this->nb_component * this->size,
 		      "The new values for size (" << size
 		      << ") and nb_component (" << nb_component <<
 		      ") are not compatible with the one of this vector");
 
   AKANTU_DEBUG_ASSERT(nb_component == n*m,
 		      "The iterator is not compatible with the type Matrix("
 		      << m << "," << n<< ")");
 
   return const_iterator<types::Matrix>(new types::Matrix(values + nb_component * size, m, n));
 }
 
 
 /* -------------------------------------------------------------------------- */
 /**
  * Specialization for scalar types
  */
 template <class T, bool is_scal>
 template <class R, class IR>
 class Vector<T, is_scal>::iterator_internal<R, IR, true> {
 public:
   typedef R                               value_type;
   typedef R*                              pointer;
   typedef R&                              reference;
   typedef IR                              internal_value_type;
   typedef IR*                             internal_pointer;
   typedef std::ptrdiff_t                  difference_type;
   typedef std::random_access_iterator_tag iterator_category;
 
 public:
   iterator_internal(pointer data = NULL, __attribute__ ((unused)) UInt offset = 1) : ret(data), initial(data) { };
   iterator_internal(const iterator_internal & it) {
     if(this != &it) { this->ret = it.ret; this->initial = it.initial; }
   }
 
   virtual ~iterator_internal() { };
 
   inline iterator_internal & operator=(const iterator_internal & it)
   { if(this != &it) { this->ret = it.ret; this->initial = it.initial; } return *this; }
 
   inline reference operator*() { return *ret; };
   inline pointer operator->() { return ret; };
   inline iterator_internal & operator++() { ++ret; return *this; };
   inline iterator_internal & operator--() { --ret; return *this; };
 
   inline iterator_internal & operator+=(const UInt n) { ret += n; return *this; }
   inline iterator_internal & operator-=(const UInt n) { ret -= n; return *this; }
 
   inline reference operator[](const UInt n) { ret = initial + n; return *ret; }
 
   inline bool operator==(const iterator_internal & other) { return ret == other.ret; }
   inline bool operator!=(const iterator_internal & other) { return ret != other.ret; }
   inline bool operator< (const iterator_internal & other) { return ret <  other.ret; }
   inline bool operator<=(const iterator_internal & other) { return ret <= other.ret; }
   inline bool operator> (const iterator_internal & other) { return ret >  other.ret; }
   inline bool operator>=(const iterator_internal & other) { return ret >= other.ret; }
 
   inline iterator_internal operator-(difference_type n) { return iterator_internal(ret - n); }
   inline iterator_internal operator+(difference_type n) { return iterator_internal(ret + n); }
 
   inline difference_type operator-(const iterator_internal & b) { return ret - b.ret; }
 
   inline pointer data() const { return ret; }
 
 protected:
   pointer ret;
   pointer initial;
 };
 
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 template<typename R>
 inline void Vector<T, is_scal>::erase(const iterator<R> & it) {
   T * curr = it.getCurrentStorage();
   UInt pos = (curr - values) / nb_component;
   erase(pos);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline Vector<T, is_scal>::iterator<T> Vector<T, is_scal>::begin() {
   AKANTU_DEBUG_ASSERT(nb_component == 1, "this iterator cannot be used on a vector which has nb_component != 1");
   return iterator<T>(values);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline Vector<T, is_scal>::iterator<T> Vector<T, is_scal>::end() {
   AKANTU_DEBUG_ASSERT(nb_component == 1, "this iterator cannot be used on a vector which has nb_component != 1");
   return iterator<T>(values + size);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline Vector<T, is_scal>::const_iterator<T> Vector<T, is_scal>::begin() const {
   AKANTU_DEBUG_ASSERT(nb_component == 1, "this iterator cannot be used on a vector which has nb_component != 1");
   return const_iterator<T>(values);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 inline Vector<T, is_scal>::const_iterator<T> Vector<T, is_scal>::end() const {
   AKANTU_DEBUG_ASSERT(nb_component == 1, "this iterator cannot be used on a vector which has nb_component != 1");
   return const_iterator<T>(values + size);
 }
diff --git a/src/fem/by_element_type.hh b/src/fem/by_element_type.hh
index 2f0f14bbb..430535cc5 100644
--- a/src/fem/by_element_type.hh
+++ b/src/fem/by_element_type.hh
@@ -1,182 +1,185 @@
 /**
  * @file   by_element_type.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Aug  4 14:40:34 2011
  *
  * @brief  storage class by element type
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_BY_ELEMENT_TYPE_HH__
 #define __AKANTU_BY_ELEMENT_TYPE_HH__
 
 #include "aka_common.hh"
 #include "aka_vector.hh"
 #include "aka_memory.hh"
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /* ByElementType                                                              */
 /* -------------------------------------------------------------------------- */
 
 template<class Stored> class ByElementType {
 protected:
   typedef std::map<ElementType, Stored> DataMap;
 public:
   ByElementType(const ID & id = "by_element_type",
 		const ID & parent_id = "");
   ~ByElementType();
 
   inline static std::string printType(const ElementType & type, const GhostType & ghost_type);
 
   inline bool exists(ElementType type, GhostType ghost_type = _not_ghost) const;
 
   inline const Stored & operator()(const ElementType & type,
 				   const GhostType & ghost_type = _not_ghost) const;
   inline Stored & operator()(const ElementType & type,
 			     const GhostType & ghost_type = _not_ghost);
 
   inline Stored & operator()(const Stored & insert,
 			     const ElementType & type,
 			     const GhostType & ghost_type = _not_ghost);
 
   void printself(std::ostream & stream, int indent = 0) const;
 
   /* ------------------------------------------------------------------------ */
   /* Element type Iterator                                                    */
   /* ------------------------------------------------------------------------ */
   class type_iterator : private std::iterator<std::forward_iterator_tag, const ElementType> {
   public:
     typedef const ElementType   value_type;
     typedef const ElementType*  pointer;
     typedef const ElementType&  reference;
   protected:
     typedef typename ByElementType<Stored>::DataMap::const_iterator DataMapIterator;
   public:
     type_iterator(DataMapIterator & list_begin,
 		  DataMapIterator & list_end,
 		  UInt dim,
 		  ElementKind ek);
 
     type_iterator(const type_iterator & it);
 
     inline reference operator*();
     inline type_iterator & operator++();
     type_iterator operator++(int);
     inline bool operator==(const type_iterator & other);
     inline bool operator!=(const type_iterator & other);
 
   private:
     DataMapIterator list_begin;
     DataMapIterator list_end;
     UInt dim;
     ElementKind kind;
   };
 
   inline type_iterator firstType(UInt dim = 0,
 				 GhostType ghost_type = _not_ghost,
 				 ElementKind kind = _ek_not_defined) const;
   inline type_iterator lastType(UInt dim = 0,
 				GhostType ghost_type = _not_ghost,
 				ElementKind kind = _ek_not_defined) const;
 
   inline void setID(const ID & id) { this->id = id; }
 
 protected:
   inline DataMap & getData(GhostType ghost_type);
   inline const DataMap & getData(GhostType ghost_type) const;
 
 public:
   AKANTU_GET_MACRO(ID, id, ID);
 /* -------------------------------------------------------------------------- */
 protected:
   ID id;
 
   DataMap data;
   DataMap ghost_data;
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* Some typedefs                                                              */
 /* -------------------------------------------------------------------------- */
 
 template <typename T>
 class ByElementTypeVector : public ByElementType<Vector<T> *>, protected Memory {
 protected:
   typedef typename ByElementType<Vector<T> *>::DataMap DataMap;
 public:
   ByElementTypeVector() {};
   // ByElementTypeVector(const ID & id = "by_element_type_vector",
   // 		      const MemoryID & memory_id = 0) :
   //   ByElementType<Vector<T> *>(id, memory_id) {};
   ByElementTypeVector(const ID & id, const ID & parent_id,
 		      const MemoryID & memory_id = 0) :
     ByElementType<Vector<T> *>(id, parent_id), Memory(memory_id) {};
 
   inline Vector<T> & alloc(UInt size,
 			   UInt nb_component,
 			   const ElementType & type,
 			   const GhostType & ghost_type);
 
   inline void alloc(UInt size,
 		    UInt nb_component,
 		    const ElementType & type);
 
   inline const Vector<T> & operator()(const ElementType & type,
 				      const GhostType & ghost_type = _not_ghost) const;
 
   inline Vector<T> & operator()(const ElementType & type,
 				const GhostType & ghost_type = _not_ghost);
 
   inline void setVector(const ElementType & type,
 			const GhostType & ghost_type,
 			const Vector<T> & vect);
 
   inline void free();
+
+  inline void onElementsRemoved(const ByElementTypeVector<UInt> & new_numbering);
+
 };
 
 /// to store data Vector<Real> by element type
 typedef ByElementTypeVector<Real> ByElementTypeReal;
 /// to store data Vector<Int> by element type
 typedef ByElementTypeVector<Int>  ByElementTypeInt;
 /// to store data Vector<UInt> by element type
 typedef ByElementTypeVector<UInt> ByElementTypeUInt;
 
 /// Map of data of type UInt stored in a mesh
 typedef std::map<std::string, Vector<UInt> *> UIntDataMap;
 typedef ByElementType<UIntDataMap> ByElementTypeUIntDataMap;
 
 // /* -------------------------------------------------------------------------- */
 // /* inline functions                                                           */
 // /* -------------------------------------------------------------------------- */
 
 // #if defined (AKANTU_INCLUDE_INLINE_IMPL)
 // #  include "by_element_type_inline_impl.cc"
 // #endif
 
 
 __END_AKANTU__
 
 #endif /* __AKANTU_BY_ELEMENT_TYPE_HH__ */
diff --git a/src/fem/by_element_type_tmpl.hh b/src/fem/by_element_type_tmpl.hh
index c96c3b901..6423556f0 100644
--- a/src/fem/by_element_type_tmpl.hh
+++ b/src/fem/by_element_type_tmpl.hh
@@ -1,368 +1,399 @@
 /**
  * @file   by_element_type_inline_impl.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Aug  4 14:41:29 2011
  *
  * @brief
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 /* ByElementType                                                              */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 template<class Stored>
 inline std::string ByElementType<Stored>::printType(const ElementType & type,
                                                     const GhostType & ghost_type) {
   std::stringstream sstr; sstr << "(" << ghost_type << ":" << type << ")";
   return sstr.str();
 }
 
 /* -------------------------------------------------------------------------- */
 template<class Stored>
 inline bool ByElementType<Stored>::exists(ElementType type, GhostType ghost_type) const {
   return this->getData(ghost_type).find(type) != this->getData(ghost_type).end();
 }
 
 /* -------------------------------------------------------------------------- */
 template<class Stored>
 inline const Stored & ByElementType<Stored>::operator()(const ElementType & type,
                                                         const GhostType & ghost_type) const {
   typename DataMap::const_iterator it =
     this->getData(ghost_type).find(type);
 
   if(it == this->getData(ghost_type).end())
     AKANTU_EXCEPTION("No element of type "
                      << ByElementType<Stored>::printType(type, ghost_type)
                      << " in this ByElementType<"
                      << debug::demangle(typeid(Stored).name()) << "> class");
   return it->second;
 }
 
 /* -------------------------------------------------------------------------- */
 template<class Stored>
 inline Stored & ByElementType<Stored>::operator()(const ElementType & type,
                                                   const GhostType & ghost_type) {
   typename DataMap::iterator it =
     this->getData(ghost_type).find(type);
 
   // if(it == this->getData(ghost_type).end())
   //   AKANTU_EXCEPTION("No element of type "
   //                 << ByElementType<Stored>::printType(type, ghost_type)
   //                 << " in this ByElementType<"
   //                 << debug::demangle(typeid(Stored).name()) << "> class");
 
   if(it == this->getData(ghost_type).end()) {
     DataMap & data = this->getData(ghost_type);
     const std::pair<typename DataMap::iterator, bool> & res =
       data.insert(std::pair<ElementType, Stored>(type, Stored()));
     it = res.first;
   }
   return it->second;
 }
 
 /* -------------------------------------------------------------------------- */
 template<class Stored>
 inline Stored & ByElementType<Stored>::operator()(const Stored & insert,
                                                   const ElementType & type,
                                                   const GhostType & ghost_type) {
   typename DataMap::iterator it =
     this->getData(ghost_type).find(type);
 
   if(it != this->getData(ghost_type).end()) {
     AKANTU_EXCEPTION("Element of type "
                      << ByElementType<Stored>::printType(type, ghost_type)
                      << " already in this ByElementType<"
                      << debug::demangle(typeid(Stored).name()) << "> class");
   } else {
     DataMap & data = this->getData(ghost_type);
     const std::pair<typename DataMap::iterator, bool> & res =
       data.insert(std::pair<ElementType, Stored>(type, insert));
     it = res.first;
   }
 
   return it->second;
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<class Stored>
 inline typename ByElementType<Stored>::DataMap &
 ByElementType<Stored>::getData(GhostType ghost_type) {
   if(ghost_type == _not_ghost) return data;
   else return ghost_data;
 }
 
 /* -------------------------------------------------------------------------- */
 template<class Stored>
 inline const typename ByElementType<Stored>::DataMap &
 ByElementType<Stored>::getData(GhostType ghost_type) const {
   if(ghost_type == _not_ghost) return data;
   else return ghost_data;
 }
 
 /* -------------------------------------------------------------------------- */
 /// Works only if stored is a pointer to a class with a printself method
 template<class Stored>
 void ByElementType<Stored>::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   stream << space << "ByElementType<" << debug::demangle(typeid(Stored).name()) << "> [" << std::endl;
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
 
     const DataMap & data = getData(gt);
     typename DataMap::const_iterator it;
     for(it = data.begin(); it != data.end(); ++it) {
       stream << space << space << ByElementType<Stored>::printType(it->first, gt) << " [" << std::endl;
       it->second->printself(stream, indent + 3);
     }
   }
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 template<class Stored>
 ByElementType<Stored>::ByElementType(const ID & id,
                                      const ID & parent_id) {
   AKANTU_DEBUG_IN();
 
   std::stringstream sstr;
   if(parent_id != "") sstr << parent_id << ":";
   sstr << id;
 
   this->id = sstr.str();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<class Stored>
 ByElementType<Stored>::~ByElementType() {
 
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline Vector<T> & ByElementTypeVector<T>::alloc(UInt size,
                                                  UInt nb_component,
                                                  const ElementType & type,
                                                  const GhostType & ghost_type) {
   std::string ghost_id = "";
   if (ghost_type == _ghost) ghost_id = ":ghost";
 
   Vector<T> * tmp;
 
   typename ByElementTypeVector<T>::DataMap::iterator it =
     this->getData(ghost_type).find(type);
 
   if(it == this->getData(ghost_type).end()) {
     std::stringstream sstr; sstr << this->id << ":" << type << ghost_id;
     tmp = &(Memory::alloc<T>(sstr.str(), size,
 			     nb_component, T()));
     std::stringstream sstrg; sstrg << ghost_type;
     tmp->setTag(sstrg.str());
     this->getData(ghost_type)[type] = tmp;
   } else {
     AKANTU_DEBUG_INFO("The vector " << this->id << this->printType(type, ghost_type)
 		      << " already exists, it is resized instead of allocated.");
     tmp = it->second;
     it->second->resize(size);
   }
 
   return *tmp;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline void ByElementTypeVector<T>::alloc(UInt size,
                                           UInt nb_component,
                                           const ElementType & type) {
   this->alloc(size, nb_component, type, _not_ghost);
   this->alloc(size, nb_component, type, _ghost);
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline void ByElementTypeVector<T>::free() {
   AKANTU_DEBUG_IN();
 
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
 
     const DataMap & data = this->getData(gt);
     typename DataMap::const_iterator it;
     for(it = data.begin(); it != data.end(); ++it) {
       dealloc(it->second->getID());
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline const Vector<T> & ByElementTypeVector<T>::operator()(const ElementType & type,
                                                             const GhostType & ghost_type) const {
   typename ByElementTypeVector<T>::DataMap::const_iterator it =
     this->getData(ghost_type).find(type);
 
   if(it == this->getData(ghost_type).end())
     AKANTU_EXCEPTION("No element of type "
                      << ByElementTypeVector<T>::printType(type, ghost_type)
-                     << " in this ByElementTypeVector<"
+                     << " in this const ByElementTypeVector<"
                      << debug::demangle(typeid(T).name()) << "> class(\""
                      << this->id << "\")");
 
   return *(it->second);
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline Vector<T> & ByElementTypeVector<T>::operator()(const ElementType & type,
                                                       const GhostType & ghost_type) {
   typename ByElementTypeVector<T>::DataMap::iterator it =
     this->getData(ghost_type).find(type);
 
   if(it == this->getData(ghost_type).end())
     AKANTU_EXCEPTION("No element of type "
                      << ByElementTypeVector<T>::printType(type, ghost_type)
                      << " in this ByElementTypeVector<"
                      << debug::demangle(typeid(T).name()) << "> class (\""
                      << this->id << "\")");
 
   return *(it->second);
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline void ByElementTypeVector<T>::setVector(const ElementType & type,
                                               const GhostType & ghost_type,
                                               const Vector<T> & vect) {
   typename ByElementTypeVector<T>::DataMap::iterator it =
     this->getData(ghost_type).find(type);
 
   if(AKANTU_DEBUG_TEST(dblWarning) && it != this->getData(ghost_type).end() && it->second != &vect) {
     AKANTU_DEBUG_WARNING("The Vector " << this->printType(type, ghost_type)
                          << " is already registred, this call can lead to a memory leak.");
   }
 
   this->getData(ghost_type)[type] = &(const_cast<Vector<T> &>(vect));
 }
 
+/* -------------------------------------------------------------------------- */
+template <typename T>
+inline void ByElementTypeVector<T>::onElementsRemoved(const ByElementTypeVector<UInt> & new_numbering) {
+  for(UInt g = _not_ghost; g <= _ghost; ++g) {
+    GhostType gt = (GhostType) g;
+    ByElementTypeVector<UInt>::type_iterator it  = new_numbering.firstType(0, gt, _ek_not_defined);
+    ByElementTypeVector<UInt>::type_iterator end = new_numbering.lastType(0, gt, _ek_not_defined);
+    for (; it != end; ++it) {
+      ElementType type = *it;
+      if(this->exists(type, gt)){
+	const Vector<UInt> & renumbering = new_numbering(type, gt);
+	Vector<T> & vect = this->operator()(type, gt);
+	UInt nb_component = vect.getNbComponent();
+	Vector<T> tmp(renumbering.getSize(), nb_component);
+	UInt new_size = 0;
+	for (UInt i = 0; i < vect.getSize(); ++i) {
+	  UInt new_i = renumbering(i);
+	  if(new_i != UInt(-1)) {
+	    memcpy(tmp.storage() + new_i * nb_component,
+		   vect.storage() + i *nb_component,
+		   nb_component * sizeof(T));
+	    ++new_size;
+	  }
+	}
+	tmp.resize(new_size);
+	vect.copy(tmp);
+      }
+    }
+  }
+}
+
 
 /* -------------------------------------------------------------------------- */
 /* ElementType Iterator                                                       */
 /* -------------------------------------------------------------------------- */
 
 template <class Stored>
 ByElementType<Stored>::type_iterator::type_iterator(DataMapIterator & list_begin,
                                                     DataMapIterator & list_end,
                                                     UInt dim, ElementKind ek) :
   list_begin(list_begin), list_end(list_end), dim(dim), kind(ek) {
 }
 
 
 /* -------------------------------------------------------------------------- */
 template <class Stored>
 ByElementType<Stored>::type_iterator::type_iterator(const type_iterator & it) :
   list_begin(it.list_begin), list_end(it.list_end), dim(it.dim), kind(it.kind) {
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored>
 inline typename ByElementType<Stored>::type_iterator::reference
 ByElementType<Stored>::type_iterator::operator*() {
   return list_begin->first;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored>
 inline typename ByElementType<Stored>::type_iterator &
 ByElementType<Stored>::type_iterator::operator++() {
   ++list_begin;
   while((list_begin != list_end) &&
 	(((dim != 0) && (dim != Mesh::getSpatialDimension(list_begin->first))) ||
 	 ((kind != _ek_not_defined) && (kind != Mesh::getKind(list_begin->first)))))
       ++list_begin;
   return *this;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored>
 typename ByElementType<Stored>::type_iterator ByElementType<Stored>::type_iterator::operator++(int) {
   type_iterator tmp(*this);
   operator++();
   return tmp;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored>
 inline bool ByElementType<Stored>::type_iterator::operator==(const type_iterator & other) {
   return this->list_begin == other.list_begin;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored>
 inline bool ByElementType<Stored>::type_iterator::operator!=(const type_iterator & other) {
   return this->list_begin != other.list_begin;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored>
 inline typename ByElementType<Stored>::type_iterator
 ByElementType<Stored>::firstType(UInt dim, GhostType ghost_type, ElementKind kind) const {
   typename DataMap::const_iterator b,e;
   if(ghost_type == _not_ghost) {
     b = data.begin();
     e = data.end();
   } else {
     b = ghost_data.begin();
     e = ghost_data.end();
   }
 
   // loop until the first valid type
   while((b != e) &&
 	(((dim != 0) && (dim != Mesh::getSpatialDimension(b->first))) ||
 	 ((kind != _ek_not_defined) && (kind != Mesh::getKind(b->first)))))
       ++b;
 
   return typename ByElementType<Stored>::type_iterator(b, e, dim, kind);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored>
 inline typename ByElementType<Stored>::type_iterator
 ByElementType<Stored>::lastType(UInt dim, GhostType ghost_type, ElementKind kind) const {
   typename DataMap::const_iterator e;
   if(ghost_type == _not_ghost) {
     e = data.end();
   } else {
     e = ghost_data.end();
   }
   return typename ByElementType<Stored>::type_iterator(e, e, dim, kind);
 }
 
 
diff --git a/src/fem/fem_template.cc b/src/fem/fem_template.cc
index ee9ff18e5..edf258135 100644
--- a/src/fem/fem_template.cc
+++ b/src/fem/fem_template.cc
@@ -1,942 +1,942 @@
 /**
  * @file   fem_template.cc
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Fri Feb 11 11:37:47 2011
  *
  * @brief  implementation of the generic FEMTemplate class
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "integrator_gauss.hh"
 #include "fem.hh"
 #include "aka_common.hh"
 #include "shape_lagrange.hh"
 #include "shape_linked.hh"
 #include "shape_cohesive.hh"
 #include "integrator_cohesive.hh"
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 FEMTemplate<Integ,Shape>::FEMTemplate(Mesh & mesh, UInt spatial_dimension,
 				      ID id, MemoryID memory_id) :
   FEM(mesh,spatial_dimension,id,memory_id),
   integrator(mesh, id, memory_id),
   shape_functions(mesh, id, memory_id)
 {
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 FEMTemplate<Integ,Shape>::~FEMTemplate()
 {
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 void FEMTemplate<Integ,Shape>::gradientOnQuadraturePoints(const Vector<Real> &u,
 							  Vector<Real> &nablauq,
 							  const UInt nb_degree_of_freedom,
 							  const ElementType & type,
 							  const GhostType & ghost_type,
 							  const Vector<UInt> * filter_elements) const {
   AKANTU_DEBUG_IN();
 
 #ifndef AKANTU_NDEBUG
 //   std::stringstream sstr; sstr << ghost_type;
 //   AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(),
 // 		      "The vector " << nablauq.getID() << " is not taged " << ghost_type);
   UInt nb_element = mesh->getNbElement(type, ghost_type);
   if(filter_elements != NULL) nb_element = filter_elements->getSize();
 
   UInt element_dimension = mesh->getSpatialDimension(type);
   UInt nb_points         = shape_functions.getControlPoints(type, ghost_type).getSize();
 
   AKANTU_DEBUG_ASSERT(u.getSize() == mesh->getNbNodes(),
 		      "The vector u(" << u.getID()
 		      << ") has not the good size.");
   AKANTU_DEBUG_ASSERT(u.getNbComponent() == nb_degree_of_freedom ,
 		      "The vector u(" << u.getID()
 		      << ") has not the good number of component.");
 
   AKANTU_DEBUG_ASSERT(nablauq.getNbComponent()
 		      == nb_degree_of_freedom * element_dimension,
 		      "The vector nablauq(" << nablauq.getID()
 		      << ") has not the good number of component.");
 
   AKANTU_DEBUG_ASSERT(nablauq.getSize() == nb_element * nb_points,
 		      "The vector nablauq(" << nablauq.getID()
 		      << ") has not the good size.");
 #endif
 
 #define COMPUTE_GRADIENT(type)						\
     if (element_dimension == ElementClass<type>::getSpatialDimension()) \
       shape_functions.template gradientOnControlPoints<type>(u,		\
 							     nablauq,	\
 							     nb_degree_of_freedom, \
 							     ghost_type, \
 							     filter_elements);
     AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(COMPUTE_GRADIENT);
 #undef COMPUTE_GRADIENT
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FEMTemplate<IntegratorCohesive<IntegratorGauss>,ShapeCohesive<ShapeLagrange> >::
 					       initShapeFunctions(const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh->getSpatialDimension();
   Mesh::type_iterator it  = mesh->firstType(element_dimension, ghost_type, _ek_cohesive);
   Mesh::type_iterator end = mesh->lastType(element_dimension, ghost_type, _ek_cohesive);
   for(; it != end; ++it) {
     ElementType type = *it;
 
 #define INIT_SHAPE_FUNCTIONS(type)					\
     integrator.computeQuadraturePoints<type>(ghost_type);		\
     integrator.								\
       precomputeJacobiansOnQuadraturePoints<type>(ghost_type);		\
     integrator.								\
       checkJacobians<type>(ghost_type);					\
     const Vector<Real> & control_points =				\
       integrator.getQuadraturePoints<type>(ghost_type);			\
     shape_functions.							\
       setControlPointsByType<type>(control_points, ghost_type);		\
     shape_functions.							\
       precomputeShapesOnControlPoints<type>(ghost_type);		\
     if (element_dimension == spatial_dimension)				\
       shape_functions.							\
      	precomputeShapeDerivativesOnControlPoints<type>(ghost_type);
 
     AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(INIT_SHAPE_FUNCTIONS);
 #undef INIT_SHAPE_FUNCTIONS
   }
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 void FEMTemplate<Integ,Shape>::initShapeFunctions(const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh->getSpatialDimension();
   Mesh::type_iterator it  = mesh->firstType(element_dimension, ghost_type);
   Mesh::type_iterator end = mesh->lastType(element_dimension, ghost_type);
   for(; it != end; ++it) {
     ElementType type = *it;
 
 #define INIT_SHAPE_FUNCTIONS(type)					\
     integrator.template computeQuadraturePoints<type>(ghost_type);	\
     integrator.								\
       template precomputeJacobiansOnQuadraturePoints<type>(ghost_type);	\
     integrator.								\
       template checkJacobians<type>(ghost_type);			\
     const Vector<Real> & control_points =				\
       integrator.template getQuadraturePoints<type>(ghost_type);	\
     shape_functions.							\
       template setControlPointsByType<type>(control_points, ghost_type); \
     shape_functions.							\
       template precomputeShapesOnControlPoints<type>(ghost_type);	\
     if (element_dimension == spatial_dimension)				\
       shape_functions.							\
 	template precomputeShapeDerivativesOnControlPoints<type>(ghost_type);
 
     AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(INIT_SHAPE_FUNCTIONS);
 #undef INIT_SHAPE_FUNCTIONS
   }
   AKANTU_DEBUG_OUT();
 }
 
 
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 void FEMTemplate<Integ,Shape>::integrate(const Vector<Real> & f,
 				       Vector<Real> &intf,
 				       UInt nb_degree_of_freedom,
 				       const ElementType & type,
 				       const GhostType & ghost_type,
 				       const Vector<UInt> * filter_elements) const{
 
 #ifndef AKANTU_NDEBUG
 //   std::stringstream sstr; sstr << ghost_type;
 //   AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(),
 // 		      "The vector " << nablauq.getID() << " is not taged " << ghost_type);
   UInt nb_element = mesh->getNbElement(type, ghost_type);
   if(filter_elements != NULL) nb_element = filter_elements->getSize();
 
   UInt nb_quadrature_points  = getNbQuadraturePoints(type);
 
   AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points,
 		      "The vector f(" << f.getID() << " size " << f.getSize()
 		      << ") has not the good size (" << nb_element << ").");
   AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom ,
 		      "The vector f(" << f.getID()
 		      << ") has not the good number of component.");
   AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom,
 		      "The vector intf(" << intf.getID()
 		      << ") has not the good number of component.");
   AKANTU_DEBUG_ASSERT(intf.getSize() == nb_element,
 		      "The vector intf(" << intf.getID()
 		      << ") has not the good size.");
 #endif
 
 #define INTEGRATE(type)					    \
   integrator.template integrate<type>(f,		    \
 				      intf,		    \
 				      nb_degree_of_freedom, \
 				      ghost_type,	    \
 				      filter_elements);
 
     AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(INTEGRATE);
 #undef INTEGRATE
 }
 
 /* -------------------------------------------------------------------------- */
 
 
 template <typename Integ, typename Shape>
 Real FEMTemplate<Integ,Shape>::integrate(const Vector<Real> & f,
 				       const ElementType & type,
 				       const GhostType & ghost_type,
 				       const Vector<UInt> * filter_elements) const{
   AKANTU_DEBUG_IN();
 
 #ifndef AKANTU_NDEBUG
 //   std::stringstream sstr; sstr << ghost_type;
 //   AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(),
 // 		      "The vector " << nablauq.getID() << " is not taged " << ghost_type);
   UInt nb_element = mesh->getNbElement(type, ghost_type);
   if(filter_elements != NULL) nb_element = filter_elements->getSize();
 
-  UInt nb_quadrature_points  = getNbQuadraturePoints(type);
+  UInt nb_quadrature_points  = getNbQuadraturePoints(type, ghost_type);
 
   AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points,
 		      "The vector f(" << f.getID()
-		      << ") has not the good size.");
+		      << ") has not the good size. (" << f.getSize() << "!=" << nb_quadrature_points * nb_element << ")");
   AKANTU_DEBUG_ASSERT(f.getNbComponent() == 1,
 		      "The vector f(" << f.getID()
 		      << ") has not the good number of component.");
 #endif
 
   Real integral = 0.;
 
 #define INTEGRATE(type)							\
   integral = integrator.template integrate<type>(f,			\
 						 ghost_type,		\
 						 filter_elements);
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(INTEGRATE);
 #undef INTEGRATE
 
   AKANTU_DEBUG_OUT();
   return integral;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 void FEMTemplate<Integ,Shape>::integrateOnQuadraturePoints(const Vector<Real> & f,
 							   Vector<Real> &intf,
 							   UInt nb_degree_of_freedom,
 							   const ElementType & type,
 							   const GhostType & ghost_type,
 							   const Vector<UInt> * filter_elements) const{
 
 #ifndef AKANTU_NDEBUG
 //   std::stringstream sstr; sstr << ghost_type;
 //   AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(),
 // 		      "The vector " << nablauq.getID() << " is not taged " << ghost_type);
   UInt nb_element = mesh->getNbElement(type, ghost_type);
   if(filter_elements != NULL) nb_element = filter_elements->getSize();
 
   UInt nb_quadrature_points  = getNbQuadraturePoints(type);
 
   AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points,
 		      "The vector f(" << f.getID() << " size " << f.getSize()
 		      << ") has not the good size (" << nb_element << ").");
   AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom ,
 		      "The vector f(" << f.getID()
 		      << ") has not the good number of component.");
   AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom,
 		      "The vector intf(" << intf.getID()
 		      << ") has not the good number of component.");
   AKANTU_DEBUG_ASSERT(intf.getSize() == nb_element * nb_quadrature_points,
 		      "The vector intf(" << intf.getID()
 		      << ") has not the good size.");
 #endif
 
 #define INTEGRATE(type)							\
   integrator.template integrateOnQuadraturePoints<type>(f,		\
 							intf,		\
 							nb_degree_of_freedom, \
 							ghost_type,	\
 							filter_elements);
 
     AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(INTEGRATE);
 #undef INTEGRATE
 }
 
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 void FEMTemplate<Integ,Shape>::interpolateOnQuadraturePoints(const Vector<Real> &u,
 							   Vector<Real> &uq,
 							   UInt nb_degree_of_freedom,
 							   const ElementType & type,
 							   const GhostType & ghost_type,
 							   const Vector<UInt> * filter_elements) const{
 
   AKANTU_DEBUG_IN();
 
 
 #ifndef AKANTU_NDEBUG
 //   std::stringstream sstr; sstr << ghost_type;
 //   AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(),
 // 		      "The vector " << nablauq.getID() << " is not taged " << ghost_type);
   UInt nb_element = mesh->getNbElement(type, ghost_type);
   if(filter_elements != NULL) nb_element = filter_elements->getSize();
 
   UInt nb_points         = shape_functions.getControlPoints(type, ghost_type).getSize();
 
   AKANTU_DEBUG_ASSERT(u.getSize() == mesh->getNbNodes(),
 		      "The vector u(" << u.getID()
 		      << ") has not the good size.");
   AKANTU_DEBUG_ASSERT(u.getNbComponent() == nb_degree_of_freedom ,
 		      "The vector u(" << u.getID()
 		      << ") has not the good number of component.");
 
   AKANTU_DEBUG_ASSERT(uq.getNbComponent() == nb_degree_of_freedom,
 		      "The vector uq(" << uq.getID()
 		      << ") has not the good number of component.");
   AKANTU_DEBUG_ASSERT(uq.getSize() == nb_element * nb_points,
 		      "The vector uq(" << uq.getID()
 		      << ") has not the good size.");
 #endif
 
 
 #define INTERPOLATE(type)						\
   shape_functions.template interpolateOnControlPoints<type>(u,		\
 							    uq,		\
 							    nb_degree_of_freedom, \
 							    ghost_type, \
 							    filter_elements);
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(INTERPOLATE);
 #undef INTERPOLATE
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 void FEMTemplate<Integ,Shape>::computeNormalsOnControlPoints(const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   computeNormalsOnControlPoints(mesh->getNodes(),
 				ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 void FEMTemplate<Integ,Shape>::computeNormalsOnControlPoints(const Vector<Real> & field,
 							     const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   if (ghost_type == _ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); }
 
   //  Real * coord = mesh->getNodes().values;
   UInt spatial_dimension = mesh->getSpatialDimension();
 
   //allocate the normal arrays
   mesh->initByElementTypeVector(normals_on_quad_points, spatial_dimension, element_dimension);
 
   //loop over the type to build the normals
   Mesh::type_iterator it  = mesh->firstType(element_dimension, ghost_type);
   Mesh::type_iterator end = mesh->lastType(element_dimension, ghost_type);
   for(; it != end; ++it) {
     Vector<Real> & normals_on_quad = normals_on_quad_points(*it, ghost_type);
     computeNormalsOnControlPoints(field, normals_on_quad, *it, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 void FEMTemplate<Integ,Shape>::computeNormalsOnControlPoints(const Vector<Real> & field,
 							     Vector<Real> & normal,
 							     const ElementType & type,
 							     const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   if (ghost_type == _ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); }
 
   UInt spatial_dimension = mesh->getSpatialDimension();
   UInt nb_nodes_per_element           = Mesh::getNbNodesPerElement(type);
   UInt nb_quad_points = getQuadraturePoints(type, ghost_type).getSize();
   UInt * elem_val = mesh->getConnectivity(type, ghost_type).storage();
   UInt nb_element = mesh->getConnectivity(type, ghost_type).getSize();
 
   normal.resize(nb_element * nb_quad_points);
   Real * normals_on_quad_val  =  normal.storage();
 
     /* ---------------------------------------------------------------------- */
 #define COMPUTE_NORMALS_ON_QUAD(type)					\
   do {									\
     const Vector<Real> & quads =					\
       integrator. template getQuadraturePoints<type>(ghost_type);	\
     UInt nb_points = quads.getSize();					\
     Real local_coord[spatial_dimension * nb_nodes_per_element];		\
     for (UInt elem = 0; elem < nb_element; ++elem) {			\
       mesh->extractNodalValuesFromElement(field,			\
 					  local_coord,			\
 					  elem_val+elem*nb_nodes_per_element, \
 					  nb_nodes_per_element,		\
 					  spatial_dimension);		\
       									\
       ElementClass<type>::computeNormalsOnQuadPoint(local_coord,	\
 						    spatial_dimension,	\
 						    normals_on_quad_val); \
       normals_on_quad_val += spatial_dimension*nb_points;	 	\
     }									\
   } while(0)
   /* ---------------------------------------------------------------------- */
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(COMPUTE_NORMALS_ON_QUAD);
 #undef COMPUTE_NORMALS_ON_QUAD
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* compatibility functions */
 /* -------------------------------------------------------------------------- */
 
 template <>
 inline UInt FEMTemplate<IntegratorCohesive<IntegratorGauss>,ShapeCohesive<ShapeLagrange> >
 ::getNbQuadraturePoints(const ElementType & type,
 			const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   UInt nb_quad_points = 0;
 
 #define GET_NB_QUAD(type)						\
   nb_quad_points =							\
     integrator. getQuadraturePoints<type>(ghost_type).getSize();
 
   //  AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_NB_QUAD);
   AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(GET_NB_QUAD);
 #undef GET_NB_QUAD
 
   AKANTU_DEBUG_OUT();
   return nb_quad_points;
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <>
 Real FEMTemplate<IntegratorCohesive<IntegratorGauss>,ShapeCohesive<ShapeLagrange> >::integrate(const Vector<Real> & f,
 											       const ElementType & type,
 											       const GhostType & ghost_type,
 											       const Vector<UInt> * filter_elements) const{
   AKANTU_DEBUG_IN();
 
 #ifndef AKANTU_NDEBUG
 //   std::stringstream sstr; sstr << ghost_type;
 //   AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(),
 // 		      "The vector " << nablauq.getID() << " is not taged " << ghost_type);
   UInt nb_element = mesh->getNbElement(type, ghost_type);
   if(filter_elements != NULL) nb_element = filter_elements->getSize();
 
   UInt nb_quadrature_points  = getNbQuadraturePoints(type);
 
   AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points,
 		      "The vector f(" << f.getID()
 		      << ") has not the good size.");
   AKANTU_DEBUG_ASSERT(f.getNbComponent() == 1,
 		      "The vector f(" << f.getID()
 		      << ") has not the good number of component.");
 #endif
 
   Real integral = 0.;
 
 #define INTEGRATE(type)							\
   integral = integrator. integrate<type>(f,				\
 						 ghost_type,		\
 						 filter_elements);
 
   AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(INTEGRATE);
 #undef INTEGRATE
 
   AKANTU_DEBUG_OUT();
   return integral;
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FEMTemplate<IntegratorCohesive<IntegratorGauss>,ShapeCohesive<ShapeLagrange> >
 ::integrate(const Vector<Real> & f,
 	    Vector<Real> &intf,
 	    UInt nb_degree_of_freedom,
 	    const ElementType & type,
 	    const GhostType & ghost_type,
 	    const Vector<UInt> * filter_elements) const{
 
 #ifndef AKANTU_NDEBUG
 //   std::stringstream sstr; sstr << ghost_type;
 //   AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(),
 // 		      "The vector " << nablauq.getID() << " is not taged " << ghost_type);
   UInt nb_element = mesh->getNbElement(type, ghost_type);
   if(filter_elements != NULL) nb_element = filter_elements->getSize();
 
   UInt nb_quadrature_points  = getNbQuadraturePoints(type);
 
   AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points,
 		      "The vector f(" << f.getID() << " size " << f.getSize()
 		      << ") has not the good size (" << nb_element << ").");
   AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom ,
 		      "The vector f(" << f.getID()
 		      << ") has not the good number of component.");
   AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom,
 		      "The vector intf(" << intf.getID()
 		      << ") has not the good number of component.");
   AKANTU_DEBUG_ASSERT(intf.getSize() == nb_element,
 		      "The vector intf(" << intf.getID()
 		      << ") has not the good size.");
 #endif
 
 #define INTEGRATE(type)					    \
   integrator. integrate<type>(f,			    \
 			      intf,			    \
 			      nb_degree_of_freedom,	    \
 			      ghost_type,		    \
 			      filter_elements);
 
   //    AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(INTEGRATE);
   AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(INTEGRATE);
 #undef INTEGRATE
 }
 
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 inline UInt FEMTemplate<Integ,Shape>::getNbQuadraturePoints(const ElementType & type,
 							    const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   UInt nb_quad_points = 0;
 
 #define GET_NB_QUAD(type)						\
   nb_quad_points =							\
     integrator. template getQuadraturePoints<type>(ghost_type).getSize();
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_NB_QUAD);
 #undef GET_NB_QUAD
 
   AKANTU_DEBUG_OUT();
   return nb_quad_points;
 }
 
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 inline const Vector<Real> & FEMTemplate<Integ,Shape>::getShapes(const ElementType & type,
 								const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
   const Vector<Real> * ret = NULL;
 
 #define GET_SHAPES(type)						\
   ret = &(shape_functions.getShapes(type, ghost_type));
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_SHAPES);
 #undef GET_SHAPES
 
   AKANTU_DEBUG_OUT();
   return *ret;
 }
 /* -------------------------------------------------------------------------- */
 template <>
 inline const Vector<Real> & FEMTemplate<IntegratorCohesive<IntegratorGauss>,ShapeCohesive<ShapeLagrange> >
 ::getShapes(const ElementType & type,
 	    const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
   const Vector<Real> * ret = NULL;
 
 #define GET_SHAPES(type)						\
   ret = &(shape_functions.getShapes(type, ghost_type));
 
   //  AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_SHAPES);
   AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(GET_SHAPES);
 #undef GET_SHAPES
 
   AKANTU_DEBUG_OUT();
   return *ret;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 inline const Vector<Real> & FEMTemplate<Integ,Shape>::getShapesDerivatives(const ElementType & type,
 									   const GhostType & ghost_type,
 									   __attribute__((unused)) UInt id) const {
   AKANTU_DEBUG_IN();
   const Vector<Real> * ret = NULL;
 
 #define GET_SHAPES(type)						\
   ret = &(shape_functions.getShapesDerivatives(type, ghost_type));
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_SHAPES);
 #undef GET_SHAPES
 
   AKANTU_DEBUG_OUT();
   return *ret;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 inline const Vector<Real> & FEMTemplate<Integ,Shape>::getQuadraturePoints(const ElementType & type,
 									  const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
   const Vector<Real> * ret = NULL;
 
 #define GET_QUADS(type)						\
   ret = &(integrator. template getQuadraturePoints<type>(ghost_type));
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_QUADS);
 #undef GET_QUADS
 
     AKANTU_DEBUG_OUT();
   return *ret;
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* Matrix lumping functions                                                   */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 void FEMTemplate<Integ,Shape>::assembleFieldLumped(const Vector<Real> & field_1,
 						   UInt nb_degree_of_freedom,
 						   Vector<Real> & lumped,
 						   const Vector<Int> & equation_number,
 						   ElementType type,
 						   const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
 #define ASSEMBLE_LUMPED(type)					\
   assembleLumpedTemplate<type>(field_1, nb_degree_of_freedom,lumped, equation_number,ghost_type)
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(ASSEMBLE_LUMPED);;
 
 #undef ASSEMBLE_LUMPED
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 inline const Vector<Real> &
 FEMTemplate<IntegratorGauss, ShapeLinked>::getShapesDerivatives(const ElementType & type,
 								const GhostType & ghost_type,
 								UInt id) const {
   AKANTU_DEBUG_IN();
   const Vector<Real> * ret = NULL;
 
 #define GET_SHAPES(type)						\
   ret = &(shape_functions.getShapesDerivatives(type, ghost_type, id));
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_SHAPES);
 #undef GET_SHAPES
 
   AKANTU_DEBUG_OUT();
   return *ret;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 void FEMTemplate<Integ,Shape>::assembleFieldMatrix(const Vector<Real> & field_1,
 						   UInt nb_degree_of_freedom,
 						   SparseMatrix & matrix,
 						   ElementType type,
 						   const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
 #define ASSEMBLE_MATRIX(type)					\
   assembleFieldMatrix<type>(field_1, nb_degree_of_freedom,	\
 			    matrix,				\
 			    ghost_type)
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(ASSEMBLE_MATRIX);;
 
 #undef ASSEMBLE_MATRIX
 
   AKANTU_DEBUG_OUT();
 }
 
 
 
 
 /* -------------------------------------------------------------------------- */
 template <typename Integ, typename Shape>
 template <ElementType type>
 void FEMTemplate<Integ,Shape>::assembleLumpedTemplate(const Vector<Real> & field_1,
 						      UInt nb_degree_of_freedom,
 						      Vector<Real> & lumped,
 						      const Vector<Int> & equation_number,
 						      const GhostType & ghost_type) const {
   this->template assembleLumpedRowSum<type>(field_1, nb_degree_of_freedom,lumped, equation_number,ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 //template <typename Integ, typename Shape>
 template <>
 template <>
 void FEMTemplate<IntegratorGauss,ShapeLagrange>::
 assembleLumpedTemplate<_triangle_6>(const Vector<Real> & field_1,
 				    UInt nb_degree_of_freedom,
 				    Vector<Real> & lumped,
 				    const Vector<Int> & equation_number,
 				    const GhostType & ghost_type) const {
   assembleLumpedDiagonalScaling<_triangle_6>(field_1, nb_degree_of_freedom,lumped, equation_number,ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 template <>
 void FEMTemplate<IntegratorGauss,ShapeLagrange>::
 assembleLumpedTemplate<_tetrahedron_10>(const Vector<Real> & field_1,
 					UInt nb_degree_of_freedom,
 					Vector<Real> & lumped,
 					const Vector<Int> & equation_number,
 					const GhostType & ghost_type) const {
   assembleLumpedDiagonalScaling<_tetrahedron_10>(field_1, nb_degree_of_freedom,lumped, equation_number,ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 template <>
 void
 FEMTemplate<IntegratorGauss,ShapeLagrange>::assembleLumpedTemplate<_quadrangle_8>(const Vector<Real> & field_1,
 										  UInt nb_degree_of_freedom,
 										  Vector<Real> & lumped,
 										  const Vector<Int> & equation_number,
 										  const GhostType & ghost_type) const {
   assembleLumpedDiagonalScaling<_quadrangle_8>(field_1, nb_degree_of_freedom,lumped, equation_number, ghost_type);
 }
 
 
 /* -------------------------------------------------------------------------- */
 /**
  * @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV = \int \rho \varphi_i dV @f$
  */
 template <typename Integ, typename Shape>
 template <ElementType type>
 void FEMTemplate<Integ,Shape>::assembleLumpedRowSum(const Vector<Real> & field_1,
 						    UInt nb_degree_of_freedom,
 						    Vector<Real> & lumped,
 						    const Vector<Int> & equation_number,
 						    const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   UInt shapes_size = ElementClass<type>::getShapeSize();
 
   Vector<Real> * field_times_shapes = new Vector<Real>(0, 1);//shapes_size);
   shape_functions.template fieldTimesShapes<type>(field_1, *field_times_shapes, ghost_type);
 
   UInt nb_element = mesh->getNbElement(type, ghost_type);
   Vector<Real> * int_field_times_shapes = new Vector<Real>(nb_element, shapes_size,
 							   "inte_rho_x_shapes");
   integrator.template integrate<type>(*field_times_shapes, *int_field_times_shapes,
 				      shapes_size, ghost_type, NULL);
   delete field_times_shapes;
 
   int_field_times_shapes->extendComponentsInterlaced(nb_degree_of_freedom,1);
   assembleVector(*int_field_times_shapes, lumped, equation_number,nb_degree_of_freedom, type, ghost_type);
   delete int_field_times_shapes;
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /**
  * @f$ \tilde{M}_{i} = c * M_{ii} = \int_{V_e} \rho dV @f$
  */
 template <typename Integ, typename Shape>
 template <ElementType type>
 void FEMTemplate<Integ,Shape>::assembleLumpedDiagonalScaling(const Vector<Real> & field_1,
 							     UInt nb_degree_of_freedom,
 							     Vector<Real> & lumped,
 							     const Vector<Int> & equation_number,
 							     const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   UInt nb_nodes_per_element_p1 = Mesh::getNbNodesPerElement(Mesh::getP1ElementType(type));
   UInt nb_nodes_per_element    = Mesh::getNbNodesPerElement(type);
   UInt nb_quadrature_points    = integrator.template getQuadraturePoints<type>(ghost_type).getSize();
 
   UInt nb_element = field_1.getSize() / nb_quadrature_points;
 
   Real corner_factor = 0;
   Real mid_factor    = 0;
 
   if(type == _triangle_6) {
     corner_factor = 1./12.;
     mid_factor    = 1./4.;
   }
 
   if (type == _tetrahedron_10) {
     corner_factor = 1./32.;
     mid_factor    = 7./48.;
   }
 
   if (type == _quadrangle_8) {
     corner_factor = 1./36.;
     mid_factor    = 8./36.;
   }
 
 
   if (nb_element == 0) {
     AKANTU_DEBUG_OUT();
     return;
   }
 
   /// compute @f$ \int \rho dV = \rho V @f$ for each element
   Vector<Real> * int_field_1 = new Vector<Real>(field_1.getSize(), 1,
 					      "inte_rho_x_1");
   integrator.template integrate<type>(field_1, *int_field_1, 1, ghost_type, NULL);
 
   /// distribute the mass of the element to the nodes
   Vector<Real> * lumped_per_node = new Vector<Real>(nb_element, nb_nodes_per_element, "mass_per_node");
   Real * int_field_1_val = int_field_1->values;
   Real * lumped_per_node_val = lumped_per_node->values;
 
   for (UInt e = 0; e < nb_element; ++e) {
     Real lmass = *int_field_1_val * corner_factor;
     for (UInt n = 0; n < nb_nodes_per_element_p1; ++n)
       *lumped_per_node_val++ = lmass; /// corner points
 
     lmass = *int_field_1_val * mid_factor;
     for (UInt n = nb_nodes_per_element_p1; n < nb_nodes_per_element; ++n)
       *lumped_per_node_val++ = lmass; /// mid points
 
     int_field_1_val++;
   }
   delete int_field_1;
 
   lumped_per_node->extendComponentsInterlaced(nb_degree_of_freedom,1);
   assembleVector(*lumped_per_node, lumped, equation_number, nb_degree_of_freedom, type, ghost_type);
   delete lumped_per_node;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV = \int \rho \varphi_i dV @f$
  */
 template <typename Integ, typename Shape>
 template <ElementType type>
 void FEMTemplate<Integ,Shape>::assembleFieldMatrix(const Vector<Real> & field_1,
 						   UInt nb_degree_of_freedom,
 						   SparseMatrix & matrix,
 						   const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   UInt vect_size   = field_1.getSize();
   UInt shapes_size = ElementClass<type>::getShapeSize();
   UInt lmat_size   = nb_degree_of_freedom * shapes_size;
 
   const Vector<Real> & shapes = shape_functions.getShapes(type,ghost_type);
   Vector<Real> * modified_shapes = new Vector<Real>(vect_size, lmat_size * nb_degree_of_freedom);
   modified_shapes->clear();
   Vector<Real> * local_mat = new Vector<Real>(vect_size, lmat_size * lmat_size);
 
   Vector<Real>::iterator<types::Matrix> shape_vect  = modified_shapes->begin(nb_degree_of_freedom, lmat_size);
   Real * sh  = shapes.values;
   for(UInt q = 0; q < vect_size; ++q) {
     Real * msh = shape_vect->storage();
     for (UInt d = 0; d < nb_degree_of_freedom; ++d) {
       Real * msh_tmp = msh + d * (lmat_size + 1);
       for (UInt s = 0; s < shapes_size; ++s) {
 	*msh_tmp = sh[s];
 	msh_tmp += nb_degree_of_freedom;
       }
     }
     ++shape_vect;
     sh += shapes_size;
   }
 
   shape_vect  = modified_shapes->begin(nb_degree_of_freedom, lmat_size);
   Vector<Real>::iterator<types::Matrix> lmat = local_mat->begin(lmat_size, lmat_size);
   Real * field_val = field_1.values;
 
   for(UInt q = 0; q < vect_size; ++q) {
     (*lmat).mul<true, false>(*shape_vect, *shape_vect, *field_val);
     ++lmat; ++shape_vect; ++field_val;
   }
 
   delete modified_shapes;
 
   UInt nb_element = mesh->getNbElement(type, ghost_type);
   Vector<Real> * int_field_times_shapes = new Vector<Real>(nb_element, lmat_size * lmat_size,
 							   "inte_rho_x_shapes");
   integrator.template integrate<type>(*local_mat, *int_field_times_shapes,
 				      lmat_size * lmat_size, ghost_type, NULL);
   delete local_mat;
 
   assembleMatrix(*int_field_times_shapes, matrix, nb_degree_of_freedom, type, ghost_type);
   delete int_field_times_shapes;
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FEMTemplate< IntegratorCohesive<IntegratorGauss>, ShapeCohesive<ShapeLagrange> >::
 gradientOnQuadraturePoints(__attribute__((unused)) const Vector<Real> &u,
 			   __attribute__((unused)) Vector<Real> &nablauq,
 			   __attribute__((unused)) const UInt nb_degree_of_freedom,
 			   __attribute__((unused)) const ElementType & type,
 			   __attribute__((unused)) const GhostType & ghost_type,
 			   __attribute__((unused)) const Vector<UInt> * filter_elements) const {
   AKANTU_DEBUG_TO_IMPLEMENT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* template instanciation                                                     */
 /* -------------------------------------------------------------------------- */
 
 template class FEMTemplate<IntegratorGauss,ShapeLagrange>;
 template class FEMTemplate<IntegratorGauss,ShapeLinked>;
 template class FEMTemplate< IntegratorCohesive<IntegratorGauss>, ShapeCohesive<ShapeLagrange> >;
 
 __END_AKANTU__
diff --git a/src/fem/integrator_gauss.cc b/src/fem/integrator_gauss.cc
index 097ede554..4cd71893d 100644
--- a/src/fem/integrator_gauss.cc
+++ b/src/fem/integrator_gauss.cc
@@ -1,328 +1,331 @@
 /**
  * @file   integrator_gauss.cc
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author  Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Feb 10 16:52:07 2011
  *
  * @brief  implementation of gauss integrator class
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "mesh.hh"
 #include "integrator_gauss.hh"
 /* -------------------------------------------------------------------------- */
 __BEGIN_AKANTU__
 
 
 /* -------------------------------------------------------------------------- */
 IntegratorGauss::IntegratorGauss(const Mesh & mesh,
 				 const ID & id,
 				 const MemoryID & memory_id) :
   Integrator(mesh, id, memory_id),
   quadrature_points("quadrature_points", id) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void IntegratorGauss::checkJacobians(const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   UInt nb_quadrature_points = ElementClass<type>::getNbQuadraturePoints();
 
   UInt nb_element;
 
   nb_element = mesh->getConnectivity(type,ghost_type).getSize();
 
   Real * jacobians_val = jacobians(type, ghost_type).storage();
 
   for (UInt i = 0; i < nb_element*nb_quadrature_points; ++i,++jacobians_val){
-    AKANTU_DEBUG_ASSERT(*jacobians_val >0,
-			"Negative jacobian computed,"
-			<< " possible problem in the element node ordering (element " << i
-/nb_quadrature_points << ")");
+    if(*jacobians_val < 0)
+      AKANTU_DEBUG_ERROR("Negative jacobian computed,"
+			 << " possible problem in the element node ordering (Quadrature Point "
+			 << i % nb_quadrature_points << ":"
+			 << i / nb_quadrature_points << ":"
+			 << type << ":"
+			 << ghost_type << ")");
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void IntegratorGauss::precomputeJacobiansOnQuadraturePoints(const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh->getSpatialDimension();
 
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
   UInt nb_quadrature_points = ElementClass<type>::getNbQuadraturePoints();
 
   Real * weights = ElementClass<type>::getGaussIntegrationWeights();
 
   UInt * elem_val = mesh->getConnectivity(type,ghost_type).storage();
   UInt nb_element = mesh->getConnectivity(type,ghost_type).getSize();
 
   Vector<Real> & jacobians_tmp = jacobians.alloc(nb_element*nb_quadrature_points,
 						 1,
 						 type,
 						 ghost_type);
 
   Real * jacobians_val = jacobians_tmp.storage();
 
   Real local_coord[spatial_dimension * nb_nodes_per_element];
   for (UInt elem = 0; elem < nb_element; ++elem) {
     mesh->extractNodalValuesFromElement(mesh->getNodes(),
 					local_coord,
 					elem_val+elem*nb_nodes_per_element,
 					nb_nodes_per_element,
 					spatial_dimension);
 
     computeJacobianOnQuadPointsByElement<type>(spatial_dimension,
 					       local_coord,
 					       nb_nodes_per_element,
 					       jacobians_val);
 
     for (UInt q = 0; q < nb_quadrature_points; ++q) {
       *jacobians_val++ *= weights[q];
     }
     //    jacobians_val += nb_quadrature_points;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void IntegratorGauss::integrate(const Vector<Real> & in_f,
 				Vector<Real> &intf,
 				UInt nb_degree_of_freedom,
 				const GhostType & ghost_type,
 				const Vector<UInt> * filter_elements) const {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type),
 		      "No jacobians for the type "
 		      << jacobians.printType(type, ghost_type));
 
   UInt nb_element = mesh->getNbElement(type,ghost_type);
   const Vector<Real> & jac_loc = jacobians(type, ghost_type);
 
   UInt nb_quadrature_points = ElementClass<type>::getNbQuadraturePoints();
 
   UInt * filter_elem_val = NULL;
   if(filter_elements != NULL) {
     nb_element      = filter_elements->getSize();
     filter_elem_val = filter_elements->values;
   }
 
   Real * in_f_val = in_f.storage();
   Real * intf_val = intf.storage();
   Real * jac_val  = jac_loc.storage();
 
   UInt offset_in_f = in_f.getNbComponent()*nb_quadrature_points;
   UInt offset_intf = intf.getNbComponent();
 
   Real * jac      = jac_val;
 
   for (UInt el = 0; el < nb_element; ++el) {
     if(filter_elements != NULL) {
       jac      = jac_val  + filter_elem_val[el] * nb_quadrature_points;
     }
 
     integrate(in_f_val, jac, intf_val, nb_degree_of_freedom, nb_quadrature_points);
 
     in_f_val += offset_in_f;
     intf_val += offset_intf;
     if(filter_elements == NULL) {
       jac      += nb_quadrature_points;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 Real IntegratorGauss::integrate(const Vector<Real> & in_f,
 				const GhostType & ghost_type,
 				const Vector<UInt> * filter_elements) const {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type),
 		      "No jacobians for the type "
 		      << jacobians.printType(type, ghost_type));
 
   UInt nb_element = mesh->getNbElement(type, ghost_type);
   const Vector<Real> & jac_loc = jacobians(type, ghost_type);
 
   UInt nb_quadrature_points = ElementClass<type>::getNbQuadraturePoints();
 
   UInt * filter_elem_val = NULL;
   if(filter_elements != NULL) {
     nb_element      = filter_elements->getSize();
     filter_elem_val = filter_elements->values;
   }
 
   Real intf = 0.;
   Real * in_f_val  = in_f.storage();
   Real * jac_val   = jac_loc.storage();
   UInt offset_in_f = in_f.getNbComponent() * nb_quadrature_points;
   Real * jac       = jac_val;
 
   for (UInt el = 0; el < nb_element; ++el) {
     if(filter_elements != NULL) {
       jac = jac_val  + filter_elem_val[el] * nb_quadrature_points;
     }
 
     Real el_intf = 0;
     integrate(in_f_val, jac, &el_intf, 1, nb_quadrature_points);
     intf += el_intf;
 
     in_f_val += offset_in_f;
     if(filter_elements == NULL) {
       jac += nb_quadrature_points;
     }
   }
 
   AKANTU_DEBUG_OUT();
   return intf;
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void IntegratorGauss::integrateOnQuadraturePoints(const Vector<Real> & in_f,
 						  Vector<Real> &intf,
 						  UInt nb_degree_of_freedom,
 						  const GhostType & ghost_type,
 						  const Vector<UInt> * filter_elements) const {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type),
 		      "No jacobians for the type "
 		      << jacobians.printType(type, ghost_type));
 
   UInt nb_element = mesh->getNbElement(type,ghost_type);
   const Vector<Real> & jac_loc = jacobians(type, ghost_type);
 
   UInt nb_quadrature_points = ElementClass<type>::getNbQuadraturePoints();
 
   UInt * filter_elem_val = NULL;
   if(filter_elements != NULL) {
     nb_element      = filter_elements->getSize();
     filter_elem_val = filter_elements->values;
   }
 
   Real * in_f_val = in_f.storage();
   Real * intf_val = intf.storage();
   Real * jac_val  = jac_loc.storage();
 
   Real * jac      = jac_val;
 
   for (UInt el = 0; el < nb_element; ++el) {
     if(filter_elements != NULL) {
       jac = jac_val  + filter_elem_val[el] * nb_quadrature_points;
     }
 
     for (UInt q = 0; q < nb_quadrature_points; ++q) {
       for (UInt dof = 0; dof < nb_degree_of_freedom; ++dof) {
 	*intf_val = *in_f_val * *jac;
 	++in_f_val; ++intf_val;
       }
       ++jac;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 template <>
 void IntegratorGauss::precomputeJacobiansOnQuadraturePoints<_bernoulli_beam_2>(const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh->getSpatialDimension();
 
   UInt nb_quadrature_points = ElementClass<_bernoulli_beam_2>::getNbQuadraturePoints();
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_bernoulli_beam_2);
 
   UInt * elem_val;
   UInt nb_element;
 
   elem_val   = mesh->getConnectivity(_bernoulli_beam_2, ghost_type).storage();
   nb_element = mesh->getConnectivity(_bernoulli_beam_2, ghost_type).getSize();
 
   Vector<Real> & jacobians_tmp = jacobians.alloc(nb_element*nb_quadrature_points,
 						 1, _bernoulli_beam_2, ghost_type);
 
   Real local_coord[spatial_dimension * nb_nodes_per_element];
   Real * jacobians_val = jacobians_tmp.storage();
   for (UInt elem = 0; elem < nb_element; ++elem) {
     mesh->extractNodalValuesFromElement(mesh->getNodes(),
 					local_coord,
 					elem_val+elem*nb_nodes_per_element,
 					nb_nodes_per_element,
 					spatial_dimension);
 
     ElementClass<_bernoulli_beam_2>::computeJacobian(local_coord,
 						     nb_quadrature_points,
 						     spatial_dimension,
 						     jacobians_val);
     jacobians_val += nb_quadrature_points;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* template instanciation */
 /* -------------------------------------------------------------------------- */
 
 #define INSTANCIATE_TEMPLATE_CLASS(type)				\
   template void IntegratorGauss::					\
   precomputeJacobiansOnQuadraturePoints<type>(const GhostType & ghost_type); \
   template void IntegratorGauss::					\
   checkJacobians<type>(const GhostType & ghost_type) const;		\
   template void IntegratorGauss::					\
   integrate<type>(const Vector<Real> & in_f,				\
 		  Vector<Real> &intf,					\
 		  UInt nb_degree_of_freedom,				\
 		  const GhostType & ghost_type,				\
 		  const Vector<UInt> * filter_elements) const;		\
   template Real IntegratorGauss::					\
   integrate<type>(const Vector<Real> & in_f,				\
 		  const GhostType & ghost_type,				\
 		  const Vector<UInt> * filter_elements) const;		\
   template void IntegratorGauss::					\
   integrateOnQuadraturePoints<type>(const Vector<Real> & in_f,		\
 			      Vector<Real> &intf,			\
 			      UInt nb_degree_of_freedom,			\
 			      const GhostType & ghost_type,		\
 			      const Vector<UInt> * filter_elements) const;
 
 AKANTU_BOOST_REGULAR_ELEMENT_LIST(INSTANCIATE_TEMPLATE_CLASS)
 #undef INSTANCIATE_TEMPLATE_CLASS
 
 
 __END_AKANTU__
diff --git a/src/fem/mesh.cc b/src/fem/mesh.cc
index 9236f3111..be2db690d 100644
--- a/src/fem/mesh.cc
+++ b/src/fem/mesh.cc
@@ -1,308 +1,315 @@
 /**
  * @file   mesh.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Wed Jun 16 12:02:26 2010
  *
  * @brief  class handling meshes
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include <sstream>
 
 /* -------------------------------------------------------------------------- */
 #include "mesh.hh"
 #include "element_class.hh"
 #include "static_communicator.hh"
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 const Element ElementNull(_not_defined, 0);
 
 /* -------------------------------------------------------------------------- */
 void Element::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
   stream << space << "Element [" << type << ", " << element << ", " << ghost_type << "]";
 }
 
 
 /* -------------------------------------------------------------------------- */
 Mesh::Mesh(UInt spatial_dimension,
 	   const ID & id,
 	   const MemoryID & memory_id) :
   Memory(memory_id), id(id), nodes_global_ids(NULL), nodes_type(NULL),
   created_nodes(true),
   connectivities("connectivities", id),
   normals("normals", id),
   spatial_dimension(spatial_dimension),
   types_offsets(Vector<UInt>((UInt) _max_element_type + 1, 1)),
   ghost_types_offsets(Vector<UInt>((UInt) _max_element_type + 1, 1)),
   nb_surfaces(0),
   surface_id("surface_id", id),
   element_to_subelement("element_to_subelement", id),
   subelement_to_element("subelement_to_element", id),
   uint_data("by_element_uint_data", id) {
   AKANTU_DEBUG_IN();
 
   std::stringstream sstr;
   sstr << id << ":coordinates";
   this->nodes = &(alloc<Real>(sstr.str(), 0, this->spatial_dimension));
 
   nb_global_nodes = 0;
 
   init();
 
   std::fill_n(lower_bounds, 3, 0.);
   std::fill_n(upper_bounds, 3, 0.);
 
   std::fill_n(size, 3, 0.);
 
   std::fill_n(local_lower_bounds, 3, 0.);
   std::fill_n(local_upper_bounds, 3, 0.);
 
   AKANTU_DEBUG_OUT();
 
 }
 
 /* -------------------------------------------------------------------------- */
 Mesh::Mesh(UInt spatial_dimension,
 	   const ID & nodes_id,
 	   const ID & id,
 	   const MemoryID & memory_id) :
   Memory(memory_id), id(id), nodes_global_ids(NULL), nodes_type(NULL),
   created_nodes(false),
   connectivities("connectivities", id),
   normals("normals", id),
   spatial_dimension(spatial_dimension),
   types_offsets(Vector<UInt>((UInt) _max_element_type + 1, 1)),
   ghost_types_offsets(Vector<UInt>((UInt) _max_element_type + 1, 1)),
   nb_surfaces(0),
   surface_id("surface_id", id),
   element_to_subelement("element_to_subelement", id),
   subelement_to_element("subelement_to_element", id),
   uint_data("by_element_uint_data", id) {
   AKANTU_DEBUG_IN();
 
   this->nodes = &(getVector<Real>(nodes_id));
   nb_global_nodes = nodes->getSize();
 
   init();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Mesh::Mesh(UInt spatial_dimension,
 	   Vector<Real> & nodes,
 	   const ID & id,
 	   const MemoryID & memory_id) :
   Memory(memory_id), id(id), nodes_global_ids(NULL), nodes_type(NULL),
   created_nodes(false),
   connectivities("connectivities", id),
   normals("normals", id),
   spatial_dimension(spatial_dimension),
   types_offsets(Vector<UInt>(_max_element_type + 1, 1)),
   ghost_types_offsets(Vector<UInt>(_max_element_type + 1, 1)),
   nb_surfaces(0),
   surface_id("surface_id", id),
   element_to_subelement("element_to_subelement", id),
   subelement_to_element("subelement_to_element", id),
   uint_data("by_element_uint_data", id) {
   AKANTU_DEBUG_IN();
 
   this->nodes = &(nodes);
   nb_global_nodes = nodes.getSize();
 
   init();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Mesh::init() {
   //  this->types_offsets.resize(_max_element_type);
 
   nodes_type = NULL;
   computeBoundingBox();
 }
 
 /* -------------------------------------------------------------------------- */
 Mesh::~Mesh() {
   AKANTU_DEBUG_IN();
 
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
 
     Mesh::type_iterator it  = firstType(0, gt);
     Mesh::type_iterator end = lastType(0, gt);
     for(; it != end; ++it) {
       UIntDataMap & map = uint_data(*it, gt);
       UIntDataMap::iterator dit;
       for (dit = map.begin(); dit != map.end(); ++dit) {
 	if(dit->second) delete dit->second;
       }
       map.clear();
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Mesh::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   stream << space << "Mesh [" << std::endl;
   stream << space << " + id                : " << this->id << std::endl;
   stream << space << " + spatial dimension : " << this->spatial_dimension << std::endl;
   stream << space << " + nodes [" << std::endl;
   nodes->printself(stream, indent+2);
   stream << space << " ]" << std::endl;
 
   stream << space << " + connectivities [" << std::endl;
   connectivities.printself(stream, indent+2);
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 void Mesh::computeBoundingBox(){
   AKANTU_DEBUG_IN();
   for (UInt k = 0; k < spatial_dimension; ++k) {
     local_lower_bounds[k] =   std::numeric_limits<double>::max();
     local_upper_bounds[k] = - std::numeric_limits<double>::max();
   }
 
   for (UInt i = 0; i < nodes->getSize(); ++i) {
     if(!isPureGhostNode(i))
       for (UInt k = 0; k < spatial_dimension; ++k) {
         local_lower_bounds[k] = std::min(local_lower_bounds[k], (*nodes)(i, k));
         local_upper_bounds[k] = std::max(local_upper_bounds[k], (*nodes)(i, k));
       }
   }
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
 
   Real reduce_bounds[2 * spatial_dimension];
   for (UInt k = 0; k < spatial_dimension; ++k) {
     reduce_bounds[2*k    ] =   local_lower_bounds[k];
     reduce_bounds[2*k + 1] = - local_upper_bounds[k];
   }
 
   comm.allReduce(reduce_bounds, 2 * spatial_dimension, _so_min);
 
   for (UInt k = 0; k < spatial_dimension; ++k) {
     lower_bounds[k] =   reduce_bounds[2*k];
     upper_bounds[k] = - reduce_bounds[2*k + 1];
   }
 
   for (UInt k = 0; k < spatial_dimension; ++k)
     size[k] = upper_bounds[k] - lower_bounds[k];
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Mesh::setSurfaceIDsFromIntData(const std::string & data_name) {
 
   std::set<Surface> surface_ids;
 
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
 
     Mesh::type_iterator it  = firstType(spatial_dimension - 1, gt);
     Mesh::type_iterator end = lastType(spatial_dimension - 1, gt);
     for(; it != end; ++it) {
       UIntDataMap & map = uint_data(*it, gt);
       UIntDataMap::iterator it_data = map.find(data_name);
       AKANTU_DEBUG_ASSERT(it_data != map.end(),
 			  "No data named " << data_name
 			  << " present in the mesh " << id
 			  << " for the element type " << *it);
       AKANTU_DEBUG_ASSERT(!surface_id.exists(*it, gt),
 			  "Surface id for type (" << gt << ":" << *it
 			  << ") already set to the vector " << surface_id(*it, gt).getID());
 
       surface_id.setVector(*it, gt, *it_data->second);
 
       for (UInt s = 0; s < it_data->second->getSize(); ++s) {
 	surface_ids.insert((*it_data->second)(s));
       }
     }
   }
 
   nb_surfaces = surface_ids.size();
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void Mesh::initByElementTypeVector(ByElementTypeVector<T> & vect,
 				   UInt nb_component,
 				   UInt dim,
 				   const bool & flag_nb_node_per_elem_multiply,
-				   ElementKind element_kind) const {
+				   ElementKind element_kind,
+				   bool size_to_nb_element) const {
   AKANTU_DEBUG_IN();
 
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
 
     Mesh::type_iterator it  = firstType(dim, gt, element_kind);
     Mesh::type_iterator end = lastType(dim, gt, element_kind);
     for(; it != end; ++it) {
       ElementType type = *it;
       if (flag_nb_node_per_elem_multiply) nb_component *= Mesh::getNbNodesPerElement(*it);
-      vect.alloc(0, nb_component, type);
+      UInt size = 0;
+      if (size_to_nb_element) size = this->getNbElement(type, gt);
+      vect.alloc(size, nb_component, type);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template void Mesh::initByElementTypeVector<Real>(ByElementTypeVector<Real> & vect,
 						  UInt nb_component,
 						  UInt dim,
 						  const bool & flag_nb_elem_multiply,
-						  ElementKind element_kind) const;
+						  ElementKind element_kind,
+						  bool size_to_nb_element) const;
 
 template void Mesh::initByElementTypeVector<Int>(ByElementTypeVector<Int> & vect,
 						 UInt nb_component,
 						 UInt dim,
 						 const bool & flag_nb_elem_multiply,
-						 ElementKind element_kind) const;
+						 ElementKind element_kind,
+						 bool size_to_nb_element) const;
 
 template void Mesh::initByElementTypeVector<UInt>(ByElementTypeVector<UInt> & vect,
 						  UInt nb_component,
 						  UInt dim,
 						  const bool & flag_nb_elem_multiply,
-						  ElementKind element_kind) const;
+						  ElementKind element_kind,
+						  bool size_to_nb_element) const;
 
 template void Mesh::initByElementTypeVector<bool>(ByElementTypeVector<bool> & vect,
 						  UInt nb_component,
 						  UInt dim,
 						  const bool & flag_nb_elem_multiply,
-						  ElementKind element_kind) const;
+						  ElementKind element_kind,
+						  bool size_to_nb_element) const;
 
 
 __END_AKANTU__
diff --git a/src/fem/mesh.hh b/src/fem/mesh.hh
index 99d2074b8..b47b6b8bd 100644
--- a/src/fem/mesh.hh
+++ b/src/fem/mesh.hh
@@ -1,553 +1,595 @@
 /**
  * @file   mesh.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Wed Jun 16 11:53:53 2010
  *
  * @brief  the class representing the meshes
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #ifndef __AKANTU_MESH_HH__
 #define __AKANTU_MESH_HH__
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "aka_memory.hh"
 #include "aka_vector.hh"
 #include "element_class.hh"
 #include "by_element_type.hh"
 #include "aka_event_handler.hh"
 
 /* -------------------------------------------------------------------------- */
 #include <set>
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /* Element                                                                    */
 /* -------------------------------------------------------------------------- */
 class Element {
 public:
   Element(ElementType type = _not_defined, UInt element = 0,
 	  GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) :
     type(type), element(element),
     ghost_type(ghost_type), kind(kind) {};
 
   Element(const Element & element) {
     this->type    = element.type;
     this->element = element.element;
     this->ghost_type = element.ghost_type;
     this->kind = element.kind;
   }
 
   inline bool operator==(const Element & elem) const {
     return ((element == elem.element)
 	    && (type == elem.type)
 	    && (ghost_type == elem.ghost_type)
 	    && (kind == elem.kind));
   }
 
   inline bool operator!=(const Element & elem) const {
     return ((element != elem.element)
 	    || (type != elem.type)
 	    || (ghost_type != elem.ghost_type)
 	    || (kind != elem.kind));
   }
 
+  bool operator<(const Element& rhs) const {
+    bool res = ((this->kind < rhs.kind) ||
+		((this->kind == rhs.kind) &&
+		 ((this->ghost_type < rhs.ghost_type) ||
+		  ((this->ghost_type == rhs.ghost_type) &&
+		   ((this->type < rhs.type) ||
+		    ((this->type == rhs.type) &&
+		     (this->element < rhs.element)))))));
+    return res;
+  }
 
   virtual ~Element() {};
 
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 public:
   ElementType type;
   UInt element;
   GhostType ghost_type;
   ElementKind kind;
 };
 
 struct CompElementLess {
   bool operator() (const Element& lhs, const Element& rhs) const {
-    bool res = ((lhs.kind < rhs.kind) ||
-		((lhs.kind == rhs.kind) &&
-		 ((lhs.ghost_type < rhs.ghost_type) ||
-		  ((lhs.ghost_type == rhs.ghost_type) &&
-		   ((lhs.type < rhs.type) ||
-		    ((lhs.type == rhs.type) &&
-		     (lhs.element < rhs.element)))))));
-    return res;
+    return lhs < rhs;
   }
 };
 
 extern const Element ElementNull;
 
 
 
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 /* Mesh modifications events                                              */
 /* -------------------------------------------------------------------------- */
 template<class Entity>
 class MeshEvent {
 public:
   const Vector<Entity> & getList() const { return list; }
   Vector<Entity> & getList() { return list; }
 protected:
   Vector<Entity> list;
 };
 
+
+
+class Mesh;
+
 class NewNodesEvent : public MeshEvent<UInt> { };
-class RemovedNodesEvent : public MeshEvent<UInt> { };
+class RemovedNodesEvent : public MeshEvent<UInt> {
+public:
+  inline RemovedNodesEvent(const Mesh & mesh);
+  AKANTU_GET_MACRO_NOT_CONST(NewNumbering, new_numbering, Vector<UInt> &);
+  AKANTU_GET_MACRO(NewNumbering, new_numbering, const Vector<UInt> &);
+private:
+  Vector<UInt> new_numbering;
+};
+
 class NewElementsEvent : public MeshEvent<Element> { };
-class RemovedElementsEvent : public MeshEvent<Element> { };
+class RemovedElementsEvent : public MeshEvent<Element> {
+public:
+  inline RemovedElementsEvent(const Mesh & mesh);
+  AKANTU_GET_MACRO(NewNumbering, new_numbering, const ByElementTypeUInt &);
+  AKANTU_GET_MACRO_NOT_CONST(NewNumbering, new_numbering, ByElementTypeUInt &);
+  AKANTU_GET_MACRO_BY_ELEMENT_TYPE(NewNumbering, new_numbering, UInt);
+  AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NewNumbering, new_numbering, UInt);
+protected:
+  ByElementTypeUInt new_numbering;
+};
 
 /* -------------------------------------------------------------------------- */
 
 class MeshEventHandler {
 public:
   virtual ~MeshEventHandler() {};
   /* ------------------------------------------------------------------------ */
   /* Internal code                                                            */
   /* ------------------------------------------------------------------------ */
 public:
   inline void sendEvent(const NewNodesEvent & event)     { onNodesAdded  (event.getList()); }
-  inline void sendEvent(const RemovedNodesEvent & event) { onNodesRemoved(event.getList()); }
+  inline void sendEvent(const RemovedNodesEvent & event) { onNodesRemoved(event.getList(),
+									  event.getNewNumbering()); }
 
   inline void sendEvent(const NewElementsEvent & event)     { onElementsAdded  (event.getList()); }
-  inline void sendEvent(const RemovedElementsEvent & event) { onElementsRemoved(event.getList()); }
+  inline void sendEvent(const RemovedElementsEvent & event) { onElementsRemoved(event.getList(),
+										event.getNewNumbering()); }
 
   /* ------------------------------------------------------------------------ */
   /* Interface                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   virtual void onNodesAdded  (__attribute__((unused)) const Vector<UInt> & nodes_list) {  }
-  virtual void onNodesRemoved(__attribute__((unused)) const Vector<UInt> & nodes_list) {  }
+  virtual void onNodesRemoved(__attribute__((unused)) const Vector<UInt> & nodes_list,
+			      __attribute__((unused)) const Vector<UInt> & new_numbering) {  }
+
 
   virtual void onElementsAdded  (__attribute__((unused)) const Vector<Element> & elements_list) { }
-  virtual void onElementsRemoved(__attribute__((unused)) const Vector<Element> & elements_list) { }
+  virtual void onElementsRemoved(__attribute__((unused)) const Vector<Element> & elements_list,
+				 __attribute__((unused)) const ByElementTypeUInt & new_numbering) { }
 };
 
 /* -------------------------------------------------------------------------- */
 /* Mesh                                                                       */
 /* -------------------------------------------------------------------------- */
 
 /**
  * @class  Mesh this  contain the  coordinates of  the nodes  in  the Mesh.nodes
  * Vector,  and the  connectivity. The  connectivity  are stored  in by  element
  * types.
  *
  * To  know  all  the  element  types   present  in  a  mesh  you  can  get  the
  * Mesh::ConnectivityTypeList
  *
  * In order to loop on all element you have to loop on all types like this :
  * @code
   Mesh::type_iterator it = mesh.firstType(dim, ghost_type);
   Mesh::type_iterator end = mesh.lastType(dim, ghost_type);
 
   for(; it != end; ++it) {
     UInt nb_element  = mesh.getNbElement(*it);
     const Vector<UInt> & conn = mesh.getConnectivity(*it);
 
     for(UInt e = 0; e < nb_element; ++e) {
        ...
     }
   }
   @endcode
  */
 class Mesh : protected Memory, public EventHandlerManager<MeshEventHandler> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// constructor that create nodes coordinates array
   Mesh(UInt spatial_dimension,
        const ID & id = "mesh",
        const MemoryID & memory_id = 0);
 
   /// constructor that use an existing nodes coordinates array, by knowing its ID
   Mesh(UInt spatial_dimension,
        const ID & nodes_id,
        const ID & id = "mesh",
        const MemoryID & memory_id = 0);
 
   /**
    * constructor that use an existing nodes coordinates
    * array, by getting the vector of coordinates
    */
   Mesh(UInt spatial_dimension,
        Vector<Real> & nodes,
        const ID & id = "mesh",
        const MemoryID & memory_id = 0);
 
 
   virtual ~Mesh();
 
   /// @typedef ConnectivityTypeList list of the types present in a Mesh
   typedef std::set<ElementType> ConnectivityTypeList;
 
   //  typedef Vector<Real> * NormalsMap[_max_element_type];
 
 private:
   /// initialize the connectivity to NULL and other stuff
   void init();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /// function that computes the bounding box (fills xmin, xmax)
   void computeBoundingBox();
 
   /// init a by-element-type real vector with provided ids
   template<typename T>
   void initByElementTypeVector(ByElementTypeVector<T> & v,
  			       UInt nb_component,
-			       UInt size,
+			       UInt spatial_dimension,
 			       const bool & flag_nb_node_per_elem_multiply = false,
-			       ElementKind element_kind = _ek_regular) const; /// @todo: think about nicer way to do it
+			       ElementKind element_kind = _ek_regular,
+			       bool size_to_nb_element = false) const; /// @todo: think about nicer way to do it
 
   /// extract coordinates of nodes from an element
   template<typename T>
   inline void extractNodalValuesFromElement(const Vector<T> & nodal_values,
 					    T * elemental_values,
 					    UInt * connectivity,
 					    UInt n_nodes,
 					    UInt nb_degree_of_freedom) const;
 
   /// extract coordinates of nodes from a reversed element
   inline void extractNodalCoordinatesFromPBCElement(Real * local_coords,
 						    UInt * connectivity,
 						    UInt n_nodes);
 
   /// convert a element to a linearized element
   inline UInt elementToLinearized(const Element & elem);
 
   /// convert a linearized element to an element
   inline Element linearizedToElement (UInt linearized_element);
 
   /// update the types offsets array for the conversions
   inline void updateTypesOffsets(const GhostType & ghost_type);
 
   /// add a Vector of connectivity for the type <type>.
   inline void addConnectivityType(const ElementType & type);
 
+  /* ------------------------------------------------------------------------ */
+  template <class Event>
+  inline void sendEvent(Event & event) {
+    if(event.getList().getSize() != 0)
+      EventHandlerManager<MeshEventHandler>::sendEvent<Event>(event);
+  }
+
+  /* ------------------------------------------------------------------------ */
+  template<typename T>
+  inline void removeNodesFromVector(Vector<T> & vect, const Vector<UInt> & new_numbering);
+
+
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   AKANTU_GET_MACRO(ID, id, const ID &);
 
   /// get the spatial dimension of the mesh = number of component of the coordinates
   AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt);
 
   /// get the nodes Vector aka coordinates
   AKANTU_GET_MACRO(Nodes, *nodes, const Vector<Real> &);
   AKANTU_GET_MACRO_NOT_CONST(Nodes, *nodes, Vector<Real> &);
 
   /// get the number of nodes
   AKANTU_GET_MACRO(NbNodes, nodes->getSize(), UInt);
 
   /// get the Vector of global ids of the nodes (only used in parallel)
   AKANTU_GET_MACRO(GlobalNodesIds, *nodes_global_ids, const Vector<UInt> &);
 
   /// get the global id of a node
   inline UInt getNodeGlobalId(UInt local_id) const;
 
   /// get the global number of nodes
   inline UInt getNbGlobalNodes() const;
 
   /// get the nodes type Vector
   AKANTU_GET_MACRO(NodesType, *nodes_type, const Vector<Int> &);
   inline Int getNodeType(UInt local_id) const;
 
   /// say if a node is a pure ghost node
   inline bool isPureGhostNode(UInt n) const;
 
   /// say if a node is pur local or master node
   inline bool isLocalOrMasterNode(UInt n) const;
 
   inline bool isLocalNode(UInt n) const;
   inline bool isMasterNode(UInt n) const;
   inline bool isSlaveNode(UInt n) const;
 
   AKANTU_GET_MACRO(XMin, lower_bounds[0], Real);
   AKANTU_GET_MACRO(YMin, lower_bounds[1], Real);
   AKANTU_GET_MACRO(ZMin, lower_bounds[2], Real);
   AKANTU_GET_MACRO(XMax, upper_bounds[0], Real);
   AKANTU_GET_MACRO(YMax, upper_bounds[1], Real);
   AKANTU_GET_MACRO(ZMax, upper_bounds[2], Real);
 
   inline void getLowerBounds(Real * lower) const;
   inline void getUpperBounds(Real * upper) const;
 
   inline void getLocalLowerBounds(Real * lower) const;
   inline void getLocalUpperBounds(Real * upper) const;
 
   /// get the number of surfaces
   AKANTU_GET_MACRO(NbSurfaces, nb_surfaces, UInt);
 
   /// get the connectivity Vector for a given type
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Connectivity, connectivities, UInt);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Connectivity, connectivities, UInt);
 
   /// @todo take out this set, if mesh can read surface id
   /// set the number of surfaces
   AKANTU_SET_MACRO(NbSurfaces, nb_surfaces, UInt);
 
   /// get the number of element of a type in the mesh
   inline UInt getNbElement(const ElementType & type, const GhostType & ghost_type = _not_ghost) const;
 
   // /// get the number of ghost element of a type in the mesh
   // inline UInt getNbGhostElement(const ElementType & type) const;
 
   /// get the connectivity list either for the elements or the ghost elements
   inline const ConnectivityTypeList & getConnectivityTypeList(const GhostType & ghost_type = _not_ghost) const;
 
   /// compute the barycenter of a given element
   inline void getBarycenter(UInt element, const ElementType & type, Real * barycenter,
 			    GhostType ghost_type = _not_ghost) const;
 
   /// get the element connected to a subelement
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementToSubelement, element_to_subelement, Vector<Element>);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementToSubelement, element_to_subelement, Vector<Element>);
 
   /// get the subelement connected to an element
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(SubelementToElement, subelement_to_element, Element);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(SubelementToElement, subelement_to_element, Element);
 
   /// get the surface values of facets
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(SurfaceID, surface_id, UInt);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(SurfaceID, surface_id, UInt);
 
   /// set the int data to the surface id vectors
   void setSurfaceIDsFromIntData(const std::string & data_name);
 
   inline const Vector<UInt> & getUIntData(const ElementType & el_type,
 					  const std::string & data_name,
 					  const GhostType & ghost_type = _not_ghost) const;
 
   /* ------------------------------------------------------------------------ */
   /* Wrappers on ElementClass functions                                       */
   /* ------------------------------------------------------------------------ */
 public:
   /// get the number of nodes per element for a given element type
   static inline UInt getNbNodesPerElement(const ElementType & type);
 
   /// get the number of nodes per element for a given element type considered as
   /// a first order element
   static inline ElementType getP1ElementType(const ElementType & type);
 
   /// get the kind of the element type
   static inline ElementKind getKind(const ElementType & type);
 
   /// get spatial dimension of a type of element
   static inline UInt getSpatialDimension(const ElementType & type);
 
   /// get number of facets of a given element type
   static inline UInt getNbFacetsPerElement(const ElementType & type);
 
   /// get local connectivity of a facet for a given facet type
   static inline UInt ** getFacetLocalConnectivity(const ElementType & type);
 
   /// get the type of the surface element associated to a given element
   static inline ElementType getFacetElementType(const ElementType & type);
 
   /// get the pointer to the list of elements for a given type
   inline Vector<UInt> * getReversedElementsPBCPointer(const ElementType & type);
 
 
   /* ------------------------------------------------------------------------ */
   /* Element type Iterator                                                    */
   /* ------------------------------------------------------------------------ */
   typedef ByElementTypeUInt::type_iterator type_iterator;
 
   inline type_iterator firstType(UInt dim = 0,
 				 GhostType ghost_type = _not_ghost,
 				 ElementKind kind = _ek_regular) const {
     return connectivities.firstType(dim, ghost_type, kind);
   }
 
   inline type_iterator lastType(UInt dim = 0,
 				GhostType ghost_type = _not_ghost,
 				ElementKind kind = _ek_regular) const {
     return connectivities.lastType(dim, ghost_type, kind);
   }
 
 
   /* ------------------------------------------------------------------------ */
   /* Private methods for friends                                              */
   /* ------------------------------------------------------------------------ */
 private:
   friend class MeshIOMSH;
   friend class MeshIOMSHStruct;
   friend class MeshIODiana;
   friend class MeshUtils;
   friend class DistributedSynchronizer;
 
   AKANTU_GET_MACRO(NodesPointer, nodes, Vector<Real> *);
 
   /// get a pointer to the nodes_global_ids Vector<UInt> and create it if necessary
   inline Vector<UInt> * getNodesGlobalIdsPointer();
 
   /// get a pointer to the nodes_type Vector<Int> and create it if necessary
   inline Vector<Int> * getNodesTypePointer();
 
   /// get a pointer to the connectivity Vector for the given type and create it if necessary
   inline Vector<UInt> * getConnectivityPointer(const ElementType & type,
 					       const GhostType & ghost_type = _not_ghost);
 
   // inline Vector<Real> * getNormalsPointer(ElementType type) const;
 
   /// get a pointer to the surface_id Vector for the given type and create it if necessary
   inline Vector<UInt> * getSurfaceIDPointer(const ElementType & type, const GhostType & ghost_type = _not_ghost);
 
   /// get the UIntDataMap for a given ElementType
   inline UIntDataMap & getUIntDataMap(const ElementType & el_type,
 				      const GhostType & ghost_type = _not_ghost);
 
   /// get the IntDataMap pointer (modifyable) for a given ElementType
   inline Vector<UInt> * getUIntDataPointer(const ElementType & el_type,
 					   const std::string & data_name,
 					   const GhostType & ghost_type = _not_ghost);
 
   /// get a pointer to the element_to_subelement Vector for the given type and create it if necessary
   inline Vector<Vector<Element> > * getElementToSubelementPointer(const ElementType & type,
 								  const GhostType & ghost_type = _not_ghost);
 
   /// get a pointer to the subelement_to_element Vector for the given type and create it if necessary
   inline Vector<Element > * getSubelementToElementPointer(const ElementType & type,
 							  const GhostType & ghost_type = _not_ghost);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
 
   /// id of the mesh
   ID id;
 
   /// array of the nodes coordinates
   Vector<Real> * nodes;
 
   /// global node ids
   Vector<UInt> * nodes_global_ids;
 
   /// node type,  -3 pure ghost, -2  master for the  node, -1 normal node,  i in
   /// [0-N] slave node and master is proc i
   Vector<Int> * nodes_type;
 
   /// global number of nodes;
   UInt nb_global_nodes;
 
   /// boolean to know if the nodes have to be deleted with the mesh or not
   bool created_nodes;
 
   /// all class of elements present in this mesh (for heterogenous meshes)
   ByElementTypeUInt connectivities;
 
   /// map to normals for all class of elements present in this mesh
   ByElementTypeReal normals;
 
   /// list of all existing types in the mesh
   ConnectivityTypeList type_set;
 
   /// the spatial dimension of this mesh
   UInt spatial_dimension;
 
   /// types offsets
   Vector<UInt> types_offsets;
 
   /// list of all existing types in the mesh
   ConnectivityTypeList ghost_type_set;
   /// ghost types offsets
   Vector<UInt> ghost_types_offsets;
 
   /// number of surfaces present in this mesh
   UInt nb_surfaces;
 
   /// surface id of the surface elements in this mesh
   ByElementTypeUInt surface_id;
 
   /// min of coordinates
   Real lower_bounds[3];
   /// max of coordinates
   Real upper_bounds[3];
   /// size covered by the mesh on each direction
   Real size[3];
 
   /// local min of coordinates
   Real local_lower_bounds[3];
   /// local max of coordinates
   Real local_upper_bounds[3];
 
   /// List of elements connected to subelements
   ByElementTypeVector<Vector<Element> > element_to_subelement;
 
   /// List of subelements connected to elements
   ByElementTypeVector<Element > subelement_to_element;
 
   // /// list of elements that are reversed due to pbc
   // ByElementTypeUInt reversed_elements_pbc;
   // /// direction in which pbc are to be applied
   // UInt pbc_directions[3];
 
   /// list of the vectors corresponding to tags in the mesh
   ByElementTypeUIntDataMap uint_data;
 
 };
 
 /* -------------------------------------------------------------------------- */
 /* Inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const Element & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 #if defined (AKANTU_INCLUDE_INLINE_IMPL)
 #  include "mesh_inline_impl.cc"
 #endif
 
 #include "by_element_type_tmpl.hh"
 
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const Mesh & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 
 __END_AKANTU__
 
 
 #endif /* __AKANTU_MESH_HH__ */
diff --git a/src/fem/mesh_inline_impl.cc b/src/fem/mesh_inline_impl.cc
index 58d315757..d84f56819 100644
--- a/src/fem/mesh_inline_impl.cc
+++ b/src/fem/mesh_inline_impl.cc
@@ -1,496 +1,550 @@
 /**
  * @file   mesh_inline_impl.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Wed Jul 14 23:58:08 2010
  *
  * @brief  Implementation of the inline functions of the mesh class
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 __END_AKANTU__
 
 #include "cohesive_element.hh"
 
 __BEGIN_AKANTU__
 
+/* -------------------------------------------------------------------------- */
+inline RemovedNodesEvent::RemovedNodesEvent(const Mesh & mesh) :
+  new_numbering(mesh.getNbNodes(), 1, "new_numbering") {
+}
+
+/* -------------------------------------------------------------------------- */
+inline RemovedElementsEvent::RemovedElementsEvent(const Mesh & mesh) :
+  new_numbering("new_numbering", mesh.getID()) {
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+inline void Mesh::sendEvent<RemovedElementsEvent>(RemovedElementsEvent & event) {
+  if(event.getList().getSize() != 0) {
+    connectivities.onElementsRemoved(event.getNewNumbering());
+    EventHandlerManager<MeshEventHandler>::sendEvent(event);
+  }
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+inline void Mesh::sendEvent<RemovedNodesEvent>(RemovedNodesEvent & event) {
+  if(event.getList().getSize() != 0) {
+    if(created_nodes)    removeNodesFromVector(*nodes           , event.getNewNumbering());
+    if(nodes_global_ids) removeNodesFromVector(*nodes_global_ids, event.getNewNumbering());
+    if(nodes_type)       removeNodesFromVector(*nodes_type      , event.getNewNumbering());
+
+    EventHandlerManager<MeshEventHandler>::sendEvent(event);
+  }
+}
+
+/* -------------------------------------------------------------------------- */
+template<typename T>
+inline void Mesh::removeNodesFromVector(Vector<T> & vect, const Vector<UInt> & new_numbering) {
+  Vector<T> tmp(vect.getSize(), vect.getNbComponent());
+  UInt nb_component = vect.getNbComponent();
+  UInt new_nb_nodes = 0;
+  for (UInt i = 0; i < new_numbering.getSize(); ++i) {
+    UInt new_i = new_numbering(i);
+    if(new_i != UInt(-1)) {
+      memcpy(tmp.storage() + new_i * nb_component,
+	     vect.storage() + i * nb_component,
+	     nb_component * sizeof(T));
+      ++new_nb_nodes;
+    }
+  }
+
+  tmp.resize(new_nb_nodes);
+  vect.copy(tmp);
+}
+
 /* -------------------------------------------------------------------------- */
 inline UInt Mesh::elementToLinearized(const Element & elem) {
   AKANTU_DEBUG_ASSERT(elem.type < _max_element_type &&
 		      elem.element < types_offsets.values[elem.type+1],
 		      "The element " << elem
 		      << "does not exists in the mesh " << id);
 
   return types_offsets.values[elem.type] + elem.element;
 }
 
 /* -------------------------------------------------------------------------- */
 inline Element Mesh::linearizedToElement (UInt linearized_element) {
 
   UInt t;
 
   for (t = _not_defined;
        t != _max_element_type && linearized_element >= types_offsets(t);
        ++t);
 
   AKANTU_DEBUG_ASSERT(t != _max_element_type,
    		      "The linearized element " << linearized_element
    		      << "does not exists in the mesh " << id);
 
   --t;
   return Element(ElementType(t), linearized_element - types_offsets.values[t]);
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Mesh::updateTypesOffsets(const GhostType & ghost_type) {
   types_offsets.clear();
   type_iterator it   = firstType(0, ghost_type);
   type_iterator last = lastType(0, ghost_type);
 
   for (; it != last; ++it)
     types_offsets(*it) = connectivities(*it, ghost_type).getSize();
 
   for (UInt t = _not_defined + 1; t < _max_element_type; ++t)
     types_offsets(t) += types_offsets(t - 1);
   for (UInt t = _max_element_type; t > _not_defined; --t)
     types_offsets(t) = types_offsets(t - 1);
   types_offsets(0) = 0;
 }
 
 /* -------------------------------------------------------------------------- */
 inline const Mesh::ConnectivityTypeList & Mesh::getConnectivityTypeList(const GhostType & ghost_type) const {
   if (ghost_type == _not_ghost)
     return type_set;
   else
     return ghost_type_set;
 }
 
 /* -------------------------------------------------------------------------- */
 inline Vector<UInt> * Mesh::getNodesGlobalIdsPointer() {
   AKANTU_DEBUG_IN();
   if(nodes_global_ids == NULL) {
     std::stringstream sstr; sstr << id << ":nodes_global_ids";
     nodes_global_ids = &(alloc<UInt>(sstr.str(), nodes->getSize(), 1));
   }
   AKANTU_DEBUG_OUT();
   return nodes_global_ids;
 }
 
 /* -------------------------------------------------------------------------- */
 inline Vector<Int> * Mesh::getNodesTypePointer() {
   AKANTU_DEBUG_IN();
   if(nodes_type == NULL) {
     std::stringstream sstr; sstr << id << ":nodes_type";
     nodes_type = &(alloc<Int>(sstr.str(), nodes->getSize(), 1, -1));
   }
   AKANTU_DEBUG_OUT();
   return nodes_type;
 }
 
 /* -------------------------------------------------------------------------- */
 inline Vector<UInt> * Mesh::getConnectivityPointer(const ElementType & type,
 						   const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   Vector<UInt> * tmp;
   if(!connectivities.exists(type, ghost_type)) {
     UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
 
     tmp = &(connectivities.alloc(0, nb_nodes_per_element,
 				 type, ghost_type));
 
     AKANTU_DEBUG_INFO("The connectivity vector for the type "
 		      << type << " created");
 
     if (ghost_type == _not_ghost) type_set.insert(type);
     else ghost_type_set.insert(type);
 
     updateTypesOffsets(ghost_type);
   } else {
     tmp = &connectivities(type, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
   return tmp;
 }
 
 /* -------------------------------------------------------------------------- */
 inline Vector<UInt> * Mesh::getSurfaceIDPointer(const ElementType & type, const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   Vector<UInt> * tmp;
   if(!surface_id.exists(type, ghost_type)) {
     tmp = &(surface_id.alloc(0, 1, type, ghost_type));
     AKANTU_DEBUG_INFO("The surface id vector for the type "
 		      << type << " created");
   } else {
     tmp = &(surface_id(type, ghost_type));
   }
 
   AKANTU_DEBUG_OUT();
   return tmp;
 }
 
 /* -------------------------------------------------------------------------- */
 inline Vector<Vector<Element> > * Mesh::getElementToSubelementPointer(const ElementType & type, const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   Vector<Vector<Element> > * tmp;
   if(!element_to_subelement.exists(type, ghost_type)) {
     tmp = &(element_to_subelement.alloc(0, 1, type, ghost_type));
 
     AKANTU_DEBUG_INFO("The element_to_subelement vector for the type "
 		      << type << " created");
   } else {
     tmp = &(element_to_subelement(type, ghost_type));
   }
 
   AKANTU_DEBUG_OUT();
   return tmp;
 }
 
 /* -------------------------------------------------------------------------- */
 inline Vector<Element > * Mesh::getSubelementToElementPointer(const ElementType & type, const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   Vector<Element > * tmp;
   if(!subelement_to_element.exists(type, ghost_type)) {
 
     UInt nb_facets = getNbFacetsPerElement(type);
 
     tmp = &(subelement_to_element.alloc(0, nb_facets, type, ghost_type));
 
     AKANTU_DEBUG_INFO("The subelement_to_element vector for the type "
 		      << type << " created");
   } else {
     tmp = &(subelement_to_element(type, ghost_type));
   }
 
   AKANTU_DEBUG_OUT();
   return tmp;
 }
 
 /* -------------------------------------------------------------------------- */
 inline Vector<UInt> * Mesh::getUIntDataPointer(const ElementType & el_type,
 					       const std::string & data_name,
 					       const GhostType & ghost_type) {
   //  AKANTU_DEBUG_IN();
 
   Vector<UInt> * data;
   // if(!uint_data.exists(el_type, ghost_type)){
   //   uint_data(UIntDataMap(), el_type, ghost_type);
   // }
   UIntDataMap & map = uint_data(el_type, ghost_type);
   UIntDataMap::iterator it = map.find(data_name);
   if(it == map.end()) {
     data = new Vector<UInt>(0, 1, data_name);
     map[data_name] = data;
   } else {
     data = it->second;
   }
 
   //  AKANTU_DEBUG_OUT();
   return data;
 }
 
 /* -------------------------------------------------------------------------- */
 inline const Vector<UInt> & Mesh::getUIntData(const ElementType & el_type,
 					      const std::string & data_name,
 					      const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   const UIntDataMap & map = uint_data(el_type, ghost_type);
   UIntDataMap::const_iterator it = map.find(data_name);
 
   AKANTU_DEBUG_ASSERT(it != map.end(),
 		      "No data named " << data_name << " in the mesh " << id);
 
   AKANTU_DEBUG_OUT();
   return *(it->second);
 }
 
 /* -------------------------------------------------------------------------- */
 inline UIntDataMap & Mesh::getUIntDataMap(const ElementType & el_type,
 					  const GhostType & ghost_type) {
   // AKANTU_DEBUG_ASSERT(uint_data.exists(el_type, ghost_type),
   // 		      "No UIntDataMap for the type (" << ghost_type << ":" << el_type << ")");
   return uint_data(el_type, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt Mesh::getNbElement(const ElementType & type,
 			       const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
-  const ByElementTypeUInt & const_conn = connectivities;
-
-  const Vector<UInt> & conn = const_conn(type, ghost_type);
-  AKANTU_DEBUG_OUT();
-  return conn.getSize();
+  try {
+    const Vector<UInt> & conn = connectivities(type, ghost_type);
+    AKANTU_DEBUG_OUT();
+    return conn.getSize();
+  } catch (...) {
+    AKANTU_DEBUG_OUT();
+    return 0;
+  }
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Mesh::getBarycenter(UInt element, const ElementType & type,
 				Real * barycenter,
 				GhostType ghost_type) const {
   AKANTU_DEBUG_IN();
 
   UInt * conn_val = getConnectivity(type, ghost_type).values;
   UInt nb_nodes_per_element = getNbNodesPerElement(type);
 
   Real local_coord[spatial_dimension * nb_nodes_per_element];
 
   UInt offset = element * nb_nodes_per_element;
   for (UInt n = 0; n < nb_nodes_per_element; ++n) {
     memcpy(local_coord + n * spatial_dimension,
 	   nodes->storage() + conn_val[offset + n] * spatial_dimension,
 	   spatial_dimension*sizeof(Real));
   }
 
   Math::barycenter(local_coord, nb_nodes_per_element, spatial_dimension, barycenter);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt Mesh::getNbNodesPerElement(const ElementType & type) {
   AKANTU_DEBUG_IN();
 
   UInt nb_nodes_per_element = 0;
 #define GET_NB_NODES_PER_ELEMENT(type)					\
   nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement()
 
 #define GET_NB_NODES_PER_ELEMENT_COHESIVE(type)				\
   nb_nodes_per_element = CohesiveElement<type>::getNbNodesPerElement()
 
   AKANTU_BOOST_ELEMENT_SWITCH(GET_NB_NODES_PER_ELEMENT,
 			      AKANTU_REGULAR_ELEMENT_TYPE,
 			      GET_NB_NODES_PER_ELEMENT_COHESIVE,
 			      AKANTU_COHESIVE_ELEMENT_TYPE);
 
 #undef GET_NB_NODES_PER_ELEMENT
 #undef GET_NB_NODES_PER_ELEMENT_COHESIVE
 
   AKANTU_DEBUG_OUT();
   return nb_nodes_per_element;
 }
 
 /* -------------------------------------------------------------------------- */
 inline ElementType Mesh::getP1ElementType(const ElementType & type) {
   AKANTU_DEBUG_IN();
 
   ElementType element_p1 = _not_defined;
 #define GET_ELEMENT_P1(type)				\
   element_p1 = ElementClass<type>::getP1ElementType()
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(GET_ELEMENT_P1);
 #undef GET_NB_NODES_PER_ELEMENT_P1
 
   AKANTU_DEBUG_OUT();
   return element_p1;
 }
 
 /* -------------------------------------------------------------------------- */
 inline ElementKind Mesh::getKind(const ElementType & type) {
   AKANTU_DEBUG_IN();
 
   ElementKind kind = _ek_not_defined;
 #define GET_KIND(type)				\
   kind = ElementClass<type>::getKind()
 
   AKANTU_BOOST_ELEMENT_SWITCH(GET_KIND,
 			      AKANTU_REGULAR_ELEMENT_TYPE,
 			      GET_KIND,
 			      AKANTU_COHESIVE_ELEMENT_TYPE);
 #undef GET_KIND
 
   AKANTU_DEBUG_OUT();
   return kind;
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt Mesh::getSpatialDimension(const ElementType & type) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = 0;
 #define GET_SPATIAL_DIMENSION(type)				\
   spatial_dimension = ElementClass<type>::getSpatialDimension()
 
 #define GET_SPATIAL_DIMENSION_COHESIVE(type)				\
   spatial_dimension = CohesiveElement<type>::getSpatialDimension()
 
 
   AKANTU_BOOST_ELEMENT_SWITCH(GET_SPATIAL_DIMENSION,
 			      AKANTU_REGULAR_ELEMENT_TYPE,
 			      GET_SPATIAL_DIMENSION_COHESIVE,
 			      AKANTU_COHESIVE_ELEMENT_TYPE);
 #undef GET_SPATIAL_DIMENSION
 #undef GET_SPATIAL_DIMENSION_COHESIVE
 
   AKANTU_DEBUG_OUT();
   return spatial_dimension;
 }
 
 /* -------------------------------------------------------------------------- */
 inline ElementType Mesh::getFacetElementType(const ElementType & type) {
   AKANTU_DEBUG_IN();
 
   ElementType surface_type = _not_defined;
 #define GET_FACET_TYPE(type)					\
   surface_type = ElementClass<type>::getFacetElementType()
 
 #define GET_FACET_TYPE_COHESIVE(type)				\
   surface_type = CohesiveElement<type>::getFacetElementType()
 
 
   AKANTU_BOOST_ELEMENT_SWITCH(GET_FACET_TYPE,
 			      AKANTU_REGULAR_ELEMENT_TYPE,
 			      GET_FACET_TYPE_COHESIVE,
 			      AKANTU_COHESIVE_ELEMENT_TYPE);
 #undef GET_FACET_TYPE
 #undef GET_FACET_TYPE_COHESIVE
 
   AKANTU_DEBUG_OUT();
   return surface_type;
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt Mesh::getNbFacetsPerElement(const ElementType & type) {
   AKANTU_DEBUG_IN();
 
   UInt n_facet = 0;
 #define GET_NB_FACET(type)				\
   n_facet = ElementClass<type>::getNbFacetsPerElement()
 
 #define GET_NB_FACET_COHESIVE(type)			\
   n_facet = CohesiveElement<type>::getNbFacetsPerElement()
 
 
   AKANTU_BOOST_ELEMENT_SWITCH(GET_NB_FACET,
 			      AKANTU_REGULAR_ELEMENT_TYPE,
 			      GET_NB_FACET_COHESIVE,
 			      AKANTU_COHESIVE_ELEMENT_TYPE);
 #undef GET_NB_FACET
 #undef GET_NB_FACET_COHESIVE
 
   AKANTU_DEBUG_OUT();
   return n_facet;
 }
 
 
 /* -------------------------------------------------------------------------- */
 inline UInt ** Mesh::getFacetLocalConnectivity(const ElementType & type) {
   AKANTU_DEBUG_IN();
 
   UInt ** facet_conn = NULL;
 #define GET_FACET_CON(type)						\
   facet_conn = ElementClass<type>::getFacetLocalConnectivityPerElement()
 
 #define GET_FACET_CON_COHESIVE(type)					\
   facet_conn = CohesiveElement<type>::getFacetLocalConnectivityPerElement()
 
   AKANTU_BOOST_ELEMENT_SWITCH(GET_FACET_CON,
 			      AKANTU_REGULAR_ELEMENT_TYPE,
 			      GET_FACET_CON_COHESIVE,
 			      AKANTU_COHESIVE_ELEMENT_TYPE);
 
 #undef GET_FACET_CON
 #undef GET_FACET_CON_COHESIVE
 
   AKANTU_DEBUG_OUT();
   return facet_conn;
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline void Mesh::extractNodalValuesFromElement(const Vector<T> & nodal_values,
 						T * local_coord,
 						UInt * connectivity,
 						UInt n_nodes,
 						UInt nb_degree_of_freedom) const {
   for (UInt n = 0; n < n_nodes; ++n) {
     memcpy(local_coord + n * nb_degree_of_freedom,
 	   nodal_values.storage() + connectivity[n] * nb_degree_of_freedom,
 	   nb_degree_of_freedom * sizeof(T));
   }
 }
 
 /* -------------------------------------------------------------------------- */
 #define DECLARE_GET_BOUND(Var, var)                               \
   inline void Mesh::get##Var##Bounds(Real * var) const {          \
     for (UInt i = 0; i < spatial_dimension; ++i) {                \
       var[i] = var##_bounds[i];                                   \
     }                                                             \
   }                                                               \
 
 DECLARE_GET_BOUND(Lower, lower)
 DECLARE_GET_BOUND(Upper, upper)
 
 DECLARE_GET_BOUND(LocalLower, local_lower)
 DECLARE_GET_BOUND(LocalUpper, local_upper)
 
 #undef DECLARE_GET_BOUND
 
 /* -------------------------------------------------------------------------- */
 inline void Mesh::addConnectivityType(const ElementType & type){
   getConnectivityPointer(type);
 }
 
 /* -------------------------------------------------------------------------- */
 inline bool Mesh::isPureGhostNode(UInt n) const {
   return nodes_type ? (*nodes_type)(n) == -3 : false;
 }
 
 /* -------------------------------------------------------------------------- */
 inline bool Mesh::isLocalOrMasterNode(UInt n) const {
   return nodes_type ? (*nodes_type)(n) == -2 || (*nodes_type)(n) == -1 : true;
 }
 
 
 /* -------------------------------------------------------------------------- */
 inline bool Mesh::isLocalNode(UInt n) const {
   return nodes_type ? (*nodes_type)(n) == -1 : true;
 }
 
 /* -------------------------------------------------------------------------- */
 inline bool Mesh::isMasterNode(UInt n) const {
   return nodes_type ? (*nodes_type)(n) == -2 : false;
 }
 
 /* -------------------------------------------------------------------------- */
 inline bool Mesh::isSlaveNode(UInt n) const {
   return nodes_type ? (*nodes_type)(n) >= 0 : false;
 }
 
 
 /* -------------------------------------------------------------------------- */
 inline UInt Mesh::getNodeGlobalId(UInt local_id) const {
   return nodes_global_ids ? (*nodes_global_ids)(local_id) : local_id;
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt Mesh::getNbGlobalNodes() const {
   return nodes_global_ids ? nb_global_nodes : nodes->getSize();
 }
 
 /* -------------------------------------------------------------------------- */
 inline Int Mesh::getNodeType(UInt local_id) const {
   return nodes_type ? (*nodes_type)(local_id) : -1;
 }
diff --git a/src/mesh_utils/mesh_utils.cc b/src/mesh_utils/mesh_utils.cc
index 2801b7f48..f49e99176 100644
--- a/src/mesh_utils/mesh_utils.cc
+++ b/src/mesh_utils/mesh_utils.cc
@@ -1,906 +1,924 @@
 /**
  * @file   mesh_utils.cc
  * @author Guillaume ANCIAUX <guillaume.anciaux@epfl.ch>
  * @date   Wed Aug 18 14:21:00 2010
  *
  * @brief  All mesh utils necessary for various tasks
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #include "mesh_utils.hh"
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildNode2Elements(const Mesh & mesh,
 				   CSR<UInt> & node_to_elem,
 				   UInt spatial_dimension) {
   AKANTU_DEBUG_IN();
   if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension();
   UInt nb_nodes = mesh.getNbNodes();
 
   const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList();
   Mesh::ConnectivityTypeList::const_iterator it;
 
   UInt nb_types = type_list.size();
   UInt nb_good_types = 0;
 
   UInt nb_nodes_per_element[nb_types];
   //  UInt nb_nodes_per_element_p1[nb_types];
 
   UInt * conn_val[nb_types];
   UInt nb_element[nb_types];
 
   //  ElementType type_p1;
 
   for(it = type_list.begin(); it != type_list.end(); ++it) {
     ElementType type = *it;
     if(Mesh::getSpatialDimension(type) != spatial_dimension) continue;
 
     nb_nodes_per_element[nb_good_types]    = Mesh::getNbNodesPerElement(type);
     //    type_p1 = Mesh::getP1ElementType(type);
     //    nb_nodes_per_element_p1[nb_good_types] = Mesh::getNbNodesPerElement(type_p1);
 
     conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).values;
     nb_element[nb_good_types] = mesh.getConnectivity(type, _not_ghost).getSize();
     nb_good_types++;
   }
 
   AKANTU_DEBUG_ASSERT(nb_good_types  != 0,
 		      "Some elements must be found in right dimension to compute facets!");
 
   /// array for the node-element list
   node_to_elem.resizeRows(nb_nodes);
   node_to_elem.clearRows();
 
   //  node_offset.resize(nb_nodes + 1);
   //  UInt * node_offset_val = node_offset.values;
 
   /// count number of occurrence of each node
   //  memset(node_offset_val, 0, (nb_nodes + 1)*sizeof(UInt));
   for (UInt t = 0; t < nb_good_types; ++t) {
     for (UInt el = 0; el < nb_element[t]; ++el) {
       UInt el_offset = el*nb_nodes_per_element[t];
       for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) {
 	++node_to_elem.rowOffset(conn_val[t][el_offset + n]);
 	//	node_offset_val[conn_val[t][el_offset + n]]++;
       }
     }
   }
 
   // /// convert the occurrence array in a csr one
   // for (UInt i = 1; i < nb_nodes; ++i) node_offset_val[i] += node_offset_val[i-1];
   // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i]  = node_offset_val[i-1];
   // node_offset_val[0] = 0;
 
   node_to_elem.countToCSR();
   node_to_elem.resizeCols();
   node_to_elem.beginInsertions();
   /// rearrange element to get the node-element list
   // node_to_elem.resize(node_offset_val[nb_nodes]);
   // UInt * node_to_elem_val = node_to_elem.values;
 
   for (UInt t = 0, linearized_el = 0; t < nb_good_types; ++t)
     for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) {
       UInt el_offset = el*nb_nodes_per_element[t];
       for (UInt n = 0; n < nb_nodes_per_element[t]; ++n)
 	node_to_elem.insertInRow(conn_val[t][el_offset + n], linearized_el);
       // node_to_elem_val[node_offset_val[conn_val[t][el_offset + n]]++] = linearized_el;
     }
 
   node_to_elem.endInsertions();
   // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i]  = node_offset_val[i-1];
   // node_offset_val[0] = 0;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildNode2ElementsByElementType(const Mesh & mesh,
 						ElementType type,
 						CSR<UInt> & node_to_elem) {
 						// Vector<UInt> & node_offset,
 						// Vector<UInt> & node_to_elem) {
 
   AKANTU_DEBUG_IN();
   UInt nb_nodes = mesh.getNbNodes();
 
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
   UInt nb_elements = mesh.getConnectivity(type, _not_ghost).getSize();
 
   UInt * conn_val = mesh.getConnectivity(type, _not_ghost).values;
 
   /// array for the node-element list
   node_to_elem.resizeRows(nb_nodes);
   node_to_elem.clearRows();
 
   // node_offset.resize(nb_nodes + 1);
   // UInt * node_offset_val = node_offset.values;
   // memset(node_offset_val, 0, (nb_nodes + 1)*sizeof(UInt));
 
   /// count number of occurrence of each node
   for (UInt el = 0; el < nb_elements; ++el) {
     UInt el_offset = el*nb_nodes_per_element;
     for (UInt n = 0; n < nb_nodes_per_element; ++n)
       ++node_to_elem.rowOffset(conn_val[el_offset + n]);
       //      node_offset_val[conn_val[nb_nodes_per_element*el + n]]++;
   }
 
   /// convert the occurrence array in a csr one
   // for (UInt i = 1; i < nb_nodes; ++i) node_offset_val[i] += node_offset_val[i-1];
   // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i]  = node_offset_val[i-1];
   // node_offset_val[0] = 0;
   node_to_elem.countToCSR();
 
   node_to_elem.resizeCols();
   node_to_elem.beginInsertions();
 
   /// save the element index in the node-element list
   // node_to_elem.resize(node_offset_val[nb_nodes]);
   // UInt * node_to_elem_val = node_to_elem.values;
 
   for (UInt el = 0; el < nb_elements; ++el) {
     UInt el_offset = el*nb_nodes_per_element;
     for (UInt n = 0; n < nb_nodes_per_element; ++n) {
       node_to_elem.insertInRow(conn_val[el_offset + n], el);
     }
     // node_to_elem_val[node_offset_val[conn_val[nb_nodes_per_element*el + n]]] = el;
     // node_offset_val[conn_val[nb_nodes_per_element*el + n]]++;
   }
 
   // ///  rearrange node_offset to start with 0
   // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i]  = node_offset_val[i-1];
   // node_offset_val[0] = 0;
   node_to_elem.endInsertions();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildFacets(Mesh & mesh){
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh.getSpatialDimension();
   ByElementTypeReal barycenter;
 
   buildFacetsDimension(mesh, mesh, true, spatial_dimension, barycenter);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildAllFacets(Mesh & mesh, Mesh & mesh_facets) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh.getSpatialDimension();
   ByElementTypeReal barycenter;
 
   /// generate facets
   buildFacetsDimension(mesh, mesh_facets, false, spatial_dimension, barycenter);
 
   /// compute their barycenters
   mesh_facets.initByElementTypeVector(barycenter, spatial_dimension, spatial_dimension - 1);
   Mesh::type_iterator it  = mesh_facets.firstType(spatial_dimension - 1);
   Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1);
   for(; it != end; ++it) {
     UInt nb_element = mesh_facets.getNbElement(*it);
     barycenter(*it).resize(nb_element);
 
     Vector<Real>::iterator<types::RVector> bary = barycenter(*it).begin(spatial_dimension);
     Vector<Real>::iterator<types::RVector> bary_end
       = barycenter(*it).end(spatial_dimension);
 
     for (UInt el = 0; bary != bary_end; ++bary, ++el) {
       mesh_facets.getBarycenter(el, *it, bary->storage());
     }
   }
 
   /// sort facets and generate subfacets
   for (UInt i = spatial_dimension - 1; i > 0; --i) {
     buildFacetsDimension(mesh_facets, mesh_facets, false, i, barycenter);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildFacetsDimension(Mesh & mesh,
 				     Mesh & mesh_facets,
 				     bool boundary_only,
 				     UInt dimension,
 				     ByElementTypeReal & barycenter){
   AKANTU_DEBUG_IN();
 
   const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList();
   Mesh::ConnectivityTypeList::const_iterator it;
 
   UInt nb_types = type_list.size();
   UInt nb_good_types = 0;
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   UInt nb_nodes_per_element[nb_types];
   UInt nb_nodes_per_facet[nb_types];
 
   UInt nb_facets[nb_types];
   UInt ** node_in_facet[nb_types];
   Vector<UInt> * connectivity_facets[nb_types];
   Vector<Vector<Element> > * element_to_subelement[nb_types];
   Vector<Element> * subelement_to_element[nb_types];
 
   UInt * conn_val[nb_types];
   UInt nb_element[nb_types];
 
   ElementType facet_type;
 
   Real epsilon = std::numeric_limits<Real>::epsilon();
 
   for(it = type_list.begin(); it != type_list.end(); ++it) {
     ElementType type = *it;
 
     if(mesh.getSpatialDimension(type) != dimension) continue;
 
     nb_nodes_per_element[nb_good_types] = mesh.getNbNodesPerElement(type);
 
     facet_type = mesh.getFacetElementType(type);
     nb_facets[nb_good_types] = mesh.getNbFacetsPerElement(type);
     node_in_facet[nb_good_types] = mesh.getFacetLocalConnectivity(type);
 
     nb_nodes_per_facet[nb_good_types] = mesh.getNbNodesPerElement(facet_type);
 
     // getting connectivity of boundary facets
     connectivity_facets[nb_good_types] = mesh_facets.getConnectivityPointer(facet_type);
     connectivity_facets[nb_good_types]->resize(0);
 
     element_to_subelement[nb_good_types] = mesh_facets.getElementToSubelementPointer(facet_type);
     element_to_subelement[nb_good_types]->resize(0);
 
     conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).values;
     nb_element[nb_good_types] = mesh.getConnectivity(type, _not_ghost).getSize();
 
     subelement_to_element[nb_good_types] = mesh_facets.getSubelementToElementPointer(type);
     subelement_to_element[nb_good_types]->resize(nb_element[nb_good_types]);
 
     nb_good_types++;
   }
 
 
   CSR<UInt> node_to_elem;
   // Vector<UInt> node_offset;
   // Vector<UInt> node_to_elem;
 
   //  buildNode2Elements(mesh,node_offset,node_to_elem);
   buildNode2Elements(mesh, node_to_elem, dimension);
 
   // std::cout << "node offset " << std::endl << node_offset << std::endl;
   // std::cout << "node to elem " << std::endl << node_to_elem << std::endl;
 
   Vector<UInt> counter;
   /// count number of occurrence of each node
   for (UInt t = 0,linearized_el = 0; t < nb_good_types; ++t) {
     for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) {
 
       UInt el_offset = el*nb_nodes_per_element[t];
       for (UInt f = 0; f < nb_facets[t]; ++f) {
 	//build the nodes involved in facet 'f'
 	UInt facet_nodes[nb_nodes_per_facet[t]];
 	for (UInt n = 0; n < nb_nodes_per_facet[t]; ++n) {
 	  UInt node_facet = node_in_facet[t][f][n];
 	  facet_nodes[n] = conn_val[t][el_offset + node_facet];
 	}
 	//our reference is the first node
 	CSR<UInt>::iterator first_node_elements;
 	//UInt * first_node_elements = node_to_elem.values+node_offset.values[facet_nodes[0]];
 	UInt first_node_nelements = node_to_elem.getNbCols(facet_nodes[0]);
 	  // node_offset.values[facet_nodes[0]+1]-
 	  // node_offset.values[facet_nodes[0]];
 	counter.resize(first_node_nelements);
 	counter.clear();
 	//loop over the other nodes to search intersecting elements,
 	//which are the elements that share another node with the
 	//starting element after first_node
 	CSR<UInt>::iterator first_node_elements_end;
 	first_node_elements_end = node_to_elem.end(facet_nodes[0]);
 	for (UInt n = 1; n < nb_nodes_per_facet[t]; ++n) {
 	  CSR<UInt>::iterator node_elements, node_elements_begin, node_elements_end;
 	  node_elements_begin = node_to_elem.begin(facet_nodes[n]);
 	  node_elements_end = node_to_elem.end(facet_nodes[n]);
 	  //	  UInt * node_elements = node_to_elem.values+node_offset.values[facet_nodes[n]];
 	    // node_offset.values[facet_nodes[n]+1]-
 	    // node_offset.values[facet_nodes[n]];
 	  UInt local_el = 0;
 	  for (first_node_elements = node_to_elem.begin(facet_nodes[0]);
 	       first_node_elements != first_node_elements_end;
 	       ++first_node_elements, ++local_el) {
 	    for (node_elements = node_elements_begin;
 		 node_elements != node_elements_end;
 		 ++node_elements) {
 	      if (*first_node_elements == *node_elements) {
 		++counter.values[local_el];
 		// it may cause trouble:
 		break;
 	      }
 	    }
 	    //	    if (counter.values[local_el] == nb_nodes_per_facet[t]) break;
 	  }
 	}
 	// bool connected_facet = false;
 
 	//the connected elements are those for which counter is n_facet
 	//	UInt connected_element = -1;
 
 	// counting the number of elements connected to the facets and
 	// taking the minimum element number, because the facet should
 	// be inserted just once
 	UInt nb_element_connected_to_facet = 0;
 	UInt minimum_el_index = std::numeric_limits<UInt>::max();
 	Vector<UInt> connected_elements;
 	for (UInt el1 = 0; el1 < counter.getSize(); el1++) {
 	  UInt el_index = node_to_elem(facet_nodes[0], el1);
 
 	  if (counter.values[el1] == nb_nodes_per_facet[t]-1) {
 	    ++nb_element_connected_to_facet;
 	    minimum_el_index = std::min(minimum_el_index, el_index);
 	    connected_elements.push_back(el_index);
 	  }
 	}
 
 	if (minimum_el_index == linearized_el) {
 	  if (!boundary_only || (boundary_only && nb_element_connected_to_facet == 1)) {
 	    connectivity_facets[t]->push_back(facet_nodes);
 
 	    UInt current_nb_facets = element_to_subelement[t]->getSize();
 	    element_to_subelement[t]->resize(current_nb_facets + 1);
 	    Vector<Element> & elements = (*element_to_subelement[t])(current_nb_facets);
 
 	    // build elements_on_facets: linearized_el must come first
 	    // in order to store the facet in the correct direction
 	    // and avoid to invert the sign in the normal computation
 	    elements.push_back(mesh.linearizedToElement(linearized_el));
 
 	    /// boundary facet
 	    if (nb_element_connected_to_facet == 1)
 	      elements.push_back(ElementNull);
 	    /// internal facet
 	    else if (nb_element_connected_to_facet == 2)
 	      elements.push_back(mesh.linearizedToElement(connected_elements.values[1]));
 	    /// facet of facet
 	    else {
 	      UInt nb_connected = connected_elements.getSize();
 	      for (UInt i = 1; i < nb_connected; ++i) {
 		elements.push_back(mesh.linearizedToElement(connected_elements.values[i]));
 	      }
 
 	      /// check if sorting is needed:
 	      /// - in 3D to sort triangles around segments
 	      /// - in 2D to sort segments around points
 	      if (dimension == spatial_dimension - 1) {
 
 		/// barycentrical coordinates for each connected
 		/// element with respect to start_node
 		Vector<Real> connected_nodes(nb_connected, 2);
 
 		const Vector<Real> & coord = mesh_facets.getNodes();
 		const Vector<UInt> & facet_conn = mesh_facets.getConnectivity(facet_type);
 
 		/// node around which the sorting is carried out is
 		/// the first node of the current facet
 		UInt start_node = facet_conn(facet_conn.getSize()-1, 0);
 		Real start_coord[spatial_dimension];
 		for (UInt dim = 0; dim < spatial_dimension; ++dim) {
 		  start_coord[dim] = coord(start_node, dim);
 		}
 
 		if (spatial_dimension == 3) {
 		  /// vector connecting facet first node to second
 		  Real tangent[spatial_dimension];
 		  /// vector connecting facet first node and
 		  /// barycenter of elements(0)
 		  Real temp[spatial_dimension];
 		  /// two normals to the segment facet to define the
 		  /// reference system
 		  Real normal1[spatial_dimension];
 		  Real normal2[spatial_dimension];
 
 		  Vector<Real> & bar = barycenter(elements(0).type);
 
 		  /// facet second node
 		  UInt second_node = facet_conn(facet_conn.getSize()-1, 1);
 
 		  /// construction of tangent and temp arrays
 		  for (UInt dim = 0; dim < spatial_dimension; ++dim) {
 		    Real x1, x2;
 		    x1 = coord(second_node, dim);
 		    x2 = bar(elements(0).element, dim);
 		    tangent[dim] = x1 - start_coord[dim];
 		    temp[dim] = x2 - start_coord[dim];
 		  }
 
 		  /// get normal1 and normal2
 		  Math::normalize3(tangent);
 		  Math::vectorProduct3(tangent, temp, normal1);
 		  Math::normalize3(normal1);
 		  Math::vectorProduct3(tangent, normal1, normal2);
 
 		  for (UInt n = 0; n < nb_connected; ++n) {
 		    Real bary_coord[spatial_dimension];
 		    Vector<Real> & bary = barycenter(elements(n).type);
 
 		    /// get the barycenter local coordinates
 		    for (UInt dim = 0; dim < spatial_dimension; ++dim) {
 		      bary_coord[dim] = bary(elements(n).element, dim)
 			- start_coord[dim];
 		    }
 		    /// project the barycenter coordinates on the two
 		    /// normals to have them on the same plane
 		    connected_nodes(n, 0) = Math::vectorDot(bary_coord, normal1, spatial_dimension);
 		    connected_nodes(n, 1) = Math::vectorDot(bary_coord, normal2, spatial_dimension);
 		  }
 		}
 		else if (spatial_dimension == 2) {
 		  for (UInt n = 0; n < nb_connected; ++n) {
 		    Vector<Real> & bary = barycenter(elements(n).type);
 		    /// get the barycenter local coordinates
 		    for (UInt dim = 0; dim < spatial_dimension; ++dim) {
 		      connected_nodes(n, dim) = bary(elements(n).element, dim)
 			- start_coord[dim];
 		    }
 		  }
 		}
 
 		/// associate to each element a real value based on
 		/// atan2 function (check wikipedia)
 		std::map<Element, Real, CompElementLess> atan2;
 
 		for (UInt n = 0; n < nb_connected; ++n) {
 		  Real x = connected_nodes(n, 0);
 		  Real y = connected_nodes(n, 1);
 		  /// in order to avoid division by zero:
 		  if (std::abs(y) <= std::abs(y) * epsilon && x < 0)
 		    y = Math::getTolerance();
 		  atan2[elements(n)] = y / (sqrt(x * x + y * y) + x);
 		}
 
 		/// sort elements according to their atan2 values
 		ElementSorter sorter(atan2);
 		std::sort(elements.storage(), elements.storage() + elements.getSize(), sorter);
 
 	      }
 	    }
 
 	    /// current facet index
 	    UInt current_facet = connectivity_facets[t]->getSize() - 1;
 
 	    /// loop on every element connected to current facet and
 	    /// insert current facet in the first free spot of the
 	    /// subelement_to_element vector
 	    for (UInt elem = 0; elem < elements.getSize(); ++elem) {
 	      if (elements(elem).type != _not_defined) {
 		for (UInt f_in = 0; f_in < nb_facets[t]; ++f_in) {
 		  if ((*subelement_to_element[t])(elements(elem).element, f_in).type == _not_defined) {
 		    (*subelement_to_element[t])(elements(elem).element, f_in).type = facet_type;
 		    (*subelement_to_element[t])(elements(elem).element, f_in).element = current_facet;
 		    break;
 		  }
 		}
 	      }
 	    }
 
 	  }
 	}
 
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 
 }
 
 /* -------------------------------------------------------------------------- */
 // void MeshUtils::buildNormals(Mesh & mesh,UInt spatial_dimension){
 //   AKANTU_DEBUG_IN();
 //   const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList();
 //   Mesh::ConnectivityTypeList::const_iterator it;
 
 //   UInt nb_types = type_list.size();
 //   UInt nb_nodes_per_element[nb_types];
 //   UInt nb_nodes_per_element_p1[nb_types];
 
 //   UInt nb_good_types = 0;
 
 //   Vector<UInt> * connectivity[nb_types];
 //   Vector<Real> * normals[nb_types];
 
 //   if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension();
 
 //   for(it = type_list.begin(); it != type_list.end(); ++it) {
 //     ElementType type = *it;
 //     ElementType type_p1 = mesh.getP1ElementType(type);
 //     if(mesh.getSpatialDimension(type) != spatial_dimension) continue;
 
 //     nb_nodes_per_element[nb_good_types]    = mesh.getNbNodesPerElement(type);
 //     nb_nodes_per_element_p1[nb_good_types] = mesh.getNbNodesPerElement(type_p1);
 
 //     // getting connectivity
 //     connectivity[nb_good_types] = mesh.getConnectivityPointer(type);
 //     if (!connectivity[nb_good_types])
 //       AKANTU_DEBUG_ERROR("connectivity is not allocatted : this should probably not have happened");
 
 //     //getting array of normals
 //     normals[nb_good_types] = mesh.getNormalsPointer(type);
 //     if(normals[nb_good_types])
 //       normals[nb_good_types]->resize(0);
 //     else
 //       normals[nb_good_types] = &mesh.createNormals(type);
 
 //     nb_good_types++;
 //   }
 //   AKANTU_DEBUG_OUT();
 // }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::renumberMeshNodes(Mesh & mesh,
 				  UInt * local_connectivities,
 				  UInt nb_local_element,
 				  UInt nb_ghost_element,
 				  ElementType type,
 				  Vector<UInt> & nodes_numbers) {
   AKANTU_DEBUG_IN();
 
   nodes_numbers.resize(0);
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
 
   std::map<UInt, UInt> renumbering_map;
 
   /// renumber the nodes
   renumberNodesInConnectivity(local_connectivities,
 			      (nb_local_element + nb_ghost_element)*nb_nodes_per_element,
 			      renumbering_map,
 			      nodes_numbers);
 
   renumbering_map.clear();
 
   /// copy the renumbered connectivity to the right place
   Vector<UInt> * local_conn = mesh.getConnectivityPointer(type);
   local_conn->resize(nb_local_element);
   memcpy(local_conn->values,
 	 local_connectivities,
 	 nb_local_element * nb_nodes_per_element * sizeof(UInt));
 
   Vector<UInt> * ghost_conn = mesh.getConnectivityPointer(type,_ghost);
   ghost_conn->resize(nb_ghost_element);
   memcpy(ghost_conn->values,
 	 local_connectivities + nb_local_element * nb_nodes_per_element,
 	 nb_ghost_element * nb_nodes_per_element * sizeof(UInt));
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::renumberNodesInConnectivity(UInt * list_nodes,
 					    UInt nb_nodes,
 					    std::map<UInt, UInt> & renumbering_map,
 					    Vector<UInt> & nodes_numbers) {
   AKANTU_DEBUG_IN();
 
   UInt * connectivity = list_nodes;
   for (UInt n = 0; n < nb_nodes; ++n, ++connectivity) {
     UInt & node = *connectivity;
     std::map<UInt, UInt>::iterator it = renumbering_map.find(node);
     if(it == renumbering_map.end()) {
       UInt old_node = node;
       nodes_numbers.push_back(old_node);
       node = nodes_numbers.getSize() - 1;
       renumbering_map[old_node] = node;
     } else {
       node = it->second;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::purifyMesh(Mesh & mesh) {
   AKANTU_DEBUG_IN();
-  
+
   std::map<UInt, UInt> renumbering_map;
   Vector<UInt> node_numbers;
 
   for (UInt gt = _not_ghost; gt <= _ghost; ++gt) {
     GhostType ghost_type = (GhostType) gt;
 
     Mesh::type_iterator it  = mesh.firstType(0, ghost_type, _ek_not_defined);
     Mesh::type_iterator end = mesh.lastType(0, ghost_type, _ek_not_defined);
     for(; it != end; ++it) {
 
       ElementType type(*it);
       UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
 
       const Vector<UInt> & connectivity_vect = mesh.getConnectivity(type, ghost_type);
       UInt nb_element(connectivity_vect.getSize());
       UInt * connectivity = connectivity_vect.storage();
 
       renumberNodesInConnectivity (connectivity, nb_element*nb_nodes_per_element, renumbering_map, node_numbers);
     }
   }
 
-  UInt spatial_dimension = mesh.getSpatialDimension();
 
-  Vector<Real> & nodes = const_cast<Vector<Real> &>(mesh.getNodes());
-  Vector<Real>::iterator<types::RVector> nodes_it = nodes.begin(spatial_dimension);
-  Vector<Real> new_nodes(0, spatial_dimension);
+
+  RemovedNodesEvent remove_nodes(mesh);
+  Vector<UInt> & nodes_removed = remove_nodes.getList();
+  Vector<UInt> & new_numbering = remove_nodes.getNewNumbering();
+
+  std::fill(new_numbering.begin(), new_numbering.end(), UInt(-1));
 
   for (UInt i = 0; i < node_numbers.getSize(); ++i) {
-    new_nodes.push_back(nodes_it + node_numbers(i));
+    new_numbering(node_numbers(i)) = i;
+  }
+
+  for (UInt i = 0; i < new_numbering.getSize(); ++i) {
+    if(new_numbering(i) == UInt(-1))
+      nodes_removed.push_back(i);
   }
 
-  std::copy(new_nodes.begin(spatial_dimension), new_nodes.end(spatial_dimension),
-	    nodes.begin(spatial_dimension));
-  
-  nodes.resize(node_numbers.getSize());
+  mesh.sendEvent(remove_nodes);
+
+  // UInt spatial_dimension = mesh.getSpatialDimension();
+  // Vector<Real> & nodes = const_cast<Vector<Real> &>(mesh.getNodes());
+  // Vector<Real>::iterator<types::RVector> nodes_it = nodes.begin(spatial_dimension);
+  // Vector<Real> new_nodes(0, spatial_dimension);
+
+  //  for (UInt i = 0; i < node_numbers.getSize(); ++i) {
+  //     new_nodes.push_back(nodes_it + node_numbers(i));
+  //  }
+
+  // std::copy(new_nodes.begin(spatial_dimension), new_nodes.end(spatial_dimension),
+  // 	    nodes.begin(spatial_dimension));
+
+  // nodes.resize(node_numbers.getSize());
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::setUIntData(Mesh & mesh, UInt * data, UInt nb_tags, const ElementType & type) {
   AKANTU_DEBUG_IN();
 
   UInt nb_element = mesh.getNbElement(type, _not_ghost);
   UInt nb_ghost_element = mesh.getNbElement(type, _ghost);
 
   char * names = reinterpret_cast<char *>(data + (nb_element + nb_ghost_element) * nb_tags);
   UIntDataMap & uint_data_map = mesh.getUIntDataMap(type, _not_ghost);
   UIntDataMap & ghost_uint_data_map = mesh.getUIntDataMap(type, _ghost);
 
   for (UInt t = 0; t < nb_tags; ++t) {
     std::string name(names);
     //    std::cout << name << std::endl;
     names += name.size() + 1;
 
     UIntDataMap::iterator it = uint_data_map.find(name);
     if(it == uint_data_map.end()) {
       uint_data_map[name] = new Vector<UInt>(0, 1, name);
       it = uint_data_map.find(name);
     }
     it->second->resize(nb_element);
     memcpy(it->second->values, data, nb_element * sizeof(UInt));
     data += nb_element;
 
     it = ghost_uint_data_map.find(name);
     if(it == ghost_uint_data_map.end()) {
       ghost_uint_data_map[name] = new Vector<UInt>(0, 1, name);
       it = ghost_uint_data_map.find(name);
     }
     it->second->resize(nb_ghost_element);
     memcpy(it->second->values, data, nb_ghost_element * sizeof(UInt));
     data += nb_ghost_element;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildSurfaceID(Mesh & mesh) {
   AKANTU_DEBUG_IN();
 
   // Vector<UInt> node_offset;
   // Vector<UInt> node_to_elem;
 
   CSR<UInt> node_to_elem;
 
   /// Get list of surface elements
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   //  buildNode2Elements(mesh, node_offset, node_to_elem, spatial_dimension-1);
   buildNode2Elements(mesh, node_to_elem, spatial_dimension-1);
 
   /// Find which types of elements have been linearized
   const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList();
   Mesh::ConnectivityTypeList::const_iterator it;
 
   UInt nb_types = type_list.size();
   ElementType lin_element_type[nb_types];
   UInt nb_lin_types = 0;
 
   UInt nb_nodes_per_element[nb_types];
   UInt nb_nodes_per_element_p1[nb_types];
 
   UInt * conn_val[nb_types];
   UInt nb_element[nb_types+1];
 
   ElementType type_p1;
 
   for(it = type_list.begin(); it != type_list.end(); ++it) {
     ElementType type = *it;
     if(Mesh::getSpatialDimension(type) != spatial_dimension) continue;
 
     ElementType facet_type = mesh.getFacetElementType(type);
     lin_element_type[nb_lin_types] = facet_type;
     nb_nodes_per_element[nb_lin_types]    = Mesh::getNbNodesPerElement(facet_type);
     type_p1 = Mesh::getP1ElementType(facet_type);
     nb_nodes_per_element_p1[nb_lin_types] = Mesh::getNbNodesPerElement(type_p1);
 
     conn_val[nb_lin_types] = mesh.getConnectivity(facet_type, _not_ghost).values;
     nb_element[nb_lin_types] = mesh.getNbElement(facet_type, _not_ghost);
     nb_lin_types++;
   }
 
   for (UInt i = 1; i < nb_lin_types; ++i) nb_element[i] += nb_element[i+1];
   for (UInt i = nb_lin_types; i > 0; --i) nb_element[i] = nb_element[i-1];
   nb_element[0] = 0;
 
   /// Find close surfaces
   Vector<Int> surface_value_id(1, nb_element[nb_lin_types], -1);
   Int * surf_val = surface_value_id.values;
   UInt nb_surfaces = 0;
 
   UInt nb_cecked_elements;
   UInt nb_elements_to_ceck;
   UInt * elements_to_ceck = new UInt [nb_element[nb_lin_types]];
   memset(elements_to_ceck, 0, nb_element[nb_lin_types]*sizeof(UInt));
 
   for (UInt lin_el = 0; lin_el < nb_element[nb_lin_types]; ++lin_el) {
 
     if(surf_val[lin_el] != -1) continue; /* Surface id already assigned */
 
     /* First element of new surface */
     surf_val[lin_el] = nb_surfaces;
     nb_cecked_elements = 0;
     nb_elements_to_ceck = 1;
     memset(elements_to_ceck, 0, nb_element[nb_lin_types]*sizeof(UInt));
     elements_to_ceck[0] = lin_el;
 
     // Find others elements belonging to this surface
     while(nb_cecked_elements < nb_elements_to_ceck) {
 
       UInt ceck_lin_el = elements_to_ceck[nb_cecked_elements];
 
       // Transform linearized index of element into ElementType one
       UInt lin_type_nb = 0;
       while (ceck_lin_el >= nb_element[lin_type_nb+1])
 	lin_type_nb++;
       UInt ceck_el = ceck_lin_el - nb_element[lin_type_nb];
 
       // Get connected elements
       UInt el_offset = ceck_el*nb_nodes_per_element[lin_type_nb];
       for (UInt n = 0; n < nb_nodes_per_element_p1[lin_type_nb]; ++n) {
 	UInt node_id = conn_val[lin_type_nb][el_offset + n];
 	CSR<UInt>::iterator it_n;
 	for (it_n = node_to_elem.begin(node_id); it_n != node_to_elem.end(node_id); ++it_n) {
 	  //	for (UInt i = node_offset.values[node_id]; i < node_offset.values[node_id+1]; ++i) {
 	  if(surf_val[*it_n] == -1) { /* Found new surface element */
 	    surf_val[*it_n] = nb_surfaces;
 	    elements_to_ceck[nb_elements_to_ceck] = *it_n;
 	    nb_elements_to_ceck++;
 	  }
 	  // if(surf_val[node_to_elem.values[i]] == -1) { /* Found new surface element */
 	  //   surf_val[node_to_elem.values[i]] = nb_surfaces;
 	  //   elements_to_ceck[nb_elements_to_ceck] = node_to_elem.values[i];
 	  //   nb_elements_to_ceck++;
 	  // }
 	}
       }
 
       nb_cecked_elements++;
     }
 
     nb_surfaces++;
   }
 
   delete [] elements_to_ceck;
 
   /// Transform local linearized element index in the global one
   for (UInt i = 0; i < nb_lin_types; ++i) nb_element[i] = nb_element[i+1] - nb_element[i];
   UInt el_offset = 0;
 
   for (UInt type_it = 0; type_it < nb_lin_types; ++type_it) {
     ElementType type = lin_element_type[type_it];
     Vector<UInt> * surf_id_type = mesh.getSurfaceIDPointer(type, _not_ghost);
     surf_id_type->resize(nb_element[type_it]);
     surf_id_type->clear();
     for (UInt el = 0; el < nb_element[type_it]; ++el)
       surf_id_type->values[el] = surf_val[el+el_offset];
     el_offset += nb_element[type_it];
   }
 
   /// Set nb_surfaces in mesh
   mesh.nb_surfaces = nb_surfaces;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildNodesPerSurface(const Mesh & mesh, CSR<UInt> & nodes_per_surface) {
   AKANTU_DEBUG_IN();
 
   UInt nb_surfaces = mesh.getNbSurfaces();
   UInt nb_nodes    = mesh.getNbNodes();
   UInt spatial_dimension = mesh.getSpatialDimension(); //surface elements
 
   UInt  nb_facet_types = 0;
   ElementType facet_type[_max_element_type];
 
   Mesh::type_iterator it  = mesh.firstType(spatial_dimension);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension);
   for(; it != end; ++it) {
     facet_type[nb_facet_types++] = mesh.getFacetElementType(*it);
   }
 
   UInt * surface_nodes_id = new UInt[nb_nodes*nb_surfaces];
   std::fill_n(surface_nodes_id, nb_surfaces*nb_nodes, 0);
 
   for(UInt t = 0; t < nb_facet_types; ++t) {
     ElementType type = facet_type[t];
 
     UInt nb_element = mesh.getNbElement(type);
     UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
 
     UInt * connecticity = mesh.getConnectivity(type, _not_ghost).values;
     UInt * surface_id = mesh.getSurfaceID(type, _not_ghost).values;;
 
     for (UInt el = 0; el < nb_element; ++el) {
       UInt offset = *surface_id * nb_nodes;
       for (UInt n = 0; n < nb_nodes_per_element; ++n) {
 	surface_nodes_id[offset + *connecticity] = 1;
 	++connecticity;
       }
       ++surface_id;
     }
   }
 
   nodes_per_surface.resizeRows(nb_surfaces);
   nodes_per_surface.clearRows();
 
   UInt * surface_nodes_id_tmp = surface_nodes_id;
   for (UInt s = 0; s < nb_surfaces; ++s)
     for (UInt n = 0; n < nb_nodes; ++n)
       nodes_per_surface.rowOffset(s) += *surface_nodes_id_tmp++;
 
   nodes_per_surface.countToCSR();
 
   nodes_per_surface.resizeCols();
   nodes_per_surface.beginInsertions();
   surface_nodes_id_tmp = surface_nodes_id;
   for (UInt s = 0; s < nb_surfaces; ++s)
     for (UInt n = 0; n < nb_nodes; ++n) {
       if (*surface_nodes_id_tmp == 1) nodes_per_surface.insertInRow(s, n);
       surface_nodes_id_tmp++;
     }
   nodes_per_surface.endInsertions();
 
   delete [] surface_nodes_id;
 
   AKANTU_DEBUG_OUT();
 }
 
 
 
 __END_AKANTU__
 
 //  LocalWords:  ElementType
diff --git a/src/model/solid_mechanics/contact/contact_rigid.cc b/src/model/solid_mechanics/contact/contact_rigid.cc
index 86947f32c..55239c4f4 100644
--- a/src/model/solid_mechanics/contact/contact_rigid.cc
+++ b/src/model/solid_mechanics/contact/contact_rigid.cc
@@ -1,1221 +1,1221 @@
 /**
  * @file   contact_rigid.cc
  * @author David Kammer <david.kammer@epfl.ch>
  * @date   Tue Oct 26 17:15:08 2010
  *
  * @brief Specialization  of the  contact structure for  3d contact  in explicit
  * time scheme
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "contact_rigid.hh"
 #include "contact_search.hh"
 /* -------------------------------------------------------------------------- */
 #include <iostream>
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 ContactRigid::ImpactorInformationPerMaster::ImpactorInformationPerMaster(const Surface master_id, const UInt spatial_dimension) : master_id(master_id) {
   AKANTU_DEBUG_IN();
 
   this->impactor_surfaces = new std::vector<Surface>(0);
 
   this->active_impactor_nodes = new Vector<UInt>(0,1);
   //this->master_element_offset = new Vector<UInt>(0,1);
   this->master_element_type = new std::vector<ElementType>(0);
   this->master_normals = new Vector<Real>(0, spatial_dimension);
   this->node_is_sticking = new Vector<bool>(0,2);
   this->friction_forces = new Vector<Real>(0,spatial_dimension);
   this->stick_positions = new Vector<Real>(0,spatial_dimension);
   this->residual_forces = new Vector<Real>(0,spatial_dimension);
   this->previous_velocities = new Vector<Real>(0,spatial_dimension);
   this->friction_resistances = new Vector<Real>(0);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 ContactRigid::ImpactorInformationPerMaster::~ImpactorInformationPerMaster() {
   AKANTU_DEBUG_IN();
 
   delete this->impactor_surfaces;
 
   delete this->active_impactor_nodes;
   //  delete this->master_element_offset;
   delete this->master_element_type;
   delete this->master_normals;
   delete this->node_is_sticking;
   delete this->friction_forces;
   delete this->stick_positions;
   delete this->residual_forces;
   delete this->previous_velocities;
   delete this->friction_resistances;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 ContactRigid::ContactRigid(const SolidMechanicsModel & model,
 			   const ContactType & type,
 			   const ContactID & id,
 			   const MemoryID & memory_id) :
   Contact(model, type, id, memory_id), spatial_dimension(model.getSpatialDimension()), mesh(model.getFEM().getMesh()), prakash(false), ref_velocity(0.), characterstic_length(0.) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 ContactRigid::~ContactRigid() {
   AKANTU_DEBUG_IN();
 
   ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
   for (it_imp = this->impactors_information.begin();
        it_imp != this->impactors_information.end();
        ++it_imp) {
     delete it_imp->second;
   }
 
   this->impactors_information.clear();
   this->friction_coefficient.clear();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::addMasterSurface(const Surface & master_surface) {
   AKANTU_DEBUG_IN();
 
   Contact::addMasterSurface(master_surface);
 
   ImpactorInformationPerMaster * impactor_info = new ImpactorInformationPerMaster(master_surface, this->spatial_dimension);
   this->impactors_information[master_surface] = impactor_info;
 
   //this->friction_coefficient[master_surface] = NULL;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::addImpactorSurfaceToMasterSurface(const Surface & impactor_surface, const Surface & master_surface) {
   AKANTU_DEBUG_IN();
 
   ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
   it_imp = this->impactors_information.find(master_surface);
   AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 		      "The master surface: " << master_surface << "couldn't be found and erased in impactors_information map");
   it_imp->second->impactor_surfaces->push_back(impactor_surface);
 
   /*
   for (UInt m=0; m < this->impactors_information.size(); ++m) {
     if (this->impactors_information.at(m)->master_id == master_surface) {
       this->impactors_information.at(m)->impactor_surfaces->push_back(impactor_surface);
       break;
     }
   }
   */
 
   ContactRigid::SurfaceToFricCoefMap::iterator it_fc;
   it_fc = this->friction_coefficient.find(master_surface);
   if (it_fc != this->friction_coefficient.end())
     it_fc->second->addImpactorSurface(impactor_surface);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::removeMasterSurface(const Surface & master_surface) {
   AKANTU_DEBUG_IN();
 
   Contact::removeMasterSurface(master_surface);
 
   ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
   it_imp = this->impactors_information.find(master_surface);
   AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 		      "The master surface: " << master_surface << "couldn't be found and erased in impactors_information map");
   delete it_imp->second;
   this->impactors_information.erase(it_imp);
 
   ContactRigid::SurfaceToFricCoefMap::iterator it_fc;
   it_fc = this->friction_coefficient.find(master_surface);
   AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(),
 		      "The master surface: " << master_surface << "couldn't be found and erased in friction_coefficient map");
   this->friction_coefficient.erase(it_fc);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::removeImpactorSurfaceFromMasterSurface(const Surface & impactor_surface, const Surface & master_surface) {
   AKANTU_DEBUG_IN();
 
   // find in map the impactor information for the given master surface
   ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
   it_imp = this->impactors_information.find(master_surface);
   AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 		      "The master surface: " << master_surface << "couldn't be found and erased in impactors_information map");
   std::vector<Surface> * imp_surfaces = it_imp->second->impactor_surfaces;
 
   // find and delete the impactor surface
   std::vector<Surface>::iterator it_surf;
   it_surf = find(imp_surfaces->begin(), imp_surfaces->end(), impactor_surface);
   AKANTU_DEBUG_ASSERT(it_surf != imp_surfaces->end(), "Couldn't find impactor surface " << impactor_surface << " for the master surface " << master_surface << " and couldn't erase it");
   imp_surfaces->erase(it_surf);
 
   /*
   for (UInt m=0; m < this->impactors_information.size(); ++m) {
     ImpactorInformationPerMaster * impactor_info = this->impactors_information.at(m);
     if (impactor_info->master_id == master_surface) {
       for (UInt i=0; i < impactor_info->impactor_surfaces->size(); ++i) {
 	Surface imp_surface = impactor_info->impactor_surfaces->at(i);
 	if (imp_surface == impactor_surface) {
 	  impactor_info->impactor_surfaces->erase(impactor_info->impactor_surfaces->begin()+i);
 	  break;
 	}
       }
     }
   }
   */
 
   ContactRigid::SurfaceToFricCoefMap::iterator it_fc;
   it_fc = this->friction_coefficient.find(master_surface);
   if (it_fc != this->friction_coefficient.end())
     it_fc->second->removeImpactorSurface(impactor_surface);
 
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::solveContact() {
   AKANTU_DEBUG_IN();
 
   for(UInt m=0; m < master_surfaces.size(); ++m) {
     Surface master = this->master_surfaces.at(m);
 
     std::stringstream sstr; sstr << id << ":penetration_list";
     PenetrationList * penet_list = new PenetrationList(sstr.str());
     contact_search->findPenetration(master, *penet_list);
 
     solvePenetrationClosestProjection(master, *penet_list);
     delete penet_list;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /*void ContactRigid::solvePenetration(const PenetrationList & penet_list) {
   AKANTU_DEBUG_IN();
 
   const UInt dim = ;
 
   const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList();
   Mesh::ConnectivityTypeList::const_iterator it;
 
   /// find existing surface element types
   UInt nb_types = type_list.size();
   UInt nb_facet_types = 0;
   ElementType facet_type[_max_element_type];
 
   for(it = type_list.begin(); it != type_list.end(); ++it) {
     ElementType type = *it;
     if(mesh.getSpatialDimension(type) == spatial_dimension) {
       ElementType current_facet_type = mesh.getFacetElementType(type);
       facet_type[nb_facet_types++] = current_facet_type;
     }
   }
 
   Real * current_position = model.getCurrentPosition().values;
   Real * displacement     = model.getDisplacement().values;
   Real * increment        = model.getIncrement().values;
 
   UInt * penetrating_nodes = penet_list.penetrating_nodes.values;
 
   for (UInt n=0; n < penet_list.penetrating_nodes.getSize(); ++n) {
     UInt current_node = penetrating_nodes[n];
 
     // count number of elements penetrated by this node
     UInt nb_penetrated_facets = 0;
     ElementType penetrated_type;
     for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) {
       ElementType type = facet_type[el_type];
       UInt offset_min = penet_list.penetrated_facets_offset[type].get(n);
       UInt offset_max = penet_list.penetrated_facets_offset[type].get(n+1);
       nb_penetrated_facets += offset_max - offset_min;
       penetrated_type = type;
     }
 
     // easy case: node penetrated only one facet
     if(nb_penetrated_facets == 1) {
       Real * facets_normals      = penet_list.facets_normals[penetrated_type].values;
       Real * gaps                = penet_list.gaps[penetrated_type].values;
       Real * projected_positions = penet_list.projected_positions[penetrated_type].values;
 
       UInt offset_min = penet_list.penetrated_facets_offset[penetrated_type].get(n);
       for(UInt i=0; i < dim; ++i) {
 	current_position[current_node*dim + i] = projected_positions[offset_min*dim + i];
 	Real displacement_correction = gaps[offset_min*dim + i] * normals[offset_min*dim + i];
 	displacement[current_node*dim + i] = displacement[current_node*dim + i] - displacement_correction;
 	increment   [current_node*dim + i] = increment   [current_node*dim + i] - displacement_correction;
       }
     }
 
     // if more penetrated facets, find the one from which the impactor node is coming
     else {
 
     }
   }
   }*/
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::solvePenetrationClosestProjection(const Surface master,
 						     const PenetrationList & penet_list) {
   AKANTU_DEBUG_IN();
 
   const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList();
   Mesh::ConnectivityTypeList::const_iterator it;
 
   /// find existing surface element types
   UInt nb_facet_types = 0;
   ElementType facet_type[_max_element_type];
 
   for(it = type_list.begin(); it != type_list.end(); ++it) {
     ElementType type = *it;
     if(mesh.getSpatialDimension(type) == spatial_dimension) {
       ElementType current_facet_type = mesh.getFacetElementType(type);
       facet_type[nb_facet_types++] = current_facet_type;
     }
   }
 
   for (UInt n=0; n < penet_list.penetrating_nodes.getSize(); ++n) {
 
     // find facet for which the gap is the smallest
     Real min_gap = std::numeric_limits<Real>::max();
     ElementType penetrated_type;
     UInt penetrated_facet_offset;
     for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) {
       ElementType type = facet_type[el_type];
       Real * gaps = penet_list.gaps(type, _not_ghost).storage();
       UInt offset_min = penet_list.penetrated_facets_offset(type, _not_ghost)(n);
       UInt offset_max = penet_list.penetrated_facets_offset(type, _not_ghost)(n+1);
       for (UInt f = offset_min; f < offset_max; ++f) {
 	if(gaps[f] < min_gap) {
 	  min_gap = gaps[f];
 	  penetrated_type = type;
 	  penetrated_facet_offset = f;
 	}
       }
     }
 
     bool is_active = isAlreadyActiveImpactor(master, penet_list, n, penetrated_type, penetrated_facet_offset);
     if (!is_active) {
       // correct the position of the impactor
       projectImpactor(penet_list, n, penetrated_type, penetrated_facet_offset);
       lockImpactorNode(master, penet_list, n, penetrated_type, penetrated_facet_offset);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 bool ContactRigid::isAlreadyActiveImpactor(const Surface master,
 					   const PenetrationList & penet_list,
 					   const UInt impactor_index,
 					   const ElementType facet_type,
 					   const UInt facet_offset) {
   AKANTU_DEBUG_IN();
 
   bool is_active = false;
 
   UInt * penetrating_nodes = penet_list.penetrating_nodes.values;
   UInt impactor_node = penetrating_nodes[impactor_index];
 
   // find facet normal
   Real * facets_normals = penet_list.facets_normals(facet_type, _not_ghost).storage();
   Real * facet_normal = &facets_normals[facet_offset*spatial_dimension];
   Int normal[this->spatial_dimension];
   for(UInt i = 0; i < this->spatial_dimension; ++i)
     normal[i] = Int(floor(facet_normal[i] + 0.5));
 
   // check if this is already in the active impactor node list
   ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
   it_imp = this->impactors_information.find(master);
   AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 		      "The master surface: " << master << "couldn't be found in impactors_information map");
   ImpactorInformationPerMaster * impactor_info = it_imp->second;
   Vector<UInt> * active_nodes = impactor_info->active_impactor_nodes;
   Vector<Real> * master_normals = impactor_info->master_normals;
 
   for (UInt i=0; i<active_nodes->getSize(); ++i) {
-    if(active_nodes->at(i) == impactor_node) {
+    if((*active_nodes)(i) == impactor_node) {
       UInt count = 0;
       for (UInt d=0; d<this->spatial_dimension; ++d) {
-	if(Math::are_float_equal(master_normals->at(i,d),normal[d]))
+	if(Math::are_float_equal((*master_normals)(i,d),normal[d]))
 	  count++;
       }
       if(count == this->spatial_dimension)
 	is_active = true;
     }
   }
 
   AKANTU_DEBUG_OUT();
   return is_active;
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::projectImpactor(const PenetrationList & penet_list, const UInt impactor_index, const ElementType facet_type, const UInt facet_offset) {
 
   AKANTU_DEBUG_IN();
 
   const bool increment_flag = model.getIncrementFlag();
 
   UInt * penetrating_nodes   = penet_list.penetrating_nodes.values;
   Real * facets_normals      = penet_list.facets_normals(facet_type, _not_ghost).storage();
   Real * gaps                = penet_list.gaps(facet_type, _not_ghost).storage();
   Real * projected_positions = penet_list.projected_positions(facet_type, _not_ghost).storage();
 
   Real * current_position = model.getCurrentPosition().values;
   Real * displacement     = model.getDisplacement().values;
   Real * increment = NULL;
   if(increment_flag)
     increment = model.getIncrement().values;
 
   UInt impactor_node = penetrating_nodes[impactor_index];
 
   for(UInt i=0; i < this->spatial_dimension; ++i) {
     current_position[impactor_node*spatial_dimension + i] = projected_positions[facet_offset*spatial_dimension + i];
     Real displacement_correction = gaps[facet_offset] * facets_normals[facet_offset*spatial_dimension + i];
     displacement[impactor_node*spatial_dimension + i] = displacement[impactor_node*spatial_dimension + i] - displacement_correction;
     if(increment_flag)
       increment   [impactor_node*spatial_dimension + i] = increment   [impactor_node*spatial_dimension + i] - displacement_correction;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::lockImpactorNode(const Surface master, const PenetrationList & penet_list, const UInt impactor_index, const ElementType facet_type, const UInt facet_offset) {
   AKANTU_DEBUG_IN();
 
   bool init_state_stick = true; // node is in sticking when it gets in contact
 
   UInt * penetrating_nodes = penet_list.penetrating_nodes.values;
   UInt impactor_node = penetrating_nodes[impactor_index];
 
   Real * facets_normals = penet_list.facets_normals(facet_type, _not_ghost).storage();
   Real * facet_normal = &facets_normals[facet_offset*spatial_dimension];
   Real normal[this->spatial_dimension];
   //Int * normal_val = &normal[0];
 
   bool * bound_val    = this->model.getBoundary().values;
   Real * position_val = this->model.getCurrentPosition().values;
   Real * veloc_val    = this->model.getVelocity().values;
   Real * accel_val    = this->model.getAcceleration().values;
   Real * residual_val = this->model.getResidual().values;
 
   for(UInt i = 0; i < this->spatial_dimension; ++i)
     normal[i] = floor(facet_normal[i] + 0.5);
 
   for(UInt i = 0; i < this->spatial_dimension; ++i) {
     UInt index = impactor_node * spatial_dimension + i;
     if(!Math::are_float_equal(normal[i],0)) {
       bound_val[index] = true;
       veloc_val[index] = 0.;
       accel_val[index] = 0.;
     }
     // if node is in initial stick its tangential velocity has to be zero
     if(init_state_stick) {
       veloc_val[index] = 0.;
       accel_val[index] = 0.;
     }
   }
 
   ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
   it_imp = this->impactors_information.find(master);
   AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 		      "The master surface: " << master << "couldn't be found in impactors_information map");
   ImpactorInformationPerMaster * impactor_info = it_imp->second;
   impactor_info->active_impactor_nodes->push_back(impactor_node);
   //  impactor_info->master_element_offset->push_back(facet_offset);
   impactor_info->master_element_type->push_back(facet_type);
   impactor_info->master_normals->push_back(normal);
   // initial value for stick state when getting in contact
   bool init_sticking[2];
   if (init_state_stick) {
     init_sticking[0] = true;
     init_sticking[1] = true;
   }
   else {
     init_sticking[0] = false;
     init_sticking[1] = false;
   }
   impactor_info->node_is_sticking->push_back(init_sticking);
   Real init_friction_force[this->spatial_dimension];
   for(UInt i=0; i<this->spatial_dimension; ++i) {
     init_friction_force[i] = 0.;
   }
   impactor_info->friction_forces->push_back(init_friction_force);
   impactor_info->stick_positions->push_back(&(position_val[impactor_node*this->spatial_dimension]));
   impactor_info->residual_forces->push_back(&(residual_val[impactor_node*this->spatial_dimension]));
   impactor_info->previous_velocities->push_back(&(veloc_val[impactor_node*this->spatial_dimension]));
   impactor_info->friction_resistances->push_back(0.);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::avoidAdhesion() {
   AKANTU_DEBUG_IN();
 
   Real * residual_val = this->model.getResidual().values;
   bool * bound_val    = this->model.getBoundary().values;
 
   for(UInt m=0; m < this->master_surfaces.size(); ++m) {
     Surface master = this->master_surfaces.at(m);
 
     ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
     it_imp = this->impactors_information.find(master);
     AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 			"The master surface: " << master << "couldn't be found in impactors_information map");
     ImpactorInformationPerMaster * impactor_info = it_imp->second;
 
     for (UInt n=0; n < impactor_info->active_impactor_nodes->getSize(); ++n) {
-      UInt current_node = impactor_info->active_impactor_nodes->at(n);
+      UInt current_node = (*impactor_info->active_impactor_nodes)(n);
 
       for (UInt i=0; i < spatial_dimension; ++i) {
-	Int direction = Int(impactor_info->master_normals->at(n,i));
+	Int direction = Int((*impactor_info->master_normals)(n,i));
 	Real force = residual_val[current_node * spatial_dimension + i];
 	if(force * direction > 0.) {
 	  bound_val[current_node * spatial_dimension + i] = false;
 	  impactor_info->active_impactor_nodes->erase(n);
 	  //	  impactor_info->master_element_offset->erase(n);
 	  impactor_info->master_element_type->erase(impactor_info->master_element_type->begin()+n);
 	  impactor_info->master_normals->erase(n);
 	  impactor_info->node_is_sticking->erase(n);
 	  impactor_info->friction_forces->erase(n);
 	  impactor_info->stick_positions->erase(n);
 	  impactor_info->residual_forces->erase(n);
 	  impactor_info->previous_velocities->erase(n);
 	  impactor_info->friction_resistances->erase(n);
 	  n--;
 	  break;
 	}
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::frictionPredictor() {
   AKANTU_DEBUG_IN();
 
   const Real null_tolerance = std::numeric_limits<Real>::epsilon() * 2.;
 
   Real * residual_val     = this->model.getResidual().values;
   Real * acceleration_val = this->model.getAcceleration().values;
   Real * velocity_val     = this->model.getVelocity().values;
 
   for(UInt m=0; m < this->master_surfaces.size(); ++m) {
     Surface master = this->master_surfaces.at(m);
 
     ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
     it_imp = this->impactors_information.find(master);
     AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 			"The master surface: " << master << "couldn't be found in impactors_information map");
     ImpactorInformationPerMaster * impactor_info = it_imp->second;
 
     ContactRigid::SurfaceToFricCoefMap::iterator it_fc;
     it_fc = this->friction_coefficient.find(master);
     AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(),
 			"The master surface: " << master << "couldn't be found in friction_coefficient map");
     FrictionCoefficient * fric_coef = it_fc->second;
     AKANTU_DEBUG_ASSERT(fric_coef != NULL, "There is no friction coefficient defined for master surface " << master);
 
     UInt nb_active_impactor_nodes = impactor_info->active_impactor_nodes->getSize();
 
     // compute the friction coefficient for each active impactor node
     Vector<Real> friction_coefficient_values(nb_active_impactor_nodes, 1);
     Real * friction_coefficient_values_p = friction_coefficient_values.values;
     fric_coef->computeFrictionCoefficient(friction_coefficient_values);
 
     UInt * active_impactor_nodes_val = impactor_info->active_impactor_nodes->storage();
     Real * direction_val = impactor_info->master_normals->storage();
     bool * node_is_sticking_val = impactor_info->node_is_sticking->storage();
     Real * friction_forces_val = impactor_info->friction_forces->storage();
     Real * residual_forces_val = impactor_info->residual_forces->storage();
     Real * previous_velocities_val = impactor_info->previous_velocities->storage();
     Real * friction_resistances_val = impactor_info->friction_resistances->storage();
 
     Vector<Real> & nodal_velocity = model.getVelocity();
 
     for (UInt n=0; n < nb_active_impactor_nodes; ++n) {
       UInt current_node = active_impactor_nodes_val[n];
 
       // save original residual
       for(UInt i=0; i < spatial_dimension; ++i) {
 	residual_forces_val[n*spatial_dimension+i] = residual_val[current_node*spatial_dimension+i];
       }
 
       // find friction force mu * normal force
       Real normal_contact_force = 0.;
       Real friction_force = 0.;
       for (UInt i=0; i < spatial_dimension; ++i) {
 	if(!Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.)) {
 	  normal_contact_force = std::abs(residual_val[current_node * this->spatial_dimension + i]);
 	  friction_force = friction_coefficient_values_p[n] * normal_contact_force;
 	}
       }
       // prakash clifton regularization
       if (this->prakash) {
 	// compute (|v| + v*)/L
 	Real v_L_term = 0.;
 	for (UInt i=0; i < spatial_dimension; ++i) {
 	  if(Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.))
 	    v_L_term += nodal_velocity(current_node,i) * nodal_velocity(current_node,i);
 	}
 	v_L_term = sqrt(v_L_term);
 	v_L_term += this->ref_velocity;
 	v_L_term /= this->characterstic_length;
 
 	Real delta_t = this->model.getTimeStep();
 	
 	// compute friction resistance
 	friction_force *= v_L_term;
 	friction_force += friction_resistances_val[n]/delta_t;
 	friction_force /= (1/delta_t + v_L_term);
       }
       friction_resistances_val[n] = friction_force;
 
       // if node is sticking, friction force acts against the residual
       if (node_is_sticking_val[n*2]) {
 	// compute length of projected residual
 	Real projected_residual = 0.;
 	for (UInt i=0; i < this->spatial_dimension; ++i) {
 	  if(Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.)) {
 	    projected_residual += residual_val[current_node * this->spatial_dimension + i] *
 				  residual_val[current_node * this->spatial_dimension + i];
 	  }
 	}
 	projected_residual = sqrt(projected_residual);
 
 	// friction is weaker than residual -> start sliding
 	if (friction_force < projected_residual) {
 	  node_is_sticking_val[n*2]   = false;
 	  node_is_sticking_val[n*2+1] = false;
 
 	  // compute friction vector
 	  Real friction_direction[3];
 	  for (UInt i=0; i < this->spatial_dimension; ++i) {
 	    if(Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.)) {
 	      friction_direction[i] = residual_val[current_node * this->spatial_dimension + i];
 	      friction_direction[i] /= projected_residual;
 	    }
 	    else
 	      friction_direction[i] = 0.;
 	    friction_direction[i] *= -1.;
 	  }
 
 	  // add friction force to residual
 	  for (UInt i=0; i < this->spatial_dimension; ++i) {
 	    Real directional_fric_force = friction_force * friction_direction[i];
 	    friction_forces_val[n*this->spatial_dimension + i] = directional_fric_force;
 	    residual_val[current_node * this->spatial_dimension + i] += directional_fric_force;
 	  }
 	}
 
 	// friction is stronger than residual -> stay sticking
 	else {
 	  // put residual in friction force and set residual to zero
 	  for (UInt i=0; i < this->spatial_dimension; ++i) {
 	    if(Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.)) {
 	      friction_forces_val[n*spatial_dimension + i] = residual_val[current_node * this->spatial_dimension + i];
 	      residual_val[current_node * this->spatial_dimension + i] = 0.;
 	    }
 	    else
 	      friction_forces_val[n*spatial_dimension + i]  = 0.;
 	    friction_forces_val[n*spatial_dimension + i] *= -1.;
 	  }
 	}
       } // end if stick
 
 
       // if node is sliding friction force acts against velocity and
       // in case there is no velocity it acts against the residual
       else {
 	Real projected_residual = 0.;
 	Real projected_velocity_magnitude = 0.;
 	for (UInt i=0; i < this->spatial_dimension; ++i) {
 	  if(Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.)) {
 	    projected_residual += residual_val[current_node * this->spatial_dimension + i] *
 				  residual_val[current_node * this->spatial_dimension + i];
 	    projected_velocity_magnitude += previous_velocities_val[n * this->spatial_dimension + i] *
 					    previous_velocities_val[n * this->spatial_dimension + i];
 	  }
 	}
 	projected_residual = sqrt(projected_residual);
 	projected_velocity_magnitude = sqrt(projected_velocity_magnitude);
 
 	// if no projected velocity nor friction force stronger than projected residual, this is stick
 	if ((projected_velocity_magnitude < null_tolerance) && !(projected_residual > friction_force)) {
 	  // put residual in friction force and set residual to zero
 	  // set projected velocity and acceleration to zero
 	  for (UInt i=0; i < this->spatial_dimension; ++i) {
 	    if(Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.)) {
 	      friction_forces_val[n*spatial_dimension + i] = residual_val[current_node * this->spatial_dimension + i];
 	      residual_val    [current_node * this->spatial_dimension + i] = 0.;
 	      velocity_val    [current_node * this->spatial_dimension + i] = 0.;
 	      acceleration_val[current_node * this->spatial_dimension + i] = 0.;
 	    }
 	    else
 	      friction_forces_val[n*spatial_dimension + i] = 0.;
 	    friction_forces_val[n*spatial_dimension + i] *= -1.;
 	  }
 	  node_is_sticking_val[n*2]   = true;
 	  node_is_sticking_val[n*2+1] = true;
 	}
 
 	// node is really sliding
 	else {
 	  UInt index = 0;
 	  Real * direction_vector;
 	  Real direction_length;
 	  // if only velocity is zero (because slider just turned direction)
 	  if (projected_velocity_magnitude < null_tolerance) {
 	    index = current_node;
 	    direction_vector = residual_val;
 	    direction_length = projected_residual;
 	  }
 	  // there is velocity
 	  else {
 	    index = n;
 	    direction_vector = previous_velocities_val;
 	    direction_length = projected_velocity_magnitude;
 	  }
 
 	  // compute the friction direction
 	  Real friction_direction[3];
 	  for (UInt i=0; i < this->spatial_dimension; ++i) {
 	    if(Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.)) {
 	      friction_direction[i] = direction_vector[index * this->spatial_dimension + i];
 	      friction_direction[i] /= direction_length;
 	    }
 	    else
 	      friction_direction[i] = 0.;
 	    friction_direction[i] *= -1.;
 	  }
 
 	  // add friction force to residual
 	  for (UInt i=0; i < this->spatial_dimension; ++i) {
 	    Real directional_fric_force = friction_force * friction_direction[i];
 	    friction_forces_val[n*this->spatial_dimension + i] = directional_fric_force;
 	    residual_val[current_node * this->spatial_dimension + i] += directional_fric_force;
 	  }
 	}
       } // end sliding
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::frictionCorrector() {
   AKANTU_DEBUG_IN();
 
   const Real tolerance = std::numeric_limits<Real>::epsilon() * 100.;
 
   Real * residual_val     = this->model.getResidual().values;
   Real * acceleration_val = this->model.getAcceleration().values;
   Real * velocity_val     = this->model.getVelocity().values;
 
   Real time_step = this->model.getTimeStep();
 
   for(UInt m=0; m < this->master_surfaces.size(); ++m) {
     Surface master = this->master_surfaces.at(m);
 
     ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
     it_imp = this->impactors_information.find(master);
     AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 			"The master surface: " << master << "couldn't be found in impactors_information map");
     ImpactorInformationPerMaster * impactor_info = it_imp->second;
 
     UInt nb_active_impactor_nodes = impactor_info->active_impactor_nodes->getSize();
 
     UInt * active_impactor_nodes_val = impactor_info->active_impactor_nodes->storage();
     Real * direction_val = impactor_info->master_normals->storage();
     bool * node_is_sticking_val = impactor_info->node_is_sticking->storage();
     //Real * friction_forces_val = impactor_info->friction_forces->storage();
     //Real * residual_forces_val = impactor_info->residual_forces->storage();
     Real * previous_velocities_val = impactor_info->previous_velocities->storage();
 
     for (UInt n=0; n < nb_active_impactor_nodes; ++n) {
       UInt current_node = active_impactor_nodes_val[n];
 
       // check only sliding impactor nodes
       if (node_is_sticking_val[n*2])
 	continue;
 
       // compute scalar product of previous velocity with current velocity
       Real dot_prod_velocities = 0.;
       Real dot_prod_pred_velocities = 0.;
       Real current_proj_vel_mag = 0.;
       for (UInt i=0; i < this->spatial_dimension; ++i) {
 	if(Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.)) {
 	  dot_prod_velocities += velocity_val[current_node * this->spatial_dimension + i] *
 				 previous_velocities_val[n * this->spatial_dimension + i];
 	  Real pred_vel = velocity_val[current_node * this->spatial_dimension + i] + 
 	                  0.5 * time_step * 
                           acceleration_val[current_node * this->spatial_dimension + i];
 	  dot_prod_pred_velocities += pred_vel * 
 	                              previous_velocities_val[n * this->spatial_dimension + i];
 	  current_proj_vel_mag += velocity_val[current_node * this->spatial_dimension + i] *
 				  velocity_val[current_node * this->spatial_dimension + i];
 	  }
       }
       current_proj_vel_mag = sqrt(current_proj_vel_mag);
 
       // if velocity has changed sign or has become very small we get into stick
       if ((dot_prod_velocities < 0.) || 
 	  (dot_prod_pred_velocities < 0.) || 
 	  (current_proj_vel_mag < tolerance)) {
 	for (UInt i=0; i < this->spatial_dimension; ++i) {
 	  if(Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.)) {
 	    //friction_forces_val[n*spatial_dimension + i] = residual_forces_val[n*spatial_dimension + i];
 	    //residual_forces_val[n * this->spatial_dimension + i] =0.;
 	    residual_val    [current_node * this->spatial_dimension + i] = 0.;
 	    velocity_val    [current_node * this->spatial_dimension + i] = 0.;
 	    acceleration_val[current_node * this->spatial_dimension + i] = 0.;
 	  }
 	  //else
 	    //friction_forces_val[n*spatial_dimension + i] = 0.;
 	  //friction_forces_val[n*spatial_dimension + i] *= -1.;
 	}
 	node_is_sticking_val[n*2]   = true;
 	node_is_sticking_val[n*2+1] = true;
       }
     }
 
     // save current velocities
     for (UInt n=0; n < nb_active_impactor_nodes; ++n) {
       UInt current_node = active_impactor_nodes_val[n];
       for(UInt i=0; i < spatial_dimension; ++i) {
 	previous_velocities_val[n*spatial_dimension+i] = velocity_val[current_node*spatial_dimension+i];
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::addRegularizedFriction(const Real & regularizer) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(this->spatial_dimension == 2,
 			"addRegularizedFriction is implemented only for 2D");
 
   Real * residual_val = this->model.getResidual().values;
   Real * position_val = this->model.getCurrentPosition().values;
 
   for(UInt m=0; m < this->master_surfaces.size(); ++m) {
     Surface master = this->master_surfaces.at(m);
 
     // find the impactors information for this master surface
     ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
     it_imp = this->impactors_information.find(master);
     AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 			"The master surface: " << master << "couldn't be found in impactors_information map");
     ImpactorInformationPerMaster * impactor_info = it_imp->second;
 
     // find the friction coefficient object for this master
     ContactRigid::SurfaceToFricCoefMap::iterator it_fc;
     it_fc = this->friction_coefficient.find(master);
     AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(),
 			"The master surface: " << master << "couldn't be found in friction_coefficient map");
     FrictionCoefficient * fric_coef = it_fc->second;
     AKANTU_DEBUG_ASSERT(fric_coef != NULL, "There is no friction coefficient defined for master surface " << master);
 
     UInt nb_active_impactor_nodes = impactor_info->active_impactor_nodes->getSize();
 
     // compute the friction coefficient for each active impactor node
     Vector<Real> friction_coefficient_values(nb_active_impactor_nodes, 1);
     Real * friction_coefficient_values_p = friction_coefficient_values.values;
     fric_coef->computeFrictionCoefficient(friction_coefficient_values);
 
     UInt * active_impactor_nodes_val = impactor_info->active_impactor_nodes->storage();
     Real * direction_val = impactor_info->master_normals->storage();
     bool * node_is_sticking_val = impactor_info->node_is_sticking->storage();
     Real * friction_forces_val = impactor_info->friction_forces->storage();
     Real * stick_positions_val = impactor_info->stick_positions->storage();
 
     for (UInt n=0; n < nb_active_impactor_nodes; ++n) {
       UInt current_node = active_impactor_nodes_val[n];
       Real normal_contact_force = 0.;
       Real friction_force = 0.;
 
       // find friction force mu * normal force
       for (UInt i=0; i<spatial_dimension; ++i) {
 	if(!Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.)) {
 	  normal_contact_force = std::abs(residual_val[current_node * this->spatial_dimension + i]);
 	  friction_force = friction_coefficient_values_p[n] * normal_contact_force;
 	}
       }
 
       // compute F_(i+1)trial
       Real f_trial = Math::distance_2d(&(position_val[current_node * this->spatial_dimension]),
 				       &(stick_positions_val[n * this->spatial_dimension]));
       f_trial *= regularizer;
 
       Real delta_s_vector[this->spatial_dimension];
       for (UInt i=0; i<spatial_dimension; ++i) {
 	delta_s_vector[i] = position_val[current_node * this->spatial_dimension + i]
 			  - stick_positions_val[n * this->spatial_dimension + i];
 	delta_s_vector[i] *= -1.;
       }
 
       // if node is on its own stick position no need to compute friction force
       // this avoids nan on normalize2
       if(Math::norm2(delta_s_vector) < Math::getTolerance()) {
 	node_is_sticking_val[n*2] = true; node_is_sticking_val[n*2+1] = true;
 	continue;
       }
       Math::normalize2(delta_s_vector);
 
       // check if node is still sticking
       if (f_trial <= friction_force) {
 	friction_force = f_trial;
 	// sticking position stays unchanged
 	node_is_sticking_val[n*2] = true; node_is_sticking_val[n*2+1] = true;
       }
       else {
 	node_is_sticking_val[n*2] = false; node_is_sticking_val[n*2+1] = false;
 	Real delta_s = std::abs(f_trial - friction_force) / regularizer;
 	// friction force stays unchanged
 	for (UInt i=0; i<spatial_dimension; ++i) {
 	  stick_positions_val[n * this->spatial_dimension + i] -= delta_s * delta_s_vector[i];
 	}
       }
 
       // add friction force to residual
       for (UInt i=0; i < this->spatial_dimension; ++i) {
 	Real directional_fric_force = friction_force * delta_s_vector[i];
 	friction_forces_val[n*this->spatial_dimension + i] = directional_fric_force;
 	residual_val[current_node * this->spatial_dimension + i] += directional_fric_force;
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::setStickPositionsToCurrentPositions(const Surface master) {
   AKANTU_DEBUG_IN();
 
   Real * position_val = this->model.getCurrentPosition().values;
 
   // find the impactors information for this master surface
   ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
   it_imp = this->impactors_information.find(master);
   AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 		      "The master surface: " << master << "couldn't be found in impactors_information map");
   ImpactorInformationPerMaster * impactor_info = it_imp->second;
 
   UInt nb_active_impactor_nodes = impactor_info->active_impactor_nodes->getSize();
   UInt * active_impactor_nodes_val = impactor_info->active_impactor_nodes->storage();
   Real * stick_positions_val = impactor_info->stick_positions->storage();
 
   for (UInt n=0; n < nb_active_impactor_nodes; ++n) {
     UInt current_node = active_impactor_nodes_val[n];
 
     // find friction force mu * normal force
     for (UInt i=0; i<spatial_dimension; ++i) {
       stick_positions_val[n*this->spatial_dimension + i] = position_val[current_node*this->spatial_dimension + i];
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::setFrictionCoefficient(FrictionCoefficient * fric_coefficient) {
   AKANTU_DEBUG_IN();
 
   Surface master = fric_coefficient->getMasterSurface();
 
   ContactRigid::SurfaceToFricCoefMap::iterator it_fc;
   it_fc = this->friction_coefficient.find(master);
   AKANTU_DEBUG_ASSERT(it_fc == this->friction_coefficient.end(),
 		      "There is already a friction coefficient for master surface: " << master);
   this->friction_coefficient[master] = fric_coefficient;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::removeFrictionCoefficient(const Surface master) {
   AKANTU_DEBUG_IN();
 
   ContactRigid::SurfaceToFricCoefMap::iterator it_fc;
   it_fc = this->friction_coefficient.find(master);
   AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(),
 		      "There is no friction coefficient for master surface: " << master);
   this->friction_coefficient.erase(it_fc);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::getRestartInformation(std::map<std::string, VectorBase* > & map_to_fill,
 					 Surface master) {
   AKANTU_DEBUG_IN();
 
   ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
   it_imp = this->impactors_information.find(master);
   AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 		      "The master surface: " << master << "couldn't be found in impactors_information map");
   ImpactorInformationPerMaster * impactor_info = it_imp->second;
   UInt nb_active_nodes = impactor_info->active_impactor_nodes->getSize();
 
   // create vectors
   Vector<bool> * activity_of_nodes = new Vector<bool>(this->mesh.getNbNodes(), 1, false);
   Vector<ElementType> * element_type_of_nodes = new Vector<ElementType>(this->mesh.getNbNodes(), 1, _not_defined);
   Vector<Real> * normals_of_nodes = new Vector<Real>(this->mesh.getNbNodes(), this->spatial_dimension, 0.);
   Vector<bool> * sticking_of_nodes = new Vector<bool>(this->mesh.getNbNodes(), 2, false);
   Vector<Real> * friction_force_of_nodes = new Vector<Real>(this->mesh.getNbNodes(), this->spatial_dimension, 0.);
   Vector<Real> * stick_position_of_nodes = new Vector<Real>(this->mesh.getNbNodes(), this->spatial_dimension, 0.);
   Vector<Real> * residual_force_of_nodes = new Vector<Real>(this->mesh.getNbNodes(), this->spatial_dimension, 0.);
   Vector<Real> * previous_velocity_of_nodes = new Vector<Real>(this->mesh.getNbNodes(), this->spatial_dimension, 0.);
   Vector<Real> * friction_resistances_of_nodes = new Vector<Real>(this->mesh.getNbNodes(), 1, 0.);
 
   UInt * active_nodes = impactor_info->active_impactor_nodes->storage();
   ElementType * element_type = &(*impactor_info->master_element_type)[0];
   Real * master_normal = impactor_info->master_normals->storage();
   bool * node_stick = impactor_info->node_is_sticking->storage();
   Real * friction_force = impactor_info->friction_forces->storage();
   Real * stick_position = impactor_info->stick_positions->storage();
   Real * residual_force = impactor_info->residual_forces->storage();
   Real * previous_velocity = impactor_info->previous_velocities->storage();
   Real * friction_resistance = impactor_info->friction_resistances->storage();
 
   for (UInt i=0; i<nb_active_nodes; ++i, ++active_nodes, ++element_type, ++friction_resistance) {
     (*activity_of_nodes)(*active_nodes) = true;
     (*element_type_of_nodes)(*active_nodes) = *element_type;
     (*friction_resistances_of_nodes)(*active_nodes) = *friction_resistance;
     for (UInt d=0; d<this->spatial_dimension; ++d, ++master_normal, ++friction_force, ++stick_position, ++residual_force, ++previous_velocity) {
       (*normals_of_nodes)(*active_nodes,d) = *master_normal;
       (*friction_force_of_nodes)(*active_nodes,d) = *friction_force;
       (*stick_position_of_nodes)(*active_nodes,d) = *stick_position;
       (*residual_force_of_nodes)(*active_nodes,d) = *residual_force;
       (*previous_velocity_of_nodes)(*active_nodes,d) = *previous_velocity;
     }
     for (UInt j=0; j<2; ++j, ++node_stick) {
       (*sticking_of_nodes)(*active_nodes,j) = *node_stick;
     }
   }
 
   map_to_fill["active_impactor_nodes"] = activity_of_nodes;
   map_to_fill["master_element_type"] = element_type_of_nodes;
   map_to_fill["master_normals"] = normals_of_nodes;
   map_to_fill["node_is_sticking"] = sticking_of_nodes;
   map_to_fill["friction_forces"] = friction_force_of_nodes;
   map_to_fill["stick_positions"] = stick_position_of_nodes;
   map_to_fill["residual_forces"] = residual_force_of_nodes;
   map_to_fill["previous_velocities"] = previous_velocity_of_nodes;
   map_to_fill["friction_resistances"] = friction_resistances_of_nodes;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::setRestartInformation(std::map<std::string, VectorBase* > & restart_map,
 					 Surface master) {
   AKANTU_DEBUG_IN();
 
   ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
   it_imp = this->impactors_information.find(master);
   AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 		      "The master surface: " << master << "couldn't be found in impactors_information map");
   ImpactorInformationPerMaster * impactor_info = it_imp->second;
 
   std::map < std::string, VectorBase* >::iterator it;
 
   it = restart_map.find("active_impactor_nodes");
   Vector<bool> * ai_nodes = (Vector<bool> *)(it->second);
   if(it == restart_map.end()) {
     std::cout << "could not find map entry for active impactor nodes" << std::endl;
   }
 
   it = restart_map.find("master_element_type");
   Vector<ElementType> * et_nodes = (Vector<ElementType> *)(it->second);
   if(it == restart_map.end()) {
     std::cout << "could not find map entry master element type" << std::endl;
   }
 
   it = restart_map.find("master_normals");
   Vector<Real> * mn_nodes = (Vector<Real> *)(it->second);
   if(it == restart_map.end()) {
     std::cout << "could not find map entry for master normals" << std::endl;
   }
 
   it = restart_map.find("node_is_sticking");
   Vector<bool> * is_nodes = (Vector<bool> *)(it->second);
   if(it == restart_map.end()) {
     std::cout << "could not find map entry node is sticking" << std::endl;
   }
 
   it = restart_map.find("friction_forces");
   Vector<Real> * ff_nodes = (Vector<Real> *)(it->second);
   if(it == restart_map.end()) {
     std::cout << "could not find map entry friction forces" << std::endl;
   }
 
   it = restart_map.find("stick_positions");
   Vector<Real> * sp_nodes = (Vector<Real> *)(it->second);
   if(it == restart_map.end()) {
     std::cout << "could not find map entry stick positions" << std::endl;
   }
 
   it = restart_map.find("residual_forces");
   Vector<Real> * rf_nodes = (Vector<Real> *)(it->second);
   if(it == restart_map.end()) {
     std::cout << "could not find map entry residual forces" << std::endl;
   }
 
   it = restart_map.find("previous_velocities");
   Vector<Real> * pv_nodes = (Vector<Real> *)(it->second);
   if(it == restart_map.end()) {
     std::cout << "could not find map entry previous velocities" << std::endl;
   }
 
   it = restart_map.find("friction_resistances");
   Vector<Real> * fr_nodes = (Vector<Real> *)(it->second);
   if(it == restart_map.end()) {
     std::cout << "could not find map entry friction resistances" << std::endl;
   }
 
 
   UInt nb_nodes = this->mesh.getNbNodes();
   for (UInt i=0; i<nb_nodes; ++i) {
     if ((*ai_nodes)(i)) {
       // get active_impactor_nodes and master_element_type information
       impactor_info->active_impactor_nodes->push_back(i);
       impactor_info->master_element_type->push_back((*et_nodes)(i));
 
       // get master_normals and friction_forces information
       Real normal[this->spatial_dimension];
       Real friction[this->spatial_dimension];
       Real position[this->spatial_dimension];
       Real residual[this->spatial_dimension];
       Real velocity[this->spatial_dimension];
       for (UInt d=0; d<this->spatial_dimension; ++d) {
 	normal[d] = (*mn_nodes)(i,d);
 	friction[d] = (*ff_nodes)(i,d);
 	position[d] = (*sp_nodes)(i,d);
 	residual[d] = (*rf_nodes)(i,d);
 	velocity[d] = (*pv_nodes)(i,d);
       }
       impactor_info->master_normals->push_back(normal);
       impactor_info->friction_forces->push_back(friction);
       impactor_info->stick_positions->push_back(position);
       impactor_info->residual_forces->push_back(residual);
       impactor_info->previous_velocities->push_back(velocity);
       impactor_info->friction_resistances->push_back((*fr_nodes)(i));
 
       // get node_is_sticking information
       bool stick[2];
       for (UInt j=0; j<2; ++j) {
 	stick[j] = (*is_nodes)(i,j);
       }
       impactor_info->node_is_sticking->push_back(stick);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::setSimplifiedPrakashCliftonFriction(Real v_star, Real length) {
   this->prakash = true;
   this->ref_velocity = v_star;
   this->characterstic_length = length;
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::unsetSimplifiedPrakashCliftonFriction() {
   this->prakash = false;
 }
 
 /* -------------------------------------------------------------------------- */
 void ContactRigid::setPrakashCliftonToSteadyState(const Surface master) {
   AKANTU_DEBUG_IN();
 
   Real * residual_val = this->model.getResidual().values;
 
   // find the impactors information for this master surface
   ContactRigid::SurfaceToImpactInfoMap::iterator it_imp;
   it_imp = this->impactors_information.find(master);
   AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(),
 		      "The master surface: " << master << "couldn't be found in impactors_information map");
   ImpactorInformationPerMaster * impactor_info = it_imp->second;
 
   ContactRigid::SurfaceToFricCoefMap::iterator it_fc;
   it_fc = this->friction_coefficient.find(master);
   AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(),
 		      "The master surface: " << master << "couldn't be found in friction_coefficient map");
   FrictionCoefficient * fric_coef = it_fc->second;
   AKANTU_DEBUG_ASSERT(fric_coef != NULL, "There is no friction coefficient defined for master surface " << master);
 
   UInt nb_active_impactor_nodes = impactor_info->active_impactor_nodes->getSize();
   UInt * active_impactor_nodes_val = impactor_info->active_impactor_nodes->storage();
   Real * direction_val = impactor_info->master_normals->storage();
   Real * friction_resistances_val = impactor_info->friction_resistances->storage();
 
   // compute the friction coefficient for each active impactor node
   Vector<Real> friction_coefficient_values(nb_active_impactor_nodes, 1);
   Real * friction_coefficient_values_p = friction_coefficient_values.values;
   fric_coef->computeFrictionCoefficient(friction_coefficient_values);
 
   for (UInt n=0; n < nb_active_impactor_nodes; ++n) {
     UInt current_node = active_impactor_nodes_val[n];
 
     Real normal_contact_force = 0.;
     Real friction_force = 0.;
     for (UInt i=0; i < spatial_dimension; ++i) {
       if(!Math::are_float_equal(direction_val[n * this->spatial_dimension + i],0.)) {
 	normal_contact_force = std::abs(residual_val[current_node * this->spatial_dimension + i]);
 	friction_force = friction_coefficient_values_p[n] * normal_contact_force;
       }
     }
 
     friction_resistances_val[n] = friction_force;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/material.cc b/src/model/solid_mechanics/material.cc
index 7fedfeb58..4e8ad3bf2 100644
--- a/src/model/solid_mechanics/material.cc
+++ b/src/model/solid_mechanics/material.cc
@@ -1,814 +1,819 @@
 /**
  * @file   material.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Tue Jul 27 11:43:41 2010
  *
  * @brief  Implementation of the common part of the material class
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material.hh"
 #include "solid_mechanics_model.hh"
 #include "sparse_matrix.hh"
 #include "dof_synchronizer.hh"
 
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 Material::Material(SolidMechanicsModel & model, const ID & id) :
   Memory(model.getMemoryID()),
   id(id),
   name(""),
   model(&model),
   stress("stress", id),
   strain("strain", id),
   element_filter("element_filter", id),
   //  potential_energy_vector(false),
   potential_energy("potential_energy", id),
   is_non_local(false),
   interpolation_inverse_coordinates("interpolation inverse coordinates", id),
   interpolation_points_matrices("interpolation points matrices", id),
   is_init(false) {
   AKANTU_DEBUG_IN();
 
   registerParam("rho",  rho,      0., ParamAccessType(_pat_parsable | _pat_readable), "Density");
   registerParam("id",   this->id,     _pat_readable);
   registerParam("name", name,         ParamAccessType(_pat_parsable | _pat_readable));
 
   spatial_dimension = this->model->getSpatialDimension();
 
   /// allocate strain stress for local elements
   initInternalVector(strain, spatial_dimension * spatial_dimension);
   initInternalVector(stress, spatial_dimension * spatial_dimension);
 
   /// for each connectivity types allocate the element filer array of the material
-  initInternalVector(element_filter, 1);
+  initInternalVector(element_filter, 1, true);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Material::~Material() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 bool Material::parseParam(const std::string & key, const std::string & value,
 			__attribute__ ((unused)) const ID & id) {
   try {
     params.parseParam(key, value);
   } catch(...) { return false; }
   return true;
 }
 /* -------------------------------------------------------------------------- */
 void Material::initMaterial() {
   AKANTU_DEBUG_IN();
 
   resizeInternalVector(stress);
   resizeInternalVector(strain);
 
   is_init = true;
 
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void Material::initInternalVector(ByElementTypeVector<T> & vect,
 				  UInt nb_component,
+				  bool temporary,
 				  ElementKind element_kind) {
   AKANTU_DEBUG_IN();
 
   model->getFEM().getMesh().initByElementTypeVector(vect,
 						    nb_component,
 						    spatial_dimension,
 						    false,
 						    element_kind);
 
-  registerInternal(vect);
+  if(!temporary)
+    registerInternal(vect);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<> void Material::registerInternal<Real>(ByElementTypeVector<Real> & vect) {
   internal_vectors_real[vect.getID()] = &vect;
 }
 template<> void Material::registerInternal<UInt>(ByElementTypeVector<UInt> & vect) {
   internal_vectors_uint[vect.getID()] = &vect;
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void Material::resizeInternalVector(ByElementTypeVector<T> & by_el_type_vect,
 				    ElementKind element_kind) const {
   AKANTU_DEBUG_IN();
 
   FEM * fem = & model->getFEM();
 
   if (element_kind == _ek_cohesive)
       fem = & model->getFEM("CohesiveFEM");
 
   const Mesh & mesh = fem->getMesh();
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
 
     Mesh::type_iterator it  = mesh.firstType(spatial_dimension, gt, element_kind);
     Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, element_kind);
     for(; it != end; ++it) {
       const Vector<UInt> & elem_filter = element_filter(*it, gt);
 
       UInt nb_element           = elem_filter.getSize();
       UInt nb_quadrature_points = fem->getNbQuadraturePoints(*it, gt);
       UInt new_size = nb_element * nb_quadrature_points;
 
       Vector<T> & vect = by_el_type_vect(*it, gt);
       vect.resize(new_size);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Compute  the  residual  by  assembling  @f$\int_{e}  \sigma_e  \frac{\partial
  * \varphi}{\partial X} dX @f$
  *
  * @param[in] displacements nodes displacements
  * @param[in] ghost_type compute the residual for _ghost or _not_ghost element
  */
 void Material::updateResidual(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   computeAllStresses(ghost_type);
 
   assembleResidual(ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void Material::assembleResidual(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model->getSpatialDimension();
 
   Vector<Real> & residual = const_cast<Vector<Real> &>(model->getResidual());
 
   Mesh & mesh = model->getFEM().getMesh();
   Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type);
   for(; it != last_type; ++it) {
     const Vector<Real> & shapes_derivatives = model->getFEM().getShapesDerivatives(*it, ghost_type);
 
     Vector<UInt> & elem_filter = element_filter(*it, ghost_type);
 
     UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent();
     UInt nb_nodes_per_element       = Mesh::getNbNodesPerElement(*it);
     UInt nb_quadrature_points       = model->getFEM().getNbQuadraturePoints(*it, ghost_type);
 
     UInt nb_element = elem_filter.getSize();
 
     /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by @f$\mathbf{B}^t \mathbf{\sigma}_q@f$
     Vector<Real> * sigma_dphi_dx =
       new Vector<Real>(nb_element*nb_quadrature_points, size_of_shapes_derivatives, "sigma_x_dphi_/_dX");
 
     Real * shapesd           = shapes_derivatives.storage();
     Real * shapesd_val;
     UInt * elem_filter_val   = elem_filter.storage();
 
     Vector<Real> * shapesd_filtered =
       new Vector<Real>(nb_element*nb_quadrature_points, size_of_shapes_derivatives, "filtered shapesd");
     Real * shapesd_filtered_val = shapesd_filtered->values;
 
     for (UInt el = 0; el < nb_element; ++el) {
       shapesd_val = shapesd + elem_filter_val[el] * size_of_shapes_derivatives * nb_quadrature_points;
       memcpy(shapesd_filtered_val, shapesd_val,
 	     size_of_shapes_derivatives * nb_quadrature_points * sizeof(Real));
       shapesd_filtered_val += size_of_shapes_derivatives * nb_quadrature_points;
     }
 
     Vector<Real> & stress_vect = stress(*it, ghost_type);
     // Vector<Real>::iterator<types::Matrix> sigma = stress_vect.begin(spatial_dimension, spatial_dimension);
     // Vector<Real>::iterator<types::Matrix> sigma_end = stress_vect.end(spatial_dimension, spatial_dimension);
     // Vector<Real>::iterator<types::Matrix> nabla_B = shapesd_filtered->begin(nb_nodes_per_element, spatial_dimension);
     // Vector<Real>::iterator<types::Matrix> sigma_dphi_dx_it = sigma_dphi_dx->begin(nb_nodes_per_element, spatial_dimension);
 
     // for (; sigma != sigma_end; ++sigma, ++nabla_B, ++sigma_dphi_dx_it) {
     //   sigma_dphi_dx_it->mul<true,false>(*nabla_B, *sigma);
     // }
 
     Math::matrix_matrixt(nb_nodes_per_element, spatial_dimension, spatial_dimension,
 			 *shapesd_filtered,
 			 stress_vect,
 			 *sigma_dphi_dx);
 
     delete shapesd_filtered;
 
     /**
      * compute @f$\int \sigma  * \frac{\partial \varphi}{\partial X}dX@f$ by  @f$ \sum_q \mathbf{B}^t
      * \mathbf{\sigma}_q \overline w_q J_q@f$
      */
     Vector<Real> * int_sigma_dphi_dx = new Vector<Real>(nb_element, nb_nodes_per_element * spatial_dimension,
 							"int_sigma_x_dphi_/_dX");
 
     model->getFEM().integrate(*sigma_dphi_dx, *int_sigma_dphi_dx,
 			      size_of_shapes_derivatives,
 			      *it, ghost_type,
 			      &elem_filter);
     delete sigma_dphi_dx;
 
     /// assemble
     model->getFEM().assembleVector(*int_sigma_dphi_dx, residual,
 				   model->getDOFSynchronizer().getLocalDOFEquationNumbers(),
 				   residual.getNbComponent(),
 				   *it, ghost_type, &elem_filter, -1);
     delete int_sigma_dphi_dx;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Compute  the  stress from the strain
  *
  * @param[in] current_position nodes postition + displacements
  * @param[in] ghost_type compute the residual for _ghost or _not_ghost element
  */
 void Material::computeAllStresses(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   resizeInternalVector(stress);
   resizeInternalVector(strain);
 
   UInt spatial_dimension = model->getSpatialDimension();
 
   Mesh::type_iterator it = model->getFEM().getMesh().firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = model->getFEM().getMesh().lastType(spatial_dimension, ghost_type);
 
   for(; it != last_type; ++it) {
     Vector<UInt> & elem_filter = element_filter(*it, ghost_type);
     Vector<Real> & strain_vect = strain(*it, ghost_type);
 
     /// compute @f$\nabla u@f$
     model->getFEM().gradientOnQuadraturePoints(model->getDisplacement(), strain_vect,
 					       spatial_dimension,
 					       *it, ghost_type, &elem_filter);
 
     /// compute @f$\mathbf{\sigma}_q@f$ from @f$\nabla u@f$
     computeStress(*it, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::setToSteadyState(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   const Vector<Real> & displacement = model->getDisplacement();
 
   resizeInternalVector(strain);
 
   UInt spatial_dimension = model->getSpatialDimension();
 
   Mesh::type_iterator it = model->getFEM().getMesh().firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = model->getFEM().getMesh().lastType(spatial_dimension, ghost_type);
 
   for(; it != last_type; ++it) {
     Vector<UInt> & elem_filter = element_filter(*it, ghost_type);
     Vector<Real> & strain_vect = strain(*it, ghost_type);
 
     /// compute @f$\nabla u@f$
     model->getFEM().gradientOnQuadraturePoints(displacement, strain_vect,
 					      spatial_dimension,
 					      *it, ghost_type, &elem_filter);
 
     setToSteadyState(*it, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /**
  * Compute  the stiffness  matrix by  assembling @f$\int_{\omega}  B^t  \times D
  * \times B d\omega @f$
  *
  * @param[in] current_position nodes postition + displacements
  * @param[in] ghost_type compute the residual for _ghost or _not_ghost element
  */
 void Material::assembleStiffnessMatrix(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model->getSpatialDimension();
 
   Mesh & mesh = model->getFEM().getMesh();
   Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type);
   for(; it != last_type; ++it) {
     switch(spatial_dimension) {
     case 1: { assembleStiffnessMatrix<1>(*it, ghost_type); break; }
     case 2: { assembleStiffnessMatrix<2>(*it, ghost_type); break; }
     case 3: { assembleStiffnessMatrix<3>(*it, ghost_type); break; }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 void Material::assembleStiffnessMatrix(const ElementType & type,
 				       GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   SparseMatrix & K = const_cast<SparseMatrix &>(model->getStiffnessMatrix());
 
   const Vector<Real> & shapes_derivatives = model->getFEM().getShapesDerivatives(type,ghost_type);
 
   Vector<UInt> & elem_filter = element_filter(type, ghost_type);
   Vector<Real> & strain_vect = strain(type, ghost_type);
 
   UInt nb_element                 = elem_filter.getSize();
   UInt nb_nodes_per_element       = Mesh::getNbNodesPerElement(type);
   UInt nb_quadrature_points       = model->getFEM().getNbQuadraturePoints(type, ghost_type);
 
   strain_vect.resize(nb_quadrature_points * nb_element);
 
   model->getFEM().gradientOnQuadraturePoints(model->getDisplacement(), strain_vect,
 					     dim, type, ghost_type, &elem_filter);
 
   UInt tangent_size = getTangentStiffnessVoigtSize(dim);
 
   Vector<Real> * tangent_stiffness_matrix =
     new Vector<Real>(nb_element*nb_quadrature_points, tangent_size * tangent_size,
 		     "tangent_stiffness_matrix");
 
   tangent_stiffness_matrix->clear();
 
   computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type);
 
 
   Vector<Real> * shapes_derivatives_filtered = new Vector<Real>(nb_element * nb_quadrature_points,
 								dim * nb_nodes_per_element,
 								"shapes derivatives filtered");
 
 
   Vector<Real>::const_iterator<types::Matrix> shapes_derivatives_it = shapes_derivatives.begin(spatial_dimension,
 											       nb_nodes_per_element);
 
   Vector<Real>::iterator<types::Matrix> shapes_derivatives_filtered_it  = shapes_derivatives_filtered->begin(spatial_dimension,
 													     nb_nodes_per_element);
   UInt * elem_filter_val = elem_filter.storage();
   for (UInt e = 0; e < nb_element; ++e, ++elem_filter_val)
     for (UInt q = 0; q < nb_quadrature_points; ++q, ++shapes_derivatives_filtered_it)
       *shapes_derivatives_filtered_it = shapes_derivatives_it[*elem_filter_val * nb_quadrature_points + q];
 
   /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
   UInt bt_d_b_size = dim * nb_nodes_per_element;
 
   Vector<Real> * bt_d_b = new Vector<Real>(nb_element * nb_quadrature_points,
 					   bt_d_b_size * bt_d_b_size,
 					   "B^t*D*B");
 
   types::Matrix B(tangent_size, dim * nb_nodes_per_element);
   types::Matrix Bt_D(dim * nb_nodes_per_element, tangent_size);
 
   shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(nb_nodes_per_element, spatial_dimension);
 
   Vector<Real>::iterator<types::Matrix> Bt_D_B_it = bt_d_b->begin(dim*nb_nodes_per_element,
 								  dim*nb_nodes_per_element);
 
   Vector<Real>::iterator<types::Matrix> D_it  = tangent_stiffness_matrix->begin(tangent_size,
 										tangent_size);
   Vector<Real>::iterator<types::Matrix> D_end = tangent_stiffness_matrix->end  (tangent_size,
 										tangent_size);
 
 
   for(; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_filtered_it) {
     types::Matrix & D = *D_it;
     types::Matrix & Bt_D_B = *Bt_D_B_it;
 
     transferBMatrixToSymVoigtBMatrix<dim>(*shapes_derivatives_filtered_it, B, nb_nodes_per_element);
     Bt_D.mul<true, false>(B, D);
     Bt_D_B.mul<false, false>(Bt_D, B);
   }
 
   delete tangent_stiffness_matrix;
   delete shapes_derivatives_filtered;
 
   /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
   Vector<Real> * K_e = new Vector<Real>(nb_element,
 					bt_d_b_size * bt_d_b_size,
 					"K_e");
 
   model->getFEM().integrate(*bt_d_b, *K_e,
 			    bt_d_b_size * bt_d_b_size,
 			    type, ghost_type,
 			    &elem_filter);
 
   delete bt_d_b;
 
   model->getFEM().assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, &elem_filter);
   delete K_e;
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void Material::computePotentialEnergy(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   if(ghost_type != _not_ghost) return;
   Real * epot = potential_energy(el_type, ghost_type).storage();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   computePotentialEnergyOnQuad(grad_u, sigma, *epot);
   epot++;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::computePotentialEnergyByElement() {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh = model->getFEM().getMesh();
   Mesh::type_iterator it = mesh.firstType(spatial_dimension);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension);
   for(; it != last_type; ++it) {
 
     if(!potential_energy.exists(*it, _not_ghost)) {
       UInt nb_element = element_filter(*it, _not_ghost).getSize();
       UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(*it, _not_ghost);
 
       potential_energy.alloc(nb_element * nb_quadrature_points, 1,
 			     *it, _not_ghost);
     }
 
     computePotentialEnergy(*it);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Real Material::getPotentialEnergy() {
   AKANTU_DEBUG_IN();
   Real epot = 0.;
 
   computePotentialEnergyByElement();
 
   /// integrate the potential energy for each type of elements
   Mesh & mesh = model->getFEM().getMesh();
   Mesh::type_iterator it = mesh.firstType(spatial_dimension);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension);
   for(; it != last_type; ++it) {
 
     epot += model->getFEM().integrate(potential_energy(*it, _not_ghost), *it,
 				      _not_ghost, &element_filter(*it, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return epot;
 }
 
 
 /* -------------------------------------------------------------------------- */
 Real Material::getEnergy(std::string type) {
   AKANTU_DEBUG_IN();
   if(type == "potential") return getPotentialEnergy();
   AKANTU_DEBUG_OUT();
   return 0.;
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::computeQuadraturePointsCoordinates(ByElementTypeReal & quadrature_points_coordinates, const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   const Mesh & mesh = model->getFEM().getMesh();
 
   Vector<Real> nodes_coordinates(mesh.getNodes(), true);
   nodes_coordinates += model->getDisplacement();
 
   Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type);
   for(; it != last_type; ++it) {
     const Vector<UInt> & elem_filter = element_filter(*it, ghost_type);
 
     UInt nb_element  = elem_filter.getSize();
     UInt nb_tot_quad = model->getFEM().getNbQuadraturePoints(*it, ghost_type) * nb_element;
 
     Vector<Real> & quads = quadrature_points_coordinates(*it, ghost_type);
     quads.resize(nb_tot_quad);
 
     model->getFEM().interpolateOnQuadraturePoints(nodes_coordinates,
 						  quads, spatial_dimension,
 						  *it, ghost_type, &elem_filter);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::initElementalFieldInterpolation(ByElementTypeReal & interpolation_points_coordinates) {
   AKANTU_DEBUG_IN();
   const Mesh & mesh = model->getFEM().getMesh();
 
   ByElementTypeReal quadrature_points_coordinates("quadrature_points_coordinates_tmp_nl", id);
   mesh.initByElementTypeVector(quadrature_points_coordinates, spatial_dimension, 0);
   computeQuadraturePointsCoordinates(quadrature_points_coordinates, _not_ghost);
   computeQuadraturePointsCoordinates(quadrature_points_coordinates, _ghost);
 
   Mesh::type_iterator it   = mesh.firstType(spatial_dimension);
   Mesh::type_iterator last = mesh.lastType(spatial_dimension);
   for (; it != last; ++it) {
     UInt nb_element = mesh.getNbElement(*it);
     if (nb_element == 0) continue;
     ElementType type = *it;
 #define AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD(type)			\
     initElementalFieldInterpolation<type>(quadrature_points_coordinates(type), \
 					  interpolation_points_coordinates(type))
 
     AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD);
 #undef AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void Material::initElementalFieldInterpolation(const Vector<Real> & quad_coordinates,
 					       const Vector<Real> & interpolation_points_coordinates) {
   AKANTU_DEBUG_IN();
   UInt size_inverse_coords = getSizeElementalFieldInterpolationCoodinates<type>();
 
   Vector<UInt> & elem_fil = element_filter(type);
   UInt nb_element = elem_fil.getSize();
   UInt nb_quad_per_element = model->getFEM().getNbQuadraturePoints(type);
 
   UInt nb_interpolation_points = interpolation_points_coordinates.getSize();
   AKANTU_DEBUG_ASSERT(nb_interpolation_points % nb_element == 0,
 		      "Can't interpolate elemental field on elements, the coordinates vector has a wrong size");
   UInt nb_interpolation_points_per_elem = nb_interpolation_points / nb_element;
 
   if(!interpolation_inverse_coordinates.exists(type))
     interpolation_inverse_coordinates.alloc(nb_element,
 					    size_inverse_coords*size_inverse_coords,
 					    type);
 
   if(!interpolation_points_matrices.exists(type))
     interpolation_points_matrices.alloc(nb_element,
 					nb_interpolation_points_per_elem * size_inverse_coords,
 					type);
 
   Vector<Real> & interp_inv_coord = interpolation_inverse_coordinates(type);
   Vector<Real> & interp_points_mat = interpolation_points_matrices(type);
 
   types::Matrix quad_coord_matrix(size_inverse_coords, size_inverse_coords);
 
   Vector<Real>::const_iterator<types::Matrix> quad_coords_it =
     quad_coordinates.begin_reinterpret(nb_quad_per_element,
 				       spatial_dimension,
 				       nb_element,
 				       nb_quad_per_element * spatial_dimension);
 
   Vector<Real>::const_iterator<types::Matrix> points_coords_it =
     interpolation_points_coordinates.begin_reinterpret(nb_interpolation_points_per_elem,
 						       spatial_dimension,
 						       nb_element,
 						       nb_interpolation_points_per_elem * spatial_dimension);
 
   Vector<Real>::iterator<types::Matrix> inv_quad_coord_it =
     interp_inv_coord.begin(size_inverse_coords, size_inverse_coords);
 
   Vector<Real>::iterator<types::Matrix> inv_points_mat_it =
     interp_points_mat.begin(nb_interpolation_points_per_elem, size_inverse_coords);
 
   /// loop over the elements of the current material and element type
   for (UInt el = 0; el < nb_element; ++el) {
     /// matrix containing the quadrature points coordinates
     const types::Matrix & quad_coords = *quad_coords_it;
     /// matrix to store the matrix inversion result
     types::Matrix & inv_quad_coord_matrix = *inv_quad_coord_it;
 
     /// insert the quad coordinates in a matrix compatible with the interpolation
     buildElementalFieldInterpolationCoodinates<type>(quad_coords,
 						     quad_coord_matrix);
 
     /// invert the interpolation matrix
     inv_quad_coord_matrix.inverse(quad_coord_matrix);
 
 
     /// matrix containing the interpolation points coordinates
     const types::Matrix & points_coords = *points_coords_it;
     /// matrix to store the interpolation points coordinates
     /// compatible with these functions
     types::Matrix & inv_points_coord_matrix = *inv_points_mat_it;
 
     /// insert the quad coordinates in a matrix compatible with the interpolation
     buildElementalFieldInterpolationCoodinates<type>(points_coords,
 						     inv_points_coord_matrix);
 
 
     ++inv_quad_coord_it;
     ++inv_points_mat_it;
     ++quad_coords_it;
     ++points_coords_it;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::interpolateStress(const ElementType type,
 				 Vector<Real> & result) {
   AKANTU_DEBUG_IN();
 
 #define INTERPOLATE_ELEMENTAL_FIELD(type)				\
   interpolateElementalField<type>(stress(type),				\
 				  result)				\
 
   AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(INTERPOLATE_ELEMENTAL_FIELD);
 #undef INTERPOLATE_ELEMENTAL_FIELD
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void Material::interpolateElementalField(const Vector<Real> & field,
 					 Vector<Real> & result) {
   AKANTU_DEBUG_IN();
 
   Vector<UInt> & elem_fil = element_filter(type);
   UInt nb_element = elem_fil.getSize();
   UInt nb_quad_per_element = model->getFEM().getNbQuadraturePoints(type);
   UInt size_inverse_coords = getSizeElementalFieldInterpolationCoodinates<type>();
 
   types::Matrix coefficients(nb_quad_per_element, field.getNbComponent());
 
   const Vector<Real> & interp_inv_coord = interpolation_inverse_coordinates(type);
   const Vector<Real> & interp_points_coord = interpolation_points_matrices(type);
 
   UInt nb_interpolation_points_per_elem = interp_points_coord.getNbComponent() / size_inverse_coords;
 
   Vector<Real> filtered_field(nb_element, nb_quad_per_element);
   extractElementalFieldForInterplation<type>(field, filtered_field);
 
   Vector<Real>::const_iterator<types::Matrix> field_it
     = field.begin_reinterpret(nb_quad_per_element,
 			      field.getNbComponent(),
 			      nb_element,
 			      nb_quad_per_element * field.getNbComponent());
 
   Vector<Real>::const_iterator<types::Matrix> interpolation_points_coordinates_it =
     interp_points_coord.begin(nb_interpolation_points_per_elem, size_inverse_coords);
 
   Vector<Real>::iterator<types::Matrix> result_it
     = result.begin_reinterpret(nb_interpolation_points_per_elem,
 			       field.getNbComponent(),
 			       nb_element,
 			       nb_interpolation_points_per_elem * field.getNbComponent());
 
   Vector<Real>::const_iterator<types::Matrix> inv_quad_coord_it =
     interp_inv_coord.begin(size_inverse_coords, size_inverse_coords);
 
   /// loop over the elements of the current material and element type
   for (UInt el = 0; el < nb_element;
        ++el, ++field_it, ++result_it,
 	 ++inv_quad_coord_it, ++interpolation_points_coordinates_it) {
     /**
      * matrix containing the inversion of the quadrature points'
      * coordinates
      */
     const types::Matrix & inv_quad_coord_matrix = *inv_quad_coord_it;
 
     /**
      * multiply it by the field values over quadrature points to get
      * the interpolation coefficients
      */
     coefficients.mul<false, false>(inv_quad_coord_matrix, *field_it);
 
     /// matrix containing the points' coordinates
     const types::Matrix & coord = *interpolation_points_coordinates_it;
 
     /// multiply the coordinates matrix by the coefficients matrix and store the result
     (*result_it).mul<false, false>(coord, coefficients);
   }
 
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 const Vector<Real> & Material::getVector(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) const {
   std::stringstream sstr;
   std::string ghost_id = "";
   if (ghost_type == _ghost) ghost_id = ":ghost";
   sstr << id << ":" << vect_id << ":" << type << ghost_id;
 
   ID fvect_id = sstr.str();
   try {
     return Memory::getVector<Real>(fvect_id);
   } catch(debug::Exception & e) {
     AKANTU_EXCEPTION("The material " << name << "(" <<id << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]");
   }
 }
 
 /* -------------------------------------------------------------------------- */
 Vector<Real> & Material::getVector(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) {
   std::stringstream sstr;
   std::string ghost_id = "";
   if (ghost_type == _ghost) ghost_id = ":ghost";
   sstr << id << ":" << vect_id << ":" << type << ghost_id;
 
   ID fvect_id = sstr.str();
   try {
     return Memory::getVector<Real>(fvect_id);
   } catch(debug::Exception & e) {
     AKANTU_EXCEPTION("The material " << name << "(" <<id << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]");
   }
 }
 
 /* -------------------------------------------------------------------------- */
-
 void Material::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   std::string type = id.substr(id.find_last_of(":") + 1);
 
   stream << space << "Material " << type << " [" << std::endl;
   params.printself(stream, indent);
   stream << space << "]" << std::endl;
 }
 
 
 /* -------------------------------------------------------------------------- */
 template void Material::initInternalVector<Real>(ByElementTypeVector<Real> & vect,
 						 UInt nb_component,
+						 bool temporary,
 						 ElementKind element_kind);
 
 template void Material::initInternalVector<UInt>(ByElementTypeVector<UInt> & vect,
 						 UInt nb_component,
+						 bool temporary,
 						 ElementKind element_kind);
 
 template void Material::initInternalVector<Int>(ByElementTypeVector<Int> & vect,
 						UInt nb_component,
+						bool temporary,
 						ElementKind element_kind);
 
 template void Material::initInternalVector<bool>(ByElementTypeVector<bool> & vect,
 						 UInt nb_component,
+						 bool temporary,
 						 ElementKind element_kind);
 
 
 template void Material::resizeInternalVector<Real>(ByElementTypeVector<Real> & vect,
 						   ElementKind element_kind) const;
 
 template void Material::resizeInternalVector<UInt>(ByElementTypeVector<UInt> & vect,
 						   ElementKind element_kind) const;
 
 template void Material::resizeInternalVector<Int>(ByElementTypeVector<Int> & vect,
 						  ElementKind element_kind) const;
 
 template void Material::resizeInternalVector<bool>(ByElementTypeVector<bool> & vect,
 						   ElementKind element_kind) const;
 
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/material.hh b/src/model/solid_mechanics/material.hh
index bb18ebf86..9825aaaf4 100644
--- a/src/model/solid_mechanics/material.hh
+++ b/src/model/solid_mechanics/material.hh
@@ -1,545 +1,553 @@
 /**
  * @file   material.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Fri Jul 23 09:06:29 2010
  *
  * @brief  Mother class for all materials
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "aka_memory.hh"
 #include "parser.hh"
 #include "data_accessor.hh"
 #include "material_parameters.hh"
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_HH__
 #define __AKANTU_MATERIAL_HH__
 
 /* -------------------------------------------------------------------------- */
 namespace akantu {
   class Model;
   class SolidMechanicsModel;
   class CommunicationBuffer;
 }
 
 __BEGIN_AKANTU__
 
 /**
  * Interface of all materials
  * Prerequisites for a new material
  * - inherit from this class
  * - implement the following methods:
  * \code
  *  virtual Real getStableTimeStep(Real h, const Element & element = ElementNull);
  *
  *  virtual void computeStress(ElementType el_type,
  *                             GhostType ghost_type = _not_ghost);
  *
  *  virtual void computeTangentStiffness(const ElementType & el_type,
  *                                       Vector<Real> & tangent_matrix,
  *                                       GhostType ghost_type = _not_ghost);
  * \endcode
  *
  */
 class Material : protected Memory, public DataAccessor, public Parsable, public MeshEventHandler {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   Material(SolidMechanicsModel & model, const ID & id = "");
   virtual ~Material();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// register a material parameter
   template<class T>
   void registerParam(std::string name, T & variable, T default_value,
 		     ParamAccessType type,
 		     std::string description = "");
 
   template<class T>
   void registerParam(std::string name, T & variable, ParamAccessType type,
 		     std::string description = "");
 
 
   template<typename T>
   void registerInternal(__attribute__((unused)) ByElementTypeVector<T> & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); }
 
   /// read parameter from file
   virtual bool parseParam(const std::string & key, const std::string & value,
 			  const ID & id);
 
   /// function called to update the internal parameters when the modifiable
   /// parameters are modified
   virtual void updateInternalParameters() {}
 
   /// initialize the material computed parameter
   virtual void initMaterial();
 
   /// compute the residual for this material
   virtual void updateResidual(GhostType ghost_type = _not_ghost);
 
 
   void assembleResidual(GhostType ghost_type);
 
   /// compute the residual for this material
   virtual void computeAllStresses(GhostType ghost_type = _not_ghost);
   virtual void computeAllNonLocalStresses(__attribute__((unused)) GhostType ghost_type = _not_ghost) {};
 
   /// set material to steady state
   void setToSteadyState(GhostType ghost_type = _not_ghost);
 
   /// compute the stiffness matrix
   virtual void assembleStiffnessMatrix(GhostType ghost_type);
 
   /// compute the stable time step for an element of size h
   virtual Real getStableTimeStep(__attribute__((unused)) Real h,
 				 __attribute__((unused)) const Element & element = ElementNull)  {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /// compute the p-wave speed in the material
   virtual Real getPushWaveSpeed() const { AKANTU_DEBUG_TO_IMPLEMENT(); };
 
   /// compute the s-wave speed in the material
   virtual Real getShearWaveSpeed() const { AKANTU_DEBUG_TO_IMPLEMENT(); };
 
   /// add an element to the local mesh filter
   inline UInt addElement(const ElementType & type,
 			 UInt element,
 			 const GhostType & ghost_type);
 
   /// function to print the contain of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /**
    * interpolate stress on given positions for each element by means
    * of a geometrical interpolation on quadrature points
    */
   virtual void interpolateStress(const ElementType type,
 				 Vector<Real> & result);
 
   /**
    * function to initialize the elemental field interpolation
    * function by inverting the quadrature points' coordinates
    */
   virtual void initElementalFieldInterpolation(ByElementTypeReal & interpolation_points_coordinates);
 
 protected:
 
   /// constitutive law
   virtual void computeStress(__attribute__((unused)) ElementType el_type,
 			     __attribute__((unused)) GhostType ghost_type = _not_ghost)  {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
 
   /// set the material to steady state (to be implemented for materials that need it)
   virtual void setToSteadyState(__attribute__((unused)) ElementType el_type,
 				__attribute__((unused)) GhostType ghost_type = _not_ghost) {}
 
   /// compute the tangent stiffness matrix
   virtual void computeTangentModuli(__attribute__((unused)) const ElementType & el_type,
 				    __attribute__((unused)) Vector<Real> & tangent_matrix,
 				    __attribute__((unused)) GhostType ghost_type = _not_ghost) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /// compute the potential energy
   virtual void computePotentialEnergy(ElementType el_type,
 				      GhostType ghost_type = _not_ghost);
 
   template<UInt dim>
   void assembleStiffnessMatrix(const ElementType & type,
 			       GhostType ghost_type);
 
   /// transfer the B matrix to a Voigt notation B matrix
   template<UInt dim>
   inline void transferBMatrixToSymVoigtBMatrix(const types::Matrix & B,
 					       types::Matrix & Bvoigt,
 					       UInt nb_nodes_per_element) const;
 
   inline UInt getTangentStiffnessVoigtSize(UInt spatial_dimension) const;
 
 
   /// compute the potential energy by element
   void computePotentialEnergyByElement();
 
   /// compute the coordinates of the quadrature points
   void computeQuadraturePointsCoordinates(ByElementTypeReal & quadrature_points_coordinates,
 					  const GhostType & ghost_type) const;
 
   /// interpolate an elemental field on given points for each element
   template <ElementType type>
   void interpolateElementalField(const Vector<Real> & field,
 				 Vector<Real> & result);
 
   /// template function to initialize the elemental field interpolation
   template <ElementType type>
   void initElementalFieldInterpolation(const Vector<Real> & quad_coordinates,
 				       const Vector<Real> & interpolation_points_coordinates);
 
   /// build the coordinate matrix for the interpolation on elemental field
   template <ElementType type>
   inline void buildElementalFieldInterpolationCoodinates(const types::Matrix & coordinates,
 							 types::Matrix & coordMatrix);
 
   /// get the size of the coordiante matrix used in the interpolation
   template <ElementType type>
   inline UInt getSizeElementalFieldInterpolationCoodinates();
 
   /// extract the field values corresponding to the quadrature points used for the interpolation
   template <ElementType type>
   inline void extractElementalFieldForInterplation(const Vector<Real> & field,
 						   Vector<Real> & filtered_field);
 
   /* ------------------------------------------------------------------------ */
   /* Function for all materials                                               */
   /* ------------------------------------------------------------------------ */
 protected:
   /// compute the potential energy for on element
   inline void computePotentialEnergyOnQuad(types::Matrix & grad_u,
 					   types::Matrix & sigma,
 					   Real & epot);
 
 protected:
   /// allocate an internal vector
   template<typename T>
   void initInternalVector(ByElementTypeVector<T> & vect,
 			  UInt nb_component,
+			  bool temporary = false,
 			  ElementKind element_kind = _ek_regular);
 
 public:
   /// resize an internal vector
   template<typename T>
   void resizeInternalVector(ByElementTypeVector<T> & vect,
 			    ElementKind element_kind = _ek_regular) const;
 
   /* ------------------------------------------------------------------------ */
   template<UInt dim>
   inline void gradUToF(const types::Matrix & grad_u, types::Matrix & F);
   inline void rightCauchy(const types::Matrix & F, types::Matrix & C);
   inline void leftCauchy (const types::Matrix & F, types::Matrix & B);
   /* ------------------------------------------------------------------------ */
   /* DataAccessor inherited members                                           */
   /* ------------------------------------------------------------------------ */
 public:
 
-  virtual inline UInt getNbDataToPack  (const Element & element, SynchronizationTag tag) const;
-  virtual inline UInt getNbDataToUnpack(const Element & element, SynchronizationTag tag) const;
-
-  virtual UInt getNbDataToPack(__attribute__((unused)) SynchronizationTag tag) const {
-    return 0;
-  }
-
-  virtual UInt getNbDataToUnpack(__attribute__((unused)) SynchronizationTag tag) const {
-    return 0;
-  }
+  virtual inline UInt getNbDataForElements(const Vector<Element> & elements,
+					   SynchronizationTag tag) const;
 
+  virtual inline void packElementData(CommunicationBuffer & buffer,
+				      const Vector<Element> & elements,
+				      SynchronizationTag tag) const;
 
-  virtual inline void packData(CommunicationBuffer & buffer,
-			       const Element & element,
-			       SynchronizationTag tag) const;
+  virtual inline void unpackElementData(CommunicationBuffer & buffer,
+					const Vector<Element> & elements,
+					SynchronizationTag tag);
 
-  virtual void packData(__attribute__((unused)) CommunicationBuffer & buffer,
-			__attribute__((unused)) const UInt index,
-			__attribute__((unused)) SynchronizationTag tag) const {
-  }
+  template<typename T>
+  inline void packElementDataHelper(const ByElementTypeVector<T> & data_to_pack,
+				    CommunicationBuffer & buffer,
+				    const Vector<Element> & elements) const;
 
-  virtual inline void unpackData(CommunicationBuffer & buffer,
-				 const Element & element,
-				 SynchronizationTag tag);
+  template<typename T>
+  inline void unpackElementDataHelper(ByElementTypeVector<T> & data_to_unpack,
+				      CommunicationBuffer & buffer,
+				      const Vector<Element> & elements) const;
 
-  virtual void unpackData(__attribute__((unused)) CommunicationBuffer & buffer,
-			  __attribute__((unused)) const UInt index,
-			  __attribute__((unused)) SynchronizationTag tag) {
-  }
+protected:
+  template<typename T, bool pack_helper>
+  inline void packUnpackElementDataHelper(ByElementTypeVector<T> & data_to_pack,
+					  CommunicationBuffer & buffer,
+					  const Vector<Element> & elements) const;
+public:
+  inline UInt getNbQuadraturePoints(const Vector<Element> & elements) const;
 
+public:
   /* ------------------------------------------------------------------------ */
   virtual inline void onElementsAdded(const Vector<Element> & element_list);
 
+  virtual inline void onElementsRemoved(const Vector<Element> & element_list,
+					const ByElementTypeUInt & new_numbering);
+
+protected:
+  template<typename T>
+  void removeQuadraturePointsFromVectors(ByElementTypeVector<T> & data,
+					 const ByElementTypeUInt & new_numbering);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   AKANTU_GET_MACRO(Model, *model, const SolidMechanicsModel &)
 
   AKANTU_GET_MACRO(ID, id, const ID &);
   AKANTU_GET_MACRO(Rho, rho, Real);
   AKANTU_SET_MACRO(Rho, rho, Real);
 
   Real getPotentialEnergy();
   virtual Real getEnergy(std::string type);
 
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Strain, strain, Real);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy, Real);
 
   bool isNonLocal() const { return is_non_local; }
 
   const Vector<Real> & getVector(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost) const;
   Vector<Real> & getVector(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost);
 
   template<typename T>
   inline T getParam(const ID & param) const;
 
   template<typename T>
   inline void setParam(const ID & param, T value);
 
 protected:
 
   bool isInit() const { return is_init; }
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// id of the material
   ID id;
 
   /// material name
   std::string name;
 
   /// The model to witch the material belong
   SolidMechanicsModel * model;
 
   /// density : rho
   Real rho;
 
   /// stresses arrays ordered by element types
   ByElementTypeReal stress;
 
   /// strains arrays ordered by element types
   ByElementTypeReal strain;
 
   /// list of element handled by the material
   ByElementTypeUInt element_filter;
 
   /// is the vector for potential energy initialized
   //  bool potential_energy_vector;
 
   /// potential energy by element
   ByElementTypeReal potential_energy;
 
   /// tell if using in non local mode or not
   bool is_non_local;
 
   /// spatial dimension
   UInt spatial_dimension;
 
   /// elemental field interpolation coordinates
   ByElementTypeReal interpolation_inverse_coordinates;
 
   /// elemental field interpolation points
   ByElementTypeReal interpolation_points_matrices;
 
   /// list of the paramters
   MaterialParameters params;
 
 private:
   /// boolean to know if the material has been initialized
   bool is_init;
 
   std::map<ID, ByElementTypeReal *> internal_vectors_real;
   std::map<ID, ByElementTypeUInt *> internal_vectors_uint;
 };
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 #if defined (AKANTU_INCLUDE_INLINE_IMPL)
 #  include "material_inline_impl.cc"
 #endif
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const Material & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 __END_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /* Auto loop                                                                  */
 /* -------------------------------------------------------------------------- */
 
 #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type) \
   Vector<Real>::iterator<types::Matrix> strain_it =			\
     this->strain(el_type, ghost_type).begin(spatial_dimension,		\
 					    spatial_dimension);		\
   Vector<Real>::iterator<types::Matrix> strain_end =			\
     this->strain(el_type, ghost_type).end(spatial_dimension,		\
 					  spatial_dimension);		\
   Vector<Real>::iterator<types::Matrix> stress_it =			\
     this->stress(el_type, ghost_type).begin(spatial_dimension,		\
 					    spatial_dimension);		\
   									\
   for(;strain_it != strain_end; ++strain_it, ++stress_it) {		\
     types::Matrix & __attribute__((unused)) grad_u = *strain_it;	\
     types::Matrix & __attribute__((unused)) sigma  = *stress_it
 
 #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END			\
   }									\
 
 
 #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_mat)	\
   Vector<Real>::iterator<types::Matrix> strain_it =			\
     this->strain(el_type, ghost_type).begin(spatial_dimension,		\
 					    spatial_dimension);		\
   Vector<Real>::iterator<types::Matrix> strain_end =			\
     this->strain(el_type, ghost_type).end(spatial_dimension,		\
 					  spatial_dimension);		\
   									\
   UInt tangent_size =							\
     this->getTangentStiffnessVoigtSize(spatial_dimension);		\
   Vector<Real>::iterator<types::Matrix> tangent_it =			\
     tangent_mat.begin(tangent_size,					\
 		      tangent_size);					\
   									\
   for(;strain_it != strain_end; ++strain_it, ++tangent_it) {		\
     types::Matrix & __attribute__((unused)) grad_u  = *strain_it;	\
     types::Matrix & tangent = *tangent_it
 
 
 #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END			\
   }
 
 
 /* -------------------------------------------------------------------------- */
 /* Material list                                                              */
 /* -------------------------------------------------------------------------- */
 #define AKANTU_CORE_MATERIAL_LIST					\
   ((2, (elastic            , MaterialElastic                      )))	\
   ((2, (elastic_orthotropic, MaterialElasticOrthotropic           )))	\
   ((2, (neohookean         , MaterialNeohookean                   )))	\
   ((2, (sls_deviatoric     , MaterialStandardLinearSolidDeviatoric)))	\
   ((2, (ve_stiffness_prop  , MaterialStiffnessProportional        )))
 
 
 #define AKANTU_COHESIVE_MATERIAL_LIST					\
   ((2, (cohesive_bilinear      , MaterialCohesiveBilinear     )))	\
   ((2, (cohesive_linear        , MaterialCohesiveLinear       )))	\
   ((2, (cohesive_linear_extrinsic, MaterialCohesiveLinearExtrinsic )))	\
   ((2, (cohesive_linear_exponential_extrinsic, MaterialCohesiveLinearExponentialExtrinsic ))) \
   ((2, (cohesive_exponential   , MaterialCohesiveExponential  )))
 
 
 #define  AKANTU_DAMAGE_MATERIAL_LIST					\
   ((2, (damage_linear          , MaterialDamageLinear         )))	\
   ((2, (marigo                 , MaterialMarigo               )))	\
   ((2, (mazars                 , MaterialMazars               )))	\
   ((2, (vreepeerlings          , MaterialVreePeerlings        )))
 
 #ifdef AKANTU_DAMAGE_NON_LOCAL
 #define AKANTU_MATERIAL_WEIGHT_FUNCTION_TMPL_LIST			\
   ((stress_wf, StressBasedWeightFunction  ))				\
   ((damage_wf, DamagedWeightFunction      ))				\
   ((remove_wf, RemoveDamagedWeightFunction))				\
   ((base_wf,   BaseWeightFunction         ))
 
 
 #define AKANTU_MATERIAL_VREEPEERLINGS_WEIGHT_FUNCTION_TMPL_LIST		\
   AKANTU_MATERIAL_WEIGHT_FUNCTION_TMPL_LIST				\
   ((removed_damrate_wf, RemoveDamagedWithDamageRateWeightFunction))
 
 #define AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST				\
   ((3, (marigo_non_local       , MaterialMarigoNonLocal,		\
 	AKANTU_MATERIAL_WEIGHT_FUNCTION_TMPL_LIST)))			\
   ((2, (mazars_non_local       , MaterialMazarsNonLocal       )))	\
   ((3, (vreepeerlings_non_local, MaterialVreePeerlingsNonLocal,		\
 	AKANTU_MATERIAL_VREEPEERLINGS_WEIGHT_FUNCTION_TMPL_LIST)))
 
 #else
 #  define AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST
 #endif
 
 #define AKANTU_MATERIAL_LIST			\
   AKANTU_CORE_MATERIAL_LIST			\
   AKANTU_COHESIVE_MATERIAL_LIST			\
   AKANTU_DAMAGE_MATERIAL_LIST			\
   AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST
 
 
 #define INSTANSIATE_MATERIAL(mat_name)			\
   template class mat_name<1>;				\
   template class mat_name<2>;				\
   template class mat_name<3>
 
 #if defined(__INTEL_COMPILER)
 #pragma warning ( push )
 /* warning #654: overloaded virtual function
    "akantu::Material::computeStress" is only partially overridden in
    class "akantu::Material*" */
 
 #pragma warning ( disable : 654 )
 #endif //defined(__INTEL_COMPILER)
 
 /* -------------------------------------------------------------------------- */
 // elastic materials
 #include "material_elastic.hh"
 #include "material_neohookean.hh"
 #include "material_elastic_orthotropic.hh"
 
 // visco-elastic materials
 #include "material_stiffness_proportional.hh"
 #include "material_standard_linear_solid_deviatoric.hh"
 
 
 // damage materials
 #include "material_damage.hh"
 #include "material_marigo.hh"
 #include "material_mazars.hh"
 #include "material_damage_linear.hh"
 #include "material_vreepeerlings.hh"
 
 #if defined(AKANTU_DAMAGE_NON_LOCAL)
 #  include "material_marigo_non_local.hh"
 #  include "material_mazars_non_local.hh"
 #  include "material_vreepeerlings_non_local.hh"
 #endif
 
 // cohesive materials
 #include "material_cohesive.hh"
 #include "material_cohesive_linear.hh"
 #include "material_cohesive_bilinear.hh"
 #include "material_cohesive_linear_extrinsic.hh"
 #include "material_cohesive_exponential.hh"
 #include "material_cohesive_linear_exponential_extrinsic.hh"
 
 
 #if defined(__INTEL_COMPILER)
 #pragma warning ( pop )
 #endif //defined(__INTEL_COMPILER)
 
 
 #endif /* __AKANTU_MATERIAL_HH__ */
diff --git a/src/model/solid_mechanics/material_inline_impl.cc b/src/model/solid_mechanics/material_inline_impl.cc
index d93822dad..c8f5696ad 100644
--- a/src/model/solid_mechanics/material_inline_impl.cc
+++ b/src/model/solid_mechanics/material_inline_impl.cc
@@ -1,268 +1,427 @@
 /**
  * @file   material_inline_impl.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Tue Jul 27 11:57:43 2010
  *
  * @brief  Implementation of the inline functions of the class material
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 __END_AKANTU__
 
 #include "solid_mechanics_model.hh"
 
 __BEGIN_AKANTU__
 
 
 /* -------------------------------------------------------------------------- */
 inline UInt Material::addElement(const ElementType & type,
 				 UInt element,
 				 const GhostType & ghost_type) {
   element_filter(type, ghost_type).push_back(element);
   return element_filter(type, ghost_type).getSize()-1;
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt Material::getTangentStiffnessVoigtSize(UInt dim) const {
   return (dim * (dim - 1) / 2 + dim);
 }
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 inline void Material::gradUToF(const types::Matrix & grad_u,
 			       types::Matrix & F) {
   UInt size_F = F.size();
 
   AKANTU_DEBUG_ASSERT(F.size() >= grad_u.size() && grad_u.size() == dim,
 		      "The dimension of the tensor F should be greater or equal to the dimension of the tensor grad_u.");
 
   for (UInt i = 0; i < dim; ++i)
     for (UInt j = 0; j < dim; ++j)
       F(i, j) = grad_u(i, j);
 
   for (UInt i = 0; i < size_F; ++i) F(i, i) += 1;
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Material::rightCauchy(const types::Matrix & F,
 				  types::Matrix & C) {
   C.mul<true, false>(F, F);
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Material::leftCauchy(const types::Matrix & F,
 				 types::Matrix & B) {
   B.mul<false, true>(F, F);
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Material::computePotentialEnergyOnQuad(types::Matrix & grad_u,
 						   types::Matrix & sigma,
 						   Real & epot) {
   epot = 0.;
   for (UInt i = 0; i < spatial_dimension; ++i)
     for (UInt j = 0; j < spatial_dimension; ++j)
       epot += sigma(i, j) * grad_u(i, j);
 
   epot *= .5;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 inline void Material::transferBMatrixToSymVoigtBMatrix(const types::Matrix & B,
 						       types::Matrix & Bvoigt,
 						       UInt nb_nodes_per_element) const {
   Bvoigt.clear();
 
   for (UInt i = 0; i < dim; ++i)
     for (UInt n = 0; n < nb_nodes_per_element; ++n)
       Bvoigt(i, i + n*dim) = B(n, i);
 
   if(dim == 2) {
     ///in 2D, fill the @f$ [\frac{\partial N_i}{\partial x}, \frac{\partial N_i}{\partial y}]@f$ row
     for (UInt n = 0; n < nb_nodes_per_element; ++n) {
       Bvoigt(2, 1 + n*2) = B(n, 0);
       Bvoigt(2, 0 + n*2) = B(n, 1);
     }
   }
 
 
   if(dim == 3) {
     for (UInt n = 0; n < nb_nodes_per_element; ++n) {
       Real dndx = B(n, 0);
       Real dndy = B(n, 1);
       Real dndz = B(n, 2);
 
       ///in 3D, fill the @f$ [0, \frac{\partial N_i}{\partial y}, \frac{N_i}{\partial z}]@f$ row
       Bvoigt(3, 1 + n*3) = dndz;
       Bvoigt(3, 2 + n*3) = dndy;
 
       ///in 3D, fill the @f$ [\frac{\partial N_i}{\partial x}, 0, \frac{N_i}{\partial z}]@f$ row
       Bvoigt(4, 0 + n*3) = dndz;
       Bvoigt(4, 2 + n*3) = dndx;
 
       ///in 3D, fill the @f$ [\frac{\partial N_i}{\partial x}, \frac{N_i}{\partial y}, 0]@f$ row
       Bvoigt(5, 0 + n*3) = dndy;
       Bvoigt(5, 1 + n*3) = dndx;
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<ElementType type>
 inline void Material::buildElementalFieldInterpolationCoodinates(__attribute__((unused)) const types::Matrix & coordinates,
 								 __attribute__((unused)) types::Matrix & coordMatrix) {
   AKANTU_DEBUG_TO_IMPLEMENT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline void Material::buildElementalFieldInterpolationCoodinates<_triangle_3>(const types::Matrix & coordinates,
 									      types::Matrix & coordMatrix) {
 
   for (UInt i = 0; i < coordinates.rows(); ++i)
     coordMatrix(i, 0) = 1;
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline void Material::buildElementalFieldInterpolationCoodinates<_triangle_6>(const types::Matrix & coordinates,
 									      types::Matrix & coordMatrix) {
 
   UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(_triangle_6);
 
   for (UInt i = 0; i < coordinates.rows(); ++i) {
     coordMatrix(i, 0) = 1;
     for (UInt j = 1; j < nb_quadrature_points; ++j)
       coordMatrix(i, j) = coordinates(i, j-1);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<ElementType type>
 inline UInt Material::getSizeElementalFieldInterpolationCoodinates() {
   return model->getFEM().getNbQuadraturePoints(type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 inline void Material::extractElementalFieldForInterplation(const Vector<Real> & field,
 							   Vector<Real> & filtered_field) {
   filtered_field.copy(field);
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void Material::registerParam(std::string name, T & variable, T default_value,
 			     ParamAccessType type,
 			     std::string description) {
   AKANTU_DEBUG_IN();
   params.registerParam<T>(name, variable, default_value, type, description);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void Material::registerParam(std::string name, T & variable, ParamAccessType type,
 			     std::string description) {
   AKANTU_DEBUG_IN();
   params.registerParam<T>(name, variable, type, description);
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
-inline UInt Material::getNbDataToPack(const Element & element,
-				      SynchronizationTag tag) const {
-  UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
-  if(tag == _gst_smm_stress) return spatial_dimension * spatial_dimension * sizeof(Real) * nb_quadrature_points;
+inline UInt Material::getNbDataForElements(const Vector<Element> & elements,
+					   SynchronizationTag tag) const {
+  //UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
+  //UInt size = 0;
+  if(tag == _gst_smm_stress) {
+    return spatial_dimension * spatial_dimension * sizeof(Real) * this->getNbQuadraturePoints(elements);
+  }
   return 0;
 }
 
 /* -------------------------------------------------------------------------- */
-inline UInt Material::getNbDataToUnpack(const Element & element,
-					SynchronizationTag tag) const {
-  UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
-  if(tag == _gst_smm_stress) return spatial_dimension * spatial_dimension * sizeof(Real) * nb_quadrature_points;
-  return 0;
+inline void Material::packElementData(CommunicationBuffer & buffer,
+				      const Vector<Element> & elements,
+				      SynchronizationTag tag) const {
+  if(tag == _gst_smm_stress) {
+    packElementDataHelper(stress, buffer, elements);
+    // UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
+    // Vector<Real>::const_iterator<types::Matrix> stress_it = stress(element.type, _not_ghost).begin(spatial_dimension, spatial_dimension);
+    // stress_it += element.element * nb_quadrature_points;
+    // for (UInt q = 0; q < nb_quadrature_points; ++q, ++stress_it)
+    //   buffer << *stress_it;
+  }
 }
 
 /* -------------------------------------------------------------------------- */
-inline void Material::packData(CommunicationBuffer & buffer,
-			       const Element & element,
-			       SynchronizationTag tag) const {
+inline void Material::unpackElementData(CommunicationBuffer & buffer,
+					const Vector<Element> & elements,
+					SynchronizationTag tag) {
   if(tag == _gst_smm_stress) {
-    UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
-    Vector<Real>::const_iterator<types::Matrix> stress_it = stress(element.type, _not_ghost).begin(spatial_dimension, spatial_dimension);
-    stress_it += element.element * nb_quadrature_points;
-    for (UInt q = 0; q < nb_quadrature_points; ++q, ++stress_it)
-      buffer << *stress_it;
+    unpackElementDataHelper(stress, buffer, elements);
+    // UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
+    // Vector<Real>::iterator<types::Matrix> stress_it = stress(element.type, _ghost).begin(spatial_dimension, spatial_dimension);
+    // stress_it += element.element * nb_quadrature_points;
+    // for (UInt q = 0; q < nb_quadrature_points; ++q, ++stress_it)
+    //   buffer >> *stress_it;
   }
 }
 
 /* -------------------------------------------------------------------------- */
-inline void Material::unpackData(CommunicationBuffer & buffer,
-				 const Element & element,
-				 SynchronizationTag tag) {
-  if(tag == _gst_smm_stress) {
-    UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
-    Vector<Real>::iterator<types::Matrix> stress_it = stress(element.type, _ghost).begin(spatial_dimension, spatial_dimension);
-    stress_it += element.element * nb_quadrature_points;
-    for (UInt q = 0; q < nb_quadrature_points; ++q, ++stress_it)
-      buffer >> *stress_it;
+inline UInt Material::getNbQuadraturePoints(const Vector<Element> & elements) const {
+  UInt nb_quad = 0;
+  Vector<Element>::const_iterator<Element> it  = elements.begin();
+  Vector<Element>::const_iterator<Element> end = elements.end();
+  for (; it != end; ++it) {
+    const Element & el = *it;
+    nb_quad += this->model->getFEM().getNbQuadraturePoints(el.type, el.ghost_type);
   }
+  return nb_quad;
+}
+
+/* -------------------------------------------------------------------------- */
+template<typename T>
+inline void Material::packElementDataHelper(const ByElementTypeVector<T> & data_to_pack,
+					    CommunicationBuffer & buffer,
+					    const Vector<Element> & elements) const {
+  packUnpackElementDataHelper<T, true>(const_cast<ByElementTypeVector<T> &>(data_to_pack),
+				       buffer,
+				       elements);
 }
 
+/* -------------------------------------------------------------------------- */
+template<typename T>
+inline void Material::unpackElementDataHelper(ByElementTypeVector<T> & data_to_unpack,
+					      CommunicationBuffer & buffer,
+					      const Vector<Element> & elements) const {
+  packUnpackElementDataHelper<T, false>(data_to_unpack, buffer, elements);
+}
+
+/* -------------------------------------------------------------------------- */
+template<typename T, bool pack_helper>
+inline void Material::packUnpackElementDataHelper(ByElementTypeVector<T> & data_to_pack,
+						  CommunicationBuffer & buffer,
+						  const Vector<Element> & element) const {
+  ElementType current_element_type = _not_defined;
+  GhostType current_ghost_type = _casper;
+  UInt nb_quad_per_elem = 0;
+  UInt nb_component = 0;
+
+  Vector<T> * vect = NULL;
+  Vector<UInt> * element_index_material = NULL;
+
+  Vector<Element>::const_iterator<Element> it  = element.begin();
+  Vector<Element>::const_iterator<Element> end = element.end();
+  for (; it != end; ++it) {
+    const Element & el = *it;
+    if(el.type != current_element_type || el.ghost_type != current_ghost_type) {
+      current_element_type = el.type;
+      current_ghost_type   = el.ghost_type;
+
+      vect = &data_to_pack(el.type, el.ghost_type);
+      element_index_material = &(this->model->getElementIndexByMaterial(current_element_type, current_ghost_type));
+
+      nb_quad_per_elem = this->model->getFEM().getNbQuadraturePoints(el.type, el.ghost_type);
+      nb_component = vect->getNbComponent();
+    }
+
+    UInt el_id = (*element_index_material)(el.element);
+    types::Vector<T> data(vect->storage() + el_id * nb_component * nb_quad_per_elem,
+			  nb_component * nb_quad_per_elem);
+    if(pack_helper)
+      buffer << data;
+    else
+      buffer >> data;
+  }
+}
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline T Material::getParam(const ID & param) const {
   try {
     return params.get<T>(param);
   } catch (...) {
     AKANTU_EXCEPTION("No parameter " << param << " in the material " << id);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline void Material::setParam(const ID & param, T value) {
   try {
     params.set<T>(param, value);
   } catch(...) {
     AKANTU_EXCEPTION("No parameter " << param << " in the material " << id);
   }
   updateInternalParameters();
 }
 
+
+/* -------------------------------------------------------------------------- */
+template<typename T>
+void Material::removeQuadraturePointsFromVectors(ByElementTypeVector<T> & data,
+						 const ByElementTypeUInt & new_numbering) {
+  for(UInt g = _not_ghost; g <= _ghost; ++g) {
+    GhostType gt = (GhostType) g;
+    ByElementTypeVector<UInt>::type_iterator it  = new_numbering.firstType(0, gt, _ek_not_defined);
+    ByElementTypeVector<UInt>::type_iterator end = new_numbering.lastType(0, gt, _ek_not_defined);
+    for (; it != end; ++it) {
+      ElementType type = *it;
+      if(data.exists(type, gt)){
+	const Vector<UInt> & renumbering = new_numbering(type, gt);
+
+	Vector<T> & vect = data(type, gt);
+
+	UInt nb_quad_per_elem = this->model->getFEM().getNbQuadraturePoints(type, gt);
+	UInt nb_component = vect.getNbComponent();
+
+	Vector<T> tmp(renumbering.getSize(), nb_component);
+	UInt new_size = 0;
+	for (UInt i = 0; i < vect.getSize(); ++i) {
+	  UInt new_i = renumbering(i);
+	  if(new_i != UInt(-1)) {
+	    memcpy(tmp.storage() + new_i * nb_component * nb_quad_per_elem,
+		   vect.storage() + i * nb_component * nb_quad_per_elem,
+		   nb_component * nb_quad_per_elem * sizeof(T));
+	    ++new_size;
+	  }
+	}
+	tmp.resize(new_size * nb_quad_per_elem);
+	vect.copy(tmp);
+      }
+    }
+  }
+}
+
 /* -------------------------------------------------------------------------- */
 inline void Material::onElementsAdded(__attribute__((unused)) const Vector<Element> & element_list) {
   for (std::map<ID, ByElementTypeReal *>::iterator it = internal_vectors_real.begin();
        it != internal_vectors_real.end();
        ++it) {
     resizeInternalVector(*(it->second));
   }
 
   for (std::map<ID, ByElementTypeUInt *>::iterator it = internal_vectors_uint.begin();
        it != internal_vectors_uint.end();
        ++it) {
     resizeInternalVector(*(it->second));
   }
 }
+
+/* -------------------------------------------------------------------------- */
+inline void Material::onElementsRemoved(const Vector<Element> & element_list, const ByElementTypeUInt & new_numbering) {
+  ByElementTypeUInt material_local_new_numbering;
+  initInternalVector(material_local_new_numbering, 1, true);
+  resizeInternalVector(material_local_new_numbering);
+
+  Vector<Element>::const_iterator<Element> el_begin = element_list.begin();
+  Vector<Element>::const_iterator<Element> el_end   = element_list.end();
+
+  for(UInt g = _not_ghost; g <= _ghost; ++g) {
+    GhostType gt = (GhostType) g;
+    ByElementTypeVector<UInt>::type_iterator it  = new_numbering.firstType(0, gt, _ek_not_defined);
+    ByElementTypeVector<UInt>::type_iterator end = new_numbering.lastType(0, gt, _ek_not_defined);
+    for (; it != end; ++it) {
+      ElementType type = *it;
+      if(element_filter.exists(type, gt)){
+	Vector<UInt> & elem_filter = element_filter(type, gt);
+
+	Vector<UInt> & element_index_material = model->getElementIndexByMaterial(type, gt);
+	element_index_material.resize(model->getFEM().getMesh().getNbElement(type, gt)); // all materials will resize of the same size...
+
+	Vector<UInt> & mat_renumbering = material_local_new_numbering(type, gt);
+	Vector<UInt> elem_filter_tmp;
+	UInt ni;
+	Element el;
+	el.type = type;
+	el.ghost_type = gt;
+	for (UInt i = 0; i < elem_filter.getSize(); ++i) {
+	  el.element = elem_filter(i);
+	  if(std::find(el_begin, el_end, el) == el_end) {
+	    elem_filter_tmp.push_back(elem_filter(i));
+	    mat_renumbering(i) = ni;
+	    element_index_material(el.element) = ni;
+	    ++ni;
+	  } else {
+	    mat_renumbering(i) = UInt(-1);
+	  }
+	}
+
+	elem_filter.resize(elem_filter_tmp.getSize());
+	elem_filter.copy(elem_filter);
+      }
+    }
+  }
+
+  for (std::map<ID, ByElementTypeReal *>::iterator it = internal_vectors_real.begin();
+       it != internal_vectors_real.end();
+       ++it) {
+    this->removeQuadraturePointsFromVectors(*(it->second), material_local_new_numbering);
+  }
+
+  for (std::map<ID, ByElementTypeUInt *>::iterator it = internal_vectors_uint.begin();
+       it != internal_vectors_uint.end();
+       ++it) {
+    this->removeQuadraturePointsFromVectors(*(it->second), material_local_new_numbering);
+  }
+}
diff --git a/src/model/solid_mechanics/materials/material_damage/material_damage.cc b/src/model/solid_mechanics/materials/material_damage/material_damage.cc
index d338cb5d2..d1472e62e 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_damage.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_damage.cc
@@ -1,163 +1,163 @@
 /**
  * @file   material_damage.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Marion Chambart <marion.chambart@epfl.ch>
  * @date   Tue Jul 27 11:53:52 2010
  *
  * @brief  Specialization of the material class for the damage material
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_damage.hh"
 #include "solid_mechanics_model.hh"
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 MaterialDamage<spatial_dimension>::MaterialDamage(SolidMechanicsModel & model,
 						  const ID & id)  :
   Material(model, id), MaterialElastic<spatial_dimension>(model, id),
   damage("damage", id),
-  dissipated_energy("Dissipated Energy", id),
-  strain_prev("Previous Strain", id),
-  stress_prev("Previous Stress", id),
-  int_sigma("Integral of sigma", id) {
+  dissipated_energy("dissipated energy", id),
+  strain_prev("previous strain", id),
+  stress_prev("previous stress", id),
+  int_sigma("integral of sigma", id) {
   AKANTU_DEBUG_IN();
 
   this->is_non_local = false;
   this->initInternalVector(this->damage, 1);
   this->initInternalVector(this->dissipated_energy, 1);
   this->initInternalVector(this->strain_prev, spatial_dimension * spatial_dimension);
   this->initInternalVector(this->stress_prev, spatial_dimension * spatial_dimension);
   this->initInternalVector(this->int_sigma, 1);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialDamage<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
   MaterialElastic<spatial_dimension>::initMaterial();
 
   this->resizeInternalVector(this->damage);
   this->resizeInternalVector(this->dissipated_energy);
   this->resizeInternalVector(this->strain_prev);
   this->resizeInternalVector(this->stress_prev);
   this->resizeInternalVector(this->int_sigma);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Compute the dissipated energy in  each element by a trapezoidal approximation
  * of
  * @f$ Ed = \int_0^{\epsilon}\sigma(\omega)d\omega - \frac{1}{2}\sigma:\epsilon@f$
  */
 template<UInt spatial_dimension>
 void MaterialDamage<spatial_dimension>::updateDissipatedEnergy(GhostType ghost_type) {
   // compute the dissipated energy per element
   const Mesh & mesh = this->model->getFEM().getMesh();
   Mesh::type_iterator it  = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type);
 
   for(; it != end; ++it) {
     ElementType el_type = *it;
     Vector<Real>::iterator<types::Matrix> sigma =
       this->stress(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
     Vector<Real>::iterator<types::Matrix> sigma_p =
       stress_prev(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
     Vector<Real>::iterator<types::Matrix> epsilon =
       this->strain(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
     Vector<Real>::iterator<types::Matrix> epsilon_p =
       strain_prev(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
 
     Vector<Real>::iterator<Real> ints = int_sigma(el_type, ghost_type).begin();
     Vector<Real>::iterator<Real> ed   = dissipated_energy(el_type, ghost_type).begin();
     Vector<Real>::iterator<Real> ed_end  = dissipated_energy(el_type, ghost_type).end();
 
     for (; ed != ed_end; ++ed, ++ints, ++epsilon, ++sigma, ++epsilon_p, ++sigma_p) {
       Real epot = 0.;
       Real dint = 0.;
       for (UInt i = 0; i < spatial_dimension; ++i) {
 	for (UInt j = 0; j < spatial_dimension; ++j) {
 	  epot += (*sigma)(i,j) * (*epsilon)(i,j); /// \f$ epot = .5 \sigma : \epsilon \f$
 	  dint += .5 * ((*sigma_p)(i,j) + (*sigma)(i,j)) * ((*epsilon)(i,j) - (*epsilon_p)(i,j)); /// \f$ \frac{.5 \sigma(\epsilon(t-h)) + \sigma(\epsilon(t))}{\epsilon(t) - \epsilon(t-h)} \f$
 
 	  (*epsilon_p)(i,j) = (*epsilon)(i,j);
 	  (*sigma_p)(i,j) = (*sigma)(i,j);
 	}
       }
 
       epot *= .5;
 
       *ints += dint;
       *ed = *ints - epot;
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialDamage<spatial_dimension>::computeAllStresses(GhostType ghost_type) {
   Material::computeAllStresses(ghost_type);
   if(!this->is_non_local) this->updateDissipatedEnergy(ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 Real MaterialDamage<spatial_dimension>::getDissipatedEnergy() const {
   AKANTU_DEBUG_IN();
 
   Real de = 0.;
   const Mesh & mesh = this->model->getFEM().getMesh();
 
   /// integrate the dissipated energy for each type of elements
   Mesh::type_iterator it  = mesh.firstType(spatial_dimension, _not_ghost);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost);
 
   for(; it != end; ++it) {
     de += this->model->getFEM().integrate(dissipated_energy(*it, _not_ghost), *it,
 					  _not_ghost, &this->element_filter(*it, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return de;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 Real MaterialDamage<spatial_dimension>::getEnergy(std::string type) {
   if(type == "dissipated") return getDissipatedEnergy();
   else return Material::getEnergy(type);
 }
 
 /* -------------------------------------------------------------------------- */
 
 INSTANSIATE_MATERIAL(MaterialDamage);
 
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/materials/material_damage/material_damage.hh b/src/model/solid_mechanics/materials/material_damage/material_damage.hh
index 9e6dabb57..79e073366 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_damage.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_damage.hh
@@ -1,101 +1,104 @@
 /**
  * @file   material_damage.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Marion Chambart <marion.chambart@epfl.ch>
  * @date   Thu Jul 29 15:00:59 2010
  *
  * @brief  Material isotropic elastic
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "material.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_DAMAGE_HH__
 #define __AKANTU_MATERIAL_DAMAGE_HH__
 
 __BEGIN_AKANTU__
 template<UInt spatial_dimension>
 class MaterialDamage : public MaterialElastic<spatial_dimension> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   MaterialDamage(SolidMechanicsModel & model, const ID & id = "");
 
   virtual ~MaterialDamage() {};
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   void initMaterial();
 
   virtual void computeAllStresses(GhostType ghost_type);
 
 protected:
   /// update the dissipated energy, must be called after the stress have been computed
   void updateDissipatedEnergy(GhostType ghost_type);
 
 
   /* ------------------------------------------------------------------------ */
   /* DataAccessor inherited members                                           */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// give the dissipated energy for the time step
   Real getDissipatedEnergy() const;
 
   virtual Real getEnergy(std::string type);
 
+  AKANTU_GET_MACRO_NOT_CONST(Damage, damage, ByElementTypeReal &);
+  AKANTU_GET_MACRO(Damage, damage, const ByElementTypeReal &);
+
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// damage internal variable
   ByElementTypeReal damage;
 
   /// dissipated energy
   ByElementTypeReal dissipated_energy;
 
   /// previous strain used to compute the dissipated energy
   ByElementTypeReal strain_prev;
 
   /// previous strain used to compute the dissipated energy
   ByElementTypeReal stress_prev;
 
   /// contain the current value of @f$ \int_0^{\epsilon}\sigma(\omega)d\omega @f$ the dissipated energy
   ByElementTypeReal int_sigma;
 };
 
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MATERIAL_DAMAGE_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh b/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh
index 94f7b23d8..e53f8bad3 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_damage_non_local.hh
@@ -1,136 +1,103 @@
 /**
  * @file   material_damage_non_local.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Aug 16 18:28:00 2012
  *
  * @brief  interface for non local damage material
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_DAMAGE_NON_LOCAL_HH__
 #define __AKANTU_MATERIAL_DAMAGE_NON_LOCAL_HH__
 
 __BEGIN_AKANTU__
 
 template<UInt spatial_dimension,
 	 template <UInt> class MaterialDamageLocal,
 	 template <UInt> class WeightFunction = BaseWeightFunction>
 class MaterialDamageNonLocal : public MaterialDamageLocal<spatial_dimension>,
 			       public MaterialNonLocal<spatial_dimension, WeightFunction> {
 public:
   typedef MaterialNonLocal<spatial_dimension, WeightFunction> MaterialNonLocalParent;
   typedef MaterialDamageLocal<spatial_dimension> MaterialDamageParent;
 
   MaterialDamageNonLocal(SolidMechanicsModel & model, const ID & id)  :
     Material(model, id),
     MaterialDamageParent(model, id), MaterialNonLocalParent(model, id) { };
 
   /* ------------------------------------------------------------------------ */
   virtual void initMaterial() {
     MaterialDamageParent::initMaterial();
     MaterialNonLocalParent::initMaterial();
   }
 
 protected:
   /* -------------------------------------------------------------------------- */
   virtual void computeNonLocalStress(ElementType type, GhostType ghost_type = _not_ghost) = 0;
 
   /* ------------------------------------------------------------------------ */
   void computeNonLocalStresses(GhostType ghost_type) {
     AKANTU_DEBUG_IN();
     Mesh::type_iterator it = this->model->getFEM().getMesh().firstType(spatial_dimension, ghost_type);
     Mesh::type_iterator last_type = this->model->getFEM().getMesh().lastType(spatial_dimension, ghost_type);
     for(; it != last_type; ++it) {
       computeNonLocalStress(*it, ghost_type);
     }
     this->updateDissipatedEnergy(ghost_type);
     AKANTU_DEBUG_OUT();
   }
 
 public:
   /* ------------------------------------------------------------------------ */
   virtual bool parseParam(const std::string & key, const std::string & value,
 			const ID & id) {
     return MaterialNonLocalParent::parseParam(key, value, id) ||
       MaterialDamageParent::parseParam(key, value, id);
   }
 
 public:
   /* ------------------------------------------------------------------------ */
-  virtual inline UInt getNbDataToPack(const Element & element,
-				      SynchronizationTag tag) const {
-    return MaterialNonLocalParent::getNbDataToPack(element, tag) +
-      MaterialDamageParent::getNbDataToPack(element, tag);
-  }
-
-  virtual inline UInt getNbDataToUnpack(const Element & element,
-					SynchronizationTag tag) const {
-    return MaterialNonLocalParent::getNbDataToUnpack(element, tag) +
-      MaterialDamageParent::getNbDataToUnpack(element, tag);
-  }
-
-  virtual inline UInt getNbDataToPack(SynchronizationTag tag) const {
-    return MaterialNonLocalParent::getNbDataToPack(tag) +
-      MaterialDamageParent::getNbDataToPack(tag);
-  }
-
-  virtual inline UInt getNbDataToUnpack(SynchronizationTag tag) const {
-    return MaterialNonLocalParent::getNbDataToUnpack(tag) +
-      MaterialDamageParent::getNbDataToUnpack(tag);
+  virtual inline UInt getNbDataForElements(const Vector<Element> & elements,
+					   SynchronizationTag tag) const {
+    return MaterialNonLocalParent::getNbDataForElements(elements, tag) +
+      MaterialDamageParent::getNbDataForElements(elements, tag);
   }
-
-
-  virtual inline void packData(CommunicationBuffer & buffer,
-			       const Element & element,
-			       SynchronizationTag tag) const {
-    MaterialNonLocalParent::packData(buffer, element, tag);
-    MaterialDamageParent::packData(buffer, element, tag);
+  virtual inline void packElementData(CommunicationBuffer & buffer,
+				      const Vector<Element> & elements,
+				      SynchronizationTag tag) const {
+    MaterialNonLocalParent::packElementData(buffer, elements, tag);
+    MaterialDamageParent::packElementData(buffer, elements, tag);
   }
 
-  virtual inline void unpackData(CommunicationBuffer & buffer,
-				 const Element & element,
+  virtual inline void unpackElementData(CommunicationBuffer & buffer,
+				 const Vector<Element> & elements,
 				 SynchronizationTag tag) {
-    MaterialNonLocalParent::unpackData(buffer, element, tag);
-    MaterialDamageParent::unpackData(buffer, element, tag);
-  }
-
-  virtual void packData(CommunicationBuffer & buffer,
-			const UInt index,
-			SynchronizationTag tag) const {
-    MaterialNonLocalParent::packData(buffer, index, tag);
-    MaterialDamageParent::packData(buffer, index, tag);
+    MaterialNonLocalParent::unpackElementData(buffer, elements, tag);
+    MaterialDamageParent::unpackElementData(buffer, elements, tag);
   }
 
-  virtual void unpackData(CommunicationBuffer & buffer,
-			const UInt index,
-			SynchronizationTag tag) {
-    MaterialNonLocalParent::unpackData(buffer, index, tag);
-    MaterialDamageParent::unpackData(buffer, index, tag);
-  }
-
-
 };
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MATERIAL_DAMAGE_NON_LOCAL_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo.hh b/src/model/solid_mechanics/materials/material_damage/material_marigo.hh
index 765ea130c..a1e44030c 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo.hh
@@ -1,151 +1,139 @@
 /**
  * @file   material_marigo.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Marion Chambart <marion.chambart@epfl.ch>
  * @date   Thu Jul 29 15:00:59 2010
  *
  * @brief  Material isotropic elastic
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "material.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_MARIGO_HH__
 #define __AKANTU_MATERIAL_MARIGO_HH__
 
 __BEGIN_AKANTU__
 
 /**
  * Material marigo
  *
  * parameters in the material files :
  *   - Yd  : (default: 50)
  *   - Sd  : (default: 5000)
  *   - Ydrandomness  : (default:0)
  */
 template<UInt spatial_dimension>
 class MaterialMarigo : public MaterialDamage<spatial_dimension> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   MaterialMarigo(SolidMechanicsModel & model, const ID & id = "");
 
   virtual ~MaterialMarigo() {};
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   void initMaterial();
 
   virtual void updateInternalParameters();
 
   /// constitutive law for all element of a type
   void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
 
 protected:
   /// constitutive law for a given quadrature point
   inline void computeStressOnQuad(types::Matrix & grad_u,
 				  types::Matrix & sigma,
 				  Real & dam,
 				  Real & Y,
 				  Real & Ydq);
 
   inline void computeDamageAndStressOnQuad(types::Matrix & sigma,
 					   Real & dam,
 					   Real & Y,
 					   Real & Ydq);
 
   /* ------------------------------------------------------------------------ */
   /* DataAccessor inherited members                                           */
   /* ------------------------------------------------------------------------ */
 public:
 
-  inline virtual UInt getNbDataToPack(const Element & element,
- 				      SynchronizationTag tag) const;
-
-  inline virtual UInt getNbDataToUnpack(const Element & element,
- 					SynchronizationTag tag) const;
-
-  inline virtual void packData(CommunicationBuffer & buffer,
- 			       const Element & element,
- 			       SynchronizationTag tag) const;
-
-  inline virtual void unpackData(CommunicationBuffer & buffer,
-                                 const Element & element,
-                                 SynchronizationTag tag);
-
-  virtual UInt getNbDataToPack(__attribute__((unused)) SynchronizationTag tag) const { return 0; }
-  virtual UInt getNbDataToUnpack(__attribute__((unused)) SynchronizationTag tag) const { return 0; }
-  virtual void packData(__attribute__((unused)) CommunicationBuffer & buffer,
-			__attribute__((unused)) const UInt index,
-			__attribute__((unused)) SynchronizationTag tag) const { }
-  virtual void unpackData(__attribute__((unused)) CommunicationBuffer & buffer,
-			  __attribute__((unused)) const UInt index,
-			  __attribute__((unused)) SynchronizationTag tag) { }
+  inline virtual UInt getNbDataForElements(const Vector<Element> & elements,
+					   SynchronizationTag tag) const;
+
+  inline virtual void packElementData(CommunicationBuffer & buffer,
+				      const Vector<Element> & elements,
+				      SynchronizationTag tag) const;
+
+  inline virtual void unpackElementData(CommunicationBuffer & buffer,
+					const Vector<Element> & elements,
+					SynchronizationTag tag);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
 
   /// resistance to damage
   Real Yd;
 
   /// damage threshold
   Real Sd;
 
   /// randomness on Yd
   Real Yd_randomness;
 
   /// critical epsilon when the material is considered as broken
   Real epsilon_c;
 
   Real Yc;
 
   /// Yd random internal variable
   ByElementTypeReal Yd_rand;
 
   bool damage_in_y;
   bool yc_limit;
 };
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 #include "material_marigo_inline_impl.cc"
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MATERIAL_MARIGO_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.cc b/src/model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.cc
index 8b1a5a078..d942c8da3 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.cc
@@ -1,146 +1,129 @@
 /**
  * @file   material_marigo_inline_impl.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Marion Chambart <marion.chambart@epfl.ch>
  * @date   Tue Jul 27 11:57:43 2010
  *
  * @brief  Implementation of the inline functions of the material marigo
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 inline void
 MaterialMarigo<spatial_dimension>::computeStressOnQuad(types::Matrix & grad_u,
 						       types::Matrix & sigma,
 						       Real & dam,
 						       Real & Y,
 						       Real &Ydq) {
   MaterialElastic<spatial_dimension>::computeStressOnQuad(grad_u, sigma);
 
   Y = 0;
   for (UInt i = 0; i < spatial_dimension; ++i) {
     for (UInt j = 0; j < spatial_dimension; ++j) {
       Y += sigma(i,j) * grad_u(i,j);
     }
   }
   Y *= 0.5;
 
   if(damage_in_y) Y *= (1 - dam);
 
   if(yc_limit) Y = std::min(Y, Yc);
 
   if(!this->is_non_local) {
     computeDamageAndStressOnQuad(sigma, dam, Y, Ydq);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 inline void
 MaterialMarigo<spatial_dimension>::computeDamageAndStressOnQuad(types::Matrix & sigma,
 								Real & dam,
 								Real & Y,
 								Real &Ydq) {
   Real Fd = Y - Ydq - Sd * dam;
 
   if (Fd > 0) dam = (Y - Ydq) / Sd;
   dam = std::min(dam,1.);
 
   sigma *= 1-dam;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
-inline UInt MaterialMarigo<spatial_dimension>::getNbDataToPack(const Element & element,
-					    SynchronizationTag tag) const {
+inline UInt MaterialMarigo<spatial_dimension>::getNbDataForElements(const Vector<Element> & elements,
+								    SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
   UInt size = 0;
   if(tag == _gst_smm_init_mat) {
-    UInt nb_quadrature_points = this->model->getFEM().getNbQuadraturePoints(element.type);
-    size += sizeof(Real) * nb_quadrature_points;
+    size += sizeof(Real) * this->getNbQuadraturePoints(elements);
   }
 
-  size += MaterialDamage<spatial_dimension>::getNbDataToPack(element, tag);
+  size += MaterialDamage<spatial_dimension>::getNbDataForElements(elements, tag);
 
   AKANTU_DEBUG_OUT();
   return size;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
-inline UInt MaterialMarigo<spatial_dimension>::getNbDataToUnpack(const Element & element,
-					      SynchronizationTag tag) const {
-  AKANTU_DEBUG_IN();
-
-  UInt size = 0;
-  if(tag == _gst_smm_init_mat) {
-    UInt nb_quadrature_points = this->model->getFEM().getNbQuadraturePoints(element.type);
-    size += sizeof(Real) * nb_quadrature_points;
-  }
-
-  size += MaterialDamage<spatial_dimension>::getNbDataToPack(element, tag);
-
-  AKANTU_DEBUG_OUT();
-  return size;
-}
-
-/* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension>
-inline void MaterialMarigo<spatial_dimension>::packData(CommunicationBuffer & buffer,
-				     const Element & element,
-				     SynchronizationTag tag) const {
+inline void MaterialMarigo<spatial_dimension>::packElementData(CommunicationBuffer & buffer,
+							       const Vector<Element> & elements,
+							       SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
   if(tag == _gst_smm_init_mat) {
-    UInt nb_quadrature_points = this->model->getFEM().getNbQuadraturePoints(element.type);
-    Vector<Real>::const_iterator<Real> Yds = Yd_rand(element.type, _not_ghost).begin();
-    Yds += element.element * nb_quadrature_points;
-    for (UInt q = 0; q < nb_quadrature_points; ++q, ++Yds)
-      buffer << *Yds;
+    this->packElementDataHelper(Yd_rand, buffer, elements);
+    // UInt nb_quadrature_points = this->model->getFEM().getNbQuadraturePoints(element.type);
+    // Vector<Real>::const_iterator<Real> Yds = Yd_rand(element.type, _not_ghost).begin();
+    // Yds += element.element * nb_quadrature_points;
+    // for (UInt q = 0; q < nb_quadrature_points; ++q, ++Yds)
+    //   buffer << *Yds;
   }
 
-  MaterialDamage<spatial_dimension>::packData(buffer, element, tag);
+  MaterialDamage<spatial_dimension>::packElementData(buffer, elements, tag);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
-inline void MaterialMarigo<spatial_dimension>::unpackData(CommunicationBuffer & buffer,
-				       const Element & element,
-				       SynchronizationTag tag) {
+inline void MaterialMarigo<spatial_dimension>::unpackElementData(CommunicationBuffer & buffer,
+								 const Vector<Element> & elements,
+								 SynchronizationTag tag) {
   AKANTU_DEBUG_IN();
 
   if(tag == _gst_smm_init_mat) {
-    UInt nb_quadrature_points = this->model->getFEM().getNbQuadraturePoints(element.type);
-    Vector<Real>::iterator<Real> Ydr = Yd_rand(element.type, _ghost).begin();
-    Ydr += element.element * nb_quadrature_points;
-    for (UInt q = 0; q < nb_quadrature_points; ++q, ++Ydr)
-      buffer << *Ydr;
+    this->unpackElementDataHelper(Yd_rand, buffer, elements);
+    // UInt nb_quadrature_points = this->model->getFEM().getNbQuadraturePoints(element.type);
+    // Vector<Real>::iterator<Real> Ydr = Yd_rand(element.type, _ghost).begin();
+    // Ydr += element.element * nb_quadrature_points;
+    // for (UInt q = 0; q < nb_quadrature_points; ++q, ++Ydr)
+    //   buffer << *Ydr;
   }
 
-  MaterialDamage<spatial_dimension>::unpackData(buffer, element, tag);
+  MaterialDamage<spatial_dimension>::unpackElementData(buffer, elements, tag);
 
   AKANTU_DEBUG_OUT();
 }
diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc
index 58d9b7870..01a37f48c 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc
@@ -1,176 +1,176 @@
 /**
  * @file   material_mazars_non_local.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marion Chambart <marion.chambart@epfl.ch>
  * @date   Tue Jul 27 11:53:52 2010
  *
  * @brief  Specialization of the material class for the non-local mazars material
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_mazars_non_local.hh"
 #include "solid_mechanics_model.hh"
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 MaterialMazarsNonLocal<spatial_dimension>::MaterialMazarsNonLocal(SolidMechanicsModel & model,
 								  const ID & id)  :
   Material(model, id),
   MaterialMazars<spatial_dimension>(model, id),
   MaterialNonLocalParent(model, id),
   Ehat("epsilon_equ", id) {
   AKANTU_DEBUG_IN();
 
   this->damage_in_compute_stress = false;
   this->is_non_local = true;
   this->initInternalVector(this->Ehat, 1);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialMazarsNonLocal<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
   MaterialMazars<spatial_dimension>::initMaterial();
   MaterialNonLocalParent::initMaterial();
   this->resizeInternalVector(this->Ehat);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialMazarsNonLocal<spatial_dimension>::computeStress(ElementType el_type,
 							      GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Real * damage      = this->damage(el_type, ghost_type).storage();
   Real * epsilon_equ = this->Ehat(el_type, ghost_type).storage();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   MaterialMazars<spatial_dimension>::computeStressOnQuad(grad_u, sigma,
 							 *damage,
 							 *epsilon_equ);
   ++damage;
   ++epsilon_equ;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialMazarsNonLocal<spatial_dimension>::computeNonLocalStresses(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
   ByElementTypeReal nl_var("Non local variable", this->id);
-  this->initInternalVector(nl_var, 1);
+  this->initInternalVector(nl_var, 1, true);
   this->resizeInternalVector(nl_var);
 
   if(this->damage_in_compute_stress)
     this->weightedAvergageOnNeighbours(this->damage, nl_var, 1);
   else
     this->weightedAvergageOnNeighbours(this->Ehat, nl_var, 1);
 
   Mesh::type_iterator it = this->model->getFEM().getMesh().firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = this->model->getFEM().getMesh().lastType(spatial_dimension, ghost_type);
   for(; it != last_type; ++it) {
     this->computeNonLocalStress(nl_var(*it, ghost_type), *it, ghost_type);
   }
 
   this->updateDissipatedEnergy(ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialMazarsNonLocal<spatial_dimension>::computeNonLocalStress(Vector<Real> & non_loc_var,
 								      ElementType el_type,
 								      GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Real * damage;
   Real * epsilon_equ;
   if(this->damage_in_compute_stress){
     damage      = non_loc_var.storage();
     epsilon_equ = this->Ehat(el_type, ghost_type).storage();
   } else {
     damage      = this->damage(el_type, ghost_type).storage();
     epsilon_equ = non_loc_var.storage();
   }
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
   this->computeDamageAndStressOnQuad(grad_u, sigma, *damage, *epsilon_equ);
 
   ++damage;
   ++epsilon_equ;
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 bool MaterialMazarsNonLocal<spatial_dimension>::parseParam(const std::string & key,
 							 const std::string & value,
 							 const ID & id) {
   std::stringstream sstr(value);
   if(key == "average_on_damage") { sstr >> this->damage_in_compute_stress; }
   else {
   return MaterialNonLocalParent::parseParam(key, value, id) ||
     MaterialMazars<spatial_dimension>::parseParam(key, value, id);
   }
 
   return true;
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialMazarsNonLocal<spatial_dimension>::printself(std::ostream & stream,
 							  int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   stream << space << "MaterialMazarsNonLocal [" << std::endl;
 
   if(this->damage_in_compute_stress)
     stream << space << " + Average on damage" << std::endl;
   else 
     stream << space << " + Average on Ehat" << std::endl;
 
   MaterialMazars<spatial_dimension>::printself(stream, indent + 1);
   MaterialNonLocalParent::printself(stream, indent + 1);
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 
 INSTANSIATE_MATERIAL(MaterialMazarsNonLocal);
 
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/materials/material_damage/material_vreepeerlings.cc b/src/model/solid_mechanics/materials/material_damage/material_vreepeerlings.cc
index 4f4ac94fe..234b5f1ab 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_vreepeerlings.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_vreepeerlings.cc
@@ -1,207 +1,205 @@
 /**
  * @file   material_vreepeerlings.cc
  * @author Cyprien Wolff <cyprien.wolff@epfl.ch>
  * @date   Fri Feb 17 14:00:00 2012
  *
  * @brief  Specialization of the material class for the VreePeerlings material
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_vreepeerlings.hh"
 #include "solid_mechanics_model.hh"
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 MaterialVreePeerlings<spatial_dimension>::MaterialVreePeerlings(SolidMechanicsModel & model,
 					     const ID & id)  :
   Material(model, id),
   MaterialDamage<spatial_dimension>(model, id),
   Kapa("Kapa",id),
   strain_rate_vreepeerlings("strain-rate-vreepeerlings", id),
   critical_strain("critical-strain", id)
  {
   AKANTU_DEBUG_IN();
 
   this->registerParam("Kapa0i"          , Kapa0i          , 0.0001, _pat_parsable);
   this->registerParam("Kapa0"           , Kapa0           , 0.0001, _pat_parsable);
   this->registerParam("Alpha"           , Alpha           , 0.99  , _pat_parsable);
   this->registerParam("Beta"            , Beta            , 300.  , _pat_parsable);
   this->registerParam("Kct"             , Kct             , 1.    , _pat_parsable);
   this->registerParam("Kapa0_randomness", Kapa0_randomness, 0.    , _pat_parsable);
 
   firststep = true;
   countforinitialstep= 0;
 
   this->initInternalVector(this->Kapa, 1);
   this->initInternalVector(this->critical_strain, 1);
   this->initInternalVector(this->strain_rate_vreepeerlings, spatial_dimension * spatial_dimension);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialVreePeerlings<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
   MaterialDamage<spatial_dimension>::initMaterial();
 
   this->resizeInternalVector(this->Kapa);
   this->resizeInternalVector(this->critical_strain);
   this->resizeInternalVector(this->strain_rate_vreepeerlings);
 
   const Mesh & mesh = this->model->getFEM().getMesh();
 
   Mesh::type_iterator it = mesh.firstType(spatial_dimension);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension);
 
   for(; it != last_type; ++it) {
     Vector <Real>::iterator<Real> kapa_it  = Kapa(*it).begin();
     Vector <Real>::iterator<Real> kapa_end = Kapa(*it).end();
 
     for(; kapa_it != kapa_end; ++kapa_it) {
       Real rand_part = (2 * drand48()-1) * Kapa0_randomness * Kapa0i;
       *kapa_it = Kapa0i + rand_part;
     }
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialVreePeerlings<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Real * dam = this->damage(el_type, ghost_type).storage();
   Real * Kapaq = Kapa(el_type, ghost_type).storage();
   Real * crit_strain = critical_strain(el_type, ghost_type).storage();
   Real dt = this->model->getTimeStep();
 
   Vector<UInt> & elem_filter = this->element_filter(el_type, ghost_type);
   Vector<Real> & velocity = this->model->getVelocity();
   Vector<Real> & strain_rate_vrplgs = this->strain_rate_vreepeerlings(el_type, ghost_type); 
 
   this->model->getFEM().gradientOnQuadraturePoints(velocity, strain_rate_vrplgs,
 						   spatial_dimension,
 						   el_type, ghost_type, &elem_filter);
 
   Vector<Real>::iterator<types::Matrix> strain_rate_vrplgs_it =
         strain_rate_vrplgs.begin(spatial_dimension, spatial_dimension);
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Real Equistrain;
   Real Equistrain_rate;
   types::Matrix & strain_rate = *strain_rate_vrplgs_it;
 
   computeStressOnQuad(grad_u, sigma, *dam, Equistrain, Equistrain_rate, *Kapaq, dt, strain_rate, *crit_strain);
   ++dam;
   ++Kapaq;
   ++strain_rate_vrplgs_it;
   ++crit_strain;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   if(!this->is_non_local) this->updateDissipatedEnergy(ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension>
-UInt MaterialVreePeerlings<spatial_dimension>::getNbDataToPack(const Element & element,
-					    SynchronizationTag tag) const {
-  AKANTU_DEBUG_IN();
-
-  UInt size = 0;
-  if(tag == _gst_smm_init_mat) {
-    UInt nb_quad = this->model->getFEM().getNbQuadraturePoints(element.type);
-    size += sizeof(Real) + nb_quad;
-  }
-
-  size += MaterialDamage<spatial_dimension>::getNbDataToPack(element, tag);
-
-  AKANTU_DEBUG_OUT();
-  return size;
-}
-
-/* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension>
-UInt MaterialVreePeerlings<spatial_dimension>::getNbDataToUnpack(const Element & element,
-					      SynchronizationTag tag) const {
-  AKANTU_DEBUG_IN();
-
-  UInt size = 0;
-  if(tag == _gst_smm_init_mat) {
-    UInt nb_quad = this->model->getFEM().getNbQuadraturePoints(element.type);
-    size += sizeof(Real) + nb_quad;
-  }
-
-  size += MaterialDamage<spatial_dimension>::getNbDataToPack(element, tag);
-
-  AKANTU_DEBUG_OUT();
-  return size;
-}
-
-/* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension>
-void MaterialVreePeerlings<spatial_dimension>::packData(CommunicationBuffer & buffer,
-				     const Element & element,
-				     SynchronizationTag tag) const {
-  AKANTU_DEBUG_IN();
-
-  if(tag == _gst_smm_init_mat){
-    UInt nb_quad = this->model->getFEM().getNbQuadraturePoints(element.type);
-    const Vector<Real> & kapa = Kapa(element.type, _not_ghost);
-    for(UInt q = 0; q < nb_quad; ++q)
-      buffer << kapa(element.element * nb_quad + q);
-  }
-
-  MaterialDamage<spatial_dimension>::packData(buffer, element, tag);
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension>
-void MaterialVreePeerlings<spatial_dimension>::unpackData(CommunicationBuffer & buffer,
-				       const Element & element,
-				       SynchronizationTag tag) {
-  AKANTU_DEBUG_IN();
-
-  if(tag == _gst_smm_init_mat) {
-    UInt nb_quad = this->model->getFEM().getNbQuadraturePoints(element.type);
-    Vector<Real> & kapa = Kapa(element.type, _not_ghost);
-    for(UInt q = 0; q < nb_quad; ++q)
-      buffer >> kapa(element.element * nb_quad + q);
-  }
-
-  MaterialDamage<spatial_dimension>::packData(buffer, element, tag);
-  AKANTU_DEBUG_OUT();
-}
+//UInt MaterialVreePeerlings<spatial_dimension>::getNbDataToPack(const Element & element,
+//					    SynchronizationTag tag) const {
+//  AKANTU_DEBUG_IN();
+//   UInt size = 0;
+//   if(tag == _gst_smm_init_mat) {
+//     UInt nb_quad = this->model->getFEM().getNbQuadraturePoints(element.type);
+//     size += sizeof(Real) + nb_quad;
+//   }
+
+//   size += MaterialDamage<spatial_dimension>::getNbDataToPack(element, tag);
+
+//   AKANTU_DEBUG_OUT();
+//   return size;
+// }
+
+// /* -------------------------------------------------------------------------- */
+// template<UInt spatial_dimension>
+// UInt MaterialVreePeerlings<spatial_dimension>::getNbDataToUnpack(const Element & element,
+// 					      SynchronizationTag tag) const {
+//   AKANTU_DEBUG_IN();
+
+//   UInt size = 0;
+//   if(tag == _gst_smm_init_mat) {
+//     UInt nb_quad = this->model->getFEM().getNbQuadraturePoints(element.type);
+//     size += sizeof(Real) + nb_quad;
+//   }
+
+//   size += MaterialDamage<spatial_dimension>::getNbDataToPack(element, tag);
+
+//   AKANTU_DEBUG_OUT();
+//   return size;
+// }
+
+// /* -------------------------------------------------------------------------- */
+// template<UInt spatial_dimension>
+// void MaterialVreePeerlings<spatial_dimension>::packData(CommunicationBuffer & buffer,
+// 				     const Element & element,
+// 				     SynchronizationTag tag) const {
+//   AKANTU_DEBUG_IN();
+
+//   if(tag == _gst_smm_init_mat){
+//     UInt nb_quad = this->model->getFEM().getNbQuadraturePoints(element.type);
+//     const Vector<Real> & kapa = Kapa(element.type, _not_ghost);
+//     for(UInt q = 0; q < nb_quad; ++q)
+//       buffer << kapa(element.element * nb_quad + q);
+//   }
+
+//   MaterialDamage<spatial_dimension>::packData(buffer, element, tag);
+//   AKANTU_DEBUG_OUT();
+// }
+
+// /* -------------------------------------------------------------------------- */
+// template<UInt spatial_dimension>
+// void MaterialVreePeerlings<spatial_dimension>::unpackData(CommunicationBuffer & buffer,
+// 				       const Element & element,
+// 				       SynchronizationTag tag) {
+//   AKANTU_DEBUG_IN();
+
+//   if(tag == _gst_smm_init_mat) {
+//     UInt nb_quad = this->model->getFEM().getNbQuadraturePoints(element.type);
+//     Vector<Real> & kapa = Kapa(element.type, _not_ghost);
+//     for(UInt q = 0; q < nb_quad; ++q)
+//       buffer >> kapa(element.element * nb_quad + q);
+//   }
+
+//   MaterialDamage<spatial_dimension>::packData(buffer, element, tag);
+//   AKANTU_DEBUG_OUT();
+// }
 
 /* -------------------------------------------------------------------------- */
 INSTANSIATE_MATERIAL(MaterialVreePeerlings);
 
 
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/materials/material_damage/material_vreepeerlings.hh b/src/model/solid_mechanics/materials/material_damage/material_vreepeerlings.hh
index b8015c671..0185d49b5 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_vreepeerlings.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_vreepeerlings.hh
@@ -1,170 +1,146 @@
 /**
  * @file   material_vreepeerlings.hh
  * @author Cyprien Wolff <cyprien.wolff@epfl.ch>
  * @date   Fri Feb 17 14:00:00 2012
  *
  * @brief  Specialization of the material class for the VreePeerlings material
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "material.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_VREEPEERLINGS_HH__
 #define __AKANTU_MATERIAL_VREEPEERLINGS_HH__
 
 __BEGIN_AKANTU__
 
 /**
  * Material vreepeerlings
  *
  * parameters in the material files :
  *   - Kapa0i  : (default: 0.0001) Initial threshold (of the equivalent strain) for the initial step
  *   - Kapa0  : (default: 0.0001) Initial threshold (of the equivalent strain)
  *   - Alpha  : (default: 0.99) Fitting parameter (must be close to 1 to do tend to 0 the stress in the damaged element)
  *   - Beta   : (default: 300) This parameter determines the rate at which the damage grows 
  *   - Kct    : (default: 1) Ratio between compressive and tensile strength
  *   - Kapa0_randomness  : (default:0) Kapa random internal variable
  */
 template<UInt spatial_dimension>
 class MaterialVreePeerlings : public MaterialDamage<spatial_dimension> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   MaterialVreePeerlings(SolidMechanicsModel & model, const ID & id = "");
 
   virtual ~MaterialVreePeerlings() {};
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   void initMaterial();
 
   /// constitutive law for all element of a type
   void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
 
 protected:
   /// constitutive law for a given quadrature point
   inline void computeStressOnQuad(types::Matrix & F,
 				  types::Matrix & sigma,
 				  Real & dam,
 				  Real & Equistrain_rate,
 				  Real & Equistrain,
 				  Real & Kapaq,
 				  Real dt,
 				  types::Matrix & strain_rate_vrpgls,
 				  Real & crit_strain);
 
   inline void computeDamageAndStressOnQuad(types::Matrix & sigma,
 					   Real & dam,
 					   Real & Equistrain_rate,
 					   Real & Equistrain,
 					   Real & Kapaq,
 					   Real dt,
 					   Real & crit_strain);
 
   /* ------------------------------------------------------------------------ */
   /* DataAccessor inherited members                                           */
   /* ------------------------------------------------------------------------ */
 public:
 
-  virtual UInt getNbDataToPack(const Element & element,
-			       SynchronizationTag tag) const;
-
-  virtual UInt getNbDataToUnpack(const Element & element,
-				 SynchronizationTag tag) const;
-
-  virtual void packData(CommunicationBuffer & buffer,
-			const Element & element,
-			SynchronizationTag tag) const;
-
-  virtual void unpackData(CommunicationBuffer & buffer,
-			  const Element & element,
-			  SynchronizationTag tag);
-
-  virtual UInt getNbDataToPack(SynchronizationTag tag) const { return MaterialDamage<spatial_dimension>::getNbDataToPack(tag); }
-  virtual UInt getNbDataToUnpack(SynchronizationTag tag) const { return MaterialDamage<spatial_dimension>::getNbDataToUnpack(tag); }
-  virtual void packData(CommunicationBuffer & buffer,
-			const UInt index,
-			SynchronizationTag tag) const { MaterialDamage<spatial_dimension>::packData(buffer, index, tag); }
-  virtual void unpackData(CommunicationBuffer & buffer,
-			  const UInt index,
-			  SynchronizationTag tag) { MaterialDamage<spatial_dimension>::unpackData(buffer, index, tag); }
-
-
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// Initial threshold (of the equivalent strain) (used in the initial step)
   Real Kapa0i;
 
   /// Initial threshold (of the equivalent strain)
   Real Kapa0;
 
   /// Fitting parameter (must be close to 1 to do tend to 0 the stress in the damaged element)
   Real Alpha;
 
   /// This parameter determines the rate at which the damage grows 
   Real Beta;
 
   /// Ratio between compressive and tensile strength
   Real Kct;
 
   /// randomness on Kapa0
   Real Kapa0_randomness;
 
   /// Kapa random internal variable
   ByElementTypeReal Kapa;
 
   /// strain_rate_vreepeerlings
   ByElementTypeReal strain_rate_vreepeerlings;
 
  /// strain_critical_vreepeerlings
   ByElementTypeReal critical_strain;
 
   /// Booleen to check the first step
   bool firststep;
 
   /// counter for initial step
   Int countforinitialstep;
 };
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 #include "material_vreepeerlings_inline_impl.cc"
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MATERIAL_VREEPEERLINGS_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_non_local.hh b/src/model/solid_mechanics/materials/material_non_local.hh
index 848387079..7044a9fac 100644
--- a/src/model/solid_mechanics/materials/material_non_local.hh
+++ b/src/model/solid_mechanics/materials/material_non_local.hh
@@ -1,215 +1,199 @@
 /**
  * @file   material_non_local.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Jul 28 11:17:41 2011
  *
  * @brief  Material class that handle the non locality of a law for example damage.
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "material.hh"
 #include "aka_grid.hh"
 #include "fem.hh"
 
 #include "weight_function.hh"
 
 namespace akantu {
   class GridSynchronizer;
 }
 
 /* -------------------------------------------------------------------------- */
 #ifndef __AKANTU_MATERIAL_NON_LOCAL_HH__
 #define __AKANTU_MATERIAL_NON_LOCAL_HH__
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim, template <UInt> class WeightFunction = BaseWeightFunction>
 class MaterialNonLocal : public virtual Material {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   MaterialNonLocal(SolidMechanicsModel & model, const ID & id = "");
   virtual ~MaterialNonLocal();
 
   template<typename T>
   class PairList : public ByElementType<ByElementTypeVector<T> > {};
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// read properties
   virtual bool parseParam(const std::string & key, const std::string & value,
 			  const ID & id);
 
   /// initialize the material computed parameter
   virtual void initMaterial();
 
   // void computeQuadraturePointsNeighborhoudVolumes(ByElementTypeReal & volumes) const;
 
   virtual void updateResidual(GhostType ghost_type);
 
   virtual void computeAllNonLocalStresses(GhostType ghost_type = _not_ghost);
 
   // void removeDamaged(const ByElementTypeReal & damage, Real thresold);
 
   void savePairs(const std::string & filename) const;
   void neighbourhoodStatistics(const std::string & filename) const;
 
 protected:
   void updatePairList(const ByElementTypeReal & quadrature_points_coordinates);
 
   void computeWeights(const ByElementTypeReal & quadrature_points_coordinates);
 
   void createCellList(ByElementTypeReal & quadrature_points_coordinates);
 
+  void cleanupExtraGhostElement(const ByElementType<UInt> & nb_ghost_protected);
+
   void fillCellList(const ByElementTypeReal & quadrature_points_coordinates,
 		    const GhostType & ghost_type);
 
   /// constitutive law
   virtual void computeNonLocalStresses(GhostType ghost_type = _not_ghost) = 0;
 
   template<typename T>
   void weightedAvergageOnNeighbours(const ByElementTypeVector<T> & to_accumulate,
 				    ByElementTypeVector<T> & accumulated,
 				    UInt nb_degree_of_freedom,
 				    GhostType ghost_type2 = _not_ghost) const;
 
 
   // template<typename T>
   // void accumulateOnNeighbours(const ByElementTypeVector<T> & to_accumulate,
   // 			      ByElementTypeVector<T> & accumulated,
   // 			      UInt nb_degree_of_freedom) const;
 
 
-  virtual inline UInt getNbDataToPack(const Element & element,
-				      SynchronizationTag tag) const;
-
-  virtual inline UInt getNbDataToUnpack(const Element & element,
-					SynchronizationTag tag) const;
-
-  virtual inline void packData(CommunicationBuffer & buffer,
-			       const Element & element,
-			       SynchronizationTag tag) const;
-
-  virtual inline void unpackData(CommunicationBuffer & buffer,
-				 const Element & element,
-				 SynchronizationTag tag);
+  virtual inline UInt getNbDataForElements(const Vector<Element> & elements,
+					  SynchronizationTag tag) const;
 
-  virtual UInt getNbDataToPack(SynchronizationTag tag) const { return Material::getNbDataToPack(tag); }
-  virtual UInt getNbDataToUnpack(SynchronizationTag tag) const { return Material::getNbDataToUnpack(tag); }
-
-  virtual void packData(CommunicationBuffer & buffer,
-			const UInt index,
-			SynchronizationTag tag) const {
-    Material::packData(buffer, index, tag);
-  }
+  virtual inline void packElementData(CommunicationBuffer & buffer,
+				      const Vector<Element> & elements,
+				      SynchronizationTag tag) const;
 
-  virtual void unpackData(CommunicationBuffer & buffer,
-			const UInt index,
-			SynchronizationTag tag) {
-    Material::unpackData(buffer, index, tag);
-  }
+  virtual inline void unpackElementData(CommunicationBuffer & buffer,
+					const Vector<Element> & elements,
+					SynchronizationTag tag);
 
 
   virtual inline void onElementsAdded(const Vector<Element> & element_list);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   void registerNonLocalVariable(ByElementTypeReal & local,
 				ByElementTypeReal & non_local,
 				UInt nb_degree_of_freedom) {
     ID id = local.getID();
     NonLocalVariable & non_local_variable = non_local_variables[id];
 
     non_local_variable.local_variable = &local;
     non_local_variable.non_local_variable = &non_local;
     non_local_variable.non_local_variable_nb_component = nb_degree_of_freedom;
   }
 
   AKANTU_GET_MACRO(PairList, pair_list, const PairList<UInt> &)
 
   AKANTU_GET_MACRO(Radius, radius, Real);
 
   AKANTU_GET_MACRO(CellList, *cell_list, const RegularGrid<QuadraturePoint> &)
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// the non local radius
   Real radius;
 
   /// the weight function used
   WeightFunction<dim> * weight_func;
 
 private:
   /// the pairs of quadrature points
   PairList<UInt> pair_list;
   /// the weights associated to the pairs
   PairList<Real> pair_weight;
 
   /// the regular grid to construct/update the pair lists
   RegularGrid<QuadraturePoint> * cell_list;
 
   /// the types of the existing pairs
   typedef std::set< std::pair<ElementType, ElementType> > pair_type;
   pair_type existing_pairs[2];
 
   /// specify if the weights should be updated and at which rate
   UInt update_weights;
 
   /// count the number of calls of computeStress
   UInt compute_stress_calls;
 
   struct NonLocalVariable {
     ByElementTypeVector<Real> * local_variable;
     ByElementTypeVector<Real> * non_local_variable;
     UInt non_local_variable_nb_component;
   };
 
   std::map<ID, NonLocalVariable> non_local_variables;
 
   bool is_creating_grid;
 
   GridSynchronizer * grid_synchronizer;
 
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 #include "material_non_local_inline_impl.cc"
 
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MATERIAL_NON_LOCAL_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc b/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc
index 99e7af095..a35e74e0f 100644
--- a/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc
+++ b/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc
@@ -1,761 +1,877 @@
 /**
  * @file   material_non_local_inline_impl.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Aug 25 11:59:39 2011
  *
  * @brief
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 __END_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 #include "aka_types.hh"
 #include "grid_synchronizer.hh"
 #include "synchronizer_registry.hh"
 #include "integrator.hh"
 /* -------------------------------------------------------------------------- */
 #include <iostream>
 #include <fstream>
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt DIM, template <UInt> class WeightFunction>
 MaterialNonLocal<DIM, WeightFunction>::MaterialNonLocal(SolidMechanicsModel & model,
 							const ID & id)  :
   Material(model, id), radius(100.), weight_func(NULL), cell_list(NULL),
   update_weights(0), compute_stress_calls(0), is_creating_grid(false), grid_synchronizer(NULL) {
   AKANTU_DEBUG_IN();
 
-
   this->registerParam("radius"         , radius        , 100., _pat_readable  , "Non local radius");
   this->registerParam("UpdateWeights"  , update_weights, 0U  , _pat_modifiable, "Update weights frequency");
   this->registerParam("Weight function", weight_func   ,       _pat_internal);
 
   this->is_non_local = true;
 
   this->weight_func = new WeightFunction<DIM>(*this);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 MaterialNonLocal<spatial_dimension, WeightFunction>::~MaterialNonLocal() {
   AKANTU_DEBUG_IN();
 
   delete cell_list;
   delete weight_func;
   delete grid_synchronizer;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::initMaterial() {
   AKANTU_DEBUG_IN();
   //  Material::initMaterial();
   Mesh & mesh = this->model->getFEM().getMesh();
 
   ByElementTypeReal quadrature_points_coordinates("quadrature_points_coordinates_tmp_nl", id);
-  mesh.initByElementTypeVector(quadrature_points_coordinates, spatial_dimension, 0);
+  this->initInternalVector(quadrature_points_coordinates, spatial_dimension, true);
   computeQuadraturePointsCoordinates(quadrature_points_coordinates, _not_ghost);
 
+  ByElementType<UInt> nb_ghost_protected;
+  Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost);
+  Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _ghost);
+  for(; it != last_type; ++it)
+    nb_ghost_protected(mesh.getNbElement(*it, _ghost), *it, _ghost);
+
+
   createCellList(quadrature_points_coordinates);
   updatePairList(quadrature_points_coordinates);
-  computeWeights(quadrature_points_coordinates);
+
+  cleanupExtraGhostElement(nb_ghost_protected);
 
   weight_func->setRadius(radius);
   weight_func->init();
 
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension, template <UInt> class WeightFunction>
-void MaterialNonLocal<spatial_dimension, WeightFunction>::updateResidual(GhostType ghost_type) {
-  AKANTU_DEBUG_IN();
-
-  // Update the weights for the non local variable averaging
-  if(ghost_type == _not_ghost &&
-     this->update_weights &&
-     (this->compute_stress_calls % this->update_weights == 0)) {
-    ByElementTypeReal quadrature_points_coordinates("quadrature_points_coordinates", id);
-    Mesh & mesh = this->model->getFEM().getMesh();
-    mesh.initByElementTypeVector(quadrature_points_coordinates, spatial_dimension, 0);
-    computeQuadraturePointsCoordinates(quadrature_points_coordinates, _not_ghost);
-    computeQuadraturePointsCoordinates(quadrature_points_coordinates, _ghost);
-    computeWeights(quadrature_points_coordinates);
-  }
-  if(ghost_type == _not_ghost) ++this->compute_stress_calls;
-
-  computeAllStresses(ghost_type);
-
-  computeNonLocalStresses(ghost_type);
-  assembleResidual(ghost_type);
+  computeWeights(quadrature_points_coordinates);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
-void MaterialNonLocal<spatial_dimension, WeightFunction>::computeAllNonLocalStresses(GhostType ghost_type) {
-  // Update the weights for the non local variable averaging
-  if(ghost_type == _not_ghost) {
-    if(this->update_weights && (this->compute_stress_calls % this->update_weights == 0)) {
-      this->model->getSynchronizerRegistry().asynchronousSynchronize(_gst_mnl_weight);
+void MaterialNonLocal<spatial_dimension, WeightFunction>::cleanupExtraGhostElement(const ByElementType<UInt> & nb_ghost_protected) {
+  AKANTU_DEBUG_IN();
 
-      ByElementTypeReal quadrature_points_coordinates("quadrature_points_coordinates", id);
-      Mesh & mesh = this->model->getFEM().getMesh();
-      mesh.initByElementTypeVector(quadrature_points_coordinates, spatial_dimension, 0);
-      computeQuadraturePointsCoordinates(quadrature_points_coordinates, _not_ghost);
-      computeQuadraturePointsCoordinates(quadrature_points_coordinates, _ghost);
+  // Create list of element to keep
+  std::set<Element> relevant_ghost_element;
 
-      this->model->getSynchronizerRegistry().waitEndSynchronize(_gst_mnl_weight);
+  pair_type::const_iterator first_pair_types = existing_pairs[1].begin();
+  pair_type::const_iterator last_pair_types = existing_pairs[1].end();
+  for (; first_pair_types != last_pair_types; ++first_pair_types) {
+    ElementType type2 = first_pair_types->second;
+    GhostType ghost_type2 = _ghost;
+    UInt nb_quad2 = this->model->getFEM().getNbQuadraturePoints(type2);
+    Vector<UInt> & elem_filter = element_filter(type2, ghost_type2);
 
-      computeWeights(quadrature_points_coordinates);
+    const Vector<UInt> & pairs =
+      pair_list(first_pair_types->first, _not_ghost)(first_pair_types->second, ghost_type2);
+    Vector<UInt>::const_iterator< types::Vector<UInt> > first_pair = pairs.begin(2);
+    Vector<UInt>::const_iterator< types::Vector<UInt> > last_pair  = pairs.end(2);
+    for(;first_pair != last_pair; ++first_pair) {
+      UInt _q2 = (*first_pair)(1);
+      QuadraturePoint q2(type2, elem_filter(_q2 / nb_quad2), _q2 % nb_quad2, ghost_type2);
+      relevant_ghost_element.insert(q2);
     }
+  }
 
-    typename std::map<ID, NonLocalVariable>::iterator it = non_local_variables.begin();
-    typename std::map<ID, NonLocalVariable>::iterator end = non_local_variables.end();
-    for(;it != end; ++it) {
-      NonLocalVariable & non_local_variable = it->second;
+  // Create list of element to remove and new numbering for element to keep
+  Mesh & mesh = this->model->getFEM().getMesh();
+  std::set<Element> ghost_to_erase;
 
-      resizeInternalVector(*non_local_variable.non_local_variable);
-      this->weightedAvergageOnNeighbours(*non_local_variable.local_variable, *non_local_variable.non_local_variable,
-					 non_local_variable.non_local_variable_nb_component, _not_ghost);
-    }
+  Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost);
+  Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _ghost);
 
-    ++this->compute_stress_calls;
-  } else {
+  RemovedElementsEvent remove_elem(mesh);
 
-    typename std::map<ID, NonLocalVariable>::iterator it = non_local_variables.begin();
-    typename std::map<ID, NonLocalVariable>::iterator end = non_local_variables.end();
-    for(;it != end; ++it) {
-      NonLocalVariable & non_local_variable = it->second;
-      this->weightedAvergageOnNeighbours(*non_local_variable.local_variable, *non_local_variable.non_local_variable,
-					 non_local_variable.non_local_variable_nb_component, _ghost);
+  Element element;
+  element.ghost_type = _ghost;
+  for(; it != last_type; ++it) {
+    element.type = *it;
+    UInt nb_ghost_elem = mesh.getNbElement(*it, _ghost);
+    UInt nb_ghost_elem_protected = 0;
+    try {
+      nb_ghost_elem_protected = nb_ghost_protected(*it, _ghost);
+    } catch (...) {}
+
+    if(!remove_elem.getNewNumbering().exists(*it, _ghost))
+      remove_elem.getNewNumbering().alloc(nb_ghost_elem, 1, *it, _ghost);
+
+    Vector<UInt> & elem_filter = element_filter(*it, _ghost);
+    Vector<UInt> & new_numbering = remove_elem.getNewNumbering(*it, _ghost);
+    UInt ng = 0;
+    for (UInt g = 0; g < nb_ghost_elem; ++g) {
+      element.element = elem_filter(g);
+      if(element.element >= nb_ghost_elem_protected &&
+	 (std::find(relevant_ghost_element.begin(),
+		    relevant_ghost_element.end(),
+		    element) == relevant_ghost_element.end())) {
+	ghost_to_erase.insert(element);
+	remove_elem.getList().push_back(element);
+
+	new_numbering(g) = UInt(-1);
+      } else {
+	new_numbering(g) = ng;
+	++ng;
+      }
     }
-
-    computeNonLocalStresses(_not_ghost);
   }
-}
 
-/* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension, template <UInt> class WeightFunction>
-template<typename T>
-void MaterialNonLocal<spatial_dimension, WeightFunction>::weightedAvergageOnNeighbours(const ByElementTypeVector<T> & to_accumulate,
-										       ByElementTypeVector<T> & accumulated,
-										       UInt nb_degree_of_freedom,
-										       GhostType ghost_type2) const {
-  AKANTU_DEBUG_IN();
-
-  UInt existing_pairs_num = 0;
-  if (ghost_type2 == _ghost) existing_pairs_num = 1;
-
-  pair_type::const_iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
-  pair_type::const_iterator last_pair_types = existing_pairs[existing_pairs_num].end();
-
-  GhostType ghost_type1 = _not_ghost; // does not make sens the ghost vs ghost so this should always by _not_ghost
+  mesh.sendEvent(remove_elem);
 
+  // Renumber element to keep
+  first_pair_types = existing_pairs[1].begin();
+  last_pair_types = existing_pairs[1].end();
   for (; first_pair_types != last_pair_types; ++first_pair_types) {
-    const Vector<UInt> & pairs =
-      pair_list(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2);
-    const Vector<Real> & weights =
-      pair_weight(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2);
-
-
-    const Vector<T> & to_acc = to_accumulate(first_pair_types->second, ghost_type2);
-    Vector<T> & acc = accumulated(first_pair_types->first, ghost_type1);
-
-    Vector<UInt>::const_iterator< types::Vector<UInt> > first_pair = pairs.begin(2);
-    Vector<UInt>::const_iterator< types::Vector<UInt> > last_pair  = pairs.end(2);
-    Vector<Real>::const_iterator< types::Vector<Real> > pair_w = weights.begin(2);
-
-    for(;first_pair != last_pair; ++first_pair, ++pair_w) {
-      UInt q1 = (*first_pair)(0);
-      UInt q2 = (*first_pair)(1);
-      for(UInt d = 0; d < nb_degree_of_freedom; ++d){
-	acc(q1, d) += (*pair_w)(0) * to_acc(q2, d);
-	if(ghost_type2 != _ghost) acc(q2, d) += (*pair_w)(1) * to_acc(q1, d);
-      }
+    ElementType type2 = first_pair_types->second;
+    GhostType ghost_type2 = _ghost;
+    UInt nb_quad2 = this->model->getFEM().getNbQuadraturePoints(type2);
+
+    Vector<UInt> & pairs =
+      pair_list(first_pair_types->first, _not_ghost)(first_pair_types->second, ghost_type2);
+    Vector<UInt>::iterator< types::Vector<UInt> > first_pair = pairs.begin(2);
+    Vector<UInt>::iterator< types::Vector<UInt> > last_pair  = pairs.end(2);
+    for(;first_pair != last_pair; ++first_pair) {
+      UInt _q2 = (*first_pair)(1);
+      Vector<UInt> & new_numbering = remove_elem.getNewNumbering(type2, ghost_type2);
+      UInt el = _q2 / nb_quad2;
+      UInt new_el = new_numbering(el);
+      (*first_pair)(1) = new_el * nb_quad2 + _q2 % nb_quad2;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::createCellList(ByElementTypeReal & quadrature_points_coordinates) {
   AKANTU_DEBUG_IN();
 
   const Real safety_factor = 1.2; // for the cell grid spacing
   Mesh & mesh = this->model->getFEM().getMesh();
   mesh.computeBoundingBox();
 
   Real lower_bounds[spatial_dimension];
   Real upper_bounds[spatial_dimension];
   mesh.getLocalLowerBounds(lower_bounds);
   mesh.getLocalUpperBounds(upper_bounds);
 
   Real spacing[spatial_dimension];
   for (UInt i = 0; i < spatial_dimension; ++i) {
     spacing[i] = radius * safety_factor;
   }
 
   cell_list = new RegularGrid<QuadraturePoint>(spatial_dimension,
 					       lower_bounds,
 					       upper_bounds,
 					       spacing);
 
 
   fillCellList(quadrature_points_coordinates, _not_ghost);
 
   is_creating_grid = true;
   SynchronizerRegistry & synch_registry = this->model->getSynchronizerRegistry();
   std::stringstream sstr; sstr << id << ":grid_synchronizer";
   grid_synchronizer = GridSynchronizer::createGridSynchronizer(mesh,
 							       *cell_list,
 							       sstr.str());
   synch_registry.registerSynchronizer(*grid_synchronizer, _gst_mnl_for_average);
   synch_registry.registerSynchronizer(*grid_synchronizer, _gst_mnl_weight);
   is_creating_grid = false;
 
   this->computeQuadraturePointsCoordinates(quadrature_points_coordinates, _ghost);
   fillCellList(quadrature_points_coordinates, _ghost);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::fillCellList(const ByElementTypeReal & quadrature_points_coordinates,
 								       const GhostType & ghost_type) {
   Mesh & mesh = this->model->getFEM().getMesh();
-  QuadraturePoint q;
-  Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
-  Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type);
 
+  QuadraturePoint q;
   q.ghost_type = ghost_type;
+
+  Mesh::type_iterator it        = mesh.firstType(spatial_dimension, ghost_type);
+  Mesh::type_iterator last_type = mesh.lastType (spatial_dimension, ghost_type);
   for(; it != last_type; ++it) {
     Vector<UInt> & elem_filter = element_filter(*it, ghost_type);
     UInt nb_element = elem_filter.getSize();
     UInt nb_quad    = this->model->getFEM().getNbQuadraturePoints(*it, ghost_type);
 
     const Vector<Real> & quads = quadrature_points_coordinates(*it, ghost_type);
 
     q.type = *it;
 
     Vector<Real>::const_iterator<types::RVector> quad = quads.begin(spatial_dimension);
     UInt * elem = elem_filter.storage();
 
     for (UInt e = 0; e < nb_element; ++e) {
       q.element = *elem;
       for (UInt nq = 0; nq < nb_quad; ++nq) {
 	q.num_point = nq;
 	q.setPosition(*quad);
 	cell_list->insert(q, *quad);
 	++quad;
       }
       ++elem;
     }
   }
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::updatePairList(const ByElementTypeReal & quadrature_points_coordinates) {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh = this->model->getFEM().getMesh();
 
   GhostType ghost_type = _not_ghost;
 
   // generate the pair of neighbor depending of the cell_list
   Mesh::type_iterator it        = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type);
 
   for(; it != last_type; ++it) {
     // Preparing datas
     const Vector<Real> & quads = quadrature_points_coordinates(*it, ghost_type);
     Vector<Real>::const_iterator<types::RVector> first_quad = quads.begin(spatial_dimension);
     Vector<Real>::const_iterator<types::RVector> last_quad  = quads.end(spatial_dimension);
 
     ByElementTypeUInt & pairs = pair_list(ByElementTypeUInt("pairs", id, memory_id),
 					  *it,
 					  ghost_type);
 
     ElementType current_element_type = _not_defined;
     GhostType current_ghost_type = _casper;
     UInt existing_pairs_num = 0;
 
     Vector<UInt> * neighbors = NULL;
+    Vector<UInt> * element_index_material2 = NULL;
+    //Vector<UInt> & element_index_material1 = this->model->getElementIndexByMaterial(*it, ghost_type);
 
     UInt my_num_quad = 0;
 
     // loop over quad points
     for(;first_quad != last_quad; ++first_quad, ++my_num_quad) {
       RegularGrid<QuadraturePoint>::Cell cell = cell_list->getCell(*first_quad);
 
       RegularGrid<QuadraturePoint>::neighbor_cells_iterator first_neigh_cell =
       cell_list->beginNeighborCells(cell);
       RegularGrid<QuadraturePoint>::neighbor_cells_iterator last_neigh_cell =
       cell_list->endNeighborCells(cell);
 
       // loop over neighbors  cells of the one containing  the current quadrature
       // point
       for (; first_neigh_cell != last_neigh_cell; ++first_neigh_cell) {
 	RegularGrid<QuadraturePoint>::iterator first_neigh_quad =
 	cell_list->beginCell(*first_neigh_cell);
 	RegularGrid<QuadraturePoint>::iterator last_neigh_quad =
 	cell_list->endCell(*first_neigh_cell);
 
 	// loop over the quadrature point in the current cell of the cell list
 	for (;first_neigh_quad != last_neigh_quad; ++first_neigh_quad){
 	  QuadraturePoint & quad = *first_neigh_quad;
 	  UInt nb_quad_per_elem =  this->model->getFEM().getNbQuadraturePoints(quad.type, quad.ghost_type);
-	  UInt neigh_num_quad = quad.element * nb_quad_per_elem + quad.num_point;
 
 	  // little optimization to not search in the map at each quad points
 	  if(quad.type != current_element_type || quad.ghost_type != current_ghost_type) {
-	    //            neigh_quad_positions = quadrature_points_coordinates(quad.type,
-	    //                                                                 quad.ghost_type).storage();
 	    current_element_type = quad.type;
 	    current_ghost_type   = quad.ghost_type;
 	    existing_pairs_num = quad.ghost_type == _not_ghost ? 0 : 1;
 	    if(!pairs.exists(current_element_type, current_ghost_type)) {
 	      neighbors = &(pairs.alloc(0, 2,
 					current_element_type,
 					current_ghost_type));
 	    } else {
 	      neighbors = &(pairs(current_element_type,
 				  current_ghost_type));
 	    }
 	    existing_pairs[existing_pairs_num].insert(std::pair<ElementType, ElementType>(*it,
 											  current_element_type));
+	    element_index_material2 = &(this->model->getElementIndexByMaterial(current_element_type, current_ghost_type));
 	  }
 
-	  // types::RVector neigh_quad(neigh_quad_positions + neigh_num_quad * spatial_dimension,
-	  //                          spatial_dimension);
+	  UInt neigh_num_quad = (*element_index_material2)(quad.element) * nb_quad_per_elem +
+	    quad.num_point;
 	  const types::RVector & neigh_quad = quad.getPosition();
 
 	  Real distance = first_quad->distance(neigh_quad);
 	  if(distance <= radius &&
 	     (current_ghost_type == _ghost ||
 	      (current_ghost_type == _not_ghost && my_num_quad <= neigh_num_quad))) { // sotring only half lists
 	    UInt pair[2];
 	    pair[0] = my_num_quad;
 	    pair[1] = neigh_num_quad;
 
 	    neighbors->push_back(pair);
 	  }
-	  //      }
+
 	}
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::computeWeights(const ByElementTypeReal & quadrature_points_coordinates) {
   AKANTU_DEBUG_IN();
 
   GhostType ghost_type1;
   ghost_type1 = _not_ghost;
 
   ByElementTypeReal quadrature_points_volumes("quadrature_points_volumes", id, memory_id);
-  this->model->getFEM().getMesh().initByElementTypeVector(quadrature_points_volumes, 1, 0);
+  this->initInternalVector(quadrature_points_volumes, 1, true);
   resizeInternalVector(quadrature_points_volumes);
 
   const ByElementTypeReal & jacobians_by_type = this->model->getFEM().getIntegratorInterface().getJacobians();
 
   weight_func->updateInternals(quadrature_points_volumes);
 
   for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
     GhostType ghost_type2 = (GhostType) gt;
     UInt existing_pairs_num = gt - _not_ghost;
     pair_type::iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
     pair_type::iterator last_pair_types = existing_pairs[existing_pairs_num].end();
 
     // Compute the weights
     for (; first_pair_types != last_pair_types; ++first_pair_types) {
       ElementType type1 = first_pair_types->first;
       ElementType type2 = first_pair_types->second;
 
       const Vector<UInt> & pairs = pair_list(type1, ghost_type1)(type2, ghost_type2);
 
       std::string ghost_id = "";
       if (ghost_type1 == _ghost) ghost_id = ":ghost";
 
       ByElementTypeReal & weights_type_1 = pair_weight(type1, ghost_type1);
       std::stringstream sstr; sstr << id << ":pair_weight:" << type1 << ghost_id;
       weights_type_1.setID(sstr.str());
 
       Vector<Real> * tmp_weight = NULL;
       if(!weights_type_1.exists(type2, ghost_type2)) {
 	tmp_weight = &(weights_type_1.alloc(0, 2, type2, ghost_type2));
       } else {
 	tmp_weight = &(weights_type_1(type2, ghost_type2));
       }
       Vector<Real> & weights = *tmp_weight;
       weights.resize(pairs.getSize());
       weights.clear();
 
       const Vector<Real> & jacobians_1 = jacobians_by_type(type1, ghost_type1);
       const Vector<Real> & jacobians_2 = jacobians_by_type(type2, ghost_type2);
 
-      // const Vector<UInt> & elem_filter1 = element_filter(type1, ghost_type1);
-      // const Vector<UInt> & elem_filter2 = element_filter(type2, ghost_type2);
       UInt nb_quad1 = this->model->getFEM().getNbQuadraturePoints(type1);
       UInt nb_quad2 = this->model->getFEM().getNbQuadraturePoints(type2);
-      // UInt nb_tot_quad1 =  nb_quad1 * elem_filter1.getSize();;
-      // UInt nb_tot_quad2 =  nb_quad2 * elem_filter2.getSize();;
 
       Vector<Real> & quads_volumes1 = quadrature_points_volumes(type1, ghost_type1);
       Vector<Real> & quads_volumes2 = quadrature_points_volumes(type2, ghost_type2);
 
       Vector<Real>::const_iterator<types::RVector> iquads1;
       Vector<Real>::const_iterator<types::RVector> iquads2;
       iquads1 = quadrature_points_coordinates(type1, ghost_type1).begin(spatial_dimension);
       iquads2 = quadrature_points_coordinates(type2, ghost_type2).begin(spatial_dimension);
 
       Vector<UInt>::const_iterator< types::Vector<UInt> > first_pair = pairs.begin(2);
       Vector<UInt>::const_iterator< types::Vector<UInt> > last_pair  = pairs.end(2);
       Vector<Real>::iterator<types::RVector> weight  = weights.begin(2);
 
       this->weight_func->selectType(type1, ghost_type1, type2, ghost_type2);
 
       // Weight function
       for(;first_pair != last_pair; ++first_pair, ++weight) {
 	UInt _q1 = (*first_pair)(0);
 	UInt _q2 = (*first_pair)(1);
 	const types::RVector & pos1 = iquads1[_q1];
 	const types::RVector & pos2 = iquads2[_q2];
 	QuadraturePoint q1(_q1 / nb_quad1, _q1 % nb_quad1, _q1, pos1, type1, ghost_type1);
 	QuadraturePoint q2(_q2 / nb_quad2, _q2 % nb_quad2, _q2, pos2, type2, ghost_type2);
 
 	Real r = pos1.distance(pos2);
 
 	Real w2J2 = jacobians_2(_q2);
 	(*weight)(0) = w2J2 * this->weight_func->operator()(r, q1, q2);
 	if(ghost_type2 != _ghost && _q1 != _q2) {
 	  Real w1J1 = jacobians_1(_q1);
 	  (*weight)(1) = w1J1 * this->weight_func->operator()(r, q2, q1);
 	} else
 	  (*weight)(1) = 0;
 
 	quads_volumes1(_q1) += (*weight)(0);
 	if(ghost_type2 != _ghost) quads_volumes2(_q2) += (*weight)(1);
       }
     }
   }
 
   //normalize the weights
   for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
     GhostType ghost_type2 = (GhostType) gt;
     UInt existing_pairs_num = gt - _not_ghost;
     pair_type::iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
     pair_type::iterator last_pair_types = existing_pairs[existing_pairs_num].end();
 
     first_pair_types = existing_pairs[existing_pairs_num].begin();
     for (; first_pair_types != last_pair_types; ++first_pair_types) {
       ElementType type1 = first_pair_types->first;
       ElementType type2 = first_pair_types->second;
 
       const Vector<UInt> & pairs = pair_list(type1, ghost_type1)(type2, ghost_type2);
       Vector<Real> & weights = pair_weight(type1, ghost_type1)(type2, ghost_type2);
 
       Vector<Real> & quads_volumes1 = quadrature_points_volumes(type1, ghost_type1);
       Vector<Real> & quads_volumes2 = quadrature_points_volumes(type2, ghost_type2);
 
       Vector<UInt>::const_iterator< types::Vector<UInt> > first_pair = pairs.begin(2);
       Vector<UInt>::const_iterator< types::Vector<UInt> > last_pair  = pairs.end(2);
       Vector<Real>::iterator<types::RVector> weight  = weights.begin(2);
 
       for(;first_pair != last_pair; ++first_pair, ++weight) {
 	UInt q1 = (*first_pair)(0);
 	UInt q2 = (*first_pair)(1);
 
 	(*weight)(0) *= 1. / quads_volumes1(q1);
 	if(ghost_type2 != _ghost) (*weight)(1) *= 1. / quads_volumes2(q2);
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
+/* -------------------------------------------------------------------------- */
+template<UInt spatial_dimension, template <UInt> class WeightFunction>
+template<typename T>
+void MaterialNonLocal<spatial_dimension, WeightFunction>::weightedAvergageOnNeighbours(const ByElementTypeVector<T> & to_accumulate,
+										       ByElementTypeVector<T> & accumulated,
+										       UInt nb_degree_of_freedom,
+										       GhostType ghost_type2) const {
+  AKANTU_DEBUG_IN();
+
+  UInt existing_pairs_num = 0;
+  if (ghost_type2 == _ghost) existing_pairs_num = 1;
+
+  pair_type::const_iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
+  pair_type::const_iterator last_pair_types = existing_pairs[existing_pairs_num].end();
+
+  GhostType ghost_type1 = _not_ghost; // does not make sens the ghost vs ghost so this should always by _not_ghost
+
+  for (; first_pair_types != last_pair_types; ++first_pair_types) {
+    const Vector<UInt> & pairs =
+      pair_list(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2);
+    const Vector<Real> & weights =
+      pair_weight(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2);
+
+
+    const Vector<T> & to_acc = to_accumulate(first_pair_types->second, ghost_type2);
+    Vector<T> & acc = accumulated(first_pair_types->first, ghost_type1);
+
+    if(ghost_type2 == _not_ghost) acc.clear();
+
+    Vector<UInt>::const_iterator< types::Vector<UInt> > first_pair = pairs.begin(2);
+    Vector<UInt>::const_iterator< types::Vector<UInt> > last_pair  = pairs.end(2);
+    Vector<Real>::const_iterator< types::Vector<Real> > pair_w = weights.begin(2);
+
+    for(;first_pair != last_pair; ++first_pair, ++pair_w) {
+      UInt q1 = (*first_pair)(0);
+      UInt q2 = (*first_pair)(1);
+      for(UInt d = 0; d < nb_degree_of_freedom; ++d){
+	acc(q1, d) += (*pair_w)(0) * to_acc(q2, d);
+	if(ghost_type2 != _ghost) acc(q2, d) += (*pair_w)(1) * to_acc(q1, d);
+      }
+    }
+  }
+
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template<UInt spatial_dimension, template <UInt> class WeightFunction>
+void MaterialNonLocal<spatial_dimension, WeightFunction>::updateResidual(GhostType ghost_type) {
+  AKANTU_DEBUG_IN();
+
+  // Update the weights for the non local variable averaging
+  if(ghost_type == _not_ghost &&
+     this->update_weights &&
+     (this->compute_stress_calls % this->update_weights == 0)) {
+    ByElementTypeReal quadrature_points_coordinates("quadrature_points_coordinates", id);
+    Mesh & mesh = this->model->getFEM().getMesh();
+    mesh.initByElementTypeVector(quadrature_points_coordinates, spatial_dimension, 0);
+    computeQuadraturePointsCoordinates(quadrature_points_coordinates, _not_ghost);
+    computeQuadraturePointsCoordinates(quadrature_points_coordinates, _ghost);
+    computeWeights(quadrature_points_coordinates);
+  }
+  if(ghost_type == _not_ghost) ++this->compute_stress_calls;
+
+  computeAllStresses(ghost_type);
+
+  computeNonLocalStresses(ghost_type);
+  assembleResidual(ghost_type);
+
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template<UInt spatial_dimension, template <UInt> class WeightFunction>
+void MaterialNonLocal<spatial_dimension, WeightFunction>::computeAllNonLocalStresses(GhostType ghost_type) {
+  // Update the weights for the non local variable averaging
+  if(ghost_type == _not_ghost) {
+    if(this->update_weights && (this->compute_stress_calls % this->update_weights == 0)) {
+      this->model->getSynchronizerRegistry().asynchronousSynchronize(_gst_mnl_weight);
+
+      ByElementTypeReal quadrature_points_coordinates("quadrature_points_coordinates", id);
+      Mesh & mesh = this->model->getFEM().getMesh();
+      mesh.initByElementTypeVector(quadrature_points_coordinates, spatial_dimension, 0);
+      computeQuadraturePointsCoordinates(quadrature_points_coordinates, _not_ghost);
+      computeQuadraturePointsCoordinates(quadrature_points_coordinates, _ghost);
+
+      this->model->getSynchronizerRegistry().waitEndSynchronize(_gst_mnl_weight);
+
+      computeWeights(quadrature_points_coordinates);
+    }
+
+    typename std::map<ID, NonLocalVariable>::iterator it = non_local_variables.begin();
+    typename std::map<ID, NonLocalVariable>::iterator end = non_local_variables.end();
+    for(;it != end; ++it) {
+      NonLocalVariable & non_local_variable = it->second;
+
+      resizeInternalVector(*non_local_variable.non_local_variable);
+      this->weightedAvergageOnNeighbours(*non_local_variable.local_variable, *non_local_variable.non_local_variable,
+					 non_local_variable.non_local_variable_nb_component, _not_ghost);
+    }
+
+    ++this->compute_stress_calls;
+  } else {
+
+    typename std::map<ID, NonLocalVariable>::iterator it = non_local_variables.begin();
+    typename std::map<ID, NonLocalVariable>::iterator end = non_local_variables.end();
+    for(;it != end; ++it) {
+      NonLocalVariable & non_local_variable = it->second;
+      this->weightedAvergageOnNeighbours(*non_local_variable.local_variable, *non_local_variable.non_local_variable,
+					 non_local_variable.non_local_variable_nb_component, _ghost);
+    }
+
+    computeNonLocalStresses(_not_ghost);
+  }
+}
+
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 bool MaterialNonLocal<spatial_dimension, WeightFunction>::parseParam(const std::string & key,
 								   const std::string & value,
 								   __attribute__((unused)) const ID & id) {
   std::stringstream sstr(value);
   if(key == "radius") { sstr >> radius; }
   else if(key == "UpdateWeights") { sstr >> update_weights; }
   else if(!weight_func->parseParam(key, value)) return Material::parseParam(key, value, id);
   return true;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::savePairs(const std::string & filename) const {
   std::ofstream pout;
 
   std::stringstream sstr;
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   Int prank = comm.whoAmI();
   sstr << filename << "." << prank;
 
   pout.open(sstr.str().c_str());
 
   GhostType ghost_type1;
   ghost_type1 = _not_ghost;
 
   for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
     GhostType ghost_type2 = (GhostType) gt;
     UInt existing_pairs_num = gt - _not_ghost;
 
     pair_type::const_iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
     pair_type::const_iterator last_pair_types = existing_pairs[existing_pairs_num].end();
 
     for (; first_pair_types != last_pair_types; ++first_pair_types) {
       const Vector<UInt> & pairs =
 	pair_list(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2);
       const Vector<Real> & weights =
 	pair_weight(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2);
 
       pout << "Types : " << first_pair_types->first << " (" << ghost_type1 << ") - " << first_pair_types->second << " (" << ghost_type2 << ")" << std::endl;
 
       Vector<UInt>::const_iterator< types::Vector<UInt> > first_pair = pairs.begin(2);
       Vector<UInt>::const_iterator< types::Vector<UInt> > last_pair  = pairs.end(2);
       Vector<Real>::const_iterator<types::RVector> pair_w = weights.begin(2);
 
       for(;first_pair != last_pair; ++first_pair, ++pair_w) {
 	UInt q1 = (*first_pair)(0);
 	UInt q2 = (*first_pair)(1);
 	pout << q1 << " " << q2 << " "<< (*pair_w)(0) << " " << (*pair_w)(1) << std::endl;
       }
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::neighbourhoodStatistics(const std::string & filename) const {
   std::ofstream pout;
   pout.open(filename.c_str());
 
   const Mesh & mesh = this->model->getFEM().getMesh();
 
   GhostType ghost_type1;
   ghost_type1 = _not_ghost;
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   Int prank = comm.whoAmI();
 
   for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
     GhostType ghost_type2 = (GhostType) gt;
     UInt existing_pairs_num = gt - _not_ghost;
 
     ByElementTypeUInt nb_neighbors("nb_neighbours", id, memory_id);
     mesh.initByElementTypeVector(nb_neighbors, 1, spatial_dimension);
     resizeInternalVector(nb_neighbors);
 
     pair_type::const_iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
     pair_type::const_iterator last_pair_types = existing_pairs[existing_pairs_num].end();
 
     for (; first_pair_types != last_pair_types; ++first_pair_types) {
       const Vector<UInt> & pairs =
 	pair_list(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2);
       if(prank == 0) {
 	pout << ghost_type2 << " ";
 	pout << "Types : " << first_pair_types->first << " " << first_pair_types->second << std::endl;
       }
       Vector<UInt>::const_iterator< types::Vector<UInt> > first_pair = pairs.begin(2);
       Vector<UInt>::const_iterator< types::Vector<UInt> > last_pair  = pairs.end(2);
       Vector<UInt> & nb_neigh_1 = nb_neighbors(first_pair_types->first, ghost_type1);
       Vector<UInt> & nb_neigh_2 = nb_neighbors(first_pair_types->second, ghost_type2);
       for(;first_pair != last_pair; ++first_pair) {
 	UInt q1 = (*first_pair)(0);
 	UInt q2 = (*first_pair)(1);
 	++(nb_neigh_1(q1));
 	if(q1 != q2) ++(nb_neigh_2(q2));
       }
     }
 
     Mesh::type_iterator it        = mesh.firstType(spatial_dimension, ghost_type1);
     Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type1);
     UInt nb_quads = 0;
     Real sum_nb_neig = 0;
     UInt max_nb_neig = 0;
     UInt min_nb_neig = std::numeric_limits<UInt>::max();
     for(; it != last_type; ++it) {
       Vector<UInt> & nb_neighor = nb_neighbors(*it, ghost_type1);
       Vector<UInt>::iterator<UInt> nb_neigh = nb_neighor.begin();
       Vector<UInt>::iterator<UInt> end_neigh  = nb_neighor.end();
 
       for (; nb_neigh != end_neigh; ++nb_neigh, ++nb_quads) {
 	UInt nb = *nb_neigh;
 	sum_nb_neig += nb;
 	max_nb_neig = std::max(max_nb_neig, nb);
 	min_nb_neig = std::min(min_nb_neig, nb);
       }
     }
 
 
     comm.allReduce(&nb_quads,    1, _so_sum);
     comm.allReduce(&sum_nb_neig, 1, _so_sum);
     comm.allReduce(&max_nb_neig, 1, _so_max);
     comm.allReduce(&min_nb_neig, 1, _so_min);
 
     if(prank == 0) {
       pout << ghost_type2 << " ";
       pout << "Nb quadrature points: " << nb_quads << std::endl;
 
       Real mean_nb_neig = sum_nb_neig / Real(nb_quads);
       pout << ghost_type2 << " ";
       pout << "Average nb neighbors: " << mean_nb_neig << "(" << sum_nb_neig << ")" << std::endl;
 
       pout << ghost_type2 << " ";
       pout << "Max nb neighbors:     " << max_nb_neig << std::endl;
 
       pout << ghost_type2 << " ";
       pout << "Min nb neighbors:     " << min_nb_neig << std::endl;
     }
   }
   pout.close();
 }
 
 /* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension, template <UInt> class WeightFunction>
-inline UInt MaterialNonLocal<spatial_dimension, WeightFunction>::getNbDataToPack(const Element & element,
-										 SynchronizationTag tag) const {
-  UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
-  if(tag == _gst_mnl_for_average) {
-    typename std::map<ID, NonLocalVariable>::const_iterator it = non_local_variables.begin();
-    typename std::map<ID, NonLocalVariable>::const_iterator end = non_local_variables.end();
-    UInt size = 0;
-    for(;it != end; ++it) {
-      const NonLocalVariable & non_local_variable = it->second;
-      size += non_local_variable.non_local_variable_nb_component;
-    }
-    return size * sizeof(Real) * nb_quadrature_points;
-  } else if(tag == _gst_mnl_weight) return weight_func->getNbData(element, tag);
-  return 0;
-}
+// template<UInt spatial_dimension, template <UInt> class WeightFunction>
+// inline UInt MaterialNonLocal<spatial_dimension, WeightFunction>::getNbDataToPack(const Element & element,
+// 										 SynchronizationTag tag) const {
+//   UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
+//   UInt size = 0;
+//   if(tag == _gst_mnl_for_average) {
+//     typename std::map<ID, NonLocalVariable>::const_iterator it = non_local_variables.begin();
+//     typename std::map<ID, NonLocalVariable>::const_iterator end = non_local_variables.end();
+
+//     for(;it != end; ++it) {
+//       const NonLocalVariable & non_local_variable = it->second;
+//       size += non_local_variable.non_local_variable_nb_component * sizeof(Real) * nb_quadrature_points;
+//     }
+//   }
+
+//   size += weight_func->getNbData(element, tag);
+
+//   return size;
+// }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
-inline UInt MaterialNonLocal<spatial_dimension, WeightFunction>::getNbDataToUnpack(const Element & element,
-										   SynchronizationTag tag) const {
-  UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
+inline UInt MaterialNonLocal<spatial_dimension, WeightFunction>::getNbDataForElements(const Vector<Element> & elements,
+										      SynchronizationTag tag) const {
+  UInt nb_quadrature_points = this->getNbQuadraturePoints(elements);
+  UInt size = 0;
+
   if(tag == _gst_mnl_for_average) {
     typename std::map<ID, NonLocalVariable>::const_iterator it = non_local_variables.begin();
     typename std::map<ID, NonLocalVariable>::const_iterator end = non_local_variables.end();
-    UInt size = 0;
+
     for(;it != end; ++it) {
       const NonLocalVariable & non_local_variable = it->second;
-      size += non_local_variable.non_local_variable_nb_component;
+      size += non_local_variable.non_local_variable_nb_component * sizeof(Real) * nb_quadrature_points;
     }
-    return size * sizeof(Real) * nb_quadrature_points;
-  } else if(tag == _gst_mnl_weight) return weight_func->getNbData(element, tag);
-  return 0;
+  }
+
+  size += weight_func->getNbDataForElements(elements, tag);
+
+  return size;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
-inline void MaterialNonLocal<spatial_dimension, WeightFunction>::packData(CommunicationBuffer & buffer,
-									  const Element & element,
-									  SynchronizationTag tag) const {
+inline void MaterialNonLocal<spatial_dimension, WeightFunction>::packElementData(CommunicationBuffer & buffer,
+										 const Vector<Element> & elements,
+										 SynchronizationTag tag) const {
   if(tag == _gst_mnl_for_average) {
-    UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
+    // UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
 
     typename std::map<ID, NonLocalVariable>::const_iterator it = non_local_variables.begin();
     typename std::map<ID, NonLocalVariable>::const_iterator end = non_local_variables.end();
 
     for(;it != end; ++it) {
       const NonLocalVariable & non_local_variable = it->second;
-      Vector<Real>::iterator<types::RVector> local_var = (*non_local_variable.local_variable)(element.type, _not_ghost).begin(non_local_variable.non_local_variable_nb_component);
-      local_var += element.element * nb_quadrature_points;
-      for (UInt q = 0; q < nb_quadrature_points; ++q, ++local_var)
-	buffer << *local_var;
+      this->packElementDataHelper(*non_local_variable.local_variable,
+				  buffer, elements);
+      // Vector<Real>::iterator<types::RVector> local_var = (*non_local_variable.local_variable)(element.type, _not_ghost).begin(non_local_variable.non_local_variable_nb_component);
+      // local_var += element.element * nb_quadrature_points;
+      // for (UInt q = 0; q < nb_quadrature_points; ++q, ++local_var)
+      // 	buffer << *local_var;
     }
-  } else if(tag == _gst_mnl_weight) return weight_func->packData(buffer, element, tag);
+  }
+
+  weight_func->packElementData(buffer, elements, tag);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
-inline void MaterialNonLocal<spatial_dimension, WeightFunction>::unpackData(CommunicationBuffer & buffer,
-									    const Element & element,
-									    SynchronizationTag tag) {
+inline void MaterialNonLocal<spatial_dimension, WeightFunction>::unpackElementData(CommunicationBuffer & buffer,
+										   const Vector<Element> & elements,
+										   SynchronizationTag tag) {
   if(tag == _gst_mnl_for_average) {
-    UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
+    // UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(element.type);
     typename std::map<ID, NonLocalVariable>::iterator it = non_local_variables.begin();
     typename std::map<ID, NonLocalVariable>::iterator end = non_local_variables.end();
 
     for(;it != end; ++it) {
       NonLocalVariable & non_local_variable = it->second;
-      Vector<Real>::iterator<types::RVector> local_var =
-	(*non_local_variable.local_variable)(element.type, _ghost).begin(non_local_variable.non_local_variable_nb_component);
-      local_var += element.element * nb_quadrature_points;
-      for (UInt q = 0; q < nb_quadrature_points; ++q, ++local_var)
-	buffer >> *local_var;
+      this->unpackElementDataHelper(*non_local_variable.local_variable,
+				    buffer, elements);
+      // Vector<Real>::iterator<types::RVector> local_var =
+      // 	(*non_local_variable.local_variable)(element.type, _ghost).begin(non_local_variable.non_local_variable_nb_component);
+      // local_var += element.element * nb_quadrature_points;
+      // for (UInt q = 0; q < nb_quadrature_points; ++q, ++local_var)
+      //   buffer >> *local_var;
     }
-  } else if(tag == _gst_mnl_weight) return weight_func->unpackData(buffer, element, tag);
+  }
+
+  weight_func->unpackElementData(buffer, elements, tag);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 inline void MaterialNonLocal<spatial_dimension, WeightFunction>::onElementsAdded(const Vector<Element> & element_list) {
   AKANTU_DEBUG_IN();
 
   if(is_creating_grid) {
     Int my_index = model->getInternalIndexFromID(id);
-    std::cout << "Toto :" << my_index << std::endl;
 
     AKANTU_DEBUG_ASSERT(my_index != -1, "Something horrible happen, the model does not know the material " << id);
     Vector<Element>::const_iterator<Element> it  = element_list.begin();
     Vector<Element>::const_iterator<Element> end = element_list.end();
     for (; it != end; ++it) {
       const Element & elem = *it;
       model->getElementIndexByMaterial(elem.type, elem.ghost_type)(elem.element) =
 	this->addElement(elem.type, elem.element, elem.ghost_type);
       model->getElementMaterial(elem.type, elem.ghost_type)(elem.element) = UInt(my_index);
     }
   }
 
   Material::onElementsAdded(element_list);
 
   AKANTU_DEBUG_OUT();
 }
diff --git a/src/model/solid_mechanics/materials/weight_function.hh b/src/model/solid_mechanics/materials/weight_function.hh
index 0e10aec12..84c32f95d 100644
--- a/src/model/solid_mechanics/materials/weight_function.hh
+++ b/src/model/solid_mechanics/materials/weight_function.hh
@@ -1,415 +1,423 @@
 /**
  * @file   weight_function.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Mar  8 16:17:00 2012
  *
  * @brief  Weight functions for non local materials
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "aka_types.hh"
 #include "solid_mechanics_model.hh"
 #include <cmath>
 
 /* -------------------------------------------------------------------------- */
 #include <vector>
 
 
 #ifndef __AKANTU_WEIGHT_FUNCTION_HH__
 #define __AKANTU_WEIGHT_FUNCTION_HH__
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /*  Normal weight function                                                    */
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 class BaseWeightFunction {
 public:
   BaseWeightFunction(Material & material) : material(material) {}
 
   virtual ~BaseWeightFunction() {}
 
   virtual void init() {};
 
   virtual void updateInternals(__attribute__((unused)) const ByElementTypeReal & quadrature_points_coordinates) {};
 
   /* ------------------------------------------------------------------------ */
   inline void setRadius(Real radius) { R = radius; R2 = R * R; }
 
   /* ------------------------------------------------------------------------ */
   inline void selectType(__attribute__((unused)) ElementType type1,
 			 __attribute__((unused)) GhostType   ghost_type1,
 			 __attribute__((unused)) ElementType type2,
 			 __attribute__((unused)) GhostType   ghost_type2) {
   }
 
   /* ------------------------------------------------------------------------ */
   inline Real operator()(Real r,
 			 __attribute__((unused)) QuadraturePoint & q1,
 			 __attribute__((unused)) QuadraturePoint & q2) {
     Real w = 0;
     if(r <= R) {
       Real alpha = (1. - r*r / R2);
       w = alpha * alpha;
       // *weight = 1 - sqrt(r / radius);
     }
     return w;
   }
 
   /* ------------------------------------------------------------------------ */
   bool parseParam(__attribute__((unused)) const std::string & key,
 		__attribute__((unused)) const std::string & value) {
     return false;
   }
 
   /* ------------------------------------------------------------------------ */
   virtual void printself(std::ostream & stream) const {
     stream << "BaseWeightFunction";
   }
 
 public:
-  virtual UInt getNbData(__attribute__((unused)) const Element & element,
-			 __attribute__((unused)) SynchronizationTag tag) const {
+  virtual UInt getNbDataForElements(__attribute__((unused)) const Vector<Element> & elements,
+				    __attribute__((unused)) SynchronizationTag tag) const {
     return 0;
   }
 
-  virtual inline void packData(__attribute__((unused)) CommunicationBuffer & buffer,
-   			       __attribute__((unused)) const Element & element,
-   			       __attribute__((unused)) SynchronizationTag tag) const {}
-
-  virtual inline void unpackData(__attribute__((unused)) CommunicationBuffer & buffer,
-   				 __attribute__((unused)) const Element & element,
-   				 __attribute__((unused)) SynchronizationTag tag) {}
+  virtual inline void packElementData(__attribute__((unused)) CommunicationBuffer & buffer,
+				      __attribute__((unused)) const Vector<Element> & elements,
+				      __attribute__((unused)) SynchronizationTag tag) const {}
 
+  virtual inline void unpackElementData(__attribute__((unused)) CommunicationBuffer & buffer,
+					__attribute__((unused)) const Vector<Element> & elements,
+					__attribute__((unused)) SynchronizationTag tag) {}
 protected:
   Material & material;
 
   Real R;
   Real R2;
 };
 
 /* -------------------------------------------------------------------------- */
 /*  Damage weight function                                                    */
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 class DamagedWeightFunction : public BaseWeightFunction<spatial_dimension> {
 public:
   DamagedWeightFunction(Material & material) : BaseWeightFunction<spatial_dimension>(material) {}
 
   inline void selectType(__attribute__((unused)) ElementType type1,
 			 __attribute__((unused)) GhostType ghost_type1,
 			 ElementType type2,
 			 GhostType ghost_type2) {
     selected_damage = &this->material.getVector("damage", type2, ghost_type2);
   }
 
   inline Real operator()(Real r, __attribute__((unused)) QuadraturePoint & q1, QuadraturePoint & q2) {
     UInt quad = q2.global_num;
     Real D = (*selected_damage)(quad);
     Real Radius = (1.-D)*(1.-D) * this->R2;
     if(Radius < Math::getTolerance()) {
       Radius = 0.01 * 0.01 * this->R2;
     }
     Real alpha = std::max(0., 1. - r*r / Radius);
     Real w = alpha * alpha;
     return w;
   }
 
   /* ------------------------------------------------------------------------ */
   bool parseParam(__attribute__((unused)) const std::string & key,
 		__attribute__((unused)) const std::string & value) {
     return false;
   }
 
   /* ------------------------------------------------------------------------ */
   virtual void printself(std::ostream & stream) const {
     stream << "DamagedWeightFunction";
   }
 
 private:
   const Vector<Real> * selected_damage;
 };
 
 /* -------------------------------------------------------------------------- */
 /*  Remove damaged weight function                                            */
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 class RemoveDamagedWeightFunction : public BaseWeightFunction<spatial_dimension> {
 public:
   RemoveDamagedWeightFunction(Material & material) : BaseWeightFunction<spatial_dimension>(material) {}
 
   inline void selectType(__attribute__((unused)) ElementType type1,
 			 __attribute__((unused)) GhostType ghost_type1,
 			 ElementType type2,
 			 GhostType ghost_type2) {
     selected_damage = &this->material.getVector("damage", type2, ghost_type2);
   }
 
   inline Real operator()(Real r, __attribute__((unused)) QuadraturePoint & q1, QuadraturePoint & q2) {
     UInt quad = q2.global_num;
 
     if(q1.global_num == quad) return 1.;
 
     Real D = (*selected_damage)(quad);
     Real w = 0.;
     if(D < damage_limit) {
 
       ////alpha2beta6////
       // Real alpha = std::max(0., 1. - r*r / this->R2);
       //  w = alpha * alpha * alpha * alpha * alpha * alpha;
 
       ////alpha4beta6////
         //Real alpha = std::max(0., 1. - (r*r / this->R2)*(r*r / this->R2));
         //w = alpha * alpha * alpha * alpha * alpha * alpha;
 
       ////alpha6beta6////
         //Real alpha = std::max(0., 1. - (r*r / this->R2)*(r*r / this->R2)*(r*r / this->R2));
         //w = alpha * alpha * alpha * alpha * alpha * alpha;
 
       ////alpha8beta6////
         //Real alpha = std::max(0., 1. - (r*r / this->R2)*(r*r / this->R2)*(r*r / this->R2)*(r*r / this->R2));
         //w = alpha * alpha * alpha * alpha * alpha * alpha; 
 
       ////alpha10beta6////
         //Real alpha = std::max(0., 1. - (r*r / this->R2)*(r*r / this->R2)*(r*r / this->R2)*(r*r / this->R2)*(r*r / this->R2));
         //w = alpha * alpha * alpha * alpha * alpha * alpha;
 
       ////alpha2beta2////
         Real alpha = std::max(0., 1. - r*r / this->R2);
         w = alpha * alpha;
     }
-
     return w;
   }
 
   /* ------------------------------------------------------------------------ */
   bool parseParam(const std::string & key,
 		const std::string & value) {
     std::stringstream sstr(value);
     if(key == "damage_limit") { sstr >> damage_limit; }
     else return BaseWeightFunction<spatial_dimension>::parseParam(key, value);
     return true;
   }
 
   /* ------------------------------------------------------------------------ */
   virtual void printself(std::ostream & stream) const {
     stream << "RemoveDamagedWeightFunction [damage_limit: " << damage_limit << "]";
   }
 
-  virtual UInt getNbData(const Element & element,
-			 __attribute__((unused)) SynchronizationTag tag) const {
-    UInt nb_quadrature_points = this->material.getModel().getFEM().getNbQuadraturePoints(element.type);
-    UInt size = sizeof(Real) * nb_quadrature_points;
-    return size;
-  }
+  virtual UInt getNbDataForElements(const Vector<Element> & elements,
+				    SynchronizationTag tag) const {
+    if(tag == _gst_mnl_weight)
+      return this->material.getNbQuadraturePoints(elements) * sizeof(Real);
 
-  virtual inline void packData(CommunicationBuffer & buffer,
-   			       const Element & element,
-   			       __attribute__((unused)) SynchronizationTag tag) const {
-    UInt nb_quadrature_points = this->material.getModel().getFEM().getNbQuadraturePoints(element.type);
-    const Vector<Real> & dam_vect = this->material.getVector("damage", element.type, _not_ghost);
-    Vector<Real>::const_iterator<Real> damage = dam_vect.begin();
+    return 0;
+  }
 
-    damage += element.element * nb_quadrature_points;
-    for (UInt q = 0; q < nb_quadrature_points; ++q, ++damage)
-      buffer << *damage;
+  virtual inline void packElementData(CommunicationBuffer & buffer,
+				      const Vector<Element> & elements,
+				      SynchronizationTag tag) const {
+    if(tag == _gst_mnl_weight)
+      this->material.packElementDataHelper(dynamic_cast<MaterialDamage<spatial_dimension> &>(this->material).getDamage(),
+					   buffer,
+					   elements);
+    // UInt nb_quadrature_points = this->material.getModel().getFEM().getNbQuadraturePoints(element.type);
+    // const Vector<Real> & dam_vect = this->material.getVector("damage", element.type, _not_ghost);
+    // Vector<Real>::const_iterator<Real> damage = dam_vect.begin();
+
+    // damage += element.element * nb_quadrature_points;
+    // for (UInt q = 0; q < nb_quadrature_points; ++q, ++damage)
+    //   buffer << *damage;
   }
 
-  virtual inline void unpackData(CommunicationBuffer & buffer,
-   				 const Element & element,
-   				 __attribute__((unused)) SynchronizationTag tag) {
-    UInt nb_quadrature_points = this->material.getModel().getFEM().getNbQuadraturePoints(element.type);
-    Vector<Real>::iterator<Real> damage =
-      this->material.getVector("damage", element.type, _ghost).begin();
-    damage += element.element * nb_quadrature_points;
-    for (UInt q = 0; q < nb_quadrature_points; ++q, ++damage)
-      buffer >> *damage;
+  virtual inline void unpackElementData(CommunicationBuffer & buffer,
+					const Vector<Element> & elements,
+					SynchronizationTag tag) {
+    if(tag == _gst_mnl_weight)
+      this->material.unpackElementDataHelper(dynamic_cast< MaterialDamage<spatial_dimension> &>(this->material).getDamage(),
+					   buffer,
+					   elements);
+
+    // UInt nb_quadrature_points = this->material.getModel().getFEM().getNbQuadraturePoints(element.type);
+    // Vector<Real>::iterator<Real> damage =
+    //   this->material.getVector("damage", element.type, _ghost).begin();
+    // damage += element.element * nb_quadrature_points;
+    // for (UInt q = 0; q < nb_quadrature_points; ++q, ++damage)
+    //   buffer >> *damage;
   }
 
 
 private:
   /// limit at which a point is considered as complitely broken
   Real damage_limit;
 
   /// internal pointer to the current damage vector
   const Vector<Real> * selected_damage;
 };
 /* -------------------------------------------------------------------------- */
 /* Remove damaged with damage rate weight function                                             */
 /* -------------------------------------------------------------------------- */
 
 template<UInt spatial_dimension>
 class RemoveDamagedWithDamageRateWeightFunction : public BaseWeightFunction<spatial_dimension> {
 public:
   RemoveDamagedWithDamageRateWeightFunction(Material & material) : BaseWeightFunction<spatial_dimension>(material) {}
 
   inline void selectType(__attribute__((unused)) ElementType type1,
 			 __attribute__((unused)) GhostType ghost_type1,
 			 ElementType type2,
 			 GhostType ghost_type2) {
     selected_damage_with_damage_rate = &(this->material.getVector("damage",type2, ghost_type2));
     selected_damage_rate_with_damage_rate = &(this->material.getVector("damage-rate",type2, ghost_type2));
   }
 
   inline Real operator()(Real r, __attribute__((unused)) QuadraturePoint & q1, QuadraturePoint & q2) {
     UInt quad = q2.global_num;
 
     if(q1.global_num == quad) return 1.;
 
     Real D = (*selected_damage_with_damage_rate)(quad);
     Real w = 0.;
     Real alphaexp = 1.;
     Real betaexp = 2.;
     if(D < damage_limit_with_damage_rate) {
       Real alpha = std::max(0., 1. - pow((r*r / this->R2),alphaexp));
       w = pow(alpha, betaexp);
     }
 
     return w;
   }
   /* ------------------------------------------------------------------------ */
   bool setParam(const std::string & key,
 		const std::string & value) {
     std::stringstream sstr(value);
     if(key == "damage_limit") { sstr >> damage_limit_with_damage_rate; }
     else return BaseWeightFunction<spatial_dimension>::setParam(key, value);
     return true;
   }
 
   /* ------------------------------------------------------------------------ */
   virtual void printself(std::ostream & stream) const {
     stream << "RemoveDamagedWithDamageRateWeightFunction [damage_limit: " << damage_limit_with_damage_rate << "]";
   }
 
 private:
   /// limit at which a point is considered as complitely broken
   Real damage_limit_with_damage_rate;
 
   /// internal pointer to the current damage vector
   const Vector<Real> * selected_damage_with_damage_rate;
 
   /// internal pointer to the current damage rate vector
   const Vector<Real> * selected_damage_rate_with_damage_rate;
 };
 
 /* -------------------------------------------------------------------------- */
 /* Stress Based Weight                                                        */
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 class StressBasedWeightFunction : public BaseWeightFunction<spatial_dimension> {
 public:
   StressBasedWeightFunction(Material & material);
 
   void init();
 
   virtual void updateInternals(__attribute__((unused)) const ByElementTypeReal & quadrature_points_coordinates) {
     updatePrincipalStress(_not_ghost);
     updatePrincipalStress(_ghost);
   };
 
   void updatePrincipalStress(GhostType ghost_type);
 
   inline void updateQuadraturePointsCoordinates(ByElementTypeReal & quadrature_points_coordinates);
 
   inline void selectType(ElementType type1, GhostType ghost_type1,
 			 ElementType type2, GhostType ghost_type2);
 
   inline Real operator()(Real r, QuadraturePoint & q1, QuadraturePoint & q2);
 
   inline Real computeRhoSquare(Real r,
 			       types::RVector & eigs,
 			       types::Matrix & eigenvects,
 			       types::RVector & x_s);
 
   /* ------------------------------------------------------------------------ */
   bool parseParam(const std::string & key, const std::string & value) {
     std::stringstream sstr(value);
     if(key == "ft") { sstr >> ft; }
     else return BaseWeightFunction<spatial_dimension>::parseParam(key, value);
     return true;
   }
 
   /* ------------------------------------------------------------------------ */
   virtual void printself(std::ostream & stream) const {
     stream << "StressBasedWeightFunction [ft: " << ft << "]";
   }
 
 private:
   Real ft;
 
   ByElementTypeReal stress_diag;
   Vector<Real> * selected_stress_diag;
   ByElementTypeReal stress_base;
   Vector<Real> * selected_stress_base;
 
 
   ByElementTypeReal quadrature_points_coordinates;
   Vector<Real> * selected_position_1;
   Vector<Real> * selected_position_2;
 
   ByElementTypeReal characteristic_size;
   Vector<Real> * selected_characteristic_size;
 };
 
 template<UInt spatial_dimension>
 inline std::ostream & operator <<(std::ostream & stream,
 				  const BaseWeightFunction<spatial_dimension> & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 
 template<UInt spatial_dimension>
 inline std::ostream & operator <<(std::ostream & stream,
 				  const BaseWeightFunction<spatial_dimension> * _this)
 {
   _this->printself(stream);
   return stream;
 }
 
 
 template<UInt d>
 inline std::ostream & operator >>(std::ostream & stream,
 				  __attribute__((unused)) const BaseWeightFunction<d> * _this)
 {  AKANTU_DEBUG_TO_IMPLEMENT(); return stream; }
 template<UInt d>
 inline std::ostream & operator >>(std::ostream & stream,
 				  __attribute__((unused)) const RemoveDamagedWeightFunction<d> * _this)
 {  AKANTU_DEBUG_TO_IMPLEMENT(); return stream; }
 template<UInt d>
 inline std::ostream & operator >>(std::ostream & stream,
 				  __attribute__((unused)) const DamagedWeightFunction<d> * _this)
 {  AKANTU_DEBUG_TO_IMPLEMENT(); return stream; }
 template<UInt d>
 inline std::ostream & operator >>(std::ostream & stream,
 				  __attribute__((unused)) const StressBasedWeightFunction<d> * _this)
 {  AKANTU_DEBUG_TO_IMPLEMENT(); return stream; }
 
 
 #include "weight_function_tmpl.hh"
 
 __END_AKANTU__
 
 #endif /* __AKANTU_WEIGHT_FUNCTION_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc
index 46efc559e..f738702f5 100644
--- a/src/model/solid_mechanics/solid_mechanics_model.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model.cc
@@ -1,1184 +1,1221 @@
 /**
  * @file   solid_mechanics_model.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Jul 22 14:35:38 2010
  *
  * @brief  Implementation of the SolidMechanicsModel class
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_math.hh"
 #include "aka_common.hh"
 #include "solid_mechanics_model.hh"
 #include "integration_scheme_2nd_order.hh"
 
 #include "static_communicator.hh"
 
 #include "dof_synchronizer.hh"
 
 
 #ifdef AKANTU_USE_MUMPS
 #include "solver_mumps.hh"
 #endif
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 
 /* -------------------------------------------------------------------------- */
 /**
  * A solid mechanics model need a mesh  and a dimension to be created. the model
  * by it  self can not  do a lot,  the good init  functions should be  called in
  * order to configure the model depending on what we want to do.
  *
  * @param  mesh mesh  representing  the model  we  want to  simulate
  * @param dim spatial  dimension of the problem, if dim =  0 (default value) the
  * dimension of the problem is assumed to be the on of the mesh
  * @param id an id to identify the model
  */
 SolidMechanicsModel::SolidMechanicsModel(Mesh & mesh,
 					 UInt dim,
 					 const ID & id,
 					 const MemoryID & memory_id) :
   Model(id, memory_id),
   time_step(NAN), f_m2a(1.0),
   mass_matrix(NULL),
   velocity_damping_matrix(NULL),
   stiffness_matrix(NULL),
   jacobian_matrix(NULL),
   element_material("element_material", id),
   element_index_by_material("element index by material", id),
   integrator(NULL),
   increment_flag(false), solver(NULL),
   spatial_dimension(dim),
   mesh(mesh) {
   AKANTU_DEBUG_IN();
 
   createSynchronizerRegistry(this);
 
   if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension();
   registerFEMObject<MyFEMType>("SolidMechanicsFEM", mesh, spatial_dimension);
 
   this->displacement = NULL;
   this->mass         = NULL;
   this->velocity     = NULL;
   this->acceleration = NULL;
   this->force        = NULL;
   this->residual     = NULL;
   this->boundary     = NULL;
 
   this->increment    = NULL;
   this->increment_acceleration = NULL;
 
   this->dof_synchronizer = NULL;
 
   materials.clear();
 
   mesh.registerEventHandler(*this);
 
   AKANTU_DEBUG_OUT();
 }
 
 
 
 /* -------------------------------------------------------------------------- */
 SolidMechanicsModel::~SolidMechanicsModel() {
   AKANTU_DEBUG_IN();
 
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     delete *mat_it;
   }
   materials.clear();
 
   delete integrator;
 
   if(solver) delete solver;
   if(mass_matrix) delete mass_matrix;
   if(velocity_damping_matrix) delete velocity_damping_matrix;
 
   if(stiffness_matrix && stiffness_matrix != jacobian_matrix)
     delete stiffness_matrix;
 
   if(jacobian_matrix) delete jacobian_matrix;
 
   if(dof_synchronizer) delete dof_synchronizer;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /* Initialisation                                                             */
 /* -------------------------------------------------------------------------- */
 /**
  * This function groups  many of the initialization in on  function. For most of
  * basics  case the  function should  be  enough. The  functions initialize  the
  * model, the internal  vectors, set them to 0, and  depending on the parameters
  * it also initialize the explicit or implicit solver.
  *
  * @param material_file the  file containing the materials to  use
  * @param method the analysis method wanted.  See the akantu::AnalysisMethod for
  * the different possibilites
  */
 void SolidMechanicsModel::initFull(std::string material_file,
 				   AnalysisMethod analysis_method) {
   method = analysis_method;
 
   // initialize the model
   initModel();
 
   // initialize the vectors
   initVectors();
 
   // set the initial condition to 0
   force->clear();
   velocity->clear();
   acceleration->clear();
   displacement->clear();
 
   // initialize pcb
   if(pbc_pair.size()!=0)
     initPBC();
 
   // initialize the time integration schemes
   switch(method) {
   case _explicit_dynamic:
     initExplicit();
     break;
   case _implicit_dynamic:
     initImplicit(true);
     break;
   case _static:
     initImplicit(false);
     break;
   }
 
   // initialize the materials
   if(material_file != "") {
     readMaterials(material_file);
     initMaterials();
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initParallel(MeshPartition * partition,
 				       DataAccessor * data_accessor) {
   AKANTU_DEBUG_IN();
 
   if (data_accessor == NULL) data_accessor = this;
   Synchronizer & synch_parallel = createParallelSynch(partition,data_accessor);
 
   synch_registry->registerSynchronizer(synch_parallel,_gst_smm_mass);
   //  synch_registry->registerSynchronizer(synch_parallel,_gst_smm_for_strain);
   synch_registry->registerSynchronizer(synch_parallel,_gst_smm_stress);
   synch_registry->registerSynchronizer(synch_parallel,_gst_smm_boundary);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initFEMBoundary(bool create_surface) {
 
   if(create_surface)
     MeshUtils::buildFacets(mesh);
 
   FEM & fem_boundary = getFEMBoundary();
   fem_boundary.initShapeFunctions();
   fem_boundary.computeNormalsOnControlPoints();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initExplicit() {
   AKANTU_DEBUG_IN();
 
   method = _explicit_dynamic;
 
   if (integrator) delete integrator;
   integrator = new CentralDifference();
 
   UInt nb_nodes = acceleration->getSize();
   UInt nb_degree_of_freedom = acceleration->getNbComponent();
 
   std::stringstream sstr; sstr << id << ":increment_acceleration";
   increment_acceleration = &(alloc<Real>(sstr.str(), nb_nodes, nb_degree_of_freedom, Real()));
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /**
  * Allocate all the needed vectors. By  default their are not necessarily set to
  * 0
  *
  */
 void SolidMechanicsModel::initVectors() {
   AKANTU_DEBUG_IN();
 
   UInt nb_nodes = mesh.getNbNodes();
   std::stringstream sstr_disp; sstr_disp << id << ":displacement";
   std::stringstream sstr_mass; sstr_mass << id << ":mass";
   std::stringstream sstr_velo; sstr_velo << id << ":velocity";
   std::stringstream sstr_acce; sstr_acce << id << ":acceleration";
   std::stringstream sstr_forc; sstr_forc << id << ":force";
   std::stringstream sstr_resi; sstr_resi << id << ":residual";
   std::stringstream sstr_boun; sstr_boun << id << ":boundary";
 
   displacement = &(alloc<Real>(sstr_disp.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE));
   mass         = &(alloc<Real>(sstr_mass.str(), nb_nodes, spatial_dimension, 0));
   velocity     = &(alloc<Real>(sstr_velo.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE));
   acceleration = &(alloc<Real>(sstr_acce.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE));
   force        = &(alloc<Real>(sstr_forc.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE));
   residual     = &(alloc<Real>(sstr_resi.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE));
   boundary     = &(alloc<bool>(sstr_boun.str(), nb_nodes, spatial_dimension, false));
 
   std::stringstream sstr_curp; sstr_curp << id << ":current_position";
   current_position = &(alloc<Real>(sstr_curp.str(), 0, spatial_dimension, REAL_INIT_VALUE));
 
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
     Mesh::type_iterator it  = mesh.firstType(spatial_dimension, gt, _ek_not_defined);
     Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, _ek_not_defined);
     for(; it != end; ++it) {
       UInt nb_element = mesh.getNbElement(*it, gt);
       element_material.alloc(nb_element, 1, *it, gt);
     }
   }
 
   dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension);
   dof_synchronizer->initLocalDOFEquationNumbers();
   dof_synchronizer->initGlobalDOFEquationNumbers();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Initialize the model,basically it  pre-compute the shapes, shapes derivatives
  * and jacobian
  *
  */
 void SolidMechanicsModel::initModel() {
   /// \todo add  the current position  as a parameter to  initShapeFunctions for
   /// large deformation
   getFEM().initShapeFunctions(_not_ghost);
   getFEM().initShapeFunctions(_ghost);
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initPBC() {
   Model::initPBC();
   registerPBCSynchronizer();
 
   // as long as there are ones on the diagonal of the matrix, we can put boudandary true for slaves
   std::map<UInt, UInt>::iterator it = pbc_pair.begin();
   std::map<UInt, UInt>::iterator end = pbc_pair.end();
   UInt dim = mesh.getSpatialDimension();
   while(it != end) {
     for (UInt i=0; i<dim; ++i)
       (*boundary)((*it).first,i) = true;
     ++it;
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::registerPBCSynchronizer(){
   PBCSynchronizer * synch = new PBCSynchronizer(pbc_pair);
   synch_registry->registerSynchronizer(*synch, _gst_smm_uv);
   synch_registry->registerSynchronizer(*synch, _gst_smm_mass);
   synch_registry->registerSynchronizer(*synch, _gst_smm_res);
   changeLocalEquationNumberforPBC(pbc_pair, mesh.getSpatialDimension());
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateCurrentPosition() {
   AKANTU_DEBUG_IN();
   UInt nb_nodes = mesh.getNbNodes();
 
   current_position->resize(nb_nodes);
   Real * current_position_val = current_position->values;
   Real * position_val         = mesh.getNodes().values;
   Real * displacement_val     = displacement->values;
 
   /// compute current_position = initial_position + displacement
   memcpy(current_position_val, position_val, nb_nodes*spatial_dimension*sizeof(Real));
   for (UInt n = 0; n < nb_nodes*spatial_dimension; ++n) {
     *current_position_val++ += *displacement_val++;
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initializeUpdateResidualData() {
   AKANTU_DEBUG_IN();
   UInt nb_nodes = mesh.getNbNodes();
   residual->resize(nb_nodes);
 
   /// copy the forces in residual for boundary conditions
   memcpy(residual->values, force->values, nb_nodes*spatial_dimension*sizeof(Real));
 
   updateCurrentPosition();
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* Explicit scheme                                                            */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 /**
  * This function compute  the second member of the motion  equation.  That is to
  * say the sum of forces @f$ r = F_{ext} - F_{int} @f$. @f$ F_{ext} @f$ is given
  * by the  user in  the force  vector, and @f$  F_{int} @f$  is computed  as @f$
  * F_{int} = \int_{\Omega} N \sigma d\Omega@f$
  *
  */
 void SolidMechanicsModel::updateResidual(bool need_initialize) {
   AKANTU_DEBUG_IN();
 
   // f = f_ext - f_int
 
   // f = f_ext
   if (need_initialize) initializeUpdateResidualData();
 
   if (method == _explicit_dynamic) {
     // f -= fint
     // start synchronization
     synch_registry->asynchronousSynchronize(_gst_smm_uv);
     synch_registry->waitEndSynchronize(_gst_smm_uv);
 
     // communicate the displacement
     // synch_registry->asynchronousSynchronize(_gst_smm_for_strain);
 
     std::vector<Material *>::iterator mat_it;
 
     // call update residual on each local elements
     for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
       Material & mat = **mat_it;
       mat.computeAllStresses(_not_ghost);
     }
 
 #ifdef AKANTU_DAMAGE_NON_LOCAL
     /* ------------------------------------------------------------------------ */
     /* Computation of the non local part */
     synch_registry->asynchronousSynchronize(_gst_mnl_for_average);
 
     for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
       Material & mat = **mat_it;
       mat.computeAllNonLocalStresses(_not_ghost);
     }
 
     synch_registry->waitEndSynchronize(_gst_mnl_for_average);
 
     for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
       Material & mat = **mat_it;
       mat.computeAllNonLocalStresses(_ghost);
     }
 #endif
 
     /* ------------------------------------------------------------------------ */
     /* assembling the forces internal */
     // communicate the strain
     synch_registry->asynchronousSynchronize(_gst_smm_stress);
 
     for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
       Material & mat = **mat_it;
       mat.assembleResidual(_not_ghost);
     }
 
     // finalize communications
     synch_registry->waitEndSynchronize(_gst_smm_stress);
     //  synch_registry->waitEndSynchronize(_gst_smm_for_strain);
 
     for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
       Material & mat = **mat_it;
       mat.assembleResidual(_ghost);
     }
   } else {
     //    updateSupportReaction();
 
     Vector<Real> * Ku = new Vector<Real>(*displacement, true, "Ku");
     *Ku *= *stiffness_matrix;
     *residual -= *Ku;
     delete Ku;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 //void SolidMechanicsModel::updateSupportReaction() {
 //  const Vector<Int> & irn = stiffness_matrix->getIRN();
 //  const Vector<Int> & jcn = stiffness_matrix->getJCN();
 //  const Vector<Real> & A = stiffness_matrix->getA();
 //
 //  Real * residual = residual->storage();
 //  Real * displacement = displacement->storage();
 //  bool * boundary = boundary->storage();
 //
 //  UInt n = stiffness_matrix->getNbNonZero();
 //
 //  for (UInt i = 0; i < n; ++i) {
 //
 //  }
 //}
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateResidualInternal() {
   AKANTU_DEBUG_IN();
 
   // f = f_ext - f_int - Ma - Cv = r - Ma - Cv;
 
   if(method != _static) {
     // f -= Ma
     if(mass_matrix) {
       // if full mass_matrix
       Vector<Real> * Ma = new Vector<Real>(*acceleration, true, "Ma");
       *Ma *= *mass_matrix;
       /// \todo check unit conversion for implicit dynamics
       //      *Ma /= f_m2a
       *residual -= *Ma;
       delete Ma;
     } else {
       // else lumped mass
       UInt nb_nodes = acceleration->getSize();
       UInt nb_degree_of_freedom = acceleration->getNbComponent();
 
       Real * mass_val     = mass->values;
       Real * accel_val    = acceleration->values;
       Real * res_val      = residual->values;
       bool * boundary_val = boundary->values;
 
       for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) {
 	if(!(*boundary_val)) {
 	  *res_val -= *accel_val * *mass_val /f_m2a;
 	}
 	boundary_val++;
 	res_val++;
 	mass_val++;
 	accel_val++;
       }
     }
 
     // f -= Cv
     if(velocity_damping_matrix) {
       Vector<Real> * Cv = new Vector<Real>(*velocity);
       *Cv *= *velocity_damping_matrix;
       *residual -= *Cv;
       delete Cv;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateAcceleration() {
   AKANTU_DEBUG_IN();
 
   updateResidualInternal();
 
   if(method == _explicit_dynamic && !mass_matrix) {
     /* residual = residual_{n+1} - M * acceleration_n therefore
        solution = increment acceleration not acceleration */
     solveLumped(*increment_acceleration,
 		*mass,
 		*residual,
 		*boundary,
 		f_m2a);
   } else {
     solveDynamic<NewmarkBeta::_acceleration_corrector>(*increment_acceleration);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::solveLumped(Vector<Real> & x,
 				      const Vector<Real> & A,
 				      const Vector<Real> & b,
 				      const Vector<bool> & boundary,
 				      Real alpha) {
   Real * A_val = A.storage();
   Real * b_val = b.storage();
   Real * x_val = x.storage();
   bool * boundary_val = boundary.storage();
 
   UInt nb_degrees_of_freedom = x.getSize() * x.getNbComponent();
 
   for (UInt n = 0; n < nb_degrees_of_freedom; ++n) {
     if(!(*boundary_val)) {
       *x_val = alpha * (*b_val / *A_val);
     }
     x_val++;
     A_val++;
     b_val++;
     boundary_val++;
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::explicitPred() {
   AKANTU_DEBUG_IN();
 
   if(increment_flag) {
     memcpy(increment->values,
 	   displacement->values,
 	   displacement->getSize()*displacement->getNbComponent()*sizeof(Real));
   }
 
   AKANTU_DEBUG_ASSERT(integrator,"itegrator should have been allocated: "
 		      << "have called initExplicit ? "
 		      << "or initImplicit ?");
 
   integrator->integrationSchemePred(time_step,
 				    *displacement,
 				    *velocity,
 				    *acceleration,
 				    *boundary);
 
   if(increment_flag) {
     Real * inc_val = increment->values;
     Real * dis_val = displacement->values;
     UInt nb_nodes = displacement->getSize();
 
     for (UInt n = 0; n < nb_nodes; ++n) {
       *inc_val = *dis_val - *inc_val;
       inc_val++;
       dis_val++;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::explicitCorr() {
   AKANTU_DEBUG_IN();
 
   integrator->integrationSchemeCorrAccel(time_step,
 					 *displacement,
 					 *velocity,
 					 *acceleration,
 					 *boundary,
 					 *increment_acceleration);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /* Implicit scheme                                                            */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 /**
  * Initialize the solver and create the sparse matrices needed.
  *
  */
 void SolidMechanicsModel::initSolver(__attribute__((unused)) SolverOptions & options) {
 #if !defined(AKANTU_USE_MUMPS) // or other solver in the future \todo add AKANTU_HAS_SOLVER in CMake
   AKANTU_DEBUG_ERROR("You should at least activate one solver.");
 #else
   UInt nb_global_node = mesh.getNbGlobalNodes();
 
   std::stringstream sstr; sstr << id << ":jacobian_matrix";
   jacobian_matrix = new SparseMatrix(nb_global_node * spatial_dimension, _symmetric,
 					 spatial_dimension, sstr.str(), memory_id);
   //  dof_synchronizer->initGlobalDOFEquationNumbers();
   jacobian_matrix->buildProfile(mesh, *dof_synchronizer);
 
 #ifdef AKANTU_USE_MUMPS
   std::stringstream sstr_solv; sstr_solv << id << ":solver";
   solver = new SolverMumps(*jacobian_matrix, sstr_solv.str());
 
   dof_synchronizer->initScatterGatherCommunicationScheme();
 #else
   AKANTU_DEBUG_ERROR("You should at least activate one solver.");
 #endif //AKANTU_USE_MUMPS
 
   solver->initialize(options);
 #endif //AKANTU_HAS_SOLVER
 }
 
 
 /* -------------------------------------------------------------------------- */
 /**
  * Initialize the implicit solver, either for dynamic or static cases,
  *
  * @param dynamic
  */
 void SolidMechanicsModel::initImplicit(bool dynamic, SolverOptions & solver_options) {
   AKANTU_DEBUG_IN();
 
   method = dynamic ? _implicit_dynamic : _static;
 
   initSolver(solver_options);
 
   if(method == _implicit_dynamic) {
     if(integrator) delete integrator;
     integrator = new TrapezoidalRule2();
 
     std::stringstream sstr; sstr << id << ":stiffness_matrix";
     stiffness_matrix = new SparseMatrix(*jacobian_matrix, sstr.str(), memory_id);
   } else {
     stiffness_matrix = jacobian_matrix;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initialAcceleration() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_INFO("Solving Ma = f");
 
   Solver * acc_solver = NULL;
 
   std::stringstream sstr; sstr << id << ":tmp_mass_matrix";
   SparseMatrix * tmp_mass = new SparseMatrix(*mass_matrix, sstr.str(), memory_id);
 
 #ifdef AKANTU_USE_MUMPS
   std::stringstream sstr_solver; sstr << id << ":solver_mass_matrix";
   acc_solver = new SolverMumps(*mass_matrix, sstr_solver.str());
 
   dof_synchronizer->initScatterGatherCommunicationScheme();
 #else
   AKANTU_DEBUG_ERROR("You should at least activate one solver.");
 #endif //AKANTU_USE_MUMPS
 
   acc_solver->initialize();
 
   tmp_mass->applyBoundary(*boundary);
 
   acc_solver->setRHS(*residual);
   acc_solver->solve(*acceleration);
 
   delete acc_solver;
   delete tmp_mass;
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleStiffnessMatrix() {
   AKANTU_DEBUG_IN();
 
   stiffness_matrix->clear();
 
   // call compute stiffness matrix on each local elements
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     (*mat_it)->assembleStiffnessMatrix(_not_ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::solveDynamic() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL,
 		      "You should first initialize the implicit solver and assemble the stiffness matrix");
   AKANTU_DEBUG_ASSERT(mass_matrix != NULL,
 		      "You should first initialize the implicit solver and assemble the mass matrix");
 
   if(!increment) setIncrementFlagOn();
 
   updateResidualInternal();
 
   solveDynamic<NewmarkBeta::_displacement_corrector>(*increment);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::solveStatic() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_INFO("Solving Ku = f");
   AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL,
 		      "You should first initialize the implicit solver and assemble the stiffness matrix");
 
   UInt nb_nodes = displacement->getSize();
   UInt nb_degree_of_freedom = displacement->getNbComponent();
 
   stiffness_matrix->applyBoundary(*boundary);
 
   if(method != _static)
     jacobian_matrix->copyContent(*stiffness_matrix);
 
   solver->setRHS(*residual);
 
   if(!increment) setIncrementFlagOn();
 
   solver->solve(*increment);
 
   Real * increment_val     = increment->values;
   Real * displacement_val  = displacement->values;
   bool * boundary_val      = boundary->values;
 
   for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) {
     if(!(*boundary_val)) {
       *displacement_val += *increment_val;
     }
 
     displacement_val++;
     boundary_val++;
     increment_val++;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance) {
   Real error;
   bool tmp = testConvergenceIncrement(tolerance, error);
 
   AKANTU_DEBUG_INFO("Norm of increment : " << error);
 
   return tmp;
 }
 
 /* -------------------------------------------------------------------------- */
 bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance, Real & error) {
   AKANTU_DEBUG_IN();
 
   UInt nb_nodes = displacement->getSize();
   UInt nb_degree_of_freedom = displacement->getNbComponent();
 
   error = 0;
   Real norm[2] = {0., 0.};
   Real * increment_val    = increment->storage();
   bool * boundary_val     = boundary->storage();
   Real * displacement_val = displacement->storage();
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     bool is_local_node = mesh.isLocalOrMasterNode(n);
     for (UInt d = 0; d < nb_degree_of_freedom; ++d) {
       if(!(*boundary_val) && is_local_node) {
 	norm[0] += *increment_val * *increment_val;
 	norm[1] += *displacement_val * *displacement_val;
       }
       boundary_val++;
       increment_val++;
       displacement_val++;
     }
   }
 
   StaticCommunicator::getStaticCommunicator().allReduce(norm, 2, _so_sum);
 
   norm[0] = sqrt(norm[0]);
   norm[1] = sqrt(norm[1]);
   AKANTU_DEBUG_ASSERT(!Math::isnan(norm[0]), "Something goes wrong in the solve phase");
 
 
   AKANTU_DEBUG_OUT();
   error = norm[0] / norm[1];
   return (error < tolerance);
 }
 
 /* -------------------------------------------------------------------------- */
 bool SolidMechanicsModel::testConvergenceResidual(Real tolerance) {
   Real error;
   bool tmp = testConvergenceResidual(tolerance, error);
 
   AKANTU_DEBUG_INFO("Norm of residual : " << error);
 
   return tmp;
 }
 
 /* -------------------------------------------------------------------------- */
 bool SolidMechanicsModel::testConvergenceResidual(Real tolerance, Real & norm) {
   AKANTU_DEBUG_IN();
 
   UInt nb_nodes = residual->getSize();
 
   norm = 0;
   Real * residual_val = residual->values;
   bool * boundary_val = boundary->values;
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     bool is_local_node = mesh.isLocalOrMasterNode(n);
     if(is_local_node) {
       for (UInt d = 0; d < spatial_dimension; ++d) {
 	if(!(*boundary_val)) {
 	  norm += *residual_val * *residual_val;
 	}
 	boundary_val++;
 	residual_val++;
       }
     } else {
       boundary_val += spatial_dimension;
       residual_val += spatial_dimension;
     }
   }
 
   StaticCommunicator::getStaticCommunicator().allReduce(&norm, 1, _so_sum);
 
   norm = sqrt(norm);
 
   AKANTU_DEBUG_ASSERT(!Math::isnan(norm), "Something goes wrong in the solve phase");
 
   AKANTU_DEBUG_OUT();
   return (norm < tolerance);
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::implicitPred() {
   AKANTU_DEBUG_IN();
 
   integrator->integrationSchemePred(time_step,
 				    *displacement,
 				    *velocity,
 				    *acceleration,
 				    *boundary);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::implicitCorr() {
   AKANTU_DEBUG_IN();
 
   integrator->integrationSchemeCorrDispl(time_step,
 					 *displacement,
 					 *velocity,
 					 *acceleration,
 					 *boundary,
 					 *increment);
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* Information                                                                */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::synchronizeBoundaries() {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT(synch_registry,"Synchronizer registry was not initialized."
 		      << " Did you call initParallel?");
   synch_registry->synchronize(_gst_smm_boundary);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::synchronizeResidual() {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT(synch_registry,"Synchronizer registry was not initialized."
 		      << " Did you call initPBC?");
   synch_registry->synchronize(_gst_smm_res);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::setIncrementFlagOn() {
   AKANTU_DEBUG_IN();
 
   if(!increment) {
     UInt nb_nodes = mesh.getNbNodes();
     std::stringstream sstr_inc; sstr_inc << id << ":increment";
     increment = &(alloc<Real>(sstr_inc.str(), nb_nodes, spatial_dimension, 0));
   }
 
   increment_flag = true;
 
   AKANTU_DEBUG_OUT();
 }
 
 
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getStableTimeStep() {
   AKANTU_DEBUG_IN();
 
   Real min_dt = getStableTimeStep(_not_ghost);
 
   /// reduction min over all processors
   StaticCommunicator::getStaticCommunicator().allReduce(&min_dt, 1, _so_min);
 
   AKANTU_DEBUG_OUT();
   return min_dt;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getStableTimeStep(const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   Material ** mat_val = &(materials.at(0));
   Real min_dt = std::numeric_limits<Real>::max();
 
   Real * coord    = mesh.getNodes().values;
   Real * disp_val = displacement->values;
 
   Element elem;
   elem.ghost_type = ghost_type;
 
   Mesh::type_iterator it  = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type);
   for(; it != end; ++it) {
     elem.type = *it;
     UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it);
     UInt nb_element           = mesh.getNbElement(*it);
 
     UInt * conn         = mesh.getConnectivity(*it, ghost_type).storage();
     UInt * elem_mat_val = element_material(*it, ghost_type).storage();
 
     Real * u = new Real[nb_nodes_per_element*spatial_dimension];
 
     for (UInt el = 0; el < nb_element; ++el) {
       UInt el_offset  = el * nb_nodes_per_element;
       elem.element = el;
       for (UInt n = 0; n < nb_nodes_per_element; ++n) {
 	UInt offset_conn = conn[el_offset + n] * spatial_dimension;
 	memcpy(u + n * spatial_dimension,
 	       coord + offset_conn,
 	       spatial_dimension * sizeof(Real));
 
 	for (UInt i = 0; i < spatial_dimension; ++i) {
 	  u[n * spatial_dimension + i] += disp_val[offset_conn + i];
 	}
       }
 
       Real el_size    = getFEM().getElementInradius(u, *it);
       Real el_dt      = mat_val[elem_mat_val[el]]->getStableTimeStep(el_size, elem);
       min_dt = min_dt > el_dt ? el_dt : min_dt;
     }
 
     delete [] u;
   }
 
   AKANTU_DEBUG_OUT();
   return min_dt;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getPotentialEnergy() {
   AKANTU_DEBUG_IN();
   Real energy = 0.;
 
   /// call update residual on each local elements
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     energy += (*mat_it)->getPotentialEnergy();
   }
 
   /// reduction sum over all processors
   StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _so_sum);
 
   AKANTU_DEBUG_OUT();
   return energy;
 }
 
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getKineticEnergy() {
   AKANTU_DEBUG_IN();
 
   Real ekin = 0.;
 
   UInt nb_nodes = mesh.getNbNodes();
 
   Real * vel_val  = velocity->values;
   Real * mass_val = mass->values;
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     Real mv2 = 0;
     bool is_local_node = mesh.isLocalOrMasterNode(n);
     bool is_not_pbc_slave_node = !getIsPBCSlaveNode(n);
+    bool count_node = is_local_node && is_not_pbc_slave_node;
     for (UInt i = 0; i < spatial_dimension; ++i) {
-      //      if(is_local_node) {
-      mv2 += is_local_node * is_not_pbc_slave_node * *vel_val * *vel_val * *mass_val;
-      //      }
+      mv2 += count_node * *vel_val * *vel_val * *mass_val;
+
       vel_val++;
       mass_val++;
     }
     ekin += mv2;
   }
 
   StaticCommunicator::getStaticCommunicator().allReduce(&ekin, 1, _so_sum);
 
   AKANTU_DEBUG_OUT();
   return ekin * .5;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getExternalWork() {
   AKANTU_DEBUG_IN();
 
   Real * velo = velocity->storage();
   Real * forc = force->storage();
   Real * resi = residual->storage();
   bool * boun = boundary->storage();
 
   Real work = 0.;
 
   UInt nb_nodes = mesh.getNbNodes();
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     bool is_local_node = mesh.isLocalOrMasterNode(n);
     bool is_not_pbc_slave_node = !getIsPBCSlaveNode(n);
     bool count_node = is_local_node && is_not_pbc_slave_node;
 
     for (UInt i = 0; i < spatial_dimension; ++i) {
       if(*boun)
 	work -= count_node * *resi * *velo * time_step;
       else
 	work += count_node * *forc * *velo * time_step;
 
       ++velo;
       ++forc;
       ++resi;
       ++boun;
     }
   }
 
   StaticCommunicator::getStaticCommunicator().allReduce(&work, 1, _so_sum);
 
   AKANTU_DEBUG_OUT();
   return work;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getEnergy(std::string id) {
   AKANTU_DEBUG_IN();
 
   if (id == "kinetic") {
     return getKineticEnergy();
   } else if (id == "external work"){
     return getExternalWork();
   }
 
   Real energy = 0.;
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     energy += (*mat_it)->getEnergy(id);
   }
 
   /// reduction sum over all processors
   StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _so_sum);
 
   AKANTU_DEBUG_OUT();
   return energy;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::onNodesAdded(const Vector<UInt> & nodes_list) {
   AKANTU_DEBUG_IN();
   UInt nb_nodes = mesh.getNbNodes();
 
   if(displacement) displacement->resize(nb_nodes);
   if(mass        ) mass        ->resize(nb_nodes);
   if(velocity    ) velocity    ->resize(nb_nodes);
   if(acceleration) acceleration->resize(nb_nodes);
   if(force       ) force       ->resize(nb_nodes);
   if(residual    ) residual    ->resize(nb_nodes);
   if(boundary    ) boundary    ->resize(nb_nodes);
 
   if(increment_acceleration) increment_acceleration->resize(nb_nodes);
   if(increment) increment->resize(nb_nodes);
 
   delete dof_synchronizer;
   dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension);
   dof_synchronizer->initLocalDOFEquationNumbers();
   dof_synchronizer->initGlobalDOFEquationNumbers();
 
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     (*mat_it)->onNodesAdded(nodes_list);
   }
 
   if(method != _explicit_dynamic) AKANTU_DEBUG_TO_IMPLEMENT();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::onElementsAdded(const Vector<Element> & element_list) {
   AKANTU_DEBUG_IN();
 
   getFEM().initShapeFunctions(_not_ghost);
-  getFEM().initShapeFunctions(_ghost);
 
+  getFEM().initShapeFunctions(_ghost);
 
   Vector<Element>::const_iterator<Element> it  = element_list.begin();
   Vector<Element>::const_iterator<Element> end = element_list.end();
   for (; it != end; ++it) {
     const Element & elem = *it;
     element_material(elem.type, elem.ghost_type).push_back(UInt(0));
     element_index_by_material(elem.type, elem.ghost_type).push_back(UInt(0));
   }
 
 
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     (*mat_it)->onElementsAdded(element_list);
   }
 
   if(method != _explicit_dynamic) AKANTU_DEBUG_TO_IMPLEMENT();
 
   AKANTU_DEBUG_OUT();
 }
 
+/* -------------------------------------------------------------------------- */
+void SolidMechanicsModel::onElementsRemoved(const Vector<Element> & element_list,
+					    const ByElementTypeUInt & new_numbering) {
+  element_material.onElementsRemoved(new_numbering);
+  //  element_index_by_material.onElementsRemoved(new_numbering);
+
+  std::cout << "NbNodes before purify " <<  mesh.getNbNodes() << std::endl;
+  //  MeshUtils::purifyMesh(mesh);
+  std::cout << "NbNodes after purify " <<  mesh.getNbNodes() << std::endl;
+
+  getFEM().initShapeFunctions(_not_ghost);
+  getFEM().initShapeFunctions(_ghost);
+
+}
+
+/* -------------------------------------------------------------------------- */
+void SolidMechanicsModel::onNodesRemoved(const Vector<UInt> & element_list,
+					 const Vector<UInt> & new_numbering) {
+  std::cout << "NbNodes in u before purify " <<  displacement->getSize() << " " << element_list.getSize() << " " << mesh.getNbNodes() << std::endl;
+  if(displacement) mesh.removeNodesFromVector(*displacement, new_numbering);
+  std::cout << "NbNodes in u after purify " <<  displacement->getSize() << std::endl;
+  if(mass        ) mesh.removeNodesFromVector(*mass        , new_numbering);
+  if(velocity    ) mesh.removeNodesFromVector(*velocity    , new_numbering);
+  if(acceleration) mesh.removeNodesFromVector(*acceleration, new_numbering);
+  if(force       ) mesh.removeNodesFromVector(*force       , new_numbering);
+  if(residual    ) mesh.removeNodesFromVector(*residual    , new_numbering);
+  if(boundary    ) mesh.removeNodesFromVector(*boundary    , new_numbering);
+
+  if(increment_acceleration) mesh.removeNodesFromVector(*increment_acceleration, new_numbering);
+  if(increment)              mesh.removeNodesFromVector(*increment             , new_numbering);
+
+  delete dof_synchronizer;
+  dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension);
+  dof_synchronizer->initLocalDOFEquationNumbers();
+  dof_synchronizer->initGlobalDOFEquationNumbers();
+}
+
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   stream << space << "Solid Mechanics Model [" << std::endl;
   stream << space << " + id                : " << id << std::endl;
   stream << space << " + spatial dimension : " << spatial_dimension << std::endl;
   stream << space << " + fem [" << std::endl;
   getFEM().printself(stream, indent + 2);
   stream << space << AKANTU_INDENT << "]" << std::endl;
   stream << space << " + nodals information [" << std::endl;
   displacement->printself(stream, indent + 2);
   mass        ->printself(stream, indent + 2);
   velocity    ->printself(stream, indent + 2);
   acceleration->printself(stream, indent + 2);
   force       ->printself(stream, indent + 2);
   residual    ->printself(stream, indent + 2);
   boundary    ->printself(stream, indent + 2);
   stream << space << AKANTU_INDENT << "]" << std::endl;
 
   stream << space << " + connectivity type information [" << std::endl;
   element_material.printself(stream, indent + 2);
   stream << space << AKANTU_INDENT << "]" << std::endl;
 
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/solid_mechanics_model.hh b/src/model/solid_mechanics/solid_mechanics_model.hh
index d34c12dff..58703f48f 100644
--- a/src/model/solid_mechanics/solid_mechanics_model.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model.hh
@@ -1,557 +1,579 @@
 /**
  * @file   solid_mechanics_model.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date[creation]            Thu Jul 22 11:51:06 2010
  * @date[last modification]   Thu Oct 14 14:00:06 2010
  *
  * @brief  Model of Solid Mechanics
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_SOLID_MECHANICS_MODEL_HH__
 #define __AKANTU_SOLID_MECHANICS_MODEL_HH__
 
 
 /* -------------------------------------------------------------------------- */
 #include <fstream>
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "model.hh"
 #include "data_accessor.hh"
 #include "integrator_gauss.hh"
 #include "shape_lagrange.hh"
 #include "integrator_cohesive.hh"
 #include "shape_cohesive.hh"
 #include "aka_types.hh"
 #include "integration_scheme_2nd_order.hh"
 #include "solver.hh"
 
 /* -------------------------------------------------------------------------- */
 namespace akantu {
   class Material;
   class IntegrationScheme2ndOrder;
   class Contact;
   class SparseMatrix;
 }
 
 __BEGIN_AKANTU__
 
 class SolidMechanicsModel : public Model, public DataAccessor, public MeshEventHandler {
 
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   typedef FEMTemplate<IntegratorGauss,ShapeLagrange> MyFEMType;
   typedef FEMTemplate< IntegratorCohesive<IntegratorGauss>, ShapeCohesive<ShapeLagrange> > MyFEMCohesiveType;
 
   SolidMechanicsModel(Mesh & mesh,
 		      UInt spatial_dimension = 0,
 		      const ID & id = "solid_mechanics_model",
 		      const MemoryID & memory_id = 0);
 
   virtual ~SolidMechanicsModel();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// initialize completely the model
   virtual void initFull(std::string material_file,
 			AnalysisMethod method = _explicit_dynamic);
 
   /// initialize the fem object needed for boundary conditions
   void initFEMBoundary(bool create_surface = true);
 
   /// register the tags associated with the parallel synchronizer
   void initParallel(MeshPartition * partition, DataAccessor * data_accessor=NULL);
 
   /// allocate all vectors
   void initVectors();
 
   /// initialize all internal arrays for materials
   void initMaterials();
 
   /// initialize the model
   virtual void initModel();
 
   /// init PBC synchronizer
   void initPBC();
 
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /* ------------------------------------------------------------------------ */
   /* PBC                                                                      */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// change the equation number for proper assembly when using PBC
   void changeEquationNumberforPBC(std::map<UInt,UInt> & pbc_pair);
 
   /// synchronize Residual for output
   void synchronizeResidual();
 
 protected:
 
   /// register PBC synchronizer
   void registerPBCSynchronizer();
 
   /* ------------------------------------------------------------------------ */
   /* Explicit                                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialize the stuff for the explicit scheme
   void initExplicit();
 
   /// initialize the array needed by updateResidual (residual, current_position)
   void initializeUpdateResidualData();
 
   /// update the current position vector
   void updateCurrentPosition();
 
   /// assemble the residual for the explicit scheme
   void updateResidual(bool need_initialize = true);
 
   /**
    * \brief compute the acceleration from the residual
    * this function is the explicit equivalent to solveDynamic in implicit
    * In the case of lumped mass just divide the residual by the mass
    * In the case of not lumped mass call solveDynamic<_acceleration_corrector>
    */
   void updateAcceleration();
 
   /// Solve the system @f[ A x = \alpha b @f] with A a lumped matrix
   void solveLumped(Vector<Real> & x, 
 		   const Vector<Real> & A,
 		   const Vector<Real> & b,
 		   const Vector<bool> & boundary,
 		   Real alpha);
 
   /// explicit integration predictor
   void explicitPred();
 
   /// explicit integration corrector
   void explicitCorr();
 
   /* ------------------------------------------------------------------------ */
   /* Implicit                                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// initialize the solver and the jacobian_matrix (called by initImplicit)
   void initSolver(SolverOptions & options = _solver_no_options);
 
   /// initialize the stuff for the implicit solver
   void initImplicit(bool dynamic = false,
                     SolverOptions & solver_options = _solver_no_options);
 
   /// solve Ma = f to get the initial acceleration
   void initialAcceleration();
 
   /// assemble the stiffness matrix
   void assembleStiffnessMatrix();
 
   /// solve @f[ A\delta u = f_ext - f_int @f] in displacement
   void solveDynamic();
 
   /// solve Ku = f
   void solveStatic();
 
   /// test the convergence (norm of increment)
   bool testConvergenceIncrement(Real tolerance);
   bool testConvergenceIncrement(Real tolerance, Real & error);
 
   /// test the convergence (norm of residual)
   bool testConvergenceResidual(Real tolerance);
   bool testConvergenceResidual(Real tolerance, Real & error);
 
   /// implicit time integration predictor
   void implicitPred();
 
   /// implicit time integration corrector
   void implicitCorr();
 
 protected:
   /// finish the computation of residual to solve in increment
   void updateResidualInternal();
 
   /// compute A and solve @f[ A\delta u = f_ext - f_int @f]
   template<NewmarkBeta::IntegrationSchemeCorrectorType type>
   void solveDynamic(Vector<Real> & increment);
 
 
   /* ------------------------------------------------------------------------ */
   /* Boundaries (solid_mechanics_model_boundary.cc)                           */
   /* ------------------------------------------------------------------------ */
 public:
   class SurfaceLoadFunctor {
   public:
     virtual void traction(__attribute__ ((unused)) const types::Vector<Real> & position,
 			  __attribute__ ((unused)) types::Vector<Real> & traction,
 			  __attribute__ ((unused)) const types::Vector<Real> & normal,
 			  __attribute__ ((unused)) Surface surface_id) {
       AKANTU_DEBUG_TO_IMPLEMENT();
     }
 
     virtual void stress(__attribute__ ((unused)) const types::Vector<Real> & position,
 			__attribute__ ((unused)) types::Matrix & stress,
 			__attribute__ ((unused)) const types::Vector<Real> & normal,
 			__attribute__ ((unused)) Surface surface_id) {
       AKANTU_DEBUG_TO_IMPLEMENT();
     }
   };
 
   /// compute force vector from a function(x,y,z) that describe stresses
   void computeForcesFromFunction(BoundaryFunction in_function,
 				 BoundaryFunctionType function_type) __attribute__((deprecated));
 
   template<class Functor>
   void computeForcesFromFunction(Functor & functor, BoundaryFunctionType function_type);
 
   /// integrate a force on the boundary by providing a stress tensor
   void computeForcesByStressTensor(const Vector<Real> & stresses,
 				   const ElementType & type,
 				   const GhostType & ghost_type);
 
   /// integrate a force on the boundary by providing a traction vector
   void computeForcesByTractionVector(const Vector<Real> & tractions,
 				     const ElementType & type,
 				     const GhostType & ghost_type);
 
   /// synchronize the ghost element boundaries values
   void synchronizeBoundaries();
 
   /* ------------------------------------------------------------------------ */
   /* Materials (solid_mechanics_model_material.cc)                            */
   /* ------------------------------------------------------------------------ */
 public:
   /// register a material in the dynamic database
   Material & registerNewMaterial(const ID & mat_type,
 				 const std::string & opt_param = "");
 
   template <typename M>
   Material & registerNewCustomMaterial(const ID & mat_type,
 				       const std::string & opt_param = "");
   /// read the material files to instantiate all the materials
   void readMaterials(const std::string & filename);
 
   /// read a custom material with a keyword and class as template
   template <typename M>
   UInt readCustomMaterial(const std::string & filename,
 				const std::string & keyword);
 
   /// Use a UIntData in the mesh to specify the material to use per element
   void setMaterialIDsFromIntData(const std::string & data_name);
 
 protected:
   // /// read properties part of a material file and create the material
   // template <typename M>
   // Material * readMaterialProperties(std::ifstream & infile,
   // 				    ID mat_id,
   // 				    UInt &current_line);
 
   /* ------------------------------------------------------------------------ */
   /* Mass (solid_mechanics_model_mass.cc)                                     */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// assemble the lumped mass matrix
   void assembleMassLumped();
 
   /// assemble the mass matrix
   void assembleMass();
 
 
 protected:
   /// assemble the lumped mass matrix for local and ghost elements
   void assembleMassLumped(GhostType ghost_type);
 
   void assembleMass(GhostType ghost_type);
 
   /// fill a vector of rho
   void computeRho(Vector<Real> & rho,
 		  ElementType type,
 		  GhostType ghost_type);
 
 
   /* ------------------------------------------------------------------------ */
   /* Data Accessor inherited members                                          */
   /* ------------------------------------------------------------------------ */
 public:
 
-  inline virtual UInt getNbDataToPack(const Element & element,
-				      SynchronizationTag tag) const;
-
-  inline virtual UInt getNbDataToUnpack(const Element & element,
-					SynchronizationTag tag) const;
+  inline virtual UInt getNbDataForElements(const Vector<Element> & elements,
+					   SynchronizationTag tag) const;
 
-  inline virtual void packData(CommunicationBuffer & buffer,
-			       const Element & element,
-			       SynchronizationTag tag) const;
+  inline virtual void packElementData(CommunicationBuffer & buffer,
+				      const Vector<Element> & elements,
+				      SynchronizationTag tag) const;
 
-  inline virtual void unpackData(CommunicationBuffer & buffer,
-				 const Element & element,
-				 SynchronizationTag tag);
+  inline virtual void unpackElementData(CommunicationBuffer & buffer,
+					const Vector<Element> & elements,
+					SynchronizationTag tag);
 
   inline virtual UInt getNbDataToPack(SynchronizationTag tag) const;
-
   inline virtual UInt getNbDataToUnpack(SynchronizationTag tag) const;
 
   inline virtual void packData(CommunicationBuffer & buffer,
 			       const UInt index,
 			       SynchronizationTag tag) const;
 
   inline virtual void unpackData(CommunicationBuffer & buffer,
 				 const UInt index,
 				 SynchronizationTag tag);
 
+protected:
+  inline void splitElementByMaterial(const Vector<Element> & elements,
+				     Vector<Element> * elements_per_mat) const;
+
+
+  template<typename T>
+  inline void packElementDataHelper(Vector<T> & data_to_pack,
+				    CommunicationBuffer & buffer,
+				    const Vector<Element> & element) const;
+
+  /* -------------------------------------------------------------------------- */
+  template<typename T>
+  inline void unpackElementDataHelper(Vector<T> & data_to_unpack,
+				      CommunicationBuffer & buffer,
+				      const Vector<Element> & element) const;
+
+  /* -------------------------------------------------------------------------- */
+  template<typename T, bool pack_helper>
+  inline void packUnpackElementDataHelper(Vector<T> & data,
+					  CommunicationBuffer & buffer,
+					  const Vector<Element> & element) const;
 
   /* ------------------------------------------------------------------------ */
   /* Mesh Event Handler inherited members                                     */
   /* ------------------------------------------------------------------------ */
 protected:
   virtual void onNodesAdded  (const Vector<UInt> & nodes_list);
+  virtual void onNodesRemoved(const Vector<UInt> & element_list,
+			      const Vector<UInt> & new_numbering);
 
   virtual void onElementsAdded  (const Vector<Element> & nodes_list);
+  virtual void onElementsRemoved(const Vector<Element> & element_list,
+				 const ByElementTypeUInt & new_numbering);
+
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// return the dimension of the system space
   AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt);
 
   /// get the current value of the time step
   AKANTU_GET_MACRO(TimeStep, time_step, Real);
   /// set the value of the time step
   AKANTU_SET_MACRO(TimeStep, time_step, Real);
 
   /// get the value of the conversion from forces/ mass to acceleration
   AKANTU_GET_MACRO(F_M2A, f_m2a, Real);
   /// set the value of the conversion from forces/ mass to acceleration
   AKANTU_SET_MACRO(F_M2A, f_m2a, Real);
 
   /// get the SolidMechanicsModel::displacement vector
   AKANTU_GET_MACRO(Displacement,    *displacement,           Vector<Real> &);
   /// get the SolidMechanicsModel::current_position vector \warn only consistent
   /// after a call to SolidMechanicsModel::updateCurrentPosition
   AKANTU_GET_MACRO(CurrentPosition, *current_position, const Vector<Real> &);
   /// get  the SolidMechanicsModel::increment  vector \warn  only  consistent if
   /// SolidMechanicsModel::setIncrementFlagOn has been called before
   AKANTU_GET_MACRO(Increment,       *increment,              Vector<Real> &);
   /// get the lumped SolidMechanicsModel::mass vector
   AKANTU_GET_MACRO(Mass,            *mass,                   Vector<Real> &);
   /// get the SolidMechanicsModel::velocity vector
   AKANTU_GET_MACRO(Velocity,        *velocity,               Vector<Real> &);
   /// get    the    SolidMechanicsModel::acceleration    vector,   updated    by
   /// SolidMechanicsModel::updateAcceleration
   AKANTU_GET_MACRO(Acceleration,    *acceleration,           Vector<Real> &);
   /// get the SolidMechanicsModel::force vector (boundary forces)
   AKANTU_GET_MACRO(Force,           *force,                  Vector<Real> &);
   /// get     the    SolidMechanicsModel::residual    vector,     computed    by
   /// SolidMechanicsModel::updateResidual
   AKANTU_GET_MACRO(Residual,        *residual,               Vector<Real> &);
   /// get the SolidMechanicsModel::boundary vector
   AKANTU_GET_MACRO(Boundary,        *boundary,               Vector<bool> &);
   /// get the SolidMechnicsModel::incrementAcceleration vector
   AKANTU_GET_MACRO(IncrementAcceleration, *increment_acceleration, Vector<Real> &);
 
   /// get the value of the SolidMechanicsModel::increment_flag
   AKANTU_GET_MACRO(IncrementFlag, increment_flag, bool);
 
   /// get  the SolidMechanicsModel::element_material  vector corresponding  to a
   /// given akantu::ElementType
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementMaterial, element_material, UInt);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementMaterial, element_material, UInt);
 
   /// vectors containing local material element index for each global element index
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementIndexByMaterial, element_index_by_material, UInt);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementIndexByMaterial, element_index_by_material, UInt);
 
   /// get a particular material
   inline Material & getMaterial(UInt mat_index);
   inline const Material & getMaterial(UInt mat_index) const;
 
   /// give the number of materials
   inline UInt getNbMaterials() const { return materials.size(); };
 
   /// give the material internal index from its id
   Int getInternalIndexFromID(const ID & id) const;
 
   /// compute the stable time step
   Real getStableTimeStep();
 
   /// compute the potential energy
   Real getPotentialEnergy();
 
   /// compute the kinetic energy
   Real getKineticEnergy();
 
   /// compute the external work (for impose displacement, the velocity should be given too)
   Real getExternalWork();
 
   /// get the energies
   Real getEnergy(std::string id);
 
   /// set the Contact object
   AKANTU_SET_MACRO(Contact, contact, Contact *);
 
   /**
    * @brief set the SolidMechanicsModel::increment_flag  to on, the activate the
    * update of the SolidMechanicsModel::increment vector
    */
   void setIncrementFlagOn();
 
   /// get the stiffness matrix
   AKANTU_GET_MACRO(StiffnessMatrix, *stiffness_matrix, SparseMatrix &);
 
   /// get the mass matrix
   AKANTU_GET_MACRO(MassMatrix, *mass_matrix, SparseMatrix &);
 
   inline FEM & getFEMBoundary(std::string name = "");
 
   /// get integrator
   AKANTU_GET_MACRO(Integrator, *integrator, const IntegrationScheme2ndOrder &);
 
   /// get access to the internal solver
   AKANTU_GET_MACRO(Solver, *solver, Solver &);
 
 protected:
   /// compute the stable time step
   Real getStableTimeStep(const GhostType & ghost_type);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
 
   /// time step
   Real time_step;
 
   /// conversion coefficient form force/mass to acceleration
   Real f_m2a;
 
   /// displacements array
   Vector<Real> * displacement;
 
   /// lumped mass array
   Vector<Real> * mass;
 
   /// velocities array
   Vector<Real> * velocity;
 
   /// accelerations array
   Vector<Real> * acceleration;
 
   /// accelerations array
   Vector<Real> * increment_acceleration;
 
   /// forces array
   Vector<Real> * force;
 
   /// residuals array
   Vector<Real> * residual;
 
   /// boundaries array
   Vector<bool> * boundary;
 
   /// array of current position used during update residual
   Vector<Real> * current_position;
 
   /// mass matrix
   SparseMatrix * mass_matrix;
 
   /// velocity damping matrix
   SparseMatrix * velocity_damping_matrix;
 
   /// stiffness matrix
   SparseMatrix * stiffness_matrix;
 
   /// jacobian matrix @f[A = cM + dD + K@f] with @f[c = \frac{1}{\beta \Delta t^2}, d = \frac{\gamma}{\beta \Delta t} @f]
   SparseMatrix * jacobian_matrix;
 
   /// materials of all elements
   ByElementTypeUInt element_material;
 
   /// vectors containing local material element index for each global element index
   ByElementTypeUInt element_index_by_material;
 
   /// list of used materials
   std::vector<Material *> materials;
 
   /// integration scheme of second order used
   IntegrationScheme2ndOrder * integrator;
 
   /// increment of displacement
   Vector<Real> * increment;
 
   /// flag defining if the increment must be computed or not
   bool increment_flag;
 
   /// solver for implicit
   Solver * solver;
 
   /// object to resolve the contact
   Contact * contact;
 
   /// the spatial dimension
   UInt spatial_dimension;
 
   /// Mesh
   Mesh & mesh;
 
   AnalysisMethod method;
 };
 
 __END_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 #include "parser.hh"
 #include "material.hh"
 
 __BEGIN_AKANTU__
 
 #include "solid_mechanics_model_tmpl.hh"
 
 #if defined (AKANTU_INCLUDE_INLINE_IMPL)
 #  include "solid_mechanics_model_inline_impl.cc"
 #endif
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const SolidMechanicsModel & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 __END_AKANTU__
 
 #endif /* __AKANTU_SOLID_MECHANICS_MODEL_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc
index 5714ed8d0..0227f2d71 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc
@@ -1,448 +1,526 @@
 /**
  * @file   solid_mechanics_model_inline_impl.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Jul 29 12:07:04 2010
  *
  * @brief  Implementation of the inline functions of the SolidMechanicsModel class
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 inline Material & SolidMechanicsModel::getMaterial(UInt mat_index) {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT(mat_index < materials.size(),
 		      "The model " << id << " has no material no "<< mat_index);
   AKANTU_DEBUG_OUT();
   return *materials[mat_index];
 }
 
 /* -------------------------------------------------------------------------- */
 inline const Material & SolidMechanicsModel::getMaterial(UInt mat_index) const {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT(mat_index < materials.size(),
 		      "The model " << id << " has no material no "<< mat_index);
   AKANTU_DEBUG_OUT();
   return *materials[mat_index];
 }
 
 
 /* -------------------------------------------------------------------------- */
 inline FEM & SolidMechanicsModel::getFEMBoundary(std::string name) {
   return dynamic_cast<FEM &>(getFEMClassBoundary<MyFEMType>(name));
 }
 
 /* -------------------------------------------------------------------------- */
-inline UInt SolidMechanicsModel::getNbDataToPack(const Element & element,
-						 SynchronizationTag tag) const {
-  AKANTU_DEBUG_IN();
+inline void SolidMechanicsModel::splitElementByMaterial(const Vector<Element> & elements,
+						 Vector<Element> * elements_per_mat) const {
+  ElementType current_element_type = _not_defined;
+  GhostType current_ghost_type = _casper;
+  UInt * elem_mat = NULL;
+
+  Vector<Element>::const_iterator<Element> it  = elements.begin();
+  Vector<Element>::const_iterator<Element> end = elements.end();
+  for (; it != end; ++it) {
+    const Element & el = *it;
+    if(el.type != current_element_type || el.ghost_type != current_ghost_type) {
+      current_element_type = el.type;
+      current_ghost_type   = el.ghost_type;
+      elem_mat = element_material(el.type, el.ghost_type).storage();
+    }
+    elements_per_mat[elem_mat[el.element]].push_back(el);
+  }
+}
 
-  UInt size = 0;
-  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type);
+/* -------------------------------------------------------------------------- */
+template<typename T>
+inline void SolidMechanicsModel::packElementDataHelper(Vector<T> & data_to_pack,
+						       CommunicationBuffer & buffer,
+						       const Vector<Element> & element) const {
+  packUnpackElementDataHelper<T, true>(data_to_pack, buffer, element);
+}
 
-#ifndef AKANTU_NDEBUG
-  size += spatial_dimension * sizeof(Real); /// position of the barycenter of the element (only for check)
-#endif
+/* -------------------------------------------------------------------------- */
+template<typename T>
+inline void SolidMechanicsModel::unpackElementDataHelper(Vector<T> & data_to_unpack,
+							 CommunicationBuffer & buffer,
+							 const Vector<Element> & element) const {
+  packUnpackElementDataHelper<T, false>(data_to_unpack, buffer, element);
+}
 
-  switch(tag) {
-  case _gst_smm_mass: {
-    size += nb_nodes_per_element * sizeof(Real) * spatial_dimension; // mass vector
-    break;
-  }
-  case _gst_smm_for_strain: {
-    size += nb_nodes_per_element * spatial_dimension * sizeof(Real); // displacement
+/* -------------------------------------------------------------------------- */
+template<typename T, bool pack_helper>
+inline void SolidMechanicsModel::packUnpackElementDataHelper(Vector<T> & data,
+							     CommunicationBuffer & buffer,
+							     const Vector<Element> & elements) const {
+  UInt nb_component = data.getNbComponent();
+  UInt nb_nodes_per_element = 0;
+
+  ElementType current_element_type = _not_defined;
+  GhostType current_ghost_type = _casper;
+  UInt * conn = NULL;
+
+  Vector<Element>::const_iterator<Element> it  = elements.begin();
+  Vector<Element>::const_iterator<Element> end = elements.end();
+  for (; it != end; ++it) {
+    const Element & el = *it;
+    if(el.type != current_element_type || el.ghost_type != current_ghost_type) {
+      current_element_type = el.type;
+      current_ghost_type   = el.ghost_type;
+      conn = mesh.getConnectivity(el.type, el.ghost_type).storage();
+      nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type);
+    }
 
-    UInt mat = element_material(element.type, _not_ghost)(element.element);
-    // Element mat_element = element;
-    // mat_element.element = element_index_by_material(element.type, _not_ghost)(element.element);
-    size += materials[mat]->getNbDataToPack(element, tag);
-    break;
-  }
-  case _gst_smm_boundary: {
-    // force, displacement, boundary
-    size += nb_nodes_per_element * spatial_dimension * (2 * sizeof(Real) + sizeof(bool));
-    break;
-  }
-  default: {
-    UInt mat = element_material(element.type, _not_ghost)(element.element);
-    // Element mat_element = element;
-    // mat_element.element = element_index_by_material(element.type, _not_ghost)(element.element);
-    size += materials[mat]->getNbDataToPack(element, tag);
-  }
-  }
+    UInt el_offset  = el.element * nb_nodes_per_element;
+    for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+      UInt offset_conn = conn[el_offset + n];
+      types::Vector<T> data_vect(data.storage() + offset_conn * nb_component,
+				 nb_component);
 
-  AKANTU_DEBUG_OUT();
-  return size;
+      if(pack_helper)
+	buffer << data_vect;
+      else
+	buffer >> data_vect;
+    }
+  }
 }
 
 /* -------------------------------------------------------------------------- */
-inline UInt SolidMechanicsModel::getNbDataToUnpack(const Element & element,
-						   SynchronizationTag tag) const {
+inline UInt SolidMechanicsModel::getNbDataForElements(const Vector<Element> & elements,
+						      SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
   UInt size = 0;
-  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type);
 
 #ifndef AKANTU_NDEBUG
-  size += spatial_dimension * sizeof(Real); /// position of the barycenter of the element (only for check)
+  size += elements.getSize() * spatial_dimension * sizeof(Real); /// position of the barycenter of the element (only for check)
 #endif
 
+  UInt nb_nodes_per_element = 0;
+
+  Vector<Element>::const_iterator<Element> it  = elements.begin();
+  Vector<Element>::const_iterator<Element> end = elements.end();
+  for (; it != end; ++it) {
+    const Element & el = *it;
+    nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type);
+  }
+
   switch(tag) {
   case _gst_smm_mass: {
     size += nb_nodes_per_element * sizeof(Real) * spatial_dimension; // mass vector
     break;
   }
   case _gst_smm_for_strain: {
     size += nb_nodes_per_element * spatial_dimension * sizeof(Real); // displacement
 
-    UInt mat = element_material(element.type, _ghost)(element.element);
-    // Element mat_element = element;
-    // mat_element.element = element_index_by_material(element.type, _not_ghost)(element.element);
-    size += materials[mat]->getNbDataToUnpack(element, tag);
-    break;
+    //UInt mat = element_material(element.type, _not_ghost)(element.element);
+    //size += materials[mat]->getNbDataToPack(element, tag);
+   break;
   }
   case _gst_smm_boundary: {
     // force, displacement, boundary
     size += nb_nodes_per_element * spatial_dimension * (2 * sizeof(Real) + sizeof(bool));
     break;
   }
-  default: {
-    UInt mat = element_material(element.type, _ghost)(element.element);
-    // Element mat_element = element;
-    // mat_element.element = element_index_by_material(element.type, _not_ghost)(element.element);
-    size += materials[mat]->getNbDataToUnpack(element, tag);
+  default: {  }
   }
+
+
+  Vector<Element> * elements_per_mat = new Vector<Element>[materials.size()];
+  this->splitElementByMaterial(elements, elements_per_mat);
+
+  for (UInt i = 0; i < materials.size(); ++i) {
+    size += materials[i]->getNbDataForElements(elements_per_mat[i], tag);
   }
+  delete [] elements_per_mat;
 
   AKANTU_DEBUG_OUT();
   return size;
 }
 
 /* -------------------------------------------------------------------------- */
-inline void SolidMechanicsModel::packData(CommunicationBuffer & buffer,
-					  const Element & element,
-					  SynchronizationTag tag) const {
+inline void SolidMechanicsModel::packElementData(CommunicationBuffer & buffer,
+						 const Vector<Element> & elements,
+						 SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
-  GhostType ghost_type = _not_ghost;
+  // GhostType ghost_type = _not_ghost;
 
-  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type);
-  UInt el_offset  = element.element * nb_nodes_per_element;
-  UInt * conn  = mesh.getConnectivity(element.type, ghost_type).storage();
+  // UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type);
+  // UInt el_offset  = element.element * nb_nodes_per_element;
+  // UInt * conn  = mesh.getConnectivity(element.type, ghost_type).storage();
 
 #ifndef AKANTU_NDEBUG
-  types::RVector barycenter(spatial_dimension);
-  mesh.getBarycenter(element.element, element.type, barycenter.storage(), ghost_type);
-  buffer << barycenter;
+  Vector<Element>::const_iterator<Element> bit  = elements.begin();
+  Vector<Element>::const_iterator<Element> bend = elements.end();
+  for (; bit != bend; ++bit) {
+    const Element & element = *bit;
+    types::RVector barycenter(spatial_dimension);
+    mesh.getBarycenter(element.element, element.type, barycenter.storage(), element.ghost_type);
+    buffer << barycenter;
+  }
 #endif
 
   switch(tag) {
   case _gst_smm_mass: {
-    for (UInt n = 0; n < nb_nodes_per_element; ++n) {
-      UInt offset_conn = conn[el_offset + n];
-      Vector<Real>::iterator<types::RVector> it_mass = mass->begin(spatial_dimension);
-      buffer << it_mass[offset_conn];
-    }
+    packElementDataHelper(*mass, buffer, elements);
+    // for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+    //   UInt offset_conn = conn[el_offset + n];
+    //   Vector<Real>::iterator<types::RVector> it_mass = mass->begin(spatial_dimension);
+    //   buffer << it_mass[offset_conn];
+    // }
     break;
   }
   case _gst_smm_for_strain: {
-    Vector<Real>::iterator<types::RVector> it_disp = displacement->begin(spatial_dimension);
-    for (UInt n = 0; n < nb_nodes_per_element; ++n) {
-      UInt offset_conn = conn[el_offset + n];
-      buffer << it_disp[offset_conn];
-    }
-
-    UInt mat = element_material(element.type, ghost_type)(element.element);
-    Element mat_element = element;
-    mat_element.element = element_index_by_material(element.type, ghost_type)(element.element);
-    materials[mat]->packData(buffer, mat_element, tag);
+    packElementDataHelper(*displacement, buffer, elements);
+    // Vector<Real>::iterator<types::RVector> it_disp = displacement->begin(spatial_dimension);
+    // for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+    //   UInt offset_conn = conn[el_offset + n];
+    //   buffer << it_disp[offset_conn];
+    // }
+
+    // UInt mat = element_material(element.type, ghost_type)(element.element);
+    // Element mat_element = element;
+    // mat_element.element = element_index_by_material(element.type, ghost_type)(element.element);
+    // materials[mat]->packData(buffer, mat_element, tag);
     break;
   }
   case _gst_smm_boundary: {
-    Vector<Real>::iterator<types::RVector> it_force = force->begin(spatial_dimension);
-    Vector<Real>::iterator<types::RVector> it_velocity = velocity->begin(spatial_dimension);
-    Vector<bool>::iterator<types::Vector<bool> > it_boundary = boundary->begin(spatial_dimension);
-
-    for (UInt n = 0; n < nb_nodes_per_element; ++n) {
-      UInt offset_conn = conn[el_offset + n];
-
-      buffer << it_force   [offset_conn];
-      buffer << it_velocity[offset_conn];
-      buffer << it_boundary[offset_conn];
-    }
+    packElementDataHelper(*force, buffer, elements);
+    packElementDataHelper(*velocity, buffer, elements);
+    packElementDataHelper(*boundary, buffer, elements);
+    // Vector<Real>::iterator<types::RVector> it_force = force->begin(spatial_dimension);
+    // Vector<Real>::iterator<types::RVector> it_velocity = velocity->begin(spatial_dimension);
+    // Vector<bool>::iterator<types::Vector<bool> > it_boundary = boundary->begin(spatial_dimension);
+
+    // for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+    //   UInt offset_conn = conn[el_offset + n];
+
+    //   buffer << it_force   [offset_conn];
+    //   buffer << it_velocity[offset_conn];
+    //   buffer << it_boundary[offset_conn];
+    // }
     break;
   }
   default: {
-    UInt mat = element_material(element.type, ghost_type)(element.element);
-    Element mat_element = element;
-    mat_element.element = element_index_by_material(element.type, ghost_type)(element.element);
-    materials[mat]->packData(buffer, mat_element, tag);
+    // UInt mat = element_material(element.type, ghost_type)(element.element);
+    // Element mat_element = element;
+    // mat_element.element = element_index_by_material(element.type, ghost_type)(element.element);
+    // materials[mat]->packData(buffer, mat_element, tag);
     //AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
+  Vector<Element> * elements_per_mat = new Vector<Element>[materials.size()];
+  splitElementByMaterial(elements, elements_per_mat);
+
+  for (UInt i = 0; i < materials.size(); ++i) {
+    materials[i]->packElementData(buffer, elements_per_mat[i], tag);
+  }
+
+  delete [] elements_per_mat;
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
-inline void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer,
-					    const Element & element,
-					    SynchronizationTag tag) {
+inline void SolidMechanicsModel::unpackElementData(CommunicationBuffer & buffer,
+						   const Vector<Element> & elements,
+						   SynchronizationTag tag) {
   AKANTU_DEBUG_IN();
 
-  GhostType ghost_type = _ghost;
+  // GhostType ghost_type = _ghost;
 
-  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type);
-  UInt el_offset  = element.element * nb_nodes_per_element;
-  UInt * conn  = mesh.getConnectivity(element.type, ghost_type).values;
+  // UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type);
+  // UInt el_offset  = element.element * nb_nodes_per_element;
+  // UInt * conn  = mesh.getConnectivity(element.type, ghost_type).values;
 
 #ifndef AKANTU_NDEBUG
-  types::RVector barycenter_loc(spatial_dimension);
-  mesh.getBarycenter(element.element, element.type, barycenter_loc.storage(), ghost_type);
-
-  types::RVector barycenter(spatial_dimension);
-  buffer >> barycenter;
-  Real tolerance = 1e-15;
-  for (UInt i = 0; i < spatial_dimension; ++i) {
-    if(!(std::abs(barycenter(i) - barycenter_loc(i)) <= tolerance))
-      AKANTU_DEBUG_ERROR("Unpacking an unknown value for the element: "
-			 << element
-			 << "(barycenter[" << i << "] = " << barycenter_loc(i)
-			 << " and buffer[" << i << "] = " << barycenter(i) << ") - tag: " << tag);
+  Vector<Element>::const_iterator<Element> bit  = elements.begin();
+  Vector<Element>::const_iterator<Element> bend = elements.end();
+  for (; bit != bend; ++bit) {
+    const Element & element = *bit;
+
+    types::RVector barycenter_loc(spatial_dimension);
+    mesh.getBarycenter(element.element, element.type, barycenter_loc.storage(), element.ghost_type);
+
+    types::RVector barycenter(spatial_dimension);
+    buffer >> barycenter;
+    Real tolerance = 1e-15;
+    for (UInt i = 0; i < spatial_dimension; ++i) {
+      if(!(std::abs(barycenter(i) - barycenter_loc(i)) <= tolerance))
+	AKANTU_DEBUG_ERROR("Unpacking an unknown value for the element: "
+			   << element
+			   << "(barycenter[" << i << "] = " << barycenter_loc(i)
+			   << " and buffer[" << i << "] = " << barycenter(i) << ") - tag: " << tag);
+    }
   }
 #endif
 
   switch(tag) {
   case _gst_smm_mass: {
-    for (UInt n = 0; n < nb_nodes_per_element; ++n) {
-      UInt offset_conn = conn[el_offset + n];
-      Vector<Real>::iterator<types::RVector> it_mass = mass->begin(spatial_dimension);
-      buffer >> it_mass[offset_conn];
-    }
+    unpackElementDataHelper(*mass, buffer, elements);
+    // for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+    //   UInt offset_conn = conn[el_offset + n];
+    //   Vector<Real>::iterator<types::RVector> it_mass = mass->begin(spatial_dimension);
+    //   buffer >> it_mass[offset_conn];
+    // }
     break;
   }
   case _gst_smm_for_strain: {
-    Vector<Real>::iterator<types::RVector> it_disp = displacement->begin(spatial_dimension);
-    for (UInt n = 0; n < nb_nodes_per_element; ++n) {
-      UInt offset_conn = conn[el_offset + n];
-      buffer >> it_disp[offset_conn];
-    }
-
-    UInt mat = element_material(element.type, ghost_type)(element.element);
-    Element mat_element = element;
-    mat_element.element = element_index_by_material(element.type, ghost_type)(element.element);
-    materials[mat]->unpackData(buffer, mat_element, tag);
+    unpackElementDataHelper(*displacement, buffer, elements);
+    // Vector<Real>::iterator<types::RVector> it_disp = displacement->begin(spatial_dimension);
+    // for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+    //   UInt offset_conn = conn[el_offset + n];
+    //   buffer >> it_disp[offset_conn];
+    // }
+
+    // UInt mat = element_material(element.type, ghost_type)(element.element);
+    // Element mat_element = element;
+    // mat_element.element = element_index_by_material(element.type, ghost_type)(element.element);
+    // materials[mat]->unpackData(buffer, mat_element, tag);
     break;
   }
   case _gst_smm_boundary: {
-    Vector<Real>::iterator<types::RVector> it_force = force->begin(spatial_dimension);
-    Vector<Real>::iterator<types::RVector> it_velocity = velocity->begin(spatial_dimension);
-    Vector<bool>::iterator<types::Vector<bool> > it_boundary = boundary->begin(spatial_dimension);
-
-    for (UInt n = 0; n < nb_nodes_per_element; ++n) {
-      UInt offset_conn = conn[el_offset + n];
-
-      buffer >> it_force   [offset_conn];
-      buffer >> it_velocity[offset_conn];
-      buffer >> it_boundary[offset_conn];
-    }
+    unpackElementDataHelper(*force, buffer, elements);
+    unpackElementDataHelper(*velocity, buffer, elements);
+    unpackElementDataHelper(*boundary, buffer, elements);
+    // Vector<Real>::iterator<types::RVector> it_force = force->begin(spatial_dimension);
+    // Vector<Real>::iterator<types::RVector> it_velocity = velocity->begin(spatial_dimension);
+    // Vector<bool>::iterator<types::Vector<bool> > it_boundary = boundary->begin(spatial_dimension);
+
+    // for (UInt n = 0; n < nb_nodes_per_element; ++n) {
+    //   UInt offset_conn = conn[el_offset + n];
+
+    //   buffer >> it_force   [offset_conn];
+    //   buffer >> it_velocity[offset_conn];
+    //   buffer >> it_boundary[offset_conn];
+    // }
     break;
   }
   default: {
-    UInt mat = element_material(element.type, ghost_type)(element.element);
-    Element mat_element = element;
-    mat_element.element = element_index_by_material(element.type, ghost_type)(element.element);
-    materials[mat]->unpackData(buffer, mat_element, tag);
+    // UInt mat = element_material(element.type, ghost_type)(element.element);
+    // Element mat_element = element;
+    // mat_element.element = element_index_by_material(element.type, ghost_type)(element.element);
+    // materials[mat]->unpackData(buffer, mat_element, tag);
     //AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
+  Vector<Element> * elements_per_mat = new Vector<Element>[materials.size()];
+  splitElementByMaterial(elements, elements_per_mat);
+
+  for (UInt i = 0; i < materials.size(); ++i) {
+    materials[i]->unpackElementData(buffer, elements_per_mat[i], tag);
+  }
+
+  delete [] elements_per_mat;
+
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 inline UInt SolidMechanicsModel::getNbDataToPack(SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
   UInt size = 0;
   //  UInt nb_nodes = mesh.getNbNodes();
 
   switch(tag) {
   case _gst_smm_uv: {
     size += sizeof(Real) * spatial_dimension * 2;
     break;
   }
   case _gst_smm_res: {
     size += sizeof(Real) * spatial_dimension;
     break;
   }
   case _gst_smm_mass: {
     size += sizeof(Real) * spatial_dimension;
     break;
   }
   default: {
     AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
-  
+
   AKANTU_DEBUG_OUT();
   return size;
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt SolidMechanicsModel::getNbDataToUnpack(SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
   UInt size = 0;
   //  UInt nb_nodes = mesh.getNbNodes();
 
   switch(tag) {
   case _gst_smm_uv: {
     size += sizeof(Real) * spatial_dimension * 2;
     break;
   }
   case _gst_smm_res: {
     size += sizeof(Real) * spatial_dimension;
     break;
   }
   case _gst_smm_mass: {
     size += sizeof(Real) * spatial_dimension;
     break;
   }
   default: {
     AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
   AKANTU_DEBUG_OUT();
   return size;
 }
 
 /* -------------------------------------------------------------------------- */
 inline void SolidMechanicsModel::packData(CommunicationBuffer & buffer,
 					  const UInt index,
 					  SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
   switch(tag) {
   case _gst_smm_uv: {
     Vector<Real>::iterator<types::RVector> it_disp = displacement->begin(spatial_dimension);
     Vector<Real>::iterator<types::RVector> it_velo = velocity->begin(spatial_dimension);
     buffer << it_disp[index];
     buffer << it_velo[index];
     break;
   }
   case _gst_smm_res: {
     Vector<Real>::iterator<types::RVector> it_res = residual->begin(spatial_dimension);
     buffer << it_res[index];
     break;
   }
   case _gst_smm_mass: {
     AKANTU_DEBUG_INFO("pack mass of node " << index << " which is " << (*mass)(index,0));
     Vector<Real>::iterator<types::RVector> it_mass = mass->begin(spatial_dimension);
     buffer << it_mass[index];
     break;
   }
   default: {
     AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 inline void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer,
 					    const UInt index,
 					    SynchronizationTag tag) {
   AKANTU_DEBUG_IN();
 
   switch(tag) {
   case _gst_smm_uv: {
     Vector<Real>::iterator<types::RVector> it_disp = displacement->begin(spatial_dimension);
     Vector<Real>::iterator<types::RVector> it_velo = velocity->begin(spatial_dimension);
     buffer >> it_disp[index];
     buffer >> it_velo[index];
     break;
   }
   case _gst_smm_res: {
     Vector<Real>::iterator<types::RVector> it_res = residual->begin(spatial_dimension);
     buffer >> it_res[index];
     break;
   }
   case _gst_smm_mass: {
     AKANTU_DEBUG_INFO("mass of node " << index << " was " << (*mass)(index,0));
     Vector<Real>::iterator<types::RVector> it_mass = mass->begin(spatial_dimension);
     buffer >> it_mass[index];
     AKANTU_DEBUG_INFO("mass of node " << index << " is now " << (*mass)(index,0));
     break;
   }
   default: {
     AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 __END_AKANTU__
 #include "sparse_matrix.hh"
 #include "solver.hh"
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<NewmarkBeta::IntegrationSchemeCorrectorType type>
 void SolidMechanicsModel::solveDynamic(Vector<Real> & increment) {
   AKANTU_DEBUG_INFO("Solving Ma + Cv + Ku = f");
 
   NewmarkBeta * nmb_int = dynamic_cast<NewmarkBeta *>(integrator);
   Real c = nmb_int->getAccelerationCoefficient<type>(time_step);
   Real d = nmb_int->getVelocityCoefficient<type>(time_step);
   Real e = nmb_int->getDisplacementCoefficient<type>(time_step);
 
   // A = c M + d C + e K
   jacobian_matrix->clear();
 
   if(type != NewmarkBeta::_acceleration_corrector)
     jacobian_matrix->add(*stiffness_matrix, e);
 
   jacobian_matrix->add(*mass_matrix, c);
 
   mass_matrix->saveMatrix("M.mtx");
   if(velocity_damping_matrix)
     jacobian_matrix->add(*velocity_damping_matrix, d);
 
   jacobian_matrix->applyBoundary(*boundary);
 
 #ifndef AKANTU_NDEBUG
   if(AKANTU_DEBUG_TEST(dblDump))
     jacobian_matrix->saveMatrix("J.mtx");
 #endif
 
   jacobian_matrix->saveMatrix("J.mtx");
 
   solver->setRHS(*residual);
 
   // solve A w = f
   solver->solve(increment);
 }
 /* -------------------------------------------------------------------------- */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_mass.cc b/src/model/solid_mechanics/solid_mechanics_model_mass.cc
index d2bedaaf6..e8cfa277b 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_mass.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_mass.cc
@@ -1,154 +1,154 @@
 /**
  * @file   solid_mechanics_model_mass.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Mon Oct  4 15:21:23 2010
  *
  * @brief  function handling mass computation
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "solid_mechanics_model.hh"
 #include "material.hh"
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleMassLumped() {
   AKANTU_DEBUG_IN();
 
   UInt nb_nodes = mesh.getNbNodes();
   mass->clear();
 
   assembleMassLumped(_not_ghost);
   assembleMassLumped(_ghost);
 
   /// for not connected nodes put mass to one in order to avoid
   /// wrong range in paraview
   Real * mass_values = mass->values;
   for (UInt i = 0; i < nb_nodes; ++i) {
     if (fabs(mass_values[i]) < std::numeric_limits<Real>::epsilon() || Math::isnan(mass_values[i]))
       mass_values[i] = 1.;
   }
 
   synch_registry->synchronize(_gst_smm_mass);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleMassLumped(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   FEM & fem = getFEM();
 
   Vector<Real> rho_1(0,1);
 
   Mesh::type_iterator it  = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type);
   for(; it != end; ++it) {
     ElementType type = *it;
 
     computeRho(rho_1, type, ghost_type);
 
     AKANTU_DEBUG_ASSERT(dof_synchronizer,
 			"DOFSynchronizer number must not be initialized");
     fem.assembleFieldLumped(rho_1, spatial_dimension,*mass,
 			    dof_synchronizer->getLocalDOFEquationNumbers(),
 			    type, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleMass() {
   AKANTU_DEBUG_IN();
 
   //  if(!dof_synchronizer) dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension);
   //  UInt nb_global_node = mesh.getNbGlobalNodes();
 
   std::stringstream sstr; sstr << id << ":mass_matrix";
   //    mass_matrix = new SparseMatrix(nb_global_node * spatial_dimension, _symmetric,
   //                                   spatial_dimension, sstr.str(), memory_id);
   //    mass_matrix->buildProfile(mesh, *dof_synchronizer);
   mass_matrix = new SparseMatrix(*jacobian_matrix, sstr.str(), memory_id);
 
   assembleMass(_not_ghost);
   //  assembleMass(_ghost);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleMass(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MyFEMType & fem = getFEMClass<MyFEMType>();
 
   Vector<Real> rho_1(0,1);
   //UInt nb_element;
   mass_matrix->clear();
 
   Mesh::type_iterator it  = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type);
   for(; it != end; ++it) {
     ElementType type = *it;
 
     computeRho(rho_1, type, ghost_type);
     fem.assembleFieldMatrix(rho_1, spatial_dimension, *mass_matrix, type, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::computeRho(Vector<Real> & rho,
 				     ElementType type,
 				     GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Material ** mat_val = &(materials.at(0));
 
   FEM & fem = getFEM();
   UInt nb_element = fem.getMesh().getNbElement(type,ghost_type);
 
-  UInt * elem_mat_val = element_material(type, ghost_type).storage();
+  Vector<UInt> & elem_mat_val = element_material(type, ghost_type);
 
   UInt nb_quadrature_points = fem.getNbQuadraturePoints(type, ghost_type);
 
   rho.resize(nb_element * nb_quadrature_points);
   Real * rho_1_val = rho.values;
 
   /// compute @f$ rho @f$ for each nodes of each element
   for (UInt el = 0; el < nb_element; ++el) {
-    Real mat_rho = mat_val[elem_mat_val[el]]->getParam<Real>("rho"); /// here rho is constant in an element
+    Real mat_rho = mat_val[elem_mat_val(el)]->getParam<Real>("rho"); /// here rho is constant in an element
 
     for (UInt n = 0; n < nb_quadrature_points; ++n) {
       *rho_1_val++ = mat_rho;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 __END_AKANTU__
diff --git a/src/solver/sparse_matrix.cc b/src/solver/sparse_matrix.cc
index 7de9a4929..6a42505f0 100644
--- a/src/solver/sparse_matrix.cc
+++ b/src/solver/sparse_matrix.cc
@@ -1,429 +1,429 @@
 /**
  * @file   sparse_matrix.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Tue Oct 26 18:25:07 2010
  *
  * @brief  implementation of the SparseMatrix class
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include <fstream>
 /* -------------------------------------------------------------------------- */
 #include "sparse_matrix.hh"
 #include "static_communicator.hh"
 #include "dof_synchronizer.hh"
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 SparseMatrix::SparseMatrix(UInt size,
 			   const SparseMatrixType & sparse_matrix_type,
 			   UInt nb_degree_of_freedom,
 			   const ID & id,
 			   const MemoryID & memory_id) :
   Memory(memory_id), id(id),
   sparse_matrix_type(sparse_matrix_type),
   nb_degree_of_freedom(nb_degree_of_freedom),
   size(size),
   nb_non_zero(0),
   irn(0,1,"irn"), jcn(0,1,"jcn"), a(0,1,"A") {
   AKANTU_DEBUG_IN();
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   nb_proc = comm.getNbProc();
   dof_synchronizer = NULL;
 
   irn_save = NULL;
   jcn_save = NULL;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 SparseMatrix::SparseMatrix(const SparseMatrix & matrix,
 			   const ID & id,
 			   const MemoryID & memory_id) :
   Memory(memory_id), id(id),
   sparse_matrix_type(matrix.sparse_matrix_type),
   nb_degree_of_freedom(matrix.nb_degree_of_freedom),
   size(matrix.size),
   nb_proc(matrix.nb_proc),
   nb_non_zero(matrix.nb_non_zero),
   irn(matrix.irn, true), jcn(matrix.jcn, true), a(matrix.getA(), true),
   irn_jcn_k(matrix.irn_jcn_k) {
   AKANTU_DEBUG_IN();
 
   size_save = 0;
   irn_save = NULL;
   jcn_save = NULL;
   dof_synchronizer = matrix.dof_synchronizer;
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 SparseMatrix::~SparseMatrix() {
   AKANTU_DEBUG_IN();
 
   //  if (irn_jcn_to_k) delete irn_jcn_to_k;
   if(irn_save) delete irn_save;
   if(jcn_save) delete jcn_save;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SparseMatrix::buildProfile(const Mesh & mesh, const DOFSynchronizer & dof_synchronizer) {
   AKANTU_DEBUG_IN();
 
   // if(irn_jcn_to_k) delete irn_jcn_to_k;
   // irn_jcn_to_k = new std::map<std::pair<UInt, UInt>, UInt>;
   clearProfile();
 
   this->dof_synchronizer = &const_cast<DOFSynchronizer &>(dof_synchronizer);
 
   coordinate_list_map::iterator irn_jcn_k_it;
 
   Int * eq_nb_val = dof_synchronizer.getGlobalDOFEquationNumbers().values;
 
   Mesh::type_iterator it  = mesh.firstType(mesh.getSpatialDimension(), _not_ghost, _ek_not_defined);
   Mesh::type_iterator end = mesh.lastType (mesh.getSpatialDimension(), _not_ghost, _ek_not_defined);
   for(; it != end; ++it) {
   
     UInt nb_element = mesh.getNbElement(*it);
     UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it);
     UInt size_mat = nb_nodes_per_element * nb_degree_of_freedom;
 
     UInt * conn_val = mesh.getConnectivity(*it, _not_ghost).values;
     Int * local_eq_nb_val = new Int[nb_degree_of_freedom * nb_nodes_per_element];
 
 
     for (UInt e = 0; e < nb_element; ++e) {
       Int * tmp_local_eq_nb_val = local_eq_nb_val;
       for (UInt i = 0; i < nb_nodes_per_element; ++i) {
 	UInt n = conn_val[i];
 	for (UInt d = 0; d < nb_degree_of_freedom; ++d) {
 	  *tmp_local_eq_nb_val++ = eq_nb_val[n * nb_degree_of_freedom + d];
 	}
 	// memcpy(tmp_local_eq_nb_val, eq_nb_val + n * nb_degree_of_freedom, nb_degree_of_freedom * sizeof(Int));
 	// tmp_local_eq_nb_val += nb_degree_of_freedom;
       }
 
       for (UInt i = 0; i < size_mat; ++i) {
 	UInt c_irn = local_eq_nb_val[i];
 	if(c_irn < size) {
 	  UInt j_start = (sparse_matrix_type == _symmetric) ? i : 0;
 	  for (UInt j = j_start; j < size_mat; ++j) {
 	    UInt c_jcn = local_eq_nb_val[j];
 	    if(c_jcn < size) {
 	      KeyCOO irn_jcn = key(c_irn, c_jcn);
 	      irn_jcn_k_it = irn_jcn_k.find(irn_jcn);
 
 	      if (irn_jcn_k_it == irn_jcn_k.end()) {
 		irn_jcn_k[irn_jcn] = nb_non_zero;
 		irn.push_back(c_irn + 1);
 		jcn.push_back(c_jcn + 1);
 		nb_non_zero++;
 	      }
 	    }
 	  }
 	}
       }
       conn_val += nb_nodes_per_element;
     }
 
     delete [] local_eq_nb_val;
   }
 
   for (UInt i = 0; i < size; ++i) {
     KeyCOO irn_jcn = key(i, i);
     irn_jcn_k_it = irn_jcn_k.find(irn_jcn);
     if(irn_jcn_k_it == irn_jcn_k.end()) {
       irn_jcn_k[irn_jcn] = nb_non_zero;
       irn.push_back(i + 1);
       jcn.push_back(i + 1);
       nb_non_zero++;
     }
   }
 
   a.resize(nb_non_zero);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SparseMatrix::applyBoundary(const Vector<bool> & boundary) {
   AKANTU_DEBUG_IN();
 
   const DOFSynchronizer::GlobalEquationNumberMap & local_eq_num_to_global = dof_synchronizer->getGlobalEquationNumberToLocal();
   Int * irn_val = irn.values;
   Int * jcn_val = jcn.values;
   Real * a_val   = a.values;
 
   for (UInt i = 0; i < nb_non_zero; ++i) {
     UInt ni = local_eq_num_to_global.find(*irn_val - 1)->second;
     UInt nj = local_eq_num_to_global.find(*jcn_val - 1)->second;
     if(boundary.values[ni]  || boundary.values[nj]) {
      if (*irn_val != *jcn_val) *a_val = 0;
      else {
        if(dof_synchronizer->getDOFTypes()(ni) >= 0) *a_val = 0;
        else *a_val = 1;
      }
     }
     irn_val++; jcn_val++; a_val++;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SparseMatrix::removeBoundary(const Vector<bool> & boundary) {
   AKANTU_DEBUG_IN();
 
   if(irn_save) delete irn_save;
   if(jcn_save) delete jcn_save;
 
   irn_save = new Vector<Int>(irn, true);
   jcn_save = new Vector<Int>(jcn, true);
 
   UInt n = boundary.getSize()*boundary.getNbComponent();
 
   UInt * perm = new UInt[n];
 
   size_save = size;
   size = 0;
   for (UInt i = 0; i < n; ++i) {
     if(!boundary.values[i]) {
       perm[i] = size;
       //      std::cout <<  "perm["<< i <<"] = " << size << std::endl;
       size++;
     }
   }
 
   for (UInt i = 0; i < nb_non_zero;) {
-    if(boundary.values[irn.at(i) - 1] || boundary.values[jcn.at(i) - 1]) {
+    if(boundary.values[irn(i) - 1] || boundary.values[jcn(i) - 1]) {
       irn.erase(i);
       jcn.erase(i);
       a.erase(i);
       nb_non_zero--;
     } else {
-      irn.values[i] = perm[irn.values[i] - 1] + 1;
-      jcn.values[i] = perm[jcn.values[i] - 1] + 1;
+      irn(i) = perm[irn(i) - 1] + 1;
+      jcn(i) = perm[jcn(i) - 1] + 1;
       i++;
     }
   }
 
   delete [] perm;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SparseMatrix::restoreProfile() {
   AKANTU_DEBUG_IN();
 
   irn.resize(irn_save->getSize());
   jcn.resize(jcn_save->getSize());
 
   nb_non_zero = irn.getSize();
   a.resize(nb_non_zero);
   size = size_save;
 
   memcpy(irn.values, irn_save->values, irn.getSize()*sizeof(Int));
   memcpy(jcn.values, jcn_save->values, jcn.getSize()*sizeof(Int));
 
   delete irn_save; irn_save = NULL;
   delete jcn_save; jcn_save = NULL;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SparseMatrix::saveProfile(const std::string & filename) const {
   AKANTU_DEBUG_IN();
 
   std::ofstream outfile;
   outfile.open(filename.c_str());
 
   outfile << "%%MatrixMarket matrix coordinate pattern";
 
   if(sparse_matrix_type == _symmetric) outfile << " symmetric";
   else outfile << " general";
   outfile << std::endl;
 
   UInt m = size;
   outfile << m << " " << m << " " << nb_non_zero << std::endl;
 
   for (UInt i = 0; i < nb_non_zero; ++i) {
     outfile << irn.values[i] << " " << jcn.values[i] << " 1" << std::endl;
   }
 
   outfile.close();
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void SparseMatrix::saveMatrix(const std::string & filename) const {
   AKANTU_DEBUG_IN();
 
   std::ofstream outfile;
   outfile.precision(std::numeric_limits<Real>::digits10);
 
   outfile.open(filename.c_str());
 
   outfile << "%%MatrixMarket matrix coordinate real";
 
   if(sparse_matrix_type == _symmetric) outfile << " symmetric";
   else outfile << " general";
   outfile << std::endl;
 
   outfile << size << " " << size << " " << nb_non_zero << std::endl;
 
   for (UInt i = 0; i < nb_non_zero; ++i) {
     outfile << irn(i) << " " << jcn(i) << " " << a(i) << std::endl;
   }
 
   outfile.close();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Vector<Real> & operator*=(Vector<Real> & vect, const SparseMatrix & mat) {
   AKANTU_DEBUG_IN();
 
   // AKANTU_DEBUG_ASSERT((vect.getSize()*vect.getNbComponent() == mat.getSize()) &&
   // 		      (vect.getNbComponent() == mat.getNbDegreOfFreedom()),
   // 		      "The size of the matrix and the vector do not match");
 
   const SparseMatrixType & sparse_matrix_type = mat.getSparseMatrixType();
   DOFSynchronizer * dof_synchronizer = mat.getDOFSynchronizerPointer();
 
   UInt nb_non_zero = mat.getNbNonZero();
   Real * tmp = new Real [vect.getNbComponent() * vect.getSize()];
   std::fill_n(tmp, vect.getNbComponent() * vect.getSize(), 0);
 
   Int * i_val  = mat.getIRN().values;
   Int * j_val  = mat.getJCN().values;
   Real * a_val = mat.getA().values;
 
   Real * vect_val = vect.values;
 
   for (UInt k = 0; k < nb_non_zero; ++k) {
     UInt i = *(i_val++);
     UInt j = *(j_val++);
     Real a = *(a_val++);
 
     UInt local_i = i - 1;
     UInt local_j = j - 1;
     if(dof_synchronizer) {
       local_i = dof_synchronizer->getDOFLocalID(local_i);
       local_j = dof_synchronizer->getDOFLocalID(local_j);
     }
 
     tmp[local_i] += a * vect_val[local_j];
     if(sparse_matrix_type == _symmetric && (local_i != local_j))
       tmp[local_j] += a * vect_val[local_i];
   }
 
   memcpy(vect_val, tmp, vect.getNbComponent() * vect.getSize() * sizeof(Real));
   delete [] tmp;
 
   if(dof_synchronizer)
     dof_synchronizer->reduceSynchronize<AddOperation<Real> >(vect);
 
   AKANTU_DEBUG_OUT();
 
   return vect;
 }
 
 /* -------------------------------------------------------------------------- */
 void SparseMatrix::copyContent(const SparseMatrix & matrix) {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT(nb_non_zero == matrix.getNbNonZero(),
 		      "The to matrix don't have the same profiles");
   memcpy(a.values, matrix.getA().values, nb_non_zero * sizeof(Real));
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SparseMatrix::add(const SparseMatrix & matrix, Real alpha) {
   AKANTU_DEBUG_ASSERT(nb_non_zero == matrix.getNbNonZero(),
 		      "The to matrix don't have the same profiles");
 
   Real * a_val = a.values;
   Real * b_val = matrix.a.values;
 
   for (UInt n = 0; n < nb_non_zero; ++n) {
     *a_val++ += alpha * *b_val++;
   }
 }
 
 
 /* -------------------------------------------------------------------------- */
 void SparseMatrix::lump(Vector<Real> & lumped) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT((lumped.getNbComponent() == nb_degree_of_freedom),
 		      "The size of the matrix and the vector do not match");
 
   UInt vect_size = size / nb_degree_of_freedom;
   if(dof_synchronizer) vect_size = dof_synchronizer->getNbDOFs() / nb_degree_of_freedom;
 
   lumped.resize(vect_size);
   lumped.clear();
 
   Int * i_val  = irn.values;
   Int * j_val  = jcn.values;
   Real * a_val = a.values;
 
   Real * vect_val = lumped.values;
 
   for (UInt k = 0; k < nb_non_zero; ++k) {
     UInt i = *(i_val++);
     UInt j = *(j_val++);
     Real a = *(a_val++);
 
     UInt local_i = i - 1;
     UInt local_j = j - 1;
     if(dof_synchronizer) {
       local_i = dof_synchronizer->getDOFLocalID(local_i);
       local_j = dof_synchronizer->getDOFLocalID(local_j);
     }
 
     vect_val[local_i] += a;
     if(sparse_matrix_type == _symmetric && (i != j))
       vect_val[local_j] += a;
   }
 
   if(dof_synchronizer)
     dof_synchronizer->reduceSynchronize<AddOperation<Real> >(lumped);
 
   AKANTU_DEBUG_OUT();
 }
 
 __END_AKANTU__
diff --git a/src/synchronizer/data_accessor.hh b/src/synchronizer/data_accessor.hh
index 3381c2d00..82fdd535a 100644
--- a/src/synchronizer/data_accessor.hh
+++ b/src/synchronizer/data_accessor.hh
@@ -1,160 +1,151 @@
 /**
  * @file   data_accessor.hh
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @date   Wed Jun 15 14:43:23 2011
  *
  * @brief  Interface of accessors for pack_unpack system
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 
 #ifndef __AKANTU_DATA_ACCESSOR_HH__
 #define __AKANTU_DATA_ACCESSOR_HH__
 
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "mesh.hh"
 #include "communication_buffer.hh"
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 class DataAccessor {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   DataAccessor();
   virtual ~DataAccessor();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /**
-   * @brief get  the number of  data to send  for a given akantu::Element  and a
+   * @brief get  the number of  data to exchange  for a given akantu::Element  and a
    * given akantu::SynchronizationTag
    */
-  virtual UInt getNbDataToPack(__attribute__((unused)) const Element & element,
-                               __attribute__((unused)) SynchronizationTag tag) const {
+  virtual UInt getNbDataForElements(__attribute__((unused)) const Vector<Element> & elements,
+				    __attribute__((unused)) SynchronizationTag tag) const {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /**
    * @brief get  the number of  data to send  for a given
    * akantu::SynchronizationTag
    */
   virtual UInt getNbDataToPack(__attribute__((unused)) SynchronizationTag tag) const {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
-  /**
-   * @brief get the number of data  to receive for a given akantu::Element and a
-   * given akantu::SynchronizationTag
-   */
-  virtual UInt getNbDataToUnpack(__attribute__((unused)) const Element & element,
-				 __attribute__((unused)) SynchronizationTag tag) const {
-    AKANTU_DEBUG_TO_IMPLEMENT();
-  }
-
   /**
    * @brief get the number of data  to receive for a given
    * akantu::SynchronizationTag
    */
   virtual UInt getNbDataToUnpack(__attribute__((unused)) SynchronizationTag tag) const {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /**
    * @brief   pack  the   data  for   a  given   akantu::Element  and   a  given
    * akantu::SynchronizationTag
    */
-  virtual void packData(__attribute__((unused)) CommunicationBuffer & buffer,
-                        __attribute__((unused)) const Element & element,
-                        __attribute__((unused)) SynchronizationTag tag) const {
+  virtual void packElementData(__attribute__((unused)) CommunicationBuffer & buffer,
+			       __attribute__((unused)) const Vector<Element> & element,
+			       __attribute__((unused)) SynchronizationTag tag) const {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /**
    * @brief   pack  the   data  for   a  given  index  and   a  given
    * akantu::SynchronizationTag
    */
   virtual void packData(__attribute__((unused)) CommunicationBuffer & buffer,
 			__attribute__((unused)) const UInt index,
                         __attribute__((unused)) SynchronizationTag tag) const {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /**
    * @brief   unpack  the   data  for   a  given   akantu::Element  and   a  given
    * akantu::SynchronizationTag
    */
-  virtual void unpackData(__attribute__((unused)) CommunicationBuffer & buffer,
-                          __attribute__((unused)) const Element & element,
-                          __attribute__((unused)) SynchronizationTag tag) {
+  virtual void unpackElementData(__attribute__((unused)) CommunicationBuffer & buffer,
+				 __attribute__((unused)) const Vector<Element> & element,
+				 __attribute__((unused)) SynchronizationTag tag) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /**
    * @brief   unpack  the   data  for   a  given  index  and   a  given
    * akantu::SynchronizationTag
    */
   virtual void unpackData(__attribute__((unused)) CommunicationBuffer & buffer,
                           __attribute__((unused)) const UInt index,
                           __attribute__((unused)) SynchronizationTag tag) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
 
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 // #include "data_accessor_inline_impl.cc"
 
 // /// standard output stream operator
 // inline std::ostream & operator <<(std::ostream & stream, const DataAccessor & _this)
 // {
 //   _this.printself(stream);
 //   return stream;
 // }
 
 __END_AKANTU__
 
 #endif /* __AKANTU_DATA_ACCESSOR_HH__ */
diff --git a/src/synchronizer/distributed_synchronizer.cc b/src/synchronizer/distributed_synchronizer.cc
index 0ed9375d6..c3f411c76 100644
--- a/src/synchronizer/distributed_synchronizer.cc
+++ b/src/synchronizer/distributed_synchronizer.cc
@@ -1,927 +1,1029 @@
 /**
  * @file   distributed_synchronizer.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Thu Aug 26 16:36:21 2010
  *
  * @brief implementation of a  communicator using a static_communicator for real
  * send/receive
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "distributed_synchronizer.hh"
 #include "static_communicator.hh"
 #include "mesh_utils.hh"
 /* -------------------------------------------------------------------------- */
 #include <map>
 #include <iostream>
 
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
-DistributedSynchronizer::DistributedSynchronizer(SynchronizerID id,
-                           MemoryID memory_id) :
+DistributedSynchronizer::DistributedSynchronizer(Mesh & mesh,
+						 SynchronizerID id,
+						 MemoryID memory_id) :
   Synchronizer(id, memory_id),
-  static_communicator(&StaticCommunicator::getStaticCommunicator())
+  mesh(mesh), static_communicator(&StaticCommunicator::getStaticCommunicator())
 {
   AKANTU_DEBUG_IN();
 
   nb_proc = static_communicator->getNbProc();
   rank    = static_communicator->whoAmI();
 
-  send_element = new std::vector<Element>[nb_proc];
-  recv_element = new std::vector<Element>[nb_proc];
+  send_element = new Vector<Element>[nb_proc];
+  recv_element = new Vector<Element>[nb_proc];
+
+  mesh.registerEventHandler(*this);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 DistributedSynchronizer::~DistributedSynchronizer() {
   AKANTU_DEBUG_IN();
 
   for (UInt p = 0; p < nb_proc; ++p) {
   //   send_buffer[p].resize(0);
   //   recv_buffer[p].resize(0);
 
     send_element[p].clear();
     recv_element[p].clear();
   }
 
   // delete [] send_buffer;
   // delete [] recv_buffer;
 
   delete [] send_element;
   delete [] recv_element;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 DistributedSynchronizer * DistributedSynchronizer::
 createDistributedSynchronizerMesh(Mesh & mesh,
                                   const MeshPartition * partition,
                                   UInt root,
                                   SynchronizerID id,
                                   MemoryID memory_id) {
   AKANTU_DEBUG_IN();
 
   const UInt TAG_SIZES        = 0;
   const UInt TAG_CONNECTIVITY = 1;
   const UInt TAG_DATA         = 2;
   const UInt TAG_PARTITIONS   = 3;
   const UInt TAG_NB_NODES     = 4;
   const UInt TAG_NODES        = 5;
   const UInt TAG_COORDINATES  = 6;
   const UInt TAG_NODES_TYPE   = 7;
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   UInt nb_proc = comm.getNbProc();
   UInt my_rank = comm.whoAmI();
 
-  DistributedSynchronizer * communicator = new DistributedSynchronizer(id, memory_id);
+  DistributedSynchronizer & communicator = *(new DistributedSynchronizer(mesh, id, memory_id));
 
-  if(nb_proc == 1) return communicator;
+  if(nb_proc == 1) return &communicator;
 
   UInt * local_connectivity = NULL;
   UInt * local_partitions = NULL;
   UInt * local_data = NULL;
   Vector<UInt> * old_nodes = mesh.getNodesGlobalIdsPointer();
   Vector<Real> * nodes = mesh.getNodesPointer();
 
   UInt spatial_dimension = nodes->getNbComponent();
 
   /* ------------------------------------------------------------------------ */
   /*  Local (rank == root)                                                    */
   /* ------------------------------------------------------------------------ */
   if(my_rank == root) {
     AKANTU_DEBUG_ASSERT(partition->getNbPartition() == nb_proc,
                         "The number of partition does not match the number of processors");
 
     /**
      * connectivity and communications scheme construction
      */
     Mesh::type_iterator it  = mesh.firstType(mesh.getSpatialDimension());
     Mesh::type_iterator end = mesh.lastType(mesh.getSpatialDimension());
+    UInt count = 0;
     for(; it != end; ++it) {
       ElementType type = *it;
 
       UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
       UInt nb_element = mesh.getNbElement(*it);
       UInt nb_local_element[nb_proc];
       UInt nb_ghost_element[nb_proc];
       UInt nb_element_to_send[nb_proc];
 
       memset(nb_local_element, 0, nb_proc*sizeof(UInt));
       memset(nb_ghost_element, 0, nb_proc*sizeof(UInt));
       memset(nb_element_to_send, 0, nb_proc*sizeof(UInt));
 
       UInt * partition_num = partition->getPartition(type, _not_ghost).values;
 
       UInt * ghost_partition = partition->getGhostPartition(type, _ghost).values;
       UInt * ghost_partition_offset = partition->getGhostPartitionOffset(type, _ghost).values;
 
       UIntDataMap & uint_data_map = mesh.getUIntDataMap(type, _not_ghost);
       UInt nb_tags = uint_data_map.size();
 
       /* -------------------------------------------------------------------- */
       /// constructing the reordering structures
       for (UInt el = 0; el < nb_element; ++el) {
         nb_local_element[partition_num[el]]++;
         for (UInt part = ghost_partition_offset[el];
              part < ghost_partition_offset[el + 1];
              ++part) {
           nb_ghost_element[ghost_partition[part]]++;
         }
         nb_element_to_send[partition_num[el]] +=
           ghost_partition_offset[el + 1] - ghost_partition_offset[el] + 1;
       }
 
       /// allocating buffers
       UInt * buffers[nb_proc];
       UInt * buffers_tmp[nb_proc];
       for (UInt p = 0; p < nb_proc; ++p) {
         UInt size = nb_nodes_per_element * (nb_local_element[p] +
                                             nb_ghost_element[p]);
         buffers[p] = new UInt[size];
         buffers_tmp[p] = buffers[p];
       }
 
       /// copying the local connectivity
       UInt * conn_val = mesh.getConnectivity(type, _not_ghost).values;
       for (UInt el = 0; el < nb_element; ++el) {
         memcpy(buffers_tmp[partition_num[el]],
                conn_val + el * nb_nodes_per_element,
                nb_nodes_per_element * sizeof(UInt));
         buffers_tmp[partition_num[el]] += nb_nodes_per_element;
       }
 
       /// copying the connectivity of ghost element
       for (UInt el = 0; el < nb_element; ++el) {
         for (UInt part = ghost_partition_offset[el];
              part < ghost_partition_offset[el + 1];
              ++part) {
           UInt proc = ghost_partition[part];
           memcpy(buffers_tmp[proc],
                  conn_val + el * nb_nodes_per_element,
                  nb_nodes_per_element * sizeof(UInt));
           buffers_tmp[proc] += nb_nodes_per_element;
         }
       }
 
       UInt names_size = 0;
       UIntDataMap::iterator it_data;
       for(it_data = uint_data_map.begin(); it_data != uint_data_map.end(); ++it_data) {
         names_size += it_data->first.size() + 1;
       }
 
       /* -------->>>>-SIZE + CONNECTIVITY------------------------------------ */
        /// send all connectivity and ghost information to all processors
       std::vector<CommunicationRequest *> requests;
       for (UInt p = 0; p < nb_proc; ++p) {
         if(p != root) {
           UInt size[6];
           size[0] = (UInt) type;
           size[1] = nb_local_element[p];
           size[2] = nb_ghost_element[p];
           size[3] = nb_element_to_send[p];
           size[4] = nb_tags;
           size[5] = names_size;
-          comm.send(size, 6, p, TAG_SIZES);
+          AKANTU_DEBUG_INFO("Sending connectivities informations to proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_SIZES) <<")");
+          comm.send(size, 6, p, Tag::genTag(my_rank, count, TAG_SIZES));
 
-          AKANTU_DEBUG_INFO("Sending connectivities to proc " << p);
+          AKANTU_DEBUG_INFO("Sending connectivities to proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_CONNECTIVITY) <<")");
           requests.push_back(comm.asyncSend(buffers[p],
                                             nb_nodes_per_element * (nb_local_element[p] +
                                                                     nb_ghost_element[p]),
-                                            p, TAG_CONNECTIVITY));
+                                            p, Tag::genTag(my_rank, count, TAG_CONNECTIVITY)));
         } else {
           local_connectivity = buffers[p];
         }
       }
 
       /// create the renumbered connectivity
       AKANTU_DEBUG_INFO("Renumbering local connectivities");
       MeshUtils::renumberMeshNodes(mesh,
                                    local_connectivity,
                                    nb_local_element[root],
                                    nb_ghost_element[root],
                                    type,
                                    *old_nodes);
 
       comm.waitAll(requests);
       comm.freeCommunicationRequest(requests);
       requests.clear();
 
       for (UInt p = 0; p < nb_proc; ++p) {
         delete [] buffers[p];
       }
 
       /* -------------------------------------------------------------------- */
       for (UInt p = 0; p < nb_proc; ++p) {
         buffers[p] = new UInt[nb_ghost_element[p] + nb_element_to_send[p]];
         buffers_tmp[p] = buffers[p];
       }
 
       /// splitting the partition information to send them to processors
       UInt count_by_proc[nb_proc];
       memset(count_by_proc, 0, nb_proc*sizeof(UInt));
       for (UInt el = 0; el < nb_element; ++el) {
         *(buffers_tmp[partition_num[el]]++) = ghost_partition_offset[el + 1] - ghost_partition_offset[el];
         for (UInt part = ghost_partition_offset[el], i = 0;
              part < ghost_partition_offset[el + 1];
              ++part, ++i) {
           *(buffers_tmp[partition_num[el]]++) = ghost_partition[part];
         }
       }
 
       for (UInt el = 0; el < nb_element; ++el) {
         for (UInt part = ghost_partition_offset[el], i = 0;
              part < ghost_partition_offset[el + 1];
              ++part, ++i) {
           *(buffers_tmp[ghost_partition[part]]++) = partition_num[el];
         }
       }
 
       /* -------->>>>-PARTITIONS--------------------------------------------- */
       /// last data to compute the communication scheme
       for (UInt p = 0; p < nb_proc; ++p) {
         if(p != root) {
-          AKANTU_DEBUG_INFO("Sending partition informations to proc " << p);
+          AKANTU_DEBUG_INFO("Sending partition informations to proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_PARTITIONS) <<")");
           requests.push_back(comm.asyncSend(buffers[p],
                                              nb_element_to_send[p] + nb_ghost_element[p],
-                                             p, TAG_PARTITIONS));
+					    p, Tag::genTag(my_rank, count, TAG_PARTITIONS)));
         } else {
           local_partitions = buffers[p];
         }
       }
 
       AKANTU_DEBUG_INFO("Creating communications scheme");
-      communicator->fillCommunicationScheme(local_partitions,
-                                            nb_local_element[root],
-                                            nb_ghost_element[root],
-                                            type);
+      communicator.fillCommunicationScheme(local_partitions,
+					   nb_local_element[root],
+					   nb_ghost_element[root],
+					   type);
 
       comm.waitAll(requests);
       comm.freeCommunicationRequest(requests);
       requests.clear();
 
       for (UInt p = 0; p < nb_proc; ++p) {
         delete [] buffers[p];
       }
 
       /* -------------------------------------------------------------------- */
       /// send int data assossiated to the mesh
       if(nb_tags) {
         UInt uint_names_size = names_size / sizeof(UInt) + (names_size % sizeof(UInt) ? 1 : 0);
         for (UInt p = 0; p < nb_proc; ++p) {
           UInt size = nb_tags * (nb_local_element[p] + nb_ghost_element[p])
             + uint_names_size;
           buffers[p] = new UInt[size];
           std::fill_n(buffers[p], size, 0);
           buffers_tmp[p] = buffers[p];
         }
 
         char * names = new char[names_size];
         char * names_tmp = names;
         memset(names, 0, names_size);
         for(it_data = uint_data_map.begin(); it_data != uint_data_map.end(); ++it_data) {
           UInt * data = it_data->second->values;
 
           memcpy(names_tmp, it_data->first.data(), it_data->first.size());
           names_tmp += it_data->first.size() + 1;
 
           /// copying data for the local element
           for (UInt el = 0; el < nb_element; ++el) {
             UInt proc = partition_num[el];
             *(buffers_tmp[proc]) = data[el];
             buffers_tmp[proc]++;
           }
 
           /// copying the data for the ghost element
           for (UInt el = 0; el < nb_element; ++el) {
             for (UInt part = ghost_partition_offset[el];
                  part < ghost_partition_offset[el + 1];
                  ++part) {
               UInt proc = ghost_partition[part];
               *(buffers_tmp[proc]) = data[el];
               buffers_tmp[proc]++;
             }
           }
         }
 
         /* -------->>>>-TAGS------------------------------------------------- */
         for (UInt p = 0; p < nb_proc; ++p) {
           memcpy((char *)buffers_tmp[p], names, names_size);
           if(p != root) {
             UInt size = nb_tags * (nb_local_element[p] + nb_ghost_element[p])
               + uint_names_size;
-            AKANTU_DEBUG_INFO("Sending associated data to proc " << p);
-            requests.push_back(comm.asyncSend(buffers[p], size, p, TAG_DATA));
+            AKANTU_DEBUG_INFO("Sending associated data to proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_DATA) <<")");
+            requests.push_back(comm.asyncSend(buffers[p], size, p, Tag::genTag(my_rank, count, TAG_DATA)));
           } else {
             local_data = buffers[p];
           }
         }
         MeshUtils::setUIntData(mesh, local_data, nb_tags, type);
 
         comm.waitAll(requests);
         comm.freeCommunicationRequest(requests);
         requests.clear();
 
         for (UInt p = 0; p < nb_proc; ++p) delete [] buffers[p];
         delete [] names;
       }
+      ++count;
     }
 
     /* -------->>>>-SIZE----------------------------------------------------- */
     for (UInt p = 0; p < nb_proc; ++p) {
       if(p != root) {
         UInt size[6];
         size[0] = (UInt) _not_defined;
         size[1] = 0;
         size[2] = 0;
         size[3] = 0;
         size[4] = 0;
         size[5] = 0;
-        comm.send(size, 6, p, TAG_SIZES);
+	AKANTU_DEBUG_INFO("Sending empty connectivities informations to proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_SIZES) <<")");
+        comm.send(size, 6, p, Tag::genTag(my_rank, count, TAG_SIZES));
       }
     }
 
     /* ---------------------------------------------------------------------- */
     /* ---------------------------------------------------------------------- */
     /**
      * Nodes coordinate construction and synchronization
      */
 
     std::multimap< UInt, std::pair<UInt, UInt> > nodes_to_proc;
     /// get the list of nodes to send and send them
     Real * local_nodes = NULL;
     UInt nb_nodes_per_proc[nb_proc];
     UInt * nodes_per_proc[nb_proc];
     /* --------<<<<-NB_NODES + NODES----------------------------------------- */
     for (UInt p = 0; p < nb_proc; ++p) {
       UInt nb_nodes = 0;
       //      UInt * buffer;
       if(p != root) {
-        AKANTU_DEBUG_INFO("Receiving list of nodes from proc " << p);
-        comm.receive(&nb_nodes, 1, p, TAG_NB_NODES);
+        AKANTU_DEBUG_INFO("Receiving number of nodes from proc " << p << " TAG("<< Tag::genTag(p, 0, TAG_NB_NODES) <<")");
+        comm.receive(&nb_nodes, 1, p, Tag::genTag(p, 0, TAG_NB_NODES));
         nodes_per_proc[p] = new UInt[nb_nodes];
         nb_nodes_per_proc[p] = nb_nodes;
-        comm.receive(nodes_per_proc[p], nb_nodes, p, TAG_NODES);
+        AKANTU_DEBUG_INFO("Receiving list of nodes from proc " << p << " TAG("<< Tag::genTag(p, 0, TAG_NODES) <<")");
+        comm.receive(nodes_per_proc[p], nb_nodes, p, Tag::genTag(p, 0, TAG_NODES));
       } else {
         nb_nodes = old_nodes->getSize();
         nb_nodes_per_proc[p] = nb_nodes;
         nodes_per_proc[p] = old_nodes->values;
       }
 
       /// get the coordinates for the selected nodes
       Real * nodes_to_send = new Real[nb_nodes * spatial_dimension];
       Real * nodes_to_send_tmp = nodes_to_send;
       for (UInt n = 0; n < nb_nodes; ++n) {
         memcpy(nodes_to_send_tmp,
                nodes->values + spatial_dimension * nodes_per_proc[p][n],
                spatial_dimension * sizeof(Real));
         // nodes_to_proc.insert(std::make_pair(buffer[n], std::make_pair(p, n)));
         nodes_to_send_tmp += spatial_dimension;
       }
 
       /* -------->>>>-COORDINATES-------------------------------------------- */
       if(p != root) { /// send them for distant processors
-        AKANTU_DEBUG_INFO("Sending coordinates to proc " << p);
-        comm.send(nodes_to_send, nb_nodes * spatial_dimension, p, TAG_COORDINATES);
+        AKANTU_DEBUG_INFO("Sending coordinates to proc " << p << " TAG("<< Tag::genTag(my_rank, 0, TAG_COORDINATES) <<")");
+        comm.send(nodes_to_send, nb_nodes * spatial_dimension, p, Tag::genTag(my_rank, 0, TAG_COORDINATES));
         delete [] nodes_to_send;
       } else { /// save them for local processor
         local_nodes = nodes_to_send;
       }
     }
 
 
     /// construct the local nodes coordinates
     UInt nb_nodes = old_nodes->getSize();
     nodes->resize(nb_nodes);
     memcpy(nodes->values, local_nodes, nb_nodes * spatial_dimension * sizeof(Real));
     delete [] local_nodes;
 
     Vector<Int> * nodes_type_per_proc[nb_proc];
     for (UInt p = 0; p < nb_proc; ++p) {
       nodes_type_per_proc[p] = new Vector<Int>(nb_nodes_per_proc[p]);
     }
 
-    communicator->fillNodesType(mesh);
+    communicator.fillNodesType(mesh);
 
     /* --------<<<<-NODES_TYPE-1--------------------------------------------- */
     for (UInt p = 0; p < nb_proc; ++p) {
       if(p != root) {
-        AKANTU_DEBUG_INFO("Receiving first nodes types from proc " << p);
+        AKANTU_DEBUG_INFO("Receiving first nodes types from proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_NODES_TYPE) <<")");
         comm.receive(nodes_type_per_proc[p]->values,
-                      nb_nodes_per_proc[p], p, TAG_NODES_TYPE);
+		     nb_nodes_per_proc[p], p, Tag::genTag(p, 0, TAG_NODES_TYPE));
       } else {
         nodes_type_per_proc[p]->copy(mesh.getNodesType());
       }
       for (UInt n = 0; n < nb_nodes_per_proc[p]; ++n) {
         if((*nodes_type_per_proc[p])(n) == -2)
           nodes_to_proc.insert(std::make_pair(nodes_per_proc[p][n], std::make_pair(p, n)));
       }
     }
 
     std::multimap< UInt, std::pair<UInt, UInt> >::iterator it_node;
     std::pair< std::multimap< UInt, std::pair<UInt, UInt> >::iterator,
       std::multimap< UInt, std::pair<UInt, UInt> >::iterator > it_range;
     for (UInt i = 0; i < mesh.nb_global_nodes; ++i) {
       it_range = nodes_to_proc.equal_range(i);
       if(it_range.first == nodes_to_proc.end() || it_range.first->first != i) continue;
 
       UInt node_type = (it_range.first)->second.first;
       for (it_node = it_range.first; it_node != it_range.second; ++it_node) {
         UInt proc = it_node->second.first;
         UInt node = it_node->second.second;
         if(proc != node_type)
           nodes_type_per_proc[proc]->values[node] = node_type;
       }
     }
 
     /* -------->>>>-NODES_TYPE-2--------------------------------------------- */
     std::vector<CommunicationRequest *> requests;
     for (UInt p = 0; p < nb_proc; ++p) {
       if(p != root) {
-        AKANTU_DEBUG_INFO("Sending nodes types to proc " << p);
+        AKANTU_DEBUG_INFO("Sending nodes types to proc " << p << " TAG("<< Tag::genTag(my_rank, 0, TAG_NODES_TYPE) <<")");
         requests.push_back(comm.asyncSend(nodes_type_per_proc[p]->values,
-                                           nb_nodes_per_proc[p], p, TAG_NODES_TYPE));
+					  nb_nodes_per_proc[p], p, Tag::genTag(my_rank, 0, TAG_NODES_TYPE)));
       } else {
         mesh.getNodesTypePointer()->copy(*nodes_type_per_proc[p]);
       }
     }
 
     comm.waitAll(requests);
     comm.freeCommunicationRequest(requests);
     requests.clear();
 
     for (UInt p = 0; p < nb_proc; ++p) {
       if(p != root) delete [] nodes_per_proc[p];
       delete nodes_type_per_proc[p];
     }
 
     /* ---------------------------------------------------------------------- */
     /*  Distant (rank != root)                                                */
     /* ---------------------------------------------------------------------- */
   } else {
     /**
      * connectivity and communications scheme construction on distant processors
      */
     ElementType type = _not_defined;
+    UInt count = 0;
     do {
       /* --------<<<<-SIZE--------------------------------------------------- */
       UInt size[6] = { 0 };
-      comm.receive(size, 6, root, TAG_SIZES);
+      comm.receive(size, 6, root, Tag::genTag(root, count, TAG_SIZES));
 
       type          = (ElementType) size[0];
       UInt nb_local_element     = size[1];
       UInt nb_ghost_element     = size[2];
       UInt nb_element_to_send   = size[3];
       UInt nb_tags              = size[4];
       UInt names_size           = size[5];
       UInt uint_names_size = names_size / sizeof(UInt) + (names_size % sizeof(UInt) ? 1 : 0);
 
       if(type != _not_defined) {
         UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
         /* --------<<<<-CONNECTIVITY----------------------------------------- */
         local_connectivity = new UInt[(nb_local_element + nb_ghost_element) *
                                       nb_nodes_per_element];
         AKANTU_DEBUG_INFO("Receiving connectivities from proc " << root);
         comm.receive(local_connectivity, nb_nodes_per_element * (nb_local_element +
                                                                   nb_ghost_element),
-                           root, TAG_CONNECTIVITY);
+		     root, Tag::genTag(root, count, TAG_CONNECTIVITY));
 
         AKANTU_DEBUG_INFO("Renumbering local connectivities");
         MeshUtils::renumberMeshNodes(mesh,
                                      local_connectivity,
                                      nb_local_element,
                                      nb_ghost_element,
                                      type,
                                      *old_nodes);
 
         delete [] local_connectivity;
 
         /* --------<<<<-PARTITIONS--------------------------------------------- */
         local_partitions = new UInt[nb_element_to_send + nb_ghost_element * 2];
         AKANTU_DEBUG_INFO("Receiving partition informations from proc " << root);
         comm.receive(local_partitions,
-                           nb_element_to_send + nb_ghost_element * 2,
-                           root, TAG_PARTITIONS);
+		     nb_element_to_send + nb_ghost_element * 2,
+		     root, Tag::genTag(root, count, TAG_PARTITIONS));
 
         AKANTU_DEBUG_INFO("Creating communications scheme");
-        communicator->fillCommunicationScheme(local_partitions,
+        communicator.fillCommunicationScheme(local_partitions,
                                              nb_local_element,
                                              nb_ghost_element,
                                              type);
 
         delete [] local_partitions;
 
         /* --------<<<<-TAGS------------------------------------------------- */
         if(nb_tags) {
           AKANTU_DEBUG_INFO("Receiving associated data from proc " << root);
           UInt size_data = (nb_local_element + nb_ghost_element) * nb_tags
             + uint_names_size;
           local_data = new UInt[size_data];
-          comm.receive(local_data, size_data, root, TAG_DATA);
+          comm.receive(local_data, size_data, root, Tag::genTag(root, count, TAG_DATA));
 
           MeshUtils::setUIntData(mesh, local_data, nb_tags, type);
 
           delete [] local_data;
         }
       }
+      ++count;
     } while(type != _not_defined);
 
     /**
      * Nodes coordinate construction and synchronization on distant processors
      */
     /* -------->>>>-NB_NODES + NODES----------------------------------------- */
     AKANTU_DEBUG_INFO("Sending list of nodes to proc " << root);
     UInt nb_nodes = old_nodes->getSize();
-    comm.send(&nb_nodes, 1, root, TAG_NB_NODES);
-    comm.send(old_nodes->values, nb_nodes, root, TAG_NODES);
+    comm.send(&nb_nodes, 1, root, Tag::genTag(my_rank, 0, TAG_NB_NODES));
+    comm.send(old_nodes->values, nb_nodes, root, Tag::genTag(my_rank, 0, TAG_NODES));
 
     /* --------<<<<-COORDINATES---------------------------------------------- */
     nodes->resize(nb_nodes);
     AKANTU_DEBUG_INFO("Receiving coordinates from proc " << root);
-    comm.receive(nodes->values, nb_nodes * spatial_dimension, root, TAG_COORDINATES);
+    comm.receive(nodes->values, nb_nodes * spatial_dimension, root, Tag::genTag(root, 0, TAG_COORDINATES));
 
-    communicator->fillNodesType(mesh);
+    communicator.fillNodesType(mesh);
     /* --------<<<<-NODES_TYPE-2--------------------------------------------- */
     Int * nodes_types = mesh.getNodesTypePointer()->values;
     AKANTU_DEBUG_INFO("Sending first nodes types to proc " << root);
     comm.send(nodes_types, nb_nodes,
-               root, TAG_NODES_TYPE);
+	      root, Tag::genTag(my_rank, 0, TAG_NODES_TYPE));
 
     /* --------<<<<-NODES_TYPE-2--------------------------------------------- */
     AKANTU_DEBUG_INFO("Receiving nodes types from proc " << root);
     comm.receive(nodes_types, nb_nodes,
-                  root, TAG_NODES_TYPE);
+		 root, Tag::genTag(root, 0, TAG_NODES_TYPE));
   }
 
   comm.broadcast(&(mesh.nb_global_nodes), 1, root);
 
   AKANTU_DEBUG_OUT();
-  return communicator;
+  return &communicator;
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::fillNodesType(Mesh & mesh) {
   AKANTU_DEBUG_IN();
 
   //  StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator();
   //  UInt my_rank = comm.whoAmI();
 
   UInt nb_nodes = mesh.getNbNodes();
   //  std::cout << nb_nodes << std::endl;
   Int * nodes_type = mesh.getNodesTypePointer()->values;
 
   //memcpy(nodes_type, nodes_type_tmp, nb_nodes * sizeof(Int));
 
   UInt * nodes_set = new UInt[nb_nodes];
   std::fill_n(nodes_set, nb_nodes, 0);
 
   //  Mesh::ConnectivityTypeList::const_iterator it;
 
   const UInt NORMAL_SET = 1;
   const UInt GHOST_SET  = 2;
 
   bool * already_seen = new bool[nb_nodes];
 
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
     UInt set = NORMAL_SET;
     if (gt == _ghost) set = GHOST_SET;
 
     std::fill_n(already_seen, nb_nodes, false);
     Mesh::type_iterator it  = mesh.firstType(0, gt);
     Mesh::type_iterator end = mesh.lastType(0, gt);
     for(; it != end; ++it) {
       ElementType type = *it;
 
       UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
       UInt nb_element = mesh.getNbElement(type, gt);
       UInt * conn_val = mesh.getConnectivity(type, gt).values;
 
       for (UInt e = 0; e < nb_element; ++e) {
         for (UInt n = 0; n < nb_nodes_per_element; ++n) {
           AKANTU_DEBUG_ASSERT(*conn_val < nb_nodes, "Node " << *conn_val
                               << " bigger than number of nodes " << nb_nodes);
           if(!already_seen[*conn_val]) {
             nodes_set[*conn_val] += set;
             already_seen[*conn_val] = true;
           }
           conn_val++;
         }
       }
     }
   }
 
   delete [] already_seen;
 
   for (UInt i = 0; i < nb_nodes; ++i) {
     if(nodes_set[i] == NORMAL_SET) nodes_type[i] = -1;
     else if(nodes_set[i] == GHOST_SET) nodes_type[i] = -3;
     else if(nodes_set[i] == (GHOST_SET + NORMAL_SET)) nodes_type[i] = -2;
   }
 
   delete [] nodes_set;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::fillCommunicationScheme(UInt * partition,
                                                       UInt nb_local_element,
                                                       UInt nb_ghost_element,
                                                       ElementType type) {
   AKANTU_DEBUG_IN();
 
   Element element;
   element.type = type;
 
   UInt * part = partition;
 
   part = partition;
   for (UInt lel = 0; lel < nb_local_element; ++lel) {
     UInt nb_send = *part; part++;
     element.element = lel;
-    element.ghost_type = _ghost;
+    element.ghost_type = _not_ghost;
     for (UInt p = 0; p < nb_send; ++p) {
       UInt proc = *part; part++;
 
       AKANTU_DEBUG(dblAccessory, "Must send : " << element << " to proc " << proc);
       (send_element[proc]).push_back(element);
     }
   }
 
   for (UInt gel = 0; gel < nb_ghost_element; ++gel) {
     UInt proc = *part; part++;
     element.element = gel;
-    element.ghost_type = _not_ghost;
+    element.ghost_type = _ghost;
     AKANTU_DEBUG(dblAccessory, "Must recv : " << element << " from proc " << proc);
     recv_element[proc].push_back(element);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::asynchronousSynchronize(DataAccessor & data_accessor,
                                 		      SynchronizationTag tag) {
   AKANTU_DEBUG_IN();
 
   if (communications.find(tag) == communications.end()) {
     communications[tag].resize(nb_proc);
     computeBufferSize(data_accessor, tag);
   }
 
   Communication & communication = communications[tag];
 
   AKANTU_DEBUG_ASSERT(communication.send_requests.size() == 0,
 		      "There must be some pending sending communications. Tag is " << tag);
 
 
   for (UInt p = 0; p < nb_proc; ++p) {
     UInt ssize = communication.size_to_send[p];
     if(p == rank || ssize == 0) continue;
 
     CommunicationBuffer & buffer = communication.send_buffer[p];
     buffer.resize(ssize);
 #ifndef AKANTU_NDEBUG
-#endif
-    Element * elements = &(send_element[p].at(0));
-    UInt nb_elements   =  send_element[p].size();
+    //Element * elements = &(send_element[p](0));
+    UInt nb_elements   =  send_element[p].getSize();
     AKANTU_DEBUG_INFO("Packing data for proc " << p
 		      << " (" << ssize << "/" << nb_elements
 		      <<" data to send/elements)");
+#endif
 
-    for (UInt el = 0; el < nb_elements; ++el) {
-      data_accessor.packData(buffer, *elements, tag);
-      elements++;
-    }
+    data_accessor.packElementData(buffer, send_element[p], tag);
+    // for (UInt el = 0; el < nb_elements; ++el) {
+    //   data_accessor.packData(buffer, *elements, tag);
+    //   elements++;
+    // }
 
 #ifndef AKANTU_NDEBUG
     // UInt block_size = data_accessor.getNbDataToPack(send_element[p][0], tag);
     // AKANTU_DEBUG_WARNING("tag is " << tag << ", packed buffer is "
     // 			 << buffer.extractStream<Real>(block_size)
     // 			 << std::endl);
 #endif
 
     AKANTU_DEBUG_ASSERT(buffer.getPackedSize() == ssize,
 			"a problem have been introduced with "
 			<< "false sent sizes declaration "
 			<< buffer.getPackedSize() << " != " << ssize);
     std::cerr << std::dec;
     AKANTU_DEBUG_INFO("Posting send to proc " << p);
     communication.send_requests.push_back(static_communicator->asyncSend(buffer.storage(),
 									 ssize,
 									 p,
 									 (Int) tag));
   }
 
   AKANTU_DEBUG_ASSERT(communication.recv_requests.size() == 0,
 		      "There must be some pending receive communications");
 
   for (UInt p = 0; p < nb_proc; ++p) {
     UInt rsize = communication.size_to_receive[p];
     if(p == rank || rsize == 0) continue;
     CommunicationBuffer & buffer = communication.recv_buffer[p];
     buffer.resize(rsize);
 
     AKANTU_DEBUG_INFO("Posting receive from proc " << p << " (" << rsize << " data to receive)");
     communication.recv_requests.push_back(static_communicator->asyncReceive(buffer.storage(),
 									    rsize,
 									    p,
 									    (Int) tag));
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::waitEndSynchronize(DataAccessor & data_accessor,
 						 SynchronizationTag tag) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(communications.find(tag) != communications.end(), "No communication with the tag \""
 		      << tag <<"\" started");
 
   Communication & communication = communications[tag];
 
   std::vector<CommunicationRequest *> req_not_finished;
   std::vector<CommunicationRequest *> * req_not_finished_tmp = &req_not_finished;
   std::vector<CommunicationRequest *> * recv_requests_tmp = &(communication.recv_requests);
 
   //  static_communicator->waitAll(recv_requests);
 
   while(!recv_requests_tmp->empty()) {
 
     for (std::vector<CommunicationRequest *>::iterator req_it = recv_requests_tmp->begin();
 	 req_it != recv_requests_tmp->end() ; ++req_it) {
       CommunicationRequest * req = *req_it;
 
       if(static_communicator->testRequest(req)) {
 	UInt proc = req->getSource();
 	AKANTU_DEBUG_INFO("Unpacking data coming from proc " << proc);
 	CommunicationBuffer & buffer = communication.recv_buffer[proc];
 
-	Element * elements = &recv_element[proc].at(0);
-	UInt nb_elements   =  recv_element[proc].size();
-	UInt el = 0;
-	try {
-	  for (el = 0; el < nb_elements; ++el) {
-	    data_accessor.unpackData(buffer, *elements, tag);
-	    elements++;
-	  }
-	}
-	catch (debug::Exception & e){
-	  UInt block_size = data_accessor.getNbDataToPack(recv_element[proc][0], tag);
-	  AKANTU_DEBUG_ERROR("catched exception during unpack from proc " << proc
-			     << " buffer index is " << el << "/" << nb_elements
-			     << std::endl << e.what() << std::endl
-			     << "buffer size " << buffer.getSize() << std::endl
-			     << buffer.extractStream<Real>(block_size));
-	}
+	data_accessor.unpackElementData(buffer, recv_element[proc], tag);
+	// Element * elements = &recv_element[proc].at(0);
+	// UInt nb_elements   =  recv_element[proc].size();
+	// UInt el = 0;
+	// try {
+	//   for (el = 0; el < nb_elements; ++el) {
+	//     data_accessor.unpackData(buffer, *elements, tag);
+	//     elements++;
+	//   }
+	// }
+	// catch (debug::Exception & e){
+	//   UInt block_size = data_accessor.getNbDataToPack(recv_element[proc][0], tag);
+	//   AKANTU_DEBUG_ERROR("catched exception during unpack from proc " << proc
+	// 		     << " buffer index is " << el << "/" << nb_elements
+	// 		     << std::endl << e.what() << std::endl
+	// 		     << "buffer size " << buffer.getSize() << std::endl
+	// 		     << buffer.extractStream<Real>(block_size));
+	// }
 
 	buffer.resize(0);
 	AKANTU_DEBUG_ASSERT(buffer.getLeftToUnpack() == 0,
 			    "all data have not been unpacked: "
 			    << buffer.getLeftToUnpack() << " bytes left");
 	static_communicator->freeCommunicationRequest(req);
       } else {
 	req_not_finished_tmp->push_back(req);
       }
     }
 
     std::vector<CommunicationRequest *> * swap = req_not_finished_tmp;
     req_not_finished_tmp = recv_requests_tmp;
     recv_requests_tmp = swap;
 
     req_not_finished_tmp->clear();
   }
 
-
   static_communicator->waitAll(communication.send_requests);
   for (std::vector<CommunicationRequest *>::iterator req_it = communication.send_requests.begin();
        req_it != communication.send_requests.end() ; ++req_it) {
     CommunicationRequest & req = *(*req_it);
 
     if(static_communicator->testRequest(&req)) {
       UInt proc = req.getDestination();
       CommunicationBuffer & buffer = communication.send_buffer[proc];
       buffer.resize(0);
       static_communicator->freeCommunicationRequest(&req);
     }
   }
   communication.send_requests.clear();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::computeBufferSize(DataAccessor & data_accessor,
 						SynchronizationTag tag) {
   AKANTU_DEBUG_IN();
 
   // AKANTU_DEBUG_ASSERT(size_to_send.find(tag) == size_to_send.end(),
   // 		      "The SynchronizationTag< " << tag
   // 		      << "is already registered in " << id);
 
   for (UInt p = 0; p < nb_proc; ++p) {
     UInt ssend    = 0;
     UInt sreceive = 0;
     if(p != rank) {
-      for (std::vector<Element>::const_iterator sit = send_element[p].begin();
-	   sit != send_element[p].end();
-	   ++sit) {
-	ssend += data_accessor.getNbDataToPack(*sit, tag);
-      }
-
-      for (std::vector<Element>::const_iterator rit = recv_element[p].begin();
-	   rit != recv_element[p].end();
-	   ++rit) {
-	sreceive += data_accessor.getNbDataToUnpack(*rit, tag);
-      }
+      ssend    = data_accessor.getNbDataForElements(send_element[p], tag);
+      sreceive = data_accessor.getNbDataForElements(recv_element[p], tag);
+      // for (std::vector<Element>::const_iterator sit = send_element[p].begin();
+      // 	   sit != send_element[p].end();
+      // 	   ++sit) {
+      // 	ssend += data_accessor.getNbDataToPack(*sit, tag);
+      // }
+
+      // for (std::vector<Element>::const_iterator rit = recv_element[p].begin();
+      // 	   rit != recv_element[p].end();
+      // 	   ++rit) {
+      // 	sreceive += data_accessor.getNbDataToUnpack(*rit, tag);
+      // }
 
       AKANTU_DEBUG_INFO("I have " << ssend << "(" << ssend / 1024.
-			<< "kB) data to send to " << p
+			<< "kB - "<< send_element[p].getSize() <<" element(s)) data to send to " << p
 			<< " and " << sreceive << "(" << sreceive / 1024.
-			<< "kB) data to receive for tag " << tag);
+			<< "kB - "<< recv_element[p].getSize() <<" element(s)) data to receive for tag " << tag);
     }
 
     communications[tag].size_to_send   [p] = ssend;
     communications[tag].size_to_receive[p] = sreceive;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   Int prank = StaticCommunicator::getStaticCommunicator().whoAmI();
   Int psize = StaticCommunicator::getStaticCommunicator().getNbProc();
   stream << "[" << prank << "/" << psize << "]" << space << "DistributedSynchronizer [" << std::endl;
   for (UInt p = 0; p < nb_proc; ++p) {
     if (p == UInt(prank)) continue;
     stream << "[" << prank << "/" << psize << "]" << space << " + Communication to proc " << p << " [" << std::endl;
     if(AKANTU_DEBUG_TEST(dblDump)) {
       stream << "[" << prank << "/" << psize << "]" << space << "    - Element to send to proc " << p << " [" << std::endl;
 
-      std::vector<Element>::const_iterator it_el  = send_element[p].begin();
-      std::vector<Element>::const_iterator end_el = send_element[p].end();
+      Vector<Element>::iterator<Element> it_el  = send_element[p].begin();
+      Vector<Element>::iterator<Element> end_el = send_element[p].end();
       for(;it_el != end_el; ++it_el)
 	stream << "[" << prank << "/" << psize << "]" << space << "       " << *it_el << std::endl;
       stream << "[" << prank << "/" << psize << "]" << space << "   ]" << std::endl;
 
       stream << "[" << prank << "/" << psize << "]" << space << "    - Element to recv from proc " << p << " [" << std::endl;
 
       it_el  = recv_element[p].begin();
       end_el = recv_element[p].end();
       for(;it_el != end_el; ++it_el)
 	stream << "[" << prank << "/" << psize << "]" << space << "       " << *it_el << std::endl;stream << "[" << prank << "/" << psize << "]" << space << "   ]" << std::endl;
     }
 
     std::map< SynchronizationTag, Communication>::const_iterator it = communications.begin();
     std::map< SynchronizationTag, Communication>::const_iterator end = communications.end();
     for (; it != end; ++it) {
       const SynchronizationTag & tag = it->first;
       const Communication & communication = it->second;
       UInt ssend    = communication.size_to_send[p];
       UInt sreceive = communication.size_to_receive[p];
       stream << "[" << prank << "/" << psize << "]" << space << "     - Tag " << tag << " -> " << ssend << "byte(s) -- <- " << sreceive << "byte(s)" << std::endl;
     }
 
     std::cout << "[" << prank << "/" << psize << "]" << space << " ]" << std::endl;
   }
   std::cout << "[" << prank << "/" << psize << "]" << space << "]" << std::endl;
 }
 
-
 /* -------------------------------------------------------------------------- */
+void DistributedSynchronizer::onElementsRemoved(const Vector<Element> & element_to_remove,
+						const ByElementTypeUInt & new_numbering) {
+  AKANTU_DEBUG_IN();
+
+  StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
+  UInt psize = comm.getNbProc();
+  UInt prank = comm.whoAmI();
+
+  std::vector<CommunicationRequest *> isend_requests;
+  // Handling ghost elements
+  for (UInt p = 0; p < psize; ++p) {
+    if (p == prank) continue;
+
+    Vector<Element> & recv = recv_element[p];
+    Vector<UInt> list_of_el_to_remove;
+    list_of_el_to_remove.push_back(UInt(-1));
+
+    Vector<Element>::iterator<Element> recv_begin = recv.begin();
+    Vector<Element>::iterator<Element> recv_end   = recv.end();
+
+    Vector<Element>::const_iterator<Element> it  = element_to_remove.begin();
+    Vector<Element>::const_iterator<Element> end = element_to_remove.end();
+    for (;it != end; ++it) {
+      const Element & el = *it;
+      if(el.ghost_type == _ghost) {
+	Vector<Element>::iterator<Element> pos = std::find(recv_begin, recv_end, el);
+	if(pos != recv_end) {
+	  UInt i = pos - recv_begin;
+	  list_of_el_to_remove.push_back(i);
+	}
+      } else {
+	/// \todo handle the removal of element to send from the ghost of other procs
+	AKANTU_EXCEPTION("DistributedSynchronizer do not know how to remove _not_ghost element, ask a developer to finish is job");
+      }
+    }
 
+    std::sort(list_of_el_to_remove.begin(), list_of_el_to_remove.end());
+
+    isend_requests.push_back(comm.asyncSend(list_of_el_to_remove.storage(), list_of_el_to_remove.getSize(),
+					    p, Tag::genTag(prank, 0, 0)));
+
+    list_of_el_to_remove.resize(list_of_el_to_remove.getSize() - 1);
+
+    Vector<Element> new_recv;
+    for (UInt nr = 0; nr < recv.getSize(); ++nr) {
+      Vector<UInt>::iterator<UInt> it = std::find(list_of_el_to_remove.begin(), list_of_el_to_remove.end(), nr);
+      if(it == list_of_el_to_remove.end()) {
+	Element & el = recv(nr);
+	el.element = new_numbering(el.type, el.ghost_type)(el.element);
+
+	new_recv.push_back(el);
+      } else { list_of_el_to_remove.erase(it - list_of_el_to_remove.begin()); }
+    }
+
+    recv.resize(new_recv.getSize());
+    std::copy(new_recv.begin(), new_recv.end(), recv.begin());
+  }
+
+  for (UInt p = 0; p < psize; ++p) {
+    if (p == prank) continue;
+    CommunicationStatus status;
+    comm.probe<UInt>(p, Tag::genTag(p, 0, 0), status);
+    Vector<UInt> list_of_el_to_remove(status.getSize());
+
+    comm.receive(list_of_el_to_remove.storage(), list_of_el_to_remove.getSize(),
+		 p, Tag::genTag(p, 0, 0));
+
+    list_of_el_to_remove.resize(list_of_el_to_remove.getSize() - 1);
+
+    Vector<Element> & send = send_element[p];
+
+    Vector<Element> new_send;
+    for (UInt ns = 0; ns < send.getSize(); ++ns) {
+      Vector<UInt>::iterator<UInt> it = std::find(list_of_el_to_remove.begin(), list_of_el_to_remove.end(), ns);
+      if(it == list_of_el_to_remove.end()) {
+	new_send.push_back(send(ns));
+      } else { list_of_el_to_remove.erase(it - list_of_el_to_remove.begin()); }
+
+    }
+
+    send.resize(new_send.getSize());
+    std::copy(new_send.begin(), new_send.end(), send.begin());
+  }
+
+  comm.waitAll(isend_requests);
+  comm.freeCommunicationRequest(isend_requests);
+
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
 
 __END_AKANTU__
diff --git a/src/synchronizer/distributed_synchronizer.hh b/src/synchronizer/distributed_synchronizer.hh
index 4718f9250..04d1b36c7 100644
--- a/src/synchronizer/distributed_synchronizer.hh
+++ b/src/synchronizer/distributed_synchronizer.hh
@@ -1,178 +1,160 @@
 /**
  * @file   distributed_synchronizer.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @date   Thu Aug 19 15:28:35 2010
  *
  * @brief  wrapper to the static communicator
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_DISTRIBUTED_SYNCHRONIZER_HH__
 #define __AKANTU_DISTRIBUTED_SYNCHRONIZER_HH__
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "aka_vector.hh"
 #include "static_communicator.hh"
 #include "synchronizer.hh"
 #include "mesh.hh"
 #include "mesh_partition.hh"
 
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 class CommunicationBuffer;
 
-class DistributedSynchronizer : public Synchronizer {
+class DistributedSynchronizer : public Synchronizer, public MeshEventHandler {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
-public:
-
-  DistributedSynchronizer(SynchronizerID id = "distributed_synchronizer",
+protected:
+  DistributedSynchronizer(Mesh & mesh,
+			  SynchronizerID id = "distributed_synchronizer",
 			  MemoryID memory_id = 0);
+
+public:
   virtual ~DistributedSynchronizer();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// get a  mesh and a partition and  create the local mesh  and the associated
   /// DistributedSynchronizer
   static DistributedSynchronizer *
   createDistributedSynchronizerMesh(Mesh & mesh,
 				    const MeshPartition * partition,
 				    UInt root = 0,
 				    SynchronizerID id = "distributed_synchronizer",
 				    MemoryID memory_id = 0);
 
   /* ------------------------------------------------------------------------ */
   /* Inherited from Synchronizer                                              */
   /* ------------------------------------------------------------------------ */
 
   /// asynchronous synchronization of ghosts
   void asynchronousSynchronize(DataAccessor & data_accessor,SynchronizationTag tag);
 
   /// wait end of asynchronous synchronization of ghosts
   void waitEndSynchronize(DataAccessor & data_accessor,SynchronizationTag tag);
 
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
+  /// mesh event handler onRemovedElement
+  virtual void onElementsRemoved(const Vector<Element> & element_list,
+				 const ByElementTypeUInt & new_numbering);
+
 protected:
   /// fill the nodes type vector
   void fillNodesType(Mesh & mesh);
 
 
   /// fill the communications array of a distributedSynchronizer based on a partition array
   void fillCommunicationScheme(UInt * partition,
 			       UInt nb_local_element,
 			       UInt nb_ghost_element,
 			       ElementType type);
 
   /// compute buffer size for a given tag and data accessor
   void computeBufferSize(DataAccessor & data_accessor, SynchronizationTag tag);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
+  /// reference to the underlying mesh
+  Mesh & mesh;
+
   /// the static memory instance
   StaticCommunicator * static_communicator;
 
   class Communication {
   public:
     void resize(UInt size) {
       send_buffer.resize(size);
       recv_buffer.resize(size);
       size_to_send   .resize(size);
       size_to_receive.resize(size);
     }
 
   public:
     /// size of data to send to each processor
     std::vector<UInt> size_to_send;
     /// size of data to recv to each processor
     std::vector<UInt> size_to_receive;
     std::vector<CommunicationBuffer> send_buffer;
     std::vector<CommunicationBuffer> recv_buffer;
 
     std::vector<CommunicationRequest *> send_requests;
     std::vector<CommunicationRequest *> recv_requests;
   };
 
   std::map<SynchronizationTag, Communication> communications;
 
-  // /// size of data to send to each processor by communication tag
-  // std::map< SynchronizationTag, Vector<UInt> > size_to_send;
-
-  // /// size of data to receive form each processor by communication tag
-  // std::map< SynchronizationTag, Vector<UInt> > size_to_receive;
-
-  // std::map<SynchronizationTag, CommunicationBuffer *> send_buffer;
-  // std::map<SynchronizationTag, CommunicationBuffer *> recv_buffer;
-
-  // /// send requests
-  // std::vector<CommunicationRequest *> send_requests;
-  // /// receive requests
-  // std::vector<CommunicationRequest *> recv_requests;
-
-  // /// list of real element to send ordered by type then by receiver processors
-  // ByElementTypeUInt element_to_send_offset;
-  // ByElementTypeUInt element_to_send;
-
-  std::vector<Element> * send_element;
-  std::vector<Element> * recv_element;
-
-  // /// list of ghost element to receive ordered by type then by sender processors
-  // ByElementTypeUInt element_to_receive_offset;
-  // ByElementTypeUInt element_to_receive;
+  /// list of element to sent to proc p
+  Vector<Element> * send_element;
+  /// list of element to receive from proc p
+  Vector<Element> * recv_element;
 
   UInt nb_proc;
   UInt rank;
 
-  // /// global node ids
-  // Vector<UInt> * nodes_global_ids;
-
-  // /// node type,  -3 pure ghost, -2  master for the  node, -1 normal node,  i in
-  // /// [0-N] slave node and master is proc i
-  // Vector<Int> * nodes_type;
-
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 //#include "distributedSynchronizer_inline_impl.cc"
 
 __END_AKANTU__
 
 #endif /* __AKANTU_DISTRIBUTED_SYNCHRONIZER_HH__ */
diff --git a/src/synchronizer/grid_synchronizer.cc b/src/synchronizer/grid_synchronizer.cc
index d65c05d2f..07aba9293 100644
--- a/src/synchronizer/grid_synchronizer.cc
+++ b/src/synchronizer/grid_synchronizer.cc
@@ -1,472 +1,479 @@
 /**
  * @file   grid_synchronizer.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Tue Sep 20 10:30:37 2011
  *
  * @brief  implementation of the grid synchronizer
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "grid_synchronizer.hh"
 #include "aka_grid.hh"
 #include "mesh.hh"
 #include "fem.hh"
 #include "static_communicator.hh"
 #include "mesh_io.hh"
 
 
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
-GridSynchronizer::GridSynchronizer(const ID & id,
+GridSynchronizer::GridSynchronizer(Mesh & mesh,
+				   const ID & id,
                                    MemoryID memory_id) :
-  DistributedSynchronizer(id, memory_id) {
+  DistributedSynchronizer(mesh, id, memory_id) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class E>
 GridSynchronizer * GridSynchronizer::createGridSynchronizer(Mesh & mesh,
                                                             const RegularGrid<E> & grid,
                                                             SynchronizerID id,
                                                             MemoryID memory_id) {
   AKANTU_DEBUG_IN();
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   UInt nb_proc = comm.getNbProc();
   UInt my_rank = comm.whoAmI();
 
-  GridSynchronizer * communicator = new GridSynchronizer(id, memory_id);
-  if(nb_proc == 1) return communicator;
+  GridSynchronizer & communicator = *(new GridSynchronizer(mesh, id, memory_id));
+  if(nb_proc == 1) return &communicator;
 
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   Real * bounding_boxes = new Real[2 * spatial_dimension * nb_proc];
   Real * my_bounding_box = bounding_boxes + 2 * spatial_dimension * my_rank;
 
   // mesh.getLocalLowerBounds(my_bounding_box);
   // mesh.getLocalUpperBounds(my_bounding_box + spatial_dimension);
 
   grid.getLocalLowerBounds(my_bounding_box);
   grid.getLocalUpperBounds(my_bounding_box + spatial_dimension);
 
   Real spacing[spatial_dimension];
   grid.getSpacing(spacing);
 
   AKANTU_DEBUG_INFO("Exchange of bounding box to detect the overlapping regions.");
 
   comm.allGather(bounding_boxes, spatial_dimension * 2);
 
   bool * intersects_proc = new bool[nb_proc];
   std::fill_n(intersects_proc, nb_proc, true);
 
   UInt * first_cells = new UInt[3 * nb_proc];
   UInt * last_cells = new UInt[3 * nb_proc];
   std::fill_n(first_cells, 3 * nb_proc, 0);
   std::fill_n(first_cells, 3 * nb_proc, 0);
 
   ByElementTypeUInt ** element_per_proc = new ByElementTypeUInt* [nb_proc];
   for (UInt p = 0; p < nb_proc; ++p) element_per_proc[p] = NULL;
 
+  // check the overlapping between my box and the one from other processors
   for (UInt p = 0; p < nb_proc; ++p) {
     if(p == my_rank) continue;
 
     Real * proc_bounding_box = bounding_boxes + 2 * spatial_dimension * p;
 
     bool intersects = false;
     UInt * first_cell_p = first_cells + p * spatial_dimension;
     UInt * last_cell_p =  last_cells  + p * spatial_dimension;
     for (UInt s = 0; s < spatial_dimension; ++s) {
+
+      // check overlapping of grid
       intersects = Math::intersects(my_bounding_box[s],
                                     my_bounding_box[spatial_dimension + s],
                                     proc_bounding_box[s],
                                     proc_bounding_box[spatial_dimension + s]);
 
       intersects_proc[p] &= intersects;
 
       if(intersects) {
         AKANTU_DEBUG_INFO("I intersects with processor " << p << " in direction " << s);
 
         // is point 1 of proc p in the dimension s in the range ?
         bool point1 = Math::is_in_range(proc_bounding_box[s],
                                         my_bounding_box[s],
                                         my_bounding_box[s+spatial_dimension]);
 
         // is point 2 of proc p in the dimension s in the range ?
         bool point2 = Math::is_in_range(proc_bounding_box[s+spatial_dimension],
                                         my_bounding_box[s],
                                         my_bounding_box[s+spatial_dimension]);
 
         Real start = 0.;
         Real end = 0.;
 
         if(point1 && !point2) {
           /* |-----------|         my_bounding_box(i)
            *       |-----------|   proc_bounding_box(i)
            *       1           2
            */
           start = proc_bounding_box[s];
           end   = my_bounding_box[s+spatial_dimension];
         } else if(point1 && point2) {
           /* |-----------------|   my_bounding_box(i)
            *   |-----------|       proc_bounding_box(i)
            *   1           2
            */
           start = proc_bounding_box[s];
           end   = proc_bounding_box[s+spatial_dimension];
         } else if(!point1 && point2) {
           /*       |-----------|  my_bounding_box(i)
            * |-----------|        proc_bounding_box(i)
            * 1           2
            */
           start = my_bounding_box[s];
           end   = proc_bounding_box[s+spatial_dimension];
         }
 
 
         first_cell_p[s] = grid.getCell(start + spacing[s]/100., s);
         last_cell_p [s] = grid.getCell(end - spacing[s]/100., s);
       }
     }
 
+    //create the list of cells in the overlapping
     typedef typename RegularGrid<E>::Cell Cell;
 
     std::vector<Cell> * cells = new std::vector<Cell>;
 
     if(intersects_proc[p]) {
       AKANTU_DEBUG_INFO("I intersects with processor " << p);
 
       Cell cell(grid);
 
       // for (UInt i = 0; i < spatial_dimension; ++i) {
       //   if(first_cell_p[i] != 0) --first_cell_p[i];
       //   if(last_cell_p[i] != 0) ++last_cell_p[i];
       // }
 
       for (UInt fd = first_cell_p[0]; fd <= last_cell_p[0]; ++fd) {
         cell.position[0] = fd;
         if(spatial_dimension == 1) {
 	  cell.updateID();
           cells->push_back(cell);
 	}
         else {
           for (UInt sd = first_cell_p[1]; sd <= last_cell_p[1] ; ++sd) {
             cell.position[1] = sd;
             if(spatial_dimension == 2) {
 	      cell.updateID();
               cells->push_back(cell);
             } else {
               for (UInt ld = first_cell_p[2]; fd <= last_cell_p[2] ; ++ld) {
                 cell.position[2] = ld;
 		cell.updateID();
                 cells->push_back(cell);
               }
             }
           }
         }
       }
 
+      // get the list of elements in the cells of the overlapping
       typename std::vector<Cell>::iterator cur_cell = cells->begin();
       typename std::vector<Cell>::iterator last_cell = cells->end();
-      std::set<E, CompElementLess> * to_send = new std::set<E, CompElementLess>();
+      std::set<Element, CompElementLess> * to_send = new std::set<Element, CompElementLess>();
 
       for (; cur_cell != last_cell; ++cur_cell) {
         typename RegularGrid<E>::const_iterator cur_elem = grid.beginCell(*cur_cell);
         typename RegularGrid<E>::const_iterator last_elem = grid.endCell(*cur_cell);
 
         for (; cur_elem != last_elem; ++cur_elem) {
           to_send->insert(*cur_elem);
         }
       }
 
       AKANTU_DEBUG_INFO("I have prepared " << to_send->size() << " elements to send to processor " << p);
 
       delete cells;
 
       std::stringstream sstr; sstr << "element_per_proc_" << p;
       element_per_proc[p] = new ByElementTypeUInt(sstr.str(), id);
       ByElementTypeUInt & elempproc = *(element_per_proc[p]);
 
-      typename std::set<E>::iterator elem = to_send->begin();
-      typename std::set<E>::iterator last_elem = to_send->end();
+      typename std::set<Element>::iterator elem = to_send->begin();
+      typename std::set<Element>::iterator last_elem = to_send->end();
       for (; elem != last_elem; ++elem) {
         ElementType type = elem->type;
         UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
 
         // /!\ this part must be slow due to the access in the ByElementTypeUInt
         if(!elempproc.exists(type))
           elempproc.alloc(0, nb_nodes_per_element, type, _not_ghost);
 
         UInt global_connect[nb_nodes_per_element];
         UInt * local_connect = mesh.getConnectivity(type).storage() + elem->element * nb_nodes_per_element;
         for (UInt i = 0; i < nb_nodes_per_element; ++i) {
           global_connect[i] = mesh.getNodeGlobalId(local_connect[i]);
         }
 
         elempproc(type).push_back(global_connect);
-        communicator->send_element[p].push_back(*elem);
+        communicator.send_element[p].push_back(*elem);
       }
 
       delete to_send;
     }
   }
 
   AKANTU_DEBUG_INFO("I have finished to compute intersection,"
                     << " no it's time to communicate with my neighbors");
 
-
-
-#define SIZE_TAG       0
-#define DATA_TAG       1
-#define ASK_NODES_TAG  2
-#define SEND_NODES_TAG 3
-  /* tag = |__________21_________|___8____|_3_|
-   *       |          proc       | num mes| ct|
-   */
-#define GEN_TAG(proc, msg_count, tag) (((proc & 0x1FFFFF) << 11) + ((msg_count & 0xFF) << 3) + (tag & 0x7))
-
   /**
    * Sending loop, sends the connectivity asynchronously to all concerned proc
    */
   std::vector<CommunicationRequest *> isend_requests;
   for (UInt p = 0; p < nb_proc; ++p) {
     if(p == my_rank) continue;
     if(intersects_proc[p]) {
       ByElementTypeUInt & elempproc = *(element_per_proc[p]);
 
       ByElementTypeUInt::type_iterator it_type   = elempproc.firstType(0, _not_ghost);
-      ByElementTypeUInt::type_iterator last_type = elempproc.lastType(0, _not_ghost);
+      ByElementTypeUInt::type_iterator last_type = elempproc.lastType (0, _not_ghost);
 
       UInt count = 0;
       for (; it_type != last_type; ++it_type) {
         Vector<UInt> & conn = elempproc(*it_type, _not_ghost);
         UInt info[2];
         info[0] = (UInt) *it_type;
         info[1] = conn.getSize() * conn.getNbComponent();
 
         AKANTU_DEBUG_INFO("I have " << conn.getSize() << " elements of type " << *it_type
                           << " to send to processor " << p
-                          << " (communication tag : " << GEN_TAG(my_rank, count, DATA_TAG) << ")");
+                          << " (communication tag : " << Tag::genTag(my_rank, count, DATA_TAG) << ")");
 
-        isend_requests.push_back(comm.asyncSend(info, 2, p, GEN_TAG(my_rank, count, SIZE_TAG)));
+        isend_requests.push_back(comm.asyncSend(info, 2, p, Tag::genTag(my_rank, count, SIZE_TAG)));
         isend_requests.push_back(comm.asyncSend(conn.storage(),
                                                 conn.getSize() * conn.getNbComponent(),
-                                                p, GEN_TAG(my_rank, count, DATA_TAG)));
+                                                p, Tag::genTag(my_rank, count, DATA_TAG)));
 
         ++count;
       }
 
       UInt info[2];
       info[0] = (UInt) _not_defined;
       info[1] = 0;
-      isend_requests.push_back(comm.asyncSend(info, 2, p, GEN_TAG(my_rank, count, SIZE_TAG)));
+      isend_requests.push_back(comm.asyncSend(info, 2, p, Tag::genTag(my_rank, count, SIZE_TAG)));
     }
   }
 
   /**
    * Receives the connectivity and store them in the ghosts elements
    */
   Vector<UInt> & global_nodes_ids = const_cast<Vector<UInt> &>(mesh.getGlobalNodesIds());
   Vector<Int> & nodes_type = const_cast<Vector<Int> &>(mesh.getNodesType());
   std::vector<CommunicationRequest *> isend_nodes_requests;
   UInt nb_nodes_to_recv[nb_proc];
   UInt nb_total_nodes_to_recv = 0;
   UInt nb_current_nodes = global_nodes_ids.getSize();
 
   NewNodesEvent new_nodes;
   NewElementsEvent new_elements;
 
+  Vector<UInt> * ask_nodes_per_proc = new Vector<UInt>[nb_proc];
+
   for (UInt p = 0; p < nb_proc; ++p) {
     nb_nodes_to_recv[p] = 0;
     if(p == my_rank) continue;
 
-    Vector<UInt> ask_nodes;
+    Vector<UInt> & ask_nodes = ask_nodes_per_proc[p];
     UInt count = 0;
     if(intersects_proc[p]) {
       ElementType type = _not_defined;
       do {
         UInt info[2] = { 0 };
-        comm.receive(info, 2, p, GEN_TAG(p, count, SIZE_TAG));
+        comm.receive(info, 2, p, Tag::genTag(p, count, SIZE_TAG));
 
         type = (ElementType) info[0];
         if(type != _not_defined) {
           UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);;
           UInt nb_element = info[1] / nb_nodes_per_element;
 
           Vector<UInt> tmp_conn(nb_element, nb_nodes_per_element);
 
-          comm.receive(tmp_conn.storage(), info[1], p, GEN_TAG(p, count, DATA_TAG));
+          comm.receive(tmp_conn.storage(), info[1], p, Tag::genTag(p, count, DATA_TAG));
 
           AKANTU_DEBUG_INFO("I will receive " << nb_element << " elements of type " << ElementType(info[0])
                           << " from processor " << p
-                          << " (communication tag : " << GEN_TAG(p, count, DATA_TAG) << ")");
+                          << " (communication tag : " << Tag::genTag(p, count, DATA_TAG) << ")");
 
 
           Vector<UInt> & ghost_connectivity = const_cast<Vector<UInt> &>(mesh.getConnectivity(type, _ghost));
 
           UInt nb_ghost_element = ghost_connectivity.getSize();
           Element element(type, 0, _ghost);
 
           UInt conn[nb_nodes_per_element];
           for (UInt el = 0; el < nb_element; ++el) {
             UInt nb_node_to_ask_for_elem = 0;
 
             for (UInt n = 0; n < nb_nodes_per_element; ++n) {
               UInt gn = tmp_conn(el, n);
               UInt ln = global_nodes_ids.find(gn);
               if(ln == UInt(-1)) {
                 global_nodes_ids.push_back(gn);
 		nodes_type.push_back(-3); // pure ghost node
                 ln = nb_current_nodes;
 
 		new_nodes.getList().push_back(ln);
                 ++nb_current_nodes;
                 ask_nodes.push_back(gn);
                 ++nb_node_to_ask_for_elem;
               }
 
               conn[n] = ln;
             }
 
             // all the nodes are already known locally, the element should already exists
             UInt c = UInt(-1);
             if(nb_node_to_ask_for_elem == 0) {
               c = ghost_connectivity.find(conn);
 	      element.element = c;
             }
 
             if(c == UInt(-1)) {
               element.element = nb_ghost_element;
               ++nb_ghost_element;
               ghost_connectivity.push_back(conn);
 	      new_elements.getList().push_back(element);
             }
-            communicator->recv_element[p].push_back(element);
+            communicator.recv_element[p].push_back(element);
           }
         }
         count++;
       } while(type != _not_defined);
 
       AKANTU_DEBUG_INFO("I have " << ask_nodes.getSize()
                         << " missing nodes for elements coming from processor " << p
-                        << " (communication tag : " << GEN_TAG(my_rank, 0, ASK_NODES_TAG) << ")");
-
+                        << " (communication tag : " << Tag::genTag(my_rank, 0, ASK_NODES_TAG) << ")");
 
       isend_nodes_requests.push_back(comm.asyncSend(ask_nodes.storage(), ask_nodes.getSize(),
-                                                     p, GEN_TAG(my_rank, 0, ASK_NODES_TAG)));
+                                                     p, Tag::genTag(my_rank, 0, ASK_NODES_TAG)));
       nb_nodes_to_recv[p] = ask_nodes.getSize();
       nb_total_nodes_to_recv += ask_nodes.getSize();
     }
   }
 
-
-  Vector<Real> & nodes = const_cast<Vector<Real> &>(mesh.getNodes());
-  UInt nb_nodes = nodes.getSize();
-  std::vector<CommunicationRequest *> irecv_nodes_requests;
-  nodes.resize(nb_total_nodes_to_recv + nb_nodes);
   for (UInt p = 0; p < nb_proc; ++p) {
-    if((p != my_rank) && (nb_nodes_to_recv[p] > 0)) {
-      irecv_nodes_requests.push_back(comm.asyncReceive(nodes.storage() + nb_nodes * spatial_dimension,
-                                                        nb_nodes_to_recv[p] * spatial_dimension,
-                                                        p, GEN_TAG(p, 0, SEND_NODES_TAG)));
-      nb_nodes += nb_nodes_to_recv[p];
-    }
+    if(element_per_proc[p]) delete element_per_proc[p];
   }
-
+  delete [] element_per_proc;
 
   comm.waitAll(isend_requests);
   comm.freeCommunicationRequest(isend_requests);
 
-  for (UInt p = 0; p < nb_proc; ++p) {
-    if(element_per_proc[p]) delete element_per_proc[p];
-  }
-  delete [] element_per_proc;
 
   /**
    * Sends requested nodes to proc
    */
+  Vector<Real> & nodes = const_cast<Vector<Real> &>(mesh.getNodes());
+  UInt nb_nodes = nodes.getSize();
+
+  std::vector<CommunicationRequest *> isend_coordinates_requests;
+  Vector<Real> * nodes_to_send_per_proc = new Vector<Real>[nb_proc];
   for (UInt p = 0; p < nb_proc; ++p) {
-    if(p == my_rank) continue;
+    if(p == my_rank || !intersects_proc[p]) continue;
 
     Vector<UInt> asked_nodes;
     CommunicationStatus status;
-    comm.probe<UInt>(p, GEN_TAG(p, 0, ASK_NODES_TAG), status);
+    AKANTU_DEBUG_INFO("Waiting list of nodes to send to processor " << p
+                      << "(communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
+
+    comm.probe<UInt>(p, Tag::genTag(p, 0, ASK_NODES_TAG), status);
     UInt nb_nodes_to_send = status.getSize();
     asked_nodes.resize(nb_nodes_to_send);
 
     AKANTU_DEBUG_INFO("I have " << nb_nodes_to_send
-                      << " to send to processor " << p
-                      << "(communication tag : " << GEN_TAG(p, 0, ASK_NODES_TAG) << ")");
+                      << " nodes to send to processor " << p
+                      << " (communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
 
-    comm.receive(asked_nodes.storage(), nb_nodes_to_send, p, GEN_TAG(p, 0, ASK_NODES_TAG));
-    Vector<Real> nodes_to_send(0, spatial_dimension);
+    AKANTU_DEBUG_INFO("Getting list of nodes to send to processor " << p
+                      << " (communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
+
+    comm.receive(asked_nodes.storage(), nb_nodes_to_send, p, Tag::genTag(p, 0, ASK_NODES_TAG));
+
+    Vector<Real> & nodes_to_send = nodes_to_send_per_proc[p];
+    nodes_to_send.extendComponentsInterlaced(spatial_dimension, 1);
     for (UInt n = 0; n < nb_nodes_to_send; ++n) {
       UInt ln = global_nodes_ids.find(asked_nodes(n));
+      AKANTU_DEBUG_ASSERT(ln != UInt(-1), "The node [" << asked_nodes(n) << "] requested by proc " << p << " was not found locally!");
       nodes_to_send.push_back(nodes.storage() + ln * spatial_dimension);
     }
-    comm.send(nodes_to_send.storage(), nb_nodes_to_send * spatial_dimension, p, GEN_TAG(my_rank, 0, SEND_NODES_TAG));
+
+    AKANTU_DEBUG_INFO("Sending the nodes to processor " << p
+                      << " (communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
+
+    isend_coordinates_requests.push_back(comm.asyncSend(nodes_to_send.storage(), nb_nodes_to_send * spatial_dimension, p, Tag::genTag(my_rank, 0, SEND_NODES_TAG)));
   }
 
   comm.waitAll(isend_nodes_requests);
   comm.freeCommunicationRequest(isend_nodes_requests);
+  delete [] ask_nodes_per_proc;
+
+  //  std::vector<CommunicationRequest *> irecv_nodes_requests;
+  nodes.resize(nb_total_nodes_to_recv + nb_nodes);
+  for (UInt p = 0; p < nb_proc; ++p) {
+    if((p != my_rank) && (nb_nodes_to_recv[p] > 0)) {
+      AKANTU_DEBUG_INFO("Receiving the nodes from processor " << p
+			<< " (communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
 
-  comm.waitAll(irecv_nodes_requests);
-  comm.freeCommunicationRequest(irecv_nodes_requests);
+      comm.receive(nodes.storage() + nb_nodes * spatial_dimension,
+		   nb_nodes_to_recv[p] * spatial_dimension,
+		   p, Tag::genTag(p, 0, SEND_NODES_TAG));
+      nb_nodes += nb_nodes_to_recv[p];
+    }
+  }
+
+  comm.waitAll(isend_coordinates_requests);
+  comm.freeCommunicationRequest(isend_coordinates_requests);
+  delete [] nodes_to_send_per_proc;
+
+  // comm.waitAll(irecv_nodes_requests);
+  // comm.freeCommunicationRequest(irecv_nodes_requests);
 
   mesh.sendEvent(new_nodes);
   mesh.sendEvent(new_elements);
 
 
   AKANTU_DEBUG_OUT();
-  return communicator;
+  return &communicator;
 }
 
-/* -------------------------------------------------------------------------- */
-// template <class E>
-// GridSynchronizer * GridSynchronizer::cleanupExtraElement(const Vector<Element> & element_to_remove) {
-//   AKANTU_DEBUG_IN();
-
-  
-
-
-
-//   AKANTU_DEBUG_OUT();
-// }
-
 /* -------------------------------------------------------------------------- */
 template GridSynchronizer *
 GridSynchronizer::createGridSynchronizer<QuadraturePoint>(Mesh & mesh,
                                                           const RegularGrid<QuadraturePoint> & grid,
                                                           SynchronizerID id,
                                                           MemoryID memory_id);
 template GridSynchronizer *
 GridSynchronizer::createGridSynchronizer<Element>(Mesh & mesh,
                                                   const RegularGrid<Element> & grid,
                                                   SynchronizerID id,
                                                   MemoryID memory_id);
 
 __END_AKANTU__
diff --git a/src/synchronizer/grid_synchronizer.hh b/src/synchronizer/grid_synchronizer.hh
index 052e2d680..cb9f959a0 100644
--- a/src/synchronizer/grid_synchronizer.hh
+++ b/src/synchronizer/grid_synchronizer.hh
@@ -1,97 +1,89 @@
 /**
  * @file   grid_synchronizer.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Fri Sep 16 15:05:52 2011
  *
  * @brief  synchronizer based in RegularGrid
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "distributed_synchronizer.hh"
 
 /* -------------------------------------------------------------------------- */
 
 
 #ifndef __AKANTU_GRID_SYNCHRONIZER_HH__
 #define __AKANTU_GRID_SYNCHRONIZER_HH__
 
 __BEGIN_AKANTU__
 
 class Mesh;
 template<class T>
 class RegularGrid;
 
 class GridSynchronizer : public DistributedSynchronizer {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
-public:
-
-  GridSynchronizer(const ID & id = "grid_synchronizer", MemoryID memory_id = 0);
+protected:
+  GridSynchronizer(Mesh & mesh, const ID & id = "grid_synchronizer", MemoryID memory_id = 0);
 
+public:
   virtual ~GridSynchronizer() { };
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   template <class E>
   static GridSynchronizer *
   createGridSynchronizer(Mesh & mesh,
 			 const RegularGrid<E> & grid,
 			 SynchronizerID id = "grid_synchronizer",
 			 MemoryID memory_id = 0);
 
-  /// function to print the contain of the class
-  // virtual void printself(std::ostream & stream, int indent = 0) const;
+
+protected:
+  enum CommTags {
+    SIZE_TAG        = 0,
+    DATA_TAG        = 1,
+    ASK_NODES_TAG   = 2,
+    SEND_NODES_TAG  = 3
+  };
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
 
 };
 
 
-/* -------------------------------------------------------------------------- */
-/* inline functions                                                           */
-/* -------------------------------------------------------------------------- */
-
-//#include "grid_synchronizer_inline_impl.cc"
-
-/// standard output stream operator
-// inline std::ostream & operator <<(std::ostream & stream, const GridSynchronizer & _this)
-// {
-//   _this.printself(stream);
-//   return stream;
-// }
-
-
 __END_AKANTU__
 
 #endif /* __AKANTU_GRID_SYNCHRONIZER_HH__ */
diff --git a/src/synchronizer/synchronizer.hh b/src/synchronizer/synchronizer.hh
index ba96706e9..2821991c1 100644
--- a/src/synchronizer/synchronizer.hh
+++ b/src/synchronizer/synchronizer.hh
@@ -1,101 +1,129 @@
 /**
  * @file   synchronizer.hh
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Mon Aug 23 13:48:37 2010
  *
  * @brief  interface for communicator and pbc synchronizers
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_SYNCHRONIZER_HH__
 #define __AKANTU_SYNCHRONIZER_HH__
 
 /* -------------------------------------------------------------------------- */
 #include "aka_memory.hh"
 #include "data_accessor.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
   class GhostSynchronizer;
 }
 
 __BEGIN_AKANTU__
 
 class Synchronizer : protected Memory {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   Synchronizer(SynchronizerID id = "synchronizer", MemoryID memory_id = 0);
 
   virtual ~Synchronizer() { };
 
   virtual void printself(__attribute__((unused)) std::ostream & stream,
 			 __attribute__((unused)) int indent = 0) const {};
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// synchronize ghosts
   void synchronize(DataAccessor & data_accessor,SynchronizationTag tag);
 
   /// asynchronous synchronization of ghosts
   virtual void asynchronousSynchronize(DataAccessor & data_accessor,SynchronizationTag tag) = 0;
 
   /// wait end of asynchronous synchronization of ghosts
   virtual void waitEndSynchronize(DataAccessor & data_accessor,SynchronizationTag tag) = 0;
 
   /// compute buffer size for a given tag and data accessor
   virtual void computeBufferSize(DataAccessor & data_accessor, SynchronizationTag tag)=0;
 
+  /**
+   * tag = |__________20_________|___8____|_4_|
+   *       |          proc       | num mes| ct|
+   */
+  class Tag {
+  public:
+    operator int() { return int(tag); }
+
+    static inline Tag genTag(int proc, UInt msg_count, UInt tag) {
+      Tag t;
+      t.tag = (((proc & 0xFFFFF) << 12) + ((msg_count & 0xFF) << 4) + (tag & 0xF));
+      return t;
+    }
+
+    virtual void printself(std::ostream & stream, int indent = 0) const {
+      stream << (tag >> 12) << ":" << (tag >> 4 & 0xFF) << ":" << (tag & 0xF);
+    }
+
+  private:
+    UInt tag;
+  };
+
 protected:
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
 
   /// id of the synchronizer
   SynchronizerID id;
 
 };
 
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const Synchronizer & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
+inline std::ostream & operator <<(std::ostream & stream, const Synchronizer::Tag & _this)
+{
+  _this.printself(stream);
+  return stream;
+}
+
 
 __END_AKANTU__
 
 #endif /* __AKANTU_SYNCHRONIZER_HH__ */
diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_1d.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_1d.cc
index 3a4b98355..ed82a9cac 100644
--- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_1d.cc
+++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_1d.cc
@@ -1,184 +1,184 @@
 /**
  * @file   test_solid_mechanics_model_implicit_1d.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Mon Feb 21 14:56:16 2011
  *
  * @brief  test of traction in implicit
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 #include <limits>
 #include <fstream>
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "mesh.hh"
 #include "mesh_io.hh"
 #include "mesh_io_msh.hh"
 #include "solid_mechanics_model.hh"
 #include "material.hh"
 /* -------------------------------------------------------------------------- */
 #ifdef AKANTU_USE_IOHELPER
 #  include "io_helper.hh"
 
 #endif //AKANTU_USE_IOHELPER
 
 #ifdef AKANTU_USE_SCOTCH
 #include "mesh_partition_scotch.hh"
 #endif
 
 int main(int argc, char *argv[])
 {
 
   akantu::initialize(argc, argv);
 
 #ifdef AKANTU_USE_IOHELPER
   akantu::ElementType type = akantu::_segment_2;
   iohelper::ElemType paraview_type = iohelper::LINE1;
 #endif //AKANTU_USE_IOHELPER
   akantu::UInt spatial_dimension = 1;
   // akantu::UInt max_steps = 10000;
   // akantu::Real time_factor = 0.2;
 
   //  akantu::Real epot, ekin;
 
   akantu::Mesh mesh(spatial_dimension);
   akantu::MeshIOMSH mesh_io;
   mesh_io.read("segment1.msh", mesh);
 
 // #ifdef AKANTU_USE_SCOTCH
 //   mesh_io.write("bar1_breorder.msh", mesh);
 
 //   akantu::MeshPartition * partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension);
 //   partition->reorder();
 //   delete partition;
 
 //   mesh_io.write("bar1_reorder.msh", mesh);
 // #endif
 
   akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh);
 
   akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes();
 #ifdef AKANTU_USE_IOHELPER
   akantu::UInt nb_element = model->getFEM().getMesh().getNbElement(type);
 #endif //AKANTU_USE_IOHELPER
 
   /// model initialization
   model->initVectors();
 
   /// set vectors to 0
   memset(model->getForce().values,        0,
 	 spatial_dimension*nb_nodes*sizeof(akantu::Real));
   memset(model->getVelocity().values,     0,
 	 spatial_dimension*nb_nodes*sizeof(akantu::Real));
   memset(model->getAcceleration().values, 0,
 	 spatial_dimension*nb_nodes*sizeof(akantu::Real));
   memset(model->getDisplacement().values, 0,
 	 spatial_dimension*nb_nodes*sizeof(akantu::Real));
 
   model->initModel();
 
   model->readMaterials("material.dat");
   model->initMaterials();
 
   model->initImplicit();
 
   std::cout << model->getMaterial(0) << std::endl;
 
   /// boundary conditions
   // akantu::Real eps = 1e-16;
   // for (akantu::UInt i = 0; i < nb_nodes; ++i) {
   //   if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] >= (bar_length  - bar_length / 10.))
   //     model->getDisplacement().values[spatial_dimension*i] = (model->getFEM().getMesh().getNodes().values[spatial_dimension*i] - (bar_length - bar_length / 10.)) / 100.;
 
   //   if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] <= eps)
   // 	model->getBoundary().values[spatial_dimension*i] = true;
 
   //   if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] <= eps ||
   //      model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] >= 1 - eps ) {
   //     model->getBoundary().values[spatial_dimension*i + 1] = true;
   //   }
   // }
 
   //  model->getForce().at(0) = -1000;
-  model->getBoundary().at(0,0) = true;
-  model->getForce().at(1,0) = 1000;
+  model->getBoundary()(0,0) = true;
+  model->getForce()(1,0) = 1000;
 
   model->initializeUpdateResidualData();
 
 #ifdef AKANTU_USE_IOHELPER
   /// initialize the paraview output
   iohelper::DumperParaview dumper;
   dumper.SetMode(iohelper::TEXT);
   dumper.SetPoints(model->getFEM().getMesh().getNodes().values,
 		   spatial_dimension, nb_nodes, "implicit");
   dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values,
 			 paraview_type, nb_element, iohelper::C_MODE);
   dumper.AddNodeDataField(model->getDisplacement().values,
 			  spatial_dimension, "displacements");
   dumper.AddNodeDataField(model->getVelocity().values,
 			  spatial_dimension, "velocity");
   dumper.AddNodeDataField(model->getForce().values,
 			  spatial_dimension, "applied_force");
   dumper.AddNodeDataField(model->getResidual().values,
 			  spatial_dimension, "forces");
   dumper.AddElemDataField(model->getMaterial(0).getStrain(type).values,
 			  spatial_dimension*spatial_dimension, "strain");
   dumper.AddElemDataField(model->getMaterial(0).getStress(type).values,
 			  spatial_dimension*spatial_dimension, "stress");
   dumper.SetEmbeddedValue("displacements", 1);
   dumper.SetEmbeddedValue("applied_force", 1);
   dumper.SetEmbeddedValue("forces", 1);
   dumper.SetPrefix("paraview/");
   dumper.Init();
   //  dumper.Dump();
 #endif //AKANTU_USE_IOHELPER
 
 
   akantu::debug::setDebugLevel(akantu::dblInfo);
   akantu::UInt count = 0;
   model->updateResidual();
 #ifdef AKANTU_USE_IOHELPER
     dumper.Dump();
 #endif //AKANTU_USE_IOHELPER
   while(!model->testConvergenceResidual(1e-1) && (count <= 10)) {
     std::cout << "Iter : " << ++count << std::endl;
     model->assembleStiffnessMatrix();
 
     model->solveStatic();
 
     model->getStiffnessMatrix().saveMatrix("Ktmp.mtx");
 
     model->updateResidual();
     //    model->assembleStiffnessMatrix();
 #ifdef AKANTU_USE_IOHELPER
     dumper.Dump();
 #endif //AKANTU_USE_IOHELPER
   }
 
   delete model;
   akantu::finalize();
 
   return EXIT_SUCCESS;
 }
diff --git a/test/test_synchronizer/test_grid_synchronizer.cc b/test/test_synchronizer/test_grid_synchronizer.cc
index 608d5f0b6..689ff8fdd 100644
--- a/test/test_synchronizer/test_grid_synchronizer.cc
+++ b/test/test_synchronizer/test_grid_synchronizer.cc
@@ -1,339 +1,354 @@
 /**
  * @file   test_grid_synchronizer.cc
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @date   Mon Nov  7 11:58:02 2011
  *
  * @brief  test the GridSynchronizer object
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "aka_grid.hh"
 #include "mesh.hh"
 #include "mesh_io.hh"
 #include "grid_synchronizer.hh"
 #include "mesh_partition.hh"
 #include "synchronizer_registry.hh"
 #ifdef AKANTU_USE_IOHELPER
 #  include "io_helper.hh"
 #endif //AKANTU_USE_IOHELPER
 
 using namespace akantu;
 
 class TestAccessor : public DataAccessor {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   TestAccessor(const Mesh & mesh);
   ~TestAccessor();
 
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Barycenter, barycenter, Real);
 
   /* ------------------------------------------------------------------------ */
   /* Ghost Synchronizer inherited members                                     */
   /* ------------------------------------------------------------------------ */
 protected:
-  virtual UInt getNbDataToPack(const Element & element,
-				       SynchronizationTag tag) const;
-  virtual UInt getNbDataToUnpack(const Element & element,
-					 SynchronizationTag tag) const;
-  virtual void packData(CommunicationBuffer & buffer,
-			const Element & element,
+  virtual UInt getNbDataForElements(const Vector<Element> & elements,
+				    SynchronizationTag tag) const;
+  virtual void packElementData(CommunicationBuffer & buffer,
+			const Vector<Element> & elements,
 			SynchronizationTag tag) const;
-  virtual void unpackData(CommunicationBuffer & buffer,
-			  const Element & element,
-			  SynchronizationTag tag);
+  virtual void unpackElementData(CommunicationBuffer & buffer,
+				 const Vector<Element> & elements,
+				 SynchronizationTag tag);
 
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   std::string id;
 
   ByElementTypeReal barycenter;
 
   const Mesh & mesh;
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* TestSynchronizer implementation                                            */
 /* -------------------------------------------------------------------------- */
 TestAccessor::TestAccessor(const Mesh & mesh) : barycenter("barycenter", id), mesh(mesh) {
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   id = "test_synchronizer";
 
   Mesh::ConnectivityTypeList::const_iterator it;
   try {
     const Mesh::ConnectivityTypeList & ghost_type_list = mesh.getConnectivityTypeList(_ghost);
     for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) {
       if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue;
 
       UInt nb_ghost_element = mesh.getNbElement(*it,_ghost);
       barycenter.alloc(nb_ghost_element, spatial_dimension, *it);
     }
   } catch (debug::Exception & e) { std::cout << e << std::endl; }
 }
 
 TestAccessor::~TestAccessor() {
 
 }
 
-UInt TestAccessor::getNbDataToPack(const Element & element,
-					       __attribute__ ((unused)) SynchronizationTag tag) const {
-  return Mesh::getSpatialDimension(element.type) * sizeof(Real);
+UInt TestAccessor::getNbDataForElements(const Vector<Element> & elements,
+					__attribute__ ((unused)) SynchronizationTag tag) const {
+  return Mesh::getSpatialDimension(elements(0).type) * sizeof(Real) * elements.getSize();
 }
 
-UInt TestAccessor::getNbDataToUnpack(const Element & element,
-						 __attribute__ ((unused)) SynchronizationTag tag) const {
-  return Mesh::getSpatialDimension(element.type) * sizeof(Real);
-}
-
-void TestAccessor::packData(CommunicationBuffer & buffer,
-				const Element & element,
-				__attribute__ ((unused)) SynchronizationTag tag) const {
-  UInt spatial_dimension = Mesh::getSpatialDimension(element.type);
-  types::RVector bary(spatial_dimension);
-  mesh.getBarycenter(element.element, element.type, bary.storage());
-
-  buffer << bary;
+void TestAccessor::packElementData(CommunicationBuffer & buffer,
+				   const Vector<Element> & elements,
+				   __attribute__ ((unused)) SynchronizationTag tag) const {
+  UInt spatial_dimension = mesh.getSpatialDimension();
+  Vector<Element>::const_iterator<Element> bit  = elements.begin();
+  Vector<Element>::const_iterator<Element> bend = elements.end();
+  for (; bit != bend; ++bit) {
+    const Element & element = *bit;
+
+    types::RVector bary(barycenter(element.type,
+				   element.ghost_type).storage() + element.element * spatial_dimension,
+			spatial_dimension);;
+    buffer << barycenter;
+  }
 }
 
-void TestAccessor::unpackData(CommunicationBuffer & buffer,
-				  const Element & element,
-				  __attribute__ ((unused)) SynchronizationTag tag) {
-  UInt spatial_dimension = Mesh::getSpatialDimension(element.type);
-  Vector<Real>::iterator<types::RVector> bary =
-    barycenter(element.type).begin(spatial_dimension);
-  buffer >> bary[element.element];
+void TestAccessor::unpackElementData(CommunicationBuffer & buffer,
+				     const Vector<Element> & elements,
+				     __attribute__ ((unused)) SynchronizationTag tag) {
+  UInt spatial_dimension = mesh.getSpatialDimension();
+  Vector<Element>::const_iterator<Element> bit  = elements.begin();
+  Vector<Element>::const_iterator<Element> bend = elements.end();
+  for (; bit != bend; ++bit) {
+    const Element & element = *bit;
+
+    types::RVector barycenter_loc(spatial_dimension);
+    mesh.getBarycenter(element.element, element.type, barycenter_loc.storage(), element.ghost_type);
+
+    types::RVector barycenter(spatial_dimension);
+    buffer >> barycenter;
+    Real tolerance = 1e-15;
+    for (UInt i = 0; i < spatial_dimension; ++i) {
+      if(!(std::abs(barycenter(i) - barycenter_loc(i)) <= tolerance))
+	AKANTU_DEBUG_ERROR("Unpacking an unknown value for the element: "
+			   << element
+			   << "(barycenter[" << i << "] = " << barycenter_loc(i)
+			   << " and buffer[" << i << "] = " << barycenter(i) << ") - tag: " << tag);
+    }
+  }
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* Main                                                                       */
 /* -------------------------------------------------------------------------- */
 int main(int argc, char *argv[]) {
   akantu::initialize(argc, argv);
 
   UInt spatial_dimension = 2;
   ElementType type = _triangle_3;
 
   Mesh mesh(spatial_dimension);
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   Int psize = comm.getNbProc();
   Int prank = comm.whoAmI();
 
   if(prank == 0) {
     MeshIOMSH mesh_io;
     mesh_io.read("triangle.msh", mesh);
     MeshPartition * partition = new MeshPartitionScotch(mesh, spatial_dimension);
     partition->partitionate(psize);
     DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, partition);
     delete partition;
   } else {
     DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, NULL);
   }
 
 #ifdef AKANTU_USE_IOHELPER
   double * part;
   unsigned int nb_nodes = mesh.getNbNodes();
   unsigned int nb_element = mesh.getNbElement(type);
 
   iohelper::DumperParaview dumper;
   dumper.SetMode(iohelper::TEXT);
   dumper.SetParallelContext(prank, psize);
   dumper.SetPoints(mesh.getNodes().values, spatial_dimension, nb_nodes, "test-grid-synchronizer");
   dumper.SetConnectivity((int*) mesh.getConnectivity(type).values,
    			 iohelper::TRIANGLE1, nb_element, iohelper::C_MODE);
   part = new double[nb_element];
   for (unsigned int i = 0; i < nb_element; ++i)
     part[i] = prank;
   dumper.AddElemDataField(part, 1, "partitions");
   dumper.SetPrefix("paraview/");
   dumper.Init();
   dumper.Dump();
   delete [] part;
 
   iohelper::DumperParaview dumper_ghost;
   dumper_ghost.SetMode(iohelper::TEXT);
   dumper_ghost.SetParallelContext(prank, psize);
 
   try {
     unsigned int nb_ghost_element = mesh.getNbElement(type,_ghost);
     dumper_ghost.SetPoints(mesh.getNodes().values, spatial_dimension, nb_nodes, "test-grid-synchronizer-ghost");
     dumper_ghost.SetConnectivity((int*) mesh.getConnectivity(type,_ghost).values,
 				 iohelper::TRIANGLE1, nb_ghost_element, iohelper::C_MODE);
     part = new double[nb_ghost_element];
     for (unsigned int i = 0; i < nb_ghost_element; ++i)
       part[i] = prank;
     dumper_ghost.AddElemDataField(part, 1, "partitions");
     dumper_ghost.SetPrefix("paraview/");
     dumper_ghost.Init();
     dumper_ghost.Dump();
     delete [] part;
   } catch (debug::Exception & e) { std::cout << e << std::endl; }
 #endif
 
 
   comm.barrier();
 
   mesh.computeBoundingBox();
 
   Real lower_bounds[spatial_dimension];
   Real upper_bounds[spatial_dimension];
 
   mesh.getLowerBounds(lower_bounds);
   mesh.getUpperBounds(upper_bounds);
 
   Real spacing[spatial_dimension];
 
   for (UInt i = 0; i < spatial_dimension; ++i) {
     spacing[i] = (upper_bounds[i] - lower_bounds[i]) / 10.;
   }
 
   Real local_lower_bounds[spatial_dimension];
   Real local_upper_bounds[spatial_dimension];
 
   mesh.getLocalLowerBounds(local_lower_bounds);
   mesh.getLocalUpperBounds(local_upper_bounds);
 
   RegularGrid<Element> grid(spatial_dimension, local_lower_bounds, local_upper_bounds, spacing);
 
   GhostType ghost_type = _not_ghost;
 
   Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type);
 
   std::cout << prank <<  " TTTTTTTOOOOOOOOOOOOOTTTTTTTTTTTTTTTTOOOOOOOOOOOOO" << grid <<std::endl;
 
   ByElementTypeReal barycenters("", "", 0);
   mesh.initByElementTypeVector(barycenters, spatial_dimension, 0);
   // first generate the quad points coordinate and count the number of points per cell
   for(; it != last_type; ++it) {
     UInt nb_element = mesh.getNbElement(*it);
     Vector<Real> & barycenter = barycenters(*it);
     barycenter.resize(nb_element);
 
     //     Vector<Real>::iterator<types::RVector> bary_it = barycenter.begin(spatial_dimension);
     // for (UInt elem = 0; elem < nb_element; ++elem) {
     //   
     //   grid.count(*bary_it);
     //   ++bary_it;
     // }
   }
 
   Element e;
   e.ghost_type = ghost_type;
 
   std::cout << prank <<  " TTTTTTTOOOOOOOOOOOOOTTTTTTTTTTTTTTTTOOOOOOOOOOOOO" << std::endl;
 
   // second insert the point in the cells
   //  grid.beginInsertions();
   it = mesh.firstType(spatial_dimension, ghost_type);
   for(; it != last_type; ++it) {
     UInt nb_element = mesh.getNbElement(*it);
     e.type = *it;
     Vector<Real> & barycenter = barycenters(*it);
     Vector<Real>::iterator<types::RVector> bary_it = barycenter.begin(spatial_dimension);
     for (UInt elem = 0; elem < nb_element; ++elem) {
       mesh.getBarycenter(elem, *it, bary_it->storage());
       e.element = elem;
       grid.insert(e, *bary_it);
       ++bary_it;
     }
   }
   //  grid.endInsertions();
 
   MeshIOMSH mesh_io;
 
   std::stringstream sstr; sstr << "mesh_" << prank << ".msh";
   mesh_io.write(sstr.str(), mesh);
 
   Mesh grid_mesh(spatial_dimension, "grid_mesh", 0);
   std::stringstream sstr_grid; sstr_grid << "grid_mesh_" << prank << ".msh";
   grid.saveAsMesh(grid_mesh);
   mesh_io.write(sstr_grid.str(), grid_mesh);
 
   std::cout << "TTTTTTTOOOOOOOOOOOOOTTTTTTTTTTTTTTTTOOOOOOOOOOOOO" << std::endl;
   GridSynchronizer * grid_communicator = GridSynchronizer::createGridSynchronizer(mesh, grid);
 
   AKANTU_DEBUG_INFO("Creating TestAccessor");
   TestAccessor test_accessor(mesh);
   SynchronizerRegistry synch_registry(test_accessor);
 
   synch_registry.registerSynchronizer(*grid_communicator, _gst_test);
 
   AKANTU_DEBUG_INFO("Synchronizing tag");
   synch_registry.synchronize(_gst_test);
 
 
 #ifdef AKANTU_USE_IOHELPER
   try {
     UInt nb_ghost_element = mesh.getNbElement(type, _ghost);
     UInt nb_nodes = mesh.getNbNodes();
 
     iohelper::DumperParaview dumper_ghost;
     dumper_ghost.SetMode(iohelper::TEXT);
     dumper_ghost.SetParallelContext(prank, psize);
 
     dumper_ghost.SetMode(iohelper::TEXT);
     dumper_ghost.SetParallelContext(prank, psize);
     dumper_ghost.SetPoints(mesh.getNodes().values, spatial_dimension, nb_nodes, "test-grid-synchronizer-ghost");
     dumper_ghost.SetConnectivity((int*) mesh.getConnectivity(type,_ghost).values,
 				 iohelper::TRIANGLE1, nb_ghost_element, iohelper::C_MODE);
     part = new double[nb_ghost_element];
     for (unsigned int i = 0; i < nb_ghost_element; ++i)
       part[i] = prank;
     dumper_ghost.AddElemDataField(part, 1, "partitions");
     dumper_ghost.Dump();
     delete [] part;
 
     unsigned int nb_grid_element = grid_mesh.getNbElement(_quadrangle_4);
     unsigned int nb_quadrature_points = 4;
     iohelper::DumperParaview dumper_grid;
     dumper_grid.SetMode(iohelper::TEXT);
     dumper_grid.SetParallelContext(prank, psize);
     dumper_grid.SetPoints(grid_mesh.getNodes().values, spatial_dimension,
 			  grid_mesh.getNbNodes(), "test-grid-synchronizer-grid");
     dumper_grid.SetConnectivity((int*) grid_mesh.getConnectivity(_quadrangle_4).values,
 				iohelper::QUAD1, nb_grid_element, iohelper::C_MODE);
 
     part = new double[nb_grid_element * nb_quadrature_points];
     std::fill_n(part, nb_grid_element * nb_quadrature_points, prank);
 
     dumper_grid.AddElemDataField(part, 1, "partitions");
     dumper_grid.SetPrefix("paraview/");
     dumper_grid.Init();
     dumper_grid.Dump();
     delete [] part;
   } catch(debug::Exception & e) { std::cout << e << std::endl; }
 #endif //AKANTU_USE_IOHELPER
 
 
   akantu::finalize();
 
   return EXIT_SUCCESS;
 }