diff --git a/src/common/aka_array.hh b/src/common/aka_array.hh
index d2b6f4e38..16a0ac321 100644
--- a/src/common/aka_array.hh
+++ b/src/common/aka_array.hh
@@ -1,363 +1,363 @@
 /**
  * @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: Fri Jan 22 2016
  *
  * @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-2012, 2014,  2015 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 = "");
 
   virtual ~ArrayBase();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// get the amount of space allocated in bytes
   inline UInt getMemorySize() const;
 
   /// set the size to zero without freeing the allocated space
   inline void empty();
 
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /* ------------------------------------------------------------------------ */
   /* Accessors */
   /* ------------------------------------------------------------------------ */
 public:
   /// 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 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 &);
 
-  // AKANTU_GET_MACRO(Tag, tag, const std::string &);
-  // AKANTU_SET_MACRO(Tag, tag, const std::string &);
-
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// id of the vector
   ID id;
 
   /// the size allocated
   UInt allocated_size{0};
 
   /// 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                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   using value_type = T;
   using reference = value_type &;
   using pointer_type = value_type *;
   using const_reference = const value_type &;
 
   /// Allocation of a new vector
   explicit inline 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 value_type def_values[],
         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 = "");
 
 #ifndef SWIG
   /// Copy constructor (deep copy)
   explicit Array(const std::vector<value_type> & vect);
 #endif
 
   inline ~Array() override;
 
   Array & operator=(const Array & a) {
     /// this is to let STL allocate and copy arrays in the case of
     /// std::vector::resize
     AKANTU_DEBUG_ASSERT(this->size == 0, "Cannot copy akantu::Array");
     return const_cast<Array &>(a);
   }
 
   /* ------------------------------------------------------------------------ */
   /* Iterator                                                                 */
   /* ------------------------------------------------------------------------ */
   /// \todo protected: does not compile with intel  check why
 public:
-  template <class R, class IR = R, bool issame = std::is_same<IR, T>::value>
+  template <class R, class it, class IR = R, bool is_tensor_ = is_tensor<R>{}>
   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);
+  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(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);
+  template <typename... Ns> inline decltype(auto) end_reinterpret(Ns&&... n);
 
   template <typename... Ns>
-  inline decltype(auto) begin_reinterpret(Ns... n) const;
+  inline decltype(auto) begin_reinterpret(Ns&&... n) const;
   template <typename... Ns>
-  inline decltype(auto) end_reinterpret(Ns... n) const;
+  inline decltype(auto) end_reinterpret(Ns&&... n) const;
 
   /* ------------------------------------------------------------------------ */
   /* 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[]);
 
   /// append a Vector or a Matrix
-  template <template <typename> class C>
+  template <template <typename> class C,
+            typename = std::enable_if_t<is_tensor<C<T>>{}>>
   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);
 
   /// 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);
 
   /// 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;
 
   /// @see Array::find(const_reference elem) const
-  template <template <typename> class C> inline UInt find(const C<T> & elem);
+  template <template <typename> class C,
+            typename = std::enable_if_t<is_tensor<C<T>>{}>>
+  inline UInt find(const C<T> & elem);
 
   /// 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); }
 
   /// 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> inline void set(const C<T> & vm);
+  template <template <typename> class C,
+            typename = std::enable_if_t<is_tensor<C<T>>{}>>
+  inline void set(const C<T> & vm);
 
   /// 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 41c10a307..eb9b21b7e 100644
--- a/src/common/aka_array_tmpl.hh
+++ b/src/common/aka_array_tmpl.hh
@@ -1,1251 +1,1252 @@
 /**
  * @file   aka_array_tmpl.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Thu Jul 15 2010
  * @date last modification: Fri Jan 22 2016
  *
  * @brief  Inline functions of the classes Array<T> and ArrayBase
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2012, 2014,  2015 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>                                                 */
 /* -------------------------------------------------------------------------- */
 #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 <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 <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 <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];
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * 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);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * 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);
 // }
 
 /* -------------------------------------------------------------------------- */
 /**
  * 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 <template <typename> class C>
+template <template <typename> class C, typename>
 inline void Array<T, is_scal>::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);
 
   T * tmp = values + nb_component * pos;
   std::uninitialized_copy(new_elem.storage(), new_elem.storage() + nb_component,
                           tmp);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * append a tuple to the array
  * @param it an iterator to the tuple to be copied to the end of the array */
 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_;
 
   resizeUnitialized(size_ + 1, false);
 
   T * tmp = values + nb_component * pos;
   T * new_elem = it.data();
   std::uninitialized_copy(new_elem, new_elem + nb_component, tmp);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * 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];
     }
   }
 
   resize(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),
                       "The too array don't have the same sizes");
 
   T * a = values;
   T * b = vect.storage();
   for (UInt i = 0; i < size_ * 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),
                       "The too array don't have the same sizes");
 
   T * a = values;
   T * b = vect.storage();
   for (UInt i = 0; i < size_ * 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
  */
 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) {
     *a++ *= alpha;
   }
 
   return *this;
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * 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;
   if (!equal)
     return false;
 
   if (values == array.storage())
     return true;
   else
     return std::equal(values, values + size_ * 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);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * 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>
