diff --git a/packages/core.cmake b/packages/core.cmake
index 52ad62250..8cab12b7a 100644
--- a/packages/core.cmake
+++ b/packages/core.cmake
@@ -1,442 +1,443 @@
 #===============================================================================
 # @file   core.cmake
 #
 # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
 # @author Nicolas Richart <nicolas.richart@epfl.ch>
 #
 # @date creation: Mon Nov 21 2011
 # @date last modification: Fri Apr 09 2021
 #
 # @brief  package description for core
 #
 #
 # @section LICENSE
 #
 # Copyright (©) 2010-2021 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/>.
 #
 #===============================================================================
 
 
 package_declare(core NOT_OPTIONAL
   DESCRIPTION "core package for Akantu"
   FEATURES_PUBLIC cxx_strong_enums cxx_defaulted_functions
                   cxx_deleted_functions cxx_auto_type cxx_decltype_auto
   FEATURES_PRIVATE cxx_lambdas cxx_nullptr cxx_range_for
                    cxx_delegating_constructors
   DEPENDS INTERFACE akantu_iterators Boost
   )
 
 if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
   package_set_compile_flags(core "-Wall -Wextra -pedantic")
 else()
   package_set_compile_flags(core "-Wall")
 endif()
 
 package_declare_sources(core
   common/aka_array.cc
   common/aka_array.hh
   common/aka_array_filter.hh
   common/aka_array_tmpl.hh
   common/aka_array_printer.hh
   common/aka_bbox.hh
   common/aka_blas_lapack.hh
   common/aka_circular_array.hh
   common/aka_circular_array_inline_impl.hh
   common/aka_common.cc
   common/aka_common.hh
   common/aka_common_inline_impl.hh
   common/aka_csr.hh
   common/aka_element_classes_info_inline_impl.hh
   common/aka_enum_macros.hh
   common/aka_error.cc
   common/aka_error.hh
   common/aka_event_handler_manager.hh
   common/aka_extern.cc
   common/aka_factory.hh
   common/aka_fwd.hh
   common/aka_grid_dynamic.hh
   common/aka_math.cc
   common/aka_math.hh
   common/aka_math_tmpl.hh
   common/aka_named_argument.hh
   common/aka_random_generator.hh
   common/aka_safe_enum.hh
   common/aka_types.hh
   common/aka_voigthelper.hh
   common/aka_voigthelper_tmpl.hh
   common/aka_voigthelper.cc
   common/aka_warning.hh
   common/aka_warning_restore.hh
   
   fe_engine/element_class.hh
   fe_engine/element_class_helper.hh
   fe_engine/element_class_tmpl.hh
   fe_engine/element_classes/element_class_hexahedron_8_inline_impl.hh
   fe_engine/element_classes/element_class_hexahedron_20_inline_impl.hh
   fe_engine/element_classes/element_class_pentahedron_6_inline_impl.hh
   fe_engine/element_classes/element_class_pentahedron_15_inline_impl.hh
   fe_engine/element_classes/element_class_point_1_inline_impl.hh
   fe_engine/element_classes/element_class_quadrangle_4_inline_impl.hh
   fe_engine/element_classes/element_class_quadrangle_8_inline_impl.hh
   fe_engine/element_classes/element_class_segment_2_inline_impl.hh
   fe_engine/element_classes/element_class_segment_3_inline_impl.hh
   fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.hh
   fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.hh
   fe_engine/element_classes/element_class_triangle_3_inline_impl.hh
   fe_engine/element_classes/element_class_triangle_6_inline_impl.hh
   fe_engine/element_type_conversion.hh
 
   fe_engine/fe_engine.cc
   fe_engine/fe_engine.hh
   fe_engine/fe_engine_inline_impl.hh
   fe_engine/fe_engine_template.hh
   fe_engine/fe_engine_template_tmpl_field.hh
   fe_engine/fe_engine_template_tmpl.hh
   fe_engine/geometrical_element_property.hh
   fe_engine/geometrical_element_property.cc
   fe_engine/gauss_integration.cc
   fe_engine/gauss_integration_tmpl.hh
   fe_engine/integrator.hh
   fe_engine/integrator_gauss.hh
   fe_engine/integrator_gauss_inline_impl.hh
   fe_engine/interpolation_element_tmpl.hh
   fe_engine/integration_point.hh
   fe_engine/shape_functions.hh
   fe_engine/shape_functions.cc
   fe_engine/shape_functions_inline_impl.hh
   fe_engine/shape_lagrange_base.cc
   fe_engine/shape_lagrange_base.hh
   fe_engine/shape_lagrange_base_inline_impl.hh
   fe_engine/shape_lagrange.hh
   fe_engine/shape_lagrange_inline_impl.hh
   fe_engine/element.hh
 
   io/dumper/dumpable.hh
   io/dumper/dumpable.cc
   io/dumper/dumpable_dummy.hh
   io/dumper/dumpable_inline_impl.hh
   io/dumper/dumper_field.hh
   io/dumper/dumper_material_padders.hh
   io/dumper/dumper_filtered_connectivity.hh
   io/dumper/dumper_element_partition.hh
 
   io/mesh_io.cc
   io/mesh_io.hh
   io/mesh_io/mesh_io_diana.cc
   io/mesh_io/mesh_io_diana.hh
   io/mesh_io/mesh_io_msh.cc
   io/mesh_io/mesh_io_msh.hh
 
   io/parser/algebraic_parser.hh
   io/parser/input_file_parser.hh
   io/parser/parsable.cc
   io/parser/parsable.hh
   io/parser/parser.cc
   io/parser/parser_real.cc
   io/parser/parser_random.cc
   io/parser/parser_types.cc
   io/parser/parser_input_files.cc
   io/parser/parser.hh
   io/parser/parser_tmpl.hh
   io/parser/parser_grammar_tmpl.hh
   io/parser/cppargparse/cppargparse.hh
   io/parser/cppargparse/cppargparse.cc
   io/parser/cppargparse/cppargparse_tmpl.hh
 
   io/parser/parameter_registry.cc
   io/parser/parameter_registry.hh
   io/parser/parameter_registry_tmpl.hh
 
   mesh/element_group.cc
   mesh/element_group.hh
   mesh/element_group_inline_impl.hh
   mesh/element_type_map.cc
   mesh/element_type_map.hh
   mesh/element_type_map_tmpl.hh
   mesh/element_type_map_filter.hh
   mesh/group_manager.cc
   mesh/group_manager.hh
   mesh/group_manager_inline_impl.hh
   mesh/mesh.cc
   mesh/mesh.hh
   mesh/mesh_periodic.cc
   mesh/mesh_accessor.hh
   mesh/mesh_events.hh
   mesh/mesh_filter.hh
   mesh/mesh_global_data_updater.hh
   mesh/mesh_data.cc
   mesh/mesh_data.hh
   mesh/mesh_data_tmpl.hh
   mesh/mesh_inline_impl.hh
   mesh/node_group.cc
   mesh/node_group.hh
   mesh/node_group_inline_impl.hh
   mesh/mesh_iterators.hh
 
   mesh_utils/mesh_partition.cc
   mesh_utils/mesh_partition.hh
   mesh_utils/mesh_partition/mesh_partition_mesh_data.cc
   mesh_utils/mesh_partition/mesh_partition_mesh_data.hh
   mesh_utils/mesh_partition/mesh_partition_scotch.hh
   mesh_utils/mesh_utils_pbc.cc
   mesh_utils/mesh_utils.cc
   mesh_utils/mesh_utils.hh
   mesh_utils/mesh_utils_distribution.cc
   mesh_utils/mesh_utils_distribution.hh
   mesh_utils/mesh_utils.hh
   mesh_utils/mesh_utils_inline_impl.hh
   mesh_utils/global_ids_updater.hh
   mesh_utils/global_ids_updater.cc
   mesh_utils/global_ids_updater_inline_impl.hh
 
   model/common/boundary_condition/boundary_condition.hh
   model/common/boundary_condition/boundary_condition_functor.hh
   model/common/boundary_condition/boundary_condition_functor_inline_impl.hh
   model/common/boundary_condition/boundary_condition_tmpl.hh
 
   model/common/constitutive_laws/constitutive_law_non_local_interface.hh
   model/common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh
   model/common/constitutive_laws/constitutive_law.hh
+  model/common/constitutive_laws/constitutive_law_selector.hh
   model/common/constitutive_laws/constitutive_law_tmpl.hh
   model/common/constitutive_laws/constitutive_laws_handler.hh
   model/common/constitutive_laws/constitutive_laws_handler_tmpl.hh
   model/common/constitutive_laws/internal_field.hh
   model/common/constitutive_laws/internal_field_tmpl.hh
   model/common/constitutive_laws/random_internal_field.hh
   model/common/constitutive_laws/random_internal_field_tmpl.hh
 
   model/common/non_local_toolbox/neighborhood_base.hh
   model/common/non_local_toolbox/neighborhood_base.cc
   model/common/non_local_toolbox/neighborhood_base_inline_impl.hh
   model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh
   model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc
   model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.hh
   model/common/non_local_toolbox/non_local_manager.hh
   model/common/non_local_toolbox/non_local_manager.cc
   model/common/non_local_toolbox/non_local_manager_inline_impl.hh
   model/common/non_local_toolbox/non_local_manager_callback.hh
   model/common/non_local_toolbox/non_local_neighborhood_base.hh
   model/common/non_local_toolbox/non_local_neighborhood_base.cc
   model/common/non_local_toolbox/non_local_neighborhood.hh
   model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh
   model/common/non_local_toolbox/non_local_neighborhood_inline_impl.hh
   model/common/non_local_toolbox/base_weight_function.hh
   model/common/non_local_toolbox/base_weight_function_inline_impl.hh
 
   model/common/model_solver.cc
   model/common/model_solver.hh
   model/common/solver_callback.hh
   model/common/solver_callback.cc
 
   model/common/dof_manager/dof_manager.cc
   model/common/dof_manager/dof_manager.hh
   model/common/dof_manager/dof_manager_default.cc
   model/common/dof_manager/dof_manager_default.hh
   model/common/dof_manager/dof_manager_default_inline_impl.hh
   model/common/dof_manager/dof_manager_inline_impl.hh
 
   model/common/non_linear_solver/non_linear_solver.cc
   model/common/non_linear_solver/non_linear_solver.hh
   model/common/non_linear_solver/non_linear_solver_default.hh
   model/common/non_linear_solver/non_linear_solver_lumped.cc
   model/common/non_linear_solver/non_linear_solver_lumped.hh
 
   model/common/time_step_solvers/time_step_solver.hh
   model/common/time_step_solvers/time_step_solver.cc
   model/common/time_step_solvers/time_step_solver_default.cc
   model/common/time_step_solvers/time_step_solver_default.hh
   model/common/time_step_solvers/time_step_solver_default_explicit.hh
 
   model/common/integration_scheme/generalized_trapezoidal.cc
   model/common/integration_scheme/generalized_trapezoidal.hh
   model/common/integration_scheme/integration_scheme.cc
   model/common/integration_scheme/integration_scheme.hh
   model/common/integration_scheme/integration_scheme_1st_order.cc
   model/common/integration_scheme/integration_scheme_1st_order.hh
   model/common/integration_scheme/integration_scheme_2nd_order.cc
   model/common/integration_scheme/integration_scheme_2nd_order.hh
   model/common/integration_scheme/newmark-beta.cc
   model/common/integration_scheme/newmark-beta.hh
   model/common/integration_scheme/pseudo_time.cc
   model/common/integration_scheme/pseudo_time.hh
 
   model/model.cc
   model/model.hh
   model/model_inline_impl.hh
   model/model_options.hh
 
   solver/solver_vector.hh
   solver/solver_vector_default.hh
   solver/solver_vector_default_tmpl.hh
   solver/solver_vector_distributed.cc
   solver/solver_vector_distributed.hh
   solver/sparse_matrix.cc
   solver/sparse_matrix.hh
   solver/sparse_matrix_aij.cc
   solver/sparse_matrix_aij.hh
   solver/sparse_matrix_aij_inline_impl.hh
   solver/sparse_matrix_inline_impl.hh
   solver/sparse_solver.cc
   solver/sparse_solver.hh
   solver/sparse_solver_inline_impl.hh
   solver/terms_to_assemble.hh
 
   synchronizer/communication_buffer_inline_impl.hh
   synchronizer/communication_descriptor.hh
   synchronizer/communication_descriptor_tmpl.hh
   synchronizer/communication_request.hh
   synchronizer/communication_tag.hh
   synchronizer/communications.hh
   synchronizer/communications_tmpl.hh
   synchronizer/communicator.cc
   synchronizer/communicator.hh
   synchronizer/communicator_dummy_inline_impl.hh
   synchronizer/communicator_event_handler.hh
   synchronizer/communicator_inline_impl.hh
   synchronizer/data_accessor.cc
   synchronizer/data_accessor.hh
   synchronizer/dof_synchronizer.cc
   synchronizer/dof_synchronizer.hh
   synchronizer/dof_synchronizer_inline_impl.hh
   synchronizer/element_info_per_processor.cc
   synchronizer/element_info_per_processor.hh
   synchronizer/element_info_per_processor_tmpl.hh
   synchronizer/element_synchronizer.cc
   synchronizer/element_synchronizer.hh
   synchronizer/facet_synchronizer.cc
   synchronizer/facet_synchronizer.hh
   synchronizer/facet_synchronizer_inline_impl.hh
   synchronizer/grid_synchronizer.cc
   synchronizer/grid_synchronizer.hh
   synchronizer/grid_synchronizer_tmpl.hh
   synchronizer/master_element_info_per_processor.cc
   synchronizer/node_info_per_processor.cc
   synchronizer/node_info_per_processor.hh
   synchronizer/node_synchronizer.cc
   synchronizer/node_synchronizer.hh
   synchronizer/node_synchronizer_inline_impl.hh
   synchronizer/periodic_node_synchronizer.cc
   synchronizer/periodic_node_synchronizer.hh
   synchronizer/slave_element_info_per_processor.cc
   synchronizer/synchronizer.cc
   synchronizer/synchronizer.hh
   synchronizer/synchronizer_impl.hh
   synchronizer/synchronizer_impl_tmpl.hh
   synchronizer/synchronizer_registry.cc
   synchronizer/synchronizer_registry.hh
   synchronizer/synchronizer_tmpl.hh
   synchronizer/communication_buffer.hh
   )
 
 set(AKANTU_SPIRIT_SOURCES
   io/mesh_io/mesh_io_abaqus.cc
   io/parser/parser_real.cc
   io/parser/parser_random.cc
   io/parser/parser_types.cc
   io/parser/parser_input_files.cc
   PARENT_SCOPE
   )
 
 package_declare_elements(core
   ELEMENT_TYPES
   _point_1
   _segment_2
   _segment_3
   _triangle_3
   _triangle_6
   _quadrangle_4
   _quadrangle_8
   _tetrahedron_4
   _tetrahedron_10
   _pentahedron_6
   _pentahedron_15
   _hexahedron_8
   _hexahedron_20
   KIND regular
   GEOMETRICAL_TYPES
   _gt_point
   _gt_segment_2
   _gt_segment_3
   _gt_triangle_3
   _gt_triangle_6
   _gt_quadrangle_4
   _gt_quadrangle_8
   _gt_tetrahedron_4
   _gt_tetrahedron_10
   _gt_hexahedron_8
   _gt_hexahedron_20
   _gt_pentahedron_6
   _gt_pentahedron_15
   INTERPOLATION_TYPES
   _itp_lagrange_point_1
   _itp_lagrange_segment_2
   _itp_lagrange_segment_3
   _itp_lagrange_triangle_3
   _itp_lagrange_triangle_6
   _itp_lagrange_quadrangle_4
   _itp_serendip_quadrangle_8
   _itp_lagrange_tetrahedron_4
   _itp_lagrange_tetrahedron_10
   _itp_lagrange_hexahedron_8
   _itp_serendip_hexahedron_20
   _itp_lagrange_pentahedron_6
   _itp_lagrange_pentahedron_15
   GEOMETRICAL_SHAPES
   _gst_point
   _gst_triangle
   _gst_square
   _gst_prism
   GAUSS_INTEGRATION_TYPES
   _git_point
   _git_segment
   _git_triangle
   _git_tetrahedron
   _git_pentahedron
   INTERPOLATION_KIND _itk_lagrangian
   FE_ENGINE_LISTS
   gradient_on_integration_points
   interpolate_on_integration_points
   interpolate
   compute_normals_on_integration_points
   inverse_map
   contains
   compute_shapes
   compute_shapes_derivatives
   get_N
   compute_dnds
   compute_d2nds2
   compute_jmat
   get_shapes_derivatives
   lagrange_base
   assemble_fields
   )
 
 find_program(READLINK_COMMAND readlink)
 find_program(ADDR2LINE_COMMAND addr2line)
 find_program(PATCH_COMMAND patch)
 mark_as_advanced(READLINK_COMMAND)
 mark_as_advanced(ADDR2LINE_COMMAND)
 
 package_declare_extra_files_to_package(core
   SOURCES
     common/aka_element_classes_info.hh.in
     common/aka_config.hh.in
   )
 
 if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.9))
   package_set_compile_flags(core CXX "-Wno-undefined-var-template")
 endif()
