diff --git a/cmake/AkantuExtraCompilationProfiles.cmake b/cmake/AkantuExtraCompilationProfiles.cmake
index b2e5bc731..b96e88ec6 100644
--- a/cmake/AkantuExtraCompilationProfiles.cmake
+++ b/cmake/AkantuExtraCompilationProfiles.cmake
@@ -1,34 +1,34 @@
 #Profiling
 set(CMAKE_CXX_FLAGS_PROFILING "-g -pg -DNDEBUG -DAKANTU_NDEBUG -O2"
   CACHE STRING "Flags used by the compiler during profiling builds")
 set(CMAKE_C_FLAGS_PROFILING "-g -pg -DNDEBUG -DAKANTU_NDEBUG -O2"
   CACHE STRING "Flags used by the compiler during profiling builds")
 set(CMAKE_Fortran_FLAGS_PROFILING "-g -pg -DNDEBUG -DAKANTU_NDEBUG -O2"
   CACHE STRING "Flags used by the compiler during profiling builds")
 set(CMAKE_EXE_LINKER_FLAGS_PROFILING "-pg"
   CACHE STRING "Flags used by the linker during profiling builds")
 set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-pg"
   CACHE STRING "Flags used by the linker during profiling builds")
 
 
 # Sanitize the code
 if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "5.2") OR
     CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