+template <template <typename> class C, typename>
 inline void Array<T, is_scal>::set(const C<T> & vm) {
   AKANTU_DEBUG_ASSERT(
       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);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 void Array<T, is_scal>::append(const Array<T> & other) {
   AKANTU_DEBUG_ASSERT(
       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);
 
   T * tmp = values + nb_component * old_size;
   std::uninitialized_copy(other.storage(),
                           other.storage() + other.size() * 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(NULL) {
   AKANTU_DEBUG_IN();
   allocate(size, nb_component);
 
   if (!is_scal) {
     T val = T();
     std::uninitialized_fill(values, values + size * nb_component, val);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 Array<T, is_scal>::Array(UInt size, UInt nb_component, const T def_values[],
                          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();
 }
 
 /* -------------------------------------------------------------------------- */
 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(NULL) {
   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, bool deep,
                          const ID & id)
     : ArrayBase(vect) {
   AKANTU_DEBUG_IN();
   this->id = (id == "") ? vect.id : id;
 
   if (deep) {
     allocate(vect.size_, vect.nb_component);
     T * tmp = values;
     std::uninitialized_copy(vect.storage(),
                             vect.storage() + size_ * nb_component, tmp);
   } 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();
 }
 
 /* -------------------------------------------------------------------------- */
 #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();
 }
 #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 (!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();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * 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();
   if (size == 0) {
     values = nullptr;
   } else {
     values = static_cast<T *>(malloc(nb_component * size * sizeof(T)));
     AKANTU_DEBUG_ASSERT(values != nullptr,
                         "Cannot allocate "
                             << printMemorySize<T>(size * nb_component) << " ("
                             << id << ")");
   }
 
   if (values == NULL) {
     this->size_ = this->allocated_size = 0;
   } 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();
 }
 
 /* -------------------------------------------------------------------------- */
 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);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * 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 = NULL;
+        values = nullptr;
       } else {
         auto * tmp_ptr = static_cast<T *>(
             realloc(values, new_size * nb_component * sizeof(T)));
 
-        if (tmp_ptr == NULL) {
+        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 != NULL,
         "Cannot allocate " << printMemorySize<T>(size_to_alloc * nb_component));
     if (tmp_ptr == NULL) {
       AKANTU_DEBUG_ERROR("Cannot allocate more data ("
                          << id << ")"
                          << " [current allocated size : " << allocated_size
                          << " | "
                          << "requested size : " << new_size << "]");
     }
 
     AKANTU_DEBUG(dblAccessory,
                  "Allocating " << 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();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * 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 {
   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;
   UInt i = 0;
   for (; i < size_; ++i) {
     if (*it == elem[0]) {
       T * cit = it;
       UInt c = 0;
       for (; (c < nb_component) && (*cit == elem[c]); ++c, ++cit)
         ;
       if (c == nb_component) {
         AKANTU_DEBUG_OUT();
         return i;
       }
     }
     it += nb_component;
   }
   return UInt(-1);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
-template <template <typename> class C>
+template <template <typename> class C, typename>
 inline UInt Array<T, is_scal>::find(const C<T> & elem) {
   AKANTU_DEBUG_ASSERT(elem.size() == nb_component,
                       "Cannot find an element with a wrong size ("
                           << elem.size() << ") != " << 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)
       AKANTU_DEBUG_ERROR(
           "The two arrays do not have the same number of components");
 
   resize((vect.size_ * vect.nb_component) / nb_component);
 
   T * tmp = values;
   std::uninitialized_copy(vect.storage(), vect.storage() + size_ * nb_component,
                           tmp);
 
   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
          << 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; }
 
 /* -------------------------------------------------------------------------- */
 /* Iterators                                                                  */
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
-template <class R, class IR, bool is_r_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() : initial(NULL), ret(NULL), ret_ptr(NULL){};
+  iterator_internal() = default;
 
   iterator_internal(pointer_type data, UInt _offset)
-      : _offset(_offset), initial(data), ret(NULL), ret_ptr(data) {
+      : _offset(_offset), initial(data), ret(nullptr), ret_ptr(data) {
     AKANTU_DEBUG_ERROR(
         "The constructor should never be called it is just an ugly trick...");
   }
 
-  iterator_internal(pointer wrapped)
+  iterator_internal(std::unique_ptr<internal_value_type> && wrapped)
       : _offset(wrapped->size()), initial(wrapped->storage()),
-        ret(const_cast<internal_pointer>(wrapped)),
-        ret_ptr(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 = new internal_value_type(*it.ret, false);
+      this->ret = std::make_unique<internal_value_type>(*it.ret, false);
     }
   }
 
-  virtual ~iterator_internal() { delete ret; };
+  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 = new internal_value_type(*it.ret, false);
+        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;
+    return ret.get();
   };
-  inline iterator_internal & operator++() {
+  inline daughter & operator++() {
     ret_ptr += _offset;
-    return *this;
+    return static_cast<daughter &>(*this);
   };
-  inline iterator_internal & operator--() {
+  inline daughter & operator--() {
     ret_ptr -= _offset;
-    return *this;
+    return static_cast<daughter &>(*this);
   };
 
-  inline iterator_internal & operator+=(const UInt n) {
+  inline daughter & operator+=(const UInt n) {
     ret_ptr += _offset * n;
-    return *this;
+    return static_cast<daughter &>(*this);
   }
-  inline iterator_internal & operator-=(const UInt n) {
+  inline daughter & operator-=(const UInt n) {
     ret_ptr -= _offset * n;
-    return *this;
+    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 iterator_internal operator+(difference_type n) {
-    iterator_internal tmp(*this);
+  inline daughter operator+(difference_type n) {
+    daughter tmp(static_cast<daughter &>(*this));
     tmp += n;
     return tmp;
   }
-  inline iterator_internal operator-(difference_type n) {
-    iterator_internal tmp(*this);
+  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;
-  internal_pointer ret;
-  pointer_type ret_ptr;
+  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 IR>
-class Array<T, is_scal>::iterator_internal<R, IR, true> {
+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, UInt _offset = 1)
-      : _offset(_offset), ret(data), initial(data){};
+  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) / this->_offset;
-  };
+  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 iterator_internal & operator++() {
+  inline daughter & operator++() {
     ++ret;
-    return *this;
+    return static_cast<daughter &>(*this);
   };
-  inline iterator_internal & operator--() {
+  inline daughter & operator--() {
     --ret;
-    return *this;
+    return static_cast<daughter &>(*this);
   };
 
-  inline iterator_internal & operator+=(const UInt n) {
+  inline daughter & operator+=(const UInt n) {
     ret += n;
-    return *this;
+    return static_cast<daughter &>(*this);
   }
-  inline iterator_internal & operator-=(const UInt n) {
+  inline daughter & operator-=(const UInt n) {
     ret -= n;
-    return *this;
+    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 iterator_internal operator-(difference_type n) {
-    return iterator_internal(ret - n);
-  }
-  inline iterator_internal operator+(difference_type n) {
-    return iterator_internal(ret + n);
-  }
+  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; }
-  inline difference_type offset() const { return _offset; }
 
 protected:
-  difference_type _offset;
-  pointer ret;
-  pointer initial;
+  pointer ret{nullptr};
+  pointer initial{nullptr};
 };
 
 /* -------------------------------------------------------------------------- */
 /* Begin/End functions implementation                                         */
 /* -------------------------------------------------------------------------- */
-namespace {
-  template <std::size_t N> struct extract_last {
-    template <typename F, typename... T, typename... Arg>
-    static decltype(auto) extract(F && func, std::tuple<T...> && t,
-                                  Arg... args) {
-      return extract_last<N - 1>::extract(
-          std::forward<F>(func), std::forward<decltype(t)>(t),
-          std::get<sizeof...(T) - N>(std::forward<decltype(t)>(t)), args...);
-    }
-  };
+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 <> struct extract_last<1> {
-    template <typename F, typename... T, typename... Arg>
-    static decltype(auto) extract(F && func, std::tuple<T...> && /*unused*/,
-                                  Arg... args) {
-      return std::forward<F>(func)(args...);
-    }
-  };
+  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>{});
+  }
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wnarrowing"
-  template <std::size_t N> struct InstantiationHelper {
-    template <typename... Ns> static constexpr std::size_t product(Ns... ns) {
-      std::size_t p = 1;
-      for (auto n : std::array<std::size_t, sizeof...(Ns)>{ns...})
-        p *= n;
-      return p;
-    }
+  template <typename... V>
+  constexpr auto product_all(V &&... v) ->
+      typename std::common_type<V...>::type {
+    typename std::common_type<V...>::type result = 1;
+    (void)std::initializer_list<int>{(result *= v, 0)...};
+    return result;
+  }
 
-    template <typename... Ns> static std::string to_string(Ns... ns) {
-      std::stringstream sstr;
-      bool first = true;
-      sstr << "(";
-      for (auto n : std::array<std::size_t, sizeof...(Ns)>{ns...}) {
-        if (!first) {
-          sstr << ", ";
-        }
-        sstr << n;
-        first = false;
-      }
-      sstr << ")";
-      return sstr.str();
-    }
-#pragma GCC diagnostic pop
+  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 new type(data, ns...);
+      return std::make_unique<type>(data, ns...);
     }
   };
 
   template <> struct InstantiationHelper<0> {
     template <typename type, typename T> static auto instantiate(T && data) {
       return data;
     }
-
-    static constexpr std::size_t product() { return 1; }
-    static std::string to_string() { return ""; }
   };
 
   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>;
+  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<Arr>::value,
                            typename array_type::template const_iterator<type>,
                            typename array_type::template iterator<type>>;
-    AKANTU_DEBUG_ASSERT(
-        array.getNbComponent() * array.size() ==
-            InstantiationHelper<sizeof...(Ns)>::product(ns...),
-        "The iterator is not compatible with the type "
-            << debug::demangle(typeid(type).name())
-            << InstantiationHelper<sizeof...(Ns)>::to_string(ns...));
+    if (array.getNbComponent() * array.size() !=
+        product_all(std::forward<Ns>(ns)...)) {
+      AKANTU_CUSTOM_EXCEPTION_INFO(
+          debug::ArrayException(),
+          "The iterator on Array "
+              << to_string_all(array.size(), array.getNbComponent())
+              << "is not compatible with the type "
+              << debug::demangle(typeid(type).name()) << to_string_all(ns...));
+    }
 
-    auto && wrapped = extract_last<sizeof...(Ns)>::extract(
+    auto && wrapped = aka::apply(
         [&](auto... n) {
           return InstantiationHelper<sizeof...(n)>::template instantiate<type>(
               data, n...);
         },
-        std::make_tuple(ns...));
+        take_front<sizeof...(Ns) - 1>(std::make_tuple(ns...)));
 
-    return iterator{wrapped};
+    return iterator(std::move(wrapped));
   }
-} // namespace
+} // namespace detail
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::begin(Ns... ns) {
-  return get_iterator(*this, values, ns..., size_);
+inline decltype(auto) Array<T, is_scal>::begin(Ns &&... ns) {
+  return detail::get_iterator(*this, values, std::forward<Ns>(ns)..., size_);
 }
 
 template <class T, bool is_scal>
 template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::end(Ns... ns) {
-  return get_iterator(*this, values + nb_component * size_, ns..., size_);
+inline decltype(auto) Array<T, is_scal>::end(Ns &&... ns) {
+  return detail::get_iterator(*this, values + nb_component * size_,
+                              std::forward<Ns>(ns)..., size_);
 }
 
 template <class T, bool is_scal>
 template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::begin(Ns... ns) const {
-  return get_iterator(*this, values, ns..., size_);
+inline decltype(auto) Array<T, is_scal>::begin(Ns &&... ns) const {
+  return detail::get_iterator(*this, values, std::forward<Ns>(ns)..., size_);
 }
 
 template <class T, bool is_scal>
 template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::end(Ns... ns) const {
-  return get_iterator(*this, values + nb_component * size_, ns..., size_);
+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_);
 }
 
 template <class T, bool is_scal>
 template <typename... Ns>
-inline decltype(auto) Array<T, is_scal>::begin_reinterpret(Ns... ns) {
-  return get_iterator(*this, values, ns...);
+inline decltype(auto) Array<T, is_scal>::begin_reinterpret(Ns &&... ns) {
+  return detail::get_iterator(*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 get_iterator(
-      *this, values + InstantiationHelper<sizeof...(Ns)>::product(ns...),
-      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)...),
+      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 get_iterator(*this, values, ns...);
+inline decltype(auto) Array<T, is_scal>::begin_reinterpret(Ns &&... ns) const {
+  return detail::get_iterator(*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 get_iterator(
-      *this, values + InstantiationHelper<sizeof...(Ns)>::product(ns...),
-      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)...),
+      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::forward<Ns>(ns)...){};
+
+    decltype(auto) begin() {
+      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) size() {
+      return std::get<std::tuple_size<tuple>::value - 1>(sizes);
+    }
+
+  private:
+    Array array;
+    tuple sizes;
+  };
+} // namespace detail
+
+/* -------------------------------------------------------------------------- */
+template <typename Array, typename... Ns>
+decltype(auto) make_view(Array && array, Ns &&... ns) {
+  auto size = std::forward<decltype(array)>(array).size() *
+              std::forward<decltype(array)>(array).getNbComponent() /
+              detail::product_all(ns...);
+
+  return detail::ArrayView<Array, Ns..., decltype(size)>(
+      std::forward<Array>(array), std::forward<Ns>(ns)...,
+      std::forward<decltype(size)>(size));
 }
 
 /* -------------------------------------------------------------------------- */
 template <class T, bool is_scal>
 template <typename R>
-class Array<T, is_scal>::const_iterator : public iterator_internal<const R, R> {
+class Array<T, is_scal>::const_iterator
+    : public iterator_internal<const R, Array<T, is_scal>::const_iterator<R>,
+                               R> {
 public:
-  typedef iterator_internal<const R, R> parent;
+  typedef iterator_internal<const R, const_iterator, R> parent;
   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<R> & it) : parent(it) {}
+  // const_iterator(pointer_type data, UInt offset) : parent(data, offset) {}
+  // const_iterator(pointer warped) : parent(warped) {}
+  // const_iterator(const parent & it) : parent(it) {}
 
-  inline const_iterator operator+(difference_type n) {
-    return parent::operator+(n);
-  }
-  inline const_iterator operator-(difference_type n) {
-    return parent::operator-(n);
-  }
-  inline difference_type operator-(const const_iterator & b) {
-    return parent::operator-(b);
-  }
+  const_iterator(const const_iterator & it) = default;
+  const_iterator(const_iterator && it) = default;
 
-  inline const_iterator & operator++() {
-    parent::operator++();
-    return *this;
-  };
-  inline const_iterator & operator--() {
-    parent::operator--();
-    return *this;
-  };
-  inline const_iterator & operator+=(const UInt n) {
-    parent::operator+=(n);
-    return *this;
-  }
+  template <typename P, typename = std::enable_if_t<not is_tensor<P>{}>>
+  const_iterator(P * data) : parent(data) {}
+
+  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;
 };
-// #endif
 
-// #if defined(AKANTU_CORE_CXX11)
-//   template<class R> using iterator = iterator_internal<R>;
-// #else
-template <class T, class R, bool issame = std::is_same<T, R>::value>
+template <class T, class R, bool is_tensor_ = is_tensor<R>{}>
 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(new R(*it, false));
+    return const_iterator(std::unique_ptr<R>(new R(*it, false)));
   }
 };
 
-template <class T, class R> struct ConstConverterIteratorHelper<T, R, true> {
+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(), it.offset());
+    return const_iterator(it.data());
   }
 };
 
 template <class T, bool is_scal>
 template <typename R>
-class Array<T, is_scal>::iterator : public iterator_internal<R> {
+class Array<T, is_scal>::iterator
+    : public iterator_internal<R, Array<T, is_scal>::iterator<R>> {
 public:
-  using parent = iterator_internal<R>;
+  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(pointer_type data, UInt offset) : parent(data, offset){};
-  iterator(pointer warped) : parent(warped) {}
-  iterator(const parent & it) : parent(it) {}
-  //    iterator(const iterator<R> & it) : parent(it) {}
+  iterator(const iterator & it) = default;
+  iterator(iterator && it) = default;
 
-  operator const_iterator<R>() {
-    return ConstConverterIteratorHelper<T, R>::convert(*this);
-  }
+  template <typename P, typename = std::enable_if_t<not is_tensor<P>::value>>
+  iterator(P * data) : parent(data) {}
 
-  inline iterator operator+(difference_type n) {
-    return parent::operator+(n);
-    ;
-  }
-  inline iterator operator-(difference_type n) {
-    return parent::operator-(n);
-    ;
-  }
-  inline difference_type operator-(const iterator & b) {
-    return parent::operator-(b);
-  }
+  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)) {}
 
-  inline iterator & operator++() {
-    parent::operator++();
-    return *this;
-  };
-  inline iterator & operator--() {
-    parent::operator--();
-    return *this;
-  };
-  inline iterator & operator+=(const UInt n) {
-    parent::operator+=(n);
-    return *this;
+  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;
   erase(pos);
   iterator<R> rit = it;
   return --rit;
 }
 
 } // namespace akantu
 
 #endif /* __AKANTU_AKA_ARRAY_TMPL_HH__ */
diff --git a/src/common/aka_common.hh b/src/common/aka_common.hh
index b21921277..50c1bcc8a 100644
--- a/src/common/aka_common.hh
+++ b/src/common/aka_common.hh
@@ -1,415 +1,414 @@
 /**
  * @file   aka_common.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Mon Jun 14 2010
  * @date last modification: Thu Jan 21 2016
  *
  * @brief  common type descriptions for akantu
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2012, 2014,  2015 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/>.
  *
  * @section DESCRIPTION
  *
  * All common things to be included in the projects files
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_COMMON_HH__
 #define __AKANTU_COMMON_HH__
 
 /* -------------------------------------------------------------------------- */
-#include <list>
 #include <limits>
+#include <list>
 #include <type_traits>
 /* -------------------------------------------------------------------------- */
 
 #include "aka_compatibilty_with_cpp_standard.hh"
 
 /* -------------------------------------------------------------------------- */
 #define __BEGIN_AKANTU_DUMPER__ namespace dumper {
 #define __END_AKANTU_DUMPER__ }
 /* -------------------------------------------------------------------------- */
 #if defined(WIN32)
 #define __attribute__(x)
 #endif
 
 /* -------------------------------------------------------------------------- */
 #include "aka_config.hh"
 #include "aka_error.hh"
 #include "aka_safe_enum.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 /* Common types                                                               */
 /* -------------------------------------------------------------------------- */
 using ID = std::string;
 
 #ifdef AKANTU_NDEBUG
 static const Real REAL_INIT_VALUE = Real(0.);
 #else
 static const Real REAL_INIT_VALUE = std::numeric_limits<Real>::quiet_NaN();
 #endif
 
 /* -------------------------------------------------------------------------- */
 /* Memory types                                                               */
 /* -------------------------------------------------------------------------- */
 
 using MemoryID = UInt;
 
 using Surface = std::string;
 typedef std::pair<Surface, Surface> SurfacePair;
 using SurfacePairList = std::list<SurfacePair>;
 
 /* -------------------------------------------------------------------------- */
 extern const UInt _all_dimensions;
 
 /* -------------------------------------------------------------------------- */
 /* Mesh/FEM/Model types                                                       */
 /* -------------------------------------------------------------------------- */
-} // akantu
+} // namespace akantu
 
 #include "aka_element_classes_info.hh"
 
 namespace akantu {
 
 /// small help to use names for directions
 enum SpacialDirection { _x = 0, _y = 1, _z = 2 };
 
 /// enum MeshIOType type of mesh reader/writer
 enum MeshIOType {
   _miot_auto,        ///< Auto guess of the reader to use based on the extension
   _miot_gmsh,        ///< Gmsh files
   _miot_gmsh_struct, ///< Gsmh reader with reintpretation of elements has
                      /// structures elements
   _miot_diana,       ///< TNO Diana mesh format
   _miot_abaqus       ///< Abaqus mesh format
 };
 
 /// enum MeshEventHandlerPriority defines relative order of execution of events
 enum EventHandlerPriority {
   _ehp_highest = 0,
   _ehp_mesh = 5,
   _ehp_fe_engine = 9,
   _ehp_synchronizer = 10,
   _ehp_dof_manager = 20,
   _ehp_model = 94,
   _ehp_non_local_manager = 100,
   _ehp_lowest = 100
 };
 
-
 /// enum AnalysisMethod type of solving method used to solve the equation of
 /// motion
 enum AnalysisMethod {
   _static = 0,
   _implicit_dynamic = 1,
   _explicit_lumped_mass = 2,
   _explicit_lumped_capacity = 2,
   _explicit_consistent_mass = 3
 };
 
 /// enum DOFSupportType defines which kind of dof that can exists
 enum DOFSupportType { _dst_nodal, _dst_generic };
 
 /// Type of non linear resolution available in akantu
 enum NonLinearSolverType {
   _nls_linear,                  ///< No non linear convergence loop
   _nls_newton_raphson,          ///< Regular Newton-Raphson
   _nls_newton_raphson_modified, ///< Newton-Raphson with initial tangent
   _nls_lumped,                  ///< Case of lumped mass or equivalent matrix
-  _nls_auto                     ///< This will take a default value that make sense in case of
-                                ///  model::getNewSolver
+  _nls_auto ///< This will take a default value that make sense in case of
+            ///  model::getNewSolver
 };
 
 /// Define the node/dof type
-enum NodeType : Int {
-  _nt_pure_gost = -3,
-  _nt_master = -2,
-  _nt_normal = -1
-};
+enum NodeType : Int { _nt_pure_gost = -3, _nt_master = -2, _nt_normal = -1 };
 
 /// Type of time stepping solver
 enum TimeStepSolverType {
   _tsst_static,         ///< Static solution
   _tsst_dynamic,        ///< Dynamic solver
   _tsst_dynamic_lumped, ///< Dynamic solver with lumped mass
   _tsst_not_defined,    ///< For not defined cases
 };
 
 /// Type of integration scheme
 enum IntegrationSchemeType {
-  _ist_pseudo_time,             ///< Pseudo Time
-  _ist_forward_euler,           ///< GeneralizedTrapezoidal(0)
-  _ist_trapezoidal_rule_1,      ///< GeneralizedTrapezoidal(1/2)
-  _ist_backward_euler,          ///< GeneralizedTrapezoidal(1)
-  _ist_central_difference,      ///< NewmarkBeta(0, 1/2)
-  _ist_fox_goodwin,             ///< NewmarkBeta(1/6, 1/2)
-  _ist_trapezoidal_rule_2,      ///< NewmarkBeta(1/2, 1/2)
-  _ist_linear_acceleration,     ///< NewmarkBeta(1/3, 1/2)
-  _ist_newmark_beta,            ///< generic NewmarkBeta with user defined
-                                /// alpha and beta
-  _ist_generalized_trapezoidal  ///< generic GeneralizedTrapezoidal with user
-                                ///  defined alpha
+  _ist_pseudo_time,            ///< Pseudo Time
+  _ist_forward_euler,          ///< GeneralizedTrapezoidal(0)
+  _ist_trapezoidal_rule_1,     ///< GeneralizedTrapezoidal(1/2)
+  _ist_backward_euler,         ///< GeneralizedTrapezoidal(1)
+  _ist_central_difference,     ///< NewmarkBeta(0, 1/2)
+  _ist_fox_goodwin,            ///< NewmarkBeta(1/6, 1/2)
+  _ist_trapezoidal_rule_2,     ///< NewmarkBeta(1/2, 1/2)
+  _ist_linear_acceleration,    ///< NewmarkBeta(1/3, 1/2)
+  _ist_newmark_beta,           ///< generic NewmarkBeta with user defined
+                               /// alpha and beta
+  _ist_generalized_trapezoidal ///< generic GeneralizedTrapezoidal with user
+                               ///  defined alpha
 };
 
 /// enum SolveConvergenceCriteria different convergence criteria
 enum SolveConvergenceCriteria {
   _scc_residual,         ///< Use residual to test the convergence
   _scc_solution,         ///< Use solution to test the convergence
   _scc_residual_mass_wgh ///< Use residual weighted by inv. nodal mass to testb
 };
 
 /// enum CohesiveMethod type of insertion of cohesive elements
 enum CohesiveMethod { _intrinsic, _extrinsic };
 
 /// @enum SparseMatrixType type of sparse matrix used
 enum MatrixType { _unsymmetric, _symmetric, _mt_not_defined };
 
 /* -------------------------------------------------------------------------- */
 /* Ghosts handling                                                            */
 /* -------------------------------------------------------------------------- */
 /// @enum CommunicatorType type of communication method to use
 enum CommunicatorType { _communicator_mpi, _communicator_dummy };
 
 /// @enum SynchronizationTag type of synchronizations
 enum SynchronizationTag {
   //--- Generic tags ---
   _gst_whatever,
   _gst_update,
   _gst_size,
 
   //--- SolidMechanicsModel tags ---
   _gst_smm_mass,      ///< synchronization of the SolidMechanicsModel.mass
   _gst_smm_for_gradu, ///< synchronization of the
                       /// SolidMechanicsModel.displacement
   _gst_smm_boundary,  ///< synchronization of the boundary, forces, velocities
                       /// and displacement
   _gst_smm_uv,  ///< synchronization of the nodal velocities and displacement
   _gst_smm_res, ///< synchronization of the nodal residual
   _gst_smm_init_mat, ///< synchronization of the data to initialize materials
   _gst_smm_stress,  ///< synchronization of the stresses to compute the internal
                     /// forces
   _gst_smmc_facets, ///< synchronization of facet data to setup facet synch
   _gst_smmc_facets_conn,   ///< synchronization of facet global connectivity
   _gst_smmc_facets_stress, ///< synchronization of facets' stress to setup facet
                            /// synch
   _gst_smmc_damage,        ///< synchronization of damage
 
   // --- GlobalIdsUpdater tags ---
   _gst_giu_global_conn, ///< synchronization of global connectivities
 
   // --- CohesiveElementInserter tags ---
   _gst_ce_groups, ///< synchronization of cohesive element insertion depending
                   /// on facet groups
 
   // --- GroupManager tags ---
   _gst_gm_clusters, ///< synchronization of clusters
 
   // --- HeatTransfer tags ---
   _gst_htm_capacity,             ///< synchronization of the nodal heat capacity
   _gst_htm_temperature,          ///< synchronization of the nodal temperature
   _gst_htm_gradient_temperature, ///< synchronization of the element gradient
                                  /// temperature
   // --- LevelSet tags ---
   _gst_htm_phi,          ///< synchronization of the nodal level set value phi
   _gst_htm_gradient_phi, ///< synchronization of the element gradient phi
 
   //--- Material non local ---
   _gst_mnl_for_average, ///< synchronization of data to average in non local
                         /// material
   _gst_mnl_weight,      ///< synchronization of data for the weight computations
 
   // --- NeighborhoodSynchronization tags ---
   _gst_nh_criterion,
 
   // --- General tags ---
   _gst_test,        ///< Test tag
   _gst_user_1,      ///< tag for user simulations
   _gst_user_2,      ///< tag for user simulations
   _gst_material_id, ///< synchronization of the material ids
   _gst_for_dump,    ///< everything that needs to be synch before dump
 
   // --- Contact & Friction ---
   _gst_cf_nodal, ///< synchronization of disp, velo, and current position
   _gst_cf_incr,  ///< synchronization of increment
 
   // --- Solver tags ---
   _gst_solver_solution ///< synchronization of the solution obained with the
                        /// PETSc solver
 };
 
 /// standard output stream operator for SynchronizationTag
 inline std::ostream & operator<<(std::ostream & stream,
                                  SynchronizationTag type);
 
 /// @enum GhostType type of ghost
 enum GhostType {
   _not_ghost,
   _ghost,
   _casper // not used but a real cute ghost
 };
 
 /* -------------------------------------------------------------------------- */
 struct GhostType_def {
   using type = GhostType;
   static const type _begin_ = _not_ghost;
   static const type _end_ = _casper;
 };
 
 using ghost_type_t = safe_enum<GhostType_def>;
 extern ghost_type_t ghost_types;
 
 /// standard output stream operator for GhostType
 inline std::ostream & operator<<(std::ostream & stream, GhostType type);
 
 /* -------------------------------------------------------------------------- */
 /* Global defines                                                             */
 /* -------------------------------------------------------------------------- */
 #define AKANTU_MIN_ALLOCATION 2000
 
 #define AKANTU_INDENT " "
 #define AKANTU_INCLUDE_INLINE_IMPL
 
 /* -------------------------------------------------------------------------- */
-template<typename T>
-using is_scalar = std::is_arithmetic<T>;
+/* Type traits                                                                */
+/* -------------------------------------------------------------------------- */
+struct TensorTrait {};
+/* -------------------------------------------------------------------------- */
+template <typename T> using is_tensor = std::is_base_of<TensorTrait, T>;
+/* -------------------------------------------------------------------------- */
+template <typename T> using is_scalar = std::is_arithmetic<T>;
+/* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 #define AKANTU_SET_MACRO(name, variable, type)                                 \
   inline void set##name(type variable) { this->variable = variable; }
 
 #define AKANTU_GET_MACRO(name, variable, type)                                 \
   inline type get##name() const { return variable; }
 
 #define AKANTU_GET_MACRO_NOT_CONST(name, variable, type)                       \
   inline type get##name() { return variable; }
 
 #define AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, support, con)   \
   inline con Array<type> & get##name(                                          \
       const support & el_type, const GhostType & ghost_type = _not_ghost)      \
       con {                                                                    \
     return variable(el_type, ghost_type);                                      \
   }
 
 #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE(name, variable, type)                 \
   AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, )
 #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(name, variable, type)           \
   AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, const)
 
 #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE(name, variable, type)               \
   AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, )
 #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE_CONST(name, variable, type)         \
   AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, const)
 
 /* -------------------------------------------------------------------------- */
 /// initialize the static part of akantu
 void initialize(int & argc, char **& argv);
 /// initialize the static part of akantu and read the global input_file
 void initialize(const std::string & input_file, int & argc, char **& argv);
 /* -------------------------------------------------------------------------- */
 /// finilize correctly akantu and clean the memory
 void finalize();
 /* -------------------------------------------------------------------------- */
 /// Read an new input file
 void readInputFile(const std::string & input_file);
 /* -------------------------------------------------------------------------- */
 
 /*
  * For intel compiler annoying remark
  */
 // #if defined(__INTEL_COMPILER)
 // /// remark #981: operands are evaluated in unspecified order
 // #pragma warning(disable : 981)
 // /// remark #383: value copied to temporary, reference to temporary used
 // #pragma warning(disable : 383)
 // #endif // defined(__INTEL_COMPILER)
 
 /* -------------------------------------------------------------------------- */
 /* string manipulation                                                        */
 /* -------------------------------------------------------------------------- */
 inline std::string to_lower(const std::string & str);
 /* -------------------------------------------------------------------------- */
 inline std::string trim(const std::string & to_trim);
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 /// give a string representation of the a human readable size in bit
 template <typename T> std::string printMemorySize(UInt size);
 /* -------------------------------------------------------------------------- */
 
-} // akantu
+} // namespace akantu
 
 #include "aka_fwd.hh"
 
 namespace akantu {
 
 /// get access to the internal argument parser
 cppargparse::ArgumentParser & getStaticArgumentParser();
 
 /// get access to the internal input file parser
 Parser & getStaticParser();
 
 /// get access to the user part of the internal input file parser
 const ParserSection & getUserParser();
 
-} // akantu
+} // namespace akantu
 
 #include "aka_common_inline_impl.cc"
 
 /* -------------------------------------------------------------------------- */
 
 #if AKANTU_INTEGER_SIZE == 4
 #define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b9
 #elif AKANTU_INTEGER_SIZE == 8
 #define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b97f4a7c13LL
 #endif
 
 namespace std {
 /**
  * Hashing function for pairs based on hash_combine from boost The magic number
  * is coming from the golden number @f[\phi = \frac{1 + \sqrt5}{2}@f]
  * @f[\frac{2^32}{\phi} = 0x9e3779b9@f]
  * http://stackoverflow.com/questions/4948780/magic-number-in-boosthash-combine
  * http://burtleburtle.net/bob/hash/doobs.html
  */
-template <typename a, typename b> struct hash<std::pair<a, b> > {
-public:
-  hash() : ah(), bh() {}
+template <typename a, typename b> struct hash<std::pair<a, b>> {
+  hash() = default;
   size_t operator()(const std::pair<a, b> & p) const {
     size_t seed = ah(p.first);
     return bh(p.second) + AKANTU_HASH_COMBINE_MAGIC_NUMBER + (seed << 6) +
            (seed >> 2);
   }
 
 private:
-  const hash<a> ah;
-  const hash<b> bh;
+  const hash<a> ah{};
+  const hash<b> bh{};
 };
 
-} //std
-
+} // namespace std
 
 #endif /* __AKANTU_COMMON_HH__ */