diff --git a/src/model/common/constitutive_laws/constitutive_law.hh b/src/model/common/constitutive_laws/constitutive_law.hh
index eb931a22a..fd97e75a1 100644
--- a/src/model/common/constitutive_laws/constitutive_law.hh
+++ b/src/model/common/constitutive_laws/constitutive_law.hh
@@ -1,238 +1,262 @@
 /**
  * @file   constitutive_law.hh
  *
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Wed Feb 21 2018
  *
  * @brief  Mother class for all constitutive laws
  *
  *
  * Copyright (©)  2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 #include "data_accessor.hh"
 #include "mesh_events.hh"
 #include "parsable.hh"
 #include "parser.hh"
 /* -------------------------------------------------------------------------- */
 #include "internal_field.hh"
 #include "random_internal_field.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_CONSTITUTIVE_LAW_HH__
 #define __AKANTU_CONSTITUTIVE_LAW_HH__
 
 /* -------------------------------------------------------------------------- */
 namespace akantu {
 
 template <class ConstitutiveLawsHandler_>
 class ConstitutiveLaw : public DataAccessor<Element>,
 			public MeshEventHandler,
 			public Parsable {
 
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   using ConstitutiveLawsHandler = ConstitutiveLawsHandler_;
 
   ConstitutiveLaw(const ConstitutiveLaw & law) = delete;
 
   ConstitutiveLaw & operator=(const ConstitutiveLaw & law) = delete;
 
   /// Initialize constitutive law with defaults
   ConstitutiveLaw(ConstitutiveLawsHandler & handler, const ID & id = "",
                   ElementKind element_kind = _ek_regular);
 
   /// Destructor
   ~ConstitutiveLaw() override;
 
 protected:
   void initialize();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
-  template <typename T, int fps = 0>
-  void registerInternal(InternalField<T> & /*vect*/) {
-    AKANTU_TO_IMPLEMENT();
-  }
+  template <typename T>
+  inline void registerInternal(std::shared_ptr<InternalField<T>> & vect);
 
-  template <typename T, int fps = 0>
-  void unregisterInternal(InternalField<T> & /*vect*/) {
-    AKANTU_TO_IMPLEMENT();
-  }
+  inline void unregisterInternal(const ID & id);
 
   /// initialize the constitutive law computed parameter
   virtual void initConstitutiveLaw();
 
   /// save the internals in the previous_state if needed
   virtual void savePreviousState();
 
   /// restore the internals from previous_state if needed
   virtual void restorePreviousState();
 
   /// add an element to the local mesh filter
   inline UInt addElement(ElementType type, UInt element, GhostType ghost_type);
   inline UInt addElement(const Element & element);
 
   /// add many elements at once
   void addElements(const Array<Element> & elements_to_add);
 
   /// remove many element at once
   void removeElements(const Array<Element> & elements_to_remove);
 
   /// function to print the contain of the class
   void printself(std::ostream & stream, int indent = 0) const override;
 
 protected:
   /// resize the internals arrrays
   virtual void resizeInternals();
 
   /// function called to update the internal parameters when the
   /// modifiable parameters are modified
   virtual void updateInternalParameters() {}
 
   /// converts global element to local element
   inline Element convertToLocalElement(const Element & global_element) const;
   /// converts local element to global element
   inline Element convertToGlobalElement(const Element & local_element) const;
 
 
   /* ------------------------------------------------------------------------ */
   /* DataAccessor inherited members                                           */
   /* ------------------------------------------------------------------------ */
 public:  
   template <typename T>
   inline void packElementDataHelper(const ElementTypeMapArray<T> & data_to_pack,
                                     CommunicationBuffer & buffer,
                                     const Array<Element> & elements,
                                     const ID & fem_id = ID()) const;
 
   template <typename T>
   inline void unpackElementDataHelper(ElementTypeMapArray<T> & data_to_unpack,
                                       CommunicationBuffer & buffer,
                                       const Array<Element> & elements,
                                       const ID & fem_id = ID());
 
 
   /* ------------------------------------------------------------------------ */
   /* MeshEventHandler inherited members                                       */
   /* ------------------------------------------------------------------------ */
 public:
   virtual void
   onNodesAdded(const Array<UInt> & /*unused*/,
 			    const NewNodesEvent & /*unused*/) override{};
   virtual void
   onNodesRemoved(const Array<UInt> & /*unused*/,
 			      const Array<UInt> & /*unused*/,
 			      const RemovedNodesEvent & /*unused*/) override{};
   virtual void
   onElementsChanged(const Array<Element> & /*unused*/,
 				 const Array<Element> & /*unused*/,
 				 const ElementTypeMapArray<UInt> & /*unused*/,
 				 const ChangedElementsEvent & /*unused*/) override{};
   
   virtual void
   onElementsAdded(const Array<Element> & /*unused*/,
                                const NewElementsEvent & /*unused*/);
 
   virtual void
   onElementsRemoved(const Array<Element> & element_list,
                     const ElementTypeMapArray<UInt> & new_numbering,
                     const RemovedElementsEvent & event);
 
 public:
-  template <typename T, int fps = 0>
-  const InternalField<T> & getInternal(const ID & /*id*/) const {
-    AKANTU_TO_IMPLEMENT();
-    return NULL;
+  template <typename T>
+  const InternalField<T> & getInternal(const ID & id) const {
+    auto it = internal_vectors.find(getID() + ":" + id);
+    if (it != internal_vectors.end() and
+        aka::is_of_type<InternalField<T>>(*it->second)) {
+      return aka::as_type<InternalField<T>>(*it->second);
+    }
+
+    AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID()
+                                            << ") does not contain an internal "
+                                            << id << " ("
+                                            << (getID() + ":" + id) << ")");
   }
 
-  template <typename T, int fps = 0>
-  InternalField<T> & getInternal(const ID & /*id*/) {
-    AKANTU_TO_IMPLEMENT();
-    return NULL;
+  template <typename T> InternalField<T> & getInternal(const ID & id) {
+    auto it = internal_vectors.find(getID() + ":" + id);
+    if (it != internal_vectors.end() and
+        aka::is_of_type<InternalField<T>>(*it->second)) {
+      return aka::as_type<InternalField<T>>(*it->second);
+    }
+
+    AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID()
+                                            << ") does not contain an internal "
+                                            << id << " ("
+                                            << (getID() + ":" + id) << ")");
   }
 
-  template <typename T, int fps = 0>
-  inline bool isInternal(const ID & /*id*/,
-                         const ElementKind & /*element_kind*/) const {
-    return false;
+  template <typename T>
+  inline bool isInternal(const ID & id,
+                         const ElementKind & element_kind) const {
+    auto it = internal_vectors.find(this->getID() + ":" + id);
+
+    return (it != internal_vectors.end() and
+            aka::is_of_type<InternalField<T>>(*it->second) and
+            aka::as_type<InternalField<T>>(*it->second).getElementKind() !=
+                element_kind);
   }
 
+  template <typename T>
+  const Array<T> & getArray(const ID & id, ElementType type,
+                            GhostType ghost_type = _not_ghost) const;
+  template <typename T>
+  Array<T> & getArray(const ID & id, ElementType type,
+                      GhostType ghost_type = _not_ghost);
+
   template <typename T> inline void setParam(const ID & param, T value);
   inline const Parameter & getParam(const ID & param) const;
 
   template <typename T>
   void flattenInternal(const std::string & field_id,
                        ElementTypeMapArray<T> & internal_flat,
                        const GhostType ghost_type = _not_ghost,
                        ElementKind element_kind = _ek_not_defined) const;
 
-  /* ------------------------------------------------------------------------ */
-  /* Accessors                                                                */
-  /* ------------------------------------------------------------------------ */
+  /* ------------------------------------------------------------------------
+   */
+  /* Accessors */
+  /* ------------------------------------------------------------------------
+   */
 public:
   AKANTU_GET_MACRO(Name, name, const std::string &);
 
   AKANTU_GET_MACRO(ID, id, const ID &);
 
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt);
 
   template <typename T>
   ElementTypeMap<UInt> getInternalDataPerElem(const ID & id,
                                               ElementKind element_kind) const;
 
 protected:
   bool isInit() const { return is_init; }
 
-  /* ------------------------------------------------------------------------ */
-  /* Class Members                                                            */
-  /* ------------------------------------------------------------------------ */
+  /* ------------------------------------------------------------------------
+   */
+  /* Class Members */
+  /* ------------------------------------------------------------------------
+   */
 private:
   /// boolean to know if the constitutive law has been initialized
   bool is_init{false};
 
-  std::map<ID, InternalField<Real> *> internal_vectors_real;
-  std::map<ID, InternalField<UInt> *> internal_vectors_uint;
-  std::map<ID, InternalField<bool> *> internal_vectors_bool;
+  std::map<ID, std::shared_ptr<InternalFieldBase>> internal_vectors;
 
 protected:
   ID id;
 
   /// constitutive law name
   std::string name;
 
   /// list of element handled by the constitutive law
   ElementTypeMapArray<UInt> element_filter;
 
   // Constitutive law handler for which this is a constitutive law
   ConstitutiveLawsHandler & handler;
 };
 
 } // namespace akantu
 
 #include "constitutive_law_tmpl.hh"
 
 #endif