-  set(CMAKE_CXX_FLAGS_SANITIZE "-g -O2 -fsanitize=address -fsanitize=leak -fsanitize=undefined"
+  set(CMAKE_CXX_FLAGS_SANITIZE "-g -O2 -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer"
     CACHE STRING "Flags used by the compiler during sanitining builds")
-  set(CMAKE_C_FLAGS_SANITIZE "-g -O2 -fsanitize=address -fsanitize=leak -fsanitize=undefined"
+  set(CMAKE_C_FLAGS_SANITIZE "-g -O2 -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer"
     CACHE STRING "Flags used by the compiler during sanitining builds")
-  set(CMAKE_Fortran_FLAGS_SANITIZE "-g -O2 -fsanitize=address -fsanitize=leak -fsanitize=undefined"
+  set(CMAKE_Fortran_FLAGS_SANITIZE "-g -O2 -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer"
     CACHE STRING "Flags used by the compiler during sanitining builds")
-  set(CMAKE_EXE_LINKER_FLAGS_SANITIZE "-fsanitize=address -fsanitize=leak -fsanitize=undefined"
+  set(CMAKE_EXE_LINKER_FLAGS_SANITIZE "-fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer"
     CACHE STRING "Flags used by the linker during sanitining builds")
-  set(CMAKE_SHARED_LINKER_FLAGS_SANITIZE "-fsanitize=address -fsanitize=leak -fsanitize=undefined"
+  set(CMAKE_SHARED_LINKER_FLAGS_SANITIZE "-fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer"
     CACHE STRING "Flags used by the linker during sanitining builds")
 
   mark_as_advanced(CMAKE_CXX_FLAGS_PROFILING CMAKE_C_FLAGS_PROFILING
     CMAKE_Fortran_FLAGS_PROFILING CMAKE_EXE_LINKER_FLAGS_PROFILING
     CMAKE_SHARED_LINKER_FLAGS_PROFILING CMAKE_SHARED_LINKER_FLAGS_SANITIZE
     CMAKE_CXX_FLAGS_SANITIZE CMAKE_C_FLAGS_SANITIZE
     CMAKE_Fortran_FLAGS_SANITIZE CMAKE_EXE_LINKER_FLAGS_SANITIZE
     )
 endif()
diff --git a/src/common/aka_array.cc b/src/common/aka_array.cc
index b31c3248d..d1601dbdc 100644
--- a/src/common/aka_array.cc
+++ b/src/common/aka_array.cc
@@ -1,117 +1,101 @@
 /**
  * @file   aka_array.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Tue Feb 20 2018
  *
  * @brief  Implementation of akantu::Array
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 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 <memory>
 #include <utility>
 
 /* -------------------------------------------------------------------------- */
 #include "aka_array.hh"
 #include "aka_common.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 /* Functions ArrayBase                                                       */
 /* -------------------------------------------------------------------------- */
 
-/* -------------------------------------------------------------------------- */
-void ArrayBase::printself(std::ostream & stream, int indent) const {
-  std::string space;
-  for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
-    ;
-  stream << space << "ArrayBase [" << std::endl;
-  stream << space << " + size             : " << size_ << std::endl;
-  stream << space << " + nb component     : " << nb_component << std::endl;
-  stream << space << " + allocated size   : " << allocated_size << std::endl;
-  Real mem_size = (allocated_size * nb_component * size_of_type) / 1024.;
-  stream << space << " + size of type     : " << size_of_type << "B"
-         << std::endl;
-  stream << space << " + memory allocated : " << mem_size << "kB" << std::endl;
-  stream << space << "]" << std::endl;
-}
-
 /* -------------------------------------------------------------------------- */
 template <> UInt Array<Real>::find(const Real & elem) const {
   AKANTU_DEBUG_IN();
 
   Real epsilon = std::numeric_limits<Real>::epsilon();
   auto it = std::find_if(begin(), end(), [&elem, &epsilon](auto && a) {
     return std::abs(a - elem) <= epsilon;
   });
 
   AKANTU_DEBUG_OUT();
   return (it != end()) ? end() - it : UInt(-1);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 Array<ElementType> & Array<ElementType>::operator*=(__attribute__((unused))
                                                     const ElementType & alpha) {
   AKANTU_TO_IMPLEMENT();
   return *this;
 }
 
 template <>
 Array<ElementType> & Array<ElementType>::
 operator-=(__attribute__((unused)) const Array<ElementType> & vect) {
   AKANTU_TO_IMPLEMENT();
   return *this;
 }
 
 template <>
 Array<ElementType> & Array<ElementType>::
 operator+=(__attribute__((unused)) const Array<ElementType> & vect) {
   AKANTU_TO_IMPLEMENT();
   return *this;
 }
 
 template <>
 Array<char> & Array<char>::operator*=(__attribute__((unused))
                                       const char & alpha) {
   AKANTU_TO_IMPLEMENT();
   return *this;
 }
 
 template <>
 Array<char> & Array<char>::operator-=(__attribute__((unused))
                                       const Array<char> & vect) {
   AKANTU_TO_IMPLEMENT();
   return *this;
 }
 
 template <>
 Array<char> & Array<char>::operator+=(__attribute__((unused))
                                       const Array<char> & vect) {
   AKANTU_TO_IMPLEMENT();
   return *this;
 }
 
 } // namespace akantu
diff --git a/src/common/aka_array.hh b/src/common/aka_array.hh
index 2a36fd1e7..c29ee5fa5 100644
--- a/src/common/aka_array.hh
+++ b/src/common/aka_array.hh
@@ -1,381 +1,439 @@
 /**
  * @file   aka_array.hh
  *
  * @author Till Junge <till.junge@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Tue Jan 16 2018
  *
  * @brief  Array container for Akantu
  * This container differs from the std::vector from the fact it as 2 dimensions
  * a main dimension and the size stored per entries
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 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>
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /// class that afford to store vectors in static memory
 class ArrayBase {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   explicit ArrayBase(ID id = "") : id(std::move(id)) {}
+  ArrayBase(const ArrayBase & other, const ID & id = "") {
+    this->id = (id == "") ? other.id : id;
+  }
 
   ArrayBase(const ArrayBase & other) = default;
   ArrayBase(ArrayBase && other) = default;
-
   ArrayBase & operator=(const ArrayBase & other) = default;
-  //ArrayBase & operator=(ArrayBase && other) = default;
+  // ArrayBase & operator=(ArrayBase && other) = default;
 
   virtual ~ArrayBase() = default;
 
-
-
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// get the amount of space allocated in bytes
-  inline UInt getMemorySize() const;
+  virtual UInt getMemorySize() const = 0;
 
   /// 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;
+  virtual void printself(std::ostream & stream, int indent = 0) const = 0;
 
   /* ------------------------------------------------------------------------ */
   /* Accessors */
   /* ------------------------------------------------------------------------ */
 public:
-  /// Get the real size allocated in memory
-  AKANTU_GET_MACRO(AllocatedSize, allocated_size, UInt);
   /// Get the Size of the Array
-  UInt getSize() const __attribute__((deprecated)) { return size_; }
   UInt size() const { return size_; }
   /// Get the number of components
   AKANTU_GET_MACRO(NbComponent, nb_component, UInt);
   /// Get the name of th array
   AKANTU_GET_MACRO(ID, id, const ID &);
   /// Set the name of th array
   AKANTU_SET_MACRO(ID, id, const ID &);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// id of the vector
-  ID id;
-
-  /// the size allocated
-  UInt allocated_size{0};
+  ID id{""};
 
   /// the size used
   UInt size_{0};
 
   /// number of components
   UInt nb_component{1};
-
-  /// size of the stored type
-  UInt size_of_type{0};
 };
 
 /* -------------------------------------------------------------------------- */
 namespace {
   template <std::size_t dim, typename T> struct IteratorHelper {};
 
   template <typename T> struct IteratorHelper<0, T> { using type = T; };
   template <typename T> struct IteratorHelper<1, T> { using type = Vector<T>; };
   template <typename T> struct IteratorHelper<2, T> { using type = Matrix<T>; };
   template <typename T> struct IteratorHelper<3, T> {
     using type = Tensor3<T>;
   };
 
   template <std::size_t dim, typename T>
   using IteratorHelper_t = typename IteratorHelper<dim, T>::type;
 } // namespace
 
 /* -------------------------------------------------------------------------- */
-template <typename T, bool is_scal> class Array : public ArrayBase {
-  /* ------------------------------------------------------------------------ */
-  /* Constructors/Destructors                                                 */
-  /* ------------------------------------------------------------------------ */
+/* Memory handling layer                                                      */
+/* -------------------------------------------------------------------------- */
+enum class ArrayAllocationType {
+  _default,
+  _pod,
+};
+
+template <typename T>
+struct ArrayAllocationTrait
+    : public std::conditional_t<
+          std::is_scalar<T>::value,
+          std::integral_constant<ArrayAllocationType,
+                                 ArrayAllocationType::_pod>,
+          std::integral_constant<ArrayAllocationType,
+                                 ArrayAllocationType::_default>> {};
+
+/* -------------------------------------------------------------------------- */
+template <typename T,
+          ArrayAllocationType allocation_trait = ArrayAllocationTrait<T>::value>
+class ArrayDataLayer : public ArrayBase {
 public:
   using value_type = T;
   using reference = value_type &;
   using pointer_type = value_type *;
   using const_reference = const value_type &;
 
-  inline ~Array() override;
+public:
+  virtual ~ArrayDataLayer() = default;
 
   /// Allocation of a new vector
-  explicit inline Array(UInt size = 0, UInt nb_component = 1,
-                        const ID & id = "");
+  explicit ArrayDataLayer(UInt size = 0, UInt nb_component = 1,
+                          const ID & id = "");
 
   /// Allocation of a new vector with a default value
-  Array(UInt size, UInt nb_component, const value_type def_values[],
-        const ID & id = "");
+  ArrayDataLayer(UInt size, UInt nb_component, const_reference value,
+                 const ID & id = "");
+
+  /// Copy constructor (deep copy)
+  ArrayDataLayer(const ArrayDataLayer & vect, const ID & id = "");
+
+#ifndef SWIG
+  /// Copy constructor (deep copy)
+  explicit ArrayDataLayer(const std::vector<value_type> & vect);
+#endif
+
+  // copy operator
+  ArrayDataLayer & operator=(const ArrayDataLayer & other);
+
+  // move constructor
+  ArrayDataLayer(ArrayDataLayer && other);
+
+  // move assign
+  ArrayDataLayer & operator=(ArrayDataLayer && other);
+
+protected:
+  // allocate the memory
+  void allocate(UInt size, UInt nb_component);
+
+  // allocate and initialize the memory
+  void allocate(UInt size, UInt nb_component, const T & value);
+
+public:
+  /// append a tuple of size nb_component containing value
+  inline void push_back(const_reference value);
+  /// append a vector
+  // inline void push_back(const value_type new_elem[]);
+
+#ifndef SWIG
+  /// append a Vector or a Matrix
+  template <template <typename> class C,
+            typename = std::enable_if_t<is_tensor<C<T>>::value>>
+  inline void push_back(const C<T> & new_elem);
+#endif
+
+  /// changes the allocated size but not the size
+  void reserve(UInt size);
+
+  /// change the size of the Array
+  void resize(UInt size);
+
+  /// change the size of the Array and initialize the values
+  void resize(UInt size, const T & val);
+
+  /// get the amount of space allocated in bytes
+  inline UInt getMemorySize() const override final;
+
+  /// Get the real size allocated in memory
+  inline UInt getAllocatedSize() const;
+
+  /// give the address of the memory allocated for this vector
+  T * storage() const { return values; };
+
+protected:
+  /// allocation type agnostic  data access
+  T * values{nullptr};
+
+  /// data storage
+  std::vector<T> data_storage;
+};
+
+/* -------------------------------------------------------------------------- */
+/* Actual Array                                                               */
+/* -------------------------------------------------------------------------- */
+template <typename T, bool is_scal> class Array : public ArrayDataLayer<T> {
+private:
+  using parent = ArrayDataLayer<T>;
+  /* ------------------------------------------------------------------------ */
+  /* Constructors/Destructors                                                 */
+  /* ------------------------------------------------------------------------ */
+public:
+  using value_type = typename parent::value_type;
+  using reference = typename parent::reference;
+  using pointer_type = typename parent::pointer_type;
+  using const_reference = typename parent::const_reference;
+
+  ~Array() override;
+
+  /// Allocation of a new vector
+  Array(UInt size = 0, UInt nb_component = 1, const ID & id = "");
 
   /// Allocation of a new vector with a default value
   Array(UInt size, UInt nb_component, const_reference value,
         const ID & id = "");
 
   /// Copy constructor (deep copy if deep=true)
-  Array(const Array<value_type, is_scal> & vect, //bool deep = true,
-        const ID & id = "");
+  Array(const Array & vect, const ID & id = "");
 
 #ifndef SWIG
   /// Copy constructor (deep copy)
-  explicit Array(const std::vector<value_type> & vect);
+  explicit Array(const std::vector<T> & vect);
 #endif
 
   // copy operator
   Array & operator=(const Array & other);
 
   // move constructor
-  Array(Array && other);
+  Array(Array && other) = default;
 
   // move assign
-  Array & operator=(Array && other);
+  Array & operator=(Array && other) = default;
 
 #ifndef SWIG
   /* ------------------------------------------------------------------------ */
   /* Iterator                                                                 */
   /* ------------------------------------------------------------------------ */
   /// \todo protected: does not compile with intel  check why
 public:
   template <class R, class it, class IR = R,
             bool is_tensor_ = is_tensor<R>::value>
   class iterator_internal;
 
 public:
   /* ------------------------------------------------------------------------ */
 
   /* ------------------------------------------------------------------------ */
   template <typename R = T> class const_iterator;
   template <typename R = T> class iterator;
 
   /* ------------------------------------------------------------------------ */
 
   /// iterator for Array of nb_component = 1
   using scalar_iterator = iterator<T>;
   /// const_iterator for Array of nb_component = 1
   using const_scalar_iterator = const_iterator<T>;
 
   /// iterator returning Vectors of size n  on entries of Array with
   /// nb_component = n
   using vector_iterator = iterator<Vector<T>>;
   /// const_iterator returning Vectors of n size on entries of Array with
   /// nb_component = n
   using const_vector_iterator = const_iterator<Vector<T>>;
 
   /// iterator returning Matrices of size (m, n) on entries of Array with
   /// nb_component = m*n
   using matrix_iterator = iterator<Matrix<T>>;
   /// const iterator returning Matrices of size (m, n) on entries of Array with
   /// nb_component = m*n
   using const_matrix_iterator = const_iterator<Matrix<T>>;
 
   /// iterator returning Tensor3 of size (m, n, k) on entries of Array with
   /// nb_component = m*n*k
   using tensor3_iterator = iterator<Tensor3<T>>;
   /// const iterator returning Tensor3 of size (m, n, k) on entries of Array
   /// with nb_component = m*n*k
   using const_tensor3_iterator = const_iterator<Tensor3<T>>;
 
   /* ------------------------------------------------------------------------ */
   template <typename... Ns> inline decltype(auto) begin(Ns &&... n);
   template <typename... Ns> inline decltype(auto) end(Ns &&... n);
 
   template <typename... Ns> inline decltype(auto) begin(Ns &&... n) const;
   template <typename... Ns> inline decltype(auto) end(Ns &&... n) const;
 
   template <typename... Ns> inline decltype(auto) begin_reinterpret(Ns &&... n);
   template <typename... Ns> inline decltype(auto) end_reinterpret(Ns &&... n);
 
   template <typename... Ns>
   inline decltype(auto) begin_reinterpret(Ns &&... n) const;
   template <typename... Ns>
   inline decltype(auto) end_reinterpret(Ns &&... n) const;
 #endif // SWIG
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
-  /// append a tuple of size nb_component containing value
-  inline void push_back(const_reference value);
-/// append a vector
-// inline void push_back(const value_type new_elem[]);
+  /// search elem in the vector, return  the position of the first occurrence or
+  /// -1 if not found
+  UInt find(const_reference elem) const;
+
+  /// @see Array::find(const_reference elem) const
+  UInt find(T elem[]) const;
+
+  inline void push_back(const_reference value) { parent::push_back(value); }
 
 #ifndef SWIG
   /// append a Vector or a Matrix
   template <template <typename> class C,
             typename = std::enable_if_t<is_tensor<C<T>>::value>>
-  inline void push_back(const C<T> & new_elem);
-  /// append the value of the iterator
-  template <typename Ret> inline void push_back(const iterator<Ret> & it);
+  inline void push_back(const C<T> & new_elem) {
+    parent::push_back(new_elem);
+  }
+
+  template <typename Ret> inline void push_back(const iterator<Ret> & it) {
+    push_back(*it);
+  }
 
   /// erase the value at position i
   inline void erase(UInt i);
   /// ask Nico, clarify
   template <typename R> inline iterator<R> erase(const iterator<R> & it);
-#endif
-
-  /// changes the allocated size but not the size
-  virtual void reserve(UInt size);
-
-  /// change the size of the Array
-  virtual void resize(UInt size);
-
-  /// change the size of the Array and initialize the values
-  virtual void resize(UInt size, const T & val);
-
-  /// change the number of components by interlacing data
-  /// @param multiplicator number of interlaced components add
-  /// @param block_size blocks of data in the array
-  /// Examaple for block_size = 2, multiplicator = 2
-  /// array = oo oo oo -> new array = oo nn nn oo nn nn oo nn nn
-  void extendComponentsInterlaced(UInt multiplicator, UInt stride);
-
-  /// search elem in the vector, return  the position of the first occurrence or
-  /// -1 if not found
-  UInt find(const_reference elem) const;
 
-  /// @see Array::find(const_reference elem) const
-  UInt find(T elem[]) const;
-
-#ifndef SWIG
   /// @see Array::find(const_reference elem) const
   template <template <typename> class C,
             typename = std::enable_if_t<is_tensor<C<T>>::value>>
   inline UInt find(const C<T> & elem);
 #endif
 
-  /// set all entries of the array to 0
-  inline void clear() { std::fill_n(values, size_ * nb_component, T()); }
-
   /// set all entries of the array to the value t
   /// @param t value to fill the array with
-  inline void set(T t) { std::fill_n(values, size_ * nb_component, t); }
+  inline void set(T t) {
+    std::fill_n(this->values, this->size_ * this->nb_component, t);
+  }
+
+  /// set all entries of the array to 0
+  inline void clear() { set(T()); }
 
 #ifndef SWIG
   /// set all tuples of the array to a given vector or matrix
   /// @param vm Matrix or Vector to fill the array with
   template <template <typename> class C,
             typename = std::enable_if_t<is_tensor<C<T>>::value>>
   inline void set(const C<T> & vm);
 #endif
 
   /// Append the content of the other array to the current one
   void append(const Array<T> & other);
 
   /// copy another Array in the current Array, the no_sanity_check allows you to
   /// force the copy in cases where you know what you do with two non matching
   /// Arrays in terms of n
   void copy(const Array<T, is_scal> & other, bool no_sanity_check = false);
 
-  /// give the address of the memory allocated for this vector
-  T * storage() const { return values; };
-
   /// function to print the containt of the class
   void printself(std::ostream & stream, int indent = 0) const override;
 
-protected:
-  /// perform the allocation for the constructors
-  void allocate(UInt size, UInt nb_component = 1);
-
-  /// resize initializing with uninitialized_fill if fill is set
-  void resizeUnitialized(UInt new_size, bool fill, const T & val = T());
-
   /* ------------------------------------------------------------------------ */
   /* Operators                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// substraction entry-wise
   Array<T, is_scal> & operator-=(const Array<T, is_scal> & other);
   /// addition entry-wise
   Array<T, is_scal> & operator+=(const Array<T, is_scal> & other);
   /// multiply evry entry by alpha
   Array<T, is_scal> & operator*=(const T & alpha);
 
   /// check if the array are identical entry-wise
   bool operator==(const Array<T, is_scal> & other) const;
   /// @see Array::operator==(const Array<T, is_scal> & other) const
   bool operator!=(const Array<T, is_scal> & other) const;
 
   /// return a reference to the j-th entry of the i-th tuple
   inline reference operator()(UInt i, UInt j = 0);
   /// return a const reference to the j-th entry of the i-th tuple
   inline const_reference operator()(UInt i, UInt j = 0) const;
 
   /// return a reference to the ith component of the 1D array
   inline reference operator[](UInt i);
   /// return a const reference to the ith component of the 1D array
   inline const_reference operator[](UInt i) const;
-
-  /* ------------------------------------------------------------------------ */
-  /* Class Members                                                            */
-  /* ------------------------------------------------------------------------ */
-protected:
-  /// array of values
-  T * values; // /!\ very dangerous
 };
 
 /* -------------------------------------------------------------------------- */
 /* Inline Functions Array<T, is_scal>                                         */
 /* -------------------------------------------------------------------------- */
 template <typename T, bool is_scal>
 inline std::ostream & operator<<(std::ostream & stream,
                                  const Array<T, is_scal> & _this) {
   _this.printself(stream);
   return stream;
 }
 
 /* -------------------------------------------------------------------------- */
 /* Inline Functions ArrayBase                                                 */
 /* -------------------------------------------------------------------------- */
 inline std::ostream & operator<<(std::ostream & stream,
                                  const ArrayBase & _this) {
   _this.printself(stream);
   return stream;
 }
 
 } // namespace akantu
 
 #include "aka_array_tmpl.hh"
 #include "aka_types.hh"
 
 #endif /* __AKANTU_VECTOR_HH__ */
diff --git a/src/common/aka_array_tmpl.hh b/src/common/aka_array_tmpl.hh
index 44dc7e3e3..d57fdd2f7 100644
--- a/src/common/aka_array_tmpl.hh
+++ b/src/common/aka_array_tmpl.hh
@@ -1,1307 +1,1359 @@
 /**
  * @file   aka_array_tmpl.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Thu Jul 15 2010
  * @date last modification: Tue Feb 20 2018
  *
  * @brief  Inline functions of the classes Array<T> and ArrayBase
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 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 Array<T>                                                 */
+/* Inline Functions Array<T>                                                  */
 /* -------------------------------------------------------------------------- */
 #include "aka_array.hh"
 /* -------------------------------------------------------------------------- */
 #include <memory>
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_AKA_ARRAY_TMPL_HH__
 #define __AKANTU_AKA_ARRAY_TMPL_HH__
 
 namespace akantu {
 
 namespace debug {
   struct ArrayException : public Exception {};
 } // namespace debug
 
 /* -------------------------------------------------------------------------- */
-template <class T, bool is_scal>
-inline T & Array<T, is_scal>::operator()(UInt i, UInt j) {
-  AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty");
-  AKANTU_DEBUG_ASSERT((i < size_) && (j < nb_component),
-                      "The value at position ["
-                          << i << "," << j << "] is out of range in array \""
-                          << id << "\"");
-  return values[i * nb_component + j];
+/* -------------------------------------------------------------------------- */
+template <typename T, ArrayAllocationType allocation_trait>
+ArrayDataLayer<T, allocation_trait>::ArrayDataLayer(UInt size,
+                                                    UInt nb_component,
+                                                    const ID & id)
+    : ArrayBase(id) {
+  allocate(size, nb_component);
 }
 
 /* -------------------------------------------------------------------------- */
-template <class T, bool is_scal>
-inline const T & Array<T, is_scal>::operator()(UInt i, UInt j) const {
-  AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty");
-  AKANTU_DEBUG_ASSERT((i < size_) && (j < nb_component),
-                      "The value at position ["
-                          << i << "," << j << "] is out of range in array \""
-                          << id << "\"");
-  return values[i * nb_component + j];
+template <typename T, ArrayAllocationType allocation_trait>
+ArrayDataLayer<T, allocation_trait>::ArrayDataLayer(UInt size,
+                                                    UInt nb_component,
+                                                    const_reference value,
+                                                    const ID & id)
+    : ArrayBase(id) {
+  allocate(size, nb_component, value);
 }
 
-template <class T, bool is_scal>
-inline T & Array<T, is_scal>::operator[](UInt i) {
-  AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty");
-  AKANTU_DEBUG_ASSERT((i < size_ * nb_component),
-                      "The value at position ["
-                          << i << "] is out of range in array \"" << id
-                          << "\"");
-  return values[i];
+/* -------------------------------------------------------------------------- */
+template <typename T, ArrayAllocationType allocation_trait>
+ArrayDataLayer<T, allocation_trait>::ArrayDataLayer(const ArrayDataLayer & vect,
+                                                    const ID & id)
+    : ArrayBase(vect, id) {
+  this->data_storage = vect.data_storage;
+  this->size_ = vect.size_;
+  this->nb_component = vect.nb_component;
+  this->values = this->data_storage.data();
 }
 
+#ifndef SWIG
 /* -------------------------------------------------------------------------- */
-template <class T, bool is_scal>
-inline const T & Array<T, is_scal>::operator[](UInt i) const {
-  AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty");
-  AKANTU_DEBUG_ASSERT((i < size_ * nb_component),
-                      "The value at position ["
-                          << i << "] is out of range in array \"" << id
-                          << "\"");
-  return values[i];
+template <typename T, ArrayAllocationType allocation_trait>
+ArrayDataLayer<T, allocation_trait>::ArrayDataLayer(
+    const std::vector<value_type> & vect) {
+  this->data_storage = vect;
+  this->size_ = vect.size();
+  this->nb_component = 1;
+  this->values = this->data_storage.data();
+}
+#endif
+
+/* -------------------------------------------------------------------------- */
+template <typename T, ArrayAllocationType allocation_trait>
+ArrayDataLayer<T, allocation_trait> & ArrayDataLayer<T, allocation_trait>::
+operator=(const ArrayDataLayer & other) {
+  if (this != &other) {
+    this->data_storage = other.data_storage;
+    this->nb_component = other.nb_component;
+    this->size_ = other.size_;
+    this->values = this->data_storage.data();
+  }
+  return *this;
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T, ArrayAllocationType allocation_trait>
+ArrayDataLayer<T, allocation_trait>::ArrayDataLayer(ArrayDataLayer && other) =
+    default;
+
+/* -------------------------------------------------------------------------- */
+template <typename T, ArrayAllocationType allocation_trait>
+ArrayDataLayer<T, allocation_trait> & ArrayDataLayer<T, allocation_trait>::
+operator=(ArrayDataLayer && other) = default;
+
+/* -------------------------------------------------------------------------- */
+template <typename T, ArrayAllocationType allocation_trait>
+void ArrayDataLayer<T, allocation_trait>::allocate(UInt new_size,
+                                                   UInt nb_component) {
+  this->nb_component = nb_component;
+  this->resize(new_size);
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T, ArrayAllocationType allocation_trait>
+void ArrayDataLayer<T, allocation_trait>::allocate(UInt new_size,
+                                                   UInt nb_component,
+                                                   const T & val) {
+  this->nb_component = nb_component;
+  this->resize(new_size, val);
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T, ArrayAllocationType allocation_trait>
+void ArrayDataLayer<T, allocation_trait>::resize(UInt new_size) {
+  this->data_storage.resize(new_size * this->nb_component);
+  this->values = this->data_storage.data();
+  this->size_ = new_size;
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T, ArrayAllocationType allocation_trait>
+void ArrayDataLayer<T, allocation_trait>::resize(UInt new_size,
+                                                 const T & value) {
+  this->data_storage.resize(new_size * this->nb_component, value);
+  this->values = this->data_storage.data();
+  this->size_ = new_size;
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T, ArrayAllocationType allocation_trait>
+void ArrayDataLayer<T, allocation_trait>::reserve(UInt size) {
+  this->data_storage.reserve(size * this->nb_component);
+  this->values = this->data_storage.data();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * append a tuple to the array with the value value for all components
  * @param value the new last tuple or the array will contain nb_component copies
  * of value
  */
-template <class T, bool is_scal>
-inline void Array<T, is_scal>::push_back(const T & value) {
-  resizeUnitialized(size_ + 1, true, value);
+template <typename T, ArrayAllocationType allocation_trait>
+inline void ArrayDataLayer<T, allocation_trait>::push_back(const T & value) {
+  this->data_storage.push_back(value);
+  this->values = this->data_storage.data();
+  this->size_ += 1;
 }
 
-/* -------------------------------------------------------------------------- */
-/**
- * append a tuple to the array
- * @param new_elem a C-array containing the values to be copied to the end of
- * the array */
-// template <class T, bool is_scal>
-// inline void Array<T, is_scal>::push_back(const T new_elem[]) {
-//   UInt pos = size_;
-
-//   resizeUnitialized(size_ + 1, false);
-
-//   T * tmp = values + nb_component * pos;
-//   std::uninitialized_copy(new_elem, new_elem + nb_component, tmp);
-// }
-
 /* -------------------------------------------------------------------------- */
 #ifndef SWIG
 /**
  * append a matrix or a vector to the array
  * @param new_elem a reference to a Matrix<T> or Vector<T> */
-template <class T, bool is_scal>
+template <typename T, ArrayAllocationType allocation_trait>
 template <template <typename> class C, typename>
-inline void Array<T, is_scal>::push_back(const C<T> & new_elem) {
+inline void
+ArrayDataLayer<T, allocation_trait>::push_back(const C<T> & new_elem) {
   AKANTU_DEBUG_ASSERT(
       nb_component == new_elem.size(),
       "The vector("
           << new_elem.size()
           << ") as not a size compatible with the Array (nb_component="
           << nb_component << ").");
-  UInt pos = size_;
-  resizeUnitialized(size_ + 1, false);
+  for (UInt i = 0; i < new_elem.size(); ++i) {
+    this->data_storage.push_back(new_elem[i]);
+  }
+  this->values = this->data_storage.data();
+  this->size_ += 1;
+}
+#endif
 
-  T * tmp = values + nb_component * pos;
-  std::uninitialized_copy(new_elem.storage(), new_elem.storage() + nb_component,
-                          tmp);
+/* -------------------------------------------------------------------------- */
+template <typename T, ArrayAllocationType allocation_trait>
+inline UInt ArrayDataLayer<T, allocation_trait>::getAllocatedSize() const {
+  return this->data_storage.capacity() / this->nb_component;
 }
 
 /* -------------------------------------------------------------------------- */
-/**
- * append a tuple to the array
- * @param it an iterator to the tuple to be copied to the end of the array */
+template <typename T, ArrayAllocationType allocation_trait>
+inline UInt ArrayDataLayer<T, allocation_trait>::getMemorySize() const {
+  return this->data_storage.capacity() * sizeof(T);
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+template <typename T>
+class ArrayDataLayer<T, ArrayAllocationType::_pod> : public ArrayBase {
+public:
+  using value_type = T;
+  using reference = value_type &;
+  using pointer_type = value_type *;
+  using const_reference = const value_type &;
+
+public:
+  virtual ~ArrayDataLayer() { free(values); }
+
+  /// Allocation of a new vector
+  ArrayDataLayer(UInt size = 0, UInt nb_component = 1, const ID & id = "")
+      : ArrayBase(id) {
+    allocate(size, nb_component);
+  }
+
+  /// Allocation of a new vector with a default value
+  ArrayDataLayer(UInt size, UInt nb_component, const_reference value,
+                 const ID & id = "")
+      : ArrayBase(id) {
+    allocate(size, nb_component, value);
+  }
+
+  /// Copy constructor (deep copy)
+  ArrayDataLayer(const ArrayDataLayer & vect, const ID & id = "")
+      : ArrayBase(vect, id) {
+    allocate(vect.size(), vect.getNbComponent());
+    std::copy_n(vect.storage(), this->size_ * this->nb_component, values);
+  }
+
+#ifndef SWIG
+  /// Copy constructor (deep copy)
+  explicit ArrayDataLayer(const std::vector<value_type> & vect) {
+    allocate(vect.size(), 1);
+    std::copy_n(vect.data(), this->size_ * this->nb_component, values);
+  }
+#endif
+
+  // copy operator
+  inline ArrayDataLayer & operator=(const ArrayDataLayer & other) {
+    if (this != &other) {
+      allocate(other.size(), other.getNbComponent());
+      std::copy_n(other.storage(), this->size_ * this->nb_component, values);
+    }
+    return *this;
+  }
+
+  // move constructor
+  inline ArrayDataLayer(ArrayDataLayer && other) = default;
+
+  // move assign
+  inline ArrayDataLayer & operator=(ArrayDataLayer && other) = default;
+
+protected:
+  // allocate the memory
+  inline void allocate(UInt size, UInt nb_component) {
+    this->values =
+        reinterpret_cast<T *>(malloc(nb_component * size * sizeof(T)));
+    if (this->values == nullptr and size != 0) {
+      throw std::bad_alloc();
+    }
+    this->nb_component = nb_component;
+    this->allocated_size = this->size_ = size;
+  }
+
+  // allocate and initialize the memory
+  inline void allocate(UInt size, UInt nb_component, const T & value) {
+    allocate(size, nb_component);
+    std::fill_n(values, size * nb_component, value);
+  }
+
+public:
+  /// append a tuple of size nb_component containing value
+  inline void push_back(const_reference value) {
+    resize(this->size_ + 1, value);
+  }
+
+#ifndef SWIG
+  /// append a Vector or a Matrix
+  template <template <typename> class C,
+            typename = std::enable_if_t<is_tensor<C<T>>::value>>
+  inline void push_back(const C<T> & new_elem) {
+    AKANTU_DEBUG_ASSERT(
+        nb_component == new_elem.size(),
+        "The vector("
+            << new_elem.size()
+            << ") as not a size compatible with the Array (nb_component="
+            << nb_component << ").");
+    this->resize(this->size_ + 1);
+    std::copy_n(new_elem.storage(), new_elem.size(),
+                values + this->nb_component * (this->size_ - 1));
+  }
+#endif
+
+  /// changes the allocated size but not the size
+  void reserve(UInt size) {
+    UInt tmp_size = this->size_;
+    this->resize(size);
+    this->size_ = tmp_size;
+  }
+
+  /// change the size of the Array
+  void resize(UInt size) {
+    if (size == 0) {
+      free(values);
+      values = nullptr;
+      this->allocated_size = 0;
+    } else {
+      Int diff = size - allocated_size;
+      UInt size_to_allocate = (std::abs(diff) > AKANTU_MIN_ALLOCATION)
+                                  ? size
+                                  : (diff > 0)
+                                        ? allocated_size + AKANTU_MIN_ALLOCATION
+                                        : allocated_size;
+
+      auto * tmp_ptr = reinterpret_cast<T *>(realloc(
+          this->values, size_to_allocate * this->nb_component * sizeof(T)));
+      if (tmp_ptr == nullptr) {
+        throw std::bad_alloc();
+      }
+
+      this->values = tmp_ptr;
+      this->allocated_size = size_to_allocate;
+    }
+
+    this->size_ = size;
+  }
+
+  /// change the size of the Array and initialize the values
+  void resize(UInt size, const T & val) {
+    UInt tmp_size = this->size_;
+    this->resize(size);
+    if (size > tmp_size) {
+      std::fill_n(values + this->nb_component * tmp_size, (size - tmp_size),
+                  val);
+    }
+  }
+
+  /// get the amount of space allocated in bytes
+  inline UInt getMemorySize() const override final {
+    return this->allocated_size * this->nb_component * sizeof(T);
+  }
+
+  /// Get the real size allocated in memory
+  inline UInt getAllocatedSize() const { return this->allocated_size; }
+
+  /// give the address of the memory allocated for this vector
+  T * storage() const { return values; };
+
+protected:
+  /// allocation type agnostic  data access
+  T * values{nullptr};
+
+  UInt allocated_size{0};
+};
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+/* template <class T> class AllocatorMalloc : public Allocator<T> {
+public:
+  T * allocate(UInt size, UInt nb_component) override final {
+    auto * ptr = reinterpret_cast<T *>(malloc(nb_component * size * sizeof(T)));
+
+    if (ptr == nullptr and size != 0) {
+      throw std::bad_alloc();
+    }
+    return ptr;
+  }
+
+  void deallocate(T * ptr, UInt size, UInt ,
+                  UInt nb_component) override final {
+    if (ptr) {
+      if (not is_scalar<T>::value) {
+        for (UInt i = 0; i < size * nb_component; ++i) {
+          (ptr + i)->~T();
+        }
+      }
+      free(ptr);
+    }
+  }
+
+  std::tuple<T *, UInt> resize(UInt new_size, UInt size, UInt allocated_size,
+                               UInt nb_component, T * ptr) override final {
+    UInt size_to_alloc = 0;
+
+    if (not is_scalar<T>::value and (new_size < size)) {
+      for (UInt i = new_size * nb_component; i < size * nb_component; ++i) {
+        (ptr + i)->~T();
+      }
+    }
+
+    // free some memory
+    if (new_size == 0) {
+      free(ptr);
+      return std::make_tuple(nullptr, 0);
+    }
+
+    if (new_size <= allocated_size) {
+      if (allocated_size - new_size > AKANTU_MIN_ALLOCATION) {
+        size_to_alloc = new_size;
+      } else {
+        return std::make_tuple(ptr, allocated_size);
+      }
+    } else {
+      // allocate more memory
+      size_to_alloc = (new_size - allocated_size < AKANTU_MIN_ALLOCATION)
+                          ? allocated_size + AKANTU_MIN_ALLOCATION
+                          : new_size;
+    }
+
+    auto * tmp_ptr = reinterpret_cast<T *>(
+        realloc(ptr, size_to_alloc * nb_component * sizeof(T)));
+    if (tmp_ptr == nullptr) {
+      throw std::bad_alloc();
+    }
+
+    return std::make_tuple(tmp_ptr, size_to_alloc);
+  }
+};
+*/
+
+/* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
-template <class Ret>
-inline void
-Array<T, is_scal>::push_back(const Array<T, is_scal>::iterator<Ret> & it) {
-  UInt pos = size_;
+inline auto Array<T, is_scal>::operator()(UInt i, UInt j) -> reference {
+  AKANTU_DEBUG_ASSERT(this->size_ > 0,
+                      "The array \"" << this->id << "\" is empty");
+  AKANTU_DEBUG_ASSERT((i < this->size_) && (j < this->nb_component),
+                      "The value at position ["
+                          << i << "," << j << "] is out of range in array \""
+                          << this->id << "\"");
+  return this->values[i * this->nb_component + j];
+}
 
-  resizeUnitialized(size_ + 1, false);
+/* -------------------------------------------------------------------------- */
+template <class T, bool is_scal>
+inline auto Array<T, is_scal>::operator()(UInt i, UInt j) const
+    -> const_reference {
+  AKANTU_DEBUG_ASSERT(this->size_ > 0,
+                      "The array \"" << this->id << "\" is empty");
+  AKANTU_DEBUG_ASSERT((i < this->size_) && (j < this->nb_component),
+                      "The value at position ["
+                          << i << "," << j << "] is out of range in array \""
+                          << this->id << "\"");
+  return this->values[i * this->nb_component + j];
+}
 
-  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 auto Array<T, is_scal>::operator[](UInt i) -> reference {
+  AKANTU_DEBUG_ASSERT(this->size_ > 0,
+                      "The array \"" << this->id << "\" is empty");
+  AKANTU_DEBUG_ASSERT((i < this->size_ * this->nb_component),
+                      "The value at position ["
+                          << i << "] is out of range in array \"" << this->id
+                          << "\"");
+  return this->values[i];
 }
-#endif
+
+/* -------------------------------------------------------------------------- */
+template <class T, bool is_scal>
+inline auto Array<T, is_scal>::operator[](UInt i) const -> const_reference {
+  AKANTU_DEBUG_ASSERT(this->size_ > 0,
+                      "The array \"" << this->id << "\" is empty");
+  AKANTU_DEBUG_ASSERT((i < this->size_ * this->nb_component),
+                      "The value at position ["
+                          << i << "] is out of range in array \"" << this->id
+                          << "\"");
+  return this->values[i];
+}
+
 /* -------------------------------------------------------------------------- */
 /**
  * erase an element. If the erased element is not the last of the array, the
  * last element is moved into the hole in order to maintain contiguity. This
  * may invalidate existing iterators (For instance an iterator obtained by
  * Array::end() is no longer correct) and will change the order of the
  * elements.
  * @param i index of element to erase
  */
 template <class T, bool is_scal> inline void Array<T, is_scal>::erase(UInt i) {
   AKANTU_DEBUG_IN();
-  AKANTU_DEBUG_ASSERT((size_ > 0), "The array is empty");
-  AKANTU_DEBUG_ASSERT((i < size_),
-                      "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];
+  AKANTU_DEBUG_ASSERT((this->size_ > 0), "The array is empty");
+  AKANTU_DEBUG_ASSERT((i < this->size_), "The element at position ["
+                                             << i << "] is out of range (" << i
+                                             << ">=" << this->size_ << ")");
+
+  if (i != (this->size_ - 1)) {
+    for (UInt j = 0; j < this->nb_component; ++j) {
+      this->values[i * this->nb_component + j] =
+          this->values[(this->size_ - 1) * this->nb_component + j];
     }
   }
 
-  resize(size_ - 1);
+  this->resize(this->size_ - 1);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Subtract another array entry by entry from this array in place. Both arrays
  * must
  * have the same size and nb_component. If the arrays have different shapes,
  * code compiled in debug mode will throw an expeption and optimised code
  * will behave in an unpredicted manner
  * @param other array to subtract from this
  * @return reference to modified this
  */
 template <class T, bool is_scal>
 Array<T, is_scal> & Array<T, is_scal>::
 operator-=(const Array<T, is_scal> & vect) {
-  AKANTU_DEBUG_ASSERT((size_ == vect.size_) &&
-                          (nb_component == vect.nb_component),
+  AKANTU_DEBUG_ASSERT((this->size_ == vect.size_) &&
+                          (this->nb_component == vect.nb_component),
                       "The too array don't have the same sizes");
 
-  T * a = values;
+  T * a = this->values;
   T * b = vect.storage();
-  for (UInt i = 0; i < size_ * nb_component; ++i) {
+  for (UInt i = 0; i < this->size_ * this->nb_component; ++i) {
     *a -= *b;
     ++a;
     ++b;
   }
 
   return *this;
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Add another array entry by entry to this array in place. Both arrays must
  * have the same size and nb_component. If the arrays have different shapes,
  * code compiled in debug mode will throw an expeption and optimised code
  * will behave in an unpredicted manner
  * @param other array to add to this
  * @return reference to modified this
  */
 template <class T, bool is_scal>
 Array<T, is_scal> & Array<T, is_scal>::
 operator+=(const Array<T, is_scal> & vect) {
-  AKANTU_DEBUG_ASSERT((size_ == vect.size()) &&
-                          (nb_component == vect.nb_component),
+  AKANTU_DEBUG_ASSERT((this->size_ == vect.size()) &&
+                          (this->nb_component == vect.nb_component),
                       "The too array don't have the same sizes");
 
-  T * a = values;
+  T * a = this->values;
   T * b = vect.storage();
-  for (UInt i = 0; i < size_ * nb_component; ++i) {
+  for (UInt i = 0; i < this->size_ * this->nb_component; ++i) {
     *a++ += *b++;
   }
 
   return *this;
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Multiply all entries of this array by a scalar in place
  * @param alpha scalar multiplicant
  * @return reference to modified this
  */
 
 #ifndef SWIG
 template <class T, bool is_scal>
 Array<T, is_scal> & Array<T, is_scal>::operator*=(const T & alpha) {
-  T * a = values;
-  for (UInt i = 0; i < size_ * nb_component; ++i) {
+  T * a = this->values;
+  for (UInt i = 0; i < this->size_ * this->nb_component; ++i) {
     *a++ *= alpha;
   }
 
   return *this;
 }
 #endif
 
 /* -------------------------------------------------------------------------- */
 /**
  * Compare this array element by element to another.
  * @param other array to compare to
  * @return true it all element are equal and arrays have the same shape, else
  * false
  */
 template <class T, bool is_scal>
 bool Array<T, is_scal>::operator==(const Array<T, is_scal> & array) const {
-  bool equal = nb_component == array.nb_component && size_ == array.size_ &&
-               id == array.id;
+  bool equal = this->nb_component == array.nb_component &&
+               this->size_ == array.size_ && this->id == array.id;
   if (!equal)
     return false;
 
-  if (values == array.storage())
+  if (this->values == array.storage())
     return true;
   else
-    return std::equal(values, values + size_ * nb_component, array.storage());
+    return std::equal(this->values,
+                      this->values + this->size_ * this->nb_component,
+                      array.storage());
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 bool Array<T, is_scal>::operator!=(const Array<T, is_scal> & array) const {
   return !operator==(array);
 }
 
 /* -------------------------------------------------------------------------- */
 #ifndef SWIG
 /**
  * set all tuples of the array to a given vector or matrix
  * @param vm Matrix or Vector to fill the array with
  */
 template <class T, bool is_scal>
 template <template <typename> class C, typename>
 inline void Array<T, is_scal>::set(const C<T> & vm) {
   AKANTU_DEBUG_ASSERT(
-      nb_component == vm.size(),
+      this->nb_component == vm.size(),
       "The size of the object does not match the number of components");
-  for (T * it = values; it < values + nb_component * size_;
-       it += nb_component) {
-    std::copy(vm.storage(), vm.storage() + nb_component, it);
+  for (T * it = this->values;
+       it < this->values + this->nb_component * this->size_;
+       it += this->nb_component) {
+    std::copy_n(vm.storage(), this->nb_component, it);
   }
 }
 #endif
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 void Array<T, is_scal>::append(const Array<T> & other) {
   AKANTU_DEBUG_ASSERT(
-      nb_component == other.nb_component,
+      this->nb_component == other.nb_component,
       "Cannot append an array with a different number of component");
   UInt old_size = this->size_;
-  this->resizeUnitialized(this->size_ + other.size(), false);
+  this->resize(this->size_ + other.size());
 
-  T * tmp = values + nb_component * old_size;
-  std::uninitialized_copy(other.storage(),
-                          other.storage() + other.size() * nb_component, tmp);
+  T * tmp = this->values + this->nb_component * old_size;
+  std::copy_n(other.storage(), other.size() * this->nb_component, tmp);
 }
 
 /* -------------------------------------------------------------------------- */
 /* Functions Array<T, is_scal>                                                */
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Array<T, is_scal>::Array(UInt size, UInt nb_component, const ID & id)
-    : ArrayBase(id), values(nullptr) {
-  AKANTU_DEBUG_IN();
-  allocate(size, nb_component);
-
-  if (!is_scal) {
-    T val = T();
-    std::uninitialized_fill(values, values + size * nb_component, val);
-  }
+    : parent(size, nb_component, id) {}
 
-  AKANTU_DEBUG_OUT();
-}
+template <>
+inline Array<std::string, false>::Array(UInt size, UInt nb_component,
+                                        const ID & id)
+    : parent(size, nb_component, "", id) {}
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
-Array<T, is_scal>::Array(UInt size, UInt nb_component, const T def_values[],
+Array<T, is_scal>::Array(UInt size, UInt nb_component, const_reference value,
                          const ID & id)
-    : ArrayBase(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);
-  }
-  AKANTU_DEBUG_OUT();
-}
+    : parent(size, nb_component, value, id) {}
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
-Array<T, is_scal>::Array(UInt size, UInt nb_component, const T & value,
-                         const ID & id)
-    : ArrayBase(id), values(nullptr) {
-  AKANTU_DEBUG_IN();
-  allocate(size, nb_component);
-
-  std::uninitialized_fill_n(values, size * nb_component, value);
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <class T, bool is_scal>
-Array<T, is_scal>::Array(const Array<T, is_scal> & vect, const ID & id)
-    : ArrayBase(vect) {
-  AKANTU_DEBUG_IN();
-  this->id = (id == "") ? vect.id : id;
-
-  // if (deep) {
-  allocate(vect.size_, vect.nb_component);
-  std::uninitialized_copy(vect.storage(), vect.storage() + size_ * nb_component,
-                          values);
-  // } else {
-  //   this->values = vect.storage();
-  //   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();
-}
+Array<T, is_scal>::Array(const Array & vect, const ID & id)
+    : parent(vect, id) {}
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Array<T, is_scal> & Array<T, is_scal>::
 operator=(const Array<T, is_scal> & other) {
   AKANTU_DEBUG_WARNING("You are copying the array "
-                       << id << " are you sure it is on purpose");
+                       << this->id << " are you sure it is on purpose");
 
   if (&other == this)
     return *this;
 
-  allocate(other.size_, other.nb_component);
-  std::uninitialized_copy(other.storage(),
-                          other.storage() + size_ * nb_component, values);
-
-  return *this;
-}
-
-/* -------------------------------------------------------------------------- */
-template <class T, bool is_scal>
-Array<T, is_scal>::Array(Array<T, is_scal> && other)
-    : ArrayBase(other), values(std::exchange(other.values, nullptr)) {}
-
-/* -------------------------------------------------------------------------- */
-template <class T, bool is_scal>
-Array<T, is_scal> & Array<T, is_scal>::operator=(Array && other) {
-  if (&other == this)
-    return *this;
-
-  ArrayBase::operator=(other);
-  values = std::exchange(other.values, nullptr);
+  parent::operator=(other);
 
   return *this;
 }
 
 /* -------------------------------------------------------------------------- */
 #ifndef SWIG
 template <class T, bool is_scal>
-Array<T, is_scal>::Array(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();
-}
+Array<T, is_scal>::Array(const std::vector<T> & vect) : parent(vect) {}
 #endif
 
 /* -------------------------------------------------------------------------- */
-template <class T, bool is_scal> Array<T, is_scal>::~Array() {
-  AKANTU_DEBUG_IN();
-  AKANTU_DEBUG(dblAccessory,
-               "Freeing " << printMemorySize<T>(allocated_size * nb_component)
-                          << " (" << id << ")");
-
-  if (values) {
-    if (not 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 Array<T, is_scal>::reserve(UInt new_size) {
-  UInt tmp_size = this->size_;
-  resizeUnitialized(new_size, false);
-  this->size_ = tmp_size;
-}
-
-/* -------------------------------------------------------------------------- */
-/**
- * change the size of the array and allocate or free memory if needed. If the
- * size increases, the new tuples are filled with zeros
- * @param new_size new number of tuples contained in the array */
-template <class T, bool is_scal> void Array<T, is_scal>::resize(UInt new_size) {
-  resizeUnitialized(new_size, !is_scal);
-}
-
-/* -------------------------------------------------------------------------- */
-/**
- * change the size of the array and allocate or free memory if needed. If the
- * size increases, the new tuples are filled with zeros
- * @param new_size new number of tuples contained in the array */
-template <class T, bool is_scal>
-void Array<T, is_scal>::resize(UInt new_size, const T & val) {
-  this->resizeUnitialized(new_size, true, val);
-}
-
-/* -------------------------------------------------------------------------- */
-/**
- * perform the allocation for the constructors
- * @param size is the size of the array
- * @param nb_component is the number of component of the array
- */
-template <class T, bool is_scal>
-void Array<T, is_scal>::allocate(UInt size, UInt nb_component) {
-  AKANTU_DEBUG_IN();
-
-  values = static_cast<T *>(malloc(nb_component * size * sizeof(T)));
-
-  if (values == nullptr and size != 0) {
-    this->size_ = this->allocated_size = 0;
-    AKANTU_EXCEPTION("Cannot allocate "
-                     << printMemorySize<T>(size * nb_component) << " (" << id
-                     << ")");
-  } else {
-    AKANTU_DEBUG(dblAccessory,
-                 "Allocated " << printMemorySize<T>(size * nb_component) << " ("
-                              << id << ")");
-  }
-
-  this->size_ = this->allocated_size = size;
-  this->size_of_type = sizeof(T);
-  this->nb_component = nb_component;
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-/**
- * change the size of the array and allocate or free memory if needed.
- * @param new_size new number of tuples contained in the array */
-template <class T, bool is_scal>
-void Array<T, is_scal>::resizeUnitialized(UInt new_size, bool fill,
-                                          const T & val) {
-  //  AKANTU_DEBUG_IN();
-  // free some memory
-  if (new_size <= allocated_size) {
-    if (!is_scal) {
-      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();
-        }
-      }
-    }
-
-    if (allocated_size - new_size > AKANTU_MIN_ALLOCATION) {
-      AKANTU_DEBUG(dblAccessory,
-                   "Freeing " << printMemorySize<T>((allocated_size - size_) *
-                                                    nb_component)
-                              << " (" << id << ")");
-
-      // Normally there are no allocation problem when reducing an array
-      if (new_size == 0) {
-        free(values);
-        values = nullptr;
-      } else {
-        auto * tmp_ptr = static_cast<T *>(
-            realloc(values, new_size * nb_component * sizeof(T)));
-
-        if (tmp_ptr == nullptr) {
-          AKANTU_EXCEPTION("Cannot free data ("
-                           << id << ")"
-                           << " [current allocated size : " << allocated_size
-                           << " | "
-                           << "requested size : " << new_size << "]");
-        }
-        values = tmp_ptr;
-      }
-      allocated_size = new_size;
-    }
-  } else {
-    // allocate more memory
-    UInt size_to_alloc = (new_size - allocated_size < AKANTU_MIN_ALLOCATION)
-                             ? allocated_size + AKANTU_MIN_ALLOCATION
-                             : new_size;
-
-    auto * tmp_ptr = static_cast<T *>(
-        realloc(values, size_to_alloc * nb_component * sizeof(T)));
-    AKANTU_DEBUG_ASSERT(
-        tmp_ptr != nullptr,
-        "Cannot allocate " << printMemorySize<T>(size_to_alloc * nb_component));
-    if (tmp_ptr == nullptr) {
-      AKANTU_ERROR("Cannot allocate more data ("
-                   << id << ")"
-                   << " [current allocated size : " << allocated_size << " | "
-                   << "requested size : " << new_size << "]");
-    }
-
-    AKANTU_DEBUG(dblAccessory,
-                 "Allocating " << printMemorySize<T>(
-                     (size_to_alloc - allocated_size) * nb_component));
-
-    allocated_size = size_to_alloc;
-    values = tmp_ptr;
-  }
-
-  if (fill && this->size_ < new_size) {
-    std::uninitialized_fill(values + size_ * nb_component,
-                            values + new_size * nb_component, val);
-  }
-
-  size_ = new_size;
-  //  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-/**
- * change the number of components by interlacing data
- * @param multiplicator number of interlaced components add
- * @param block_size blocks of data in the array
- * Examaple for block_size = 2, multiplicator = 2
- * array = oo oo oo -> new array = oo nn nn oo nn nn oo nn nn */
-template <class T, bool is_scal>
-void Array<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> Array<T, is_scal>::~Array() = default;
 
 /* -------------------------------------------------------------------------- */
 /**
  * search elem in the array, return  the position of the first occurrence or
  * -1 if not found
  *  @param elem the element to look for
  *  @return index of the first occurrence of elem or -1 if elem is not present
  */
 template <class T, bool is_scal>
-UInt Array<T, is_scal>::find(const T & elem) const {
+UInt Array<T, is_scal>::find(const_reference elem) const {
   AKANTU_DEBUG_IN();
 
   auto begin = this->begin();
   auto end = this->end();
   auto it = std::find(begin, end, elem);
 
   AKANTU_DEBUG_OUT();
   return (it != end) ? it - begin : UInt(-1);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal> UInt Array<T, is_scal>::find(T elem[]) const {
   AKANTU_DEBUG_IN();
-  T * it = values;
+  T * it = this->values;
   UInt i = 0;
-  for (; i < size_; ++i) {
+  for (; i < this->size_; ++i) {
     if (*it == elem[0]) {
       T * cit = it;
       UInt c = 0;
-      for (; (c < nb_component) && (*cit == elem[c]); ++c, ++cit)
+      for (; (c < this->nb_component) && (*cit == elem[c]); ++c, ++cit)
         ;
-      if (c == nb_component) {
+      if (c == this->nb_component) {
         AKANTU_DEBUG_OUT();
         return i;
       }
     }
-    it += nb_component;
+    it += this->nb_component;
   }
   return UInt(-1);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 template <template <typename> class C, typename>
 inline UInt Array<T, is_scal>::find(const C<T> & elem) {
-  AKANTU_DEBUG_ASSERT(elem.size() == nb_component,
+  AKANTU_DEBUG_ASSERT(elem.size() == this->nb_component,
                       "Cannot find an element with a wrong size ("
-                          << elem.size() << ") != " << nb_component);
+                          << elem.size() << ") != " << this->nb_component);
   return this->find(elem.storage());
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * copy the content of another array. This overwrites the current content.
  * @param other Array to copy into this array. It has to have the same
  * nb_component as this. If compiled in debug mode, an incorrect other will
  * result in an exception being thrown. Optimised code may result in
  * unpredicted behaviour.
  */
 template <class T, bool is_scal>
 void Array<T, is_scal>::copy(const Array<T, is_scal> & vect,
                              bool no_sanity_check) {
   AKANTU_DEBUG_IN();
 
   if (!no_sanity_check)
-    if (vect.nb_component != nb_component)
+    if (vect.nb_component != this->nb_component)
       AKANTU_ERROR("The two arrays do not have the same number of components");
 
-  resize((vect.size_ * vect.nb_component) / nb_component);
+  this->resize((vect.size_ * vect.nb_component) / this->nb_component);
 
-  T * tmp = values;
-  std::uninitialized_copy(vect.storage(), vect.storage() + size_ * nb_component,
-                          tmp);
+  std::copy_n(vect.storage(), this->size_ * this->nb_component, this->values);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <bool is_scal> class ArrayPrintHelper {
 public:
   template <typename T>
   static void print_content(const Array<T> & vect, std::ostream & stream,
                             int indent) {
     if (AKANTU_DEBUG_TEST(dblDump) || AKANTU_DEBUG_LEVEL_IS_TEST()) {
       std::string space;
       for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
         ;
 
       stream << space << " + values         : {";
       for (UInt i = 0; i < vect.size(); ++i) {
         stream << "{";
         for (UInt j = 0; j < vect.getNbComponent(); ++j) {
           stream << vect(i, j);
           if (j != vect.getNbComponent() - 1)
             stream << ", ";
         }
         stream << "}";
         if (i != vect.size() - 1)
           stream << ", ";
       }
       stream << "}" << std::endl;
     }
   }
 };
 
 template <> class ArrayPrintHelper<false> {
 public:
   template <typename T>
   static void print_content(__attribute__((unused)) const Array<T> & vect,
                             __attribute__((unused)) std::ostream & stream,
                             __attribute__((unused)) int indent) {}
 };
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 void Array<T, is_scal>::printself(std::ostream & stream, int indent) const {
   std::string space;
   for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
     ;
 
   std::streamsize prec = stream.precision();
   std::ios_base::fmtflags ff = stream.flags();
 
   stream.setf(std::ios_base::showbase);
   stream.precision(2);
 
   stream << space << "Array<" << 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
+  stream << space << " + allocated size : " << this->getAllocatedSize()
+         << std::endl;
+  stream << space
+         << " + memory size    : " << printMemorySize<T>(this->getMemorySize())
          << std::endl;
-  stream << space << " + memory size    : "
-         << printMemorySize<T>(allocated_size * nb_component) << 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);
 
   ArrayPrintHelper<is_scal>::print_content(*this, stream, indent);
 
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 /* Inline Functions ArrayBase                                                */
 /* -------------------------------------------------------------------------- */
 
-inline UInt ArrayBase::getMemorySize() const {
-  return allocated_size * nb_component * size_of_type;
-}
-
-inline void ArrayBase::empty() { size_ = 0; }
+inline void ArrayBase::empty() { this->size_ = 0; }
 
 #ifndef SWIG
 /* -------------------------------------------------------------------------- */
 /* Iterators                                                                  */
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 template <class R, class daughter, class IR, bool is_tensor>
 class Array<T, is_scal>::iterator_internal {
 public:
   using value_type = R;
   using pointer = R *;
   using reference = R &;
   using proxy = typename R::proxy;
   using const_proxy = const typename R::proxy;
   using const_reference = const R &;
   using internal_value_type = IR;
   using internal_pointer = IR *;
   using difference_type = std::ptrdiff_t;
   using iterator_category = std::random_access_iterator_tag;
 
 public:
   iterator_internal() = default;
 
   iterator_internal(pointer_type data, UInt _offset)
       : _offset(_offset), initial(data), ret(nullptr), ret_ptr(data) {
     AKANTU_ERROR(
         "The constructor should never be called it is just an ugly trick...");
   }
 
   iterator_internal(std::unique_ptr<internal_value_type> && wrapped)
       : _offset(wrapped->size()), initial(wrapped->storage()),
         ret(std::move(wrapped)), ret_ptr(ret->storage()) {}
 
   iterator_internal(const iterator_internal & it) {
     if (this != &it) {
       this->_offset = it._offset;
       this->initial = it.initial;
       this->ret_ptr = it.ret_ptr;
       this->ret = std::make_unique<internal_value_type>(*it.ret, false);
     }
   }
 
   iterator_internal(iterator_internal && it) = default;
 
   virtual ~iterator_internal() = default;
 
   inline iterator_internal & operator=(const iterator_internal & it) {
     if (this != &it) {
       this->_offset = it._offset;
       this->initial = it.initial;
       this->ret_ptr = it.ret_ptr;
       if (this->ret)
         this->ret->shallowCopy(*it.ret);
       else
         this->ret = std::make_unique<internal_value_type>(*it.ret, false);
     }
     return *this;
   }
 
   UInt getCurrentIndex() {
     return (this->ret_ptr - this->initial) / this->_offset;
   };
 
   inline reference operator*() {
     ret->values = ret_ptr;
     return *ret;
   };
   inline const_reference operator*() const {
     ret->values = ret_ptr;
     return *ret;
   };
   inline pointer operator->() {
     ret->values = ret_ptr;
     return ret.get();
   };
   inline daughter & operator++() {
     ret_ptr += _offset;
     return static_cast<daughter &>(*this);
   };
   inline daughter & operator--() {
     ret_ptr -= _offset;
     return static_cast<daughter &>(*this);
   };
 
   inline daughter & operator+=(const UInt n) {
     ret_ptr += _offset * n;
     return static_cast<daughter &>(*this);
   }
   inline daughter & operator-=(const UInt n) {
     ret_ptr -= _offset * n;
     return static_cast<daughter &>(*this);
   }
 
   inline proxy operator[](const UInt n) {
     ret->values = ret_ptr + n * _offset;
     return proxy(*ret);
   }
   inline const_proxy operator[](const UInt n) const {
     ret->values = ret_ptr + n * _offset;
     return const_proxy(*ret);
   }
 
   inline bool operator==(const iterator_internal & other) const {
     return this->ret_ptr == other.ret_ptr;
   }
   inline bool operator!=(const iterator_internal & other) const {
     return this->ret_ptr != other.ret_ptr;
   }
   inline bool operator<(const iterator_internal & other) const {
     return this->ret_ptr < other.ret_ptr;
   }
   inline bool operator<=(const iterator_internal & other) const {
     return this->ret_ptr <= other.ret_ptr;
   }
   inline bool operator>(const iterator_internal & other) const {
     return this->ret_ptr > other.ret_ptr;
   }
   inline bool operator>=(const iterator_internal & other) const {
     return this->ret_ptr >= other.ret_ptr;
   }
 
   inline daughter operator+(difference_type n) {
     daughter tmp(static_cast<daughter &>(*this));
     tmp += n;
     return tmp;
   }
   inline daughter operator-(difference_type n) {
     daughter tmp(static_cast<daughter &>(*this));
     tmp -= n;
     return tmp;
   }
 
   inline difference_type operator-(const iterator_internal & b) {
     return (this->ret_ptr - b.ret_ptr) / _offset;
   }
 
   inline pointer_type data() const { return ret_ptr; }
   inline difference_type offset() const { return _offset; }
 
 protected:
   UInt _offset{0};
   pointer_type initial{nullptr};
   std::unique_ptr<internal_value_type> ret{nullptr};
   pointer_type ret_ptr{nullptr};
 };
 
 /* -------------------------------------------------------------------------- */
 /**
  * Specialization for scalar types
  */
 template <class T, bool is_scal>
 template <class R, class daughter, class IR>
 class Array<T, is_scal>::iterator_internal<R, daughter, IR, false> {
 public:
   using value_type = R;
   using pointer = R *;
   using reference = R &;
   using const_reference = const R &;
   using internal_value_type = IR;
   using internal_pointer = IR *;
   using difference_type = std::ptrdiff_t;
   using iterator_category = std::random_access_iterator_tag;
 
 public:
   iterator_internal(pointer data = nullptr) : ret(data), initial(data){};
   iterator_internal(const iterator_internal & it) = default;
   iterator_internal(iterator_internal && it) = default;
 
   virtual ~iterator_internal() = default;
 
   inline iterator_internal & operator=(const iterator_internal & it) = default;
 
   UInt getCurrentIndex() { return (this->ret - this->initial); };
 
   inline reference operator*() { return *ret; };
   inline const_reference operator*() const { return *ret; };
   inline pointer operator->() { return ret; };
   inline daughter & operator++() {
     ++ret;
     return static_cast<daughter &>(*this);
   };
   inline daughter & operator--() {
     --ret;
     return static_cast<daughter &>(*this);
   };
 
   inline daughter & operator+=(const UInt n) {
     ret += n;
     return static_cast<daughter &>(*this);
   }
   inline daughter & operator-=(const UInt n) {
     ret -= n;
     return static_cast<daughter &>(*this);
   }
 
   inline reference operator[](const UInt n) { return ret[n]; }
 
   inline bool operator==(const iterator_internal & other) const {
     return ret == other.ret;
   }
   inline bool operator!=(const iterator_internal & other) const {
     return ret != other.ret;
   }
   inline bool operator<(const iterator_internal & other) const {
     return ret < other.ret;
   }
   inline bool operator<=(const iterator_internal & other) const {
     return ret <= other.ret;
   }
   inline bool operator>(const iterator_internal & other) const {
     return ret > other.ret;
   }
   inline bool operator>=(const iterator_internal & other) const {
     return ret >= other.ret;
   }
 
   inline daughter operator-(difference_type n) { return daughter(ret - n); }
   inline daughter operator+(difference_type n) { return daughter(ret + n); }
 
   inline difference_type operator-(const iterator_internal & b) {
     return ret - b.ret;
   }
 
   inline pointer data() const { return ret; }
 
 protected:
   pointer ret{nullptr};
   pointer initial{nullptr};
 };
 
 /* -------------------------------------------------------------------------- */
 /* Begin/End functions implementation                                         */
 /* -------------------------------------------------------------------------- */
 namespace detail {
   template <class Tuple, size_t... Is>
   constexpr auto take_front_impl(Tuple && t, std::index_sequence<Is...>) {
     return std::make_tuple(std::get<Is>(std::forward<Tuple>(t))...);
   }
 
   template <size_t N, class Tuple> constexpr auto take_front(Tuple && t) {
     return take_front_impl(std::forward<Tuple>(t),
                            std::make_index_sequence<N>{});
   }
 
   template <typename... V> constexpr auto product_all(V &&... v) {
     std::common_type_t<int, V...> result = 1;
     (void)std::initializer_list<int>{(result *= v, 0)...};
     return result;
   }
 
   template <typename... T> std::string to_string_all(T &&... t) {
     if (sizeof...(T) == 0)
       return "";
 
     std::stringstream ss;
     bool noComma = true;
     ss << "(";
     (void)std::initializer_list<bool>{
         (ss << (noComma ? "" : ", ") << t, noComma = false)...};
     ss << ")";
     return ss.str();
   }
 
   template <std::size_t N> struct InstantiationHelper {
     template <typename type, typename T, typename... Ns>
     static auto instantiate(T && data, Ns... ns) {
       return std::make_unique<type>(data, ns...);
     }
   };
 
   template <> struct InstantiationHelper<0> {
     template <typename type, typename T> static auto instantiate(T && data) {
       return data;
     }
   };
 
   template <typename Arr, typename T, typename... Ns>
   decltype(auto) get_iterator(Arr && array, T * data, Ns &&... ns) {
     using type = IteratorHelper_t<sizeof...(Ns) - 1, T>;
     using array_type = std::decay_t<Arr>;
     using iterator =
         std::conditional_t<std::is_const<std::remove_reference_t<Arr>>::value,
                            typename array_type::template const_iterator<type>,
                            typename array_type::template iterator<type>>;
     static_assert(sizeof...(Ns), "You should provide a least one size");
 
     if (array.getNbComponent() * array.size() !=
         product_all(std::forward<Ns>(ns)...)) {
       AKANTU_CUSTOM_EXCEPTION_INFO(
           debug::ArrayException(),
           "The iterator on "
               << debug::demangle(typeid(Arr).name())
               << to_string_all(array.size(), array.getNbComponent())
               << "is not compatible with the type "
               << debug::demangle(typeid(type).name()) << to_string_all(ns...));
     }
 
     auto && wrapped = aka::apply(
         [&](auto... n) {
           return InstantiationHelper<sizeof...(n)>::template instantiate<type>(
               data, n...);
         },
         take_front<sizeof...(Ns) - 1>(std::make_tuple(ns...)));
 
     return iterator(std::move(wrapped));
   }
 } // namespace detail
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 template <typename... Ns>
 inline decltype(auto) Array<T, is_scal>::begin(Ns &&... ns) {
-  return detail::get_iterator(*this, values, std::forward<Ns>(ns)..., size_);
+  return detail::get_iterator(*this, this->values, std::forward<Ns>(ns)...,
+                              this->size_);
 }
 
 template <class T, bool is_scal>
 template <typename... Ns>
 inline decltype(auto) Array<T, is_scal>::end(Ns &&... ns) {
-  return detail::get_iterator(*this, values + nb_component * size_,
-                              std::forward<Ns>(ns)..., size_);
+  return detail::get_iterator(*this,
+                              this->values + this->nb_component * this->size_,
+                              std::forward<Ns>(ns)..., this->size_);
 }
 
 template <class T, bool is_scal>
 template <typename... Ns>
 inline decltype(auto) Array<T, is_scal>::begin(Ns &&... ns) const {
-  return detail::get_iterator(*this, values, std::forward<Ns>(ns)..., size_);
+  return detail::get_iterator(*this, this->values, std::forward<Ns>(ns)...,
+                              this->size_);
 }
 
 template <class T, bool is_scal>
 template <typename... Ns>
 inline decltype(auto) Array<T, is_scal>::end(Ns &&... ns) const {
-  return detail::get_iterator(*this, values + nb_component * size_,
-                              std::forward<Ns>(ns)..., size_);
+  return detail::get_iterator(*this,
+                              this->values + this->nb_component * this->size_,
+                              std::forward<Ns>(ns)..., this->size_);
 }
 
 template <class T, bool is_scal>
 template <typename... Ns>
 inline decltype(auto) Array<T, is_scal>::begin_reinterpret(Ns &&... ns) {
-  return detail::get_iterator(*this, values, std::forward<Ns>(ns)...);
+  return detail::get_iterator(*this, this->values, std::forward<Ns>(ns)...);
 }
 
 template <class T, bool is_scal>
 template <typename... Ns>
 inline decltype(auto) Array<T, is_scal>::end_reinterpret(Ns &&... ns) {
   return detail::get_iterator(
-      *this, values + detail::product_all(std::forward<Ns>(ns)...),
+      *this, this->values + detail::product_all(std::forward<Ns>(ns)...),
       std::forward<Ns>(ns)...);
 }
 
 template <class T, bool is_scal>
 template <typename... Ns>
 inline decltype(auto) Array<T, is_scal>::begin_reinterpret(Ns &&... ns) const {
-  return detail::get_iterator(*this, values, std::forward<Ns>(ns)...);
+  return detail::get_iterator(*this, this->values, std::forward<Ns>(ns)...);
 }
 
 template <class T, bool is_scal>
 template <typename... Ns>
 inline decltype(auto) Array<T, is_scal>::end_reinterpret(Ns &&... ns) const {
   return detail::get_iterator(
-      *this, values + detail::product_all(std::forward<Ns>(ns)...),
+      *this, this->values + detail::product_all(std::forward<Ns>(ns)...),
       std::forward<Ns>(ns)...);
 }
 
 /* -------------------------------------------------------------------------- */
 /* Views                                                                      */
 /* -------------------------------------------------------------------------- */
 namespace detail {
   template <typename Array, typename... Ns> class ArrayView {
     using tuple = std::tuple<Ns...>;
 
   public:
     ArrayView(Array && array, Ns... ns)
         : array(std::forward<Array>(array)), sizes(std::move(ns)...) {}
 
     ArrayView(ArrayView && array_view) = default;
 
     ArrayView & operator=(const ArrayView & array_view) = default;
     ArrayView & operator=(ArrayView && array_view) = default;
 
     decltype(auto) begin() {
       return aka::apply(
           [&](auto &&... ns) { return array.begin_reinterpret(ns...); }, sizes);
     }
 
     decltype(auto) begin() const {
       return aka::apply(
           [&](auto &&... ns) { return array.begin_reinterpret(ns...); }, sizes);
     }
 
     decltype(auto) end() {
       return aka::apply(
           [&](auto &&... ns) { return array.end_reinterpret(ns...); }, sizes);
     }
 
     decltype(auto) end() const {
       return aka::apply(
           [&](auto &&... ns) { return array.end_reinterpret(ns...); }, sizes);
     }
 
     decltype(auto) size() const {
       return std::get<std::tuple_size<tuple>::value - 1>(sizes);
     }
 
     decltype(auto) dims() const { return std::tuple_size<tuple>::value - 1; }
 
   private:
     Array array;
     tuple sizes;
   };
 } // namespace detail
 
 /* -------------------------------------------------------------------------- */
 template <typename Array, typename... Ns>
 decltype(auto) make_view(Array && array, Ns... ns) {
   static_assert(aka::conjunction<std::is_integral<std::decay_t<Ns>>...>::value,
                 "Ns should be integral types");
   auto size = std::forward<decltype(array)>(array).size() *
               std::forward<decltype(array)>(array).getNbComponent() /
               detail::product_all(ns...);
 
   return detail::ArrayView<Array, std::common_type_t<size_t, Ns>...,
                            std::common_type_t<size_t, decltype(size)>>(
       std::forward<Array>(array), std::move(ns)..., size);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 template <typename R>
 class Array<T, is_scal>::const_iterator
     : public iterator_internal<const R, Array<T, is_scal>::const_iterator<R>,
                                R> {
 public:
   using parent = iterator_internal<const R, const_iterator, R>;
   using value_type = typename parent::value_type;
   using pointer = typename parent::pointer;
   using reference = typename parent::reference;
   using difference_type = typename parent::difference_type;
   using iterator_category = typename parent::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) {}
 
   const_iterator(const const_iterator & it) = default;
   const_iterator(const_iterator && it) = default;
 
   template <typename P, typename = std::enable_if_t<not is_tensor<P>::value>>
   const_iterator(P * data) : parent(data) {}
 
-  template <typename UP_P,
-            typename =
-                std::enable_if_t<is_tensor<typename UP_P::element_type>::value>>
+  template <typename UP_P, typename = std::enable_if_t<
+                               is_tensor<typename UP_P::element_type>::value>>
   const_iterator(UP_P && tensor) : parent(std::forward<UP_P>(tensor)) {}
 
   const_iterator & operator=(const const_iterator & it) = default;
 };
 
 template <class T, class R, bool is_tensor_ = is_tensor<R>::value>
 struct ConstConverterIteratorHelper {
   using const_iterator = typename Array<T>::template const_iterator<R>;
   using iterator = typename Array<T>::template iterator<R>;
 
   static inline const_iterator convert(const iterator & it) {
     return const_iterator(std::unique_ptr<R>(new R(*it, false)));
   }
 };
 
 template <class T, class R> struct ConstConverterIteratorHelper<T, R, false> {
   using const_iterator = typename Array<T>::template const_iterator<R>;
   using iterator = typename Array<T>::template iterator<R>;
   static inline const_iterator convert(const iterator & it) {
     return const_iterator(it.data());
   }
 };
 
 template <class T, bool is_scal>
 template <typename R>
 class Array<T, is_scal>::iterator
     : public iterator_internal<R, Array<T, is_scal>::iterator<R>> {
 public:
   using parent = iterator_internal<R, iterator>;
   using value_type = typename parent::value_type;
   using pointer = typename parent::pointer;
   using reference = typename parent::reference;
   using difference_type = typename parent::difference_type;
   using iterator_category = typename parent::iterator_category;
 
 public:
   iterator() : parent(){};
   iterator(const iterator & it) = default;
   iterator(iterator && it) = default;
 
   template <typename P, typename = std::enable_if_t<not is_tensor<P>::value>>
   iterator(P * data) : parent(data) {}
 
-  template <typename UP_P,
-            typename =
-                std::enable_if_t<is_tensor<typename UP_P::element_type>::value>>
+  template <typename UP_P, typename = std::enable_if_t<
+                               is_tensor<typename UP_P::element_type>::value>>
   iterator(UP_P && tensor) : parent(std::forward<UP_P>(tensor)) {}
 
   iterator & operator=(const iterator & it) = default;
 
   operator const_iterator<R>() {
     return ConstConverterIteratorHelper<T, R>::convert(*this);
   }
 };
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 template <typename R>
 inline typename Array<T, is_scal>::template iterator<R>
 Array<T, is_scal>::erase(const iterator<R> & it) {
   T * curr = it.data();
-  UInt pos = (curr - values) / nb_component;
+  UInt pos = (curr - this->values) / this->nb_component;
   erase(pos);
   iterator<R> rit = it;
   return --rit;
 }
 #endif
 
 } // namespace akantu
 
 #endif /* __AKANTU_AKA_ARRAY_TMPL_HH__ */
diff --git a/src/common/aka_bbox.hh b/src/common/aka_bbox.hh
index b0bc5710f..9bc4183e8 100644
--- a/src/common/aka_bbox.hh
+++ b/src/common/aka_bbox.hh
@@ -1,261 +1,265 @@
 /**
  * @file   aka_bbox.hh
  *
  * @author Nicolas Richart
  *
  * @date creation  Mon Feb 12 2018
  *
  * @brief A simple bounding box 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_iterators.hh"
 #include "aka_types.hh"
 #include "communicator.hh"
 /* -------------------------------------------------------------------------- */
+#include <map>
+/* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_AKA_BBOX_HH__
 #define __AKANTU_AKA_BBOX_HH__
 
 namespace akantu {
 
 class BBox {
 public:
+  BBox() = default;
+
   BBox(UInt spatial_dimension)
       : dim(spatial_dimension),
         lower_bounds(spatial_dimension, std::numeric_limits<Real>::max()),
         upper_bounds(spatial_dimension, -std::numeric_limits<Real>::max()) {}
 
   BBox(const BBox & other)
       : dim(other.dim), empty{false}, lower_bounds(other.lower_bounds),
         upper_bounds(other.upper_bounds) {}
 
   BBox & operator=(const BBox & other) {
     if (this != &other) {
       this->dim = other.dim;
       this->lower_bounds = other.lower_bounds;
       this->upper_bounds = other.upper_bounds;
       this->empty = other.empty;
     }
     return *this;
   }
 
   inline BBox & operator+=(const Vector<Real> & position) {
     AKANTU_DEBUG_ASSERT(
         this->dim == position.size(),
         "You are adding a point of a wrong dimension to the bounding box");
 
     this->empty = false;
 
     for (auto s : arange(dim)) {
       lower_bounds(s) = std::min(lower_bounds(s), position(s));
       upper_bounds(s) = std::max(upper_bounds(s), position(s));
     }
     return *this;
   }
 
   /* ------------------------------------------------------------------------ */
   inline bool intersects(const BBox & other,
                          const SpatialDirection & direction) const {
     AKANTU_DEBUG_ASSERT(
         this->dim == other.dim,
         "You are intersecting bounding boxes of different dimensions");
     return Math::intersects(lower_bounds(direction), upper_bounds(direction),
                             other.lower_bounds(direction),
                             other.upper_bounds(direction));
   }
 
   inline bool intersects(const BBox & other) const {
     if (this->empty or other.empty)
       return false;
 
     bool intersects_ = true;
     for (auto s : arange(this->dim)) {
       intersects_ &= this->intersects(other, SpatialDirection(s));
     }
     return intersects_;
   }
 
   /* ------------------------------------------------------------------------ */
   inline BBox intersection(const BBox & other) const {
     AKANTU_DEBUG_ASSERT(
         this->dim == other.dim,
         "You are intersecting bounding boxes of different dimensions");
 
     BBox intersection_(this->dim);
     intersection_.empty = not this->intersects(other);
 
     if (intersection_.empty)
       return intersection_;
 
     for (auto s : arange(this->dim)) {
       // is lower point in range ?
       bool point1 = Math::is_in_range(other.lower_bounds(s), lower_bounds(s),
                                       upper_bounds(s));
 
       // is upper point in range ?
       bool point2 = Math::is_in_range(other.upper_bounds(s), lower_bounds(s),
                                       upper_bounds(s));
 
       if (point1 and not point2) {
         // |-----------|         this (i)
         //       |-----------|   other(i)
         //       1           2
         intersection_.lower_bounds(s) = other.lower_bounds(s);
         intersection_.upper_bounds(s) = upper_bounds(s);
       } else if (point1 && point2) {
         // |-----------------|   this (i)
         //   |-----------|       other(i)
         //   1           2
         intersection_.lower_bounds(s) = other.lower_bounds(s);
         intersection_.upper_bounds(s) = other.upper_bounds(s);
       } else if (!point1 && point2) {
         //       |-----------|   this (i)
         // |-----------|         other(i)
         // 1           2
         intersection_.lower_bounds(s) = this->lower_bounds(s);
         intersection_.upper_bounds(s) = other.upper_bounds(s);
       } else {
         //   |-----------|       this (i)
         // |-----------------|   other(i)
         // 1                 2
         intersection_.lower_bounds(s) = this->lower_bounds(s);
         intersection_.upper_bounds(s) = this->upper_bounds(s);
       }
     }
 
     return intersection_;
   }
 
   /* ------------------------------------------------------------------------ */
   inline bool contains(const Vector<Real> & point) const {
     return (point >= lower_bounds) and (point <= upper_bounds);
   }
 
   /* ------------------------------------------------------------------------ */
   inline void reset() {
     lower_bounds.set(std::numeric_limits<Real>::max());
     upper_bounds.set(-std::numeric_limits<Real>::max());
   }
 
   /* ------------------------------------------------------------------------ */
   const Vector<Real> & getLowerBounds() const { return lower_bounds; }
   const Vector<Real> & getUpperBounds() const { return upper_bounds; }
 
   Vector<Real> & getLowerBounds() { return lower_bounds; }
   Vector<Real> & getUpperBounds() { return upper_bounds; }
 
   /* ------------------------------------------------------------------------ */
   inline Real size(const SpatialDirection & direction) const {
     return upper_bounds(direction) - lower_bounds(direction);
   }
 
   Vector<Real> size() const {
     Vector<Real> size_(dim);
     for (auto s : arange(this->dim)) {
       size_(s) = this->size(SpatialDirection(s));
     }
     return size_;
   }
 
   inline operator bool() const { return not empty; }
 
   /* ------------------------------------------------------------------------ */
   BBox allSum(const Communicator & communicator) const {
     Matrix<Real> reduce_bounds(dim, 2);
 
     Vector<Real>(reduce_bounds(0)) = lower_bounds;
     Vector<Real>(reduce_bounds(1)) = Real(-1.) * upper_bounds;
 
     communicator.allReduce(reduce_bounds, SynchronizerOperation::_min);
 
     BBox global(dim);
     global.lower_bounds = Vector<Real>(reduce_bounds(0));
     global.upper_bounds = Real(-1.) * Vector<Real>(reduce_bounds(1));
     global.empty = false;
     return global;
   }
 
   std::vector<BBox> allGather(const Communicator & communicator) const {
     auto prank = communicator.whoAmI();
     auto nb_proc = communicator.getNbProc();
     Array<Real> bboxes_data(nb_proc, dim * 2 + 1);
 
     auto * base = bboxes_data.storage() + prank * (2 * dim + 1);
     Vector<Real>(base + dim * 0, dim) = lower_bounds;
     Vector<Real>(base + dim * 1, dim) = upper_bounds;
     base[dim * 2] = empty ? 1. : 0.; // ugly trick
 
     communicator.allGather(bboxes_data);
 
     std::vector<BBox> bboxes;
     bboxes.reserve(nb_proc);
 
     for (auto p : arange(nb_proc)) {
       bboxes.emplace_back(dim);
       auto & bbox = bboxes.back();
 
       auto * base = bboxes_data.storage() + p * (2 * dim + 1);
       bbox.lower_bounds = Vector<Real>(base + dim * 0, dim);
       bbox.upper_bounds = Vector<Real>(base + dim * 1, dim);
       bbox.empty = base[dim * 2] == 1. ? true : false;
     }
 
     return bboxes;
   }
 
   std::map<UInt, BBox> intersection(const BBox & other,
                                     const Communicator & communicator) {
     // todo: change for a custom reduction algorithm
     auto other_bboxes = other.allGather(communicator);
     std::map<UInt, BBox> intersections;
-    for (auto & bbox : enumerate(other_bboxes)) {
+    for (const auto & bbox : enumerate(other_bboxes)) {
       auto && tmp = this->intersection(std::get<1>(bbox));
       if (tmp) {
         intersections[std::get<0>(bbox)] = tmp;
       }
     }
     return intersections;
   }
 
   void printself(std::ostream & stream) const {
     stream << "BBox[";
     if (not empty) {
       stream << lower_bounds << " - " << upper_bounds;
     }
     stream << "]";
   }
 
 protected:
-  UInt dim;
+  UInt dim{0};
   bool empty{true};
   Vector<Real> lower_bounds;
   Vector<Real> upper_bounds;
 };
 
 inline std::ostream & operator<<(std::ostream & stream, const BBox & bbox) {
   bbox.printself(stream);
   return stream;
 }
 
 } // akantu
 
 #endif /* __AKANTU_AKA_BBOX_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc
index 65cd472b9..6c576cf54 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc
@@ -1,551 +1,562 @@
 /**
  * @file   material_cohesive.cc
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Wed Feb 22 2012
  * @date last modification: Mon Feb 19 2018
  *
  * @brief  Specialization of the material class for cohesive elements
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 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_cohesive.hh"
 #include "aka_random_generator.hh"
 #include "dof_synchronizer.hh"
 #include "fe_engine_template.hh"
 #include "integrator_gauss.hh"
 #include "shape_cohesive.hh"
 #include "solid_mechanics_model_cohesive.hh"
 #include "sparse_matrix.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 MaterialCohesive::MaterialCohesive(SolidMechanicsModel & model, const ID & id)
     : Material(model, id),
       facet_filter("facet_filter", id, this->getMemoryID()),
       fem_cohesive(
           model.getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine")),
       reversible_energy("reversible_energy", *this),
       total_energy("total_energy", *this), opening("opening", *this),
       tractions("tractions", *this),
       contact_tractions("contact_tractions", *this),
       contact_opening("contact_opening", *this), delta_max("delta max", *this),
       use_previous_delta_max(false), use_previous_opening(false),
       damage("damage", *this), sigma_c("sigma_c", *this),
       normal(0, spatial_dimension, "normal") {
 
   AKANTU_DEBUG_IN();
 
   this->model = dynamic_cast<SolidMechanicsModelCohesive *>(&model);
 
   this->registerParam("sigma_c", sigma_c, _pat_parsable | _pat_readable,
                       "Critical stress");
   this->registerParam("delta_c", delta_c, Real(0.),
                       _pat_parsable | _pat_readable, "Critical displacement");
 
   this->element_filter.initialize(this->model->getMesh(),
                                   _spatial_dimension = spatial_dimension,
                                   _element_kind = _ek_cohesive);
   // this->model->getMesh().initElementTypeMapArray(
   //     this->element_filter, 1, spatial_dimension, false, _ek_cohesive);
 
   if (this->model->getIsExtrinsic())
     this->facet_filter.initialize(this->model->getMeshFacets(),
                                   _spatial_dimension = spatial_dimension - 1,
                                   _element_kind = _ek_regular);
   // this->model->getMeshFacets().initElementTypeMapArray(facet_filter, 1,
   //                                                      spatial_dimension -
   //                                                      1);
 
   this->reversible_energy.initialize(1);
   this->total_energy.initialize(1);
 
   this->tractions.initialize(spatial_dimension);
   this->tractions.initializeHistory();
 
   this->contact_tractions.initialize(spatial_dimension);
   this->contact_opening.initialize(spatial_dimension);
 
   this->opening.initialize(spatial_dimension);
   this->opening.initializeHistory();
 
   this->delta_max.initialize(1);
   this->damage.initialize(1);
 
   if (this->model->getIsExtrinsic())
     this->sigma_c.initialize(1);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 MaterialCohesive::~MaterialCohesive() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::initMaterial() {
   AKANTU_DEBUG_IN();
   Material::initMaterial();
   if (this->use_previous_delta_max)
     this->delta_max.initializeHistory();
   if (this->use_previous_opening)
     this->opening.initializeHistory();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::assembleInternalForces(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
 #if defined(AKANTU_DEBUG_TOOLS)
   debug::element_manager.printData(debug::_dm_material_cohesive,
                                    "Cohesive Tractions", tractions);
 #endif
 
   auto & internal_force = const_cast<Array<Real> &>(model->getInternalForce());
 
   for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type,
                                                _ek_cohesive)) {
     auto & elem_filter = element_filter(type, ghost_type);
     UInt nb_element = elem_filter.size();
     if (nb_element == 0)
       continue;
 
     const auto & shapes = fem_cohesive.getShapes(type, ghost_type);
     auto & traction = tractions(type, ghost_type);
     auto & contact_traction = contact_tractions(type, ghost_type);
 
     UInt size_of_shapes = shapes.getNbComponent();
     UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
     UInt nb_quadrature_points =
         fem_cohesive.getNbIntegrationPoints(type, ghost_type);
 
     /// compute @f$t_i N_a@f$
 
     Array<Real> * traction_cpy = new Array<Real>(
         nb_element * nb_quadrature_points, spatial_dimension * size_of_shapes);
 
     auto traction_it = traction.begin(spatial_dimension, 1);
     auto contact_traction_it = contact_traction.begin(spatial_dimension, 1);
     auto shapes_filtered_begin = shapes.begin(1, size_of_shapes);
     auto traction_cpy_it =
         traction_cpy->begin(spatial_dimension, size_of_shapes);
 
     Matrix<Real> traction_tmp(spatial_dimension, 1);
 
     for (UInt el = 0; el < nb_element; ++el) {
 
       UInt current_quad = elem_filter(el) * nb_quadrature_points;
 
       for (UInt q = 0; q < nb_quadrature_points; ++q, ++traction_it,
                 ++contact_traction_it, ++current_quad, ++traction_cpy_it) {
 
         const Matrix<Real> & shapes_filtered =
             shapes_filtered_begin[current_quad];
 
         traction_tmp.copy(*traction_it);
         traction_tmp += *contact_traction_it;
 
         traction_cpy_it->mul<false, false>(traction_tmp, shapes_filtered);
       }
     }
 
     /**
      * compute @f$\int t \cdot N\, dS@f$ by  @f$ \sum_q \mathbf{N}^t
      * \mathbf{t}_q \overline w_q J_q@f$
      */
-    Array<Real> * int_t_N = new Array<Real>(
+    Array<Real> * partial_int_t_N = new Array<Real>(
         nb_element, spatial_dimension * size_of_shapes, "int_t_N");
 
-    fem_cohesive.integrate(*traction_cpy, *int_t_N,
+    fem_cohesive.integrate(*traction_cpy, *partial_int_t_N,
                            spatial_dimension * size_of_shapes, type, ghost_type,
                            elem_filter);
 
     delete traction_cpy;
 
-    int_t_N->extendComponentsInterlaced(2, int_t_N->getNbComponent());
+    Array<Real> * int_t_N = new Array<Real>(
+        nb_element, 2 * spatial_dimension * size_of_shapes, "int_t_N");
 
     Real * int_t_N_val = int_t_N->storage();
+    Real * partial_int_t_N_val = partial_int_t_N->storage();
     for (UInt el = 0; el < nb_element; ++el) {
+      std::copy_n(partial_int_t_N_val, size_of_shapes * spatial_dimension,
+                  int_t_N_val);
+      std::copy_n(partial_int_t_N_val, size_of_shapes * spatial_dimension,
+                  int_t_N_val + size_of_shapes * spatial_dimension);
+
       for (UInt n = 0; n < size_of_shapes * spatial_dimension; ++n)
         int_t_N_val[n] *= -1.;
+
       int_t_N_val += nb_nodes_per_element * spatial_dimension;
+      partial_int_t_N_val += size_of_shapes * spatial_dimension;
     }
 
+    delete partial_int_t_N;
+
     /// assemble
     model->getDOFManager().assembleElementalArrayLocalArray(
         *int_t_N, internal_force, type, ghost_type, 1, elem_filter);
 
     delete int_t_N;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::assembleStiffnessMatrix(GhostType ghost_type) {
 
   AKANTU_DEBUG_IN();
 
   for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type,
                                                _ek_cohesive)) {
     UInt nb_quadrature_points =
         fem_cohesive.getNbIntegrationPoints(type, ghost_type);
     UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
 
     const Array<Real> & shapes = fem_cohesive.getShapes(type, ghost_type);
     Array<UInt> & elem_filter = element_filter(type, ghost_type);
 
     UInt nb_element = elem_filter.size();
 
     if (!nb_element)
       continue;
 
     UInt size_of_shapes = shapes.getNbComponent();
 
     Array<Real> * shapes_filtered = new Array<Real>(
         nb_element * nb_quadrature_points, size_of_shapes, "filtered shapes");
 
     Real * shapes_filtered_val = shapes_filtered->storage();
     UInt * elem_filter_val = elem_filter.storage();
 
     for (UInt el = 0; el < nb_element; ++el) {
-      auto shapes_val =
-          shapes.storage() +
-          elem_filter_val[el] * size_of_shapes * nb_quadrature_points;
+      auto shapes_val = shapes.storage() + elem_filter_val[el] *
+                                               size_of_shapes *
+                                               nb_quadrature_points;
       memcpy(shapes_filtered_val, shapes_val,
              size_of_shapes * nb_quadrature_points * sizeof(Real));
       shapes_filtered_val += size_of_shapes * nb_quadrature_points;
     }
 
     Matrix<Real> A(spatial_dimension * size_of_shapes,
                    spatial_dimension * nb_nodes_per_element);
 
     for (UInt i = 0; i < spatial_dimension * size_of_shapes; ++i) {
       A(i, i) = 1;
       A(i, i + spatial_dimension * size_of_shapes) = -1;
     }
 
     /// get the tangent matrix @f$\frac{\partial{(t/\delta)}}{\partial{\delta}}
     /// @f$
     Array<Real> * tangent_stiffness_matrix = new Array<Real>(
         nb_element * nb_quadrature_points,
         spatial_dimension * spatial_dimension, "tangent_stiffness_matrix");
 
     //    Array<Real> * normal = new Array<Real>(nb_element *
     //    nb_quadrature_points, spatial_dimension, "normal");
     normal.resize(nb_quadrature_points);
 
     computeNormal(model->getCurrentPosition(), normal, type, ghost_type);
 
     /// compute openings @f$\mathbf{\delta}@f$
     // computeOpening(model->getDisplacement(), opening(type, ghost_type), type,
     // ghost_type);
 
     tangent_stiffness_matrix->clear();
 
     computeTangentTraction(type, *tangent_stiffness_matrix, normal, ghost_type);
 
     // delete normal;
 
     UInt size_at_nt_d_n_a = spatial_dimension * nb_nodes_per_element *
                             spatial_dimension * nb_nodes_per_element;
     Array<Real> * at_nt_d_n_a = new Array<Real>(
         nb_element * nb_quadrature_points, size_at_nt_d_n_a, "A^t*N^t*D*N*A");
 
     Array<Real>::iterator<Vector<Real>> shapes_filt_it =
         shapes_filtered->begin(size_of_shapes);
 
     Array<Real>::matrix_iterator D_it =
         tangent_stiffness_matrix->begin(spatial_dimension, spatial_dimension);
 
     Array<Real>::matrix_iterator At_Nt_D_N_A_it =
         at_nt_d_n_a->begin(spatial_dimension * nb_nodes_per_element,
                            spatial_dimension * nb_nodes_per_element);
 
     Array<Real>::matrix_iterator At_Nt_D_N_A_end =
         at_nt_d_n_a->end(spatial_dimension * nb_nodes_per_element,
                          spatial_dimension * nb_nodes_per_element);
 
     Matrix<Real> N(spatial_dimension, spatial_dimension * size_of_shapes);
     Matrix<Real> N_A(spatial_dimension,
                      spatial_dimension * nb_nodes_per_element);
     Matrix<Real> D_N_A(spatial_dimension,
                        spatial_dimension * nb_nodes_per_element);
 
     for (; At_Nt_D_N_A_it != At_Nt_D_N_A_end;
          ++At_Nt_D_N_A_it, ++D_it, ++shapes_filt_it) {
       N.clear();
       /**
        * store  the   shapes  in  voigt   notations  matrix  @f$\mathbf{N}  =
        * \begin{array}{cccccc} N_0(\xi) & 0 & N_1(\xi)  &0 & N_2(\xi) & 0 \\
        * 0 & * N_0(\xi)& 0 &N_1(\xi)& 0 & N_2(\xi) \end{array} @f$
        **/
       for (UInt i = 0; i < spatial_dimension; ++i)
         for (UInt n = 0; n < size_of_shapes; ++n)
           N(i, i + spatial_dimension * n) = (*shapes_filt_it)(n);
 
       /**
        * compute stiffness matrix  @f$   \mathbf{K}    =    \delta \mathbf{U}^T
        * \int_{\Gamma_c}    {\mathbf{P}^t \frac{\partial{\mathbf{t}}}
        *{\partial{\delta}}
        * \mathbf{P} d\Gamma \Delta \mathbf{U}}  @f$
        **/
       N_A.mul<false, false>(N, A);
       D_N_A.mul<false, false>(*D_it, N_A);
       (*At_Nt_D_N_A_it).mul<true, false>(D_N_A, N_A);
     }
 
     delete tangent_stiffness_matrix;
     delete shapes_filtered;
 
     Array<Real> * K_e = new Array<Real>(nb_element, size_at_nt_d_n_a, "K_e");
 
     fem_cohesive.integrate(*at_nt_d_n_a, *K_e, size_at_nt_d_n_a, type,
                            ghost_type, elem_filter);
 
     delete at_nt_d_n_a;
 
     model->getDOFManager().assembleElementalMatricesToMatrix(
         "K", "displacement", *K_e, type, ghost_type, _unsymmetric, elem_filter);
 
     delete K_e;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- *
  * Compute traction from displacements
  *
  * @param[in] ghost_type compute the residual for _ghost or _not_ghost element
  */
 void MaterialCohesive::computeTraction(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
 #if defined(AKANTU_DEBUG_TOOLS)
   debug::element_manager.printData(debug::_dm_material_cohesive,
                                    "Cohesive Openings", opening);
 #endif
 
   for (auto & type : element_filter.elementTypes(spatial_dimension, ghost_type,
                                                  _ek_cohesive)) {
     Array<UInt> & elem_filter = element_filter(type, ghost_type);
 
     UInt nb_element = elem_filter.size();
     if (nb_element == 0)
       continue;
 
     UInt nb_quadrature_points =
         nb_element * fem_cohesive.getNbIntegrationPoints(type, ghost_type);
 
     normal.resize(nb_quadrature_points);
 
     /// compute normals @f$\mathbf{n}@f$
     computeNormal(model->getCurrentPosition(), normal, type, ghost_type);
 
     /// compute openings @f$\mathbf{\delta}@f$
     computeOpening(model->getDisplacement(), opening(type, ghost_type), type,
                    ghost_type);
 
     /// compute traction @f$\mathbf{t}@f$
     computeTraction(normal, type, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::computeNormal(const Array<Real> & position,
                                      Array<Real> & normal, ElementType type,
                                      GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   auto & fem_cohesive =
       this->model->getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine");
 
 #define COMPUTE_NORMAL(type)                                                   \
   fem_cohesive.getShapeFunctions()                                             \
       .computeNormalsOnIntegrationPoints<type, CohesiveReduceFunctionMean>(    \
           position, normal, ghost_type, element_filter(type, ghost_type));
 
   AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(COMPUTE_NORMAL);
 #undef COMPUTE_NORMAL
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::computeOpening(const Array<Real> & displacement,
                                       Array<Real> & opening, ElementType type,
                                       GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   auto & fem_cohesive =
       this->model->getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine");
 
 #define COMPUTE_OPENING(type)                                                  \
   fem_cohesive.getShapeFunctions()                                             \
       .interpolateOnIntegrationPoints<type, CohesiveReduceFunctionOpening>(    \
           displacement, opening, spatial_dimension, ghost_type,                \
           element_filter(type, ghost_type));
 
   AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(COMPUTE_OPENING);
 #undef COMPUTE_OPENING
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::updateEnergies(ElementType type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   if (Mesh::getKind(type) != _ek_cohesive)
     return;
 
   Vector<Real> b(spatial_dimension);
   Vector<Real> h(spatial_dimension);
   auto erev = reversible_energy(type, ghost_type).begin();
   auto etot = total_energy(type, ghost_type).begin();
   auto traction_it = tractions(type, ghost_type).begin(spatial_dimension);
   auto traction_old_it =
       tractions.previous(type, ghost_type).begin(spatial_dimension);
   auto opening_it = opening(type, ghost_type).begin(spatial_dimension);
   auto opening_old_it =
       opening.previous(type, ghost_type).begin(spatial_dimension);
 
   auto traction_end = tractions(type, ghost_type).end(spatial_dimension);
 
   /// loop on each quadrature point
   for (; traction_it != traction_end; ++traction_it, ++traction_old_it,
                                       ++opening_it, ++opening_old_it, ++erev,
                                       ++etot) {
     /// trapezoidal integration
     b = *opening_it;
     b -= *opening_old_it;
 
     h = *traction_old_it;
     h += *traction_it;
 
     *etot += .5 * b.dot(h);
     *erev = .5 * traction_it->dot(*opening_it);
   }
 
   /// update old values
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getReversibleEnergy() {
   AKANTU_DEBUG_IN();
   Real erev = 0.;
 
   /// integrate reversible energy for each type of elements
   for (auto & type : element_filter.elementTypes(spatial_dimension, _not_ghost,
                                                  _ek_cohesive)) {
     erev +=
         fem_cohesive.integrate(reversible_energy(type, _not_ghost), type,
                                _not_ghost, element_filter(type, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return erev;
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getDissipatedEnergy() {
   AKANTU_DEBUG_IN();
   Real edis = 0.;
 
   /// integrate dissipated energy for each type of elements
   for (auto & type : element_filter.elementTypes(spatial_dimension, _not_ghost,
                                                  _ek_cohesive)) {
     Array<Real> dissipated_energy(total_energy(type, _not_ghost));
     dissipated_energy -= reversible_energy(type, _not_ghost);
     edis += fem_cohesive.integrate(dissipated_energy, type, _not_ghost,
                                    element_filter(type, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return edis;
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getContactEnergy() {
   AKANTU_DEBUG_IN();
   Real econ = 0.;
 
   /// integrate contact energy for each type of elements
   for (auto & type : element_filter.elementTypes(spatial_dimension, _not_ghost,
                                                  _ek_cohesive)) {
 
     auto & el_filter = element_filter(type, _not_ghost);
     UInt nb_quad_per_el = fem_cohesive.getNbIntegrationPoints(type, _not_ghost);
     UInt nb_quad_points = el_filter.size() * nb_quad_per_el;
     Array<Real> contact_energy(nb_quad_points);
 
     auto contact_traction_it =
         contact_tractions(type, _not_ghost).begin(spatial_dimension);
     auto contact_opening_it =
         contact_opening(type, _not_ghost).begin(spatial_dimension);
 
     /// loop on each quadrature point
     for (UInt q = 0; q < nb_quad_points;
          ++contact_traction_it, ++contact_opening_it, ++q) {
 
       contact_energy(q) = .5 * contact_traction_it->dot(*contact_opening_it);
     }
 
     econ += fem_cohesive.integrate(contact_energy, type, _not_ghost, el_filter);
   }
 
   AKANTU_DEBUG_OUT();
   return econ;
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getEnergy(const std::string & type) {
   AKANTU_DEBUG_IN();
 
   if (type == "reversible")
     return getReversibleEnergy();
   else if (type == "dissipated")
     return getDissipatedEnergy();
   else if (type == "cohesive contact")
     return getContactEnergy();
 
   AKANTU_DEBUG_OUT();
   return 0.;
 }
 
 /* -------------------------------------------------------------------------- */
 } // namespace akantu
diff --git a/src/model/time_step_solvers/time_step_solver_default.cc b/src/model/time_step_solvers/time_step_solver_default.cc
index cec055b5a..b115e433b 100644
--- a/src/model/time_step_solvers/time_step_solver_default.cc
+++ b/src/model/time_step_solvers/time_step_solver_default.cc
@@ -1,310 +1,302 @@
 /**
  * @file   time_step_solver_default.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Tue Sep 15 2015
  * @date last modification: Wed Feb 21 2018
  *
  * @brief  Default implementation of the time step solver
  *
  * @section LICENSE
  *
  * Copyright (©) 2015-2018 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 "time_step_solver_default.hh"
 #include "dof_manager_default.hh"
 #include "integration_scheme_1st_order.hh"
 #include "integration_scheme_2nd_order.hh"
 #include "mesh.hh"
 #include "non_linear_solver.hh"
 #include "pseudo_time.hh"
 #include "sparse_matrix_aij.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 TimeStepSolverDefault::TimeStepSolverDefault(
     DOFManagerDefault & dof_manager, const TimeStepSolverType & type,
     NonLinearSolver & non_linear_solver, const ID & id, UInt memory_id)
     : TimeStepSolver(dof_manager, type, non_linear_solver, id, memory_id),
       dof_manager(dof_manager), is_mass_lumped(false) {
   switch (type) {
   case _tsst_dynamic:
     break;
   case _tsst_dynamic_lumped:
     this->is_mass_lumped = true;
     break;
   case _tsst_static:
     /// initialize a static time solver for callback dofs
     break;
   default:
     AKANTU_TO_IMPLEMENT();
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void TimeStepSolverDefault::setIntegrationScheme(
     const ID & dof_id, const IntegrationSchemeType & type,
     IntegrationScheme::SolutionType solution_type) {
   if (this->integration_schemes.find(dof_id) !=
       this->integration_schemes.end()) {
     AKANTU_EXCEPTION("Their DOFs "
                      << dof_id
                      << "  have already an integration scheme associated");
   }
 
   std::unique_ptr<IntegrationScheme> integration_scheme;
   if (this->is_mass_lumped) {
     switch (type) {
     case _ist_forward_euler: {
       integration_scheme = std::make_unique<ForwardEuler>(dof_manager, dof_id);
       break;
     }
     case _ist_central_difference: {
       integration_scheme =
           std::make_unique<CentralDifference>(dof_manager, dof_id);
       break;
     }
     default:
       AKANTU_EXCEPTION(
           "This integration scheme cannot be used in lumped dynamic");
     }
   } else {
     switch (type) {
     case _ist_pseudo_time: {
       integration_scheme = std::make_unique<PseudoTime>(dof_manager, dof_id);
       break;
     }
     case _ist_forward_euler: {
       integration_scheme = std::make_unique<ForwardEuler>(dof_manager, dof_id);
       break;
     }
     case _ist_trapezoidal_rule_1: {
       integration_scheme =
           std::make_unique<TrapezoidalRule1>(dof_manager, dof_id);
       break;
     }
     case _ist_backward_euler: {
       integration_scheme = std::make_unique<BackwardEuler>(dof_manager, dof_id);
       break;
     }
     case _ist_central_difference: {
       integration_scheme =
           std::make_unique<CentralDifference>(dof_manager, dof_id);
       break;
     }
     case _ist_fox_goodwin: {
       integration_scheme = std::make_unique<FoxGoodwin>(dof_manager, dof_id);
       break;
     }
     case _ist_trapezoidal_rule_2: {
       integration_scheme =
           std::make_unique<TrapezoidalRule2>(dof_manager, dof_id);
       break;
     }
     case _ist_linear_acceleration: {
       integration_scheme =
           std::make_unique<LinearAceleration>(dof_manager, dof_id);
       break;
     }
     case _ist_generalized_trapezoidal: {
       integration_scheme =
           std::make_unique<GeneralizedTrapezoidal>(dof_manager, dof_id);
       break;
     }
     case _ist_newmark_beta:
       integration_scheme = std::make_unique<NewmarkBeta>(dof_manager, dof_id);
       break;
     }
   }
 
   AKANTU_DEBUG_ASSERT(integration_scheme,
                       "No integration scheme was found for the provided types");
 
   auto && matrices_names = integration_scheme->getNeededMatrixList();
   for (auto && name : matrices_names) {
     needed_matrices.insert({name, _mt_not_defined});
   }
 
   this->integration_schemes[dof_id] = std::move(integration_scheme);
   this->solution_types[dof_id] = solution_type;
 
   this->integration_schemes_owner.insert(dof_id);
 }
 
 /* -------------------------------------------------------------------------- */
 bool TimeStepSolverDefault::hasIntegrationScheme(const ID & dof_id) const {
   return this->integration_schemes.find(dof_id) !=
          this->integration_schemes.end();
 }
 
 /* -------------------------------------------------------------------------- */
 TimeStepSolverDefault::~TimeStepSolverDefault() = default;
 
 /* -------------------------------------------------------------------------- */
 void TimeStepSolverDefault::solveStep(SolverCallback & solver_callback) {
   this->solver_callback = &solver_callback;
 
   this->solver_callback->beforeSolveStep();
   this->non_linear_solver.solve(*this);
   this->solver_callback->afterSolveStep();
 
   this->solver_callback = nullptr;
 }
 
 /* -------------------------------------------------------------------------- */
 void TimeStepSolverDefault::predictor() {
-  AKANTU_DEBUG_IN();
-
   TimeStepSolver::predictor();
 
-  for (auto & pair : this->integration_schemes) {
-    auto & dof_id = pair.first;
+  for (auto && pair : this->integration_schemes) {
+    const auto & dof_id = pair.first;
     auto & integration_scheme = pair.second;
 
     if (this->dof_manager.hasPreviousDOFs(dof_id)) {
       this->dof_manager.savePreviousDOFs(dof_id);
     }
 
     /// integrator predictor
     integration_scheme->predictor(this->time_step);
   }
-
-  AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void TimeStepSolverDefault::corrector() {
   AKANTU_DEBUG_IN();
 
   TimeStepSolver::corrector();
 
   for (auto & pair : this->integration_schemes) {
     auto & dof_id = pair.first;
     auto & integration_scheme = pair.second;
 
     const auto & solution_type = this->solution_types[dof_id];
     integration_scheme->corrector(solution_type, this->time_step);
 
     /// computing the increment of dof if needed
     if (this->dof_manager.hasDOFsIncrement(dof_id)) {
       if (!this->dof_manager.hasPreviousDOFs(dof_id)) {
         AKANTU_DEBUG_WARNING("In order to compute the increment of "
                              << dof_id << " a 'previous' has to be registered");
         continue;
       }
 
       Array<Real> & increment = this->dof_manager.getDOFsIncrement(dof_id);
       Array<Real> & previous = this->dof_manager.getPreviousDOFs(dof_id);
 
       UInt dof_array_comp = this->dof_manager.getDOFs(dof_id).getNbComponent();
 
       auto prev_dof_it = previous.begin(dof_array_comp);
       auto incr_it = increment.begin(dof_array_comp);
       auto incr_end = increment.end(dof_array_comp);
 
       increment.copy(this->dof_manager.getDOFs(dof_id));
       for (; incr_it != incr_end; ++incr_it, ++prev_dof_it) {
         *incr_it -= *prev_dof_it;
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void TimeStepSolverDefault::assembleMatrix(const ID & matrix_id) {
   AKANTU_DEBUG_IN();
 
   TimeStepSolver::assembleMatrix(matrix_id);
 
   if (matrix_id != "J")
     return;
 
   for (auto & pair : this->integration_schemes) {
     auto & dof_id = pair.first;
     auto & integration_scheme = pair.second;
 
     const auto & solution_type = this->solution_types[dof_id];
 
     integration_scheme->assembleJacobian(solution_type, this->time_step);
   }
 
   this->dof_manager.applyBoundary("J");
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void TimeStepSolverDefault::assembleResidual() {
-  AKANTU_DEBUG_IN();
-
   if (this->needed_matrices.find("M") != needed_matrices.end()) {
     if (this->is_mass_lumped) {
       this->assembleLumpedMatrix("M");
     } else {
       this->assembleMatrix("M");
     }
   }
 
   TimeStepSolver::assembleResidual();
 
-  for (auto & pair : this->integration_schemes) {
+  for (auto && pair : this->integration_schemes) {
     auto & integration_scheme = pair.second;
 
     integration_scheme->assembleResidual(this->is_mass_lumped);
   }
-
-  AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void TimeStepSolverDefault::assembleResidual(const ID & residual_part) {
   AKANTU_DEBUG_IN();
 
   if (this->needed_matrices.find("M") != needed_matrices.end()) {
     if (this->is_mass_lumped) {
       this->assembleLumpedMatrix("M");
     } else {
       this->assembleMatrix("M");
     }
   }
 
   if (residual_part != "inertial") {
     TimeStepSolver::assembleResidual(residual_part);
   }
 
   if (residual_part == "inertial") {
     for (auto & pair : this->integration_schemes) {
       auto & integration_scheme = pair.second;
 
       integration_scheme->assembleResidual(this->is_mass_lumped);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 } // namespace akantu
diff --git a/test/test_common/test_array.cc b/test/test_common/test_array.cc
index 6b587b845..081874ad9 100644
--- a/test/test_common/test_array.cc
+++ b/test/test_common/test_array.cc
@@ -1,285 +1,289 @@
 /**
  * @file   test_array.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Thu Nov 09 2017
  * @date last modification: Fri Jan 26 2018
  *
  * @brief  Test the arry class
  *
  * @section LICENSE
  *
  * Copyright (©) 2016-2018 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_array.hh"
 #include "aka_types.hh"
 /* -------------------------------------------------------------------------- */
 #include <gtest/gtest.h>
 #include <memory>
 #include <typeindex>
 #include <typeinfo>
 /* -------------------------------------------------------------------------- */
 
 using namespace akantu;
 
 namespace {
 
 class NonTrivial {
 public:
   NonTrivial() = default;
   NonTrivial(int a) : a(a){};
 
   bool operator==(const NonTrivial & rhs) { return a == rhs.a; }
   int a{0};
 };
 
 bool operator==(const int & a, const NonTrivial & rhs) { return a == rhs.a; }
 
 std::ostream & operator<<(std::ostream & stream, const NonTrivial & _this) {
   stream << _this.a;
   return stream;
 }
 
 /* -------------------------------------------------------------------------- */
 using TestTypes = ::testing::Types<Real, UInt, NonTrivial>;
 /* -------------------------------------------------------------------------- */
 
 ::testing::AssertionResult AssertType(const char * /*a_expr*/,
                                       const char * /*b_expr*/,
                                       const std::type_info & a,
                                       const std::type_info & b) {
   if (std::type_index(a) == std::type_index(b))
     return ::testing::AssertionSuccess();
 
   return ::testing::AssertionFailure()
          << debug::demangle(a.name()) << " != " << debug::demangle(b.name())
          << ") are different";
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <typename T> class ArrayConstructor : public ::testing::Test {
 protected:
   using type = T;
 
   void SetUp() override { type_str = debug::demangle(typeid(T).name()); }
 
   template <typename... P> decltype(auto) construct(P &&... params) {
     return std::make_unique<Array<T>>(std::forward<P>(params)...);
   }
 
 protected:
   std::string type_str;
 };
 
 TYPED_TEST_CASE(ArrayConstructor, TestTypes);
 
 TYPED_TEST(ArrayConstructor, ConstructDefault1) {
   auto array = this->construct();
   EXPECT_EQ(0, array->size());
   EXPECT_EQ(1, array->getNbComponent());
   EXPECT_STREQ("", array->getID().c_str());
 }
 
 TYPED_TEST(ArrayConstructor, ConstructDefault2) {
   auto array = this->construct(1000);
   EXPECT_EQ(1000, array->size());
   EXPECT_EQ(1, array->getNbComponent());
   EXPECT_STREQ("", array->getID().c_str());
 }
 
 TYPED_TEST(ArrayConstructor, ConstructDefault3) {
   auto array = this->construct(1000, 10);
   EXPECT_EQ(1000, array->size());
   EXPECT_EQ(10, array->getNbComponent());
   EXPECT_STREQ("", array->getID().c_str());
 }
 
 TYPED_TEST(ArrayConstructor, ConstructDefault4) {
   auto array = this->construct(1000, 10, "test");
   EXPECT_EQ(1000, array->size());
   EXPECT_EQ(10, array->getNbComponent());
   EXPECT_STREQ("test", array->getID().c_str());
 }
 
 TYPED_TEST(ArrayConstructor, ConstructDefault5) {
   auto array = this->construct(1000, 10, 1);
   EXPECT_EQ(1000, array->size());
   EXPECT_EQ(10, array->getNbComponent());
   EXPECT_EQ(1, array->operator()(10, 6));
   EXPECT_STREQ("", array->getID().c_str());
 }
 
-TYPED_TEST(ArrayConstructor, ConstructDefault6) {
-  typename TestFixture::type defaultv[2] = {0, 1};
+// TYPED_TEST(ArrayConstructor, ConstructDefault6) {
+//   typename TestFixture::type defaultv[2] = {0, 1};
 
-  auto array = this->construct(1000, 2, defaultv);
-  EXPECT_EQ(1000, array->size());
-  EXPECT_EQ(2, array->getNbComponent());
-  EXPECT_EQ(1, array->operator()(10, 1));
-  EXPECT_EQ(0, array->operator()(603, 0));
-  EXPECT_STREQ("", array->getID().c_str());
-}
+//   auto array = this->construct(1000, 2, defaultv);
+//   EXPECT_EQ(1000, array->size());
+//   EXPECT_EQ(2, array->getNbComponent());
+//   EXPECT_EQ(1, array->operator()(10, 1));
+//   EXPECT_EQ(0, array->operator()(603, 0));
+//   EXPECT_STREQ("", array->getID().c_str());
+// }
 
 /* -------------------------------------------------------------------------- */
 template <typename T> class ArrayFixture : public ArrayConstructor<T> {
 public:
   void SetUp() override {
     ArrayConstructor<T>::SetUp();
     array = this->construct(1000, 10);
   }
 
   void TearDown() override { array.reset(nullptr); }
 
 protected:
   std::unique_ptr<Array<T>> array;
 };
 
 TYPED_TEST_CASE(ArrayFixture, TestTypes);
 
 TYPED_TEST(ArrayFixture, Copy) {
   Array<typename TestFixture::type> copy(*this->array);
 
   EXPECT_EQ(1000, copy.size());
   EXPECT_EQ(10, copy.getNbComponent());
   EXPECT_NE(this->array->storage(), copy.storage());
 }
 
 TYPED_TEST(ArrayFixture, Set) {
   auto & arr = *(this->array);
   arr.set(12);
   EXPECT_EQ(12, arr(156, 5));
   EXPECT_EQ(12, arr(520, 7));
   EXPECT_EQ(12, arr(999, 9));
 }
 
 TYPED_TEST(ArrayFixture, Resize) {
   auto & arr = *(this->array);
 
-  auto ptr = arr.storage();
+  auto * ptr = arr.storage();
 
   arr.resize(0);
   EXPECT_EQ(0, arr.size());
-  EXPECT_EQ(ptr, arr.storage());
-  EXPECT_EQ(1000, arr.getAllocatedSize());
+  EXPECT_TRUE(arr.storage() == nullptr or arr.storage() == ptr);
+  EXPECT_LE(0, arr.getAllocatedSize());
 
   arr.resize(3000);
   EXPECT_EQ(3000, arr.size());
-  EXPECT_EQ(3000, arr.getAllocatedSize());
+  EXPECT_LE(3000, arr.getAllocatedSize());
+
+  ptr = arr.storage();
 
   arr.resize(0);
   EXPECT_EQ(0, arr.size());
-  EXPECT_EQ(nullptr, arr.storage());
-  EXPECT_EQ(0, arr.getAllocatedSize());
+  EXPECT_TRUE(arr.storage() == nullptr or arr.storage() == ptr);
+  EXPECT_LE(0, arr.getAllocatedSize());
 }
 
 TYPED_TEST(ArrayFixture, PushBack) {
   auto & arr = *(this->array);
 
-  auto ptr = arr.storage();
+  auto * ptr = arr.storage();
 
   arr.resize(0);
   EXPECT_EQ(0, arr.size());
-  EXPECT_EQ(ptr, arr.storage());
-  EXPECT_EQ(1000, arr.getAllocatedSize());
+  EXPECT_TRUE(arr.storage() == nullptr or arr.storage() == ptr);
+  EXPECT_LE(0, arr.getAllocatedSize());
 
   arr.resize(3000);
   EXPECT_EQ(3000, arr.size());
-  EXPECT_EQ(3000, arr.getAllocatedSize());
+  EXPECT_LE(3000, arr.getAllocatedSize());
+
+  ptr = arr.storage();
 
   arr.resize(0);
   EXPECT_EQ(0, arr.size());
-  EXPECT_EQ(nullptr, arr.storage());
-  EXPECT_EQ(0, arr.getAllocatedSize());
+  EXPECT_TRUE(arr.storage() == nullptr or arr.storage() == ptr);
+  EXPECT_LE(0, arr.getAllocatedSize());
 }
 
 TYPED_TEST(ArrayFixture, ViewVector) {
   auto && view = make_view(*this->array, 10);
   EXPECT_NO_THROW(view.begin());
   {
     auto it = view.begin();
     EXPECT_EQ(10, it->size());
     EXPECT_PRED_FORMAT2(AssertType, typeid(*it),
                         typeid(Vector<typename TestFixture::type>));
     EXPECT_PRED_FORMAT2(AssertType, typeid(it[0]),
                         typeid(VectorProxy<typename TestFixture::type>));
   }
 }
 
 TYPED_TEST(ArrayFixture, ViewMatrix) {
   {
     auto && view = make_view(*this->array, 2, 5);
 
     EXPECT_NO_THROW(view.begin());
     {
       auto it = view.begin();
       EXPECT_EQ(10, it->size());
       EXPECT_EQ(2, it->size(0));
       EXPECT_EQ(5, it->size(1));
 
       EXPECT_PRED_FORMAT2(AssertType, typeid(*it),
                           typeid(Matrix<typename TestFixture::type>));
       EXPECT_PRED_FORMAT2(AssertType, typeid(it[0]),
                           typeid(MatrixProxy<typename TestFixture::type>));
     }
   }
 }
 
 TYPED_TEST(ArrayFixture, ViewVectorWrong) {
   auto && view = make_view(*this->array, 11);
   EXPECT_THROW(view.begin(), debug::ArrayException);
 }
 
 TYPED_TEST(ArrayFixture, ViewMatrixWrong) {
   auto && view = make_view(*this->array, 3, 7);
   EXPECT_THROW(view.begin(), debug::ArrayException);
 }
 
 TYPED_TEST(ArrayFixture, ViewMatrixIter) {
   std::size_t count = 0;
   for (auto && mat : make_view(*this->array, 10, 10)) {
     EXPECT_EQ(100, mat.size());
     EXPECT_EQ(10, mat.size(0));
     EXPECT_EQ(10, mat.size(1));
     EXPECT_PRED_FORMAT2(AssertType, typeid(mat),
                         typeid(Matrix<typename TestFixture::type>));
 
     ++count;
   }
 
   EXPECT_EQ(100, count);
 }
 
 TYPED_TEST(ArrayFixture, ConstViewVector) {
   const auto & carray = *this->array;
   auto && view = make_view(carray, 10);
   EXPECT_NO_THROW(view.begin());
   {
     auto it = view.begin();
     EXPECT_EQ(10, it->size());
     EXPECT_PRED_FORMAT2(AssertType, typeid(*it),
                         typeid(Vector<typename TestFixture::type>));
     EXPECT_PRED_FORMAT2(AssertType, typeid(it[0]),
                         typeid(VectorProxy<typename TestFixture::type>));
   }
 }
 
 } // namespace
diff --git a/test/test_model/test_model_solver/test_model_solver.cc b/test/test_model/test_model_solver/test_model_solver.cc
index bbca4d32c..9ccc544b0 100644
--- a/test/test_model/test_model_solver/test_model_solver.cc
+++ b/test/test_model/test_model_solver/test_model_solver.cc
@@ -1,148 +1,170 @@
 /**
  * @file   test_model_solver.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Apr 13 2016
  * @date last modification: Thu Feb 01 2018
  *
  * @brief  Test default dof manager
  *
  * @section LICENSE
  *
  * Copyright (©) 2016-2018 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_random_generator.hh"
 #include "dof_manager.hh"
 #include "dof_synchronizer.hh"
 #include "mesh.hh"
 #include "mesh_accessor.hh"
 #include "model_solver.hh"
 #include "non_linear_solver.hh"
 #include "sparse_matrix.hh"
 
 /* -------------------------------------------------------------------------- */
 #include "test_model_solver_my_model.hh"
 /* -------------------------------------------------------------------------- */
 #include <cmath>
 /* -------------------------------------------------------------------------- */
 
 using namespace akantu;
 
 static void genMesh(Mesh & mesh, UInt nb_nodes);
 static void printResults(MyModel & model, UInt nb_nodes);
 
 Real F = -10;
 
 /* -------------------------------------------------------------------------- */
 int main(int argc, char * argv[]) {
   initialize(argc, argv);
 
   UInt prank = Communicator::getStaticCommunicator().whoAmI();
 
   std::cout << std::setprecision(7);
 
   UInt global_nb_nodes = 100;
   Mesh mesh(1);
 
   RandomGenerator<UInt>::seed(1);
 
   if (prank == 0) {
     genMesh(mesh, global_nb_nodes);
   }
 
   // std::cout << prank << RandGenerator<Real>::seed() << std::endl;
   mesh.distribute();
 
   MyModel model(F, mesh, false);
 
   model.getNewSolver("static", _tsst_static, _nls_newton_raphson);
   model.setIntegrationScheme("static", "disp", _ist_pseudo_time);
 
   NonLinearSolver & solver = model.getDOFManager().getNonLinearSolver("static");
   solver.set("max_iterations", 2);
 
   model.solveStep();
 
   printResults(model, global_nb_nodes);
 
   finalize();
   return EXIT_SUCCESS;
 }
 
 /* -------------------------------------------------------------------------- */
 void genMesh(Mesh & mesh, UInt nb_nodes) {
   MeshAccessor mesh_accessor(mesh);
   Array<Real> & nodes = mesh_accessor.getNodes();
   Array<UInt> & conn = mesh_accessor.getConnectivity(_segment_2);
 
   nodes.resize(nb_nodes);
   mesh_accessor.setNbGlobalNodes(nb_nodes);
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     nodes(n, _x) = n * (1. / (nb_nodes - 1));
   }
 
   conn.resize(nb_nodes - 1);
   for (UInt n = 0; n < nb_nodes - 1; ++n) {
     conn(n, 0) = n;
     conn(n, 1) = n + 1;
   }
+  mesh_accessor.makeReady();
 }
 
 /* -------------------------------------------------------------------------- */
 void printResults(MyModel & model, UInt nb_nodes) {
-  UInt prank = model.mesh.getCommunicator().whoAmI();
-  auto & sync = dynamic_cast<DOFManagerDefault &>(model.getDOFManager())
-                    .getSynchronizer();
-
-  if (prank == 0) {
-    Array<Real> global_displacement(nb_nodes);
-    Array<Real> global_forces(nb_nodes);
-    Array<bool> global_blocked(nb_nodes);
-
-    sync.gather(model.forces, global_forces);
-    sync.gather(model.displacement, global_displacement);
-    sync.gather(model.blocked, global_blocked);
-
-    auto force_it = global_forces.begin();
-    auto disp_it = global_displacement.begin();
-    auto blocked_it = global_blocked.begin();
+  if (model.mesh.isDistributed()) {
+    UInt prank = model.mesh.getCommunicator().whoAmI();
+    auto & sync = dynamic_cast<DOFManagerDefault &>(model.getDOFManager())
+        .getSynchronizer();
+
+    if (prank == 0) {
+      Array<Real> global_displacement(nb_nodes);
+      Array<Real> global_forces(nb_nodes);
+      Array<bool> global_blocked(nb_nodes);
+
+      sync.gather(model.forces, global_forces);
+      sync.gather(model.displacement, global_displacement);
+      sync.gather(model.blocked, global_blocked);
+
+      auto force_it = global_forces.begin();
+      auto disp_it = global_displacement.begin();
+      auto blocked_it = global_blocked.begin();
+
+      std::cout << "node"
+                << ", " << std::setw(8) << "disp"
+                << ", " << std::setw(8) << "force"
+                << ", " << std::setw(8) << "blocked" << std::endl;
+
+      UInt node = 0;
+      for (; disp_it != global_displacement.end();
+           ++disp_it, ++force_it, ++blocked_it, ++node) {
+        std::cout << node << ", " << std::setw(8) << *disp_it << ", "
+                  << std::setw(8) << *force_it << ", " << std::setw(8)
+                  << *blocked_it << std::endl;
+
+        std::cout << std::flush;
+      }
+    } else {
+      sync.gather(model.forces);
+      sync.gather(model.displacement);
+      sync.gather(model.blocked);
+    }
+  } else {
+    auto force_it = model.forces.begin();
+    auto disp_it = model.displacement.begin();
+    auto blocked_it = model.blocked.begin();
 
     std::cout << "node"
-              << ", " << std::setw(8) << "disp"
-              << ", " << std::setw(8) << "force"
-              << ", " << std::setw(8) << "blocked" << std::endl;
+                << ", " << std::setw(8) << "disp"
+                << ", " << std::setw(8) << "force"
+                << ", " << std::setw(8) << "blocked" << std::endl;
 
     UInt node = 0;
-    for (; disp_it != global_displacement.end();
-         ++disp_it, ++force_it, ++blocked_it, ++node) {
-      std::cout << node << ", " << std::setw(8) << *disp_it << ", "
-                << std::setw(8) << *force_it << ", " << std::setw(8)
-                << *blocked_it << std::endl;
-
-      std::cout << std::flush;
-    }
-  } else {
-    sync.gather(model.forces);
-    sync.gather(model.displacement);
-    sync.gather(model.blocked);
+    for (; disp_it != model.displacement.end();
+           ++disp_it, ++force_it, ++blocked_it, ++node) {
+        std::cout << node << ", " << std::setw(8) << *disp_it << ", "
+                  << std::setw(8) << *force_it << ", " << std::setw(8)
+                  << *blocked_it << std::endl;
+
+        std::cout << std::flush;
+      }
   }
 }