diff --git a/src/common/aka_compatibilty_with_cpp_standard.hh b/src/common/aka_compatibilty_with_cpp_standard.hh
index c3b223671..154f339f1 100644
--- a/src/common/aka_compatibilty_with_cpp_standard.hh
+++ b/src/common/aka_compatibilty_with_cpp_standard.hh
@@ -1,63 +1,132 @@
 /**
  * @file   aka_compatibilty_with_cpp_standard.hh
  *
  * @author Nicolas Richart
  *
  * @date creation  Wed Oct 25 2017
  *
  * @brief The content of this file is taken from the possible implementations on
  * http://en.cppreference.com
  *
  * @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 <type_traits>
+#include <utility>
+#include <tuple>
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH__
 #define __AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH__
 
-namespace std {
+namespace aka {
 
 // Part taken from C++14
 #if __cplusplus < 201402L
 template <bool B, class T = void>
 using enable_if_t = typename enable_if<B, T>::type;
+#else
+template <bool B, class T = void>
+using enable_if_t = std::enable_if_t<B, T>;
 #endif
 
 // Part taken from C++17
 #if __cplusplus < 201703L
 // bool_constant
-template <bool B> using bool_constant = integral_constant<bool, B>;
+template <bool B> using bool_constant = std::integral_constant<bool, B>;
 namespace {
   template <bool B> constexpr bool bool_constant_v = bool_constant<B>::value;
 }
 
 // conjunction
 template <class...> struct conjunction : std::true_type {};
 template <class B1> struct conjunction<B1> : B1 {};
 template <class B1, class... Bn>
 struct conjunction<B1, Bn...>
     : std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
 
-#endif
+namespace detail {
+  // template <class T>
+  // struct is_reference_wrapper : std::false_type {};
+  // template <class U>
+  // struct is_reference_wrapper<std::reference_wrapper<U>> : std::true_type {};
+  // template <class T>
+  // constexpr bool is_reference_wrapper_v = is_reference_wrapper<T>::value;
+
+  template <class T, class Type, class T1, class... Args>
+  decltype(auto) INVOKE(Type T::*f, T1 && t1, Args &&... args) {
+    static_assert(std::is_member_function_pointer<decltype(f)>{} and
+                      std::is_base_of<T, std::decay_t<T1>>{},
+                  "Does not know what to do with this types");
+    return (std::forward<T1>(t1).*f)(std::forward<Args>(args)...);
+  }
+
+  // template <class T, class Type, class T1, class... Args>
+  // decltype(auto) INVOKE(Type T::*f, T1 && t1, Args &&... args) {
+  //   if constexpr (std::is_member_function_pointer_v<decltype(f)>) {
+  //     if constexpr (std::is_base_of_v<T, std::decay_t<T1>>)
+  //       return (std::forward<T1>(t1).*f)(std::forward<Args>(args)...);
+  //     else if constexpr (is_reference_wrapper_v<std::decay_t<T1>>)
+  //       return (t1.get().*f)(std::forward<Args>(args)...);
+  //     else
+  //       return ((*std::forward<T1>(t1)).*f)(std::forward<Args>(args)...);
+  //   } else {
+  //     static_assert(std::is_member_object_pointer_v<decltype(f)>);
+  //     static_assert(sizeof...(args) == 0);
+  //     if constexpr (std::is_base_of_v<T, std::decay_t<T1>>)
+  //       return std::forward<T1>(t1).*f;
+  //     else if constexpr (is_reference_wrapper_v<std::decay_t<T1>>)
+  //       return t1.get().*f;
+  //     else
+  //       return (*std::forward<T1>(t1)).*f;
+  //   }
+  // }
+
+  template <class F, class... Args>
+  decltype(auto) INVOKE(F && f, Args &&... args) {
+    return std::forward<F>(f)(std::forward<Args>(args)...);
+  }
+} // namespace detail
+
+template <class F, class... Args>
+decltype(auto) invoke(F && f, Args &&... args) {
+  return detail::INVOKE(std::forward<F>(f), std::forward<Args>(args)...);
 }
 
+namespace detail {
+  template <class F, class Tuple, std::size_t... Is>
+  constexpr decltype(auto) apply_impl(F && f, Tuple && t,
+                                      std::index_sequence<Is...>) {
+    return invoke(std::forward<F>(f),
+                  std::get<Is>(std::forward<Tuple>(t))...);
+  }
+} // namespace detail
+
+template <class F, class Tuple>
+constexpr decltype(auto) apply(F && f, Tuple && t) {
+  return detail::apply_impl(
+      std::forward<F>(f), std::forward<Tuple>(t),
+      std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{});
+}
+
+#endif
+} // namespace aka
+
 #endif /* __AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH__ */