diff --git a/src/model/common/constitutive_laws/constitutive_law_tmpl.hh b/src/model/common/constitutive_laws/constitutive_law_tmpl.hh
index baf0fb5ed..d39f106b6 100644
--- a/src/model/common/constitutive_laws/constitutive_law_tmpl.hh
+++ b/src/model/common/constitutive_laws/constitutive_law_tmpl.hh
@@ -1,666 +1,467 @@
 /**
  * @file   constitutive_law_tmpl.hh *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Tue Jul 27 2010
  * @date last modification: Wed Feb 21 2018
  *
  * @brief  Implementation of the templated part of the constitutive law class
  *
  *
  * Copyright (©)  2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "constitutive_law.hh"
 #include "constitutive_laws_handler.hh"
+#include "fe_engine.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef AKANTU_CONSTITUTIVE_LAW_TMPL_HH
 #define AKANTU_CONSTITUTIVE_LAW_TMPL_HH
 
 namespace akantu {
 template <class ConstitutiveLawsHandler_>
 ConstitutiveLaw<ConstitutiveLawsHandler_>::ConstitutiveLaw(
     ConstitutiveLawsHandler_ & handler, const ID & id, ElementKind element_kind)
     : Parsable(ParserType::_constitutive_law, id), handler(handler), id(id),
       element_filter("element_filter", id) {
   /// for each connectivity types allocate the element filer array of the
   /// constitutive law
   element_filter.initialize(handler.getMesh(),
                             _spatial_dimension = handler.getSpatialDimension(),
                             _element_kind = element_kind);
 
   this->initialize();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 void ConstitutiveLaw<ConstitutiveLawsHandler_>::initialize() {
   registerParam("name", name, std::string(), _pat_parsable | _pat_readable);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 void ConstitutiveLaw<ConstitutiveLawsHandler_>::initConstitutiveLaw() {
   this->resizeInternals();
 
   this->updateInternalParmaters();
 
   is_init = true;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 void ConstitutiveLaw<ConstitutiveLawsHandler_>::savePreviousState() {
-  for (auto pair : internal_vectors_real) {
+  for (auto pair : internal_vectors) {
     if (pair.second->hasHistory()) {
       pair.second->saveCurrentValues();
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 void ConstitutiveLaw<ConstitutiveLawsHandler_>::restorePreviousState() {
-  for (auto pair : internal_vectors_real) {
+  for (auto pair : internal_vectors) {
     if (pair.second->hasHistory()) {
       pair.second->restorePreviousValues();
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 void ConstitutiveLaw<ConstitutiveLawsHandler_>::resizeInternals() {
-  for (auto it = internal_vectors_real.begin();
-       it != internal_vectors_real.end(); ++it) {
-    it->second->resize();
-  }
-
-  for (auto it = internal_vectors_uint.begin();
-       it != internal_vectors_uint.end(); ++it) {
-    it->second->resize();
-  }
-
-  for (auto it = internal_vectors_bool.begin();
-       it != internal_vectors_bool.end(); ++it) {
-    it->second->resize();
+  for (auto && pair : internal_vectors) {
+    pair.second->resize();
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 void ConstitutiveLaw<ConstitutiveLawsHandler_>::addElements(
     const Array<Element> & elements_to_add) {
   AKANTU_DEBUG_IN();
 
   UInt law_id = handler.getConstitutiveLawIndex(name);
   for (const auto & element : elements_to_add) {
     auto index = this->addElement(element);
     handler.constitutive_law_index(element) = law_id;
     handler.constitutive_law_local_numbering(element) = index;
   }
 
   this->resizeInternals();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 void ConstitutiveLaw<ConstitutiveLawsHandler_>::removeElements(
     const Array<Element> & elements_to_remove) {
   AKANTU_DEBUG_IN();
 
   auto el_begin = elements_to_remove.begin();
   auto el_end = elements_to_remove.end();
 
   if (elements_to_remove.empty()) {
     return;
   }
 
   auto & mesh = handler.getMesh();
 
   ElementTypeMapArray<UInt> constitutive_law_local_new_numbering(
       "remove constitutive law filter elem", id);
 
   constitutive_law_local_new_numbering.initialize(
       mesh, _element_filter = &element_filter, _element_kind = _ek_not_defined,
       _with_nb_element = true);
 
   ElementTypeMapArray<UInt> element_filter_tmp("element_filter_tmp", id);
 
   element_filter_tmp.initialize(mesh, _element_filter = &element_filter,
                                 _element_kind = _ek_not_defined);
 
   ElementTypeMap<UInt> new_ids, element_ids;
 
   for_each_element(
       mesh,
       [&](auto && el) {
         if (not new_ids(el.type, el.ghost_type)) {
           element_ids(el.type, el.ghost_type) = 0;
         }
 
         auto & element_id = element_ids(el.type, el.ghost_type);
         auto l_el = Element{el.type, element_id, el.ghost_type};
         if (std::find(el_begin, el_end, el) != el_end) {
           constitutive_law_local_new_numbering(l_el) = UInt(-1);
           return;
         }
 
         element_filter_tmp(el.type, el.ghost_type).push_back(el.element);
         if (not new_ids(el.type, el.ghost_type)) {
           new_ids(el.type, el.ghost_type) = 0;
         }
 
         auto & new_id = new_ids(el.type, el.ghost_type);
 
         constitutive_law_local_new_numbering(l_el) = new_id;
         handler.constitutive_law_local_numbering(el) = new_id;
 
         ++new_id;
         ++element_id;
       },
       _element_filter = &element_filter, _element_kind = _ek_not_defined);
 
   for (auto ghost_type : ghost_types) {
     for (const auto & type : element_filter.elementTypes(
              _ghost_type = ghost_type, _element_kind = _ek_not_defined)) {
       element_filter(type, ghost_type)
           .copy(element_filter_tmp(type, ghost_type));
     }
   }
 
-  for (auto it = internal_vectors_real.begin();
-       it != internal_vectors_real.end(); ++it) {
-    it->second->removeIntegrationPoints(constitutive_law_local_new_numbering);
-  }
-
-  for (auto it = internal_vectors_uint.begin();
-       it != internal_vectors_uint.end(); ++it) {
-    it->second->removeIntegrationPoints(constitutive_law_local_new_numbering);
-  }
-
-  for (auto it = internal_vectors_bool.begin();
-       it != internal_vectors_bool.end(); ++it) {
-    it->second->removeIntegrationPoints(constitutive_law_local_new_numbering);
+  for (auto && pair : internal_vectors) {
+    pair.second->removeIntegrationPoints(constitutive_law_local_new_numbering);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 void ConstitutiveLaw<ConstitutiveLawsHandler_>::onElementsAdded(
     const Array<Element> & /*unused*/, const NewElementsEvent & /*unused*/) {
   this->resizeInternals();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 void ConstitutiveLaw<ConstitutiveLawsHandler_>::onElementsRemoved(
     const Array<Element> & element_list,
     const ElementTypeMapArray<UInt> & new_numbering,
     const RemovedElementsEvent & /*event*/) {
 
   UInt my_num = handler.getInternalIndexFromID(getID());
 
   ElementTypeMapArray<UInt> constitutive_law_local_new_numbering(
       "remove constitutive law filter elem", getID());
 
   auto el_begin = element_list.begin();
   auto el_end = element_list.end();
 
   for (auto && gt : ghost_types) {
     for (auto && type :
          new_numbering.elementTypes(_all_dimensions, gt, _ek_not_defined)) {
 
       if (not element_filter.exists(type, gt) ||
           element_filter(type, gt).empty()) {
         continue;
       }
 
       auto & elem_filter = element_filter(type, gt);
       auto & law_indexes = this->handler.constitutive_law_index(type, gt);
       auto & law_loc_num =
           this->handler.constitutive_law_local_numbering(type, gt);
       auto nb_element = this->handler.getMesh().getNbElement(type, gt);
 
       // all constitutive laws will resized to the same size...
       law_indexes.resize(nb_element);
       law_loc_num.resize(nb_element);
 
       if (!constitutive_law_local_new_numbering.exists(type, gt)) {
         constitutive_law_local_new_numbering.alloc(elem_filter.size(), 1, type,
                                                    gt);
       }
 
       auto & law_renumbering = constitutive_law_local_new_numbering(type, gt);
       const auto & renumbering = new_numbering(type, gt);
       Array<UInt> elem_filter_tmp;
       UInt ni = 0;
       Element el{type, 0, gt};
 
       for (UInt i = 0; i < elem_filter.size(); ++i) {
         el.element = elem_filter(i);
         if (std::find(el_begin, el_end, el) == el_end) {
           UInt new_el = renumbering(el.element);
           AKANTU_DEBUG_ASSERT(new_el != UInt(-1),
                               "A not removed element as been badly renumbered");
           elem_filter_tmp.push_back(new_el);
           law_renumbering(i) = ni;
 
           law_indexes(new_el) = my_num;
           law_loc_num(new_el) = ni;
           ++ni;
         } else {
           law_renumbering(i) = UInt(-1);
         }
       }
 
       elem_filter.resize(elem_filter_tmp.size());
       elem_filter.copy(elem_filter_tmp);
     }
   }
 
-  for (auto it = internal_vectors_real.begin();
-       it != internal_vectors_real.end(); ++it) {
-    it->second->removeIntegrationPoints(constitutive_law_local_new_numbering);
-  }
-
-  for (auto it = internal_vectors_uint.begin();
-       it != internal_vectors_uint.end(); ++it) {
-    it->second->removeIntegrationPoints(constitutive_law_local_new_numbering);
-  }
-
-  for (auto it = internal_vectors_bool.begin();
-       it != internal_vectors_bool.end(); ++it) {
-    it->second->removeIntegrationPoints(constitutive_law_local_new_numbering);
+  for (auto pair : internal_vectors) {
+    pair.second->removeIntegrationPoints(constitutive_law_local_new_numbering);
   }
 }
 
-
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 template <typename T>
 inline void ConstitutiveLaw<ConstitutiveLawsHandler_>::packElementDataHelper(
     const ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer,
     const Array<Element> & elements, const ID & fem_id) const {
   DataAccessor::packElementalDataHelper<T>(data_to_pack, buffer, elements, true,
                                            handler.getFEEngine(fem_id));
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 template <typename T>
 inline void ConstitutiveLaw<ConstitutiveLawsHandler_>::unpackElementDataHelper(
     ElementTypeMapArray<T> & data_to_unpack, CommunicationBuffer & buffer,
     const Array<Element> & elements, const ID & fem_id) {
   DataAccessor::unpackElementalDataHelper<T>(data_to_unpack, buffer, elements,
                                              true, handler.getFEEngine(fem_id));
-}  
-
+}
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
-inline Element
-ConstitutiveLaw<ConstitutiveLawsHandler_>::convertToLocalElement(const Element & global_element) const {
+inline Element ConstitutiveLaw<ConstitutiveLawsHandler_>::convertToLocalElement(
+    const Element & global_element) const {
   UInt ge = global_element.element;
 #ifndef AKANTU_NDEBUG
   UInt model_law_index = handler.getConstitutiveLawByElement(
       global_element.type, global_element.ghost_type)(ge);
 
   UInt law_index = handler.getConstitutiveLawIndex(this->name);
   AKANTU_DEBUG_ASSERT(model_law_index == law_index,
                       "Conversion of a global  element in a local element for "
                       "the wrong constitutive law "
                           << this->name << std::endl);
 #endif
   UInt le = handler.getConstitutiveLawLocalNumbering(
       global_element.type, global_element.ghost_type)(ge);
 
   Element tmp_quad{global_element.type, le, global_element.ghost_type};
   return tmp_quad;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 inline Element
-ConstitutiveLaw<ConstitutiveLawsHandler_>::convertToGlobalElement(const Element & local_element) const {
+ConstitutiveLaw<ConstitutiveLawsHandler_>::convertToGlobalElement(
+    const Element & local_element) const {
   UInt le = local_element.element;
   UInt ge =
       this->element_filter(local_element.type, local_element.ghost_type)(le);
 
   Element tmp_quad{local_element.type, ge, local_element.ghost_type};
   return tmp_quad;
 }
-  
-  
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 inline UInt ConstitutiveLaw<ConstitutiveLawsHandler_>::addElement(
     ElementType type, UInt element, GhostType ghost_type) {
   Array<UInt> & el_filter = this->element_filter(type, ghost_type);
   el_filter.push_back(element);
   return el_filter.size() - 1;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 inline UInt
 ConstitutiveLaw<ConstitutiveLawsHandler_>::addElement(const Element & element) {
   return this->addElement(element.type, element.element, element.ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 inline const Parameter &
 ConstitutiveLaw<ConstitutiveLawsHandler_>::getParam(const ID & param) const {
   try {
     return get(param);
   } catch (...) {
     AKANTU_EXCEPTION("No parameter " << param << " in the constitutive law"
                                      << getID());
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
 template <typename T>
 inline void
 ConstitutiveLaw<ConstitutiveLawsHandler_>::setParam(const ID & param, T value) {
   try {
     set<T>(param, value);
   } catch (...) {
     AKANTU_EXCEPTION("No parameter " << param << " in the constitutive law "
                                      << getID());
   }
   updateInternalParameters();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
-template <int fps>
-inline void
-ConstitutiveLaw<ConstitutiveLawsHandler_>::registerInternal<Real, fps>(
-    InternalField<Real> & vect) {
-  internal_vectors_real[vect.getID()] = &vect;
-}
-
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-inline void
-ConstitutiveLaw<ConstitutiveLawsHandler_>::registerInternal<UInt, fps>(
-    InternalField<UInt> & vect) {
-  internal_vectors_uint[vect.getID()] = &vect;
-}
-
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-inline void
-ConstitutiveLaw<ConstitutiveLawsHandler_>::registerInternal<bool, fps>(
-    InternalField<bool> & vect) {
-  internal_vectors_bool[vect.getID()] = &vect;
+template <typename T>
+inline void ConstitutiveLaw<ConstitutiveLawsHandler_>::registerInternal(
+    std::shared_ptr<InternalField<T>> & vect) {
+  internal_vectors[vect.getID()] = vect;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
-template <int fps>
 inline void
-ConstitutiveLaw<ConstitutiveLawsHandler_>::unregisterInternal<Real, fps>(
-    InternalField<Real> & vect) {
-  internal_vectors_real.erase(vect.getID());
-}
-
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-inline void
-ConstitutiveLaw<ConstitutiveLawsHandler_>::unregisterInternal<UInt, fps>(
-    InternalField<UInt> & vect) {
-  internal_vectors_uint.erase(vect.getID());
-}
-
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-inline void
-ConstitutiveLaw<ConstitutiveLawsHandler_>::unregisterInternal<bool, fps>(
-    InternalField<bool> & vect) {
-  internal_vectors_bool.erase(vect.getID());
-}
-
-/* -------------------------------------------------------------------------- */
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-const InternalField<Real> &
-ConstituitveLaw<ConstitutiveLawsHandler_>::getInternal<Real, fps>(
-    const ID & int_id) const {
-  auto it = internal_vectors_real.find(getID() + ":" + int_id);
-  if (it == internal_vectors_real.end()) {
-    AKANTU_SILENT_EXCEPTION("The constitutive law " << name << "(" << getID()
-                                            << ") does not contain an internal "
-                                            << int_id << " ("
-                                            << (getID() + ":" + int_id) << ")");
-  }
-  return *it->second;
-}
-
-/* -------------------------------------------------------------------------- */
-template <class ConstitutiveLawsHandler_>
-template <>
-InternalField<Real, fps> &
-ConstituitveLaw<ConstitutiveLawsHandler_>::getInternal<Real, fps>(
-    const ID & int_id) {
-  auto it = internal_vectors_real.find(getID() + ":" + int_id);
-  if (it == internal_vectors_real.end()) {
-    AKANTU_SILENT_EXCEPTION("The constitutive law " << name << "(" << getID()
-                                            << ") does not contain an internal "
-                                            << int_id << " ("
-                                            << (getID() + ":" + int_id) << ")");
-  }
-  return *it->second;
-}
-
-/* -------------------------------------------------------------------------- */
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-const InternalField<UInt> &
-ConstituitveLaw<ConstitutiveLawsHandler_>::getInternal<UInt, fps>(
-    const ID & int_id) const {
-  auto it = internal_vectors_uint.find(getID() + ":" + int_id);
-  if (it == internal_vectors_uint.end()) {
-    AKANTU_SILENT_EXCEPTION("The constitutive law " << name << "(" << getID()
-                                            << ") does not contain an internal "
-                                            << int_id << " ("
-                                            << (getID() + ":" + int_id) << ")");
-  }
-  return *it->second;
-}
-
-/* -------------------------------------------------------------------------- */
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-InternalField<UInt> &
-ConstituitveLaw<ConstitutiveLawsHandler_>::getInternal<UInt, fps>(
-    const ID & int_id) {
-  auto it = internal_vectors_uint.find(getID() + ":" + int_id);
-  if (it == internal_vectors_uint.end()) {
-    AKANTU_SILENT_EXCEPTION("The constitutive law " << name << "(" << getID()
-                                            << ") does not contain an internal "
-                                            << int_id << " ("
-                                            << (getID() + ":" + int_id) << ")");
-  }
-  return *it->second;
-}
-
-/* -------------------------------------------------------------------------- */
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-const InternalField<bool> &
-ConstituitveLaw<ConstitutiveLawsHandler_>::getInternal<bool, fps>(
-    const ID & int_id) const {
-  auto it = internal_vectors_bool.find(getID() + ":" + int_id);
-  if (it == internal_vectors_bool.end()) {
-    AKANTU_SILENT_EXCEPTION("The constitutive law " << name << "(" << getID()
-                                            << ") does not contain an internal "
-                                            << int_id << " ("
-                                            << (getID() + ":" + int_id) << ")");
-  }
-  return *it->second;
-}
-
-/* -------------------------------------------------------------------------- */
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-InternalField<bool> &
-ConstituitveLaw<ConstitutiveLawsHandler_>::getInternal<bool, fps>(
-    const ID & int_id) {
-  auto it = internal_vectors_bool.find(getID() + ":" + int_id);
-  if (it == internal_vectors_bool.end()) {
-    AKANTU_SILENT_EXCEPTION("The constitutive law " << name << "(" << getID()
-                                            << ") does not contain an internal "
-                                            << int_id << " ("
-                                            << (getID() + ":" + int_id) << ")");
-  }
-  return *it->second;
-}
-
-/* -------------------------------------------------------------------------- */
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-inline bool ConstitutiveLaw<ConstitutiveLawsHandler_>::isInternal<Real, fps>(
-    const ID & id, ElementKind element_kind) const {
-  auto internal_array = internal_vectors_real.find(this->getID() + ":" + id);
-
-  return not(internal_array == internal_vectors_real.end() ||
-             internal_array->second->getElementKind() != element_kind);
-}
-
-/* -------------------------------------------------------------------------- */
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-inline bool ConstitutiveLaw<ConstitutiveLawsHandler_>::isInternal<UInt, fps>(
-    const ID & id, ElementKind element_kind) const {
-  auto internal_array = internal_vectors_uint.find(this->getID() + ":" + id);
-
-  return not(internal_array == internal_vectors_uint.end() ||
-             internal_array->second->getElementKind() != element_kind);
-}
-
-/* -------------------------------------------------------------------------- */
-template <class ConstitutiveLawsHandler_>
-template <int fps>
-inline bool ConstitutiveLaw<ConstitutiveLawsHandler_>::isInternal<bool, fps>(
-    const ID & id, ElementKind element_kind) const {
-  auto internal_array = internal_vectors_bool.find(this->getID() + ":" + id);
-
-  return not(internal_array == internal_vectors_bool.end() ||
-             internal_array->second->getElementKind() != element_kind);
+ConstitutiveLaw<ConstitutiveLawsHandler_>::unregisterInternal(const ID & id) {
+  internal_vectors.erase(id);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
+template <typename T>
 inline ElementTypeMap<UInt>
 ConstitutiveLaw<ConstitutiveLawsHandler_>::getInternalDataPerElem(
     const ID & field_id, ElementKind element_kind) const {
 
-  if (!this->template isInternal<T>(field_id, element_kind)) {
+  if (not this->template isInternal<T>(field_id, element_kind)) {
     AKANTU_EXCEPTION("Cannot find internal field "
                      << id << " in the constitutive law " << this->name);
   }
 
-  const InternalField<T> & internal_field =
-      this->template getInternal<T>(field_id);
+  const auto & internal_field = this->template getInternal<T>(field_id);
   const FEEngine & fe_engine = internal_field.getFEEngine();
   UInt nb_data_per_quad = internal_field.getNbComponent();
 
   ElementTypeMap<UInt> res;
   for (auto ghost_type : ghost_types) {
     for (auto & type : internal_field.elementTypes(ghost_type)) {
       UInt nb_quadrature_points =
           fe_engine.getNbIntegrationPoints(type, ghost_type);
       res(type, ghost_type) = nb_data_per_quad * nb_quadrature_points;
     }
   }
 
   return res;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class ConstitutiveLawsHandler_>
+template <typename T>
 void ConstitutiveLaw<ConstitutiveLawsHandler_>::flattenInternal(
     const std::string & field_id, ElementTypeMapArray<T> & internal_flat,
     const GhostType ghost_type, ElementKind element_kind) const {
 
   if (!this->template isInternal<T>(field_id, element_kind)) {
     AKANTU_EXCEPTION("Cannot find internal field "
                      << id << " in the constitutive law " << this->name);
   }
 
   const InternalField<T> & internal_field =
       this->template getInternal<T>(field_id);
 
   const FEEngine & fe_engine = internal_field.getFEEngine();
   const Mesh & mesh = fe_engine.getMesh();
 
   for (auto && type : internal_field.filterTypes(ghost_type)) {
     const Array<Real> & src_vect = internal_field(type, ghost_type);
     const Array<UInt> & filter = internal_field.getFilter(type, ghost_type);
 
     // total number of elements in the corresponding mesh
     UInt nb_element_dst = mesh.getNbElement(type, ghost_type);
     // number of element in the internal field
     UInt nb_element_src = filter.size();
     // number of quadrature points per elem
     UInt nb_quad_per_elem = fe_engine.getNbIntegrationPoints(type);
     // number of data per quadrature point
     UInt nb_data_per_quad = internal_field.getNbComponent();
 
     if (!internal_flat.exists(type, ghost_type)) {
       internal_flat.alloc(nb_element_dst * nb_quad_per_elem, nb_data_per_quad,
                           type, ghost_type);
     }
 
     if (nb_element_src == 0) {
       continue;
     }
 
     // number of data per element
     UInt nb_data = nb_quad_per_elem * nb_data_per_quad;
 
     Array<Real> & dst_vect = internal_flat(type, ghost_type);
     dst_vect.resize(nb_element_dst * nb_quad_per_elem);
 
     auto it_dst = make_view(dst_vect, nb_data).begin();
 
     for (auto && data : zip(filter, make_view(src_vect, nb_data))) {
       it_dst[std::get<0>(data)] = std::get<1>(data);
     }
   }
 }
 
-
 } // namespace akantu
 
 #endif // AKANTU_CONSTITUTIVE_LAW_TMPL_HH
diff --git a/src/model/common/constitutive_laws/internal_field.hh b/src/model/common/constitutive_laws/internal_field.hh
index 8632a87a0..a8f5c1a89 100644
--- a/src/model/common/constitutive_laws/internal_field.hh
+++ b/src/model/common/constitutive_laws/internal_field.hh
@@ -1,252 +1,277 @@
 /**
  * @file   internal_field.hh
  *
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Fri Mar 26 2021
  *
  * @brief  Constitutive law internal properties
  *
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free software: you can redistribute it and/or modify it under the
  * terms of the GNU Lesser General Public License as published by the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  * details.
  *
  * You should have received a copy of the GNU Lesser General Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "element_type_map.hh"
 /* -------------------------------------------------------------------------- */
+#include <memory>
+/* -------------------------------------------------------------------------- */
 
 #ifndef AKANTU_INTERNAL_FIELD_HH_
 #define AKANTU_INTERNAL_FIELD_HH_
 
 namespace akantu {
 
 class ConstitutiveLaw;
 class FEEngine;
 
+class InternalFieldBase
+    : public std::enable_shared_from_this<InternalFieldBase> {
+public:
+  /// activate the history of this field
+  virtual void initializeHistory() = 0;
+
+  /// resize the arrays and set the new element to 0
+  virtual void resize() = 0;
+
+  /// save the current values in the history
+  virtual void saveCurrentValues() = 0;
+
+  /// restore the previous values from the history
+  virtual void restorePreviousValues() = 0;
+
+  /// remove the quadrature points corresponding to suppressed elements
+  virtual void
+  removeIntegrationPoints(const ElementTypeMapArray<UInt> & new_numbering) = 0;
+
+  virtual bool hasHistory() const = 0;
+};
+
 /**
  * class for the internal fields of constitutive law
  * to store values for each quadrature
  */
 template <class ConstitutiveLaw_, typename T>
-class InternalFieldTmpl : public ElementTypeMapArray<T> {
+class InternalFieldTmpl : public InternalFieldBase,
+                          public ElementTypeMapArray<T> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   using ConstitutiveLaw = ConstitutiveLaw_;
 
   InternalFieldTmpl(const ID & id, ConstitutiveLaw & constitutive_law);
   ~InternalFieldTmpl() override;
 
   /// This constructor is only here to let cohesive elements compile
   InternalFieldTmpl(const ID & id, ConstitutiveLaw & constitutive_law,
                     FEEngine & fem,
                     const ElementTypeMapArray<UInt> & element_filter);
 
   /// More general constructor
   InternalFieldTmpl(const ID & id, ConstitutiveLaw & constitutive_law, UInt dim,
                     FEEngine & fem,
                     const ElementTypeMapArray<UInt> & element_filter);
 
   InternalFieldTmpl(const ID & id,
                     const InternalFieldTmpl<ConstitutiveLaw_, T> & other);
 
   InternalFieldTmpl operator=(const InternalFieldTmpl &) = delete;
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// function to reset the FEEngine for the internal fieldx
   virtual void setFEEngine(FEEngine & fe_engine);
 
   /// function to reset the element kind for the internal
   virtual void setElementKind(ElementKind element_kind);
 
   /// initialize the field to a given number of component
   virtual void initialize(UInt nb_component);
 
   /// activate the history of this field
-  virtual void initializeHistory();
+  void initializeHistory() override;
 
   /// resize the arrays and set the new element to 0
-  virtual void resize();
+  void resize() override;
 
   /// set the field to a given value v
   virtual void setDefaultValue(const T & v);
 
   /// reset all the fields to the default value
   virtual void reset();
 
   /// save the current values in the history
-  virtual void saveCurrentValues();
+  void saveCurrentValues() override;
 
   /// restore the previous values from the history
-  virtual void restorePreviousValues();
+  void restorePreviousValues() override;
 
   /// remove the quadrature points corresponding to suppressed elements
-  virtual void
-  removeIntegrationPoints(const ElementTypeMapArray<UInt> & new_numbering);
+  void removeIntegrationPoints(
+      const ElementTypeMapArray<UInt> & new_numbering) override;
 
   /// print the content
   void printself(std::ostream & stream, int /*indent*/ = 0) const override;
 
   /// get the default value
   inline operator T() const;
 
   virtual FEEngine & getFEEngine() { return *fem; }
 
   virtual const FEEngine & getFEEngine() const { return *fem; }
 
 protected:
   /// initialize the arrays in the ElementTypeMapArray<T>
   void internalInitialize(UInt nb_component);
 
   /// set the values for new internals
   virtual void setArrayValues(T * begin, T * end);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// get filter types for range loop
   decltype(auto) elementTypes(GhostType ghost_type = _not_ghost) const {
     return ElementTypeMapArray<T>::elementTypes(
         _spatial_dimension = this->spatial_dimension,
         _element_kind = this->element_kind, _ghost_type = ghost_type);
   }
 
   /// get filter types for range loop
   decltype(auto) filterTypes(GhostType ghost_type = _not_ghost) const {
     return this->element_filter.elementTypes(
         _spatial_dimension = this->spatial_dimension,
         _element_kind = this->element_kind, _ghost_type = ghost_type);
   }
 
   /// get the array for a given type of the element_filter
   const Array<UInt> & getFilter(ElementType type,
                                 GhostType ghost_type = _not_ghost) const {
     return this->element_filter(type, ghost_type);
   }
 
   /// get the Array corresponding to the type en ghost_type specified
   virtual Array<T> & operator()(ElementType type,
                                 GhostType ghost_type = _not_ghost) {
     return ElementTypeMapArray<T>::operator()(type, ghost_type);
   }
 
   virtual const Array<T> & operator()(ElementType type,
                                       GhostType ghost_type = _not_ghost) const {
     return ElementTypeMapArray<T>::operator()(type, ghost_type);
   }
 
   virtual Array<T> & previous(ElementType type,
                               GhostType ghost_type = _not_ghost) {
     AKANTU_DEBUG_ASSERT(previous_values != nullptr,
                         "The history of the internal "
                             << this->getID() << " has not been activated");
     return this->previous_values->operator()(type, ghost_type);
   }
 
   virtual const Array<T> & previous(ElementType type,
                                     GhostType ghost_type = _not_ghost) const {
     AKANTU_DEBUG_ASSERT(previous_values != nullptr,
                         "The history of the internal "
                             << this->getID() << " has not been activated");
     return this->previous_values->operator()(type, ghost_type);
   }
 
   virtual InternalFieldTmpl<ConstitutiveLaw_, T> & previous() {
     AKANTU_DEBUG_ASSERT(previous_values != nullptr,
                         "The history of the internal "
                             << this->getID() << " has not been activated");
     return *(this->previous_values);
   }
 
   virtual const InternalFieldTmpl<ConstitutiveLaw_, T> & previous() const {
     AKANTU_DEBUG_ASSERT(previous_values != nullptr,
                         "The history of the internal "
                             << this->getID() << " has not been activated");
     return *(this->previous_values);
   }
 
   /// check if the history is used or not
-  bool hasHistory() const { return (previous_values != nullptr); }
+  bool hasHistory() const override { return (previous_values != nullptr); }
 
   /// get the kind treated by the internal
   ElementKind getElementKind() const { return element_kind; }
 
   /// return the number of components
   UInt getNbComponent() const { return nb_component; }
 
   /// return the spatial dimension corresponding to the internal element type
   /// loop filter
   UInt getSpatialDimension() const { return this->spatial_dimension; }
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// the constitutive_law for which this is an internal parameter
   ConstitutiveLaw & constitutive_law;
 
   /// the fem containing the mesh and the element informations
   FEEngine * fem{nullptr};
 
   /// Element filter if needed
   const ElementTypeMapArray<UInt> & element_filter;
 
   /// default value
   T default_value{};
 
   /// spatial dimension of the element to consider
   UInt spatial_dimension{0};
 
   /// ElementKind of the element to consider
   ElementKind element_kind{_ek_regular};
 
   /// Number of component of the internal field
   UInt nb_component{0};
 
   /// Is the field initialized
   bool is_init{false};
 
   /// previous values
   std::unique_ptr<InternalFieldTmpl<ConstitutiveLaw_, T>> previous_values;
 };
 
 /// standard output stream operator
 template <class ConstitutiveLaw_, typename T>
 inline std::ostream &
 operator<<(std::ostream & stream,
            const InternalFieldTmpl<ConstitutiveLaw_, T> & _this) {
   _this.printself(stream);
   return stream;
 }
 
 template <typename T>
 using InternalField = InternalFieldTmpl<ConstitutiveLaw_, T>;
 
 } // namespace akantu
 
 #endif /* AKANTU_INTERNAL_FIELD_HH_ */
diff --git a/src/model/solid_mechanics/material.hh b/src/model/solid_mechanics/material.hh
index 49256cfdf..c50fabcdc 100644
--- a/src/model/solid_mechanics/material.hh
+++ b/src/model/solid_mechanics/material.hh
@@ -1,595 +1,594 @@
 /**
  * @file   material.hh
  *
  * @author Fabian Barras <fabian.barras@epfl.ch>
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  * @author Enrico Milanese <enrico.milanese@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Fri Apr 09 2021
  *
  * @brief  Mother class for all materials
  *
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2021 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_factory.hh"
 #include "aka_voigthelper.hh"
 #include "constitutive_law.hh"
 #include "data_accessor.hh"
 #include "integration_point.hh"
 #include "parsable.hh"
 #include "parser.hh"
 /* -------------------------------------------------------------------------- */
 #include "internal_field.hh"
 #include "random_internal_field.hh"
 /* -------------------------------------------------------------------------- */
 #include "mesh_events.hh"
 #include "solid_mechanics_model_event_handler.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef AKANTU_MATERIAL_HH_
 #define AKANTU_MATERIAL_HH_
 
 /* -------------------------------------------------------------------------- */
 namespace akantu {
 class Model;
 class SolidMechanicsModel;
 class Material;
 } // namespace akantu
 
 namespace akantu {
 
 using MaterialFactory =
     Factory<Material, ID, UInt, const ID &, SolidMechanicsModel &, const ID &>;
 
 /**
  * Interface of all materials
  * Prerequisites for a new material
  * - inherit from this class
  * - implement the following methods:
  * \code
  *  virtual Real getStableTimeStep(Real h, const Element & element =
  * ElementNull);
  *
  *  virtual void computeStress(ElementType el_type,
  *                             GhostType ghost_type = _not_ghost);
  *
  *  virtual void computeTangentStiffness(ElementType el_type,
  *                                       Array<Real> & tangent_matrix,
  *                                       GhostType ghost_type = _not_ghost);
  * \endcode
  *
  */
-class Material
-    : public ConstitutiveLaw<SolidMechanicsModel> public DataAccessor<Element>,
-      public Parsable,
-      protected SolidMechanicsModelEventHandler {
+class Material : public ConstitutiveLaw<SolidMechanicsModel>,
+                 public MeshEventHandler,
+                 protected SolidMechanicsModelEventHandler {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   Material(const Material & mat) = delete;
   Material & operator=(const Material & mat) = delete;
 
   /// Initialize material with defaults
   Material(SolidMechanicsModel & model, const ID & id = "");
 
   /// Initialize material with custom mesh & fe_engine
   Material(SolidMechanicsModel & model, UInt dim, const Mesh & mesh,
            FEEngine & fe_engine, const ID & id = "");
 
   /// Destructor
   ~Material() override;
 
 protected:
   void initialize();
 
   /* ------------------------------------------------------------------------ */
   /* Function that materials can/should reimplement                           */
   /* ------------------------------------------------------------------------ */
 protected:
   /// constitutive law
   virtual void computeStress(ElementType /* el_type */,
                              GhostType /* ghost_type */ = _not_ghost) {
     AKANTU_TO_IMPLEMENT();
   }
 
   /// compute the tangent stiffness matrix
   virtual void computeTangentModuli(ElementType /*el_type*/,
                                     Array<Real> & /*tangent_matrix*/,
                                     GhostType /*ghost_type*/ = _not_ghost) {
     AKANTU_TO_IMPLEMENT();
   }
 
   /// compute the potential energy
   virtual void computePotentialEnergy(ElementType el_type);
 
   /// compute the potential energy for an element
   virtual void
   computePotentialEnergyByElement(ElementType /*type*/, UInt /*index*/,
                                   Vector<Real> & /*epot_on_quad_points*/) {
     AKANTU_TO_IMPLEMENT();
   }
 
   virtual void updateEnergies(ElementType /*el_type*/) {}
 
   virtual void updateEnergiesAfterDamage(ElementType /*el_type*/) {}
 
   /// set the material to steady state (to be implemented for materials that
   /// need it)
   virtual void setToSteadyState(ElementType /*el_type*/,
                                 GhostType /*ghost_type*/ = _not_ghost) {}
 
   /// function called to update the internal parameters when the
   /// modifiable parameters are modified
   virtual void updateInternalParameters();
 
 public:
   /// extrapolate internal values
   virtual void extrapolateInternal(const ID & id, const Element & element,
                                    const Matrix<Real> & points,
                                    Matrix<Real> & extrapolated);
 
   /// compute the p-wave speed in the material
   virtual Real getPushWaveSpeed(const Element & /*element*/) const {
     AKANTU_TO_IMPLEMENT();
   }
 
   /// compute the s-wave speed in the material
   virtual Real getShearWaveSpeed(const Element & /*element*/) const {
     AKANTU_TO_IMPLEMENT();
   }
 
   /// get a material celerity to compute the stable time step (default: is the
   /// push wave speed)
   virtual Real getCelerity(const Element & element) const {
     return getPushWaveSpeed(element);
   }
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialize the material computed parameter
   virtual void initMaterial();
 
   /// compute the residual for this material
   //  virtual void updateResidual(GhostType ghost_type = _not_ghost);
 
   /// assemble the residual for this material
   virtual void assembleInternalForces(GhostType ghost_type);
 
   /// compute the stresses for this material
   virtual void computeAllStresses(GhostType ghost_type = _not_ghost);
   // virtual void
   // computeAllStressesFromTangentModuli(GhostType ghost_type = _not_ghost);
   virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost);
 
   /// set material to steady state
   void setToSteadyState(GhostType ghost_type = _not_ghost);
 
   /// compute the stiffness matrix
   virtual void assembleStiffnessMatrix(GhostType ghost_type);
 
   /// function to print the contain of the class
   void printself(std::ostream & stream, int indent = 0) const override;
 
   /**
    * interpolate stress on given positions for each element by means
    * of a geometrical interpolation on quadrature points
    */
   void interpolateStress(ElementTypeMapArray<Real> & result,
                          GhostType ghost_type = _not_ghost);
 
   /**
    * interpolate stress on given positions for each element by means
    * of a geometrical interpolation on quadrature points and store the
    * results per facet
    */
   void interpolateStressOnFacets(ElementTypeMapArray<Real> & result,
                                  ElementTypeMapArray<Real> & by_elem_result,
                                  GhostType ghost_type = _not_ghost);
 
   /**
    * function to initialize the elemental field interpolation
    * function by inverting the quadrature points' coordinates
    */
   void initElementalFieldInterpolation(
       const ElementTypeMapArray<Real> & interpolation_points_coordinates);
 
   /* ------------------------------------------------------------------------ */
   /* Common part                                                              */
   /* ------------------------------------------------------------------------ */
 protected:
   /* ------------------------------------------------------------------------ */
   static inline UInt getTangentStiffnessVoigtSize(UInt dim);
 
   /// compute the potential energy by element
   void computePotentialEnergyByElements();
 
   /* ------------------------------------------------------------------------ */
   /* Finite deformation functions                                             */
   /* This functions area implementing what is described in the paper of Bathe */
   /* et al, in IJNME, Finite Element Formulations For Large Deformation       */
   /* Dynamic Analysis, Vol 9, 353-386, 1975                                   */
   /* ------------------------------------------------------------------------ */
 protected:
   /// assemble the residual
   template <UInt dim> void assembleInternalForces(GhostType ghost_type);
 
   template <UInt dim>
   void computeAllStressesFromTangentModuli(ElementType type,
                                            GhostType ghost_type);
 
   template <UInt dim>
   void assembleStiffnessMatrix(ElementType type, GhostType ghost_type);
 
   /// assembling in finite deformation
   template <UInt dim>
   void assembleStiffnessMatrixNL(ElementType type, GhostType ghost_type);
 
   template <UInt dim>
   void assembleStiffnessMatrixL2(ElementType type, GhostType ghost_type);
 
   /* ------------------------------------------------------------------------ */
   /* Conversion functions                                                     */
   /* ------------------------------------------------------------------------ */
 public:
   /// Size of the Stress matrix for the case of finite deformation see: Bathe et
   /// al, IJNME, Vol 9, 353-386, 1975
   static inline UInt getCauchyStressMatrixSize(UInt dim);
 
   /// Sets the stress matrix according to Bathe et al, IJNME, Vol 9, 353-386,
   /// 1975
   template <UInt dim>
   static inline void setCauchyStressMatrix(const Matrix<Real> & S_t,
                                            Matrix<Real> & sigma);
 
   /// write the stress tensor in the Voigt notation.
   template <UInt dim>
   static inline decltype(auto) stressToVoigt(const Matrix<Real> & stress) {
     return VoigtHelper<dim>::matrixToVoigt(stress);
   }
 
   /// write the strain tensor in the Voigt notation.
   template <UInt dim>
   static inline decltype(auto) strainToVoigt(const Matrix<Real> & strain) {
     return VoigtHelper<dim>::matrixToVoigtWithFactors(strain);
   }
 
   /// write a voigt vector to stress
   template <UInt dim>
   static inline void voigtToStress(const Vector<Real> & voigt,
                                    Matrix<Real> & stress) {
     VoigtHelper<dim>::voigtToMatrix(voigt, stress);
   }
 
   /// Computation of Cauchy stress tensor in the case of finite deformation from
   /// the 2nd Piola-Kirchhoff for a given element type
   template <UInt dim>
   void StoCauchy(ElementType el_type, GhostType ghost_type = _not_ghost);
 
   /// Computation the Cauchy stress the 2nd Piola-Kirchhoff and the deformation
   /// gradient
   template <UInt dim>
   inline void StoCauchy(const Matrix<Real> & F, const Matrix<Real> & S,
                         Matrix<Real> & sigma, const Real & C33 = 1.0) const;
 
   template <UInt dim>
   static inline void gradUToF(const Matrix<Real> & grad_u, Matrix<Real> & F);
 
   template <UInt dim>
   static inline decltype(auto) gradUToF(const Matrix<Real> & grad_u);
 
   static inline void rightCauchy(const Matrix<Real> & F, Matrix<Real> & C);
   static inline void leftCauchy(const Matrix<Real> & F, Matrix<Real> & B);
 
   template <UInt dim>
   static inline void gradUToEpsilon(const Matrix<Real> & grad_u,
                                     Matrix<Real> & epsilon);
   template <UInt dim>
   static inline decltype(auto) gradUToEpsilon(const Matrix<Real> & grad_u);
 
   template <UInt dim>
   static inline void gradUToE(const Matrix<Real> & grad_u,
                               Matrix<Real> & epsilon);
 
   template <UInt dim>
   static inline decltype(auto) gradUToE(const Matrix<Real> & grad_u);
 
   static inline Real stressToVonMises(const Matrix<Real> & stress);
 
   /* ------------------------------------------------------------------------ */
   /* DataAccessor inherited members                                           */
   /* ------------------------------------------------------------------------ */
 public:
   inline UInt getNbData(const Array<Element> & elements,
                         const SynchronizationTag & tag) const override;
 
   inline void packData(CommunicationBuffer & buffer,
                        const Array<Element> & elements,
                        const SynchronizationTag & tag) const override;
 
   inline void unpackData(CommunicationBuffer & buffer,
                          const Array<Element> & elements,
                          const SynchronizationTag & tag) override;
 
   /* ------------------------------------------------------------------------ */
   /* SolidMechanicsModelEventHandler inherited members                        */
   /* ------------------------------------------------------------------------ */
 public:
   virtual void beforeSolveStep();
   virtual void afterSolveStep(bool converged = true);
 
   void onDamageIteration() override;
   void onDamageUpdate() override;
   void onDump() override;
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   AKANTU_GET_MACRO(Model, model, const SolidMechanicsModel &)
 
   AKANTU_GET_MACRO(Rho, rho, Real);
   AKANTU_SET_MACRO(Rho, rho, Real);
 
   AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt);
 
   /// return the potential energy for the subset of elements contained by the
   /// material
   Real getPotentialEnergy();
   /// return the potential energy for the provided element
   Real getPotentialEnergy(ElementType & type, UInt index);
 
   /// return the energy (identified by id) for the subset of elements contained
   /// by the material
   virtual Real getEnergy(const std::string & type);
   /// return the energy (identified by id) for the provided element
   virtual Real getEnergy(const std::string & energy_id, ElementType type,
                          UInt index);
 
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GradU, gradu, Real);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy,
                                          Real);
   AKANTU_GET_MACRO(GradU, gradu, const ElementTypeMapArray<Real> &);
   AKANTU_GET_MACRO(Stress, stress, const ElementTypeMapArray<Real> &);
   AKANTU_GET_MACRO(ElementFilter, element_filter,
                    const ElementTypeMapArray<UInt> &);
   AKANTU_GET_MACRO(FEEngine, fem, FEEngine &);
 
   bool isNonLocal() const { return is_non_local; }
 
   bool isFiniteDeformation() const { return finite_deformation; }
   bool isInelasticDeformation() const { return inelastic_deformation; }
 
   template <typename T>
   void inflateInternal(const std::string & field_id,
                        const ElementTypeMapArray<T> & field,
                        GhostType ghost_type = _not_ghost,
                        ElementKind element_kind = _ek_not_defined);
 
   /// apply a constant eigengrad_u everywhere in the material
   virtual void applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u,
                                GhostType /*ghost_type*/ = _not_ghost);
 
   bool hasMatrixChanged(const ID & id) {
     if (id == "K") {
       return hasStiffnessMatrixChanged() or finite_deformation;
     }
 
     return true;
   }
 
   MatrixType getMatrixType(const ID & id) {
     if (id == "K") {
       return getTangentType();
     }
 
     if (id == "M") {
       return _symmetric;
     }
 
     return _mt_not_defined;
   }
 
   /// specify if the matrix need to be recomputed for this material
   virtual bool hasStiffnessMatrixChanged() { return true; }
 
   /// specify the type of matrix, if not overloaded the material is not valid
   /// for static or implicit computations
   virtual MatrixType getTangentType() { return _mt_not_defined; }
 
   /// static method to reteive the material factory
   static MaterialFactory & getFactory();
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 
 protected:
   /// Link to the fem object in the model
   FEEngine & fem;
 
   /// Finite deformation
   bool finite_deformation{false};
 
   /// Finite deformation
   bool inelastic_deformation{false};
 
   /// The model to witch the material belong
   SolidMechanicsModel & model;
 
   /// density : rho
   Real rho{0.};
 
   /// spatial dimension
   UInt spatial_dimension;
 
   /// stresses arrays ordered by element types
   InternalField<Real> stress;
 
   /// eigengrad_u arrays ordered by element types
   InternalField<Real> eigengradu;
 
   /// grad_u arrays ordered by element types
   InternalField<Real> gradu;
 
   /// Green Lagrange strain (Finite deformation)
   InternalField<Real> green_strain;
 
   /// Second Piola-Kirchhoff stress tensor arrays ordered by element types
   /// (Finite deformation)
   InternalField<Real> piola_kirchhoff_2;
 
   /// potential energy by element
   InternalField<Real> potential_energy;
 
   /// tell if using in non local mode or not
   bool is_non_local{false};
 
   /// tell if the material need the previous stress state
   bool use_previous_stress{false};
 
   /// tell if the material need the previous strain state
   bool use_previous_gradu{false};
 
   /// elemental field interpolation coordinates
   InternalField<Real> interpolation_inverse_coordinates;
 
   /// elemental field interpolation points
   InternalField<Real> interpolation_points_matrices;
 
 private:
   /// eigen_grad_u for the parser
   Matrix<Real> eigen_grad_u;
 };
 
 /// standard output stream operator
 inline std::ostream & operator<<(std::ostream & stream,
                                  const Material & _this) {
   _this.printself(stream);
   return stream;
 }
 
 } // namespace akantu
 
 #include "material_inline_impl.hh"
 
 #include "internal_field_tmpl.hh"
 #include "random_internal_field_tmpl.hh"
 
 /* -------------------------------------------------------------------------- */
 /* Auto loop                                                                  */
 /* -------------------------------------------------------------------------- */
 /// This can be used to automatically write the loop on quadrature points in
 /// functions such as computeStress. This macro in addition to write the loop
 /// provides two tensors (matrices) sigma and grad_u
 #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type)       \
   auto && grad_u_view =                                                        \
       make_view(this->gradu(el_type, ghost_type), this->spatial_dimension,     \
                 this->spatial_dimension);                                      \
                                                                                \
   auto stress_view =                                                           \
       make_view(this->stress(el_type, ghost_type), this->spatial_dimension,    \
                 this->spatial_dimension);                                      \
                                                                                \
   if (this->isFiniteDeformation()) {                                           \
     stress_view = make_view(this->piola_kirchhoff_2(el_type, ghost_type),      \
                             this->spatial_dimension, this->spatial_dimension); \
   }                                                                            \
                                                                                \
   for (auto && data : zip(grad_u_view, stress_view)) {                         \
     [[gnu::unused]] Matrix<Real> & grad_u = std::get<0>(data);                 \
     [[gnu::unused]] Matrix<Real> & sigma = std::get<1>(data)
 
 #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END }
 
 /// This can be used to automatically write the loop on quadrature points in
 /// functions such as computeTangentModuli. This macro in addition to write the
 /// loop provides two tensors (matrices) sigma_tensor, grad_u, and a matrix
 /// where the elemental tangent moduli should be stored in Voigt Notation
 #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_mat)              \
   auto && grad_u_view =                                                        \
       make_view(this->gradu(el_type, ghost_type), this->spatial_dimension,     \
                 this->spatial_dimension);                                      \
                                                                                \
   auto && stress_view =                                                        \
       make_view(this->stress(el_type, ghost_type), this->spatial_dimension,    \
                 this->spatial_dimension);                                      \
                                                                                \
   auto tangent_size =                                                          \
       this->getTangentStiffnessVoigtSize(this->spatial_dimension);             \
                                                                                \
   auto && tangent_view = make_view(tangent_mat, tangent_size, tangent_size);   \
                                                                                \
   for (auto && data : zip(grad_u_view, stress_view, tangent_view)) {           \
     [[gnu::unused]] Matrix<Real> & grad_u = std::get<0>(data);                 \
     [[gnu::unused]] Matrix<Real> & sigma = std::get<1>(data);                  \
     Matrix<Real> & tangent = std::get<2>(data);
 
 #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END }
 
 /* -------------------------------------------------------------------------- */
 
 #define INSTANTIATE_MATERIAL_ONLY(mat_name)                                    \
   template class mat_name<1>; /* NOLINT */                                     \
   template class mat_name<2>; /* NOLINT */                                     \
   template class mat_name<3>  /* NOLINT */
 
 #define MATERIAL_DEFAULT_PER_DIM_ALLOCATOR(id, mat_name)                       \
   [](UInt dim, const ID &, SolidMechanicsModel & model,                        \
      const ID & id) /* NOLINT */                                               \
       -> std::unique_ptr<                                                      \
           Material> { /* NOLINT */                                             \
                       switch (dim) {                                           \
                       case 1:                                                  \
                         return std::make_unique<mat_name<1>>(/* NOLINT */      \
                                                              model, id);       \
                       case 2:                                                  \
                         return std::make_unique<mat_name<2>>(/* NOLINT */      \
                                                              model, id);       \
                       case 3:                                                  \
                         return std::make_unique<mat_name<3>>(/* NOLINT */      \
                                                              model, id);       \
                       default:                                                 \
                         AKANTU_EXCEPTION(                                      \
                             "The dimension "                                   \
                             << dim                                             \
                             << "is not a valid dimension for the material "    \
                             << #id);                                           \
                       }                                                        \
   }
 
 #define INSTANTIATE_MATERIAL(id, mat_name)                                     \
   INSTANTIATE_MATERIAL_ONLY(mat_name);                                         \
   static bool material_is_alocated_##id =                                      \
       MaterialFactory::getInstance().registerAllocator(                        \
           #id, MATERIAL_DEFAULT_PER_DIM_ALLOCATOR(id, mat_name))
 
 #endif /* AKANTU_MATERIAL_HH_ */