diff --git a/src/common/aka_iterators.hh b/src/common/aka_iterators.hh
index e5a41ca92..f76cf6214 100644
--- a/src/common/aka_iterators.hh
+++ b/src/common/aka_iterators.hh
@@ -1,326 +1,341 @@
 /**
  * @file   aka_iterators.hh
  *
  * @author Nicolas Richart
  *
  * @date creation  Wed Jul 19 2017
  *
  * @brief iterator interfaces
  *
  * @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_error.hh"
 /* -------------------------------------------------------------------------- */
 #include <cassert>
 #include <iostream>
 #include <tuple>
 #include <utility>
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_AKA_ITERATORS_HH__
 #define __AKANTU_AKA_ITERATORS_HH__
 
 namespace akantu {
 
 namespace tuple {
   /* ------------------------------------------------------------------------ */
   namespace details {
     template <size_t N> struct Foreach {
       template <class F, class Tuple>
       static inline decltype(auto) transform_forward(F && func,
                                                      Tuple && tuple) {
         return std::tuple_cat(
             Foreach<N - 1>::transform_forward(std::forward<F>(func),
                                               std::forward<Tuple>(tuple)),
             std::forward_as_tuple(std::forward<F>(func)(
                 std::get<N - 1>(std::forward<Tuple>(tuple)))));
       }
 
       template <class F, class Tuple>
       static inline decltype(auto) transform(F && func, Tuple && tuple) {
         return std::tuple_cat(
             Foreach<N - 1>::transform(std::forward<F>(func),
                                       std::forward<Tuple>(tuple)),
             std::make_tuple(std::forward<F>(func)(
                 std::get<N - 1>(std::forward<Tuple>(tuple)))));
       }
 
       template <class F, class Tuple>
       static inline void foreach (F && func, Tuple && tuple) {
         Foreach<N - 1>::foreach (std::forward<F>(func),
                                  std::forward<Tuple>(tuple));
         std::forward<F>(func)(std::get<N - 1>(std::forward<Tuple>(tuple)));
       }
 
       template <class Tuple> static inline bool equal(Tuple && a, Tuple && b) {
         if (not(std::get<N - 1>(std::forward<Tuple>(a)) ==
                 std::get<N - 1>(std::forward<Tuple>(b))))
           return false;
         return Foreach<N - 1>::equal(std::forward<Tuple>(a),
                                      std::forward<Tuple>(b));
       }
     };
 
     /* ------------------------------------------------------------------------
      */
     template <> struct Foreach<1> {
       template <class F, class Tuple>
       static inline decltype(auto) transform_forward(F && func,
                                                      Tuple && tuple) {
         return std::forward_as_tuple(
             std::forward<F>(func)(std::get<0>(std::forward<Tuple>(tuple))));
       }
 
       template <class F, class Tuple>
       static inline decltype(auto) transform(F && func, Tuple && tuple) {
         return std::make_tuple(
             std::forward<F>(func)(std::get<0>(std::forward<Tuple>(tuple))));
       }
 
       template <class F, class Tuple>
       static inline void foreach (F && func, Tuple && tuple) {
         std::forward<F>(func)(std::get<0>(std::forward<Tuple>(tuple)));
       }
 
       template <class Tuple> static inline bool equal(Tuple && a, Tuple && b) {
         return std::get<0>(std::forward<Tuple>(a)) ==
                std::get<0>(std::forward<Tuple>(b));
       }
     };
   } // namespace details
   /* ------------------------------------------------------------------------ */
   template <class Tuple> bool are_equal(Tuple && a, Tuple && b) {
     return details::Foreach<std::tuple_size<std::decay_t<Tuple>>::value>::equal(
         std::forward<Tuple>(a), std::forward<Tuple>(b));
   }
 
   template <class F, class Tuple> void foreach (F && func, Tuple && tuple) {
     details::Foreach<std::tuple_size<std::decay_t<Tuple>>::value>::foreach (
         std::forward<F>(func), std::forward<Tuple>(tuple));
   }
 
   template <class F, class Tuple>
   decltype(auto) transform_forward(F && func, Tuple && tuple) {
     return details::Foreach<std::tuple_size<std::decay_t<Tuple>>::value>::
         transform_forward(std::forward<F>(func), std::forward<Tuple>(tuple));
   }
 
   template <class F, class Tuple>
   decltype(auto) transform(F && func, Tuple && tuple) {
     return details::Foreach<std::tuple_size<std::decay_t<Tuple>>::value>::
         transform(std::forward<F>(func), std::forward<Tuple>(tuple));
   }
 } // namespace tuple
 
 namespace iterators {
   namespace details {
     struct dereference_iterator {
       template <class Iter> decltype(auto) operator()(Iter & it) const {
         return std::forward<decltype(*it)>(*it);
       }
     };
 
     struct increment_iterator {
       template <class Iter> void operator()(Iter & it) const { ++it; }
     };
 
     struct begin_container {
       template <class Container>
       decltype(auto) operator()(Container && cont) const {
         return std::forward<Container>(cont).begin();
       }
     };
 
     struct end_container {
       template <class Container>
       decltype(auto) operator()(Container && cont) const {
         return std::forward<Container>(cont).end();
       }
     };
   } // namespace details
 
   /* ------------------------------------------------------------------------ */
   template <class... Iterators> class ZipIterator {
   private:
     using tuple_t = std::tuple<Iterators...>;
 
   public:
     explicit ZipIterator(tuple_t iterators) : iterators(std::move(iterators)) {}
 
     decltype(auto) operator*() {
       return tuple::transform_forward(details::dereference_iterator(),
                                       iterators);
     }
 
     ZipIterator & operator++() {
       tuple::foreach (details::increment_iterator(), iterators);
       return *this;
     }
 
     bool operator==(const ZipIterator & other) const {
       return tuple::are_equal(iterators, other.iterators);
     }
 
     bool operator!=(const ZipIterator & other) const {
       return not operator==(other);
     }
 
   private:
     tuple_t iterators;
   };
 } // namespace iterators
 
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 template <class... Iterators>
 decltype(auto) zip_iterator(std::tuple<Iterators...> && iterators_tuple) {
   auto zip = iterators::ZipIterator<Iterators...>(
       std::forward<decltype(iterators_tuple)>(iterators_tuple));
   return zip;
 }
 
 /* -------------------------------------------------------------------------- */
 namespace containers {
   template <class... Containers> class ZipContainer {
     using containers_t = std::tuple<Containers...>;
 
   public:
     explicit ZipContainer(Containers &&... containers)
         : containers(std::forward<Containers>(containers)...) {}
 
     decltype(auto) begin() const {
       return zip_iterator(
           tuple::transform(iterators::details::begin_container(),
                            std::forward<containers_t>(containers)));
     }
 
     decltype(auto) end() const {
       return zip_iterator(
           tuple::transform(iterators::details::end_container(),
                            std::forward<containers_t>(containers)));
     }
 
     decltype(auto) begin() {
       return zip_iterator(
           tuple::transform(iterators::details::begin_container(),
                            std::forward<containers_t>(containers)));
     }
 
     decltype(auto) end() {
       return zip_iterator(
           tuple::transform(iterators::details::end_container(),
                            std::forward<containers_t>(containers)));
     }
 
   private:
     containers_t containers;
   };
 } // namespace containers
 
 /* -------------------------------------------------------------------------- */
 template <class... Containers> decltype(auto) zip(Containers &&... conts) {
   return containers::ZipContainer<Containers...>(
       std::forward<Containers>(conts)...);
 }
 
 /* -------------------------------------------------------------------------- */
 /* Arange                                                                     */
 /* -------------------------------------------------------------------------- */
 namespace iterators {
   template <class T> class ArangeIterator {
   public:
     using value_type = T;
     using pointer = T *;
     using reference = T &;
     using iterator_category = std::input_iterator_tag;
 
     constexpr ArangeIterator(T value, T step) : value(value), step(step) {}
     constexpr ArangeIterator(const ArangeIterator &) = default;
 
     constexpr ArangeIterator & operator++() {
       value += step;
       return *this;
     }
 
     constexpr const T & operator*() const { return value; }
 
     constexpr bool operator==(const ArangeIterator & other) const {
       return (value == other.value) and (step == other.step);
     }
 
     constexpr bool operator!=(const ArangeIterator & other) const {
       return not operator==(other);
     }
 
   private:
     T value{0};
     const T step{1};
   };
 } // namespace iterators
 
 namespace containers {
   template <class T> class ArangeContainer {
   public:
     using iterator = iterators::ArangeIterator<T>;
 
     constexpr ArangeContainer(T start, T stop, T step = 1)
         : start(start), stop((stop - start) % step == 0
                                  ? stop
                                  : start + (1 + (stop - start) / step) * step),
           step(step) {}
     explicit constexpr ArangeContainer(T stop) : ArangeContainer(0, stop, 1) {}
 
     constexpr T operator[](size_t i) {
       T val = start + i * step;
       assert(val < stop && "i is out of range");
       return val;
     }
 
-    constexpr size_t size() { return (stop - start) / step; }
+    constexpr T size() { return (stop - start) / step; }
 
     constexpr iterator begin() { return iterator(start, step); }
     constexpr iterator end() { return iterator(stop, step); }
 
   private:
     const T start{0}, stop{0}, step{1};
   };
 } // namespace containers
 
-template <class T> inline decltype(auto) arange(T stop) {
+template <class T,
+          typename = std::enable_if_t<std::is_integral<std::decay_t<T>>::value>>
+inline decltype(auto) arange(const T & stop) {
   return containers::ArangeContainer<T>(stop);
 }
 
-template <class T>
-inline constexpr decltype(auto) arange(T start, T stop, T step = 1) {
-  return containers::ArangeContainer<T>(start, stop, step);
+template <class T1, class T2,
+          typename = std::enable_if_t<
+              std::is_integral<std::common_type_t<T1, T2>>::value>>
+inline constexpr decltype(auto) arange(const T1 & start, const T2 & stop) {
+  return containers::ArangeContainer<std::common_type_t<T1, T2>>(start, stop);
 }
 
+template <class T1, class T2, class T3,
+          typename = std::enable_if_t<
+              std::is_integral<std::common_type_t<T1, T2, T3>>::value>>
+inline constexpr decltype(auto) arange(const T1 & start, const T2 & stop,
+                                       const T3 & step) {
+  return containers::ArangeContainer<std::common_type_t<T1, T2, T3>>(
+      start, stop, step);
+}
+
+/* -------------------------------------------------------------------------- */
+
 template <class Container>
 inline constexpr decltype(auto) enumerate(Container && container,
                                           size_t start_ = 0) {
   auto stop = std::forward<Container>(container).size();
   decltype(stop) start = start_;
   return zip(arange(start, stop), std::forward<Container>(container));
 }
 
 } // namespace akantu
 
 #endif /* __AKANTU_AKA_ITERATORS_HH__ */
diff --git a/src/common/aka_safe_enum.hh b/src/common/aka_safe_enum.hh
index 20af59899..b129b7fbd 100644
--- a/src/common/aka_safe_enum.hh
+++ b/src/common/aka_safe_enum.hh
@@ -1,83 +1,86 @@
 /**
  * @file   aka_safe_enum.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Thu Feb 21 2013
  * @date last modification: Sun Oct 19 2014
  *
  * @brief  Safe enums type (see More C++ Idioms/Type Safe Enum on Wikibooks
  * http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Type_Safe_Enum)
  *
  * @section LICENSE
  *
  * Copyright  (©)  2014,  2015 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_AKA_SAFE_ENUM_HH__
 #define __AKANTU_AKA_SAFE_ENUM_HH__
 
 namespace akantu {
 
 /// Safe enumerated type
 template<typename def, typename inner = typename def::type>
 class safe_enum : public def {
   using type = typename def::type;
 
 public:
   explicit safe_enum(type v = def::_end_) : val(v) {}
+  safe_enum(safe_enum && other) = default;
+  safe_enum& operator=(safe_enum && other) = default;
+
   inner underlying() const { return val; }
 
   bool operator == (const safe_enum & s) const { return this->val == s.val; }
   bool operator != (const safe_enum & s) const { return this->val != s.val; }
   bool operator <  (const safe_enum & s) const { return this->val <  s.val; }
   bool operator <= (const safe_enum & s) const { return this->val <= s.val; }
   bool operator >  (const safe_enum & s) const { return this->val >  s.val; }
   bool operator >= (const safe_enum & s) const { return this->val >= s.val; }
 
   operator inner() { return val; };
 
 public:
   // Works only if enumerations are contiguous.
   class iterator {
   public:
     explicit iterator(type v) : it(v) { }
     iterator & operator++() { ++it; return *this; }
     safe_enum operator*() { return safe_enum(static_cast<type>(it)); }
     bool operator!=(iterator const & it) { return it.it != this->it; }
   private:
     int it;
   };
 
   static iterator begin() {
     return iterator(def::_begin_);
   }
 
   static iterator end() {
     return iterator(def::_end_);
   }
 
 protected:
   inner val;
 };
 
 } // akantu
 
 #endif /* __AKANTU_AKA_SAFE_ENUM_HH__ */
diff --git a/src/common/aka_types.hh b/src/common/aka_types.hh
index d8da67f62..bd65ef234 100644
--- a/src/common/aka_types.hh
+++ b/src/common/aka_types.hh
@@ -1,1255 +1,1263 @@
 /**
  * @file   aka_types.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Thu Feb 17 2011
  * @date last modification: Fri Jan 22 2016
  *
  * @brief  description of the "simple" types
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2012, 2014,  2015 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_error.hh"
 #include "aka_fwd.hh"
 #include "aka_math.hh"
 /* -------------------------------------------------------------------------- */
 #include <initializer_list>
 #include <iomanip>
 #include <type_traits>
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_AKA_TYPES_HH__
 #define __AKANTU_AKA_TYPES_HH__
 
 namespace akantu {
 
 enum NormType { L_1 = 1, L_2 = 2, L_inf = UInt(-1) };
 
 /**
  * DimHelper is a class to generalize the setup of a dim array from 3
  * values. This gives a common interface in the TensorStorage class
  * independently of its derived inheritance (Vector, Matrix, Tensor3)
  * @tparam dim
  */
 template <UInt dim> struct DimHelper {
   static inline void setDims(UInt m, UInt n, UInt p, UInt dims[dim]);
 };
 
 /* -------------------------------------------------------------------------- */
 template <> struct DimHelper<1> {
   static inline void setDims(UInt m, __attribute__((unused)) UInt n,
                              __attribute__((unused)) UInt p, UInt dims[1]) {
     dims[0] = m;
   }
 };
 
 /* -------------------------------------------------------------------------- */
 template <> struct DimHelper<2> {
   static inline void setDims(UInt m, UInt n, __attribute__((unused)) UInt p,
                              UInt dims[2]) {
     dims[0] = m;
     dims[1] = n;
   }
 };
 
 /* -------------------------------------------------------------------------- */
 template <> struct DimHelper<3> {
   static inline void setDims(UInt m, UInt n, UInt p, UInt dims[3]) {
     dims[0] = m;
     dims[1] = n;
     dims[2] = p;
   }
 };
 
 /* -------------------------------------------------------------------------- */
 template <typename T, UInt ndim, class RetType> class TensorStorage;
 
 /* -------------------------------------------------------------------------- */
 /* Proxy classes                                                              */
 /* -------------------------------------------------------------------------- */
 namespace tensors {
-template <class A, class B> struct is_copyable {
-  enum : bool { value = false };
-};
+  template <class A, class B> struct is_copyable {
+    enum : bool { value = false };
+  };
 
-template <class A> struct is_copyable<A, A> {
-  enum : bool { value = true };
-};
+  template <class A> struct is_copyable<A, A> {
+    enum : bool { value = true };
+  };
 
-template <class A> struct is_copyable<A, typename A::RetType> {
-  enum : bool { value = true };
-};
+  template <class A> struct is_copyable<A, typename A::RetType> {
+    enum : bool { value = true };
+  };
 
-template <class A> struct is_copyable<A, typename A::RetType::proxy> {
-  enum : bool { value = true };
-};
+  template <class A> struct is_copyable<A, typename A::RetType::proxy> {
+    enum : bool { value = true };
+  };
 
 } // namespace tensors
+
+
 /**
  * @class TensorProxy aka_types.hh
  * @desc The TensorProxy class is a proxy class to the TensorStorage it handles
  * the
  * wrapped case. That is to say if an accessor should give access to a Tensor
  * wrapped on some data, like the Array<T>::iterator they can return a
  * TensorProxy that will be automatically transformed as a TensorStorage wrapped
  * on the same data
  * @tparam T stored type
  * @tparam ndim order of the tensor
  * @tparam RetType real derived type
  */
 template <typename T, UInt ndim, class _RetType> class TensorProxy {
 protected:
   using RetTypeProxy = typename _RetType::proxy;
 
   TensorProxy(T * data, UInt m, UInt n, UInt p) {
     DimHelper<ndim>::setDims(m, n, p, this->n);
     this->values = data;
   }
 
   template <class Other, typename = std::enable_if_t<
                              tensors::is_copyable<TensorProxy, Other>::value>>
   explicit TensorProxy(const Other & other) {
     this->values = other.storage();
     for (UInt i = 0; i < ndim; ++i)
       this->n[i] = other.size(i);
   }
 
 public:
   using RetType = _RetType;
 
-  operator RetType() { return RetType(static_cast<RetTypeProxy &>(*this)); }
+  //operator RetType() { return RetType(static_cast<RetTypeProxy &>(*this)); }
 
   UInt size(UInt i) const {
     AKANTU_DEBUG_ASSERT(i < ndim, "This tensor has only " << ndim
                                                           << " dimensions, not "
                                                           << (i + 1));
     return n[i];
   }
 
   inline UInt size() const {
     UInt _size = 1;
     for (UInt d = 0; d < ndim; ++d)
       _size *= this->n[d];
     return _size;
   }
 
   T * storage() const { return values; }
 
   template <class Other, typename = std::enable_if_t<
                              tensors::is_copyable<TensorProxy, Other>::value>>
   inline TensorProxy & operator=(const Other & other) {
     AKANTU_DEBUG_ASSERT(
         other.size() == this->size(),
         "You are trying to copy two tensors with different sizes");
     memcpy(this->values, other.storage(), this->size() * sizeof(T));
     return *this;
   }
 
   // template <class Other, typename = std::enable_if_t<
   //                          tensors::is_copyable<TensorProxy, Other>::value>>
   // inline TensorProxy & operator=(const Other && other) {
   //   AKANTU_DEBUG_ASSERT(
   //       other.size() == this->size(),
   //       "You are trying to copy two tensors with different sizes");
   //   memcpy(this->values, other.storage(), this->size() * sizeof(T));
   //   return *this;
   // }
 
   template <typename O> inline RetTypeProxy & operator*=(const O & o) {
     RetType(*this) *= o;
     return static_cast<RetTypeProxy &>(*this);
   }
 
   template <typename O> inline RetTypeProxy & operator/=(const O & o) {
     RetType(*this) /= o;
     return static_cast<RetTypeProxy &>(*this);
   }
 
 protected:
   T * values;
   UInt n[ndim];
 };
 
 /* -------------------------------------------------------------------------- */
 template <typename T> class VectorProxy : public TensorProxy<T, 1, Vector<T>> {
   using parent = TensorProxy<T, 1, Vector<T>>;
   using type = Vector<T>;
 
 public:
   VectorProxy(T * data, UInt n) : parent(data, n, 0, 0) {}
   template <class Other> explicit VectorProxy(Other & src) : parent(src) {}
 
   /* ---------------------------------------------------------------------- */
   template <class Other>
   inline VectorProxy<T> & operator=(const Other & other) {
     parent::operator=(other);
     return *this;
   }
 
   // inline VectorProxy<T> & operator=(const VectorProxy && other) {
   //   parent::operator=(other);
   //   return *this;
   // }
 
   /* ------------------------------------------------------------------------ */
   T & operator()(UInt index) { return this->values[index]; };
   const T & operator()(UInt index) const { return this->values[index]; };
 };
 
 template <typename T> class MatrixProxy : public TensorProxy<T, 2, Matrix<T>> {
   using parent = TensorProxy<T, 2, Matrix<T>>;
   using type = Matrix<T>;
 
 public:
   MatrixProxy(T * data, UInt m, UInt n) : parent(data, m, n, 0) {}
   template <class Other> explicit MatrixProxy(Other & src) : parent(src) {}
 
   /* ---------------------------------------------------------------------- */
   template <class Other>
   inline MatrixProxy<T> & operator=(const Other & other) {
     parent::operator=(other);
     return *this;
   }
 };
 
 template <typename T>
 class Tensor3Proxy : public TensorProxy<T, 3, Tensor3<T>> {
   typedef TensorProxy<T, 3, Tensor3<T>> parent;
   using type = Tensor3<T>;
 
 public:
   Tensor3Proxy(T * data, UInt m, UInt n, UInt k) : parent(data, m, n, k) {}
   Tensor3Proxy(const Tensor3Proxy & src) : parent(src) {}
   Tensor3Proxy(const Tensor3<T> & src) : parent(src) {}
 
   /* ---------------------------------------------------------------------- */
   template <class Other>
   inline Tensor3Proxy<T> & operator=(const Other & other) {
     parent::operator=(other);
     return *this;
   }
 };
 
 /* -------------------------------------------------------------------------- */
 /* Tensor base class                                                          */
 /* -------------------------------------------------------------------------- */
-template <typename T, UInt ndim, class RetType> class TensorStorage {
+template <typename T, UInt ndim, class RetType>
+class TensorStorage : public TensorTrait {
 public:
   using value_type = T;
 
+  friend class Array<T>;
 protected:
   template <class TensorType> void copySize(const TensorType & src) {
     for (UInt d = 0; d < ndim; ++d)
       this->n[d] = src.size(d);
     this->_size = src.size();
   }
 
   TensorStorage() : values(nullptr) {
     for (UInt d = 0; d < ndim; ++d)
       this->n[d] = 0;
     _size = 0;
   }
 
   TensorStorage(const TensorProxy<T, ndim, RetType> & proxy) {
     this->copySize(proxy);
     this->values = proxy.storage();
     this->wrapped = true;
   }
 
 protected:
   TensorStorage(const TensorStorage & src) = delete;
 
 public:
   TensorStorage(const TensorStorage & src, bool deep_copy)
       : values(nullptr), wrapped(false) {
     if (deep_copy)
       this->deepCopy(src);
     else
       this->shallowCopy(src);
   }
 
 protected:
   TensorStorage(UInt m, UInt n, UInt p, const T & def) {
+    static_assert(std::is_trivially_constructible<T>{},
+                  "Cannot create a tensor on non trivial types");
     DimHelper<ndim>::setDims(m, n, p, this->n);
 
     this->computeSize();
     this->values = new T[this->_size];
     this->set(def);
     this->wrapped = false;
   }
 
   TensorStorage(T * data, UInt m, UInt n, UInt p) {
     DimHelper<ndim>::setDims(m, n, p, this->n);
 
     this->computeSize();
     this->values = data;
     this->wrapped = true;
   }
 
 public:
   /* ------------------------------------------------------------------------ */
   template <class TensorType> inline void shallowCopy(const TensorType & src) {
     this->copySize(src);
     if (!this->wrapped)
       delete[] this->values;
     this->values = src.storage();
     this->wrapped = true;
   }
 
   /* ------------------------------------------------------------------------ */
   template <class TensorType> inline void deepCopy(const TensorType & src) {
     this->copySize(src);
+
     if (!this->wrapped)
       delete[] this->values;
+
+    static_assert(std::is_trivially_constructible<T>{},
+                  "Cannot create a tensor on non trivial types");
     this->values = new T[this->_size];
+
+    static_assert(std::is_trivially_copyable<T>{},
+                  "Cannot copy a tensor on non trivial types");
     memcpy((void *)this->values, (void *)src.storage(),
            this->_size * sizeof(T));
+
     this->wrapped = false;
   }
 
   virtual ~TensorStorage() {
     if (!this->wrapped)
       delete[] this->values;
   }
 
   /* ------------------------------------------------------------------------ */
   inline TensorStorage & operator=(const TensorStorage & src) {
     return this->operator=(dynamic_cast<RetType &>(src));
   }
 
   /* ------------------------------------------------------------------------ */
   inline TensorStorage & operator=(const RetType & src) {
     if (this != &src) {
       if (this->wrapped) {
+        static_assert(std::is_trivially_copyable<T>{},
+                  "Cannot copy a tensor on non trivial types");
         // this test is not sufficient for Tensor of order higher than 1
         AKANTU_DEBUG_ASSERT(this->_size == src.size(),
                             "Tensors of different size");
         memcpy((void *)this->values, (void *)src.storage(),
                this->_size * sizeof(T));
       } else {
         deepCopy(src);
       }
     }
     return *this;
   }
 
   /* ------------------------------------------------------------------------ */
   template <class R>
   inline RetType & operator+=(const TensorStorage<T, ndim, R> & other) {
     T * a = this->storage();
     T * b = other.storage();
     AKANTU_DEBUG_ASSERT(
         _size == other.size(),
         "The two tensors do not have the same size, they cannot be subtracted");
     for (UInt i = 0; i < _size; ++i)
       *(a++) += *(b++);
     return *(static_cast<RetType *>(this));
   }
 
   /* ------------------------------------------------------------------------ */
   template <class R>
   inline RetType & operator-=(const TensorStorage<T, ndim, R> & other) {
     T * a = this->storage();
     T * b = other.storage();
     AKANTU_DEBUG_ASSERT(
         _size == other.size(),
         "The two tensors do not have the same size, they cannot be subtracted");
     for (UInt i = 0; i < _size; ++i)
       *(a++) -= *(b++);
     return *(static_cast<RetType *>(this));
   }
 
   /* ------------------------------------------------------------------------ */
   inline RetType & operator+=(const T & x) {
     T * a = this->values;
     for (UInt i = 0; i < _size; ++i)
       *(a++) += x;
     return *(static_cast<RetType *>(this));
   }
 
   /* ------------------------------------------------------------------------ */
   inline RetType & operator-=(const T & x) {
     T * a = this->values;
     for (UInt i = 0; i < _size; ++i)
       *(a++) -= x;
     return *(static_cast<RetType *>(this));
   }
 
   /* ------------------------------------------------------------------------ */
   inline RetType & operator*=(const T & x) {
     T * a = this->storage();
     for (UInt i = 0; i < _size; ++i)
       *(a++) *= x;
     return *(static_cast<RetType *>(this));
   }
 
   /* ---------------------------------------------------------------------- */
   inline RetType & operator/=(const T & x) {
     T * a = this->values;
     for (UInt i = 0; i < _size; ++i)
       *(a++) /= x;
     return *(static_cast<RetType *>(this));
   }
 
   /// Y = \alpha X + Y
   inline RetType & aXplusY(const TensorStorage & other, const T & alpha = 1.) {
     AKANTU_DEBUG_ASSERT(
         _size == other.size(),
         "The two tensors do not have the same size, they cannot be subtracted");
 
     Math::aXplusY(this->_size, alpha, other.storage(), this->storage());
     return *(static_cast<RetType *>(this));
   }
 
   /* ------------------------------------------------------------------------ */
   T * storage() const { return values; }
   UInt size() const { return _size; }
   UInt size(UInt i) const {
     AKANTU_DEBUG_ASSERT(i < ndim, "This tensor has only " << ndim
                                                           << " dimensions, not "
                                                           << (i + 1));
     return n[i];
   };
   /* ------------------------------------------------------------------------ */
   inline void clear() { memset(values, 0, _size * sizeof(T)); };
   inline void set(const T & t) { std::fill_n(values, _size, t); };
 
   template <class TensorType> inline void copy(const TensorType & other) {
     AKANTU_DEBUG_ASSERT(
         _size == other.size(),
         "The two tensors do not have the same size, they cannot be copied");
     memcpy(values, other.storage(), _size * sizeof(T));
   }
 
   bool isWrapped() const { return this->wrapped; }
 
 protected:
-  friend class Array<T>;
-
   inline void computeSize() {
     _size = 1;
     for (UInt d = 0; d < ndim; ++d)
       _size *= this->n[d];
   }
 
 protected:
   template <typename R, NormType norm_type> struct NormHelper {
     template <class Ten> static R norm(const Ten & ten) {
       R _norm = 0.;
       R * it = ten.storage();
       R * end = ten.storage() + ten.size();
       for (; it < end; ++it)
         _norm += std::pow(std::abs(*it), norm_type);
       return std::pow(_norm, 1. / norm_type);
     }
   };
 
   template <typename R> struct NormHelper<R, L_1> {
     template <class Ten> static R norm(const Ten & ten) {
       R _norm = 0.;
       R * it = ten.storage();
       R * end = ten.storage() + ten.size();
       for (; it < end; ++it)
         _norm += std::abs(*it);
       return _norm;
     }
   };
 
   template <typename R> struct NormHelper<R, L_2> {
     template <class Ten> static R norm(const Ten & ten) {
       R _norm = 0.;
       R * it = ten.storage();
       R * end = ten.storage() + ten.size();
       for (; it < end; ++it)
         _norm += *it * *it;
       return sqrt(_norm);
     }
   };
 
   template <typename R> struct NormHelper<R, L_inf> {
     template <class Ten> static R norm(const Ten & ten) {
       R _norm = 0.;
       R * it = ten.storage();
       R * end = ten.storage() + ten.size();
       for (; it < end; ++it)
         _norm = std::max(std::abs(*it), _norm);
       return _norm;
     }
   };
 
 public:
   /*----------------------------------------------------------------------- */
   /// "Entrywise" norm norm<L_p> @f[ \|\boldsymbol{T}\|_p = \left(
   /// \sum_i^{n[0]}\sum_j^{n[1]}\sum_k^{n[2]} |T_{ijk}|^p \right)^{\frac{1}{p}}
   /// @f]
   template <NormType norm_type> inline T norm() const {
     return NormHelper<T, norm_type>::norm(*this);
   }
 
 protected:
   UInt n[ndim];
   UInt _size;
   T * values;
   bool wrapped{false};
 };
 
-// template <typename T, UInt ndim, class RetType>
-// inline TensorProxy<T, ndim, RetType>::TensorProxy(
-//     const TensorStorage<T, ndim, RetType> & other) {
-//   this->values = other.storage();
-//   for (UInt i = 0; i < ndim; ++i)
-//     this->n[i] = other.size(i);
-// }
-
 /* -------------------------------------------------------------------------- */
 /* Vector                                                                     */
 /* -------------------------------------------------------------------------- */
 template <typename T> class Vector : public TensorStorage<T, 1, Vector<T>> {
   typedef TensorStorage<T, 1, Vector<T>> parent;
 
 public:
   using value_type = typename parent::value_type;
   using proxy = VectorProxy<T>;
 
 public:
   Vector() : parent() {}
   explicit Vector(UInt n, const T & def = T()) : parent(n, 0, 0, def) {}
   Vector(T * data, UInt n) : parent(data, n, 0, 0) {}
   Vector(const Vector & src, bool deep_copy = true) : parent(src, deep_copy) {}
-  Vector(const VectorProxy<T> & src) : parent(src) {}
+  Vector(const TensorProxy<T, 1, Vector> & src) : parent(src) {}
 
   Vector(std::initializer_list<T> list) : parent(list.size(), 0, 0, T()) {
     UInt i = 0;
     for (auto val : list) {
       operator()(i++) = val;
     }
   }
 
 public:
   ~Vector() override = default;
 
   /* ------------------------------------------------------------------------ */
   inline Vector & operator=(const Vector & src) {
     parent::operator=(src);
     return *this;
   }
 
   /* ------------------------------------------------------------------------ */
   inline T & operator()(UInt i) {
     AKANTU_DEBUG_ASSERT((i < this->n[0]),
                         "Access out of the vector! "
                             << "Index (" << i
                             << ") is out of the vector of size (" << this->n[0]
                             << ")");
     return *(this->values + i);
   }
 
   inline const T & operator()(UInt i) const {
     AKANTU_DEBUG_ASSERT((i < this->n[0]),
                         "Access out of the vector! "
                             << "Index (" << i
                             << ") is out of the vector of size (" << this->n[0]
                             << ")");
     return *(this->values + i);
   }
 
   inline T & operator[](UInt i) { return this->operator()(i); }
   inline const T & operator[](UInt i) const { return this->operator()(i); }
 
   /* ------------------------------------------------------------------------ */
   inline Vector<T> & operator*=(Real x) { return parent::operator*=(x); }
   inline Vector<T> & operator/=(Real x) { return parent::operator/=(x); }
   /* ------------------------------------------------------------------------ */
   inline Vector<T> & operator*=(const Vector<T> & vect) {
     T * a = this->storage();
     T * b = vect.storage();
     for (UInt i = 0; i < this->_size; ++i)
       *(a++) *= *(b++);
     return *this;
   }
 
   /* ------------------------------------------------------------------------ */
   inline Real dot(const Vector<T> & vect) const {
     return Math::vectorDot(this->values, vect.storage(), this->_size);
   }
 
   /* ------------------------------------------------------------------------ */
   inline Real mean() const {
     Real mean = 0;
     T * a = this->storage();
     for (UInt i = 0; i < this->_size; ++i)
       mean += *(a++);
     return mean / this->_size;
   }
 
   /* ------------------------------------------------------------------------ */
   inline Vector & crossProduct(const Vector<T> & v1, const Vector<T> & v2) {
     AKANTU_DEBUG_ASSERT(this->size() == 3,
                         "crossProduct is only defined in 3D (n=" << this->size()
                                                                  << ")");
     AKANTU_DEBUG_ASSERT(
         this->size() == v1.size() && this->size() == v2.size(),
         "crossProduct is not a valid operation non matching size vectors");
     Math::vectorProduct3(v1.storage(), v2.storage(), this->values);
     return *this;
   }
 
   /* ------------------------------------------------------------------------ */
   inline void solve(const Matrix<T> & A, const Vector<T> & b) {
     AKANTU_DEBUG_ASSERT(
         this->size() == A.rows() && this->_size == A.cols(),
         "The size of the solution vector mismatches the size of the matrix");
     AKANTU_DEBUG_ASSERT(
         this->_size == b._size,
         "The rhs vector has a mismatch in size with the matrix");
     Math::solve(this->_size, A.storage(), this->values, b.storage());
   }
 
   /* ------------------------------------------------------------------------ */
   template <bool tr_A>
   inline void mul(const Matrix<T> & A, const Vector<T> & x, Real alpha = 1.0);
   /* ------------------------------------------------------------------------ */
   inline Real norm() const { return parent::template norm<L_2>(); }
 
   template <NormType nt> inline Real norm() const {
     return parent::template norm<nt>();
   }
 
   /* ------------------------------------------------------------------------ */
   inline void normalize() {
     Real n = norm();
     operator/=(n);
   }
 
   /* ------------------------------------------------------------------------ */
   /// norm of (*this - x)
   inline Real distance(const Vector<T> & y) const {
     Real * vx = this->values;
     Real * vy = y.storage();
     Real sum_2 = 0;
     for (UInt i = 0; i < this->_size; ++i, ++vx, ++vy)
       sum_2 += (*vx - *vy) * (*vx - *vy);
     return sqrt(sum_2);
   }
 
   /* ------------------------------------------------------------------------ */
   inline bool equal(const Vector<T> & v,
                     Real tolerance = Math::getTolerance()) const {
     T * a = this->storage();
     T * b = v.storage();
     UInt i = 0;
     while (i < this->_size && (std::abs(*(a++) - *(b++)) < tolerance))
       ++i;
     return i == this->_size;
   }
 
   /* ------------------------------------------------------------------------ */
   inline short compare(const Vector<T> & v,
                        Real tolerance = Math::getTolerance()) const {
     T * a = this->storage();
     T * b = v.storage();
     for (UInt i(0); i < this->_size; ++i, ++a, ++b) {
       if (std::abs(*a - *b) > tolerance)
         return (((*a - *b) > tolerance) ? 1 : -1);
     }
     return 0;
   }
 
   /* ------------------------------------------------------------------------ */
   inline bool operator==(const Vector<T> & v) const { return equal(v); }
   inline bool operator!=(const Vector<T> & v) const { return !operator==(v); }
   inline bool operator<(const Vector<T> & v) const { return compare(v) == -1; }
   inline bool operator>(const Vector<T> & v) const { return compare(v) == 1; }
 
   /* ------------------------------------------------------------------------ */
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const {
     std::string space;
     for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
       ;
 
     stream << "[";
     for (UInt i = 0; i < this->_size; ++i) {
       if (i != 0)
         stream << ", ";
       stream << this->values[i];
     }
     stream << "]";
   }
 
   //  friend class ::akantu::Array<T>;
 };
 
 using RVector = Vector<Real>;
 
 /* ------------------------------------------------------------------------ */
 template <>
 inline bool Vector<UInt>::equal(const Vector<UInt> & v,
                                 __attribute__((unused)) Real tolerance) const {
   UInt * a = this->storage();
   UInt * b = v.storage();
   UInt i = 0;
   while (i < this->_size && (*(a++) == *(b++)))
     ++i;
   return i == this->_size;
 }
 
 /* ------------------------------------------------------------------------ */
 /* Matrix                                                                   */
 /* ------------------------------------------------------------------------ */
 template <typename T> class Matrix : public TensorStorage<T, 2, Matrix<T>> {
   typedef TensorStorage<T, 2, Matrix<T>> parent;
 
 public:
   using value_type = typename parent::value_type;
   using proxy = MatrixProxy<T>;
 
 public:
   Matrix() : parent() {}
   Matrix(UInt m, UInt n, const T & def = T()) : parent(m, n, 0, def) {}
   Matrix(T * data, UInt m, UInt n) : parent(data, m, n, 0) {}
   Matrix(const Matrix & src, bool deep_copy = true) : parent(src, deep_copy) {}
   Matrix(const MatrixProxy<T> & src) : parent(src) {}
   Matrix(std::initializer_list<std::initializer_list<T>> list) {
+    static_assert(std::is_trivially_copyable<T>{},
+                  "Cannot create a tensor on non trivial types");
     std::size_t n = 0;
     std::size_t m = list.size();
     for (auto row : list) {
       n = std::max(n, row.size());
     }
 
     DimHelper<2>::setDims(m, n, 0, this->n);
     this->computeSize();
     this->values = new T[this->_size];
     this->set(0);
 
     UInt i = 0, j = 0;
     for (auto & row : list) {
       for (auto & val : row) {
         at(i, j++) = val;
       }
       ++i;
       j = 0;
     }
   }
 
   virtual ~Matrix() = default;
   /* ------------------------------------------------------------------------ */
   inline Matrix & operator=(const Matrix & src) {
     parent::operator=(src);
     return *this;
   }
 
 public:
   /* ---------------------------------------------------------------------- */
   UInt rows() const { return this->n[0]; }
   UInt cols() const { return this->n[1]; }
 
   /* ---------------------------------------------------------------------- */
   inline T & at(UInt i, UInt j) {
     AKANTU_DEBUG_ASSERT(((i < this->n[0]) && (j < this->n[1])),
                         "Access out of the matrix! "
                             << "Index (" << i << ", " << j
                             << ") is out of the matrix of size (" << this->n[0]
                             << ", " << this->n[1] << ")");
     return *(this->values + i + j * this->n[0]);
   }
 
   inline const T & at(UInt i, UInt j) const {
     AKANTU_DEBUG_ASSERT(((i < this->n[0]) && (j < this->n[1])),
                         "Access out of the matrix! "
                             << "Index (" << i << ", " << j
                             << ") is out of the matrix of size (" << this->n[0]
                             << ", " << this->n[1] << ")");
     return *(this->values + i + j * this->n[0]);
   }
 
   /* ------------------------------------------------------------------------ */
   inline T & operator()(UInt i, UInt j) { return this->at(i, j); }
   inline const T & operator()(UInt i, UInt j) const { return this->at(i, j); }
 
   /// give a line vector wrapped on the column i
   inline VectorProxy<T> operator()(UInt j) {
     AKANTU_DEBUG_ASSERT(j < this->n[1],
                         "Access out of the matrix! "
                             << "You are trying to access the column vector "
                             << j << " in a matrix of size (" << this->n[0]
                             << ", " << this->n[1] << ")");
     return VectorProxy<T>(this->values + j * this->n[0], this->n[0]);
   }
 
   inline const VectorProxy<T> operator()(UInt j) const {
     AKANTU_DEBUG_ASSERT(j < this->n[1],
                         "Access out of the matrix! "
                             << "You are trying to access the column vector "
                             << j << " in a matrix of size (" << this->n[0]
                             << ", " << this->n[1] << ")");
     return VectorProxy<T>(this->values + j * this->n[0], this->n[0]);
   }
 
   inline T & operator[](UInt idx) { return *(this->values + idx); };
   inline const T & operator[](UInt idx) const { return *(this->values + idx); };
 
   /* ---------------------------------------------------------------------- */
   inline Matrix operator*(const Matrix & B) {
     Matrix C(this->rows(), B.cols());
     C.mul<false, false>(*this, B);
     return C;
   }
 
   /* ----------------------------------------------------------------------- */
   inline Matrix & operator*=(const T & x) { return parent::operator*=(x); }
 
   inline Matrix & operator*=(const Matrix & B) {
     Matrix C(*this);
     this->mul<false, false>(C, B);
     return *this;
   }
 
   /* ---------------------------------------------------------------------- */
   template <bool tr_A, bool tr_B>
   inline void mul(const Matrix & A, const Matrix & B, T alpha = 1.0) {
     UInt k = A.cols();
     if (tr_A)
       k = A.rows();
 
 #ifndef AKANTU_NDEBUG
     if (tr_B) {
       AKANTU_DEBUG_ASSERT(k == B.cols(),
                           "matrices to multiply have no fit dimensions");
       AKANTU_DEBUG_ASSERT(this->cols() == B.rows(),
                           "matrices to multiply have no fit dimensions");
     } else {
       AKANTU_DEBUG_ASSERT(k == B.rows(),
                           "matrices to multiply have no fit dimensions");
       AKANTU_DEBUG_ASSERT(this->cols() == B.cols(),
                           "matrices to multiply have no fit dimensions");
     }
     if (tr_A) {
       AKANTU_DEBUG_ASSERT(this->rows() == A.cols(),
                           "matrices to multiply have no fit dimensions");
     } else {
       AKANTU_DEBUG_ASSERT(this->rows() == A.rows(),
                           "matrices to multiply have no fit dimensions");
     }
 #endif // AKANTU_NDEBUG
 
     Math::matMul<tr_A, tr_B>(this->rows(), this->cols(), k, alpha, A.storage(),
                              B.storage(), 0., this->storage());
   }
 
   /* ---------------------------------------------------------------------- */
   inline void outerProduct(const Vector<T> & A, const Vector<T> & B) {
     AKANTU_DEBUG_ASSERT(
         A.size() == this->rows() && B.size() == this->cols(),
         "A and B are not compatible with the size of the matrix");
     for (UInt i = 0; i < this->rows(); ++i) {
       for (UInt j = 0; j < this->cols(); ++j) {
         this->values[i + j * this->rows()] += A[i] * B[j];
       }
     }
   }
 
 private:
   class EigenSorter {
   public:
     EigenSorter(const Vector<T> & eigs) : eigs(eigs) {}
 
     bool operator()(const UInt & a, const UInt & b) const {
       return (eigs(a) > eigs(b));
     }
 
   private:
     const Vector<T> & eigs;
   };
 
 public:
   /* ---------------------------------------------------------------------- */
   inline void eig(Vector<T> & eigenvalues, Matrix<T> & eigenvectors) const {
     AKANTU_DEBUG_ASSERT(this->cols() == this->rows(),
                         "eig is not a valid operation on a rectangular matrix");
     AKANTU_DEBUG_ASSERT(eigenvalues.size() == this->cols(),
                         "eigenvalues should be of size " << this->cols()
                                                          << ".");
 #ifndef AKANTU_NDEBUG
     if (eigenvectors.storage() != NULL)
       AKANTU_DEBUG_ASSERT((eigenvectors.rows() == eigenvectors.cols()) &&
                               (eigenvectors.rows() == this->cols()),
                           "Eigenvectors needs to be a square matrix of size "
                               << this->cols() << " x " << this->cols() << ".");
 #endif
 
     Matrix<T> tmp = *this;
     Vector<T> tmp_eigs(eigenvalues.size());
     Matrix<T> tmp_eig_vects(eigenvectors.rows(), eigenvectors.cols());
 
     if (tmp_eig_vects.rows() == 0 || tmp_eig_vects.cols() == 0)
       Math::matrixEig(tmp.cols(), tmp.storage(), tmp_eigs.storage());
     else
       Math::matrixEig(tmp.cols(), tmp.storage(), tmp_eigs.storage(),
                       tmp_eig_vects.storage());
 
     Vector<UInt> perm(eigenvalues.size());
     for (UInt i = 0; i < perm.size(); ++i)
       perm(i) = i;
 
     std::sort(perm.storage(), perm.storage() + perm.size(),
               EigenSorter(tmp_eigs));
 
     for (UInt i = 0; i < perm.size(); ++i)
       eigenvalues(i) = tmp_eigs(perm(i));
 
     if (tmp_eig_vects.rows() != 0 && tmp_eig_vects.cols() != 0)
       for (UInt i = 0; i < perm.size(); ++i) {
         for (UInt j = 0; j < eigenvectors.rows(); ++j) {
           eigenvectors(j, i) = tmp_eig_vects(j, perm(i));
         }
       }
   }
 
   /* ---------------------------------------------------------------------- */
   inline void eig(Vector<T> & eigenvalues) const {
     Matrix<T> empty;
     eig(eigenvalues, empty);
   }
 
   /* ---------------------------------------------------------------------- */
   inline void eye(T alpha = 1.) {
     AKANTU_DEBUG_ASSERT(this->cols() == this->rows(),
                         "eye is not a valid operation on a rectangular matrix");
     this->clear();
     for (UInt i = 0; i < this->cols(); ++i) {
       this->values[i + i * this->rows()] = alpha;
     }
   }
 
   /* ---------------------------------------------------------------------- */
   static inline Matrix<T> eye(UInt m, T alpha = 1.) {
     Matrix<T> tmp(m, m);
     tmp.eye(alpha);
     return tmp;
   }
 
   /* ---------------------------------------------------------------------- */
   inline T trace() const {
     AKANTU_DEBUG_ASSERT(
         this->cols() == this->rows(),
         "trace is not a valid operation on a rectangular matrix");
     T trace = 0.;
     for (UInt i = 0; i < this->rows(); ++i) {
       trace += this->values[i + i * this->rows()];
     }
     return trace;
   }
 
   /* ---------------------------------------------------------------------- */
   inline Matrix transpose() const {
     Matrix tmp(this->cols(), this->rows());
     for (UInt i = 0; i < this->rows(); ++i) {
       for (UInt j = 0; j < this->cols(); ++j) {
         tmp(j, i) = operator()(i, j);
       }
     }
     return tmp;
   }
 
   /* ---------------------------------------------------------------------- */
   inline void inverse(const Matrix & A) {
     AKANTU_DEBUG_ASSERT(A.cols() == A.rows(),
                         "inv is not a valid operation on a rectangular matrix");
     AKANTU_DEBUG_ASSERT(this->cols() == A.cols(),
                         "the matrix should have the same size as its inverse");
 
     if (this->cols() == 1)
       *this->values = 1. / *A.storage();
     else if (this->cols() == 2)
       Math::inv2(A.storage(), this->values);
     else if (this->cols() == 3)
       Math::inv3(A.storage(), this->values);
     else
       Math::inv(this->cols(), A.storage(), this->values);
   }
 
   /* --------------------------------------------------------------------- */
   inline T det() const {
     AKANTU_DEBUG_ASSERT(this->cols() == this->rows(),
                         "inv is not a valid operation on a rectangular matrix");
     if (this->cols() == 1)
       return *(this->values);
     else if (this->cols() == 2)
       return Math::det2(this->values);
     else if (this->cols() == 3)
       return Math::det3(this->values);
     else
       return Math::det(this->cols(), this->values);
   }
 
   /* --------------------------------------------------------------------- */
   inline T doubleDot(const Matrix<T> & other) const {
     AKANTU_DEBUG_ASSERT(
         this->cols() == this->rows(),
         "doubleDot is not a valid operation on a rectangular matrix");
     if (this->cols() == 1)
       return *(this->values) * *(other.storage());
     else if (this->cols() == 2)
       return Math::matrixDoubleDot22(this->values, other.storage());
     else if (this->cols() == 3)
       return Math::matrixDoubleDot33(this->values, other.storage());
     else
       AKANTU_DEBUG_ERROR("doubleDot is not defined for other spatial dimensions"
                          << " than 1, 2 or 3.");
     return T();
   }
 
   /* ---------------------------------------------------------------------- */
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const {
     std::string space;
     for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
       ;
 
     stream << "[";
     for (UInt i = 0; i < this->n[0]; ++i) {
       if (i != 0)
         stream << ", ";
       stream << "[";
       for (UInt j = 0; j < this->n[1]; ++j) {
         if (j != 0)
           stream << ", ";
         stream << operator()(i, j);
       }
       stream << "]";
     }
     stream << "]";
   };
 };
 
 /* ------------------------------------------------------------------------ */
 template <typename T>
 template <bool tr_A>
 inline void Vector<T>::mul(const Matrix<T> & A, const Vector<T> & x,
                            Real alpha) {
 #ifndef AKANTU_NDEBUG
   UInt n = x.size();
   if (tr_A) {
     AKANTU_DEBUG_ASSERT(n == A.rows(),
                         "matrix and vector to multiply have no fit dimensions");
     AKANTU_DEBUG_ASSERT(this->size() == A.cols(),
                         "matrix and vector to multiply have no fit dimensions");
   } else {
     AKANTU_DEBUG_ASSERT(n == A.cols(),
                         "matrix and vector to multiply have no fit dimensions");
     AKANTU_DEBUG_ASSERT(this->size() == A.rows(),
                         "matrix and vector to multiply have no fit dimensions");
   }
 #endif
   Math::matVectMul<tr_A>(A.rows(), A.cols(), alpha, A.storage(), x.storage(),
                          0., this->storage());
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline std::ostream & operator<<(std::ostream & stream,
                                  const Matrix<T> & _this) {
   _this.printself(stream);
   return stream;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline std::ostream & operator<<(std::ostream & stream,
                                  const Vector<T> & _this) {
   _this.printself(stream);
   return stream;
 }
 
 /* ------------------------------------------------------------------------ */
 /* Tensor3                                                                  */
 /* ------------------------------------------------------------------------ */
 template <typename T> class Tensor3 : public TensorStorage<T, 3, Tensor3<T>> {
   typedef TensorStorage<T, 3, Tensor3<T>> parent;
 
 public:
   using value_type = typename parent::value_type;
   using proxy = Tensor3Proxy<T>;
 
 public:
   Tensor3() : parent(){};
 
   Tensor3(UInt m, UInt n, UInt p, const T & def = T()) : parent(m, n, p, def) {}
 
   Tensor3(T * data, UInt m, UInt n, UInt p) : parent(data, m, n, p) {}
 
   Tensor3(const Tensor3 & src, bool deep_copy = true)
       : parent(src, deep_copy) {}
 
 public:
   /* ------------------------------------------------------------------------ */
   inline Tensor3 & operator=(const Tensor3 & src) {
     parent::operator=(src);
     return *this;
   }
 
   /* ---------------------------------------------------------------------- */
   inline T & operator()(UInt i, UInt j, UInt k) {
     AKANTU_DEBUG_ASSERT(
         (i < this->n[0]) && (j < this->n[1]) && (k < this->n[2]),
         "Access out of the tensor3! "
             << "You are trying to access the element "
             << "(" << i << ", " << j << ", " << k << ") in a tensor of size ("
             << this->n[0] << ", " << this->n[1] << ", " << this->n[2] << ")");
     return *(this->values + (k * this->n[0] + i) * this->n[1] + j);
   }
 
   inline const T & operator()(UInt i, UInt j, UInt k) const {
     AKANTU_DEBUG_ASSERT(
         (i < this->n[0]) && (j < this->n[1]) && (k < this->n[2]),
         "Access out of the tensor3! "
             << "You are trying to access the element "
             << "(" << i << ", " << j << ", " << k << ") in a tensor of size ("
             << this->n[0] << ", " << this->n[1] << ", " << this->n[2] << ")");
     return *(this->values + (k * this->n[0] + i) * this->n[1] + j);
   }
 
   inline MatrixProxy<T> operator()(UInt k) {
     AKANTU_DEBUG_ASSERT((k < this->n[2]),
                         "Access out of the tensor3! "
                             << "You are trying to access the slice " << k
                             << " in a tensor3 of size (" << this->n[0] << ", "
                             << this->n[1] << ", " << this->n[2] << ")");
     return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1],
                           this->n[0], this->n[1]);
   }
 
   inline const MatrixProxy<T> operator()(UInt k) const {
     AKANTU_DEBUG_ASSERT((k < this->n[2]),
                         "Access out of the tensor3! "
                             << "You are trying to access the slice " << k
                             << " in a tensor3 of size (" << this->n[0] << ", "
                             << this->n[1] << ", " << this->n[2] << ")");
     return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1],
                           this->n[0], this->n[1]);
   }
 
   inline MatrixProxy<T> operator[](UInt k) {
     return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1],
                           this->n[0], this->n[1]);
   }
 
   inline const MatrixProxy<T> operator[](UInt k) const {
     return MatrixProxy<T>(this->values + k * this->n[0] * this->n[1],
                           this->n[0], this->n[1]);
   }
 };
 
 /* -------------------------------------------------------------------------- */
 // support operations for the creation of other vectors
 /* -------------------------------------------------------------------------- */
 template <typename T>
 Vector<T> operator*(const T & scalar, const Vector<T> & a) {
   Vector<T> r(a);
   r *= scalar;
   return r;
 }
 
 template <typename T>
 Vector<T> operator*(const Vector<T> & a, const T & scalar) {
   Vector<T> r(a);
   r *= scalar;
   return r;
 }
 
 template <typename T>
 Vector<T> operator/(const Vector<T> & a, const T & scalar) {
   Vector<T> r(a);
   r /= scalar;
   return r;
 }
 
 template <typename T>
 Vector<T> operator*(const Vector<T> & a, const Vector<T> & b) {
   Vector<T> r(a);
   r *= b;
   return r;
 }
 
 template <typename T>
 Vector<T> operator+(const Vector<T> & a, const Vector<T> & b) {
   Vector<T> r(a);
   r += b;
   return r;
 }
 
 template <typename T>
 Vector<T> operator-(const Vector<T> & a, const Vector<T> & b) {
   Vector<T> r(a);
   r -= b;
   return r;
 }
 
 template <typename T>
 Vector<T> operator*(const Matrix<T> & A, const Vector<T> & b) {
   Vector<T> r(b.size());
   r.template mul<false>(A, b);
   return r;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 Matrix<T> operator*(const T & scalar, const Matrix<T> & a) {
   Matrix<T> r(a);
   r *= scalar;
   return r;
 }
 
 template <typename T>
 Matrix<T> operator*(const Matrix<T> & a, const T & scalar) {
   Matrix<T> r(a);
   r *= scalar;
   return r;
 }
 
 template <typename T>
 Matrix<T> operator/(const Matrix<T> & a, const T & scalar) {
   Matrix<T> r(a);
   r /= scalar;
   return r;
 }
 
 template <typename T>
 Matrix<T> operator+(const Matrix<T> & a, const Matrix<T> & b) {
   Matrix<T> r(a);
   r += b;
   return r;
 }
 
 template <typename T>
 Matrix<T> operator-(const Matrix<T> & a, const Matrix<T> & b) {
   Matrix<T> r(a);
   r -= b;
   return r;
 }
 
-} // akantu
+} // namespace akantu
 
 #endif /* __AKANTU_AKA_TYPES_HH__ */