diff --git a/packages/core.cmake b/packages/core.cmake
index 23dd56108..0608787ec 100644
--- a/packages/core.cmake
+++ b/packages/core.cmake
@@ -1,581 +1,583 @@
 #===============================================================================
 # @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: Mon Jan 18 2016
 #
 # @brief  package description for core
 #
 # @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/>.
 #
 #===============================================================================
 
 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_delegated_constructors
   cxx_range_for )
 
 package_declare_sources(core
   common/aka_array.cc
   common/aka_array.hh
   common/aka_array_tmpl.hh
   common/aka_blas_lapack.hh
   common/aka_circular_array.hh
   common/aka_circular_array_inline_impl.cc
   common/aka_common.cc
   common/aka_common.hh
   common/aka_common_inline_impl.cc
   common/aka_csr.hh
   common/aka_element_classes_info_inline_impl.cc
   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_memory.cc
   common/aka_memory.hh
   common/aka_memory_inline_impl.cc
   common/aka_named_argument.hh
   common/aka_random_generator.hh
   common/aka_safe_enum.hh
   common/aka_static_memory.cc
   common/aka_static_memory.hh
   common/aka_static_memory_inline_impl.cc
   common/aka_static_memory_tmpl.hh
   common/aka_typelist.hh
   common/aka_types.hh
   common/aka_visitor.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.cc
   fe_engine/element_class.hh
   fe_engine/element_class_tmpl.hh
   fe_engine/element_classes/element_class_hexahedron_8_inline_impl.cc
   fe_engine/element_classes/element_class_hexahedron_20_inline_impl.cc
   fe_engine/element_classes/element_class_pentahedron_6_inline_impl.cc
   fe_engine/element_classes/element_class_pentahedron_15_inline_impl.cc
   fe_engine/element_classes/element_class_point_1_inline_impl.cc
   fe_engine/element_classes/element_class_quadrangle_4_inline_impl.cc
   fe_engine/element_classes/element_class_quadrangle_8_inline_impl.cc
   fe_engine/element_classes/element_class_segment_2_inline_impl.cc
   fe_engine/element_classes/element_class_segment_3_inline_impl.cc
   fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.cc
   fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.cc
   fe_engine/element_classes/element_class_triangle_3_inline_impl.cc
   fe_engine/element_classes/element_class_triangle_6_inline_impl.cc
 
   fe_engine/fe_engine.cc
   fe_engine/fe_engine.hh
   fe_engine/fe_engine_inline_impl.cc
   fe_engine/fe_engine_template.hh
   fe_engine/fe_engine_template_tmpl.hh
   fe_engine/geometrical_element.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.cc
   fe_engine/interpolation_element.cc
   fe_engine/interpolation_element_tmpl.hh
   fe_engine/integration_point.hh
   fe_engine/shape_functions.hh
   fe_engine/shape_functions_inline_impl.cc
   fe_engine/shape_lagrange.cc
   fe_engine/shape_lagrange.hh
   fe_engine/shape_lagrange_inline_impl.cc
   fe_engine/shape_linked.cc
   fe_engine/shape_linked.hh
   fe_engine/shape_linked_inline_impl.cc
   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_abaqus.cc
   io/mesh_io/mesh_io_abaqus.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/model_io.cc
   io/model_io.hh
 
   io/parser/algebraic_parser.hh
   io/parser/input_file_parser.hh
   io/parser/parsable.cc
   io/parser/parsable.hh
   io/parser/parsable_tmpl.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.cc
   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.cc
   mesh/mesh.cc
   mesh/mesh.hh
   mesh/mesh_accessor.hh
   mesh/mesh_accessor.cc
   mesh/mesh_events.hh
   mesh/mesh_filter.hh
   mesh/mesh_data.cc
   mesh/mesh_data.hh
   mesh/mesh_data_tmpl.hh
   mesh/mesh_inline_impl.cc
   mesh/node_group.cc
   mesh/node_group.hh
   mesh/node_group_inline_impl.cc
 
   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.cc
   mesh_utils/global_ids_updater.hh
   mesh_utils/global_ids_updater.cc
   mesh_utils/global_ids_updater_inline_impl.cc
 
   model/boundary_condition.hh
   model/boundary_condition_functor.hh
   model/boundary_condition_functor_inline_impl.cc
   model/boundary_condition_tmpl.hh
 
   model/common/neighborhood_base.hh
   model/common/neighborhood_base.cc
   model/common/neighborhood_base_inline_impl.cc
   model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh
   model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc
   model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.cc
   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.cc
   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.cc
 
   model/dof_manager.cc
   model/dof_manager.hh
   model/dof_manager_default.cc
   model/dof_manager_default.hh
   model/dof_manager_default_inline_impl.cc
   model/dof_manager_inline_impl.cc
   model/model_solver.cc
   model/model_solver.hh
   model/model_solver_tmpl.hh
   model/non_linear_solver.cc
   model/non_linear_solver.hh
   model/non_linear_solver_default.hh
   model/non_linear_solver_lumped.cc
   model/non_linear_solver_lumped.hh
   model/solver_callback.hh
   model/solver_callback.cc
   model/time_step_solver.hh
   model/time_step_solvers/time_step_solver.cc
   model/time_step_solvers/time_step_solver_default.cc
   model/time_step_solvers/time_step_solver_default.hh
   model/time_step_solvers/time_step_solver_default_explicit.hh
   model/non_linear_solver_callback.hh
   model/time_step_solvers/time_step_solver_default_solver_callback.hh
 
   model/integration_scheme/generalized_trapezoidal.cc
   model/integration_scheme/generalized_trapezoidal.hh
   model/integration_scheme/integration_scheme.cc
   model/integration_scheme/integration_scheme.hh
   model/integration_scheme/integration_scheme_1st_order.cc
   model/integration_scheme/integration_scheme_1st_order.hh
   model/integration_scheme/integration_scheme_2nd_order.cc
   model/integration_scheme/integration_scheme_2nd_order.hh
   model/integration_scheme/newmark-beta.cc
   model/integration_scheme/newmark-beta.hh
   model/integration_scheme/pseudo_time.cc
   model/integration_scheme/pseudo_time.hh
   model/model.cc
   model/model.hh
   model/model_inline_impl.cc
 
   model/solid_mechanics/material.cc
   model/solid_mechanics/material.hh
   model/solid_mechanics/material_inline_impl.cc
   model/solid_mechanics/material_selector.hh
   model/solid_mechanics/material_selector_tmpl.hh
   model/solid_mechanics/materials/internal_field.hh
   model/solid_mechanics/materials/internal_field_tmpl.hh
   model/solid_mechanics/materials/random_internal_field.hh
   model/solid_mechanics/materials/random_internal_field_tmpl.hh
   model/solid_mechanics/solid_mechanics_model.cc
   model/solid_mechanics/solid_mechanics_model.hh
   model/solid_mechanics/solid_mechanics_model_inline_impl.cc
+  model/solid_mechanics/solid_mechanics_model_io.cc
   model/solid_mechanics/solid_mechanics_model_mass.cc
   model/solid_mechanics/solid_mechanics_model_material.cc
   model/solid_mechanics/solid_mechanics_model_tmpl.hh
   model/solid_mechanics/solid_mechanics_model_event_handler.hh
   model/solid_mechanics/materials/plane_stress_toolbox.hh
   model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh
 
 
   model/solid_mechanics/materials/material_core_includes.hh
   model/solid_mechanics/materials/material_elastic.cc
   model/solid_mechanics/materials/material_elastic.hh
   model/solid_mechanics/materials/material_elastic_inline_impl.cc
   model/solid_mechanics/materials/material_thermal.cc
   model/solid_mechanics/materials/material_thermal.hh
   model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc
   model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh
   model/solid_mechanics/materials/material_elastic_orthotropic.cc
   model/solid_mechanics/materials/material_elastic_orthotropic.hh
   model/solid_mechanics/materials/material_damage/material_damage.hh
   model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh
   model/solid_mechanics/materials/material_damage/material_marigo.cc
   model/solid_mechanics/materials/material_damage/material_marigo.hh
   model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.cc
   model/solid_mechanics/materials/material_damage/material_mazars.cc
   model/solid_mechanics/materials/material_damage/material_mazars.hh
   model/solid_mechanics/materials/material_damage/material_mazars_inline_impl.cc
   model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc
   model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh
   model/solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.cc
   model/solid_mechanics/materials/material_plastic/material_plastic.cc
   model/solid_mechanics/materials/material_plastic/material_plastic.hh
   model/solid_mechanics/materials/material_plastic/material_plastic_inline_impl.cc
   model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc
   model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh
   model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc
   model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc
   model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh
 
   model/solid_mechanics/materials/material_non_local.hh
   model/solid_mechanics/materials/material_non_local_tmpl.hh
   model/solid_mechanics/materials/material_non_local_includes.hh
   model/solid_mechanics/materials/material_non_local_inline_impl.cc
 
   solver/sparse_solver.cc
   solver/sparse_solver.hh
   solver/sparse_solver_inline_impl.cc
   solver/sparse_matrix.cc
   solver/sparse_matrix.hh
   solver/sparse_matrix_inline_impl.cc
   solver/sparse_matrix_aij.cc
   solver/sparse_matrix_aij.hh
   solver/sparse_matrix_aij_inline_impl.cc
   solver/terms_to_assemble.hh
 
   synchronizer/communication_descriptor_tmpl.hh
   synchronizer/communications_tmpl.hh
   synchronizer/communication_buffer.hh
   synchronizer/communication_buffer_inline_impl.cc
   synchronizer/communication_descriptor.hh
   synchronizer/communication_tag.hh
   synchronizer/communications.hh
   synchronizer/data_accessor.cc
   synchronizer/data_accessor.hh
   synchronizer/element_synchronizer.cc
   synchronizer/element_synchronizer.hh
   synchronizer/node_synchronizer.cc
   synchronizer/node_synchronizer.hh
   synchronizer/dof_synchronizer.cc
   synchronizer/dof_synchronizer.hh
   synchronizer/dof_synchronizer_inline_impl.cc
   synchronizer/element_info_per_processor.cc
   synchronizer/element_info_per_processor.hh
   synchronizer/element_info_per_processor_tmpl.hh
   synchronizer/filtered_synchronizer.cc
   synchronizer/filtered_synchronizer.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/real_static_communicator.hh
   synchronizer/slave_element_info_per_processor.cc
   synchronizer/static_communicator.cc
   synchronizer/static_communicator.hh
   synchronizer/static_communicator_dummy.hh
   synchronizer/static_communicator_inline_impl.hh
   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
   )
 
 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_shapes_derivatives
   )
 
 package_declare_material_infos(core
   LIST AKANTU_CORE_MATERIAL_LIST
   INCLUDE material_core_includes.hh
   )
 
 package_declare_documentation_files(core
   manual.sty
   manual.cls
   manual.tex
   manual-macros.sty
   manual-titlepages.tex
   manual-authors.tex
   manual-introduction.tex
   manual-gettingstarted.tex
   manual-io.tex
   manual-feengine.tex
   manual-solidmechanicsmodel.tex
   manual-constitutive-laws.tex
   manual-lumping.tex
   manual-elements.tex
   manual-appendix-elements.tex
   manual-appendix-materials.tex
   manual-appendix-packages.tex
   manual-backmatter.tex
   manual-bibliography.bib
   manual-bibliographystyle.bst
 
   figures/bc_and_ic_example.pdf
   figures/boundary.pdf
   figures/boundary.svg
   figures/dirichlet.pdf
   figures/dirichlet.svg
   figures/doc_wheel.pdf
   figures/doc_wheel.svg
   figures/dynamic_analysis.png
   figures/explicit_dynamic.pdf
   figures/explicit_dynamic.svg
   figures/static.pdf
   figures/static.svg
   figures/hooke_law.pdf
   figures/hot-point-1.png
   figures/hot-point-2.png
   figures/implicit_dynamic.pdf
   figures/implicit_dynamic.svg
   figures/insertion.pdf
   figures/interpolate.pdf
   figures/interpolate.svg
   figures/problemDomain.pdf_tex
   figures/problemDomain.pdf
   figures/static_analysis.png
   figures/stress_strain_el.pdf
   figures/tangent.pdf
   figures/tangent.svg
   figures/vectors.pdf
   figures/vectors.svg
 
   figures/stress_strain_neo.pdf
   figures/visco_elastic_law.pdf
   figures/isotropic_hardening_plasticity.pdf
   figures/stress_strain_visco.pdf
 
   figures/elements/hexahedron_8.pdf
   figures/elements/hexahedron_8.svg
   figures/elements/quadrangle_4.pdf
   figures/elements/quadrangle_4.svg
   figures/elements/quadrangle_8.pdf
   figures/elements/quadrangle_8.svg
   figures/elements/segment_2.pdf
   figures/elements/segment_2.svg
   figures/elements/segment_3.pdf
   figures/elements/segment_3.svg
   figures/elements/tetrahedron_10.pdf
   figures/elements/tetrahedron_10.svg
   figures/elements/tetrahedron_4.pdf
   figures/elements/tetrahedron_4.svg
   figures/elements/triangle_3.pdf
   figures/elements/triangle_3.svg
   figures/elements/triangle_6.pdf
   figures/elements/triangle_6.svg
   figures/elements/xtemp.pdf
   )
 
 package_declare_documentation(core
   "This package is the core engine of \\akantu. It depends on:"
   "\\begin{itemize}"
   "\\item A C++ compiler (\\href{http://gcc.gnu.org/}{GCC} >= 4, or \\href{https://software.intel.com/en-us/intel-compilers}{Intel})."
   "\\item The cross-platform, open-source \\href{http://www.cmake.org/}{CMake} build system."
   "\\item The \\href{http://www.boost.org/}{Boost} C++ portable libraries."
   "\\item The \\href{http://www.zlib.net/}{zlib} compression library."
   "\\end{itemize}"
   ""
   "Under Ubuntu (14.04 LTS) the installation can be performed using the commands:"
   "\\begin{command}"
   "  > sudo apt-get install cmake libboost-dev zlib1g-dev g++"
   "\\end{command}"
   ""
   "Under Mac OS X the installation requires the following steps:"
   "\\begin{itemize}"
   "\\item Install Xcode"
   "\\item Install the command line tools."
   "\\item Install the MacPorts project which allows to automatically"
   "download and install opensource packages."
   "\\end{itemize}"
   "Then the following commands should be typed in a terminal:"
   "\\begin{command}"
   "  > sudo port install cmake gcc48 boost"
   "\\end{command}"
   )
 
 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
     model/solid_mechanics/material_list.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()
 
 if(DEFINED AKANTU_CXX11_FLAGS)
   package_declare(core_cxx11 NOT_OPTIONAL
     DESCRIPTION "C++ 11 additions for Akantu core"
     COMPILE_FLAGS CXX "${AKANTU_CXX11_FLAGS}")
 
   if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
     if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.6")
       set(AKANTU_CORE_CXX11 OFF CACHE BOOL "C++ 11 additions for Akantu core - not supported by the selected compiler" FORCE)
     endif()
   endif()
 
   package_declare_documentation(core_cxx11
     "This option activates some features of the C++11 standard. This is usable with GCC>=4.7 or Intel>=13.")
 else()
   if(CMAKE_VERSION VERSION_LESS 3.1)
     message(FATAL_ERROR "Since version 3.0 Akantu requires at least c++11 capable compiler")
   endif()
 endif()
diff --git a/packages/damage_non_local.cmake b/packages/damage_non_local.cmake
index c3b2335f2..c3bb6f74a 100644
--- a/packages/damage_non_local.cmake
+++ b/packages/damage_non_local.cmake
@@ -1,68 +1,68 @@
 #===============================================================================
 # @file   damage_non_local.cmake
 #
 # @author Nicolas Richart <nicolas.richart@epfl.ch>
 #
 # @date creation: Fri Jun 15 2012
 # @date last modification: Mon Jan 18 2016
 #
 # @brief  package description for non-local materials
 #
 # @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/>.
 #
 #===============================================================================
 
 package_declare(damage_non_local
   DESCRIPTION "Package for Non-local damage constitutives laws Akantu"
   DEPENDS lapack)
 
 package_declare_sources(damage_non_local
   model/solid_mechanics/materials/material_damage/material_damage_non_local.hh
+  model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc
   model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh
-  model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc
   model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc
   model/solid_mechanics/materials/material_damage/material_mazars_non_local.hh
 
   model/solid_mechanics/materials/weight_functions/base_weight_function.hh
   model/solid_mechanics/materials/weight_functions/base_weight_function_inline_impl.cc
   model/solid_mechanics/materials/weight_functions/damaged_weight_function.hh
   model/solid_mechanics/materials/weight_functions/damaged_weight_function_inline_impl.cc
   model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh
   model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.cc
   model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh
   model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function_inline_impl.cc
   model/solid_mechanics/materials/weight_functions/stress_based_weight_function.hh
   model/solid_mechanics/materials/weight_functions/stress_based_weight_function.cc
   model/solid_mechanics/materials/weight_functions/stress_based_weight_function_inline_impl.cc
   )
 
 package_declare_material_infos(damage_non_local
   LIST AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST
   INCLUDE material_non_local_includes.hh
   )
 
 package_declare_documentation_files(damage_non_local
   manual-constitutive-laws-non_local.tex
   manual-appendix-materials-non-local.tex)
 
 package_declare_documentation(damage_non_local
 "This package activates the non local damage feature of AKANTU"
 "")
 
diff --git a/src/common/aka_common.cc b/src/common/aka_common.cc
index dd5955a94..0fd4b6d31 100644
--- a/src/common/aka_common.cc
+++ b/src/common/aka_common.cc
@@ -1,155 +1,152 @@
 /**
  * @file   aka_common.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Mon Jun 14 2010
  * @date last modification: Tue Jan 19 2016
  *
  * @brief  Initialization of global variables
  *
  * @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_common.hh"
 #include "aka_static_memory.hh"
 #include "static_communicator.hh"
 #include "aka_random_generator.hh"
 
 #include "parser.hh"
 #include "cppargparse.hh"
 
 #include "communication_tag.hh"
 /* -------------------------------------------------------------------------- */
 #include <ctime>
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 void initialize(int & argc, char **& argv) {
   AKANTU_DEBUG_IN();
 
   initialize("", argc, argv);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void initialize(const std::string & input_file, int & argc, char **& argv) {
   AKANTU_DEBUG_IN();
   StaticMemory::getStaticMemory();
   StaticCommunicator & comm =
       StaticCommunicator::getStaticCommunicator(argc, argv);
 
   Tag::setMaxTag(comm.getMaxTag());
 
   debug::debugger.setParallelContext(comm.whoAmI(), comm.getNbProc());
   debug::initSignalHandler();
   debug::setDebugLevel(dblError);
 
   static_argparser.setParallelContext(comm.whoAmI(), comm.getNbProc());
   static_argparser.setExternalExitFunction(debug::exit);
   static_argparser.addArgument("--aka_input_file", "Akantu's input file", 1,
                                cppargparse::_string, std::string());
   static_argparser.addArgument(
       "--aka_debug_level",
       std::string("Akantu's overall debug level") +
           std::string(" (0: error, 1: exceptions, 4: warnings, 5: info, ..., "
                       "100: dump") +
           std::string(" more info on levels can be foind in aka_error.hh)"),
       1, cppargparse::_integer, int(dblWarning));
 
   static_argparser.addArgument(
       "--aka_print_backtrace",
       "Should Akantu print a backtrace in case of error", 0,
       cppargparse::_boolean, false, true);
 
   static_argparser.parse(argc, argv, cppargparse::_remove_parsed);
 
   std::string infile = static_argparser["aka_input_file"];
   if (infile == "")
     infile = input_file;
 
   debug::debugger.printBacktrace(static_argparser["aka_print_backtrace"]);
 
   if ("" != infile) {
     readInputFile(infile);
   }
 
   long int seed;
   try {
     seed = static_parser.getParameter("seed", _ppsc_current_scope);
   } catch (debug::Exception &) {
     seed = time(NULL);
   }
 
   seed *= (comm.whoAmI() + 1);
-#if not defined(_WIN32)
-  Rand48Generator<Real>::seed(seed);
-#endif
-  RandGenerator<Real>::seed(seed);
+  RandomGenerator<UInt>::seed(seed);
 
   int dbl_level = static_argparser["aka_debug_level"];
   debug::setDebugLevel(DebugLevel(dbl_level));
 
   AKANTU_DEBUG_INFO("Random seed set to " << seed);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void finalize() {
   AKANTU_DEBUG_IN();
 
   if (StaticCommunicator::isInstantiated()) {
     StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
     delete &comm;
   }
 
   if (StaticMemory::isInstantiated()) {
     delete &(StaticMemory::getStaticMemory());
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void readInputFile(const std::string & input_file) {
   static_parser.parse(input_file);
 }
 
 /* -------------------------------------------------------------------------- */
 cppargparse::ArgumentParser & getStaticArgumentParser() {
   return static_argparser;
 }
 
 /* -------------------------------------------------------------------------- */
 Parser & getStaticParser() { return static_parser; }
 
 /* -------------------------------------------------------------------------- */
 const ParserSection & getUserParser() {
   return *(static_parser.getSubSections(_st_user).first);
 }
 
 } // akantu
diff --git a/src/common/aka_extern.cc b/src/common/aka_extern.cc
index 4c5b7d03e..27d30649a 100644
--- a/src/common/aka_extern.cc
+++ b/src/common/aka_extern.cc
@@ -1,137 +1,128 @@
 /**
  * @file   aka_extern.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Mon Jun 14 2010
  * @date last modification: Thu Nov 19 2015
  *
  * @brief  initialisation of all global variables
  * to insure the order of creation
  *
  * @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_array.hh"
 #include "aka_common.hh"
 #include "aka_math.hh"
 #include "aka_named_argument.hh"
 #include "aka_random_generator.hh"
 #include "communication_tag.hh"
 #include "cppargparse.hh"
 #include "parser.hh"
 #include "solid_mechanics_model.hh"
 #if defined(AKANTU_COHESIVE_ELEMENT)
 #include "solid_mechanics_model_cohesive.hh"
 #endif
 /* -------------------------------------------------------------------------- */
 #include <iostream>
 #include <limits>
 /* -------------------------------------------------------------------------- */
 #if defined(AKANTU_DEBUG_TOOLS)
 #include "aka_debug_tools.hh"
 #endif
 
 namespace akantu {
 
-/** \todo write function to get this
- *   values from the environment or a config file
- */
-
 /* -------------------------------------------------------------------------- */
 /* error.hpp variables                                                        */
 /* -------------------------------------------------------------------------- */
 namespace debug {
+  /** \todo write function to get this
+   *   values from the environment or a config file
+   */
   /// standard output for debug messages
   std::ostream * _akantu_debug_cout = &std::cerr;
 
   /// standard output for normal messages
   std::ostream & _akantu_cout = std::cout;
 
   /// parallel context used in debug messages
   std::string _parallel_context = "";
 
   Debugger debugger;
 
 #if defined(AKANTU_DEBUG_TOOLS)
   DebugElementManager element_manager;
 #endif
 } // namespace debug
 
 /* -------------------------------------------------------------------------- */
 /// list of ghost iterable types
 ghost_type_t ghost_types(_casper);
 
 /* -------------------------------------------------------------------------- */
 use_named_args_t use_named_args;
 
 CREATE_NAMED_ARGUMENT(all_ghost_types);
 CREATE_NAMED_ARGUMENT(default_value);
 CREATE_NAMED_ARGUMENT(element_kind);
 CREATE_NAMED_ARGUMENT(ghost_type);
 CREATE_NAMED_ARGUMENT(nb_component);
 CREATE_NAMED_ARGUMENT(spatial_dimension);
 CREATE_NAMED_ARGUMENT(with_nb_element);
 CREATE_NAMED_ARGUMENT(with_nb_nodes_per_element);
 
 CREATE_NAMED_ARGUMENT(analysis_method);
 CREATE_NAMED_ARGUMENT(no_init_materials);
 
 #if defined(AKANTU_COHESIVE_ELEMENT)
 CREATE_NAMED_ARGUMENT(is_extrinsic);
 #endif
 
 /* -------------------------------------------------------------------------- */
 /// Paser for commandline arguments
 ::cppargparse::ArgumentParser static_argparser;
 
 /// Parser containing the information parsed by the input file given to initFull
 Parser static_parser;
 
 bool Parser::permissive_parser = false;
 
 /* -------------------------------------------------------------------------- */
 Real Math::tolerance = std::numeric_limits<Real>::epsilon();
 
 /* -------------------------------------------------------------------------- */
 const UInt _all_dimensions = UInt(-1);
 
 /* -------------------------------------------------------------------------- */
 const Array<UInt> empty_filter(0, 1, "empty_filter");
 
 /* -------------------------------------------------------------------------- */
-template <> long int RandGenerator<Real>::_seed = 0;
-template <>
-long int RandGenerator<bool>::_seed =
-    0; // useless just defined due to a template instantiation
-template <> long int RandGenerator<UInt>::_seed = 0;
-template <> long int RandGenerator<Int>::_seed = 0;
-#if not defined(_WIN32)
-template <> long int Rand48Generator<Real>::_seed = 0;
-#endif
-
+template <> long int RandomGenerator<UInt>::_seed = 5489u;
+template <> std::default_random_engine RandomGenerator<UInt>::generator(5489u);
 /* -------------------------------------------------------------------------- */
 int Tag::max_tag = 0;
 
 /* -------------------------------------------------------------------------- */
 
 } // namespace akantu
diff --git a/src/common/aka_factory.hh b/src/common/aka_factory.hh
new file mode 100644
index 000000000..958ed5285
--- /dev/null
+++ b/src/common/aka_factory.hh
@@ -0,0 +1,78 @@
+/**
+ * @file   aka_factory.hh
+ *
+ * @author Nicolas Richart
+ *
+ * @date creation  Thu Jul 06 2017
+ *
+ * @brief This is a generic factory
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free  software: you can redistribute it and/or  modify it under the
+ * terms  of the  GNU Lesser  General Public  License as  published by  the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
+ * details.
+ *
+ * You should  have received  a copy  of the GNU  Lesser General  Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+/* -------------------------------------------------------------------------- */
+#include "aka_common.hh"
+/* -------------------------------------------------------------------------- */
+#include <map>
+#include <memory>
+#include <functional>
+#include <string>
+/* -------------------------------------------------------------------------- */
+
+#ifndef __AKANTU_AKA_FACTORY_HH__
+#define __AKANTU_AKA_FACTORY_HH__
+
+namespace akantu {
+
+template <class Base, class... Args> class Factory {
+  using allocator_t = std::function<std::unique_ptr<Base>(Args...)>;
+private:
+  Factory() = default;
+public:
+  Factory(const Factory &) = delete;
+  Factory & operator=(const Factory &) = delete;
+
+  static Factory & getInstance() {
+    static Factory instance;
+    return instance;
+  }
+  /* ------------------------------------------------------------------------ */
+  bool registerAllocator(ID id, const allocator_t & allocator) {
+    if (allocators.find(id) != allocators.end())
+      AKANTU_EXCEPTION("The id " << id << " is already registered in the "
+                       << debug::demangle(typeid(Base).name()) << " factory");
+    allocators[id] = allocator;
+    return true;
+  }
+
+  std::unique_ptr<Base> allocate(ID id, Args... args) {
+    if (allocators.find(id) == allocators.end())
+      AKANTU_EXCEPTION("The id  " << id << " is not registered in the "
+                                  << debug::demangle(typeid(Base).name())
+                                  << " factory.");
+    return std::forward<std::unique_ptr<Base>>(allocators[id](args...));
+  }
+
+private:
+  std::map<std::string, allocator_t> allocators;
+};
+
+} // namespace akantu
+
+#endif /* __AKANTU_AKA_FACTORY_HH__ */
diff --git a/src/common/aka_named_argument.hh b/src/common/aka_named_argument.hh
index 1b5ecc1bf..af0c7d742 100644
--- a/src/common/aka_named_argument.hh
+++ b/src/common/aka_named_argument.hh
@@ -1,158 +1,158 @@
 /**
  * @file   aka_named_argument.hh
  *
  * @author Marco Arena
  *
  * @date creation  Fri Jun 16 2017
  *
  * @brief A Documented file.
  *
  * @section LICENSE
  *
  * Public Domain ? https://gist.github.com/ilpropheta/7576dce4c3249df89f85
  *
  */
 /* -------------------------------------------------------------------------- */
 #include <tuple>
 #include <type_traits>
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_AKA_NAMED_ARGUMENT_HH__
 #define __AKANTU_AKA_NAMED_ARGUMENT_HH__
 
 namespace akantu {
 
 struct use_named_args_t {};
 extern use_named_args_t use_named_args;
 
 namespace named_argument {
   /* -- Pack utils (proxy version) --------------------------------------------
    */
   /// Proxy containing [tag, value]
   template <typename tag, typename type> struct param_t {
     using _tag = tag;
     using _type = type;
 
     template <typename T>
     explicit param_t(T && value) : _value(std::forward<T>(value)) {}
 
     type _value;
   };
 
   /*
    * Tagged proxy that allows syntax _name = value
    * operator=(T&&) returns a param_t instance
    **/
   template <typename tag> struct param_proxy {
     using _tag = tag;
 
     template <typename T> decltype(auto) operator=(T && value) {
       return param_t<tag, decltype(value)>{std::forward<T>(value)};
     }
   };
 
   /*  Same as type_at but it's supposed to be used by passing
       a pack of param_t (_tag is looked for instead of a
       plain type). This and type_at should be refactored.
   */
   template <typename T, typename head, typename... tail> struct type_at_p {
     enum {
       _tmp = (std::is_same<T, typename std::decay<head>::type::_tag>::value)
                  ? 0
                  : type_at_p<T, tail...>::_pos
     };
     enum { _pos = _tmp == -1 ? -1 : 1 + _tmp };
   };
 
   template <typename T, typename head> struct type_at_p<T, head> {
     enum {
       _pos =
           (std::is_same<T, typename std::decay<head>::type::_tag>::value ? 1
                                                                          : -1)
     };
   };
 
   template <typename T, typename head, typename... tail> struct type_at {
     enum { _tmp = type_at_p<T, head, tail...>::_pos };
     enum { _pos = _tmp == 1 ? 0 : (_tmp == -1 ? -1 : _tmp - 1) };
   };
 
   /*  Same as get_at but it's supposed to be used by passing
       a pack of param_t (_type is retrieved instead)
       This and get_at should be refactored.
   */
   template <int pos, int curr> struct get_at {
     static_assert(pos >= 0, "Required parameter");
 
     template <typename head, typename... tail>
     static decltype(auto) get(head &&, tail &&... t) {
       return get_at<pos, curr + 1>::get(std::forward<tail>(t)...);
     }
   };
 
   template <int pos> struct get_at<pos, pos> {
     static_assert(pos >= 0, "Required parameter");
 
     template <typename head, typename... tail>
     static decltype(auto) get(head && h, tail &&...) {
-      return std::forward<typename head::_type>(h._value);
+      return std::forward<decltype(h._value)>(h._value);
     }
   };
 
   // Optional version
   template <int pos, int curr> struct get_optional {
     template <typename T, typename... pack>
     static decltype(auto) get(T &&, pack &&... _pack) {
       return get_at<pos, curr>::get(std::forward<pack>(_pack)...);
     }
   };
 
   template <int curr> struct get_optional<-1, curr> {
     template <typename T, typename... pack>
     static decltype(auto) get(T && _default, pack &&...) {
       return std::forward<T>(_default);
     }
   };
 
 } // namespace named_argument
 
 // CONVENIENCE MACROS FOR CLASS DESIGNERS ==========
 #define TAG_OF_ARGUMENT(_name) p_##_name
 #define TAG_OF_ARGUMENT_WNS(_name) named_argument::TAG_OF_ARGUMENT(_name)
 
 #define REQUIRED_NAMED_ARG(_name)                                              \
   named_argument::get_at<                                                      \
       named_argument::type_at<TAG_OF_ARGUMENT_WNS(_name), pack...>::_pos,      \
       0>::get(std::forward<pack>(_pack)...)
 #define OPTIONAL_NAMED_ARG(_name, _defaultVal)                                 \
   named_argument::get_optional<                                                \
       named_argument::type_at<TAG_OF_ARGUMENT_WNS(_name), pack...>::_pos,      \
       0>::get(_defaultVal, std::forward<pack>(_pack)...)
 
 #define DECLARE_NAMED_ARGUMENT(name)                                           \
   namespace named_argument {                                                   \
     struct TAG_OF_ARGUMENT(name) {};                                           \
   }                                                                            \
   extern named_argument::param_proxy<TAG_OF_ARGUMENT_WNS(name)> _##name
 
 #define CREATE_NAMED_ARGUMENT(name)                                            \
   named_argument::param_proxy<TAG_OF_ARGUMENT_WNS(name)> _##name
 
 DECLARE_NAMED_ARGUMENT(all_ghost_types);
 DECLARE_NAMED_ARGUMENT(default_value);
 DECLARE_NAMED_ARGUMENT(element_kind);
 DECLARE_NAMED_ARGUMENT(ghost_type);
 DECLARE_NAMED_ARGUMENT(nb_component);
 DECLARE_NAMED_ARGUMENT(with_nb_element);
 DECLARE_NAMED_ARGUMENT(with_nb_nodes_per_element);
 DECLARE_NAMED_ARGUMENT(spatial_dimension);
 
 DECLARE_NAMED_ARGUMENT(analysis_method);
 DECLARE_NAMED_ARGUMENT(no_init_materials);
 
 #if defined(AKANTU_COHESIVE_ELEMENT)
 DECLARE_NAMED_ARGUMENT(is_extrinsic);
 #endif
 } // namespace akantu
 
 #endif /* __AKANTU_AKA_NAMED_ARGUMENT_HH__ */
diff --git a/src/fe_engine/fe_engine_template_tmpl.hh b/src/fe_engine/fe_engine_template_tmpl.hh
index 15f8a9fe3..c6f135b15 100644
--- a/src/fe_engine/fe_engine_template_tmpl.hh
+++ b/src/fe_engine/fe_engine_template_tmpl.hh
@@ -1,1674 +1,1673 @@
 /**
  * @file   fe_engine_template_tmpl.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Tue Feb 15 2011
  * @date last modification: Thu Nov 19 2015
  *
  * @brief  Template implementation of FEEngineTemplate
  *
  * @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_common.hh"
 #include "dof_manager.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::FEEngineTemplate(
     Mesh & mesh, UInt spatial_dimension, ID id, MemoryID memory_id)
     : FEEngine(mesh, spatial_dimension, id, memory_id),
       integrator(mesh, id, memory_id), shape_functions(mesh, id, memory_id) {}
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::~FEEngineTemplate() {}
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct GradientOnIntegrationPointsHelper {
   template <class S>
   static void call(__attribute__((unused)) const S & shape_functions,
                    __attribute__((unused)) Mesh & mesh,
                    __attribute__((unused)) const Array<Real> & u,
                    __attribute__((unused)) Array<Real> & nablauq,
                    __attribute__((unused)) const UInt nb_degree_of_freedom,
                    __attribute__((unused)) const ElementType & type,
                    __attribute__((unused)) const GhostType & ghost_type,
                    __attribute__((unused))
                    const Array<UInt> & filter_elements) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 };
 
 #define COMPUTE_GRADIENT(type)                                                 \
   if (element_dimension == ElementClass<type>::getSpatialDimension())          \
     shape_functions.template gradientOnIntegrationPoints<type>(                \
         u, nablauq, nb_degree_of_freedom, ghost_type, filter_elements);
 
 #define AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER(kind)          \
   template <> struct GradientOnIntegrationPointsHelper<kind> {                 \
     template <class S>                                                         \
     static void call(const S & shape_functions, Mesh & mesh,                   \
                      const Array<Real> & u, Array<Real> & nablauq,             \
                      const UInt nb_degree_of_freedom,                          \
                      const ElementType & type, const GhostType & ghost_type,   \
                      const Array<UInt> & filter_elements) {                    \
       UInt element_dimension = mesh.getSpatialDimension(type);                 \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_GRADIENT, kind);                \
     }                                                                          \
   };
 AKANTU_BOOST_ALL_KIND_LIST(
     AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER,
     AKANTU_FE_ENGINE_LIST_GRADIENT_ON_INTEGRATION_POINTS)
 
 #undef AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER
 #undef COMPUTE_GRADIENT
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     gradientOnIntegrationPoints(const Array<Real> & u, Array<Real> & nablauq,
                                 const UInt nb_degree_of_freedom,
                                 const ElementType & type,
                                 const GhostType & ghost_type,
                                 const Array<UInt> & filter_elements) const {
   AKANTU_DEBUG_IN();
 
   UInt nb_element = mesh.getNbElement(type, ghost_type);
   if (filter_elements != empty_filter)
     nb_element = filter_elements.getSize();
   UInt nb_points =
       shape_functions.getIntegrationPoints(type, ghost_type).cols();
 
 #ifndef AKANTU_NDEBUG
 
   UInt element_dimension = mesh.getSpatialDimension(type);
 
   AKANTU_DEBUG_ASSERT(u.getSize() == mesh.getNbNodes(),
                       "The vector u(" << u.getID()
                                       << ") has not the good size.");
   AKANTU_DEBUG_ASSERT(u.getNbComponent() == nb_degree_of_freedom,
                       "The vector u("
                           << u.getID()
                           << ") has not the good number of component.");
 
   AKANTU_DEBUG_ASSERT(
       nablauq.getNbComponent() == nb_degree_of_freedom * element_dimension,
       "The vector nablauq(" << nablauq.getID()
                             << ") has not the good number of component.");
 
 // AKANTU_DEBUG_ASSERT(nablauq.getSize() == nb_element * nb_points,
 //                  "The vector nablauq(" << nablauq.getID()
 //                  << ") has not the good size.");
 #endif
 
   nablauq.resize(nb_element * nb_points);
 
   GradientOnIntegrationPointsHelper<kind>::call(
       shape_functions, mesh, u, nablauq, nb_degree_of_freedom, type, ghost_type,
       filter_elements);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::initShapeFunctions(
     const GhostType & ghost_type) {
   initShapeFunctions(mesh.getNodes(), ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::initShapeFunctions(
     const Array<Real> & nodes, const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   Mesh::type_iterator it = mesh.firstType(element_dimension, ghost_type, kind);
   Mesh::type_iterator end = mesh.lastType(element_dimension, ghost_type, kind);
   for (; it != end; ++it) {
     ElementType type = *it;
     integrator.initIntegrator(nodes, type, ghost_type);
     const Matrix<Real> & control_points =
         getIntegrationPoints(type, ghost_type);
     shape_functions.initShapeFunctions(nodes, control_points, type, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct IntegrateHelper {};
 
 #define INTEGRATE(type)                                                        \
   integrator.template integrate<type>(f, intf, nb_degree_of_freedom,           \
                                       ghost_type, filter_elements);
 
 #define AKANTU_SPECIALIZE_INTEGRATE_HELPER(kind)                               \
   template <> struct IntegrateHelper<kind> {                                   \
     template <class I>                                                         \
     static void call(const I & integrator, const Array<Real> & f,              \
                      Array<Real> & intf, UInt nb_degree_of_freedom,            \
                      const ElementType & type, const GhostType & ghost_type,   \
                      const Array<UInt> & filter_elements) {                    \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind);                       \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_HELPER)
 
 #undef AKANTU_SPECIALIZE_INTEGRATE_HELPER
 #undef INTEGRATE
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate(
     const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom,
     const ElementType & type, const GhostType & ghost_type,
     const Array<UInt> & filter_elements) const {
 
   UInt nb_element = mesh.getNbElement(type, ghost_type);
   if (filter_elements != empty_filter)
     nb_element = filter_elements.getSize();
 #ifndef AKANTU_NDEBUG
 
   UInt nb_quadrature_points = getNbIntegrationPoints(type);
 
   AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points,
                       "The vector f(" << f.getID() << " size " << f.getSize()
                                       << ") has not the good size ("
                                       << nb_element << ").");
   AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom,
                       "The vector f("
                           << f.getID()
                           << ") has not the good number of component.");
   AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom,
                       "The vector intf("
                           << intf.getID()
                           << ") has not the good number of component.");
 #endif
 
   intf.resize(nb_element);
 
   IntegrateHelper<kind>::call(integrator, f, intf, nb_degree_of_freedom, type,
                               ghost_type, filter_elements);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct IntegrateScalarHelper {};
 
 #define INTEGRATE(type)                                                        \
   integral =                                                                   \
       integrator.template integrate<type>(f, ghost_type, filter_elements);
 
 #define AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER(kind)                        \
   template <> struct IntegrateScalarHelper<kind> {                             \
     template <class I>                                                         \
     static Real call(const I & integrator, const Array<Real> & f,              \
                      const ElementType & type, const GhostType & ghost_type,   \
                      const Array<UInt> & filter_elements) {                    \
       Real integral = 0.;                                                      \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind);                       \
       return integral;                                                         \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER)
 
 #undef AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER
 #undef INTEGRATE
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 Real FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate(
     const Array<Real> & f, const ElementType & type,
     const GhostType & ghost_type, const Array<UInt> & filter_elements) const {
   AKANTU_DEBUG_IN();
 
 #ifndef AKANTU_NDEBUG
   //   std::stringstream sstr; sstr << ghost_type;
   //   AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(),
   //                  "The vector " << nablauq.getID() << " is not taged " <<
   //                  ghost_type);
   UInt nb_element = mesh.getNbElement(type, ghost_type);
   if (filter_elements != empty_filter)
     nb_element = filter_elements.getSize();
 
   UInt nb_quadrature_points = getNbIntegrationPoints(type, ghost_type);
 
   AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points,
                       "The vector f("
                           << f.getID() << ") has not the good size. ("
                           << f.getSize()
                           << "!=" << nb_quadrature_points * nb_element << ")");
   AKANTU_DEBUG_ASSERT(f.getNbComponent() == 1,
                       "The vector f("
                           << f.getID()
                           << ") has not the good number of component.");
 #endif
 
   Real integral = IntegrateScalarHelper<kind>::call(
       integrator, f, type, ghost_type, filter_elements);
   AKANTU_DEBUG_OUT();
   return integral;
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct IntegrateScalarOnOneElementHelper {};
 
 #define INTEGRATE(type)                                                        \
   res = integrator.template integrate<type>(f, index, ghost_type);
 
 #define AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER(kind)         \
   template <> struct IntegrateScalarOnOneElementHelper<kind> {                 \
     template <class I>                                                         \
     static Real call(const I & integrator, const Vector<Real> & f,             \
                      const ElementType & type, UInt index,                     \
                      const GhostType & ghost_type) {                           \
       Real res = 0.;                                                           \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind);                       \
       return res;                                                              \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER)
 
 #undef AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER
 #undef INTEGRATE
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 Real FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate(
     const Vector<Real> & f, const ElementType & type, UInt index,
     const GhostType & ghost_type) const {
 
   Real res = IntegrateScalarOnOneElementHelper<kind>::call(integrator, f, type,
                                                            index, ghost_type);
   return res;
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct IntegrateOnIntegrationPointsHelper {};
 
 #define INTEGRATE(type)                                                        \
   integrator.template integrateOnIntegrationPoints<type>(                      \
       f, intf, nb_degree_of_freedom, ghost_type, filter_elements);
 
 #define AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER(kind)         \
   template <> struct IntegrateOnIntegrationPointsHelper<kind> {                \
     template <class I>                                                         \
     static void call(const I & integrator, const Array<Real> & f,              \
                      Array<Real> & intf, UInt nb_degree_of_freedom,            \
                      const ElementType & type, const GhostType & ghost_type,   \
                      const Array<UInt> & filter_elements) {                    \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind);                       \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER)
 
 #undef AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER
 #undef INTEGRATE
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     integrateOnIntegrationPoints(const Array<Real> & f, Array<Real> & intf,
                                  UInt nb_degree_of_freedom,
                                  const ElementType & type,
                                  const GhostType & ghost_type,
                                  const Array<UInt> & filter_elements) const {
 
   UInt nb_element = mesh.getNbElement(type, ghost_type);
   if (filter_elements != empty_filter)
     nb_element = filter_elements.getSize();
   UInt nb_quadrature_points = getNbIntegrationPoints(type);
 #ifndef AKANTU_NDEBUG
   //   std::stringstream sstr; sstr << ghost_type;
   //   AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(),
   //                  "The vector " << nablauq.getID() << " is not taged " <<
   //                  ghost_type);
 
   AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points,
                       "The vector f(" << f.getID() << " size " << f.getSize()
                                       << ") has not the good size ("
                                       << nb_element << ").");
   AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom,
                       "The vector f("
                           << f.getID()
                           << ") has not the good number of component.");
   AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom,
                       "The vector intf("
                           << intf.getID()
                           << ") has not the good number of component.");
 #endif
 
   intf.resize(nb_element * nb_quadrature_points);
   IntegrateOnIntegrationPointsHelper<kind>::call(integrator, f, intf,
                                                  nb_degree_of_freedom, type,
                                                  ghost_type, filter_elements);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct InterpolateOnIntegrationPointsHelper {
   template <class S>
   static void call(__attribute__((unused)) const S & shape_functions,
                    __attribute__((unused)) const Array<Real> & u,
                    __attribute__((unused)) Array<Real> & uq,
                    __attribute__((unused)) const UInt nb_degree_of_freedom,
                    __attribute__((unused)) const ElementType & type,
                    __attribute__((unused)) const GhostType & ghost_type,
                    __attribute__((unused))
                    const Array<UInt> & filter_elements) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 };
 
 #define INTERPOLATE(type)                                                      \
   shape_functions.template interpolateOnIntegrationPoints<type>(               \
       u, uq, nb_degree_of_freedom, ghost_type, filter_elements);
 
 #define AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER(kind)       \
   template <> struct InterpolateOnIntegrationPointsHelper<kind> {              \
     template <class S>                                                         \
     static void call(const S & shape_functions, const Array<Real> & u,         \
                      Array<Real> & uq, const UInt nb_degree_of_freedom,        \
                      const ElementType & type, const GhostType & ghost_type,   \
                      const Array<UInt> & filter_elements) {                    \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTERPOLATE, kind);                     \
     }                                                                          \
   };
 AKANTU_BOOST_ALL_KIND_LIST(
     AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER,
     AKANTU_FE_ENGINE_LIST_INTERPOLATE_ON_INTEGRATION_POINTS)
 
 #undef AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER
 #undef INTERPOLATE
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     interpolateOnIntegrationPoints(const Array<Real> & u, Array<Real> & uq,
                                    const UInt nb_degree_of_freedom,
                                    const ElementType & type,
                                    const GhostType & ghost_type,
                                    const Array<UInt> & filter_elements) const {
   AKANTU_DEBUG_IN();
 
   UInt nb_points =
       shape_functions.getIntegrationPoints(type, ghost_type).cols();
   UInt nb_element = mesh.getNbElement(type, ghost_type);
   if (filter_elements != empty_filter)
     nb_element = filter_elements.getSize();
 #ifndef AKANTU_NDEBUG
 
   AKANTU_DEBUG_ASSERT(u.getSize() == mesh.getNbNodes(),
                       "The vector u(" << u.getID()
                                       << ") has not the good size.");
   AKANTU_DEBUG_ASSERT(u.getNbComponent() == nb_degree_of_freedom,
                       "The vector u("
                           << u.getID()
                           << ") has not the good number of component.");
   AKANTU_DEBUG_ASSERT(uq.getNbComponent() == nb_degree_of_freedom,
                       "The vector uq("
                           << uq.getID()
                           << ") has not the good number of component.");
 #endif
 
   uq.resize(nb_element * nb_points);
 
   InterpolateOnIntegrationPointsHelper<kind>::call(shape_functions, u, uq,
                                                    nb_degree_of_freedom, type,
                                                    ghost_type, filter_elements);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     interpolateOnIntegrationPoints(
         const Array<Real> & u, ElementTypeMapArray<Real> & uq,
         const ElementTypeMapArray<UInt> * filter_elements) const {
   AKANTU_DEBUG_IN();
 
   const Array<UInt> * filter = NULL;
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType ghost_type = *gt;
     ElementTypeMapArray<Real>::type_iterator it =
         uq.firstType(_all_dimensions, ghost_type, kind);
     ElementTypeMapArray<Real>::type_iterator last =
         uq.lastType(_all_dimensions, ghost_type, kind);
 
     for (; it != last; ++it) {
       ElementType type = *it;
 
       UInt nb_quad_per_element = getNbIntegrationPoints(type, ghost_type);
 
       UInt nb_element = 0;
 
       if (filter_elements) {
         filter = &((*filter_elements)(type, ghost_type));
         nb_element = filter->getSize();
       } else {
         filter = &empty_filter;
         nb_element = mesh.getNbElement(type, ghost_type);
       }
 
       UInt nb_tot_quad = nb_quad_per_element * nb_element;
 
       Array<Real> & quad = uq(type, ghost_type);
       quad.resize(nb_tot_quad);
 
       interpolateOnIntegrationPoints(u, quad, quad.getNbComponent(), type,
                                      ghost_type, *filter);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     computeIntegrationPointsCoordinates(
         ElementTypeMapArray<Real> & quadrature_points_coordinates,
         const ElementTypeMapArray<UInt> * filter_elements) const {
 
   const Array<Real> & nodes_coordinates = mesh.getNodes();
 
   interpolateOnIntegrationPoints(
       nodes_coordinates, quadrature_points_coordinates, filter_elements);
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     computeIntegrationPointsCoordinates(
         Array<Real> & quadrature_points_coordinates, const ElementType & type,
         const GhostType & ghost_type,
         const Array<UInt> & filter_elements) const {
 
   const Array<Real> & nodes_coordinates = mesh.getNodes();
 
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   interpolateOnIntegrationPoints(
       nodes_coordinates, quadrature_points_coordinates, spatial_dimension, type,
       ghost_type, filter_elements);
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     initElementalFieldInterpolationFromIntegrationPoints(
         const ElementTypeMapArray<Real> & interpolation_points_coordinates,
         ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
         ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
         const ElementTypeMapArray<UInt> * element_filter) const {
 
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = this->mesh.getSpatialDimension();
 
   ElementTypeMapArray<Real> quadrature_points_coordinates(
       "quadrature_points_coordinates_for_interpolation", getID(),
       getMemoryID());
 
   quadrature_points_coordinates.initialize(
-      *this, _nb_component = spatial_dimension,
-      _spatial_dimension = spatial_dimension);
+      *this, _nb_component = spatial_dimension);
 
   computeIntegrationPointsCoordinates(quadrature_points_coordinates,
                                       element_filter);
   shape_functions.initElementalFieldInterpolationFromIntegrationPoints(
       interpolation_points_coordinates,
       interpolation_points_coordinates_matrices,
       quad_points_coordinates_inv_matrices, quadrature_points_coordinates,
       element_filter);
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     interpolateElementalFieldFromIntegrationPoints(
         const ElementTypeMapArray<Real> & field,
         const ElementTypeMapArray<Real> & interpolation_points_coordinates,
         ElementTypeMapArray<Real> & result, const GhostType ghost_type,
         const ElementTypeMapArray<UInt> * element_filter) const {
 
   ElementTypeMapArray<Real> interpolation_points_coordinates_matrices(
       "interpolation_points_coordinates_matrices", id, memory_id);
   ElementTypeMapArray<Real> quad_points_coordinates_inv_matrices(
       "quad_points_coordinates_inv_matrices", id, memory_id);
 
   initElementalFieldInterpolationFromIntegrationPoints(
       interpolation_points_coordinates,
       interpolation_points_coordinates_matrices,
       quad_points_coordinates_inv_matrices, element_filter);
 
   interpolateElementalFieldFromIntegrationPoints(
       field, interpolation_points_coordinates_matrices,
       quad_points_coordinates_inv_matrices, result, ghost_type, element_filter);
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     interpolateElementalFieldFromIntegrationPoints(
         const ElementTypeMapArray<Real> & field,
         const ElementTypeMapArray<Real> &
             interpolation_points_coordinates_matrices,
         const ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
         ElementTypeMapArray<Real> & result, const GhostType ghost_type,
         const ElementTypeMapArray<UInt> * element_filter) const {
 
   shape_functions.interpolateElementalFieldFromIntegrationPoints(
       field, interpolation_points_coordinates_matrices,
       quad_points_coordinates_inv_matrices, result, ghost_type, element_filter);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct InterpolateHelper {
   template <class S>
   static void call(__attribute__((unused)) const S & shape_functions,
                    __attribute__((unused)) const Vector<Real> & real_coords,
                    __attribute__((unused)) UInt elem,
                    __attribute__((unused)) const Matrix<Real> & nodal_values,
                    __attribute__((unused)) Vector<Real> & interpolated,
                    __attribute__((unused)) const ElementType & type,
                    __attribute__((unused)) const GhostType & ghost_type) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 };
 
 #define INTERPOLATE(type)                                                      \
   shape_functions.template interpolate<type>(                                  \
       real_coords, element, nodal_values, interpolated, ghost_type);
 
 #define AKANTU_SPECIALIZE_INTERPOLATE_HELPER(kind)                             \
   template <> struct InterpolateHelper<kind> {                                 \
     template <class S>                                                         \
     static void call(const S & shape_functions,                                \
                      const Vector<Real> & real_coords, UInt element,           \
                      const Matrix<Real> & nodal_values,                        \
                      Vector<Real> & interpolated, const ElementType & type,    \
                      const GhostType & ghost_type) {                           \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTERPOLATE, kind);                     \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_INTERPOLATE_HELPER,
                            AKANTU_FE_ENGINE_LIST_INTERPOLATE)
 
 #undef AKANTU_SPECIALIZE_INTERPOLATE_HELPER
 #undef INTERPOLATE
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::interpolate(
     const Vector<Real> & real_coords, const Matrix<Real> & nodal_values,
     Vector<Real> & interpolated, const Element & element) const {
 
   AKANTU_DEBUG_IN();
 
   InterpolateHelper<kind>::call(shape_functions, real_coords, element.element,
                                 nodal_values, interpolated, element.type,
                                 element.ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     computeNormalsOnIntegrationPoints(const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   computeNormalsOnIntegrationPoints(mesh.getNodes(), ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     computeNormalsOnIntegrationPoints(const Array<Real> & field,
                                       const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   //  Real * coord = mesh.getNodes().storage();
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   // allocate the normal arrays
   Mesh::type_iterator it = mesh.firstType(element_dimension, ghost_type, kind);
   Mesh::type_iterator end = mesh.lastType(element_dimension, ghost_type, kind);
   for (; it != end; ++it) {
     ElementType type = *it;
     UInt size = mesh.getNbElement(type, ghost_type);
     if (normals_on_integration_points.exists(type, ghost_type)) {
       normals_on_integration_points(type, ghost_type).resize(size);
     } else {
       normals_on_integration_points.alloc(size, spatial_dimension, type,
                                           ghost_type);
     }
   }
 
   // loop over the type to build the normals
   it = mesh.firstType(element_dimension, ghost_type, kind);
   for (; it != end; ++it) {
     Array<Real> & normals_on_quad =
         normals_on_integration_points(*it, ghost_type);
     computeNormalsOnIntegrationPoints(field, normals_on_quad, *it, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct ComputeNormalsOnIntegrationPoints {
   template <template <ElementKind, class> class I,
             template <ElementKind> class S, ElementKind k, class IOF>
   static void call(__attribute__((unused))
                    const FEEngineTemplate<I, S, k, IOF> & fem,
                    __attribute__((unused)) const Array<Real> & field,
                    __attribute__((unused)) Array<Real> & normal,
                    __attribute__((unused)) const ElementType & type,
                    __attribute__((unused)) const GhostType & ghost_type) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 };
 
 #define COMPUTE_NORMALS_ON_INTEGRATION_POINTS(type)                            \
   fem.template computeNormalsOnIntegrationPoints<type>(field, normal,          \
                                                        ghost_type);
 
 #define AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS(kind)          \
   template <> struct ComputeNormalsOnIntegrationPoints<kind> {                 \
     template <template <ElementKind, class> class I,                           \
               template <ElementKind> class S, ElementKind k, class IOF>        \
     static void call(const FEEngineTemplate<I, S, k, IOF> & fem,               \
                      const Array<Real> & field, Array<Real> & normal,          \
                      const ElementType & type, const GhostType & ghost_type) { \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_NORMALS_ON_INTEGRATION_POINTS,  \
                                        kind);                                  \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND_LIST(
     AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS,
     AKANTU_FE_ENGINE_LIST_COMPUTE_NORMALS_ON_INTEGRATION_POINTS)
 
 #undef AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS
 #undef COMPUTE_NORMALS_ON_INTEGRATION_POINTS
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     computeNormalsOnIntegrationPoints(const Array<Real> & field,
                                       Array<Real> & normal,
                                       const ElementType & type,
                                       const GhostType & ghost_type) const {
   ComputeNormalsOnIntegrationPoints<kind>::call(*this, field, normal, type,
                                                 ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 template <ElementType type>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     computeNormalsOnIntegrationPoints(const Array<Real> & field,
                                       Array<Real> & normal,
                                       const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh.getSpatialDimension();
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
   UInt nb_points = getNbIntegrationPoints(type, ghost_type);
 
   UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize();
   normal.resize(nb_element * nb_points);
   Array<Real>::matrix_iterator normals_on_quad =
       normal.begin_reinterpret(spatial_dimension, nb_points, nb_element);
   Array<Real> f_el(0, spatial_dimension * nb_nodes_per_element);
   FEEngine::extractNodalToElementField(mesh, field, f_el, type, ghost_type);
 
   const Matrix<Real> & quads =
       integrator.template getIntegrationPoints<type>(ghost_type);
 
   Array<Real>::matrix_iterator f_it =
       f_el.begin(spatial_dimension, nb_nodes_per_element);
 
   for (UInt elem = 0; elem < nb_element; ++elem) {
     ElementClass<type>::computeNormalsOnNaturalCoordinates(quads, *f_it,
                                                            *normals_on_quad);
     ++normals_on_quad;
     ++f_it;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /* Matrix lumping functions                                                   */
 /* -------------------------------------------------------------------------- */
 
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct AssembleLumpedTemplateHelper {};
 
 #define ASSEMBLE_LUMPED(type)                                                  \
   fem.template assembleLumpedTemplate<type>(field_1, lumped, dof_id,           \
                                             dof_manager, ghost_type)
 
 #define AKANTU_SPECIALIZE_ASSEMBLE_HELPER(kind)                                \
   template <> struct AssembleLumpedTemplateHelper<kind> {                      \
     template <template <ElementKind, class> class I,                           \
               template <ElementKind> class S, ElementKind k, class IOF>        \
     static void call(const FEEngineTemplate<I, S, k, IOF> & fem,               \
                      const Array<Real> & field_1, const ID & lumped,           \
                      const ID & dof_id, DOFManager & dof_manager,              \
                      ElementType type, const GhostType & ghost_type) {         \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(ASSEMBLE_LUMPED, kind);                 \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_ASSEMBLE_HELPER)
 
 #undef AKANTU_SPECIALIZE_ASSEMBLE_HELPER
 #undef ASSEMBLE_LUMPED
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IOF>
 void FEEngineTemplate<I, S, kind, IOF>::assembleFieldLumped(
     const Array<Real> & field, const ID & lumped, const ID & dof_id,
     DOFManager & dof_manager, ElementType type,
     const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   AssembleLumpedTemplateHelper<kind>::call(*this, field, lumped, dof_id,
                                            dof_manager, type, ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct AssembleFieldMatrixHelper {};
 
 #define ASSEMBLE_MATRIX(type)                                                  \
   fem.template assembleFieldMatrix<Functor, type>(                             \
       field_funct, matrix_id, dof_id, dof_manager, ghost_type)
 
 #define AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER(kind)                   \
   template <> struct AssembleFieldMatrixHelper<kind> {                         \
     template <template <ElementKind, class> class I,                           \
               template <ElementKind> class S, ElementKind k, class IOF,        \
               class Functor>                                                   \
     static void call(const FEEngineTemplate<I, S, k, IOF> & fem,               \
                      Functor field_funct, const ID & matrix_id,                \
                      const ID & dof_id, DOFManager & dof_manager,              \
                      ElementType type, const GhostType & ghost_type) {         \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(ASSEMBLE_MATRIX, kind);                 \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER)
 
 #undef AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER
 #undef ASSEMBLE_MATRIX
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IOF>
 template <class Functor>
 void FEEngineTemplate<I, S, kind, IOF>::assembleFieldMatrix(
     Functor field_funct, const ID & matrix_id, const ID & dof_id,
     DOFManager & dof_manager, ElementType type,
     const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
   AssembleFieldMatrixHelper<kind>::template call(
       *this, field_funct, matrix_id, dof_id, dof_manager, type, ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 template <ElementType type>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     assembleLumpedTemplate(const Array<Real> & field, const ID & lumped,
                            const ID & dof_id, DOFManager & dof_manager,
                            const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
   this->template assembleLumpedRowSum<type>(field, lumped, dof_id, dof_manager,
                                             ghost_type);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV =
  * \int \rho \varphi_i dV @f$
  */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 template <ElementType type>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     assembleLumpedRowSum(const Array<Real> & field, const ID & lumped,
                          const ID & dof_id, DOFManager & dof_manager,
                          const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   UInt shapes_size = ElementClass<type>::getShapeSize();
   UInt nb_degree_of_freedom = field.getNbComponent();
 
   Array<Real> * field_times_shapes =
       new Array<Real>(0, shapes_size * nb_degree_of_freedom);
 
   shape_functions.template fieldTimesShapes<type>(field, *field_times_shapes,
                                                   ghost_type);
 
   UInt nb_element = mesh.getNbElement(type, ghost_type);
   Array<Real> * int_field_times_shapes = new Array<Real>(
       nb_element, shapes_size * nb_degree_of_freedom, "inte_rho_x_shapes");
 
   integrator.template integrate<type>(
       *field_times_shapes, *int_field_times_shapes,
       nb_degree_of_freedom * shapes_size, ghost_type, empty_filter);
 
   delete field_times_shapes;
 
   dof_manager.assembleElementalArrayToLumpedMatrix(
       dof_id, *int_field_times_shapes, lumped, type, ghost_type);
 
   delete int_field_times_shapes;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * @f$ \tilde{M}_{i} = c * M_{ii} = \int_{V_e} \rho dV @f$
  */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 template <ElementType type>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::
     assembleLumpedDiagonalScaling(const Array<Real> & field, const ID & lumped,
                                   const ID & dof_id, DOFManager & dof_manager,
                                   const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   const ElementType & type_p1 = ElementClass<type>::getP1ElementType();
   UInt nb_nodes_per_element_p1 = Mesh::getNbNodesPerElement(type_p1);
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
   UInt nb_quadrature_points =
       integrator.template getIntegrationPoints<type>(ghost_type).cols();
   UInt nb_degree_of_freedom = field.getNbComponent();
 
   UInt nb_element = field.getSize() / nb_quadrature_points;
   Vector<Real> nodal_factor(nb_nodes_per_element);
 
 #define ASSIGN_WEIGHT_TO_NODES(corner, mid)                                    \
   {                                                                            \
     for (UInt n = 0; n < nb_nodes_per_element_p1; n++)                         \
       nodal_factor(n) = corner;                                                \
     for (UInt n = nb_nodes_per_element_p1; n < nb_nodes_per_element; n++)      \
       nodal_factor(n) = mid;                                                   \
   }
 
   if (type == _triangle_6)
     ASSIGN_WEIGHT_TO_NODES(1. / 12., 1. / 4.);
   if (type == _tetrahedron_10)
     ASSIGN_WEIGHT_TO_NODES(1. / 32., 7. / 48.);
   if (type == _quadrangle_8)
     ASSIGN_WEIGHT_TO_NODES(
         3. / 76.,
         16. / 76.); /** coeff. derived by scaling
                      * the diagonal terms of the corresponding
                      * consistent mass computed with 3x3 gauss points;
                      * coeff. are (1./36., 8./36.) for 2x2 gauss points */
   if (type == _hexahedron_20)
     ASSIGN_WEIGHT_TO_NODES(
         7. / 248.,
         16. / 248.); /** coeff. derived by scaling
                       * the diagonal terms of the corresponding
                       * consistent mass computed with 3x3x3 gauss points;
                       * coeff. are (1./40.,
                       * 1./15.) for 2x2x2 gauss points */
   if (type == _pentahedron_15) {
     // coefficients derived by scaling the diagonal terms of the corresponding
     // consistent mass computed with 8 gauss points;
     for (UInt n = 0; n < nb_nodes_per_element_p1; n++)
       nodal_factor(n) = 51. / 2358.;
 
     Real mid_triangle = 192. / 2358.;
     Real mid_quadrangle = 300. / 2358.;
 
     nodal_factor(6) = mid_triangle;
     nodal_factor(7) = mid_triangle;
     nodal_factor(8) = mid_triangle;
     nodal_factor(9) = mid_quadrangle;
     nodal_factor(10) = mid_quadrangle;
     nodal_factor(11) = mid_quadrangle;
     nodal_factor(12) = mid_triangle;
     nodal_factor(13) = mid_triangle;
     nodal_factor(14) = mid_triangle;
   }
 
   if (nb_element == 0) {
     AKANTU_DEBUG_OUT();
     return;
   }
 
 #undef ASSIGN_WEIGHT_TO_NODES
 
   /// compute @f$ \int \rho dV = \rho V @f$ for each element
   Array<Real> * int_field =
       new Array<Real>(field.getSize(), nb_degree_of_freedom, "inte_rho_x");
   integrator.template integrate<type>(field, *int_field, nb_degree_of_freedom,
                                       ghost_type, empty_filter);
 
   /// distribute the mass of the element to the nodes
   Array<Real> * lumped_per_node = new Array<Real>(
       nb_element, nb_degree_of_freedom * nb_nodes_per_element, "mass_per_node");
   Array<Real>::const_vector_iterator int_field_it =
       int_field->begin(nb_degree_of_freedom);
   Array<Real>::matrix_iterator lumped_per_node_it =
       lumped_per_node->begin(nb_degree_of_freedom, nb_nodes_per_element);
 
   for (UInt e = 0; e < nb_element; ++e) {
     for (UInt n = 0; n < nb_nodes_per_element; ++n) {
       Vector<Real> l = (*lumped_per_node_it)(n);
       l = *int_field_it;
       l *= nodal_factor(n);
     }
     ++int_field_it;
     ++lumped_per_node_it;
   }
   delete int_field;
 
   dof_manager.assembleElementalArrayToLumpedMatrix(dof_id, *lumped_per_node,
                                                    lumped, type, ghost_type);
   delete lumped_per_node;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV =
  * \int \rho \varphi_i dV @f$
  */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 template <class Functor, ElementType type>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::assembleFieldMatrix(
     Functor field_funct, const ID & matrix_id, const ID & dof_id,
     DOFManager & dof_manager, const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   UInt shapes_size = ElementClass<type>::getShapeSize();
   UInt nb_degree_of_freedom = dof_manager.getDOFs(dof_id).getNbComponent();
   UInt lmat_size = nb_degree_of_freedom * shapes_size;
   UInt nb_element = mesh.getNbElement(type, ghost_type);
 
   // \int N * N  so degree 2 * degree of N
   const UInt polynomial_degree =
       2 * ElementClassProperty<type>::polynomial_degree;
 
   Matrix<Real> integration_points =
       integrator.template getIntegrationPoints<type, polynomial_degree>();
 
   UInt nb_integration_points = integration_points.cols();
   UInt vect_size = nb_integration_points * nb_element;
 
   Array<Real> shapes(0, shapes_size);
   shape_functions.template computeShapesOnIntegrationPoints<type>(
       mesh.getNodes(), integration_points, shapes, ghost_type);
 
   Array<Real> integration_points_pos(vect_size, mesh.getSpatialDimension());
   shape_functions.template interpolateOnIntegrationPoints<type>(
       mesh.getNodes(), integration_points_pos, mesh.getSpatialDimension(),
       shapes, ghost_type, empty_filter);
 
   Array<Real> * modified_shapes =
       new Array<Real>(vect_size, lmat_size * nb_degree_of_freedom);
   modified_shapes->clear();
   Array<Real> * local_mat = new Array<Real>(vect_size, lmat_size * lmat_size);
 
   Array<Real>::matrix_iterator mshapes_it =
       modified_shapes->begin(nb_degree_of_freedom, lmat_size);
   Array<Real>::const_vector_iterator shapes_it = shapes.begin(shapes_size);
 
   for (UInt q = 0; q < vect_size; ++q, ++mshapes_it, ++shapes_it) {
     for (UInt d = 0; d < nb_degree_of_freedom; ++d) {
       for (UInt s = 0; s < shapes_size; ++s) {
         (*mshapes_it)(d, s * nb_degree_of_freedom + d) = (*shapes_it)(s);
       }
     }
   }
 
   Array<Real> field(vect_size, nb_degree_of_freedom);
   Array<Real>::matrix_iterator field_c_it = field.begin_reinterpret(
       nb_degree_of_freedom, nb_integration_points, nb_element);
   Array<Real>::const_matrix_iterator pos_it =
       integration_points_pos.begin_reinterpret(
           mesh.getSpatialDimension(), nb_integration_points, nb_element);
   Element el;
   el.type = type, el.ghost_type = ghost_type;
 
   for (el.element = 0; el.element < nb_element;
        ++el.element, ++field_c_it, ++pos_it) {
     field_funct(*field_c_it, el, *pos_it);
   }
 
   mshapes_it = modified_shapes->begin(nb_degree_of_freedom, lmat_size);
   Array<Real>::matrix_iterator lmat = local_mat->begin(lmat_size, lmat_size);
   Array<Real>::const_vector_iterator field_it =
       field.begin_reinterpret(nb_degree_of_freedom, field.getSize());
 
   for (UInt q = 0; q < vect_size; ++q, ++lmat, ++mshapes_it, ++field_it) {
     const Vector<Real> & rho = *field_it;
     const Matrix<Real> & N = *mshapes_it;
     Matrix<Real> & mat = *lmat;
 
     Matrix<Real> Nt = N.transpose();
     for (UInt d = 0; d < Nt.cols(); ++d) {
       Nt(d) *= rho(d);
     }
 
     mat.mul<false, false>(Nt, N);
   }
 
   delete modified_shapes;
 
   Array<Real> * int_field_times_shapes =
       new Array<Real>(nb_element, lmat_size * lmat_size, "inte_rho_x_shapes");
   this->integrator.template integrate<type, polynomial_degree>(
       *local_mat, *int_field_times_shapes, lmat_size * lmat_size, ghost_type);
   delete local_mat;
 
   dof_manager.assembleElementalMatricesToMatrix(
       matrix_id, dof_id, *int_field_times_shapes, type, ghost_type);
   delete int_field_times_shapes;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct InverseMapHelper {
   template <class S>
   static void call(__attribute__((unused)) const S & shape_functions,
                    __attribute__((unused)) const Vector<Real> & real_coords,
                    __attribute__((unused)) UInt element,
                    __attribute__((unused)) const ElementType & type,
                    __attribute__((unused)) Vector<Real> & natural_coords,
                    __attribute__((unused)) const GhostType & ghost_type) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 };
 
 #define INVERSE_MAP(type)                                                      \
   shape_functions.template inverseMap<type>(real_coords, element,              \
                                             natural_coords, ghost_type);
 
 #define AKANTU_SPECIALIZE_INVERSE_MAP_HELPER(kind)                             \
   template <> struct InverseMapHelper<kind> {                                  \
     template <class S>                                                         \
     static void call(const S & shape_functions,                                \
                      const Vector<Real> & real_coords, UInt element,           \
                      const ElementType & type, Vector<Real> & natural_coords,  \
                      const GhostType & ghost_type) {                           \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(INVERSE_MAP, kind);                     \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_INVERSE_MAP_HELPER,
                            AKANTU_FE_ENGINE_LIST_INVERSE_MAP)
 
 #undef AKANTU_SPECIALIZE_INVERSE_MAP_HELPER
 #undef INVERSE_MAP
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::inverseMap(
     const Vector<Real> & real_coords, UInt element, const ElementType & type,
     Vector<Real> & natural_coords, const GhostType & ghost_type) const {
 
   AKANTU_DEBUG_IN();
 
   InverseMapHelper<kind>::call(shape_functions, real_coords, element, type,
                                natural_coords, ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct ContainsHelper {
   template <class S>
   static void call(__attribute__((unused)) const S & shape_functions,
                    __attribute__((unused)) const Vector<Real> & real_coords,
                    __attribute__((unused)) UInt element,
                    __attribute__((unused)) const ElementType & type,
                    __attribute__((unused)) const GhostType & ghost_type) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 };
 
 #define CONTAINS(type)                                                         \
   contain = shape_functions.template contains<type>(real_coords, element,      \
                                                     ghost_type);
 
 #define AKANTU_SPECIALIZE_CONTAINS_HELPER(kind)                                \
   template <> struct ContainsHelper<kind> {                                    \
     template <template <ElementKind> class S, ElementKind k>                   \
     static bool call(const S<k> & shape_functions,                             \
                      const Vector<Real> & real_coords, UInt element,           \
                      const ElementType & type, const GhostType & ghost_type) { \
       bool contain = false;                                                    \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(CONTAINS, kind);                        \
       return contain;                                                          \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_CONTAINS_HELPER,
                            AKANTU_FE_ENGINE_LIST_CONTAINS)
 
 #undef AKANTU_SPECIALIZE_CONTAINS_HELPER
 #undef CONTAINS
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline bool FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::contains(
     const Vector<Real> & real_coords, UInt element, const ElementType & type,
     const GhostType & ghost_type) const {
   return ContainsHelper<kind>::call(shape_functions, real_coords, element, type,
                                     ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct ComputeShapesHelper {
   template <class S>
   static void call(__attribute__((unused)) const S & shape_functions,
                    __attribute__((unused)) const Vector<Real> & real_coords,
                    __attribute__((unused)) UInt element,
                    __attribute__((unused)) const ElementType type,
                    __attribute__((unused)) Vector<Real> & shapes,
                    __attribute__((unused)) const GhostType & ghost_type) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 };
 
 #define COMPUTE_SHAPES(type)                                                   \
   shape_functions.template computeShapes<type>(real_coords, element, shapes,   \
                                                ghost_type);
 
 #define AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER(kind)                          \
   template <> struct ComputeShapesHelper<kind> {                               \
     template <class S>                                                         \
     static void call(const S & shape_functions,                                \
                      const Vector<Real> & real_coords, UInt element,           \
                      const ElementType type, Vector<Real> & shapes,            \
                      const GhostType & ghost_type) {                           \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_SHAPES, kind);                  \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER,
                            AKANTU_FE_ENGINE_LIST_COMPUTE_SHAPES)
 
 #undef AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER
 #undef COMPUTE_SHAPES
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline void
 FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapes(
     const Vector<Real> & real_coords, UInt element, const ElementType & type,
     Vector<Real> & shapes, const GhostType & ghost_type) const {
 
   AKANTU_DEBUG_IN();
 
   ComputeShapesHelper<kind>::call(shape_functions, real_coords, element, type,
                                   shapes, ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct ComputeShapeDerivativesHelper {
   template <class S>
   static void call(__attribute__((unused)) const S & shape_functions,
                    __attribute__((unused)) const Vector<Real> & real_coords,
                    __attribute__((unused)) UInt element,
                    __attribute__((unused)) const ElementType type,
                    __attribute__((unused)) Matrix<Real> & shape_derivatives,
                    __attribute__((unused)) const GhostType & ghost_type) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 };
 
 #define COMPUTE_SHAPE_DERIVATIVES(type)                                        \
   Matrix<Real> coords_mat(real_coords.storage(), shape_derivatives.rows(), 1); \
   Tensor3<Real> shapesd_tensor(shape_derivatives.storage(),                    \
                                shape_derivatives.rows(),                       \
                                shape_derivatives.cols(), 1);                   \
   shape_functions.template computeShapeDerivatives<type>(                      \
       coords_mat, element, shapesd_tensor, ghost_type);
 
 #define AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER(kind)               \
   template <> struct ComputeShapeDerivativesHelper<kind> {                     \
     template <class S>                                                         \
     static void call(const S & shape_functions,                                \
                      const Vector<Real> & real_coords, UInt element,           \
                      const ElementType type, Matrix<Real> & shape_derivatives, \
                      const GhostType & ghost_type) {                           \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_SHAPE_DERIVATIVES, kind);       \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER,
                            AKANTU_FE_ENGINE_LIST_COMPUTE_SHAPES_DERIVATIVES)
 
 #undef AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER
 #undef COMPUTE_SHAPE_DERIVATIVES
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline void
 FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapeDerivatives(
     const Vector<Real> & real_coords, UInt element, const ElementType & type,
     Matrix<Real> & shape_derivatives, const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   ComputeShapeDerivativesHelper<kind>::call(shape_functions, real_coords,
                                             element, type, shape_derivatives,
                                             ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct GetNbIntegrationPointsHelper {};
 
 #define GET_NB_INTEGRATION_POINTS(type)                                        \
   nb_quad_points = integrator.template getNbIntegrationPoints<type>(ghost_type);
 
 #define AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER(kind)               \
   template <> struct GetNbIntegrationPointsHelper<kind> {                      \
     template <template <ElementKind, class> class I, ElementKind k, class IOF> \
     static UInt call(const I<k, IOF> & integrator, const ElementType type,     \
                      const GhostType & ghost_type) {                           \
       UInt nb_quad_points = 0;                                                 \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_NB_INTEGRATION_POINTS, kind);       \
       return nb_quad_points;                                                   \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER)
 
 #undef AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER
 #undef GET_NB_INTEGRATION
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline UInt
 FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getNbIntegrationPoints(
     const ElementType & type, const GhostType & ghost_type) const {
   return GetNbIntegrationPointsHelper<kind>::call(integrator, type, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct GetShapesHelper {};
 
 #define GET_SHAPES(type) ret = &(shape_functions.getShapes(type, ghost_type));
 
 #define AKANTU_SPECIALIZE_GET_SHAPES_HELPER(kind)                              \
   template <> struct GetShapesHelper<kind> {                                   \
     template <class S>                                                         \
     static const Array<Real> & call(const S & shape_functions,                 \
                                     const ElementType type,                    \
                                     const GhostType & ghost_type) {            \
       const Array<Real> * ret = NULL;                                          \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_SHAPES, kind);                      \
       return *ret;                                                             \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_SHAPES_HELPER)
 
 #undef AKANTU_SPECIALIZE_GET_SHAPES_HELPER
 #undef GET_SHAPES
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline const Array<Real> &
 FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getShapes(
     const ElementType & type, const GhostType & ghost_type,
     __attribute__((unused)) UInt id) const {
   return GetShapesHelper<kind>::call(shape_functions, type, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct GetShapesDerivativesHelper {
   template <template <ElementKind> class S, ElementKind k>
   static const Array<Real> &
   call(__attribute__((unused)) const S<k> & shape_functions,
        __attribute__((unused)) const ElementType & type,
        __attribute__((unused)) const GhostType & ghost_type,
        __attribute__((unused)) UInt id) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 };
 
 #define GET_SHAPES_DERIVATIVES(type)                                           \
   ret = &(shape_functions.getShapesDerivatives(type, ghost_type));
 
 #define AKANTU_SPECIALIZE_GET_SHAPES_DERIVATIVES_HELPER(kind)                  \
   template <> struct GetShapesDerivativesHelper<kind> {                        \
     template <template <ElementKind> class S, ElementKind k>                   \
     static const Array<Real> &                                                 \
     call(const S<k> & shape_functions, const ElementType type,                 \
          const GhostType & ghost_type, __attribute__((unused)) UInt id) {      \
       const Array<Real> * ret = NULL;                                          \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_SHAPES_DERIVATIVES, kind);          \
       return *ret;                                                             \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_GET_SHAPES_DERIVATIVES_HELPER,
                            AKANTU_FE_ENGINE_LIST_GET_SHAPES_DERIVATIVES)
 
 #undef AKANTU_SPECIALIZE_GET_SHAPE_DERIVATIVES_HELPER
 #undef GET_SHAPES_DERIVATIVES
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline const Array<Real> &
 FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getShapesDerivatives(
     const ElementType & type, const GhostType & ghost_type,
     __attribute__((unused)) UInt id) const {
   return GetShapesDerivativesHelper<kind>::call(shape_functions, type,
                                                 ghost_type, id);
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Helper class to be able to write a partial specialization on the element kind
  */
 template <ElementKind kind> struct GetIntegrationPointsHelper {};
 
 #define GET_INTEGRATION_POINTS(type)                                           \
   ret = &(integrator.template getIntegrationPoints<type>(ghost_type));
 
 #define AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER(kind)                  \
   template <> struct GetIntegrationPointsHelper<kind> {                        \
     template <template <ElementKind, class> class I, ElementKind k, class IOF> \
     static const Matrix<Real> & call(const I<k, IOF> & integrator,             \
                                      const ElementType type,                   \
                                      const GhostType & ghost_type) {           \
       const Matrix<Real> * ret = NULL;                                         \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_INTEGRATION_POINTS, kind);          \
       return *ret;                                                             \
     }                                                                          \
   };
 
 AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER)
 
 #undef AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER
 #undef GET_INTEGRATION_POINTS
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline const Matrix<Real> &
 FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getIntegrationPoints(
     const ElementType & type, const GhostType & ghost_type) const {
   return GetIntegrationPointsHelper<kind>::call(integrator, type, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::printself(
     std::ostream & stream, int indent) const {
   std::string space;
   for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
     ;
 
   stream << space << "FEEngineTemplate [" << std::endl;
   stream << space << " + parent [" << std::endl;
   FEEngine::printself(stream, indent + 3);
   stream << space << "   ]" << std::endl;
   stream << space << " + shape functions [" << std::endl;
   shape_functions.printself(stream, indent + 3);
   stream << space << "   ]" << std::endl;
   stream << space << " + integrator [" << std::endl;
   integrator.printself(stream, indent + 3);
   stream << space << "   ]" << std::endl;
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 
 } // akantu
 
 #include "integrator_gauss.hh"
 #include "shape_lagrange.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <>
 template <>
 inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>::
     assembleLumpedTemplate<_triangle_6>(const Array<Real> & field,
                                         const ID & lumped, const ID & dof_id,
                                         DOFManager & dof_manager,
                                         const GhostType & ghost_type) const {
   assembleLumpedDiagonalScaling<_triangle_6>(field, lumped, dof_id, dof_manager,
                                              ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 template <>
 inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular,
                              DefaultIntegrationOrderFunctor>::
     assembleLumpedTemplate<_tetrahedron_10>(
         const Array<Real> & field, const ID & lumped, const ID & dof_id,
         DOFManager & dof_manager, const GhostType & ghost_type) const {
   assembleLumpedDiagonalScaling<_tetrahedron_10>(field, lumped, dof_id,
                                                  dof_manager, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 template <>
 inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>::
     assembleLumpedTemplate<_quadrangle_8>(const Array<Real> & field,
                                           const ID & lumped, const ID & dof_id,
                                           DOFManager & dof_manager,
                                           const GhostType & ghost_type) const {
   assembleLumpedDiagonalScaling<_quadrangle_8>(field, lumped, dof_id,
                                                dof_manager, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 template <>
 inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>::
     assembleLumpedTemplate<_hexahedron_20>(const Array<Real> & field,
                                            const ID & lumped, const ID & dof_id,
                                            DOFManager & dof_manager,
                                            const GhostType & ghost_type) const {
   assembleLumpedDiagonalScaling<_hexahedron_20>(field, lumped, dof_id,
                                                 dof_manager, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 template <>
 inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular,
                              DefaultIntegrationOrderFunctor>::
     assembleLumpedTemplate<_pentahedron_15>(
         const Array<Real> & field, const ID & lumped, const ID & dof_id,
         DOFManager & dof_manager, const GhostType & ghost_type) const {
   assembleLumpedDiagonalScaling<_pentahedron_15>(field, lumped, dof_id,
                                                  dof_manager, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 template <>
 inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular,
                              DefaultIntegrationOrderFunctor>::
     computeNormalsOnIntegrationPoints<_point_1>(
         const Array<Real> &, Array<Real> & normal,
         const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(mesh.getSpatialDimension() == 1,
                       "Mesh dimension must be 1 to compute normals on points!");
   const ElementType type = _point_1;
   UInt spatial_dimension = mesh.getSpatialDimension();
   // UInt nb_nodes_per_element  = Mesh::getNbNodesPerElement(type);
   UInt nb_points = getNbIntegrationPoints(type, ghost_type);
 
   UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize();
   normal.resize(nb_element * nb_points);
   Array<Real>::matrix_iterator normals_on_quad =
       normal.begin_reinterpret(spatial_dimension, nb_points, nb_element);
   const Array<std::vector<Element>> & segments =
       mesh.getElementToSubelement(type, ghost_type);
   const Array<Real> & coords = mesh.getNodes();
 
   const Mesh * mesh_segment;
   if (mesh.isMeshFacets())
     mesh_segment = &(mesh.getMeshParent());
   else
     mesh_segment = &mesh;
 
   for (UInt elem = 0; elem < nb_element; ++elem) {
     UInt nb_segment = segments(elem).size();
 
     AKANTU_DEBUG_ASSERT(
         nb_segment > 0,
         "Impossible to compute a normal on a point connected to 0 segments");
 
     Real normal_value = 1;
     if (nb_segment == 1) {
       const Element & segment = segments(elem)[0];
       const Array<UInt> & segment_connectivity =
           mesh_segment->getConnectivity(segment.type, segment.ghost_type);
       // const Vector<UInt> & segment_points =
       // segment_connectivity.begin(Mesh::getNbNodesPerElement(segment.type))[segment.element];
       Real difference;
       if (segment_connectivity(0) == elem) {
         difference = coords(elem) - coords(segment_connectivity(1));
       } else {
         difference = coords(elem) - coords(segment_connectivity(0));
       }
       normal_value = difference / std::abs(difference);
     }
 
     for (UInt n(0); n < nb_points; ++n) {
       (*normals_on_quad)(0, n) = normal_value;
     }
     ++normals_on_quad;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 } // akantu
diff --git a/src/io/dumper/dumpable_iohelper.hh b/src/io/dumper/dumpable_iohelper.hh
index db0a8ee8c..1ffe18fd8 100644
--- a/src/io/dumper/dumpable_iohelper.hh
+++ b/src/io/dumper/dumpable_iohelper.hh
@@ -1,195 +1,196 @@
 /**
  * @file   dumpable_iohelper.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author David Simon Kammer <david.kammer@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Tue Jan 06 2015
  * @date last modification: Thu Nov 19 2015
  *
  * @brief  Interface for object who wants to dump themselves
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "dumper_iohelper.hh"
+/* -------------------------------------------------------------------------- */
+#include <set>
 /* -------------------------------------------------------------------------- */
 #ifndef __AKANTU_DUMPABLE_IOHELPER_HH__
 #define __AKANTU_DUMPABLE_IOHELPER_HH__
 /* -------------------------------------------------------------------------- */
 
-#include "dumper_iohelper.hh"
-#include <set>
-
 namespace akantu {
 
 class Dumpable {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   Dumpable();
   virtual ~Dumpable();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// create a new dumper (of templated type T) and register it under
   /// dumper_name. file_name is used for construction of T. is default states if
   /// this dumper is the default dumper.
   template<class T>
   inline void registerDumper(const std::string & dumper_name,
                              const std::string & file_name = "",
                              const bool is_default = false);
 
   /// register an externally created dumper
   void registerExternalDumper(DumperIOHelper & dumper,
                               const std::string & dumper_name,
                               const bool is_default = false);
 
   /// register a mesh to the default dumper
   void addDumpMesh(const Mesh & mesh, UInt spatial_dimension = _all_dimensions,
                    const GhostType & ghost_type = _not_ghost,
                    const ElementKind & element_kind = _ek_not_defined);
 
   /// register a mesh to the default identified by its name
   void addDumpMeshToDumper(const std::string & dumper_name,
                            const Mesh & mesh, UInt spatial_dimension = _all_dimensions,
                            const GhostType & ghost_type = _not_ghost,
                            const ElementKind & element_kind = _ek_not_defined);
 
   /// register a filtered mesh as the default dumper
   void addDumpFilteredMesh(const Mesh & mesh,
                            const ElementTypeMapArray<UInt> & elements_filter,
                            const Array<UInt> & nodes_filter,
                            UInt spatial_dimension = _all_dimensions,
                            const GhostType & ghost_type = _not_ghost,
                            const ElementKind & element_kind = _ek_not_defined);
 
   /// register a filtered mesh and provides a name
   void addDumpFilteredMeshToDumper(const std::string & dumper_name,
                                    const Mesh & mesh,
                                    const ElementTypeMapArray<UInt> & elements_filter,
                                    const Array<UInt> & nodes_filter,
                                    UInt spatial_dimension = _all_dimensions,
                                    const GhostType & ghost_type = _not_ghost,
                                    const ElementKind & element_kind = _ek_not_defined);
 
   /// to implement
   virtual void addDumpField(const std::string & field_id);
   /// to implement
   virtual void addDumpFieldToDumper(const std::string & dumper_name,
                                     const std::string & field_id);
   /// add a field
   virtual void addDumpFieldExternal(const std::string & field_id,
                                     dumper::Field * field);
   virtual void addDumpFieldExternalToDumper(const std::string & dumper_name,
                                             const std::string & field_id,
                                             dumper::Field * field);
 
   template<typename T>
   inline void addDumpFieldExternal(const std::string & field_id,
                                    const Array<T> & field);
   template<typename T>
   inline void addDumpFieldExternalToDumper(const std::string & dumper_name,
                                     const std::string & field_id,
                                     const Array<T> & field);
   template<typename T>
   inline void addDumpFieldExternal(const std::string & field_id,
                                    const ElementTypeMapArray<T> & field,
                                    UInt spatial_dimension = _all_dimensions,
                                    const GhostType & ghost_type = _not_ghost,
                                    const ElementKind & element_kind = _ek_not_defined);
   template<typename T>
   inline void addDumpFieldExternalToDumper(const std::string & dumper_name,
                                     const std::string & field_id,
                                     const ElementTypeMapArray<T> & field,
                                     UInt spatial_dimension = _all_dimensions,
                                     const GhostType & ghost_type = _not_ghost,
                                     const ElementKind & element_kind = _ek_not_defined);
 
   void removeDumpField(const std::string & field_id);
   void removeDumpFieldFromDumper(const std::string & dumper_name,
                                  const std::string & field_id);
 
   virtual void addDumpFieldVector(const std::string & field_id);
   virtual void addDumpFieldVectorToDumper(const std::string & dumper_name,
                                           const std::string & field_id);
 
   virtual void addDumpFieldTensor(const std::string & field_id);
   virtual void addDumpFieldTensorToDumper(const std::string & dumper_name,
                                           const std::string & field_id);
 
   void setDirectory(const std::string & directory);
   void setDirectoryToDumper(const std::string & dumper_name,
                             const std::string & directory);
 
   void setBaseName(const std::string & basename);
 
   void setBaseNameToDumper(const std::string & dumper_name,
                            const std::string & basename);
   void setTimeStepToDumper(Real time_step);
   void setTimeStepToDumper(const std::string & dumper_name,
                            Real time_step);
 
 
   void setTextModeToDumper(const std::string & dumper_name);
   void setTextModeToDumper();
 
   virtual void dump();
   virtual void dump(UInt step);
   virtual void dump(Real time, UInt step);
   virtual void dump(const std::string & dumper_name);
   virtual void dump(const std::string & dumper_name, UInt step);
   virtual void dump(const std::string & dumper_name, Real time, UInt step);
 
 
 public:
   void internalAddDumpFieldToDumper(const std::string & dumper_name,
                                     const std::string & field_id,
                                     dumper::Field * field);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   DumperIOHelper & getDumper();
   DumperIOHelper & getDumper(const std::string & dumper_name);
 
   template<class T> T & getDumper(const std::string & dumper_name);
   std::string getDefaultDumperName() const;
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   typedef std::map<std::string, DumperIOHelper *> DumperMap;
   typedef std::set<std::string> DumperSet;
 
   DumperMap dumpers;
   std::string default_dumper;
 };
 
 } // akantu
 
 #endif /* __AKANTU_DUMPABLE_IOHELPER_HH__ */
diff --git a/src/mesh/element_type_map_tmpl.hh b/src/mesh/element_type_map_tmpl.hh
index cac4ae88c..6a6e038e3 100644
--- a/src/mesh/element_type_map_tmpl.hh
+++ b/src/mesh/element_type_map_tmpl.hh
@@ -1,623 +1,623 @@
 /**
  * @file   element_type_map_tmpl.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Aug 31 2011
  * @date last modification: Fri Oct 02 2015
  *
  * @brief  implementation of template functions of the ElementTypeMap and
  * ElementTypeMapArray classes
  *
  * @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 "element_type_map.hh"
 #include "mesh.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_ELEMENT_TYPE_MAP_TMPL_HH__
 #define __AKANTU_ELEMENT_TYPE_MAP_TMPL_HH__
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 /* ElementTypeMap */
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline std::string
 ElementTypeMap<Stored, SupportType>::printType(const SupportType & type,
                                                const GhostType & ghost_type) {
   std::stringstream sstr;
   sstr << "(" << ghost_type << ":" << type << ")";
   return sstr.str();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline bool ElementTypeMap<Stored, SupportType>::exists(
     const SupportType & type, const GhostType & ghost_type) const {
   return this->getData(ghost_type).find(type) !=
          this->getData(ghost_type).end();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline const Stored & ElementTypeMap<Stored, SupportType>::
 operator()(const SupportType & type, const GhostType & ghost_type) const {
   typename DataMap::const_iterator it = this->getData(ghost_type).find(type);
 
   if (it == this->getData(ghost_type).end())
     AKANTU_SILENT_EXCEPTION("No element of type "
                             << ElementTypeMap::printType(type, ghost_type)
                             << " in this ElementTypeMap<"
                             << debug::demangle(typeid(Stored).name())
                             << "> class");
   return it->second;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline Stored & ElementTypeMap<Stored, SupportType>::
 operator()(const SupportType & type, const GhostType & ghost_type) {
   return this->getData(ghost_type)[type];
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline Stored & ElementTypeMap<Stored, SupportType>::
 operator()(const Stored & insert, const SupportType & type,
            const GhostType & ghost_type) {
   typename DataMap::iterator it = this->getData(ghost_type).find(type);
 
   if (it != this->getData(ghost_type).end()) {
     AKANTU_SILENT_EXCEPTION("Element of type "
                             << ElementTypeMap::printType(type, ghost_type)
                             << " already in this ElementTypeMap<"
                             << debug::demangle(typeid(Stored).name())
                             << "> class");
   } else {
     DataMap & data = this->getData(ghost_type);
     const std::pair<typename DataMap::iterator, bool> & res =
         data.insert(std::pair<ElementType, Stored>(type, insert));
     it = res.first;
   }
 
   return it->second;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline typename ElementTypeMap<Stored, SupportType>::DataMap &
 ElementTypeMap<Stored, SupportType>::getData(GhostType ghost_type) {
   if (ghost_type == _not_ghost)
     return data;
   else
     return ghost_data;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline const typename ElementTypeMap<Stored, SupportType>::DataMap &
 ElementTypeMap<Stored, SupportType>::getData(GhostType ghost_type) const {
   if (ghost_type == _not_ghost)
     return data;
   else
     return ghost_data;
 }
 
 /* -------------------------------------------------------------------------- */
 /// Works only if stored is a pointer to a class with a printself method
 template <class Stored, typename SupportType>
 void ElementTypeMap<Stored, SupportType>::printself(std::ostream & stream,
                                                     int indent) const {
   std::string space;
   for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
     ;
 
   stream << space << "ElementTypeMap<" << debug::demangle(typeid(Stored).name())
          << "> [" << std::endl;
   for (UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType)g;
 
     const DataMap & data = getData(gt);
     typename DataMap::const_iterator it;
     for (it = data.begin(); it != data.end(); ++it) {
       stream << space << space << ElementTypeMap::printType(it->first, gt)
              << std::endl;
     }
   }
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 ElementTypeMap<Stored, SupportType>::ElementTypeMap() {
   AKANTU_DEBUG_IN();
 
   // std::stringstream sstr;
   // if(parent_id != "") sstr << parent_id << ":";
   // sstr << id;
 
   // this->id = sstr.str();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 ElementTypeMap<Stored, SupportType>::~ElementTypeMap() {}
 
 /* -------------------------------------------------------------------------- */
 /* ElementTypeMapArray                                                        */
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 inline Array<T> & ElementTypeMapArray<T, SupportType>::alloc(
     UInt size, UInt nb_component, const SupportType & type,
     const GhostType & ghost_type, const T & default_value) {
   std::string ghost_id = "";
   if (ghost_type == _ghost)
     ghost_id = ":ghost";
 
   Array<T> * tmp;
 
   typename ElementTypeMapArray<T, SupportType>::DataMap::iterator it =
       this->getData(ghost_type).find(type);
 
   if (it == this->getData(ghost_type).end()) {
     std::stringstream sstr;
     sstr << this->id << ":" << type << ghost_id;
     tmp = &(Memory::alloc<T>(sstr.str(), size, nb_component, default_value));
     std::stringstream sstrg;
     sstrg << ghost_type;
     // tmp->setTag(sstrg.str());
     this->getData(ghost_type)[type] = tmp;
   } else {
     AKANTU_DEBUG_INFO(
         "The vector "
         << this->id << this->printType(type, ghost_type)
         << " already exists, it is resized instead of allocated.");
     tmp = it->second;
     it->second->resize(size);
   }
 
   return *tmp;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 inline void
 ElementTypeMapArray<T, SupportType>::alloc(UInt size, UInt nb_component,
                                            const SupportType & type,
                                            const T & default_value) {
   this->alloc(size, nb_component, type, _not_ghost, default_value);
   this->alloc(size, nb_component, type, _ghost, default_value);
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 inline void ElementTypeMapArray<T, SupportType>::free() {
   AKANTU_DEBUG_IN();
 
   for (UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType)g;
 
     DataMap & data = this->getData(gt);
     typename DataMap::const_iterator it;
     for (it = data.begin(); it != data.end(); ++it) {
       dealloc(it->second->getID());
     }
     data.clear();
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 inline void ElementTypeMapArray<T, SupportType>::clear() {
   for (UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType)g;
 
     DataMap & data = this->getData(gt);
     typename DataMap::const_iterator it;
     for (it = data.begin(); it != data.end(); ++it) {
       it->second->clear();
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 inline const Array<T> & ElementTypeMapArray<T, SupportType>::
 operator()(const SupportType & type, const GhostType & ghost_type) const {
   typename ElementTypeMapArray<T, SupportType>::DataMap::const_iterator it =
       this->getData(ghost_type).find(type);
 
   if (it == this->getData(ghost_type).end())
     AKANTU_SILENT_EXCEPTION("No element of type "
                             << ElementTypeMapArray::printType(type, ghost_type)
                             << " in this const ElementTypeMapArray<"
                             << debug::demangle(typeid(T).name()) << "> class(\""
                             << this->id << "\")");
   return *(it->second);
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 inline Array<T> & ElementTypeMapArray<T, SupportType>::
 operator()(const SupportType & type, const GhostType & ghost_type) {
   typename ElementTypeMapArray<T, SupportType>::DataMap::iterator it =
       this->getData(ghost_type).find(type);
 
   if (it == this->getData(ghost_type).end())
     AKANTU_SILENT_EXCEPTION("No element of type "
                             << ElementTypeMapArray::printType(type, ghost_type)
                             << " in this ElementTypeMapArray<"
                             << debug::demangle(typeid(T).name())
                             << "> class (\"" << this->id << "\")");
 
   return *(it->second);
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 inline void
 ElementTypeMapArray<T, SupportType>::setArray(const SupportType & type,
                                               const GhostType & ghost_type,
                                               const Array<T> & vect) {
   typename ElementTypeMapArray<T, SupportType>::DataMap::iterator it =
       this->getData(ghost_type).find(type);
 
   if (AKANTU_DEBUG_TEST(dblWarning) && it != this->getData(ghost_type).end() &&
       it->second != &vect) {
     AKANTU_DEBUG_WARNING(
         "The Array "
         << this->printType(type, ghost_type)
         << " is already registred, this call can lead to a memory leak.");
   }
 
   this->getData(ghost_type)[type] = &(const_cast<Array<T> &>(vect));
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 inline void ElementTypeMapArray<T, SupportType>::onElementsRemoved(
     const ElementTypeMapArray<UInt> & new_numbering) {
   for (UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType)g;
     ElementTypeMapArray<UInt>::type_iterator it =
         new_numbering.firstType(_all_dimensions, gt, _ek_not_defined);
     ElementTypeMapArray<UInt>::type_iterator end =
         new_numbering.lastType(_all_dimensions, gt, _ek_not_defined);
     for (; it != end; ++it) {
       SupportType type = *it;
       if (this->exists(type, gt)) {
         const Array<UInt> & renumbering = new_numbering(type, gt);
         if (renumbering.getSize() == 0)
           continue;
         Array<T> & vect = this->operator()(type, gt);
         UInt nb_component = vect.getNbComponent();
         Array<T> tmp(renumbering.getSize(), nb_component);
         UInt new_size = 0;
         for (UInt i = 0; i < vect.getSize(); ++i) {
           UInt new_i = renumbering(i);
           if (new_i != UInt(-1)) {
             memcpy(tmp.storage() + new_i * nb_component,
                    vect.storage() + i * nb_component, nb_component * sizeof(T));
             ++new_size;
           }
         }
         tmp.resize(new_size);
         vect.copy(tmp);
       }
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 void ElementTypeMapArray<T, SupportType>::printself(std::ostream & stream,
                                                     int indent) const {
   std::string space;
   for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
     ;
 
   stream << space << "ElementTypeMapArray<" << debug::demangle(typeid(T).name())
          << "> [" << std::endl;
   for (UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType)g;
 
     const DataMap & data = this->getData(gt);
     typename DataMap::const_iterator it;
     for (it = data.begin(); it != data.end(); ++it) {
       stream << space << space << ElementTypeMapArray::printType(it->first, gt)
              << " [" << std::endl;
       it->second->printself(stream, indent + 3);
       stream << space << space << " ]" << std::endl;
     }
   }
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 /* SupportType Iterator                                                       */
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 ElementTypeMap<Stored, SupportType>::type_iterator::type_iterator(
     DataMapIterator & list_begin, DataMapIterator & list_end, UInt dim,
     ElementKind ek)
     : list_begin(list_begin), list_end(list_end), dim(dim), kind(ek) {}
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 ElementTypeMap<Stored, SupportType>::type_iterator::type_iterator(
     const type_iterator & it)
     : list_begin(it.list_begin), list_end(it.list_end), dim(it.dim),
       kind(it.kind) {}
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 typename ElementTypeMap<Stored, SupportType>::type_iterator &
 ElementTypeMap<Stored, SupportType>::type_iterator::
 operator=(const type_iterator & it) {
   if (this != &it) {
     list_begin = it.list_begin;
     list_end = it.list_end;
     dim = it.dim;
     kind = it.kind;
   }
   return *this;
 }
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline typename ElementTypeMap<Stored, SupportType>::type_iterator::reference
     ElementTypeMap<Stored, SupportType>::type_iterator::operator*() {
   return list_begin->first;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline typename ElementTypeMap<Stored, SupportType>::type_iterator::reference
     ElementTypeMap<Stored, SupportType>::type_iterator::operator*() const {
   return list_begin->first;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline typename ElementTypeMap<Stored, SupportType>::type_iterator &
     ElementTypeMap<Stored, SupportType>::type_iterator::operator++() {
   ++list_begin;
   while ((list_begin != list_end) &&
          (((dim != _all_dimensions) &&
            (dim != Mesh::getSpatialDimension(list_begin->first))) ||
           ((kind != _ek_not_defined) &&
            (kind != Mesh::getKind(list_begin->first)))))
     ++list_begin;
   return *this;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 typename ElementTypeMap<Stored, SupportType>::type_iterator
     ElementTypeMap<Stored, SupportType>::type_iterator::operator++(int) {
   type_iterator tmp(*this);
   operator++();
   return tmp;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline bool ElementTypeMap<Stored, SupportType>::type_iterator::
 operator==(const type_iterator & other) const {
   return this->list_begin == other.list_begin;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline bool ElementTypeMap<Stored, SupportType>::type_iterator::
 operator!=(const type_iterator & other) const {
   return this->list_begin != other.list_begin;
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 typename ElementTypeMap<Stored, SupportType>::ElementTypesIteratorHelper
 ElementTypeMap<Stored, SupportType>::elementTypes(UInt dim,
                                                   GhostType ghost_type,
                                                   ElementKind kind) const {
   return ElementTypesIteratorHelper(*this, dim, ghost_type, kind);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline typename ElementTypeMap<Stored, SupportType>::type_iterator
 ElementTypeMap<Stored, SupportType>::firstType(UInt dim, GhostType ghost_type,
                                                ElementKind kind) const {
   typename DataMap::const_iterator b, e;
   b = getData(ghost_type).begin();
   e = getData(ghost_type).end();
 
   // loop until the first valid type
   while ((b != e) &&
          (((dim != _all_dimensions) &&
            (dim != Mesh::getSpatialDimension(b->first))) ||
           ((kind != _ek_not_defined) && (kind != Mesh::getKind(b->first)))))
     ++b;
 
   return typename ElementTypeMap<Stored, SupportType>::type_iterator(b, e, dim,
                                                                      kind);
 }
 
 /* -------------------------------------------------------------------------- */
 template <class Stored, typename SupportType>
 inline typename ElementTypeMap<Stored, SupportType>::type_iterator
 ElementTypeMap<Stored, SupportType>::lastType(UInt dim, GhostType ghost_type,
                                               ElementKind kind) const {
   typename DataMap::const_iterator e;
   e = getData(ghost_type).end();
   return typename ElementTypeMap<Stored, SupportType>::type_iterator(e, e, dim,
                                                                      kind);
 }
 
 /* -------------------------------------------------------------------------- */
 
 /// standard output stream operator
 template <class Stored, typename SupportType>
 inline std::ostream &
 operator<<(std::ostream & stream,
            const ElementTypeMap<Stored, SupportType> & _this) {
   _this.printself(stream);
   return stream;
 }
 
 /* -------------------------------------------------------------------------- */
 class ElementTypeMapArrayInializer {
 public:
   ElementTypeMapArrayInializer(UInt spatial_dimension = _all_dimensions,
                                UInt nb_component = 1,
                                const GhostType & ghost_type = _not_ghost,
                                const ElementKind & element_kind = _ek_regular)
       : spatial_dimension(spatial_dimension), nb_component(nb_component),
         ghost_type(ghost_type), element_kind(element_kind) {}
 
   const GhostType & ghostType() const { return ghost_type; }
 
 protected:
   UInt spatial_dimension;
   UInt nb_component;
   GhostType ghost_type;
   ElementKind element_kind;
 };
 
 /* -------------------------------------------------------------------------- */
 class MeshElementTypeMapArrayInializer : public ElementTypeMapArrayInializer {
 public:
   MeshElementTypeMapArrayInializer(
       const Mesh & mesh, UInt spatial_dimension = _all_dimensions,
       UInt nb_component = 1, const GhostType & ghost_type = _not_ghost,
       const ElementKind & element_kind = _ek_regular,
       bool with_nb_element = false, bool with_nb_nodes_per_element = false)
       : ElementTypeMapArrayInializer(spatial_dimension, nb_component,
                                      ghost_type, element_kind),
         mesh(mesh), with_nb_element(with_nb_element),
         with_nb_nodes_per_element(with_nb_nodes_per_element) {}
 
   decltype(auto) elementTypes() const {
     return mesh.elementTypes(this->spatial_dimension, this->ghost_type,
                              this->element_kind);
   }
 
   virtual UInt size(const ElementType & type) const {
     if (with_nb_element)
       return mesh.getNbElement(type, this->ghost_type);
 
     return 0;
   }
 
   UInt nbComponent(const ElementType & type) const {
     if (with_nb_nodes_per_element)
       return (this->nb_component * mesh.getNbNodesPerElement(type));
 
     return this->nb_component;
   }
 
 protected:
   const Mesh & mesh;
   bool with_nb_element;
   bool with_nb_nodes_per_element;
 };
 
 /* -------------------------------------------------------------------------- */
 class FEEngineElementTypeMapArrayInializer
     : public MeshElementTypeMapArrayInializer {
 public:
   FEEngineElementTypeMapArrayInializer(
       const FEEngine & fe_engine, UInt spatial_dimension = _all_dimensions,
       UInt nb_component = 1, const GhostType & ghost_type = _not_ghost,
       const ElementKind & element_kind = _ek_regular);
 
   UInt size(const ElementType & type) const override;
 
 protected:
   const FEEngine & fe_engine;
 };
 
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 template <class Func>
 void ElementTypeMapArray<T, SupportType>::initialize(const Func & f,
                                                      const T & default_value) {
   for (auto & type : f.elementTypes()) {
     if (not this->exists(type, f.ghostType()))
       this->alloc(f.size(type), f.nbComponent(type), type, f.ghostType(),
                   default_value);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 template <typename... pack>
 void ElementTypeMapArray<T, SupportType>::initialize(const Mesh & mesh,
                                                      pack &&... _pack) {
   GhostType requested_ghost_type = OPTIONAL_NAMED_ARG(ghost_type, _casper);
   bool all_ghost_types = requested_ghost_type == _casper;
 
   for (auto ghost_type : ghost_types) {
     if ((not(ghost_type == requested_ghost_type)) and (not all_ghost_types))
       continue;
 
-    this->initialize(MeshElementTypeMapArrayInializer(
-                         mesh, OPTIONAL_NAMED_ARG(nb_component, 1),
-                         OPTIONAL_NAMED_ARG(spatial_dimension, _all_dimensions),
-                         ghost_type,
-                         OPTIONAL_NAMED_ARG(element_kind, _ek_regular),
-                         OPTIONAL_NAMED_ARG(with_nb_element, false),
-                         OPTIONAL_NAMED_ARG(with_nb_nodes_per_element, false)),
-                     OPTIONAL_NAMED_ARG(default_value, T()));
+    this->initialize(
+        MeshElementTypeMapArrayInializer(
+            mesh, OPTIONAL_NAMED_ARG(nb_component, 1),
+            OPTIONAL_NAMED_ARG(spatial_dimension, mesh.getSpatialDimension()),
+            ghost_type, OPTIONAL_NAMED_ARG(element_kind, _ek_regular),
+            OPTIONAL_NAMED_ARG(with_nb_element, false),
+            OPTIONAL_NAMED_ARG(with_nb_nodes_per_element, false)),
+        OPTIONAL_NAMED_ARG(default_value, T()));
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T, typename SupportType>
 template <typename... pack>
 void ElementTypeMapArray<T, SupportType>::initialize(const FEEngine & fe_engine,
                                                      pack &&... _pack) {
   bool all_ghost_types = OPTIONAL_NAMED_ARG(all_ghost_types, true);
   GhostType requested_ghost_type = OPTIONAL_NAMED_ARG(ghost_type, _not_ghost);
 
   for (auto ghost_type : ghost_types) {
     if ((not(ghost_type == requested_ghost_type)) and (not all_ghost_types))
       continue;
 
     this->initialize(FEEngineElementTypeMapArrayInializer(
                          fe_engine,
                          OPTIONAL_NAMED_ARG(spatial_dimension, _all_dimensions),
                          OPTIONAL_NAMED_ARG(nb_component, 1), ghost_type,
                          OPTIONAL_NAMED_ARG(element_kind, _ek_regular)),
                      OPTIONAL_NAMED_ARG(default_value, T()));
   }
 }
 
 } // namespace akantu
 
 #endif /* __AKANTU_ELEMENT_TYPE_MAP_TMPL_HH__ */
diff --git a/src/mesh/group_manager.cc b/src/mesh/group_manager.cc
index b3a7e9e17..18afdb476 100644
--- a/src/mesh/group_manager.cc
+++ b/src/mesh/group_manager.cc
@@ -1,1029 +1,1030 @@
 /**
  * @file   group_manager.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Dana Christen <dana.christen@gmail.com>
  * @author David Simon Kammer <david.kammer@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Wed Nov 13 2013
  * @date last modification: Mon Aug 17 2015
  *
  * @brief  Stores information about ElementGroup and NodeGroup
  *
  * @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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "group_manager.hh"
 #include "aka_csr.hh"
 #include "data_accessor.hh"
 #include "element_group.hh"
 #include "element_synchronizer.hh"
 #include "mesh.hh"
 #include "mesh_utils.hh"
 #include "node_group.hh"
 /* -------------------------------------------------------------------------- */
 #include <algorithm>
 #include <iterator>
 #include <list>
 #include <numeric>
 #include <queue>
 #include <sstream>
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 GroupManager::GroupManager(const Mesh & mesh, const ID & id,
                            const MemoryID & mem_id)
     : id(id), memory_id(mem_id), mesh(mesh) {
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 GroupManager::~GroupManager() {
   auto eit = element_groups.begin();
   auto eend = element_groups.end();
   for (; eit != eend; ++eit)
     delete (eit->second);
 
   auto nit = node_groups.begin();
   auto nend = node_groups.end();
   for (; nit != nend; ++nit)
     delete (nit->second);
 }
 
 /* -------------------------------------------------------------------------- */
 NodeGroup & GroupManager::createNodeGroup(const std::string & group_name,
                                           bool replace_group) {
   AKANTU_DEBUG_IN();
 
   auto it = node_groups.find(group_name);
 
   if (it != node_groups.end()) {
     if (replace_group) {
       it->second->empty();
       AKANTU_DEBUG_OUT();
       return *(it->second);
     } else
       AKANTU_EXCEPTION(
           "Trying to create a node group that already exists:" << group_name);
   }
 
   std::stringstream sstr;
   sstr << this->id << ":" << group_name << "_node_group";
 
   NodeGroup * node_group =
       new NodeGroup(group_name, mesh, sstr.str(), memory_id);
 
   node_groups[group_name] = node_group;
 
   AKANTU_DEBUG_OUT();
 
   return *node_group;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 NodeGroup &
 GroupManager::createFilteredNodeGroup(const std::string & group_name,
                                       const NodeGroup & source_node_group,
                                       T & filter) {
   AKANTU_DEBUG_IN();
 
   NodeGroup & node_group = this->createNodeGroup(group_name);
   node_group.append(source_node_group);
   if (T::type == FilterFunctor::_node_filter_functor) {
     node_group.applyNodeFilter(filter);
   } else {
     AKANTU_DEBUG_ERROR("ElementFilter cannot be applied to NodeGroup yet."
                        << " Needs to be implemented.");
   }
 
   AKANTU_DEBUG_OUT();
   return node_group;
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::destroyNodeGroup(const std::string & group_name) {
   AKANTU_DEBUG_IN();
 
   NodeGroups::iterator nit = node_groups.find(group_name);
   NodeGroups::iterator nend = node_groups.end();
   if (nit != nend) {
     delete (nit->second);
     node_groups.erase(nit);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 ElementGroup & GroupManager::createElementGroup(const std::string & group_name,
                                                 UInt dimension,
                                                 bool replace_group) {
   AKANTU_DEBUG_IN();
 
   NodeGroup & new_node_group =
       createNodeGroup(group_name + "_nodes", replace_group);
 
   auto it = element_groups.find(group_name);
 
   if (it != element_groups.end()) {
     if (replace_group) {
       it->second->empty();
       AKANTU_DEBUG_OUT();
       return *(it->second);
     } else
       AKANTU_EXCEPTION("Trying to create a element group that already exists:"
                        << group_name);
   }
 
   std::stringstream sstr;
   sstr << this->id << ":" << group_name << "_element_group";
 
   ElementGroup * element_group = new ElementGroup(
       group_name, mesh, new_node_group, dimension, sstr.str(), memory_id);
 
   std::stringstream sstr_nodes;
   sstr_nodes << group_name << "_nodes";
 
   node_groups[sstr_nodes.str()] = &new_node_group;
   element_groups[group_name] = element_group;
 
   AKANTU_DEBUG_OUT();
 
   return *element_group;
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::destroyElementGroup(const std::string & group_name,
                                        bool destroy_node_group) {
   AKANTU_DEBUG_IN();
 
   auto eit = element_groups.find(group_name);
   auto eend = element_groups.end();
   if (eit != eend) {
     if (destroy_node_group)
       destroyNodeGroup(eit->second->getNodeGroup().getName());
     delete (eit->second);
     element_groups.erase(eit);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::destroyAllElementGroups(bool destroy_node_groups) {
   AKANTU_DEBUG_IN();
 
   auto eit = element_groups.begin();
   auto eend = element_groups.end();
   for (; eit != eend; ++eit) {
     if (destroy_node_groups)
       destroyNodeGroup(eit->second->getNodeGroup().getName());
     delete (eit->second);
   }
   element_groups.clear();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 ElementGroup & GroupManager::createElementGroup(const std::string & group_name,
                                                 UInt dimension,
                                                 NodeGroup & node_group) {
   AKANTU_DEBUG_IN();
 
   if (element_groups.find(group_name) != element_groups.end())
     AKANTU_EXCEPTION(
         "Trying to create a element group that already exists:" << group_name);
 
   ElementGroup * element_group =
       new ElementGroup(group_name, mesh, node_group, dimension,
                        id + ":" + group_name + "_element_group", memory_id);
 
   element_groups[group_name] = element_group;
 
   AKANTU_DEBUG_OUT();
 
   return *element_group;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 ElementGroup & GroupManager::createFilteredElementGroup(
     const std::string & group_name, UInt dimension,
     const NodeGroup & node_group, T & filter) {
   AKANTU_DEBUG_IN();
 
   ElementGroup * element_group = NULL;
 
   if (T::type == FilterFunctor::_node_filter_functor) {
     NodeGroup & filtered_node_group = this->createFilteredNodeGroup(
         group_name + "_nodes", node_group, filter);
     element_group =
         &(this->createElementGroup(group_name, dimension, filtered_node_group));
   } else if (T::type == FilterFunctor::_element_filter_functor) {
     AKANTU_DEBUG_ERROR(
         "Cannot handle an ElementFilter yet. Needs to be implemented.");
   }
 
   AKANTU_DEBUG_OUT();
 
   return *element_group;
 }
 
 /* -------------------------------------------------------------------------- */
 class ClusterSynchronizer : public DataAccessor<Element> {
   using DistantIDs = std::set<std::pair<UInt, UInt>>;
 
 public:
   ClusterSynchronizer(GroupManager & group_manager, UInt element_dimension,
                       std::string cluster_name_prefix,
                       ElementTypeMapArray<UInt> & element_to_fragment,
                       const ElementSynchronizer & element_synchronizer,
                       UInt nb_cluster)
       : group_manager(group_manager), element_dimension(element_dimension),
         cluster_name_prefix(cluster_name_prefix),
         element_to_fragment(element_to_fragment),
         element_synchronizer(element_synchronizer), nb_cluster(nb_cluster) {}
 
   UInt synchronize() {
     StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
     UInt rank = comm.whoAmI();
     UInt nb_proc = comm.getNbProc();
 
     /// find starting index to renumber local clusters
     Array<UInt> nb_cluster_per_proc(nb_proc);
     nb_cluster_per_proc(rank) = nb_cluster;
     comm.allGather(nb_cluster_per_proc);
 
     starting_index = std::accumulate(nb_cluster_per_proc.begin(),
                                      nb_cluster_per_proc.begin() + rank, 0);
 
     UInt global_nb_fragment =
         std::accumulate(nb_cluster_per_proc.begin() + rank,
                         nb_cluster_per_proc.end(), starting_index);
 
     /// create the local to distant cluster pairs with neighbors
     element_synchronizer.synchronizeOnce(*this, _gst_gm_clusters);
 
     /// count total number of pairs
     Array<int> nb_pairs(nb_proc); // This is potentially a bug for more than
     // 2**31 pairs, but due to a all gatherv after
     // it must be int to match MPI interfaces
     nb_pairs(rank) = distant_ids.size();
     comm.allGather(nb_pairs);
 
     UInt total_nb_pairs = std::accumulate(nb_pairs.begin(), nb_pairs.end(), 0);
 
     /// generate pairs global array
     UInt local_pair_index =
         std::accumulate(nb_pairs.storage(), nb_pairs.storage() + rank, 0);
 
     Array<UInt> total_pairs(total_nb_pairs, 2);
 
     for (auto & ids : distant_ids) {
       total_pairs(local_pair_index, 0) = ids.first;
       total_pairs(local_pair_index, 1) = ids.second;
       ++local_pair_index;
     }
 
     /// communicate pairs to all processors
     nb_pairs *= 2;
     comm.allGatherV(total_pairs, nb_pairs);
 
     /// renumber clusters
 
     /// generate fragment list
     std::vector<std::set<UInt>> global_clusters;
     UInt total_nb_cluster = 0;
 
     Array<bool> is_fragment_in_cluster(global_nb_fragment, 1, false);
     std::queue<UInt> fragment_check_list;
 
     while (total_pairs.getSize() != 0) {
       /// create a new cluster
       ++total_nb_cluster;
       global_clusters.resize(total_nb_cluster);
       std::set<UInt> & current_cluster = global_clusters[total_nb_cluster - 1];
 
       UInt first_fragment = total_pairs(0, 0);
       UInt second_fragment = total_pairs(0, 1);
       total_pairs.erase(0);
 
       fragment_check_list.push(first_fragment);
       fragment_check_list.push(second_fragment);
 
       while (!fragment_check_list.empty()) {
         UInt current_fragment = fragment_check_list.front();
 
         UInt * total_pairs_end =
             total_pairs.storage() + total_pairs.getSize() * 2;
 
         UInt * fragment_found =
             std::find(total_pairs.storage(), total_pairs_end, current_fragment);
 
         if (fragment_found != total_pairs_end) {
           UInt position = fragment_found - total_pairs.storage();
           UInt pair = position / 2;
           UInt other_index = (position + 1) % 2;
           fragment_check_list.push(total_pairs(pair, other_index));
           total_pairs.erase(pair);
         } else {
           fragment_check_list.pop();
           current_cluster.insert(current_fragment);
           is_fragment_in_cluster(current_fragment) = true;
         }
       }
     }
 
     /// add to FragmentToCluster all local fragments
     for (UInt c = 0; c < global_nb_fragment; ++c) {
       if (!is_fragment_in_cluster(c)) {
         ++total_nb_cluster;
         global_clusters.resize(total_nb_cluster);
         std::set<UInt> & current_cluster =
             global_clusters[total_nb_cluster - 1];
 
         current_cluster.insert(c);
       }
     }
 
     /// reorganize element groups to match global clusters
     for (UInt c = 0; c < global_clusters.size(); ++c) {
 
       /// create new element group corresponding to current cluster
       std::stringstream sstr;
       sstr << cluster_name_prefix << "_" << c;
       ElementGroup & cluster =
           group_manager.createElementGroup(sstr.str(), element_dimension, true);
 
       std::set<UInt>::iterator it = global_clusters[c].begin();
       std::set<UInt>::iterator end = global_clusters[c].end();
 
       /// append to current element group all fragments that belong to
       /// the same cluster if they exist
       for (; it != end; ++it) {
         Int local_index = *it - starting_index;
 
         if (local_index < 0 || local_index >= Int(nb_cluster))
           continue;
 
         std::stringstream tmp_sstr;
         tmp_sstr << "tmp_" << cluster_name_prefix << "_" << local_index;
         auto eg_it = group_manager.element_group_find(tmp_sstr.str());
 
         AKANTU_DEBUG_ASSERT(eg_it != group_manager.element_group_end(),
                             "Temporary fragment \"" << tmp_sstr.str()
                                                     << "\" not found");
 
         cluster.append(*(eg_it->second));
         group_manager.destroyElementGroup(tmp_sstr.str(), true);
       }
     }
 
     return total_nb_cluster;
   }
 
 private:
   /// functions for parallel communications
   inline UInt getNbData(const Array<Element> & elements,
                         const SynchronizationTag & tag) const {
     if (tag == _gst_gm_clusters)
       return elements.getSize() * sizeof(UInt);
 
     return 0;
   }
 
   inline void packData(CommunicationBuffer & buffer,
                        const Array<Element> & elements,
                        const SynchronizationTag & tag) const {
     if (tag != _gst_gm_clusters)
       return;
 
     Array<Element>::const_iterator<> el_it = elements.begin();
     Array<Element>::const_iterator<> el_end = elements.end();
 
     for (; el_it != el_end; ++el_it) {
 
       const Element & el = *el_it;
 
       /// for each element pack its global cluster index
       buffer << element_to_fragment(el.type, el.ghost_type)(el.element) +
                     starting_index;
     }
   }
 
   inline void unpackData(CommunicationBuffer & buffer,
                          const Array<Element> & elements,
                          const SynchronizationTag & tag) {
     if (tag != _gst_gm_clusters)
       return;
 
     Array<Element>::const_iterator<> el_it = elements.begin();
     Array<Element>::const_iterator<> el_end = elements.end();
 
     for (; el_it != el_end; ++el_it) {
       UInt distant_cluster;
 
       buffer >> distant_cluster;
 
       const Element & el = *el_it;
       UInt local_cluster =
           element_to_fragment(el.type, el.ghost_type)(el.element) +
           starting_index;
 
       distant_ids.insert(std::make_pair(local_cluster, distant_cluster));
     }
   }
 
 private:
   GroupManager & group_manager;
   UInt element_dimension;
   std::string cluster_name_prefix;
   ElementTypeMapArray<UInt> & element_to_fragment;
   const ElementSynchronizer & element_synchronizer;
 
   UInt nb_cluster;
   DistantIDs distant_ids;
 
   UInt starting_index;
 };
 
 /* -------------------------------------------------------------------------- */
 /// \todo this function doesn't work in 1D
 UInt GroupManager::createBoundaryGroupFromGeometry() {
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   return createClusters(spatial_dimension - 1, "boundary");
 }
 
 /* -------------------------------------------------------------------------- */
 //// \todo if needed element list construction can be optimized by
 //// templating the filter class
 UInt GroupManager::createClusters(UInt element_dimension,
                                   std::string cluster_name_prefix,
                                   const GroupManager::ClusteringFilter & filter,
                                   Mesh * mesh_facets) {
   AKANTU_DEBUG_IN();
 
   UInt nb_proc = StaticCommunicator::getStaticCommunicator().getNbProc();
   std::string tmp_cluster_name_prefix = cluster_name_prefix;
 
   ElementTypeMapArray<UInt> * element_to_fragment = nullptr;
 
   if (nb_proc > 1 && mesh.isDistributed()) {
     element_to_fragment =
         new ElementTypeMapArray<UInt>("element_to_fragment", id, memory_id);
 
-    element_to_fragment->initialize(mesh, _nb_component = element_dimension,
+    element_to_fragment->initialize(mesh, _nb_component = 1,
+                                    _spatial_dimension = element_dimension,
                                     _element_kind = _ek_not_defined,
                                     _with_nb_element = true);
     // mesh.initElementTypeMapArray(*element_to_fragment, 1, element_dimension,
     //                              false, _ek_not_defined, true);
     tmp_cluster_name_prefix = "tmp_" + tmp_cluster_name_prefix;
   }
 
   /// Get facets
   bool mesh_facets_created = false;
 
   if (!mesh_facets && element_dimension > 0) {
     mesh_facets = new Mesh(mesh.getSpatialDimension(), mesh.getNodes().getID(),
                            "mesh_facets_for_clusters");
 
     mesh_facets->defineMeshParent(mesh);
 
     MeshUtils::buildAllFacets(mesh, *mesh_facets, element_dimension,
                               element_dimension - 1);
   }
 
   ElementTypeMapArray<bool> seen_elements("seen_elements", id, memory_id);
-  seen_elements.initialize(mesh, _nb_component = element_dimension,
+  seen_elements.initialize(mesh, _spatial_dimension = element_dimension,
                             _element_kind = _ek_not_defined,
                             _with_nb_element = true);
   // mesh.initElementTypeMapArray(seen_elements, 1, element_dimension, false,
   //                              _ek_not_defined, true);
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType ghost_type = *gt;
     Element el;
     el.ghost_type = ghost_type;
 
     Mesh::type_iterator type_it =
         mesh.firstType(element_dimension, ghost_type, _ek_not_defined);
     Mesh::type_iterator type_end =
         mesh.lastType(element_dimension, ghost_type, _ek_not_defined);
 
     for (; type_it != type_end; ++type_it) {
       el.type = *type_it;
       el.kind = Mesh::getKind(*type_it);
       UInt nb_element = mesh.getNbElement(*type_it, ghost_type);
       Array<bool> & seen_elements_array = seen_elements(el.type, ghost_type);
 
       for (UInt e = 0; e < nb_element; ++e) {
         el.element = e;
         if (!filter(el))
           seen_elements_array(e) = true;
       }
     }
   }
 
   Array<bool> checked_node(mesh.getNbNodes(), 1, false);
 
   UInt nb_cluster = 0;
 
   /// keep looping until all elements are seen
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType ghost_type = *gt;
     Element uns_el;
     uns_el.ghost_type = ghost_type;
 
     Mesh::type_iterator type_it =
         mesh.firstType(element_dimension, ghost_type, _ek_not_defined);
     Mesh::type_iterator type_end =
         mesh.lastType(element_dimension, ghost_type, _ek_not_defined);
 
     for (; type_it != type_end; ++type_it) {
       uns_el.type = *type_it;
       Array<bool> & seen_elements_vec =
           seen_elements(uns_el.type, uns_el.ghost_type);
 
       for (UInt e = 0; e < seen_elements_vec.getSize(); ++e) {
         // skip elements that have been already seen
         if (seen_elements_vec(e) == true)
           continue;
 
         // set current element
         uns_el.element = e;
         seen_elements_vec(e) = true;
 
         /// create a new cluster
         std::stringstream sstr;
         sstr << tmp_cluster_name_prefix << "_" << nb_cluster;
         ElementGroup & cluster =
             createElementGroup(sstr.str(), element_dimension, true);
         ++nb_cluster;
 
         // point element are cluster by themself
         if (element_dimension == 0) {
           cluster.add(uns_el);
 
           UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(uns_el.type);
           Vector<UInt> connect =
               mesh.getConnectivity(uns_el.type, uns_el.ghost_type)
                   .begin(nb_nodes_per_element)[uns_el.element];
           for (UInt n = 0; n < nb_nodes_per_element; ++n) {
             /// add element's nodes to the cluster
             UInt node = connect[n];
             if (!checked_node(node)) {
               cluster.addNode(node);
               checked_node(node) = true;
             }
           }
 
           continue;
         }
 
         std::queue<Element> element_to_add;
         element_to_add.push(uns_el);
 
         /// keep looping until current cluster is complete (no more
         /// connected elements)
         while (!element_to_add.empty()) {
 
           /// take first element and erase it in the queue
           Element el = element_to_add.front();
           element_to_add.pop();
 
           /// if parallel, store cluster index per element
           if (nb_proc > 1 && mesh.isDistributed())
             (*element_to_fragment)(el.type, el.ghost_type)(el.element) =
                 nb_cluster - 1;
 
           /// add current element to the cluster
           cluster.add(el);
 
           const Array<Element> & element_to_facet =
               mesh_facets->getSubelementToElement(el.type, el.ghost_type);
 
           UInt nb_facet_per_element = element_to_facet.getNbComponent();
 
           for (UInt f = 0; f < nb_facet_per_element; ++f) {
             const Element & facet = element_to_facet(el.element, f);
 
             if (facet == ElementNull)
               continue;
 
             const std::vector<Element> & connected_elements =
                 mesh_facets->getElementToSubelement(
                     facet.type, facet.ghost_type)(facet.element);
 
             for (UInt elem = 0; elem < connected_elements.size(); ++elem) {
               const Element & check_el = connected_elements[elem];
 
               // check if this element has to be skipped
               if (check_el == ElementNull || check_el == el)
                 continue;
 
               Array<bool> & seen_elements_vec_current =
                   seen_elements(check_el.type, check_el.ghost_type);
 
               if (seen_elements_vec_current(check_el.element) == false) {
                 seen_elements_vec_current(check_el.element) = true;
                 element_to_add.push(check_el);
               }
             }
           }
 
           UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type);
           Vector<UInt> connect = mesh.getConnectivity(el.type, el.ghost_type)
                                      .begin(nb_nodes_per_element)[el.element];
           for (UInt n = 0; n < nb_nodes_per_element; ++n) {
             /// add element's nodes to the cluster
             UInt node = connect[n];
             if (!checked_node(node)) {
               cluster.addNode(node, false);
               checked_node(node) = true;
             }
           }
         }
       }
     }
   }
 
   if (nb_proc > 1 && mesh.isDistributed()) {
     ClusterSynchronizer cluster_synchronizer(
         *this, element_dimension, cluster_name_prefix, *element_to_fragment,
         this->mesh.getElementSynchronizer(), nb_cluster);
     nb_cluster = cluster_synchronizer.synchronize();
     delete element_to_fragment;
   }
 
   if (mesh_facets_created)
     delete mesh_facets;
 
   if (mesh.isDistributed())
     this->synchronizeGroupNames();
 
   AKANTU_DEBUG_OUT();
   return nb_cluster;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 void GroupManager::createGroupsFromMeshData(const std::string & dataset_name) {
   std::set<std::string> group_names;
   const ElementTypeMapArray<T> & datas = mesh.getData<T>(dataset_name);
   typedef typename ElementTypeMapArray<T>::type_iterator type_iterator;
 
   std::map<std::string, UInt> group_dim;
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
     type_iterator type_it = datas.firstType(_all_dimensions, *gt);
     type_iterator type_end = datas.lastType(_all_dimensions, *gt);
     for (; type_it != type_end; ++type_it) {
       const Array<T> & dataset = datas(*type_it, *gt);
       UInt nb_element = mesh.getNbElement(*type_it, *gt);
       AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element,
                           "Not the same number of elements ("
                               << *type_it << ":" << *gt
                               << ") in the map from MeshData ("
                               << dataset.getSize() << ") " << dataset_name
                               << " and in the mesh (" << nb_element << ")!");
       for (UInt e(0); e < nb_element; ++e) {
         std::stringstream sstr;
         sstr << dataset(e);
         std::string gname = sstr.str();
         group_names.insert(gname);
 
         std::map<std::string, UInt>::iterator it = group_dim.find(gname);
         if (it == group_dim.end()) {
           group_dim[gname] = mesh.getSpatialDimension(*type_it);
         } else {
           it->second = std::max(it->second, mesh.getSpatialDimension(*type_it));
         }
       }
     }
   }
 
   std::set<std::string>::iterator git = group_names.begin();
   std::set<std::string>::iterator gend = group_names.end();
   for (; git != gend; ++git)
     createElementGroup(*git, group_dim[*git]);
 
   if (mesh.isDistributed())
     this->synchronizeGroupNames();
 
   Element el;
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
     el.ghost_type = *gt;
 
     type_iterator type_it = datas.firstType(_all_dimensions, *gt);
     type_iterator type_end = datas.lastType(_all_dimensions, *gt);
     for (; type_it != type_end; ++type_it) {
       el.type = *type_it;
 
       const Array<T> & dataset = datas(*type_it, *gt);
       UInt nb_element = mesh.getNbElement(*type_it, *gt);
       AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element,
                           "Not the same number of elements in the map from "
                           "MeshData and in the mesh!");
 
       UInt nb_nodes_per_element = mesh.getNbNodesPerElement(el.type);
 
       Array<UInt>::const_iterator<Vector<UInt>> cit =
           mesh.getConnectivity(*type_it, *gt).begin(nb_nodes_per_element);
 
       for (UInt e(0); e < nb_element; ++e, ++cit) {
         el.element = e;
         std::stringstream sstr;
         sstr << dataset(e);
         ElementGroup & group = getElementGroup(sstr.str());
         group.add(el, false, false);
 
         const Vector<UInt> & connect = *cit;
         for (UInt n = 0; n < nb_nodes_per_element; ++n) {
           UInt node = connect[n];
           group.addNode(node, false);
         }
       }
     }
   }
 
   git = group_names.begin();
   for (; git != gend; ++git) {
     getElementGroup(*git).optimize();
   }
 }
 
 template void GroupManager::createGroupsFromMeshData<std::string>(
     const std::string & dataset_name);
 template void
 GroupManager::createGroupsFromMeshData<UInt>(const std::string & dataset_name);
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::createElementGroupFromNodeGroup(
     const std::string & name, const std::string & node_group_name,
     UInt dimension) {
   NodeGroup & node_group = getNodeGroup(node_group_name);
   ElementGroup & group = createElementGroup(name, dimension, node_group);
 
   group.fillFromNodeGroup();
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::printself(std::ostream & stream, int indent) const {
   std::string space;
   for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
     ;
 
   stream << space << "GroupManager [" << std::endl;
 
   std::set<std::string> node_group_seen;
   for (const_element_group_iterator it(element_group_begin());
        it != element_group_end(); ++it) {
     it->second->printself(stream, indent + 1);
     node_group_seen.insert(it->second->getNodeGroup().getName());
   }
 
   for (const_node_group_iterator it(node_group_begin()); it != node_group_end();
        ++it) {
     if (node_group_seen.find(it->second->getName()) == node_group_seen.end())
       it->second->printself(stream, indent + 1);
   }
 
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 UInt GroupManager::getNbElementGroups(UInt dimension) const {
   if (dimension == _all_dimensions)
     return element_groups.size();
 
   ElementGroups::const_iterator it = element_groups.begin();
   ElementGroups::const_iterator end = element_groups.end();
   UInt count = 0;
   for (; it != end; ++it)
     count += (it->second->getDimension() == dimension);
   return count;
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::checkAndAddGroups(CommunicationBuffer & buffer) {
   AKANTU_DEBUG_IN();
 
   UInt nb_node_group;
   buffer >> nb_node_group;
   AKANTU_DEBUG_INFO("Received " << nb_node_group << " node group names");
 
   for (UInt ng = 0; ng < nb_node_group; ++ng) {
     std::string node_group_name;
     buffer >> node_group_name;
 
     if (node_groups.find(node_group_name) == node_groups.end()) {
       this->createNodeGroup(node_group_name);
     }
 
     AKANTU_DEBUG_INFO("Received node goup name: " << node_group_name);
   }
 
   UInt nb_element_group;
   buffer >> nb_element_group;
   AKANTU_DEBUG_INFO("Received " << nb_element_group << " element group names");
   for (UInt eg = 0; eg < nb_element_group; ++eg) {
     std::string element_group_name;
     buffer >> element_group_name;
     std::string node_group_name;
     buffer >> node_group_name;
     UInt dim;
     buffer >> dim;
 
     AKANTU_DEBUG_INFO("Received element group name: "
                       << element_group_name << " corresponding to a "
                       << Int(dim) << "D group with node group "
                       << node_group_name);
 
     NodeGroup & node_group = *node_groups[node_group_name];
 
     if (element_groups.find(element_group_name) == element_groups.end()) {
       this->createElementGroup(element_group_name, dim, node_group);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::fillBufferWithGroupNames(
     DynamicCommunicationBuffer & comm_buffer) const {
   AKANTU_DEBUG_IN();
 
   // packing node group names;
   UInt nb_groups = this->node_groups.size();
   comm_buffer << nb_groups;
   AKANTU_DEBUG_INFO("Sending " << nb_groups << " node group names");
 
   NodeGroups::const_iterator nnames_it = node_groups.begin();
   NodeGroups::const_iterator nnames_end = node_groups.end();
   for (; nnames_it != nnames_end; ++nnames_it) {
     std::string node_group_name = nnames_it->first;
     comm_buffer << node_group_name;
     AKANTU_DEBUG_INFO("Sending node goupe name: " << node_group_name);
   }
 
   // packing element group names with there associated node group name
   nb_groups = this->element_groups.size();
   comm_buffer << nb_groups;
   AKANTU_DEBUG_INFO("Sending " << nb_groups << " element group names");
   ElementGroups::const_iterator gnames_it = this->element_groups.begin();
   ElementGroups::const_iterator gnames_end = this->element_groups.end();
   for (; gnames_it != gnames_end; ++gnames_it) {
     ElementGroup & element_group = *(gnames_it->second);
     std::string element_group_name = gnames_it->first;
     std::string node_group_name = element_group.getNodeGroup().getName();
     UInt dim = element_group.getDimension();
 
     comm_buffer << element_group_name;
     comm_buffer << node_group_name;
     comm_buffer << dim;
 
     AKANTU_DEBUG_INFO("Sending element group name: "
                       << element_group_name << " corresponding to a "
                       << Int(dim) << "D group with the node group "
                       << node_group_name);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::synchronizeGroupNames() {
   AKANTU_DEBUG_IN();
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   Int nb_proc = comm.getNbProc();
   Int my_rank = comm.whoAmI();
 
   if (nb_proc == 1)
     return;
 
   if (my_rank == 0) {
     for (Int p = 1; p < nb_proc; ++p) {
       CommunicationStatus status;
       comm.probe<char>(p, p, status);
       AKANTU_DEBUG_INFO("Got " << printMemorySize<char>(status.getSize())
                                << " from proc " << p);
 
       CommunicationBuffer recv_buffer(status.getSize());
       comm.receive(recv_buffer, p, p);
 
       this->checkAndAddGroups(recv_buffer);
     }
 
     DynamicCommunicationBuffer comm_buffer;
     this->fillBufferWithGroupNames(comm_buffer);
 
     UInt buffer_size = comm_buffer.getSize();
 
     comm.broadcast(buffer_size, 0);
 
     AKANTU_DEBUG_INFO("Initiating broadcast with "
                       << printMemorySize<char>(comm_buffer.getSize()));
     comm.broadcast(comm_buffer, 0);
 
   } else {
     DynamicCommunicationBuffer comm_buffer;
     this->fillBufferWithGroupNames(comm_buffer);
 
     AKANTU_DEBUG_INFO("Sending " << printMemorySize<char>(comm_buffer.getSize())
                                  << " to proc " << 0);
     comm.send(comm_buffer, 0, my_rank);
 
     UInt buffer_size = 0;
     comm.broadcast(buffer_size, 0);
 
     AKANTU_DEBUG_INFO("Receiving broadcast with "
                       << printMemorySize<char>(comm_buffer.getSize()));
     CommunicationBuffer recv_buffer(buffer_size);
     comm.broadcast(recv_buffer, 0);
 
     this->checkAndAddGroups(recv_buffer);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 const ElementGroup &
 GroupManager::getElementGroup(const std::string & name) const {
   const_element_group_iterator it = element_group_find(name);
   if (it == element_group_end()) {
     AKANTU_EXCEPTION("There are no element groups named "
                      << name << " associated to the group manager: " << id);
   }
 
   return *(it->second);
 }
 
 /* -------------------------------------------------------------------------- */
 ElementGroup & GroupManager::getElementGroup(const std::string & name) {
   element_group_iterator it = element_group_find(name);
   if (it == element_group_end()) {
     AKANTU_EXCEPTION("There are no element groups named "
                      << name << " associated to the group manager: " << id);
   }
 
   return *(it->second);
 }
 
 /* -------------------------------------------------------------------------- */
 const NodeGroup & GroupManager::getNodeGroup(const std::string & name) const {
   const_node_group_iterator it = node_group_find(name);
   if (it == node_group_end()) {
     AKANTU_EXCEPTION("There are no node groups named "
                      << name << " associated to the group manager: " << id);
   }
 
   return *(it->second);
 }
 
 /* -------------------------------------------------------------------------- */
 NodeGroup & GroupManager::getNodeGroup(const std::string & name) {
   node_group_iterator it = node_group_find(name);
   if (it == node_group_end()) {
     AKANTU_EXCEPTION("There are no node groups named "
                      << name << " associated to the group manager: " << id);
   }
 
   return *(it->second);
 }
 
 } // namespace akantu
diff --git a/src/mesh/group_manager.hh b/src/mesh/group_manager.hh
index 9caf83c86..d4b7dc1a3 100644
--- a/src/mesh/group_manager.hh
+++ b/src/mesh/group_manager.hh
@@ -1,295 +1,294 @@
 /**
  * @file   group_manager.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Dana Christen <dana.christen@gmail.com>
  * @author David Simon Kammer <david.kammer@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Wed Nov 13 2013
  * @date last modification: Mon Nov 16 2015
  *
  * @brief  Stores information relevent to the notion of element and nodes
  *groups.
  *
  * @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_GROUP_MANAGER_HH__
 #define __AKANTU_GROUP_MANAGER_HH__
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "element_type_map.hh"
 /* -------------------------------------------------------------------------- */
 #include <set>
 /* -------------------------------------------------------------------------- */
 
-
 namespace akantu {
-  class ElementGroup;
-  class NodeGroup;
-  class Mesh;
-  class Element;
-  class ElementSynchronizer;
-  template <bool> class CommunicationBufferTemplated;
-  namespace dumper {
-    class Field;
-  }
+class ElementGroup;
+class NodeGroup;
+class Mesh;
+class Element;
+class ElementSynchronizer;
+template <bool> class CommunicationBufferTemplated;
+namespace dumper {
+  class Field;
 }
+} // namespace akantu
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 class GroupManager {
   /* ------------------------------------------------------------------------ */
   /* Typedefs                                                                 */
   /* ------------------------------------------------------------------------ */
 private:
-  using ElementGroups =  std::map<std::string, ElementGroup *> ;
-  using NodeGroups = std::map<std::string, NodeGroup *> ;
+  using ElementGroups = std::map<std::string, ElementGroup *>;
+  using NodeGroups = std::map<std::string, NodeGroup *>;
 
 public:
   typedef std::set<ElementType> GroupManagerTypeSet;
 
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   GroupManager(const Mesh & mesh, const ID & id = "group_manager",
                const MemoryID & memory_id = 0);
   virtual ~GroupManager();
 
   /* ------------------------------------------------------------------------ */
   /* Groups iterators                                                         */
   /* ------------------------------------------------------------------------ */
 public:
   typedef NodeGroups::iterator node_group_iterator;
   typedef ElementGroups::iterator element_group_iterator;
 
   typedef NodeGroups::const_iterator const_node_group_iterator;
   typedef ElementGroups::const_iterator const_element_group_iterator;
 
 #ifndef SWIG
 #define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(group_type, function,    \
                                                       param_in, param_out)     \
   inline BOOST_PP_CAT(BOOST_PP_CAT(const_, group_type), _iterator)             \
       BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) const {    \
     return BOOST_PP_CAT(group_type, s).function(param_out);                    \
   };                                                                           \
                                                                                \
   inline BOOST_PP_CAT(group_type, _iterator)                                   \
       BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) {          \
     return BOOST_PP_CAT(group_type, s).function(param_out);                    \
   }
 
 #define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(group_type, function) \
   AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(                               \
       group_type, function, BOOST_PP_EMPTY(), BOOST_PP_EMPTY())
 
   AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, begin);
   AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, end);
   AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, begin);
   AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, end);
   AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(element_group, find,
                                                 const std::string & name, name);
   AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(node_group, find,
                                                 const std::string & name, name);
 #endif
 
   /* ------------------------------------------------------------------------ */
   /* Clustering filter                                                        */
   /* ------------------------------------------------------------------------ */
 public:
   class ClusteringFilter {
   public:
     virtual bool operator()(const Element &) const { return true; }
   };
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// create an empty node group
   NodeGroup & createNodeGroup(const std::string & group_name,
                               bool replace_group = false);
 
   /// create a node group from another node group but filtered
   template <typename T>
   NodeGroup & createFilteredNodeGroup(const std::string & group_name,
                                       const NodeGroup & node_group, T & filter);
 
   /// destroy a node group
   void destroyNodeGroup(const std::string & group_name);
 
   /// create an element group and the associated node group
   ElementGroup & createElementGroup(const std::string & group_name,
                                     UInt dimension = _all_dimensions,
                                     bool replace_group = false);
 
   /// create an element group from another element group but filtered
   template <typename T>
   ElementGroup &
   createFilteredElementGroup(const std::string & group_name, UInt dimension,
                              const NodeGroup & node_group, T & filter);
 
   /// destroy an element group and the associated node group
   void destroyElementGroup(const std::string & group_name,
                            bool destroy_node_group = false);
 
   /// destroy all element groups and the associated node groups
   void destroyAllElementGroups(bool destroy_node_groups = false);
 
   /// create a element group using an existing node group
   ElementGroup & createElementGroup(const std::string & group_name,
                                     UInt dimension, NodeGroup & node_group);
 
   /// create groups based on values stored in a given mesh data
   template <typename T>
   void createGroupsFromMeshData(const std::string & dataset_name);
 
   /// create boundaries group by a clustering algorithm \todo extend to parallel
   UInt createBoundaryGroupFromGeometry();
 
   /// create element clusters for a given dimension
   UInt createClusters(UInt element_dimension,
                       std::string cluster_name_prefix = "cluster",
                       const ClusteringFilter & filter = ClusteringFilter(),
                       Mesh * mesh_facets = nullptr);
 
   /// Create an ElementGroup based on a NodeGroup
   void createElementGroupFromNodeGroup(const std::string & name,
                                        const std::string & node_group,
                                        UInt dimension = _all_dimensions);
 
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /// this function insure that the group names are present on all processors
   /// /!\ it is a SMP call
   void synchronizeGroupNames();
 
 /// register an elemental field to the given group name (overloading for
 /// ElementalPartionField)
 #ifndef SWIG
   template <typename T, template <bool> class dump_type>
-  inline dumper::Field * createElementalField(
+  dumper::Field * createElementalField(
       const ElementTypeMapArray<T> & field, const std::string & group_name,
       UInt spatial_dimension, const ElementKind & kind,
       ElementTypeMap<UInt> nb_data_per_elem = ElementTypeMap<UInt>());
 
   /// register an elemental field to the given group name (overloading for
   /// ElementalField)
   template <typename T, template <class> class ret_type,
             template <class, template <class> class, bool> class dump_type>
-  inline dumper::Field * createElementalField(
+  dumper::Field * createElementalField(
       const ElementTypeMapArray<T> & field, const std::string & group_name,
       UInt spatial_dimension, const ElementKind & kind,
       ElementTypeMap<UInt> nb_data_per_elem = ElementTypeMap<UInt>());
 
   /// register an elemental field to the given group name (overloading for
   /// MaterialInternalField)
   template <typename T,
             /// type of InternalMaterialField
             template <typename, bool filtered> class dump_type>
-  inline dumper::Field *
-  createElementalField(const ElementTypeMapArray<T> & field,
-                       const std::string & group_name, UInt spatial_dimension,
-                       const ElementKind & kind,
-                       ElementTypeMap<UInt> nb_data_per_elem);
+  dumper::Field * createElementalField(const ElementTypeMapArray<T> & field,
+                                       const std::string & group_name,
+                                       UInt spatial_dimension,
+                                       const ElementKind & kind,
+                                       ElementTypeMap<UInt> nb_data_per_elem);
 
   template <typename type, bool flag, template <class, bool> class ftype>
-  inline dumper::Field * createNodalField(const ftype<type, flag> * field,
-                                          const std::string & group_name,
-                                          UInt padding_size = 0);
+  dumper::Field * createNodalField(const ftype<type, flag> * field,
+                                   const std::string & group_name,
+                                   UInt padding_size = 0);
 
   template <typename type, bool flag, template <class, bool> class ftype>
-  inline dumper::Field *
-  createStridedNodalField(const ftype<type, flag> * field,
-                          const std::string & group_name, UInt size,
-                          UInt stride, UInt padding_size);
+  dumper::Field * createStridedNodalField(const ftype<type, flag> * field,
+                                          const std::string & group_name,
+                                          UInt size, UInt stride,
+                                          UInt padding_size);
 
 protected:
   /// fill a buffer with all the group names
   void fillBufferWithGroupNames(
       CommunicationBufferTemplated<false> & comm_buffer) const;
 
   /// take a buffer and create the missing groups localy
   void checkAndAddGroups(CommunicationBufferTemplated<true> & buffer);
 
   /// register an elemental field to the given group name
   template <class dump_type, typename field_type>
   inline dumper::Field *
   createElementalField(const field_type & field, const std::string & group_name,
                        UInt spatial_dimension, const ElementKind & kind,
                        ElementTypeMap<UInt> nb_data_per_elem);
 
   /// register an elemental field to the given group name
   template <class dump_type, typename field_type>
   inline dumper::Field *
   createElementalFilteredField(const field_type & field,
                                const std::string & group_name,
                                UInt spatial_dimension, const ElementKind & kind,
                                ElementTypeMap<UInt> nb_data_per_elem);
 #endif
 
   /* ------------------------------------------------------------------------ */
   /* Accessor                                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   const ElementGroup & getElementGroup(const std::string & name) const;
   const NodeGroup & getNodeGroup(const std::string & name) const;
 
   ElementGroup & getElementGroup(const std::string & name);
   NodeGroup & getNodeGroup(const std::string & name);
 
   UInt getNbElementGroups(UInt dimension = _all_dimensions) const;
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// id to create element and node groups
   ID id;
   /// memory_id to create element and node groups
   MemoryID memory_id;
 
   /// list of the node groups managed
   NodeGroups node_groups;
 
   /// list of the element groups managed
   ElementGroups element_groups;
 
   /// Mesh to which the element belongs
   const Mesh & mesh;
 };
 
 /// standard output stream operator
 inline std::ostream & operator<<(std::ostream & stream,
                                  const GroupManager & _this) {
   _this.printself(stream);
   return stream;
 }
 
-} // akantu
+} // namespace akantu
 
 #endif /* __AKANTU_GROUP_MANAGER_HH__ */
diff --git a/src/mesh_utils/mesh_utils.cc b/src/mesh_utils/mesh_utils.cc
index 78771cdb7..61ee0a24a 100644
--- a/src/mesh_utils/mesh_utils.cc
+++ b/src/mesh_utils/mesh_utils.cc
@@ -1,2346 +1,2342 @@
 /**
  * @file   mesh_utils.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Dana Christen <dana.christen@epfl.ch>
  * @author David Simon Kammer <david.kammer@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Fri Aug 20 2010
  * @date last modification: Fri Jan 22 2016
  *
  * @brief  All mesh utils necessary for various tasks
  *
  * @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 "mesh_utils.hh"
 #include "element_synchronizer.hh"
 #include "fe_engine.hh"
 #include "mesh_accessor.hh"
 /* -------------------------------------------------------------------------- */
 #include <limits>
 #include <numeric>
 #include <queue>
 #include <set>
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildNode2Elements(const Mesh & mesh,
                                    CSR<Element> & node_to_elem,
                                    UInt spatial_dimension) {
   AKANTU_DEBUG_IN();
   if (spatial_dimension == _all_dimensions)
     spatial_dimension = mesh.getSpatialDimension();
 
   /// count number of occurrence of each node
   UInt nb_nodes = mesh.getNbNodes();
 
   /// array for the node-element list
   node_to_elem.resizeRows(nb_nodes);
   node_to_elem.clearRows();
 
   AKANTU_DEBUG_ASSERT(
       mesh.firstType(spatial_dimension) != mesh.lastType(spatial_dimension),
       "Some elements must be found in right dimension to compute facets!");
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
     Mesh::type_iterator first =
         mesh.firstType(spatial_dimension, *gt, _ek_not_defined);
     Mesh::type_iterator last =
         mesh.lastType(spatial_dimension, *gt, _ek_not_defined);
 
     for (; first != last; ++first) {
       ElementType type = *first;
       UInt nb_element = mesh.getNbElement(type, *gt);
       Array<UInt>::const_iterator<Vector<UInt>> conn_it =
           mesh.getConnectivity(type, *gt).begin(
               Mesh::getNbNodesPerElement(type));
 
       for (UInt el = 0; el < nb_element; ++el, ++conn_it)
         for (UInt n = 0; n < conn_it->size(); ++n)
           ++node_to_elem.rowOffset((*conn_it)(n));
     }
   }
 
   node_to_elem.countToCSR();
   node_to_elem.resizeCols();
 
   /// rearrange element to get the node-element list
   Element e;
   node_to_elem.beginInsertions();
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
     Mesh::type_iterator first =
         mesh.firstType(spatial_dimension, *gt, _ek_not_defined);
     Mesh::type_iterator last =
         mesh.lastType(spatial_dimension, *gt, _ek_not_defined);
     e.ghost_type = *gt;
     for (; first != last; ++first) {
       ElementType type = *first;
       e.type = type;
       e.kind = Mesh::getKind(type);
       UInt nb_element = mesh.getNbElement(type, *gt);
       Array<UInt>::const_iterator<Vector<UInt>> conn_it =
           mesh.getConnectivity(type, *gt).begin(
               Mesh::getNbNodesPerElement(type));
 
       for (UInt el = 0; el < nb_element; ++el, ++conn_it) {
         e.element = el;
         for (UInt n = 0; n < conn_it->size(); ++n)
           node_to_elem.insertInRow((*conn_it)(n), e);
       }
     }
   }
 
   node_to_elem.endInsertions();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * This function should disappear in the future (used in mesh partitioning)
  */
 void MeshUtils::buildNode2Elements(const Mesh & mesh, CSR<UInt> & node_to_elem,
                                    UInt spatial_dimension) {
   AKANTU_DEBUG_IN();
   if (spatial_dimension == _all_dimensions)
     spatial_dimension = mesh.getSpatialDimension();
   UInt nb_nodes = mesh.getNbNodes();
 
   const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList();
   Mesh::ConnectivityTypeList::const_iterator it;
 
   UInt nb_types = type_list.size();
   UInt nb_good_types = 0;
 
   Vector<UInt> nb_nodes_per_element(nb_types);
   UInt ** conn_val = new UInt *[nb_types];
   Vector<UInt> nb_element(nb_types);
 
   for (it = type_list.begin(); it != type_list.end(); ++it) {
     ElementType type = *it;
     if (Mesh::getSpatialDimension(type) != spatial_dimension)
       continue;
 
     nb_nodes_per_element[nb_good_types] = Mesh::getNbNodesPerElement(type);
     conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).storage();
     nb_element[nb_good_types] =
         mesh.getConnectivity(type, _not_ghost).getSize();
     nb_good_types++;
   }
 
   AKANTU_DEBUG_ASSERT(
       nb_good_types != 0,
       "Some elements must be found in right dimension to compute facets!");
 
   /// array for the node-element list
   node_to_elem.resizeRows(nb_nodes);
   node_to_elem.clearRows();
 
   /// count number of occurrence of each node
   for (UInt t = 0; t < nb_good_types; ++t) {
     for (UInt el = 0; el < nb_element[t]; ++el) {
       UInt el_offset = el * nb_nodes_per_element[t];
       for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) {
         ++node_to_elem.rowOffset(conn_val[t][el_offset + n]);
       }
     }
   }
 
   node_to_elem.countToCSR();
   node_to_elem.resizeCols();
   node_to_elem.beginInsertions();
 
   /// rearrange element to get the node-element list
   for (UInt t = 0, linearized_el = 0; t < nb_good_types; ++t)
     for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) {
       UInt el_offset = el * nb_nodes_per_element[t];
       for (UInt n = 0; n < nb_nodes_per_element[t]; ++n)
         node_to_elem.insertInRow(conn_val[t][el_offset + n], linearized_el);
     }
 
   node_to_elem.endInsertions();
   delete[] conn_val;
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildNode2ElementsElementTypeMap(const Mesh & mesh,
                                                  CSR<UInt> & node_to_elem,
                                                  const ElementType & type,
                                                  const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
   UInt nb_nodes = mesh.getNbNodes();
 
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
   UInt nb_elements = mesh.getConnectivity(type, ghost_type).getSize();
 
   UInt * conn_val = mesh.getConnectivity(type, ghost_type).storage();
 
   /// array for the node-element list
   node_to_elem.resizeRows(nb_nodes);
   node_to_elem.clearRows();
 
   /// count number of occurrence of each node
   for (UInt el = 0; el < nb_elements; ++el) {
     UInt el_offset = el * nb_nodes_per_element;
     for (UInt n = 0; n < nb_nodes_per_element; ++n)
       ++node_to_elem.rowOffset(conn_val[el_offset + n]);
   }
 
   /// convert the occurrence array in a csr one
   node_to_elem.countToCSR();
 
   node_to_elem.resizeCols();
   node_to_elem.beginInsertions();
 
   /// save the element index in the node-element list
   for (UInt el = 0; el < nb_elements; ++el) {
     UInt el_offset = el * nb_nodes_per_element;
     for (UInt n = 0; n < nb_nodes_per_element; ++n) {
       node_to_elem.insertInRow(conn_val[el_offset + n], el);
     }
   }
 
   node_to_elem.endInsertions();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildFacets(Mesh & mesh) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
     GhostType gt_facet = *gt;
     Mesh::type_iterator it = mesh.firstType(spatial_dimension - 1, gt_facet);
     Mesh::type_iterator end = mesh.lastType(spatial_dimension - 1, gt_facet);
     for (; it != end; ++it) {
       mesh.getConnectivity(*it, *gt).resize(0);
       // \todo inform the mesh event handler
     }
   }
 
   buildFacetsDimension(mesh, mesh, true, spatial_dimension);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildAllFacets(const Mesh & mesh, Mesh & mesh_facets,
                                UInt to_dimension) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   buildAllFacets(mesh, mesh_facets, spatial_dimension, to_dimension);
 
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildAllFacets(const Mesh & mesh, Mesh & mesh_facets,
                                UInt from_dimension, UInt to_dimension) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(
       mesh_facets.isMeshFacets(),
       "The mesh_facets should be initialized with initMeshFacets");
 
   const ElementTypeMapArray<UInt> * prank_to_element = nullptr;
 
   if (mesh.isDistributed()) {
     prank_to_element = &(mesh.getElementSynchronizer().getPrankToElement());
   }
 
   /// generate facets
   buildFacetsDimension(mesh, mesh_facets, false, from_dimension,
                        prank_to_element);
 
   /// copy nodes type
   MeshAccessor mesh_accessor_facets(mesh_facets);
   mesh_accessor_facets.getNodesType().copy(mesh.getNodesType());
 
   /// sort facets and generate sub-facets
   for (UInt i = from_dimension - 1; i > to_dimension; --i) {
     buildFacetsDimension(mesh_facets, mesh_facets, false, i, prank_to_element);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildFacetsDimension(
     const Mesh & mesh, Mesh & mesh_facets, bool boundary_only, UInt dimension,
     const ElementTypeMapArray<UInt> * prank_to_element) {
   AKANTU_DEBUG_IN();
 
   // save the current parent of mesh_facets and set it temporarly to mesh since
   // mesh is the one containing the elements for which mesh_facets has the
   // sub-elements
   // example: if the function is called with mesh = mesh_facets
   const Mesh * mesh_facets_parent = nullptr;
   try {
     mesh_facets_parent = &mesh_facets.getMeshParent();
   } catch (...) {
   }
 
   mesh_facets.defineMeshParent(mesh);
   MeshAccessor mesh_accessor(mesh_facets);
 
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   const Array<Real> & mesh_facets_nodes = mesh_facets.getNodes();
   const Array<Real>::const_vector_iterator mesh_facets_nodes_it =
       mesh_facets_nodes.begin(spatial_dimension);
 
   CSR<Element> node_to_elem;
   buildNode2Elements(mesh, node_to_elem, dimension);
 
   Array<UInt> counter;
   std::vector<Element> connected_elements;
 
   // init the SubelementToElement data to improve performance
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
     GhostType ghost_type = *gt;
     Mesh::type_iterator first = mesh.firstType(dimension, ghost_type);
     Mesh::type_iterator last = mesh.lastType(dimension, ghost_type);
 
     for (; first != last; ++first) {
       ElementType type = *first;
 
       mesh_accessor.getSubelementToElement(type, ghost_type);
 
       Vector<ElementType> facet_types = mesh.getAllFacetTypes(type);
 
       for (UInt ft = 0; ft < facet_types.size(); ++ft) {
         ElementType facet_type = facet_types(ft);
         mesh_accessor.getElementToSubelement(facet_type, ghost_type);
         mesh_accessor.getConnectivity(facet_type, ghost_type);
       }
     }
   }
 
   Element current_element;
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
     GhostType ghost_type = *gt;
     GhostType facet_ghost_type = ghost_type;
 
     current_element.ghost_type = ghost_type;
     Mesh::type_iterator first = mesh.firstType(dimension, ghost_type);
     Mesh::type_iterator last = mesh.lastType(dimension, ghost_type);
 
     for (; first != last; ++first) {
       ElementType type = *first;
       Vector<ElementType> facet_types = mesh.getAllFacetTypes(type);
 
       current_element.type = type;
 
       for (UInt ft = 0; ft < facet_types.size(); ++ft) {
         ElementType facet_type = facet_types(ft);
         UInt nb_element = mesh.getNbElement(type, ghost_type);
 
         Array<std::vector<Element>> * element_to_subelement =
             &mesh_facets.getElementToSubelement(facet_type, ghost_type);
         Array<UInt> * connectivity_facets =
             &mesh_facets.getConnectivity(facet_type, ghost_type);
 
         UInt nb_facet_per_element = mesh.getNbFacetsPerElement(type, ft);
         const Array<UInt> & element_connectivity =
             mesh.getConnectivity(type, ghost_type);
 
         const Matrix<UInt> facet_local_connectivity =
             mesh.getFacetLocalConnectivity(type, ft);
         UInt nb_nodes_per_facet = connectivity_facets->getNbComponent();
         Vector<UInt> facet(nb_nodes_per_facet);
 
         for (UInt el = 0; el < nb_element; ++el) {
           current_element.element = el;
 
           for (UInt f = 0; f < nb_facet_per_element; ++f) {
             for (UInt n = 0; n < nb_nodes_per_facet; ++n)
               facet(n) =
                   element_connectivity(el, facet_local_connectivity(f, n));
 
             UInt first_node_nb_elements = node_to_elem.getNbCols(facet(0));
             counter.resize(first_node_nb_elements);
             counter.clear();
 
             // loop over the other nodes to search intersecting elements,
             // which are the elements that share another node with the
             // starting element after first_node
             CSR<Element>::iterator first_node_elements =
                 node_to_elem.begin(facet(0));
             CSR<Element>::iterator first_node_elements_end =
                 node_to_elem.end(facet(0));
             UInt local_el = 0;
             for (; first_node_elements != first_node_elements_end;
                  ++first_node_elements, ++local_el) {
               for (UInt n = 1; n < nb_nodes_per_facet; ++n) {
                 CSR<Element>::iterator node_elements_begin =
                     node_to_elem.begin(facet(n));
                 CSR<Element>::iterator node_elements_end =
                     node_to_elem.end(facet(n));
                 counter(local_el) +=
                     std::count(node_elements_begin, node_elements_end,
                                *first_node_elements);
               }
             }
 
             // counting the number of elements connected to the facets and
             // taking the minimum element number, because the facet should
             // be inserted just once
             UInt nb_element_connected_to_facet = 0;
             Element minimum_el = ElementNull;
             connected_elements.clear();
             for (UInt el_f = 0; el_f < first_node_nb_elements; el_f++) {
               Element real_el = node_to_elem(facet(0), el_f);
               if (counter(el_f) == nb_nodes_per_facet - 1) {
                 ++nb_element_connected_to_facet;
                 minimum_el = std::min(minimum_el, real_el);
                 connected_elements.push_back(real_el);
               }
             }
 
             if (minimum_el == current_element) {
               bool full_ghost_facet = false;
 
               UInt n = 0;
               while (n < nb_nodes_per_facet && mesh.isPureGhostNode(facet(n)))
                 ++n;
               if (n == nb_nodes_per_facet)
                 full_ghost_facet = true;
 
               if (!full_ghost_facet) {
                 if (!boundary_only ||
                     (boundary_only && nb_element_connected_to_facet == 1)) {
 
                   std::vector<Element> elements;
 
                   // build elements_on_facets: linearized_el must come first
                   // in order to store the facet in the correct direction
                   // and avoid to invert the sign in the normal computation
                   elements.push_back(current_element);
 
                   /// boundary facet
                   if (nb_element_connected_to_facet == 1)
                     elements.push_back(ElementNull);
                   /// internal facet
                   else if (nb_element_connected_to_facet == 2) {
                     elements.push_back(connected_elements[1]);
 
                     /// check if facet is in between ghost and normal
                     /// elements: if it's the case, the facet is either
                     /// ghost or not ghost. The criterion to decide this
                     /// is arbitrary. It was chosen to check the processor
                     /// id (prank) of the two neighboring elements. If
                     /// prank of the ghost element is lower than prank of
                     /// the normal one, the facet is not ghost, otherwise
                     /// it's ghost
                     GhostType gt[2] = {_not_ghost, _not_ghost};
                     for (UInt el = 0; el < connected_elements.size(); ++el)
                       gt[el] = connected_elements[el].ghost_type;
 
                     if (gt[0] + gt[1] == 1) {
                       if (prank_to_element) {
                         UInt prank[2];
                         for (UInt el = 0; el < 2; ++el) {
                           UInt current_el = connected_elements[el].element;
                           ElementType current_type =
                               connected_elements[el].type;
                           GhostType current_gt =
                               connected_elements[el].ghost_type;
 
                           const Array<UInt> & prank_to_el =
                               (*prank_to_element)(current_type, current_gt);
 
                           prank[el] = prank_to_el(current_el);
                         }
 
                         bool ghost_one = (gt[0] != _ghost);
 
                         if (prank[ghost_one] > prank[!ghost_one])
                           facet_ghost_type = _not_ghost;
                         else
                           facet_ghost_type = _ghost;
 
                         connectivity_facets = &mesh_facets.getConnectivity(
                             facet_type, facet_ghost_type);
                         element_to_subelement =
                             &mesh_facets.getElementToSubelement(
                                 facet_type, facet_ghost_type);
                       }
                     }
                   }
                   /// facet of facet
                   else {
                     for (UInt i = 1; i < nb_element_connected_to_facet; ++i) {
                       elements.push_back(connected_elements[i]);
                     }
                   }
 
                   element_to_subelement->push_back(elements);
                   connectivity_facets->push_back(facet);
 
                   /// current facet index
                   UInt current_facet = connectivity_facets->getSize() - 1;
 
                   /// loop on every element connected to current facet and
                   /// insert current facet in the first free spot of the
                   /// subelement_to_element vector
                   for (UInt elem = 0; elem < elements.size(); ++elem) {
                     Element loc_el = elements[elem];
 
                     if (loc_el.type != _not_defined) {
 
                       Array<Element> & subelement_to_element =
                           mesh_facets.getSubelementToElement(loc_el.type,
                                                              loc_el.ghost_type);
 
                       UInt nb_facet_per_loc_element =
                           subelement_to_element.getNbComponent();
 
                       for (UInt f_in = 0; f_in < nb_facet_per_loc_element;
                            ++f_in) {
                         if (subelement_to_element(loc_el.element, f_in).type ==
                             _not_defined) {
                           subelement_to_element(loc_el.element, f_in).type =
                               facet_type;
                           subelement_to_element(loc_el.element, f_in).element =
                               current_facet;
                           subelement_to_element(loc_el.element, f_in)
                               .ghost_type = facet_ghost_type;
                           break;
                         }
                       }
                     }
                   }
 
                   /// reset connectivity in case a facet was found in
                   /// between ghost and normal elements
                   if (facet_ghost_type != ghost_type) {
                     facet_ghost_type = ghost_type;
                     connectivity_facets = &mesh_accessor.getConnectivity(
                         facet_type, facet_ghost_type);
                     element_to_subelement =
                         &mesh_accessor.getElementToSubelement(facet_type,
                                                               facet_ghost_type);
                   }
                 }
               }
             }
           }
         }
       }
     }
   }
 
   // restore the parent of mesh_facet
   if (mesh_facets_parent)
     mesh_facets.defineMeshParent(*mesh_facets_parent);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::renumberMeshNodes(Mesh & mesh,
                                   Array<UInt> & local_connectivities,
                                   UInt nb_local_element, UInt nb_ghost_element,
                                   ElementType type,
                                   Array<UInt> & old_nodes_numbers) {
   AKANTU_DEBUG_IN();
 
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
 
   std::map<UInt, UInt> renumbering_map;
   for (UInt i = 0; i < old_nodes_numbers.getSize(); ++i) {
     renumbering_map[old_nodes_numbers(i)] = i;
   }
 
   /// renumber the nodes
   renumberNodesInConnectivity(local_connectivities,
                               (nb_local_element + nb_ghost_element) *
                                   nb_nodes_per_element,
                               renumbering_map);
 
   std::map<UInt, UInt>::iterator it = renumbering_map.begin();
   std::map<UInt, UInt>::iterator end = renumbering_map.end();
   old_nodes_numbers.resize(renumbering_map.size());
   for (; it != end; ++it) {
     old_nodes_numbers(it->second) = it->first;
   }
   renumbering_map.clear();
 
   MeshAccessor mesh_accessor(mesh);
 
   /// copy the renumbered connectivity to the right place
   Array<UInt> & local_conn = mesh_accessor.getConnectivity(type);
   local_conn.resize(nb_local_element);
   memcpy(local_conn.storage(), local_connectivities.storage(),
          nb_local_element * nb_nodes_per_element * sizeof(UInt));
 
   Array<UInt> & ghost_conn = mesh_accessor.getConnectivity(type, _ghost);
   ghost_conn.resize(nb_ghost_element);
   memcpy(ghost_conn.storage(),
          local_connectivities.storage() +
              nb_local_element * nb_nodes_per_element,
          nb_ghost_element * nb_nodes_per_element * sizeof(UInt));
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::renumberNodesInConnectivity(
     Array<UInt> & list_nodes, UInt nb_nodes,
     std::map<UInt, UInt> & renumbering_map) {
   AKANTU_DEBUG_IN();
 
   UInt * connectivity = list_nodes.storage();
   UInt new_node_num = renumbering_map.size();
   for (UInt n = 0; n < nb_nodes; ++n, ++connectivity) {
     UInt & node = *connectivity;
     std::map<UInt, UInt>::iterator it = renumbering_map.find(node);
     if (it == renumbering_map.end()) {
       UInt old_node = node;
       renumbering_map[old_node] = new_node_num;
       node = new_node_num;
       ++new_node_num;
     } else {
       node = it->second;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::purifyMesh(Mesh & mesh) {
   AKANTU_DEBUG_IN();
 
   std::map<UInt, UInt> renumbering_map;
 
   RemovedNodesEvent remove_nodes(mesh);
   Array<UInt> & nodes_removed = remove_nodes.getList();
 
   for (UInt gt = _not_ghost; gt <= _ghost; ++gt) {
     GhostType ghost_type = (GhostType)gt;
 
     Mesh::type_iterator it =
         mesh.firstType(_all_dimensions, ghost_type, _ek_not_defined);
     Mesh::type_iterator end =
         mesh.lastType(_all_dimensions, ghost_type, _ek_not_defined);
     for (; it != end; ++it) {
 
       ElementType type(*it);
       UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
 
       Array<UInt> & connectivity = mesh.getConnectivity(type, ghost_type);
       UInt nb_element(connectivity.getSize());
 
       renumberNodesInConnectivity(
           connectivity, nb_element * nb_nodes_per_element, renumbering_map);
     }
   }
 
   Array<UInt> & new_numbering = remove_nodes.getNewNumbering();
   std::fill(new_numbering.begin(), new_numbering.end(), UInt(-1));
 
   std::map<UInt, UInt>::iterator it = renumbering_map.begin();
   std::map<UInt, UInt>::iterator end = renumbering_map.end();
   for (; it != end; ++it) {
     new_numbering(it->first) = it->second;
   }
 
   for (UInt i = 0; i < new_numbering.getSize(); ++i) {
     if (new_numbering(i) == UInt(-1))
       nodes_removed.push_back(i);
   }
 
   mesh.sendEvent(remove_nodes);
 
   AKANTU_DEBUG_OUT();
 }
 
 #if defined(AKANTU_COHESIVE_ELEMENT)
 /* -------------------------------------------------------------------------- */
 UInt MeshUtils::insertCohesiveElements(
     Mesh & mesh, Mesh & mesh_facets,
     const ElementTypeMapArray<bool> & facet_insertion,
     Array<UInt> & doubled_nodes, Array<Element> & new_elements,
     bool only_double_facets) {
   UInt spatial_dimension = mesh.getSpatialDimension();
   UInt elements_to_insert = updateFacetToDouble(mesh_facets, facet_insertion);
 
   if (elements_to_insert > 0) {
 
     if (spatial_dimension == 1) {
       doublePointFacet(mesh, mesh_facets, doubled_nodes);
     } else {
       doubleFacet(mesh, mesh_facets, spatial_dimension - 1, doubled_nodes,
                   true);
       findSubfacetToDouble<false>(mesh, mesh_facets);
 
       if (spatial_dimension == 2) {
         doubleSubfacet<2>(mesh, mesh_facets, doubled_nodes);
       } else if (spatial_dimension == 3) {
         doubleFacet(mesh, mesh_facets, 1, doubled_nodes, false);
         findSubfacetToDouble<true>(mesh, mesh_facets);
         doubleSubfacet<3>(mesh, mesh_facets, doubled_nodes);
       }
     }
 
     if (!only_double_facets)
       updateCohesiveData(mesh, mesh_facets, new_elements);
   }
 
   return elements_to_insert;
 }
 #endif
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::doubleNodes(Mesh & mesh, const std::vector<UInt> & old_nodes,
                             Array<UInt> & doubled_nodes) {
   AKANTU_DEBUG_IN();
 
   Array<Real> & position = mesh.getNodes();
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   UInt old_nb_nodes = position.getSize();
   UInt new_nb_nodes = old_nb_nodes + old_nodes.size();
 
   UInt old_nb_doubled_nodes = doubled_nodes.getSize();
   UInt new_nb_doubled_nodes = old_nb_doubled_nodes + old_nodes.size();
 
   position.resize(new_nb_nodes);
   doubled_nodes.resize(new_nb_doubled_nodes);
 
   Array<Real>::iterator<Vector<Real>> position_begin =
       position.begin(spatial_dimension);
 
   for (UInt n = 0; n < old_nodes.size(); ++n) {
     UInt new_node = old_nb_nodes + n;
 
     /// store doubled nodes
     doubled_nodes(old_nb_doubled_nodes + n, 0) = old_nodes[n];
     doubled_nodes(old_nb_doubled_nodes + n, 1) = new_node;
 
     /// update position
     std::copy(position_begin + old_nodes[n], position_begin + old_nodes[n] + 1,
               position_begin + new_node);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::doubleFacet(Mesh & mesh, Mesh & mesh_facets,
                             UInt facet_dimension, Array<UInt> & doubled_nodes,
                             bool facet_mode) {
   AKANTU_DEBUG_IN();
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType gt_facet = *gt;
 
     Mesh::type_iterator it = mesh_facets.firstType(facet_dimension, gt_facet);
     Mesh::type_iterator end = mesh_facets.lastType(facet_dimension, gt_facet);
 
     for (; it != end; ++it) {
 
       ElementType type_facet = *it;
 
       Array<UInt> & f_to_double =
           mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet);
       UInt nb_facet_to_double = f_to_double.getSize();
 
       if (nb_facet_to_double == 0)
         continue;
 
       ElementType type_subfacet = Mesh::getFacetType(type_facet);
       const UInt nb_subfacet_per_facet =
           Mesh::getNbFacetsPerElement(type_facet);
       GhostType gt_subfacet = _casper;
       Array<std::vector<Element>> * f_to_subfacet = NULL;
 
       Array<Element> & subfacet_to_facet =
           mesh_facets.getSubelementToElement(type_facet, gt_facet);
 
       Array<UInt> & conn_facet =
           mesh_facets.getConnectivity(type_facet, gt_facet);
       UInt nb_nodes_per_facet = conn_facet.getNbComponent();
 
       UInt old_nb_facet = conn_facet.getSize();
       UInt new_nb_facet = old_nb_facet + nb_facet_to_double;
 
       conn_facet.resize(new_nb_facet);
       subfacet_to_facet.resize(new_nb_facet);
 
       UInt new_facet = old_nb_facet - 1;
       Element new_facet_el(type_facet, 0, gt_facet);
 
       Array<Element>::iterator<Vector<Element>> subfacet_to_facet_begin =
           subfacet_to_facet.begin(nb_subfacet_per_facet);
       Array<UInt>::iterator<Vector<UInt>> conn_facet_begin =
           conn_facet.begin(nb_nodes_per_facet);
 
       for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
         UInt old_facet = f_to_double(facet);
         ++new_facet;
 
         /// adding a new facet by copying original one
 
         /// copy connectivity in new facet
         std::copy(conn_facet_begin + old_facet,
                   conn_facet_begin + old_facet + 1,
                   conn_facet_begin + new_facet);
 
         /// update subfacet_to_facet
         std::copy(subfacet_to_facet_begin + old_facet,
                   subfacet_to_facet_begin + old_facet + 1,
                   subfacet_to_facet_begin + new_facet);
 
         new_facet_el.element = new_facet;
 
         /// loop on every subfacet
         for (UInt sf = 0; sf < nb_subfacet_per_facet; ++sf) {
           Element & subfacet = subfacet_to_facet(old_facet, sf);
           if (subfacet == ElementNull)
             continue;
 
           if (gt_subfacet != subfacet.ghost_type) {
             gt_subfacet = subfacet.ghost_type;
             f_to_subfacet = &mesh_facets.getElementToSubelement(
                 type_subfacet, subfacet.ghost_type);
           }
 
           /// update facet_to_subfacet array
           (*f_to_subfacet)(subfacet.element).push_back(new_facet_el);
         }
       }
 
       /// update facet_to_subfacet and _segment_3 facets if any
       if (!facet_mode) {
         updateSubfacetToFacet(mesh_facets, type_facet, gt_facet, true);
         updateFacetToSubfacet(mesh_facets, type_facet, gt_facet, true);
         updateQuadraticSegments<true>(mesh, mesh_facets, type_facet, gt_facet,
                                       doubled_nodes);
       } else
         updateQuadraticSegments<false>(mesh, mesh_facets, type_facet, gt_facet,
                                        doubled_nodes);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 UInt MeshUtils::updateFacetToDouble(
     Mesh & mesh_facets, const ElementTypeMapArray<bool> & facet_insertion) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh_facets.getSpatialDimension();
   UInt nb_facets_to_double = 0.;
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType gt_facet = *gt;
 
     Mesh::type_iterator it =
         mesh_facets.firstType(spatial_dimension - 1, gt_facet);
     Mesh::type_iterator end =
         mesh_facets.lastType(spatial_dimension - 1, gt_facet);
 
     for (; it != end; ++it) {
 
       ElementType type_facet = *it;
 
       const Array<bool> & f_insertion = facet_insertion(type_facet, gt_facet);
       Array<UInt> & f_to_double =
           mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet);
 
       Array<std::vector<Element>> & element_to_facet =
           mesh_facets.getElementToSubelement(type_facet, gt_facet);
 
       ElementType el_type = _not_defined;
       GhostType el_gt = _casper;
       UInt nb_facet_per_element = 0;
       Element old_facet_el(type_facet, 0, gt_facet);
 
       Array<Element> * facet_to_element = NULL;
 
       for (UInt f = 0; f < f_insertion.getSize(); ++f) {
 
         if (f_insertion(f) == false)
           continue;
 
         ++nb_facets_to_double;
 
         if (element_to_facet(f)[1].type == _not_defined
 #if defined(AKANTU_COHESIVE_ELEMENT)
             || element_to_facet(f)[1].kind == _ek_cohesive
 #endif
         ) {
           AKANTU_DEBUG_WARNING("attempt to double a facet on the boundary");
           continue;
         }
 
         f_to_double.push_back(f);
 
         UInt new_facet = mesh_facets.getNbElement(type_facet, gt_facet) +
                          f_to_double.getSize() - 1;
         old_facet_el.element = f;
 
         /// update facet_to_element vector
         Element & elem_to_update = element_to_facet(f)[1];
         UInt el = elem_to_update.element;
 
         if (elem_to_update.ghost_type != el_gt ||
             elem_to_update.type != el_type) {
           el_type = elem_to_update.type;
           el_gt = elem_to_update.ghost_type;
           facet_to_element =
               &mesh_facets.getSubelementToElement(el_type, el_gt);
           nb_facet_per_element = facet_to_element->getNbComponent();
         }
 
         Element * f_update =
             std::find(facet_to_element->storage() + el * nb_facet_per_element,
                       facet_to_element->storage() + el * nb_facet_per_element +
                           nb_facet_per_element,
                       old_facet_el);
 
         AKANTU_DEBUG_ASSERT(
             facet_to_element->storage() + el * nb_facet_per_element !=
                 facet_to_element->storage() + el * nb_facet_per_element +
                     nb_facet_per_element,
             "Facet not found");
 
         f_update->element = new_facet;
 
         /// update elements connected to facet
         std::vector<Element> first_facet_list = element_to_facet(f);
         element_to_facet.push_back(first_facet_list);
 
         /// set new and original facets as boundary facets
         element_to_facet(new_facet)[0] = element_to_facet(new_facet)[1];
 
         element_to_facet(f)[1] = ElementNull;
         element_to_facet(new_facet)[1] = ElementNull;
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
   return nb_facets_to_double;
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::resetFacetToDouble(Mesh & mesh_facets) {
   AKANTU_DEBUG_IN();
 
   for (UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType)g;
 
     Mesh::type_iterator it = mesh_facets.firstType(_all_dimensions, gt);
     Mesh::type_iterator end = mesh_facets.lastType(_all_dimensions, gt);
     for (; it != end; ++it) {
       ElementType type = *it;
       mesh_facets.getDataPointer<UInt>("facet_to_double", type, gt, 1, false);
 
       mesh_facets.getDataPointer<std::vector<Element>>(
           "facets_to_subfacet_double", type, gt, 1, false);
 
       mesh_facets.getDataPointer<std::vector<Element>>(
           "elements_to_subfacet_double", type, gt, 1, false);
 
       mesh_facets.getDataPointer<std::vector<Element>>(
           "subfacets_to_subsubfacet_double", type, gt, 1, false);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <bool subsubfacet_mode>
 void MeshUtils::findSubfacetToDouble(Mesh & mesh, Mesh & mesh_facets) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh_facets.getSpatialDimension();
   if (spatial_dimension == 1)
     return;
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType gt_facet = *gt;
 
     Mesh::type_iterator it =
         mesh_facets.firstType(spatial_dimension - 1, gt_facet);
     Mesh::type_iterator end =
         mesh_facets.lastType(spatial_dimension - 1, gt_facet);
 
     for (; it != end; ++it) {
 
       ElementType type_facet = *it;
 
       Array<UInt> & f_to_double =
           mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet);
       UInt nb_facet_to_double = f_to_double.getSize();
       if (nb_facet_to_double == 0)
         continue;
 
       ElementType type_subfacet = Mesh::getFacetType(type_facet);
       GhostType gt_subfacet = _casper;
 
       ElementType type_subsubfacet = Mesh::getFacetType(type_subfacet);
       GhostType gt_subsubfacet = _casper;
 
       Array<UInt> * conn_subfacet = NULL;
       Array<UInt> * sf_to_double = NULL;
       Array<std::vector<Element>> * sf_to_subfacet_double = NULL;
       Array<std::vector<Element>> * f_to_subfacet_double = NULL;
       Array<std::vector<Element>> * el_to_subfacet_double = NULL;
 
       UInt nb_subfacet = Mesh::getNbFacetsPerElement(type_facet);
 
       UInt nb_subsubfacet;
       UInt nb_nodes_per_sf_el;
 
       if (subsubfacet_mode) {
         nb_nodes_per_sf_el = Mesh::getNbNodesPerElement(type_subsubfacet);
         nb_subsubfacet = Mesh::getNbFacetsPerElement(type_subfacet);
       } else
         nb_nodes_per_sf_el = Mesh::getNbNodesPerElement(type_subfacet);
 
       Array<Element> & subfacet_to_facet =
           mesh_facets.getSubelementToElement(type_facet, gt_facet);
 
       Array<std::vector<Element>> & element_to_facet =
           mesh_facets.getElementToSubelement(type_facet, gt_facet);
 
       Array<Element> * subsubfacet_to_subfacet = NULL;
 
       UInt old_nb_facet = subfacet_to_facet.getSize() - nb_facet_to_double;
 
       Element current_facet(type_facet, 0, gt_facet);
       std::vector<Element> element_list;
       std::vector<Element> facet_list;
       std::vector<Element> * subfacet_list;
       if (subsubfacet_mode)
         subfacet_list = new std::vector<Element>;
 
       /// map to filter subfacets
       Array<std::vector<Element>> * facet_to_subfacet = NULL;
 
       /// this is used to make sure that both new and old facets are
       /// checked
       UInt facets[2];
 
       /// loop on every facet
       for (UInt f_index = 0; f_index < 2; ++f_index) {
         for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
           facets[bool(f_index)] = f_to_double(facet);
           facets[!bool(f_index)] = old_nb_facet + facet;
 
           UInt old_facet = facets[0];
           UInt new_facet = facets[1];
 
           Element & starting_element = element_to_facet(new_facet)[0];
           current_facet.element = old_facet;
 
           /// loop on every subfacet
           for (UInt sf = 0; sf < nb_subfacet; ++sf) {
 
             Element & subfacet = subfacet_to_facet(old_facet, sf);
             if (subfacet == ElementNull)
               continue;
 
             if (gt_subfacet != subfacet.ghost_type) {
               gt_subfacet = subfacet.ghost_type;
 
               if (subsubfacet_mode) {
                 subsubfacet_to_subfacet = &mesh_facets.getSubelementToElement(
                     type_subfacet, gt_subfacet);
               } else {
                 conn_subfacet =
                     &mesh_facets.getConnectivity(type_subfacet, gt_subfacet);
                 sf_to_double = &mesh_facets.getData<UInt>(
                     "facet_to_double", type_subfacet, gt_subfacet);
 
                 f_to_subfacet_double =
                     &mesh_facets.getData<std::vector<Element>>(
                         "facets_to_subfacet_double", type_subfacet,
                         gt_subfacet);
 
                 el_to_subfacet_double =
                     &mesh_facets.getData<std::vector<Element>>(
                         "elements_to_subfacet_double", type_subfacet,
                         gt_subfacet);
 
                 facet_to_subfacet = &mesh_facets.getElementToSubelement(
                     type_subfacet, gt_subfacet);
               }
             }
 
             if (subsubfacet_mode) {
               /// loop on every subsubfacet
               for (UInt ssf = 0; ssf < nb_subsubfacet; ++ssf) {
                 Element & subsubfacet =
                     (*subsubfacet_to_subfacet)(subfacet.element, ssf);
 
                 if (subsubfacet == ElementNull)
                   continue;
 
                 if (gt_subsubfacet != subsubfacet.ghost_type) {
                   gt_subsubfacet = subsubfacet.ghost_type;
                   conn_subfacet = &mesh_facets.getConnectivity(type_subsubfacet,
                                                                gt_subsubfacet);
                   sf_to_double = &mesh_facets.getData<UInt>(
                       "facet_to_double", type_subsubfacet, gt_subsubfacet);
 
                   sf_to_subfacet_double =
                       &mesh_facets.getData<std::vector<Element>>(
                           "subfacets_to_subsubfacet_double", type_subsubfacet,
                           gt_subsubfacet);
 
                   f_to_subfacet_double =
                       &mesh_facets.getData<std::vector<Element>>(
                           "facets_to_subfacet_double", type_subsubfacet,
                           gt_subsubfacet);
 
                   el_to_subfacet_double =
                       &mesh_facets.getData<std::vector<Element>>(
                           "elements_to_subfacet_double", type_subsubfacet,
                           gt_subsubfacet);
 
                   facet_to_subfacet = &mesh_facets.getElementToSubelement(
                       type_subsubfacet, gt_subsubfacet);
                 }
 
                 UInt global_ssf = subsubfacet.element;
 
                 Vector<UInt> subsubfacet_connectivity(
                     conn_subfacet->storage() + global_ssf * nb_nodes_per_sf_el,
                     nb_nodes_per_sf_el);
 
                 /// check if subsubfacet is to be doubled
                 if (findElementsAroundSubfacet<true>(
                         mesh, mesh_facets, starting_element, current_facet,
                         subsubfacet_connectivity, element_list, facet_list,
                         subfacet_list) == false &&
                     removeElementsInVector(*subfacet_list,
                                            (*facet_to_subfacet)(global_ssf)) ==
                         false) {
 
                   sf_to_double->push_back(global_ssf);
                   sf_to_subfacet_double->push_back(*subfacet_list);
                   f_to_subfacet_double->push_back(facet_list);
                   el_to_subfacet_double->push_back(element_list);
                 }
               }
             } else {
               const UInt global_sf = subfacet.element;
 
               Vector<UInt> subfacet_connectivity(
                   conn_subfacet->storage() + global_sf * nb_nodes_per_sf_el,
                   nb_nodes_per_sf_el);
 
               /// check if subfacet is to be doubled
               if (findElementsAroundSubfacet<false>(
                       mesh, mesh_facets, starting_element, current_facet,
                       subfacet_connectivity, element_list,
                       facet_list) == false &&
                   removeElementsInVector(
                       facet_list, (*facet_to_subfacet)(global_sf)) == false) {
 
                 sf_to_double->push_back(global_sf);
                 f_to_subfacet_double->push_back(facet_list);
                 el_to_subfacet_double->push_back(element_list);
               }
             }
           }
         }
       }
 
       if (subsubfacet_mode)
         delete subfacet_list;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 #if defined(AKANTU_COHESIVE_ELEMENT)
 void MeshUtils::updateCohesiveData(Mesh & mesh, Mesh & mesh_facets,
                                    Array<Element> & new_elements) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh.getSpatialDimension();
   bool third_dimension = spatial_dimension == 3;
 
   MeshAccessor mesh_facets_accessor(mesh_facets);
 
   for (auto gt_facet : ghost_types) {
     for (auto type_facet :
          mesh_facets.elementTypes(spatial_dimension - 1, gt_facet)) {
 
       Array<UInt> & f_to_double =
           mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet);
 
       UInt nb_facet_to_double = f_to_double.getSize();
       if (nb_facet_to_double == 0)
         continue;
 
       ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
 
       auto & facet_to_coh_element =
           mesh_facets_accessor.getSubelementToElement(type_cohesive, gt_facet);
 
       auto & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet);
       auto & conn_cohesive = mesh.getConnectivity(type_cohesive, gt_facet);
       UInt nb_nodes_per_facet = Mesh::getNbNodesPerElement(type_facet);
 
       Array<std::vector<Element>> & element_to_facet =
           mesh_facets.getElementToSubelement(type_facet, gt_facet);
 
       UInt old_nb_cohesive_elements = conn_cohesive.getSize();
       UInt new_nb_cohesive_elements =
           conn_cohesive.getSize() + nb_facet_to_double;
 
       UInt old_nb_facet = element_to_facet.getSize() - nb_facet_to_double;
       facet_to_coh_element.resize(new_nb_cohesive_elements);
       conn_cohesive.resize(new_nb_cohesive_elements);
 
       UInt new_elements_old_size = new_elements.getSize();
       new_elements.resize(new_elements_old_size + nb_facet_to_double);
 
       Element c_element(type_cohesive, 0, gt_facet, _ek_cohesive);
       Element f_element(type_facet, 0, gt_facet);
 
       UInt facets[2];
 
       for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
 
         /// (in 3D cohesive elements connectivity is inverted)
         facets[third_dimension] = f_to_double(facet);
         facets[!third_dimension] = old_nb_facet + facet;
 
         UInt cohesive_element = old_nb_cohesive_elements + facet;
 
         /// store doubled facets
         f_element.element = facets[0];
         facet_to_coh_element(cohesive_element, 0) = f_element;
         f_element.element = facets[1];
         facet_to_coh_element(cohesive_element, 1) = f_element;
 
         /// modify cohesive elements' connectivity
         for (UInt n = 0; n < nb_nodes_per_facet; ++n) {
           conn_cohesive(cohesive_element, n) = conn_facet(facets[0], n);
           conn_cohesive(cohesive_element, n + nb_nodes_per_facet) =
               conn_facet(facets[1], n);
         }
 
         /// update element_to_facet vectors
         c_element.element = cohesive_element;
         element_to_facet(facets[0])[1] = c_element;
         element_to_facet(facets[1])[1] = c_element;
 
         /// add cohesive element to the element event list
         new_elements(new_elements_old_size + facet) = c_element;
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 #endif
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::doublePointFacet(Mesh & mesh, Mesh & mesh_facets,
                                  Array<UInt> & doubled_nodes) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh.getSpatialDimension();
   if (spatial_dimension != 1)
     return;
 
   Array<Real> & position = mesh.getNodes();
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType gt_facet = *gt;
 
     Mesh::type_iterator it =
         mesh_facets.firstType(spatial_dimension - 1, gt_facet);
     Mesh::type_iterator end =
         mesh_facets.lastType(spatial_dimension - 1, gt_facet);
 
     for (; it != end; ++it) {
 
       ElementType type_facet = *it;
 
       Array<UInt> & conn_facet =
           mesh_facets.getConnectivity(type_facet, gt_facet);
       Array<std::vector<Element>> & element_to_facet =
           mesh_facets.getElementToSubelement(type_facet, gt_facet);
 
       const Array<UInt> & f_to_double =
           mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet);
 
       UInt nb_facet_to_double = f_to_double.getSize();
 
       UInt old_nb_facet = element_to_facet.getSize() - nb_facet_to_double;
       UInt new_nb_facet = element_to_facet.getSize();
 
       UInt old_nb_nodes = position.getSize();
       UInt new_nb_nodes = old_nb_nodes + nb_facet_to_double;
 
       position.resize(new_nb_nodes);
       conn_facet.resize(new_nb_facet);
 
       UInt old_nb_doubled_nodes = doubled_nodes.getSize();
       doubled_nodes.resize(old_nb_doubled_nodes + nb_facet_to_double);
 
       for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
         UInt old_facet = f_to_double(facet);
         UInt new_facet = old_nb_facet + facet;
 
         ElementType type = element_to_facet(new_facet)[0].type;
         UInt el = element_to_facet(new_facet)[0].element;
         GhostType gt = element_to_facet(new_facet)[0].ghost_type;
 
         UInt old_node = conn_facet(old_facet);
         UInt new_node = old_nb_nodes + facet;
 
         /// update position
         position(new_node) = position(old_node);
 
         conn_facet(new_facet) = new_node;
         Array<UInt> & conn_segment = mesh.getConnectivity(type, gt);
         UInt nb_nodes_per_segment = conn_segment.getNbComponent();
 
         /// update facet connectivity
         UInt i;
         for (i = 0;
              conn_segment(el, i) != old_node && i <= nb_nodes_per_segment; ++i)
           ;
         conn_segment(el, i) = new_node;
 
         doubled_nodes(old_nb_doubled_nodes + facet, 0) = old_node;
         doubled_nodes(old_nb_doubled_nodes + facet, 1) = new_node;
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <bool third_dim_segments>
 void MeshUtils::updateQuadraticSegments(Mesh & mesh, Mesh & mesh_facets,
                                         ElementType type_facet,
                                         GhostType gt_facet,
                                         Array<UInt> & doubled_nodes) {
   AKANTU_DEBUG_IN();
 
   if (type_facet != _segment_3)
     return;
 
   Array<UInt> & f_to_double =
       mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet);
   UInt nb_facet_to_double = f_to_double.getSize();
 
   UInt old_nb_facet =
       mesh_facets.getNbElement(type_facet, gt_facet) - nb_facet_to_double;
 
   Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet);
 
   Array<std::vector<Element>> & element_to_facet =
       mesh_facets.getElementToSubelement(type_facet, gt_facet);
 
   /// this ones matter only for segments in 3D
   Array<std::vector<Element>> * el_to_subfacet_double = NULL;
   Array<std::vector<Element>> * f_to_subfacet_double = NULL;
 
   if (third_dim_segments) {
     el_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>(
         "elements_to_subfacet_double", type_facet, gt_facet);
 
     f_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>(
         "facets_to_subfacet_double", type_facet, gt_facet);
   }
 
   std::vector<UInt> middle_nodes;
 
   for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
     UInt old_facet = f_to_double(facet);
     UInt node = conn_facet(old_facet, 2);
     if (!mesh.isPureGhostNode(node))
       middle_nodes.push_back(node);
   }
 
   UInt n = doubled_nodes.getSize();
 
   doubleNodes(mesh, middle_nodes, doubled_nodes);
 
   for (UInt facet = 0; facet < nb_facet_to_double; ++facet) {
     UInt old_facet = f_to_double(facet);
     UInt old_node = conn_facet(old_facet, 2);
     if (mesh.isPureGhostNode(old_node))
       continue;
 
     UInt new_node = doubled_nodes(n, 1);
     UInt new_facet = old_nb_facet + facet;
 
     conn_facet(new_facet, 2) = new_node;
 
     if (third_dim_segments) {
       updateElementalConnectivity(mesh_facets, old_node, new_node,
                                   element_to_facet(new_facet));
 
       updateElementalConnectivity(mesh, old_node, new_node,
                                   (*el_to_subfacet_double)(facet),
                                   &(*f_to_subfacet_double)(facet));
     } else {
       updateElementalConnectivity(mesh, old_node, new_node,
                                   element_to_facet(new_facet));
     }
     ++n;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::updateSubfacetToFacet(Mesh & mesh_facets,
                                       ElementType type_subfacet,
                                       GhostType gt_subfacet, bool facet_mode) {
   AKANTU_DEBUG_IN();
 
   Array<UInt> & sf_to_double =
       mesh_facets.getData<UInt>("facet_to_double", type_subfacet, gt_subfacet);
   UInt nb_subfacet_to_double = sf_to_double.getSize();
 
   /// update subfacet_to_facet vector
   ElementType type_facet = _not_defined;
   GhostType gt_facet = _casper;
   Array<Element> * subfacet_to_facet = NULL;
   UInt nb_subfacet_per_facet = 0;
   UInt old_nb_subfacet = mesh_facets.getNbElement(type_subfacet, gt_subfacet) -
                          nb_subfacet_to_double;
 
   Array<std::vector<Element>> * facet_list = NULL;
   if (facet_mode)
     facet_list = &mesh_facets.getData<std::vector<Element>>(
         "facets_to_subfacet_double", type_subfacet, gt_subfacet);
   else
     facet_list = &mesh_facets.getData<std::vector<Element>>(
         "subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet);
 
   Element old_subfacet_el(type_subfacet, 0, gt_subfacet);
   Element new_subfacet_el(type_subfacet, 0, gt_subfacet);
 
   for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) {
     old_subfacet_el.element = sf_to_double(sf);
     new_subfacet_el.element = old_nb_subfacet + sf;
 
     for (UInt f = 0; f < (*facet_list)(sf).size(); ++f) {
       Element & facet = (*facet_list)(sf)[f];
 
       if (facet.type != type_facet || facet.ghost_type != gt_facet) {
         type_facet = facet.type;
         gt_facet = facet.ghost_type;
 
         subfacet_to_facet =
             &mesh_facets.getSubelementToElement(type_facet, gt_facet);
         nb_subfacet_per_facet = subfacet_to_facet->getNbComponent();
       }
 
       Element * sf_update = std::find(
           subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet,
           subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet +
               nb_subfacet_per_facet,
           old_subfacet_el);
 
       AKANTU_DEBUG_ASSERT(subfacet_to_facet->storage() +
                                   facet.element * nb_subfacet_per_facet !=
                               subfacet_to_facet->storage() +
                                   facet.element * nb_subfacet_per_facet +
                                   nb_subfacet_per_facet,
                           "Subfacet not found");
 
       *sf_update = new_subfacet_el;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::updateFacetToSubfacet(Mesh & mesh_facets,
                                       ElementType type_subfacet,
                                       GhostType gt_subfacet, bool facet_mode) {
   AKANTU_DEBUG_IN();
 
   Array<UInt> & sf_to_double =
       mesh_facets.getData<UInt>("facet_to_double", type_subfacet, gt_subfacet);
   UInt nb_subfacet_to_double = sf_to_double.getSize();
 
   Array<std::vector<Element>> & facet_to_subfacet =
       mesh_facets.getElementToSubelement(type_subfacet, gt_subfacet);
 
   Array<std::vector<Element>> * facet_to_subfacet_double = NULL;
 
   if (facet_mode) {
     facet_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>(
         "facets_to_subfacet_double", type_subfacet, gt_subfacet);
   } else {
     facet_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>(
         "subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet);
   }
 
   UInt old_nb_subfacet = facet_to_subfacet.getSize();
   facet_to_subfacet.resize(old_nb_subfacet + nb_subfacet_to_double);
 
   for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf)
     facet_to_subfacet(old_nb_subfacet + sf) = (*facet_to_subfacet_double)(sf);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MeshUtils::doubleSubfacet(Mesh & mesh, Mesh & mesh_facets,
                                Array<UInt> & doubled_nodes) {
   AKANTU_DEBUG_IN();
 
   if (spatial_dimension == 1)
     return;
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType gt_subfacet = *gt;
 
     Mesh::type_iterator it = mesh_facets.firstType(0, gt_subfacet);
     Mesh::type_iterator end = mesh_facets.lastType(0, gt_subfacet);
 
     for (; it != end; ++it) {
 
       ElementType type_subfacet = *it;
 
       Array<UInt> & sf_to_double = mesh_facets.getData<UInt>(
           "facet_to_double", type_subfacet, gt_subfacet);
       UInt nb_subfacet_to_double = sf_to_double.getSize();
 
       if (nb_subfacet_to_double == 0)
         continue;
 
       AKANTU_DEBUG_ASSERT(
           type_subfacet == _point_1,
           "Only _point_1 subfacet doubling is supported at the moment");
 
       Array<UInt> & conn_subfacet =
           mesh_facets.getConnectivity(type_subfacet, gt_subfacet);
 
       UInt old_nb_subfacet = conn_subfacet.getSize();
       UInt new_nb_subfacet = old_nb_subfacet + nb_subfacet_to_double;
 
       conn_subfacet.resize(new_nb_subfacet);
 
       std::vector<UInt> nodes_to_double;
       UInt old_nb_doubled_nodes = doubled_nodes.getSize();
 
       /// double nodes
       for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) {
         UInt old_subfacet = sf_to_double(sf);
         nodes_to_double.push_back(conn_subfacet(old_subfacet));
       }
 
       doubleNodes(mesh, nodes_to_double, doubled_nodes);
 
       /// add new nodes in connectivity
       for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) {
         UInt new_subfacet = old_nb_subfacet + sf;
         UInt new_node = doubled_nodes(old_nb_doubled_nodes + sf, 1);
 
         conn_subfacet(new_subfacet) = new_node;
       }
 
       /// update facet and element connectivity
       Array<std::vector<Element>> & f_to_subfacet_double =
           mesh_facets.getData<std::vector<Element>>("facets_to_subfacet_double",
                                                     type_subfacet, gt_subfacet);
 
       Array<std::vector<Element>> & el_to_subfacet_double =
           mesh_facets.getData<std::vector<Element>>(
               "elements_to_subfacet_double", type_subfacet, gt_subfacet);
 
       Array<std::vector<Element>> * sf_to_subfacet_double = NULL;
 
       if (spatial_dimension == 3)
         sf_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>(
             "subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet);
 
       for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) {
         UInt old_node = doubled_nodes(old_nb_doubled_nodes + sf, 0);
         UInt new_node = doubled_nodes(old_nb_doubled_nodes + sf, 1);
 
         updateElementalConnectivity(mesh, old_node, new_node,
                                     el_to_subfacet_double(sf),
                                     &f_to_subfacet_double(sf));
 
         updateElementalConnectivity(mesh_facets, old_node, new_node,
                                     f_to_subfacet_double(sf));
 
         if (spatial_dimension == 3)
           updateElementalConnectivity(mesh_facets, old_node, new_node,
                                       (*sf_to_subfacet_double)(sf));
       }
 
       if (spatial_dimension == 2) {
         updateSubfacetToFacet(mesh_facets, type_subfacet, gt_subfacet, true);
         updateFacetToSubfacet(mesh_facets, type_subfacet, gt_subfacet, true);
       } else if (spatial_dimension == 3) {
         updateSubfacetToFacet(mesh_facets, type_subfacet, gt_subfacet, false);
         updateFacetToSubfacet(mesh_facets, type_subfacet, gt_subfacet, false);
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::flipFacets(
     Mesh & mesh_facets, const ElementTypeMapArray<UInt> & global_connectivity,
     GhostType gt_facet) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh_facets.getSpatialDimension();
 
   /// get global connectivity for local mesh
   ElementTypeMapArray<UInt> global_connectivity_tmp("global_connectivity_tmp",
                                                     mesh_facets.getID(),
                                                     mesh_facets.getMemoryID());
 
   global_connectivity_tmp.initialize(
       mesh_facets, _spatial_dimension = spatial_dimension - 1,
       _with_nb_nodes_per_element = true, _with_nb_element = true);
   // mesh_facets.initElementTypeMapArray(global_connectivity_tmp, 1,
   //                                     spatial_dimension - 1, gt_facet,
   //                                     true, _ek_regular, true);
 
   mesh_facets.getGlobalConnectivity(global_connectivity_tmp,
                                     spatial_dimension - 1, gt_facet);
 
   /// loop on every facet
   for (auto type_facet :
        mesh_facets.elementTypes(spatial_dimension - 1, gt_facet)) {
 
     auto & connectivity = mesh_facets.getConnectivity(type_facet, gt_facet);
     const auto & g_connectivity = global_connectivity(type_facet, gt_facet);
 
     auto & el_to_f = mesh_facets.getElementToSubelement(type_facet, gt_facet);
     auto & subfacet_to_facet =
         mesh_facets.getSubelementToElement(type_facet, gt_facet);
 
     UInt nb_subfacet_per_facet = subfacet_to_facet.getNbComponent();
     UInt nb_nodes_per_facet = connectivity.getNbComponent();
     UInt nb_facet = connectivity.getSize();
 
     UInt nb_nodes_per_P1_facet =
         Mesh::getNbNodesPerElement(Mesh::getP1ElementType(type_facet));
 
-    auto & global_conn_tmp =
-        global_connectivity_tmp(type_facet, gt_facet);
-
-    auto conn_it =
-        connectivity.begin(nb_nodes_per_facet);
-    auto gconn_tmp_it =
-        global_conn_tmp.begin(nb_nodes_per_facet);
-    auto conn_glob_it =
-        g_connectivity.begin(nb_nodes_per_facet);
-    auto subf_to_f =
-        subfacet_to_facet.begin(nb_subfacet_per_facet);
+    auto & global_conn_tmp = global_connectivity_tmp(type_facet, gt_facet);
+
+    auto conn_it = connectivity.begin(nb_nodes_per_facet);
+    auto gconn_tmp_it = global_conn_tmp.begin(nb_nodes_per_facet);
+    auto conn_glob_it = g_connectivity.begin(nb_nodes_per_facet);
+    auto subf_to_f = subfacet_to_facet.begin(nb_subfacet_per_facet);
 
     UInt * conn_tmp_pointer = new UInt[nb_nodes_per_facet];
     Vector<UInt> conn_tmp(conn_tmp_pointer, nb_nodes_per_facet);
 
     Element el_tmp;
     Element * subf_tmp_pointer = new Element[nb_subfacet_per_facet];
     Vector<Element> subf_tmp(subf_tmp_pointer, nb_subfacet_per_facet);
 
     for (UInt f = 0; f < nb_facet;
          ++f, ++conn_it, ++gconn_tmp_it, ++subf_to_f, ++conn_glob_it) {
 
       Vector<UInt> & gconn_tmp = *gconn_tmp_it;
       const Vector<UInt> & conn_glob = *conn_glob_it;
       Vector<UInt> & conn_local = *conn_it;
 
       /// skip facet if connectivities are the same
       if (gconn_tmp == conn_glob)
         continue;
 
       /// re-arrange connectivity
       conn_tmp = conn_local;
 
       UInt * begin = conn_glob.storage();
       UInt * end = conn_glob.storage() + nb_nodes_per_facet;
 
       for (UInt n = 0; n < nb_nodes_per_facet; ++n) {
 
         UInt * new_node = std::find(begin, end, gconn_tmp(n));
         AKANTU_DEBUG_ASSERT(new_node != end, "Node not found");
 
         UInt new_position = new_node - begin;
 
         conn_local(new_position) = conn_tmp(n);
       }
 
       /// if 3D, check if facets are just rotated
       if (spatial_dimension == 3) {
         /// find first node
         UInt * new_node = std::find(begin, end, gconn_tmp(0));
         AKANTU_DEBUG_ASSERT(new_node != end, "Node not found");
 
         UInt new_position = new_node - begin;
         UInt n = 1;
 
         /// count how many nodes in the received connectivity follow
         /// the same order of those in the local connectivity
         for (; n < nb_nodes_per_P1_facet &&
                gconn_tmp(n) ==
                    conn_glob((new_position + n) % nb_nodes_per_P1_facet);
              ++n)
           ;
 
         /// skip the facet inversion if facet is just rotated
         if (n == nb_nodes_per_P1_facet)
           continue;
       }
 
       /// update data to invert facet
       el_tmp = el_to_f(f)[0];
       el_to_f(f)[0] = el_to_f(f)[1];
       el_to_f(f)[1] = el_tmp;
 
       subf_tmp = (*subf_to_f);
       (*subf_to_f)(0) = subf_tmp(1);
       (*subf_to_f)(1) = subf_tmp(0);
     }
 
     delete[] subf_tmp_pointer;
     delete[] conn_tmp_pointer;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::fillElementToSubElementsData(Mesh & mesh) {
   AKANTU_DEBUG_IN();
 
   if (mesh.getNbElement(mesh.getSpatialDimension() - 1) == 0) {
     AKANTU_DEBUG_INFO("There are not facets, add them in the mesh file or call "
                       "the buildFacet method.");
     return;
   }
 
   UInt spatial_dimension = mesh.getSpatialDimension();
   ElementTypeMapArray<Real> barycenters("barycenter_tmp", mesh.getID(),
                                         mesh.getMemoryID());
-  barycenters.initialize(mesh, _nb_component = spatial_dimension);
+  barycenters.initialize(mesh, _nb_component = spatial_dimension,
+                         _spatial_dimension = _all_dimensions);
   // mesh.initElementTypeMapArray(barycenters, spatial_dimension,
   // _all_dimensions);
 
   Element element;
   for (auto ghost_type : ghost_types) {
     element.ghost_type = ghost_type;
     for (auto & type : mesh.elementTypes(_all_dimensions, ghost_type)) {
       element.type = type;
 
       UInt nb_element = mesh.getNbElement(type, ghost_type);
       Array<Real> & barycenters_arr = barycenters(type, ghost_type);
       barycenters_arr.resize(nb_element);
       auto bary = barycenters_arr.begin(spatial_dimension);
       auto bary_end = barycenters_arr.end(spatial_dimension);
 
       for (UInt el = 0; bary != bary_end; ++bary, ++el) {
         element.element = el;
         mesh.getBarycenter(element, *bary);
       }
     }
   }
 
   MeshAccessor mesh_accessor(mesh);
   for (Int sp(spatial_dimension); sp >= 1; --sp) {
     if (mesh.getNbElement(sp) == 0)
       continue;
 
     for (auto ghost_type : ghost_types) {
       for (auto & type : mesh.elementTypes(sp, ghost_type)) {
         mesh_accessor.getSubelementToElement(type, ghost_type)
             .resize(mesh.getNbElement(type, ghost_type));
         mesh_accessor.getSubelementToElement(type, ghost_type).clear();
       }
 
       for (auto & type : mesh.elementTypes(sp - 1, ghost_type)) {
         mesh_accessor.getElementToSubelement(type, ghost_type)
             .resize(mesh.getNbElement(type, ghost_type));
         mesh.getElementToSubelement(type, ghost_type).clear();
       }
     }
 
     CSR<Element> nodes_to_elements;
     buildNode2Elements(mesh, nodes_to_elements, sp);
 
     Element facet_element;
 
     for (auto ghost_type : ghost_types) {
       facet_element.ghost_type = ghost_type;
       for (auto & type : mesh.elementTypes(sp - 1, ghost_type)) {
         facet_element.type = type;
 
         auto & element_to_subelement =
             mesh.getElementToSubelement(type, ghost_type);
 
         const auto & connectivity = mesh.getConnectivity(type, ghost_type);
 
         auto fit = connectivity.begin(mesh.getNbNodesPerElement(type));
         auto fend = connectivity.end(mesh.getNbNodesPerElement(type));
 
         UInt fid = 0;
         for (; fit != fend; ++fit, ++fid) {
           const Vector<UInt> & facet = *fit;
           facet_element.element = fid;
           std::map<Element, UInt> element_seen_counter;
           UInt nb_nodes_per_facet =
               mesh.getNbNodesPerElement(Mesh::getP1ElementType(type));
 
           for (UInt n(0); n < nb_nodes_per_facet; ++n) {
 
             auto eit = nodes_to_elements.begin(facet(n));
             auto eend = nodes_to_elements.end(facet(n));
             for (; eit != eend; ++eit) {
               auto & elem = *eit;
               auto cit = element_seen_counter.find(elem);
               if (cit != element_seen_counter.end()) {
                 cit->second++;
               } else {
                 element_seen_counter[elem] = 1;
               }
             }
           }
 
           std::vector<Element> connected_elements;
           auto cit = element_seen_counter.begin();
           auto cend = element_seen_counter.end();
           for (; cit != cend; ++cit) {
             if (cit->second == nb_nodes_per_facet)
               connected_elements.push_back(cit->first);
           }
 
           auto ceit = connected_elements.begin();
           auto ceend = connected_elements.end();
           for (; ceit != ceend; ++ceit)
             element_to_subelement(fid).push_back(*ceit);
 
           for (UInt ce = 0; ce < connected_elements.size(); ++ce) {
             Element & elem = connected_elements[ce];
             Array<Element> & subelement_to_element =
                 mesh_accessor.getSubelementToElement(elem.type,
                                                      elem.ghost_type);
 
             UInt f(0);
             for (; f < mesh.getNbFacetsPerElement(elem.type) &&
                    subelement_to_element(elem.element, f) != ElementNull;
                  ++f)
               ;
 
             AKANTU_DEBUG_ASSERT(
                 f < mesh.getNbFacetsPerElement(elem.type),
                 "The element " << elem << " seems to have too many facets!! ("
                                << f << " < "
                                << mesh.getNbFacetsPerElement(elem.type) << ")");
 
             subelement_to_element(elem.element, f) = facet_element;
           }
         }
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <bool third_dim_points>
 bool MeshUtils::findElementsAroundSubfacet(
     const Mesh & mesh, const Mesh & mesh_facets,
     const Element & starting_element, const Element & end_facet,
     const Vector<UInt> & subfacet_connectivity,
     std::vector<Element> & elem_list, std::vector<Element> & facet_list,
     std::vector<Element> * subfacet_list) {
   AKANTU_DEBUG_IN();
 
   /// preallocated stuff before starting
   bool facet_matched = false;
 
   elem_list.clear();
   facet_list.clear();
 
   if (third_dim_points)
     subfacet_list->clear();
 
   elem_list.push_back(starting_element);
 
   const Array<UInt> * facet_connectivity = NULL;
   const Array<UInt> * sf_connectivity = NULL;
   const Array<Element> * facet_to_element = NULL;
   const Array<Element> * subfacet_to_facet = NULL;
 
   ElementType current_type = _not_defined;
   GhostType current_ghost_type = _casper;
 
   ElementType current_facet_type = _not_defined;
   GhostType current_facet_ghost_type = _casper;
 
   ElementType current_subfacet_type = _not_defined;
   GhostType current_subfacet_ghost_type = _casper;
 
   const Array<std::vector<Element>> * element_to_facet = NULL;
 
   const Element * opposing_el = NULL;
 
   std::queue<Element> elements_to_check;
   elements_to_check.push(starting_element);
 
   /// keep going until there are elements to check
   while (!elements_to_check.empty()) {
 
     /// check current element
     Element & current_el = elements_to_check.front();
 
     if (current_el.type != current_type ||
         current_el.ghost_type != current_ghost_type) {
 
       current_type = current_el.type;
       current_ghost_type = current_el.ghost_type;
 
       facet_to_element =
           &mesh_facets.getSubelementToElement(current_type, current_ghost_type);
     }
 
     /// loop over each facet of the element
     for (UInt f = 0; f < facet_to_element->getNbComponent(); ++f) {
 
       const Element & current_facet =
           (*facet_to_element)(current_el.element, f);
 
       if (current_facet == ElementNull)
         continue;
 
       if (current_facet_type != current_facet.type ||
           current_facet_ghost_type != current_facet.ghost_type) {
 
         current_facet_type = current_facet.type;
         current_facet_ghost_type = current_facet.ghost_type;
 
         element_to_facet = &mesh_facets.getElementToSubelement(
             current_facet_type, current_facet_ghost_type);
         facet_connectivity = &mesh_facets.getConnectivity(
             current_facet_type, current_facet_ghost_type);
 
         if (third_dim_points)
           subfacet_to_facet = &mesh_facets.getSubelementToElement(
               current_facet_type, current_facet_ghost_type);
       }
 
       /// check if end facet is reached
       if (current_facet == end_facet)
         facet_matched = true;
 
       /// add this facet if not already passed
       if (std::find(facet_list.begin(), facet_list.end(), current_facet) ==
               facet_list.end() &&
           hasElement(*facet_connectivity, current_facet,
                      subfacet_connectivity)) {
         facet_list.push_back(current_facet);
 
         if (third_dim_points) {
           /// check subfacets
           for (UInt sf = 0; sf < subfacet_to_facet->getNbComponent(); ++sf) {
             const Element & current_subfacet =
                 (*subfacet_to_facet)(current_facet.element, sf);
 
             if (current_subfacet == ElementNull)
               continue;
 
             if (current_subfacet_type != current_subfacet.type ||
                 current_subfacet_ghost_type != current_subfacet.ghost_type) {
               current_subfacet_type = current_subfacet.type;
               current_subfacet_ghost_type = current_subfacet.ghost_type;
 
               sf_connectivity = &mesh_facets.getConnectivity(
                   current_subfacet_type, current_subfacet_ghost_type);
             }
 
             if (std::find(subfacet_list->begin(), subfacet_list->end(),
                           current_subfacet) == subfacet_list->end() &&
                 hasElement(*sf_connectivity, current_subfacet,
                            subfacet_connectivity))
               subfacet_list->push_back(current_subfacet);
           }
         }
       } else
         continue;
 
       /// consider opposing element
       if ((*element_to_facet)(current_facet.element)[0] == current_el)
         opposing_el = &(*element_to_facet)(current_facet.element)[1];
       else
         opposing_el = &(*element_to_facet)(current_facet.element)[0];
 
       /// skip null elements since they are on a boundary
       if (*opposing_el == ElementNull)
         continue;
 
       /// skip this element if already added
       if (std::find(elem_list.begin(), elem_list.end(), *opposing_el) !=
           elem_list.end())
         continue;
 
       /// only regular elements have to be checked
       if (opposing_el->kind == _ek_regular)
         elements_to_check.push(*opposing_el);
 
       elem_list.push_back(*opposing_el);
 
 #ifndef AKANTU_NDEBUG
       const Array<UInt> & conn_elem =
           mesh.getConnectivity(opposing_el->type, opposing_el->ghost_type);
 
       AKANTU_DEBUG_ASSERT(
           hasElement(conn_elem, *opposing_el, subfacet_connectivity),
           "Subfacet doesn't belong to this element");
 #endif
     }
 
     /// erased checked element from the list
     elements_to_check.pop();
   }
 
   AKANTU_DEBUG_OUT();
   return facet_matched;
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::buildSegmentToNodeType(const Mesh & mesh, Mesh & mesh_facets) {
   buildAllFacets(mesh, mesh_facets, 1);
 
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   const ElementTypeMapArray<UInt> & element_to_rank =
       mesh.getElementSynchronizer().getPrankToElement();
   Int local_rank = StaticCommunicator::getStaticCommunicator().whoAmI();
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
     GhostType ghost_type = *gt;
     Mesh::type_iterator it = mesh_facets.firstType(1, ghost_type);
     Mesh::type_iterator end = mesh_facets.lastType(1, ghost_type);
     for (; it != end; ++it) {
       ElementType type = *it;
       UInt nb_segments = mesh_facets.getNbElement(type, ghost_type);
 
       // allocate the data
       Array<Int> & segment_to_nodetype = *(mesh_facets.getDataPointer<Int>(
           "segment_to_nodetype", type, ghost_type));
 
       std::set<Element> connected_elements;
       const Array<std::vector<Element>> & segment_to_2Delement =
           mesh_facets.getElementToSubelement(type, ghost_type);
 
       // loop over segments
       for (UInt s = 0; s < nb_segments; ++s) {
 
         // determine the elements connected to the segment
         connected_elements.clear();
         const std::vector<Element> & twoD_elements = segment_to_2Delement(s);
 
         if (spatial_dimension == 2) {
           // if 2D just take the elements connected to the segments
           connected_elements.insert(twoD_elements.begin(), twoD_elements.end());
         } else if (spatial_dimension == 3) {
           // if 3D a second loop is needed to get to the 3D elements
           std::vector<Element>::const_iterator facet = twoD_elements.begin();
 
           for (; facet != twoD_elements.end(); ++facet) {
             const std::vector<Element> & threeD_elements =
                 mesh_facets.getElementToSubelement(
                     facet->type, facet->ghost_type)(facet->element);
             connected_elements.insert(threeD_elements.begin(),
                                       threeD_elements.end());
           }
         }
 
         // get the minimum processor rank associated to the connected
         // elements and verify if ghost and not ghost elements are
         // found
         Int minimum_rank = std::numeric_limits<Int>::max();
 
         // two booleans saying if not ghost and ghost elements are found in the
         // loop
         bool ghost_found[2];
         ghost_found[0] = false;
         ghost_found[1] = false;
 
         std::set<Element>::iterator connected_elements_it =
             connected_elements.begin();
 
         for (; connected_elements_it != connected_elements.end();
              ++connected_elements_it) {
           if (*connected_elements_it == ElementNull)
             continue;
           ghost_found[connected_elements_it->ghost_type] = true;
           const Array<UInt> & el_to_rank_array = element_to_rank(
               connected_elements_it->type, connected_elements_it->ghost_type);
           minimum_rank =
               std::min(minimum_rank,
                        Int(el_to_rank_array(connected_elements_it->element)));
         }
 
         // if no ghost elements are found the segment is local
         if (!ghost_found[1])
           segment_to_nodetype(s) = -1;
         // if no not ghost elements are found the segment is pure ghost
         else if (!ghost_found[0])
           segment_to_nodetype(s) = -3;
         // if the minimum rank is equal to the local rank, the segment is master
         else if (local_rank == minimum_rank)
           segment_to_nodetype(s) = -2;
         // if the minimum rank is less than the local rank, the segment is slave
         else if (local_rank > minimum_rank)
           segment_to_nodetype(s) = minimum_rank;
         else
           AKANTU_DEBUG_ERROR("The local rank cannot be smaller than the "
                              "minimum rank if both ghost and not ghost "
                              "elements are found");
       }
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 UInt MeshUtils::updateLocalMasterGlobalConnectivity(Mesh & mesh,
                                                     UInt local_nb_new_nodes) {
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   Int rank = comm.whoAmI();
   Int nb_proc = comm.getNbProc();
   if (nb_proc == 1)
     return local_nb_new_nodes;
 
   /// resize global ids array
   Array<UInt> & nodes_global_ids = mesh.getGlobalNodesIds();
   UInt old_nb_nodes = mesh.getNbNodes() - local_nb_new_nodes;
 
   nodes_global_ids.resize(mesh.getNbNodes());
 
   /// compute the number of global nodes based on the number of old nodes
   Vector<UInt> old_local_master_nodes(nb_proc);
   for (UInt n = 0; n < old_nb_nodes; ++n)
     if (mesh.isLocalOrMasterNode(n))
       ++old_local_master_nodes(rank);
   comm.allGather(old_local_master_nodes);
   UInt old_global_nodes =
       std::accumulate(old_local_master_nodes.storage(),
                       old_local_master_nodes.storage() + nb_proc, 0);
 
   /// compute amount of local or master doubled nodes
   Vector<UInt> local_master_nodes(nb_proc);
   for (UInt n = old_nb_nodes; n < mesh.getNbNodes(); ++n)
     if (mesh.isLocalOrMasterNode(n))
       ++local_master_nodes(rank);
 
   comm.allGather(local_master_nodes);
 
   /// update global number of nodes
   UInt total_nb_new_nodes = std::accumulate(
       local_master_nodes.storage(), local_master_nodes.storage() + nb_proc, 0);
 
   if (total_nb_new_nodes == 0)
     return 0;
 
   /// set global ids of local and master nodes
   UInt starting_index =
       std::accumulate(local_master_nodes.storage(),
                       local_master_nodes.storage() + rank, old_global_nodes);
 
   for (UInt n = old_nb_nodes; n < mesh.getNbNodes(); ++n) {
     if (mesh.isLocalOrMasterNode(n)) {
       nodes_global_ids(n) = starting_index;
       ++starting_index;
     }
   }
 
   MeshAccessor mesh_accessor(mesh);
   mesh_accessor.setNbGlobalNodes(old_global_nodes + total_nb_new_nodes);
   return total_nb_new_nodes;
 }
 
 /* -------------------------------------------------------------------------- */
 // Deactivating -Wunused-parameter
 #if defined(__INTEL_COMPILER)
 //#pragma warning ( disable : 383 )
 #elif defined(__clang__) // test clang to be sure that when we test for gnu it
 // is only gnu
 #elif (defined(__GNUC__) || defined(__GNUG__))
 #define GCC_VERSION                                                            \
   (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
 #if GCC_VERSION > 40600
 #pragma GCC diagnostic push
 #endif
 #pragma GCC diagnostic ignored "-Wunused-parameter"
 #endif
 
 /* -------------------------------------------------------------------------- */
 void MeshUtils::updateElementalConnectivity(
     Mesh & mesh, UInt old_node, UInt new_node,
     const std::vector<Element> & element_list,
     __attribute__((unused)) const std::vector<Element> * facet_list) {
   AKANTU_DEBUG_IN();
 
   ElementType el_type = _not_defined;
   GhostType gt_type = _casper;
   Array<UInt> * conn_elem = NULL;
 #if defined(AKANTU_COHESIVE_ELEMENT)
   const Array<Element> * cohesive_facets = NULL;
 #endif
   UInt nb_nodes_per_element = 0;
   UInt * n_update = NULL;
 
   for (UInt el = 0; el < element_list.size(); ++el) {
     const Element & elem = element_list[el];
     if (elem.type == _not_defined)
       continue;
 
     if (elem.type != el_type || elem.ghost_type != gt_type) {
       el_type = elem.type;
       gt_type = elem.ghost_type;
       conn_elem = &mesh.getConnectivity(el_type, gt_type);
       nb_nodes_per_element = conn_elem->getNbComponent();
 #if defined(AKANTU_COHESIVE_ELEMENT)
       if (elem.kind == _ek_cohesive)
         cohesive_facets =
             &mesh.getMeshFacets().getSubelementToElement(el_type, gt_type);
 #endif
     }
 
 #if defined(AKANTU_COHESIVE_ELEMENT)
     if (elem.kind == _ek_cohesive) {
 
       AKANTU_DEBUG_ASSERT(
           facet_list != NULL,
           "Provide a facet list in order to update cohesive elements");
 
       /// loop over cohesive element's facets
       for (UInt f = 0, n = 0; f < 2; ++f, n += nb_nodes_per_element / 2) {
         const Element & facet = (*cohesive_facets)(elem.element, f);
 
         /// skip facets if not present in the list
         if (std::find(facet_list->begin(), facet_list->end(), facet) ==
             facet_list->end())
           continue;
 
         n_update = std::find(
             conn_elem->storage() + elem.element * nb_nodes_per_element + n,
             conn_elem->storage() + elem.element * nb_nodes_per_element + n +
                 nb_nodes_per_element / 2,
             old_node);
 
         AKANTU_DEBUG_ASSERT(n_update !=
                                 conn_elem->storage() +
                                     elem.element * nb_nodes_per_element + n +
                                     nb_nodes_per_element / 2,
                             "Node not found in current element");
 
         /// update connectivity
         *n_update = new_node;
       }
     } else {
 #endif
       n_update =
           std::find(conn_elem->storage() + elem.element * nb_nodes_per_element,
                     conn_elem->storage() + elem.element * nb_nodes_per_element +
                         nb_nodes_per_element,
                     old_node);
 
       AKANTU_DEBUG_ASSERT(n_update != conn_elem->storage() +
                                           elem.element * nb_nodes_per_element +
                                           nb_nodes_per_element,
                           "Node not found in current element");
 
       /// update connectivity
       *n_update = new_node;
 #if defined(AKANTU_COHESIVE_ELEMENT)
     }
 #endif
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 // Reactivating -Wunused-parameter
 #if defined(__INTEL_COMPILER)
 //#pragma warning ( disable : 383 )
 #elif defined(__clang__) // test clang to be sure that when we test for gnu it
 // is only gnu
 #elif defined(__GNUG__)
 #if GCC_VERSION > 40600
 #pragma GCC diagnostic pop
 #else
 #pragma GCC diagnostic warning "-Wunused-parameter"
 #endif
 #endif
 /* -------------------------------------------------------------------------- */
 
 } // namespace akantu
 
 //  LocalWords:  ElementType
diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood.hh b/src/model/common/non_local_toolbox/non_local_neighborhood.hh
index 0020bf03b..cff16242e 100644
--- a/src/model/common/non_local_toolbox/non_local_neighborhood.hh
+++ b/src/model/common/non_local_toolbox/non_local_neighborhood.hh
@@ -1,131 +1,131 @@
 /**
  * @file   non_local_neighborhood.hh
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Wed Nov 25 2015
  *
  * @brief  Non-local neighborhood for non-local averaging based on
  * weight function
  *
  * @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_NON_LOCAL_NEIGHBORHOOD_HH__
 #define __AKANTU_NON_LOCAL_NEIGHBORHOOD_HH__
 /* -------------------------------------------------------------------------- */
 #include "base_weight_function.hh"
 #include "non_local_neighborhood_base.hh"
 #include "parsable.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 class NonLocalManager;
 class BaseWeightFunction;
 } // namespace akantu
 
 namespace akantu {
 
 template <class WeightFunction = BaseWeightFunction>
 class NonLocalNeighborhood : public NonLocalNeighborhoodBase {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   NonLocalNeighborhood(NonLocalManager & manager,
                        const ElementTypeMapReal & quad_coordinates,
                        const ID & id = "neighborhood",
                        const MemoryID & memory_id = 0);
   virtual ~NonLocalNeighborhood();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// compute the weights for non-local averaging
   void computeWeights();
 
   /// save the pair of weights in a file
-  void saveWeights(const std::string & filename) const;
+  void saveWeights(const std::string & filename) const override;
 
   /// compute the non-local counter part for a given element type map
   // compute the non-local counter part for a given element type map
   void weightedAverageOnNeighbours(const ElementTypeMapReal & to_accumulate,
                                    ElementTypeMapReal & accumulated,
                                    UInt nb_degree_of_freedom,
                                    const GhostType & ghost_type2) const override;
 
   /// update the weights based on the weight function
   void updateWeights();
 
   /// register a new non-local variable in the neighborhood
   //void registerNonLocalVariable(const ID & id);
 
 protected:
   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;
 
   /* --------------------------------------------------------------------------
    */
   /* Accessor */
   /* --------------------------------------------------------------------------
    */
   AKANTU_GET_MACRO(NonLocalManager, non_local_manager, const NonLocalManager &);
   AKANTU_GET_MACRO_NOT_CONST(NonLocalManager, non_local_manager,
                              NonLocalManager &);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   /// Pointer to non-local manager class
   NonLocalManager & non_local_manager;
 
   /// the weights associated to the pairs
   std::array<std::unique_ptr<Array<Real>>, 2> pair_weight;
 
   /// weight function
   std::unique_ptr<WeightFunction> weight_function;
 };
 
 } // namespace akantu
 
 /* -------------------------------------------------------------------------- */
 /* Implementation of template functions                                       */
 /* -------------------------------------------------------------------------- */
 #include "non_local_neighborhood_tmpl.hh"
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 #include "non_local_neighborhood_inline_impl.cc"
 
 #endif /* __AKANTU_NON_LOCAL_NEIGHBORHOOD_HH__ */
diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh b/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh
index 85cd6725b..7c02c8483 100644
--- a/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh
+++ b/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh
@@ -1,122 +1,125 @@
 /**
  * @file   non_local_neighborhood_base.hh
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Sat Sep 26 2015
  * @date last modification: Wed Nov 25 2015
  *
  * @brief  Non-local neighborhood base class
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "neighborhood_base.hh"
 #include "parsable.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH__
 #define __AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH__
 
 namespace akantu {
 class Model;
 }
 /* -------------------------------------------------------------------------- */
 namespace akantu {
 
 class NonLocalNeighborhoodBase : public NeighborhoodBase, public Parsable {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   NonLocalNeighborhoodBase(Model & model,
                            const ElementTypeMapReal & quad_coordinates,
                            const ID & id = "non_local_neighborhood",
                            const MemoryID & memory_id = 0);
   virtual ~NonLocalNeighborhoodBase();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// create grid synchronizer and exchange ghost cells
   void createGridSynchronizer() override;
 
   /// compute weights, for instance needed for non-local damage computation
   virtual void computeWeights(){};
 
   // compute the non-local counter part for a given element type map
   virtual void
   weightedAverageOnNeighbours(const ElementTypeMapReal & to_accumulate,
                               ElementTypeMapReal & accumulated,
                               UInt nb_degree_of_freedom,
                               const GhostType & ghost_type2) const = 0;
 
   /// update the weights for the non-local averaging
   virtual void updateWeights() = 0;
 
+  /// update the weights for the non-local averaging
+  virtual void saveWeights(const std::string & ) const { AKANTU_DEBUG_TO_IMPLEMENT(); }
+
   /// register a new non-local variable in the neighborhood
   virtual void registerNonLocalVariable(const ID & id);
 
   /// clean up the unneccessary ghosts
   void cleanupExtraGhostElements(std::set<Element> & relevant_ghost_elements);
 
 protected:
   /// create the grid
   void createGrid();
 
   /* --------------------------------------------------------------------------
    */
   /* DataAccessor inherited members */
   /* --------------------------------------------------------------------------
    */
 public:
   inline UInt getNbData(const Array<Element> &,
                         const SynchronizationTag &) const override {
     return 0;
   }
 
   inline void packData(CommunicationBuffer &, const Array<Element> &,
                        const SynchronizationTag &) const override {}
 
   inline void unpackData(CommunicationBuffer &, const Array<Element> &,
                          const SynchronizationTag &) override {}
 
   /* --------------------------------------------------------------------------
    */
   /* Accessors */
   /* --------------------------------------------------------------------------
    */
 public:
   AKANTU_GET_MACRO(NonLocalVariables, non_local_variables,
                    const std::set<ID> &);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// list of non-local variables associated to the neighborhood
   std::set<ID> non_local_variables;
 };
 
 } // namespace akantu
 
 #endif /* __AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH__ */
diff --git a/src/model/solid_mechanics/material.hh b/src/model/solid_mechanics/material.hh
index 84b66a2ef..0969d76de 100644
--- a/src/model/solid_mechanics/material.hh
+++ b/src/model/solid_mechanics/material.hh
@@ -1,653 +1,680 @@
 
 /**
  * @file   material.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 Nov 25 2015
  *
  * @brief  Mother class for all materials
  *
  * @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_factory.hh"
 #include "aka_voigthelper.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;
 } // namespace akantu
 
 namespace akantu {
 
 /**
  * Interface of all materials
  * Prerequisites for a new material
  * - inherit from this class
  * - implement the following methods:
  * \code
  *  virtual Real getStableTimeStep(Real h, const Element & element =
  * ElementNull);
  *
  *  virtual void computeStress(ElementType el_type,
  *                             GhostType ghost_type = _not_ghost);
  *
  *  virtual void computeTangentStiffness(const ElementType & el_type,
  *                                       Array<Real> & tangent_matrix,
  *                                       GhostType ghost_type = _not_ghost);
  * \endcode
  *
  */
 
 class Material : public Memory,
                  public DataAccessor<Element>,
                  public Parsable,
                  public MeshEventHandler,
                  protected SolidMechanicsModelEventHandler {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 #if __cplusplus > 199711L
   Material(const Material & mat) = delete;
   Material & operator=(const Material & mat) = delete;
 #endif
 
   /// 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
   virtual ~Material();
 
 protected:
   void initialize();
 
   /* ------------------------------------------------------------------------ */
   /* Function that materials can/should reimplement                           */
   /* ------------------------------------------------------------------------ */
 protected:
   /// constitutive law
   virtual void computeStress(__attribute__((unused)) ElementType el_type,
                              __attribute__((unused))
                              GhostType ghost_type = _not_ghost) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /// compute the tangent stiffness matrix
   virtual void computeTangentModuli(__attribute__((unused))
                                     const ElementType & el_type,
                                     __attribute__((unused))
                                     Array<Real> & tangent_matrix,
                                     __attribute__((unused))
                                     GhostType ghost_type = _not_ghost) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /// compute the potential energy
   virtual void computePotentialEnergy(ElementType el_type,
                                       GhostType ghost_type = _not_ghost);
 
   /// compute the potential energy for an element
   virtual void
   computePotentialEnergyByElement(__attribute__((unused)) ElementType type,
                                   __attribute__((unused)) UInt index,
                                   __attribute__((unused))
                                   Vector<Real> & epot_on_quad_points) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   virtual void updateEnergies(__attribute__((unused)) ElementType el_type,
                               __attribute__((unused))
                               GhostType ghost_type = _not_ghost) {}
 
   virtual void updateEnergiesAfterDamage(__attribute__((unused))
                                          ElementType el_type,
                                          __attribute__((unused))
                                          GhostType ghost_type = _not_ghost) {}
 
   /// set the material to steady state (to be implemented for materials that
   /// need it)
   virtual void setToSteadyState(__attribute__((unused)) ElementType el_type,
                                 __attribute__((unused))
                                 GhostType ghost_type = _not_ghost) {}
 
   /// 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(__attribute__((unused))
                                 const Element & element) const {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /// compute the s-wave speed in the material
   virtual Real getShearWaveSpeed(__attribute__((unused))
                                  const Element & element) const {
     AKANTU_DEBUG_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:
   template <typename T>
   void registerInternal(__attribute__((unused)) InternalField<T> & vect) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   template <typename T>
   void unregisterInternal(__attribute__((unused)) InternalField<T> & vect) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /// 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);
 
   /// save the stress in the previous_stress if needed
   virtual void savePreviousState();
 
   /// 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);
 
   /// add an element to the local mesh filter
   inline UInt addElement(const ElementType & type, UInt element,
                          const GhostType & ghost_type);
 
   /// 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
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /**
    * interpolate stress on given positions for each element by means
    * of a geometrical interpolation on quadrature points
    */
   void interpolateStress(ElementTypeMapArray<Real> & result,
                          const 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,
                                  const 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:
   /* ------------------------------------------------------------------------ */
   inline UInt getTangentStiffnessVoigtSize(UInt spatial_dimension) const;
 
   /// compute the potential energy by element
   void computePotentialEnergyByElements();
 
   /// resize the intenals arrays
   virtual void resizeInternals();
 
   /* ------------------------------------------------------------------------ */
   /* 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);
 
   /// 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 computeCauchyStress(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 computeCauchyStressOnQuad(const Matrix<Real> & F,
                                         const Matrix<Real> & S,
                                         Matrix<Real> & cauchy,
                                         const Real & C33 = 1.0) const;
 
   template <UInt dim>
   void computeAllStressesFromTangentModuli(const ElementType & type,
                                            GhostType ghost_type);
 
   template <UInt dim>
   void assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type);
 
   /// assembling in finite deformation
   template <UInt dim>
   void assembleStiffnessMatrixNL(const ElementType & type,
                                  GhostType ghost_type);
 
   template <UInt dim>
   void assembleStiffnessMatrixL2(const ElementType & type,
                                  GhostType ghost_type);
 
   /// Size of the Stress matrix for the case of finite deformation see: Bathe et
   /// al, IJNME, Vol 9, 353-386, 1975
   inline UInt getCauchyStressMatrixSize(UInt spatial_dimension) const;
 
   /// Sets the stress matrix according to Bathe et al, IJNME, Vol 9, 353-386,
   /// 1975
   template <UInt dim>
   inline void setCauchyStressMatrix(const Matrix<Real> & S_t,
                                     Matrix<Real> & sigma);
 
   /// write the stress tensor in the Voigt notation.
   template <UInt dim>
   inline void setCauchyStressArray(const Matrix<Real> & S_t,
                                    Matrix<Real> & sigma_voight);
 
   /* ------------------------------------------------------------------------ */
   /* Conversion functions                                                     */
   /* ------------------------------------------------------------------------ */
 public:
   template <UInt dim>
   static inline void gradUToF(const Matrix<Real> & grad_u, Matrix<Real> & F);
   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 void gradUToGreenStrain(const Matrix<Real> & grad_u,
                                         Matrix<Real> & epsilon);
 
   static inline Real stressToVonMises(const Matrix<Real> & stress);
 
 protected:
   /// 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;
 
   /// converts global quadrature point to local quadrature point
   inline IntegrationPoint
   convertToLocalPoint(const IntegrationPoint & global_point) const;
   /// converts local quadrature point to global quadrature point
   inline IntegrationPoint
   convertToGlobalPoint(const IntegrationPoint & local_point) const;
 
   /* ------------------------------------------------------------------------ */
   /* DataAccessor inherited members                                           */
   /* ------------------------------------------------------------------------ */
 public:
   virtual inline UInt getNbData(const Array<Element> & elements,
                                 const SynchronizationTag & tag) const;
 
   virtual inline void packData(CommunicationBuffer & buffer,
                                const Array<Element> & elements,
                                const SynchronizationTag & tag) const;
 
   virtual inline void unpackData(CommunicationBuffer & buffer,
                                  const Array<Element> & elements,
                                  const SynchronizationTag & tag);
 
   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> &, const NewNodesEvent &){};
   virtual void onNodesRemoved(const Array<UInt> &, const Array<UInt> &,
                               const RemovedNodesEvent &){};
 
   virtual void onElementsAdded(const Array<Element> & element_list,
                                const NewElementsEvent & event);
 
   virtual void
   onElementsRemoved(const Array<Element> & element_list,
                     const ElementTypeMapArray<UInt> & new_numbering,
                     const RemovedElementsEvent & event);
 
   virtual void onElementsChanged(const Array<Element> &, const Array<Element> &,
                                  const ElementTypeMapArray<UInt> &,
                                  const ChangedElementsEvent &){};
 
   /* ------------------------------------------------------------------------ */
   /* SolidMechanicsModelEventHandler inherited members                        */
   /* ------------------------------------------------------------------------ */
 public:
   virtual void onBeginningSolveStep(const AnalysisMethod & method);
   virtual void onEndSolveStep(const AnalysisMethod & method);
   virtual void onDamageIteration();
   virtual void onDamageUpdate();
   virtual void onDump();
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   AKANTU_GET_MACRO(Name, name, const std::string &);
 
   AKANTU_GET_MACRO(Model, model, const SolidMechanicsModel &)
 
   AKANTU_GET_MACRO(ID, Memory::getID(), const ID &);
   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(std::string energy_id);
   /// return the energy (identified by id) for the provided element
   virtual Real getEnergy(std::string energy_id, ElementType type, UInt index);
 
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt);
   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; }
 
   template <typename T>
   const Array<T> & getArray(const ID & id, const ElementType & type,
                             const GhostType & ghost_type = _not_ghost) const;
   template <typename T>
   Array<T> & getArray(const ID & id, const ElementType & type,
                       const GhostType & ghost_type = _not_ghost);
 
   template <typename T>
   const InternalField<T> & getInternal(const ID & id) const;
   template <typename T> InternalField<T> & getInternal(const ID & id);
 
   template <typename T>
   inline bool isInternal(const ID & id, const ElementKind & element_kind) const;
 
   template <typename T>
   ElementTypeMap<UInt>
   getInternalDataPerElem(const ID & id, const ElementKind & element_kind) const;
 
   bool isFiniteDeformation() const { return finite_deformation; }
   bool isInelasticDeformation() const { return inelastic_deformation; }
 
   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;
 
   /// apply a constant eigengrad_u everywhere in the material
   virtual void applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u,
                                const GhostType = _not_ghost);
 
   /// specify if the matrix need to be recomputed for this material
   virtual bool hasStiffnessMatrixChanged() { return true; }
 
 protected:
   bool isInit() const { return is_init; }
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// boolean to know if the material has been initialized
   bool is_init;
 
   std::map<ID, InternalField<Real> *> internal_vectors_real;
   std::map<ID, InternalField<UInt> *> internal_vectors_uint;
   std::map<ID, InternalField<bool> *> internal_vectors_bool;
 
 protected:
   /// Link to the fem object in the model
   FEEngine & fem;
 
   /// Finite deformation
   bool finite_deformation;
 
   /// Finite deformation
   bool inelastic_deformation;
 
   /// material name
   std::string name;
 
   /// The model to witch the material belong
   SolidMechanicsModel & model;
 
   /// density : rho
   Real rho;
 
   /// spatial dimension
   UInt spatial_dimension;
 
   /// list of element handled by the material
   ElementTypeMapArray<UInt> element_filter;
 
   /// 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;
 
   /// tell if the material need the previous stress state
   bool use_previous_stress;
 
   /// tell if the material need the previous strain state
   bool use_previous_gradu;
 
   /// elemental field interpolation coordinates
   InternalField<Real> interpolation_inverse_coordinates;
 
   /// elemental field interpolation points
   InternalField<Real> interpolation_points_matrices;
 
   /// vector that contains the names of all the internals that need to
   /// be transferred when material interfaces move
   std::vector<ID> internals_to_transfer;
 };
 
 /// 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.cc"
 
 #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)       \
   Array<Real>::matrix_iterator gradu_it =                                      \
       this->gradu(el_type, ghost_type)                                         \
           .begin(this->spatial_dimension, this->spatial_dimension);            \
   Array<Real>::matrix_iterator gradu_end =                                     \
       this->gradu(el_type, ghost_type)                                         \
           .end(this->spatial_dimension, this->spatial_dimension);              \
                                                                                \
   this->stress(el_type, ghost_type)                                            \
       .resize(this->gradu(el_type, ghost_type).getSize());                     \
                                                                                \
   Array<Real>::iterator<Matrix<Real>> stress_it =                              \
       this->stress(el_type, ghost_type)                                        \
           .begin(this->spatial_dimension, this->spatial_dimension);            \
                                                                                \
   if (this->isFiniteDeformation()) {                                           \
     this->piola_kirchhoff_2(el_type, ghost_type)                               \
         .resize(this->gradu(el_type, ghost_type).getSize());                   \
     stress_it = this->piola_kirchhoff_2(el_type, ghost_type)                   \
                     .begin(this->spatial_dimension, this->spatial_dimension);  \
   }                                                                            \
                                                                                \
   for (; gradu_it != gradu_end; ++gradu_it, ++stress_it) {                     \
     Matrix<Real> & __attribute__((unused)) grad_u = *gradu_it;                 \
     Matrix<Real> & __attribute__((unused)) sigma = *stress_it
 
 #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)              \
   Array<Real>::matrix_iterator gradu_it =                                      \
       this->gradu(el_type, ghost_type)                                         \
           .begin(this->spatial_dimension, this->spatial_dimension);            \
   Array<Real>::matrix_iterator gradu_end =                                     \
       this->gradu(el_type, ghost_type)                                         \
           .end(this->spatial_dimension, this->spatial_dimension);              \
   Array<Real>::matrix_iterator sigma_it =                                      \
       this->stress(el_type, ghost_type)                                        \
           .begin(this->spatial_dimension, this->spatial_dimension);            \
                                                                                \
   tangent_mat.resize(this->gradu(el_type, ghost_type).getSize());              \
                                                                                \
   UInt tangent_size =                                                          \
       this->getTangentStiffnessVoigtSize(this->spatial_dimension);             \
   Array<Real>::matrix_iterator tangent_it =                                    \
       tangent_mat.begin(tangent_size, tangent_size);                           \
                                                                                \
   for (; gradu_it != gradu_end; ++gradu_it, ++sigma_it, ++tangent_it) {        \
     Matrix<Real> & __attribute__((unused)) grad_u = *gradu_it;                 \
     Matrix<Real> & __attribute__((unused)) sigma_tensor = *sigma_it;           \
     Matrix<Real> & tangent = *tangent_it
 
 #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END }
 
 /* -------------------------------------------------------------------------- */
-#define INSTANTIATE_MATERIAL(mat_name)                                         \
+namespace akantu {
+using MaterialFactory =
+    Factory<Material, UInt, const ID &, SolidMechanicsModel &, const ID &>;
+} // namespace akantu
+
+#define INSTANTIATE_MATERIAL_ONLY(mat_name)                                    \
   template class mat_name<1>;                                                  \
   template class mat_name<2>;                                                  \
   template class mat_name<3>
 
-#endif /* __AKANTU_MATERIAL_HH__ */
+#define MATERIAL_DEFAULT_PER_DIM_ALLOCATOR(id, mat_name)                       \
+  [](UInt dim, const ID &, SolidMechanicsModel & model,                        \
+     const ID & id) -> std::unique_ptr<Material> {                             \
+    switch (dim) {                                                             \
+    case 1:                                                                    \
+      return std::make_unique<mat_name<1>>(model, id);                         \
+    case 2:                                                                    \
+      return std::make_unique<mat_name<2>>(model, id);                         \
+    case 3:                                                                    \
+      return std::make_unique<mat_name<3>>(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))
 
-//  LocalWords:  ElementNull
+#endif /* __AKANTU_MATERIAL_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc
index 27d48cc8d..8e9c52889 100644
--- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc
+++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc
@@ -1,211 +1,211 @@
 /**
  * @file   material_cohesive_bilinear.cc
  *
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Wed Feb 22 2012
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  Bilinear cohesive constitutive law
  *
  * @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 "material_cohesive_bilinear.hh"
 #include "solid_mechanics_model_cohesive.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 MaterialCohesiveBilinear<spatial_dimension>::MaterialCohesiveBilinear(SolidMechanicsModel & model, const ID & id) :
   MaterialCohesiveLinear<spatial_dimension>(model, id) {
   AKANTU_DEBUG_IN();
 
   this->registerParam("delta_0", delta_0, Real(0.),
 		      _pat_parsable | _pat_readable,
 		      "Elastic limit displacement");
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialCohesiveBilinear<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
   this->sigma_c_eff.setRandomDistribution(this->sigma_c.getRandomParameter());
   MaterialCohesiveLinear<spatial_dimension>::initMaterial();
 
   this->delta_max       .setDefaultValue(delta_0);
   this->insertion_stress.setDefaultValue(0);
 
   this->delta_max       .reset();
   this->insertion_stress.reset();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialCohesiveBilinear<spatial_dimension>::onElementsAdded(const Array<Element> & element_list,
 								  const NewElementsEvent & event) {
   AKANTU_DEBUG_IN();
 
   MaterialCohesiveLinear<spatial_dimension>::onElementsAdded(element_list, event);
 
   bool scale_traction = false;
 
   // don't scale sigma_c if volume_s hasn't been specified by the user
   if (!Math::are_float_equal(this->volume_s, 0.)) scale_traction = true;
 
   Array<Element>::const_scalar_iterator el_it = element_list.begin();
   Array<Element>::const_scalar_iterator el_end = element_list.end();
 
   for (; el_it != el_end; ++el_it) {
     // filter not ghost cohesive elements
     if (el_it->ghost_type != _not_ghost || el_it->kind != _ek_cohesive) continue;
 
     UInt index = el_it->element;
     ElementType type = el_it->type;
     UInt nb_element = this->model->getMesh().getNbElement(type);
     UInt nb_quad_per_element = this->fem_cohesive->getNbIntegrationPoints(type);
 
     Array<Real>::vector_iterator sigma_c_begin
       = this->sigma_c_eff(type).begin_reinterpret(nb_quad_per_element, nb_element);
     Vector<Real> sigma_c_vec = sigma_c_begin[index];
 
     Array<Real>::vector_iterator delta_c_begin
       = this->delta_c_eff(type).begin_reinterpret(nb_quad_per_element, nb_element);
     Vector<Real> delta_c_vec = delta_c_begin[index];
 
     if (scale_traction) scaleTraction(*el_it, sigma_c_vec);
 
     /**
      * Recompute sigma_c as
      * @f$ {\sigma_c}_\textup{new} =
      * \frac{{\sigma_c}_\textup{old} \delta_c} {\delta_c - \delta_0} @f$
      */
 
     for (UInt q = 0; q < nb_quad_per_element; ++q) {
       delta_c_vec(q) = 2 * this->G_c / sigma_c_vec(q);
 
       if (delta_c_vec(q) - delta_0 < Math::getTolerance())
 	AKANTU_DEBUG_ERROR("delta_0 = " << delta_0 <<
 			   " must be lower than delta_c = " << delta_c_vec(q)
 			   << ", modify your material file");
 
       sigma_c_vec(q) *= delta_c_vec(q) / (delta_c_vec(q) - delta_0);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialCohesiveBilinear<spatial_dimension>::scaleTraction(const Element & el,
 								Vector<Real> & sigma_c_vec) {
   AKANTU_DEBUG_IN();
 
   Real base_sigma_c = this->sigma_c_eff;
 
   const Mesh & mesh_facets = this->model->getMeshFacets();
   const FEEngine & fe_engine = this->model->getFEEngine();
 
   Array<Element>::const_vector_iterator coh_element_to_facet_begin
     = mesh_facets.getSubelementToElement(el.type).begin(2);
   const Vector<Element> & coh_element_to_facet
     = coh_element_to_facet_begin[el.element];
 
   // compute bounding volume
   Real volume = 0;
 
   // loop over facets
   for (UInt f = 0; f < 2; ++f) {
     const Element & facet = coh_element_to_facet(f);
 
     const Array< std::vector<Element> > & facet_to_element
       = mesh_facets.getElementToSubelement(facet.type, facet.ghost_type);
 
     const std::vector<Element> & element_list = facet_to_element(facet.element);
 
     std::vector<Element>::const_iterator elem = element_list.begin();
     std::vector<Element>::const_iterator elem_end = element_list.end();
 
     // loop over elements connected to each facet
     for (; elem != elem_end; ++elem) {
       // skip cohesive elements and dummy elements
       if (*elem == ElementNull || elem->kind == _ek_cohesive) continue;
 
       // unit vector for integration in order to obtain the volume
       UInt nb_quadrature_points = fe_engine.getNbIntegrationPoints(elem->type);
       Vector<Real> unit_vector(nb_quadrature_points, 1);
 
       volume += fe_engine.integrate(unit_vector, elem->type,
 				    elem->element, elem->ghost_type);
     }
   }
 
   // scale sigma_c
   sigma_c_vec -= base_sigma_c;
   sigma_c_vec *= std::pow(this->volume_s / volume, 1. / this->m_s);
   sigma_c_vec += base_sigma_c;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialCohesiveBilinear<spatial_dimension>::computeTraction(const Array<Real> & normal,
 								  ElementType el_type,
 								  GhostType ghost_type) {
   AKANTU_DEBUG_IN();
   MaterialCohesiveLinear<spatial_dimension>::computeTraction(normal,
 							     el_type,
 							     ghost_type);
 
   // adjust damage
   Array<Real>::scalar_iterator delta_c_it
     = this->delta_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator delta_max_it
     = this->delta_max(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator damage_it
     = this->damage(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator damage_end
    = this->damage(el_type, ghost_type).end();
 
   for (; damage_it != damage_end; ++damage_it, ++delta_max_it, ++delta_c_it) {
     *damage_it = std::max((*delta_max_it - delta_0) / (*delta_c_it - delta_0), Real(0.));
     *damage_it = std::min(*damage_it, Real(1.));
   }
 }
 
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialCohesiveBilinear);
+INSTANTIATE_MATERIAL(cohesive_bilinear, MaterialCohesiveBilinear);
 
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc
index 7e9b2b4ea..ff2e48708 100644
--- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc
+++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc
@@ -1,358 +1,358 @@
 /**
  * @file   material_cohesive_exponential.cc
  *
  * @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Mon Jul 09 2012
  * @date last modification: Tue Aug 04 2015
  *
  * @brief  Exponential irreversible cohesive law of mixed mode loading
  *
  * @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 "material_cohesive_exponential.hh"
 #include "dof_synchronizer.hh"
 #include "solid_mechanics_model.hh"
 #include "sparse_matrix.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialCohesiveExponential<spatial_dimension>::MaterialCohesiveExponential(
     SolidMechanicsModel & model, const ID & id)
     : MaterialCohesive(model, id) {
   AKANTU_DEBUG_IN();
 
   this->registerParam("beta", beta, Real(0.), _pat_parsable, "Beta parameter");
 
   this->registerParam("exponential_penalty", exp_penalty, true, _pat_parsable,
                       "Is contact penalty following the exponential law?");
 
   this->registerParam(
       "contact_tangent", contact_tangent, Real(1.0), _pat_parsable,
       "Ratio of contact tangent over the initial exponential tangent");
 
   // this->initInternalArray(delta_max, 1, _ek_cohesive);
 
   use_previous_delta_max = true;
 
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveExponential<spatial_dimension>::initMaterial() {
 
   AKANTU_DEBUG_IN();
   MaterialCohesive::initMaterial();
 
   if ((exp_penalty) && (contact_tangent != 1)) {
 
     contact_tangent = 1;
     AKANTU_DEBUG_WARNING("The parsed paramter <contact_tangent> is forced to "
                          "1.0 when the contact penalty follows the exponential "
                          "law");
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveExponential<spatial_dimension>::computeTraction(
     const Array<Real> & normal, ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /// define iterators
   Array<Real>::vector_iterator traction_it =
       tractions(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator opening_it =
       opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::const_vector_iterator normal_it =
       normal.begin(spatial_dimension);
 
   Array<Real>::vector_iterator traction_end =
       tractions(el_type, ghost_type).end(spatial_dimension);
 
   Array<Real>::iterator<Real> delta_max_it =
       delta_max(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real> delta_max_prev_it =
       delta_max.previous(el_type, ghost_type).begin();
 
   /// compute scalars
   Real beta2 = beta * beta;
 
   /// loop on each quadrature point
   for (; traction_it != traction_end; ++traction_it, ++opening_it, ++normal_it,
                                       ++delta_max_it, ++delta_max_prev_it) {
 
     /// compute normal and tangential opening vectors
     Real normal_opening_norm = opening_it->dot(*normal_it);
     Vector<Real> normal_opening(spatial_dimension);
     normal_opening = (*normal_it);
     normal_opening *= normal_opening_norm;
 
     Vector<Real> tangential_opening(spatial_dimension);
     tangential_opening = *opening_it;
     tangential_opening -= normal_opening;
 
     Real tangential_opening_norm = tangential_opening.norm();
 
     /**
      * compute effective opening displacement
      * @f$ \delta = \sqrt{
      * \beta^2 \Delta_t^2 + \Delta_n^2 } @f$
      */
     Real delta = tangential_opening_norm;
     delta *= delta * beta2;
     delta += normal_opening_norm * normal_opening_norm;
 
     delta = sqrt(delta);
 
     if ((normal_opening_norm < 0) &&
         (std::abs(normal_opening_norm) > Math::getTolerance())) {
 
       Vector<Real> op_n(*normal_it);
       op_n *= normal_opening_norm;
       Vector<Real> delta_s(*opening_it);
       delta_s -= op_n;
       delta = tangential_opening_norm * beta;
 
       computeCoupledTraction(*traction_it, *normal_it, delta, delta_s,
                              *delta_max_it, *delta_max_prev_it);
 
       computeCompressiveTraction(*traction_it, *normal_it, normal_opening_norm,
                                  *opening_it);
 
     } else
       computeCoupledTraction(*traction_it, *normal_it, delta, *opening_it,
                              *delta_max_it, *delta_max_prev_it);
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveExponential<spatial_dimension>::computeCoupledTraction(
     Vector<Real> & tract, const Vector<Real> & normal, Real delta,
     const Vector<Real> & opening, Real & delta_max_new, Real delta_max) {
   AKANTU_DEBUG_IN();
 
   /// full damage case
   if (std::abs(delta) < Math::getTolerance()) {
     /// set traction to zero
     tract.clear();
   } else { /// element not fully damaged
     /**
      * Compute traction loading @f$ \mathbf{T} =
      * e \sigma_c \frac{\delta}{\delta_c} e^{-\delta/ \delta_c}@f$
      */
     /**
      * Compute traction unloading @f$ \mathbf{T} =
      *  \frac{t_{max}}{\delta_{max}} \delta @f$
      */
     Real beta2 = beta * beta;
     Real normal_open_norm = opening.dot(normal);
     Vector<Real> op_n_n(spatial_dimension);
     op_n_n = normal;
     op_n_n *= (1 - beta2);
     op_n_n *= normal_open_norm;
     tract = beta2 * opening;
     tract += op_n_n;
 
     delta_max_new = std::max(delta_max, delta);
     tract *= exp(1) * sigma_c * exp(-delta_max_new / delta_c) / delta_c;
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveExponential<spatial_dimension>::computeCompressiveTraction(
     Vector<Real> & tract, const Vector<Real> & normal, Real delta_n,
     __attribute__((unused)) const Vector<Real> & opening) {
   Vector<Real> temp_tract(normal);
 
   if (exp_penalty) {
     temp_tract *=
         delta_n * exp(1) * sigma_c * exp(-delta_n / delta_c) / delta_c;
   } else {
     Real initial_tg = contact_tangent * exp(1) * sigma_c * delta_n / delta_c;
     temp_tract *= initial_tg;
   }
 
   tract += temp_tract;
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveExponential<spatial_dimension>::computeTangentTraction(
     const ElementType & el_type, Array<Real> & tangent_matrix,
     const Array<Real> & normal, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Array<Real>::matrix_iterator tangent_it =
       tangent_matrix.begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::matrix_iterator tangent_end =
       tangent_matrix.end(spatial_dimension, spatial_dimension);
 
   Array<Real>::const_vector_iterator normal_it =
       normal.begin(spatial_dimension);
 
   Array<Real>::vector_iterator opening_it =
       opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::iterator<Real> delta_max_it =
       delta_max.previous(el_type, ghost_type).begin();
 
   Real beta2 = beta * beta;
 
   /**
    * compute tangent matrix  @f$ \frac{\partial \mathbf{t}}
    * {\partial \delta} = \hat{\mathbf{t}} \otimes
    * \frac{\partial (t/\delta)}{\partial \delta}
    * \frac{\hat{\mathbf{t}}}{\delta}+ \frac{t}{\delta}  [ \beta^2 \mathbf{I} +
    * (1-\beta^2) (\mathbf{n} \otimes \mathbf{n})] @f$
    **/
 
   /**
    * In which @f$
    *  \frac{\partial(t/ \delta)}{\partial \delta} =
    * \left\{\begin{array} {l l}
    *  -e  \frac{\sigma_c}{\delta_c^2  }e^{-\delta  /  \delta_c} &  \quad  if
    *  \delta \geq \delta_{max} \\
    *  0 & \quad if \delta < \delta_{max}, \delta_n > 0
    *  \end{array}\right. @f$
    **/
 
   for (; tangent_it != tangent_end;
        ++tangent_it, ++normal_it, ++opening_it, ++delta_max_it) {
 
     Real normal_opening_norm = opening_it->dot(*normal_it);
     Vector<Real> normal_opening(spatial_dimension);
     normal_opening = (*normal_it);
     normal_opening *= normal_opening_norm;
 
     Vector<Real> tangential_opening(spatial_dimension);
     tangential_opening = *opening_it;
     tangential_opening -= normal_opening;
 
     Real tangential_opening_norm = tangential_opening.norm();
 
     Real delta = tangential_opening_norm;
     delta *= delta * beta2;
     delta += normal_opening_norm * normal_opening_norm;
     delta = sqrt(delta);
 
     if ((normal_opening_norm < 0) &&
         (std::abs(normal_opening_norm) > Math::getTolerance())) {
 
       Vector<Real> op_n(*normal_it);
       op_n *= normal_opening_norm;
       Vector<Real> delta_s(*opening_it);
       delta_s -= op_n;
       delta = tangential_opening_norm * beta;
 
       computeCoupledTangent(*tangent_it, *normal_it, delta, delta_s,
                             *delta_max_it);
 
       computeCompressivePenalty(*tangent_it, *normal_it, normal_opening_norm);
 
     } else
       computeCoupledTangent(*tangent_it, *normal_it, delta, *opening_it,
                             *delta_max_it);
   }
 
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveExponential<spatial_dimension>::computeCoupledTangent(
     Matrix<Real> & tangent, const Vector<Real> & normal, Real delta,
     const Vector<Real> & opening, Real) {
   AKANTU_DEBUG_IN();
 
   Real beta2 = beta * beta;
   Matrix<Real> J(spatial_dimension, spatial_dimension);
   J.eye(beta2);
 
   if (std::abs(delta) < Math::getTolerance()) {
     delta = Math::getTolerance();
   }
 
   Real opening_normal;
   opening_normal = opening.dot(normal);
 
   Vector<Real> delta_e(normal);
   delta_e *= opening_normal;
   delta_e *= (1 - beta2);
   delta_e += (beta2 * opening);
 
   Real exponent = exp(1 - delta / delta_c) * sigma_c / delta_c;
 
   Matrix<Real> first_term(spatial_dimension, spatial_dimension);
   first_term.outerProduct(normal, normal);
   first_term *= (1 - beta2);
   first_term += J;
 
   Matrix<Real> second_term(spatial_dimension, spatial_dimension);
   second_term.outerProduct(delta_e, delta_e);
   second_term /= delta;
   second_term /= delta_c;
 
   Matrix<Real> diff(first_term);
   diff -= second_term;
 
   tangent = diff;
   tangent *= exponent;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveExponential<spatial_dimension>::computeCompressivePenalty(
     Matrix<Real> & tangent, const Vector<Real> & normal, Real delta_n) {
 
   if (!exp_penalty)
     delta_n = 0;
 
   Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
   n_outer_n.outerProduct(normal, normal);
 
   Real normal_tg = contact_tangent * exp(1) * sigma_c *
                    exp(-delta_n / delta_c) * (1 - delta_n / delta_c) / delta_c;
 
   n_outer_n *= normal_tg;
 
   tangent += n_outer_n;
 }
 
-INSTANTIATE_MATERIAL(MaterialCohesiveExponential);
+INSTANTIATE_MATERIAL(cohesive_exponential, MaterialCohesiveExponential);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc
index 669d3e684..9277b1bb1 100644
--- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc
+++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc
@@ -1,700 +1,700 @@
 /**
  * @file   material_cohesive_linear.cc
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Wed Feb 22 2012
  * @date last modification: Thu Jan 14 2016
  *
  * @brief  Linear irreversible cohesive law of mixed mode loading with
  * random stress definition for extrinsic type
  *
  * @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 <algorithm>
 #include <numeric>
 
 /* -------------------------------------------------------------------------- */
 #include "dof_synchronizer.hh"
 #include "material_cohesive_linear.hh"
 #include "solid_mechanics_model_cohesive.hh"
 #include "sparse_matrix.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialCohesiveLinear<spatial_dimension>::MaterialCohesiveLinear(
     SolidMechanicsModel & model, const ID & id)
     : MaterialCohesive(model, id), sigma_c_eff("sigma_c_eff", *this),
       delta_c_eff("delta_c_eff", *this),
       insertion_stress("insertion_stress", *this),
       opening_prec("opening_prec", *this),
       reduction_penalty("reduction_penalty", *this) {
   AKANTU_DEBUG_IN();
 
   this->registerParam("beta", beta, Real(0.), _pat_parsable | _pat_readable,
                       "Beta parameter");
 
   this->registerParam("G_c", G_c, Real(0.), _pat_parsable | _pat_readable,
                       "Mode I fracture energy");
 
   this->registerParam("penalty", penalty, Real(0.),
                       _pat_parsable | _pat_readable, "Penalty coefficient");
 
   this->registerParam("volume_s", volume_s, Real(0.),
                       _pat_parsable | _pat_readable,
                       "Reference volume for sigma_c scaling");
 
   this->registerParam("m_s", m_s, Real(1.), _pat_parsable | _pat_readable,
                       "Weibull exponent for sigma_c scaling");
 
   this->registerParam("kappa", kappa, Real(1.), _pat_parsable | _pat_readable,
                       "Kappa parameter");
 
   this->registerParam(
       "contact_after_breaking", contact_after_breaking, false,
       _pat_parsable | _pat_readable,
       "Activation of contact when the elements are fully damaged");
 
   this->registerParam("max_quad_stress_insertion", max_quad_stress_insertion,
                       false, _pat_parsable | _pat_readable,
                       "Insertion of cohesive element when stress is high "
                       "enough just on one quadrature point");
 
   this->registerParam("recompute", recompute, false,
                       _pat_parsable | _pat_modifiable, "recompute solution");
 
   this->use_previous_delta_max = true;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
   MaterialCohesive::initMaterial();
 
   /// compute scalars
   beta2_kappa2 = beta * beta / kappa / kappa;
   beta2_kappa = beta * beta / kappa;
 
   if (Math::are_float_equal(beta, 0))
     beta2_inv = 0;
   else
     beta2_inv = 1. / beta / beta;
 
   sigma_c_eff.initialize(1);
   delta_c_eff.initialize(1);
   insertion_stress.initialize(spatial_dimension);
   opening_prec.initialize(spatial_dimension);
   reduction_penalty.initialize(1);
 
   if (!Math::are_float_equal(delta_c, 0.))
     delta_c_eff.setDefaultValue(delta_c);
   else
     delta_c_eff.setDefaultValue(2 * G_c / sigma_c);
 
   if (model->getIsExtrinsic())
     scaleInsertionTraction();
   opening_prec.initializeHistory();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::scaleInsertionTraction() {
   AKANTU_DEBUG_IN();
 
   // do nothing if volume_s hasn't been specified by the user
   if (Math::are_float_equal(volume_s, 0.))
     return;
 
   const Mesh & mesh_facets = model->getMeshFacets();
   const FEEngine & fe_engine = model->getFEEngine();
   const FEEngine & fe_engine_facet = model->getFEEngine("FacetsFEEngine");
 
   // loop over facet type
   Mesh::type_iterator first = mesh_facets.firstType(spatial_dimension - 1);
   Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1);
 
   Real base_sigma_c = sigma_c;
 
   for (; first != last; ++first) {
     ElementType type_facet = *first;
 
     const Array<std::vector<Element> > & facet_to_element =
         mesh_facets.getElementToSubelement(type_facet);
 
     UInt nb_facet = facet_to_element.getSize();
     UInt nb_quad_per_facet = fe_engine_facet.getNbIntegrationPoints(type_facet);
 
     // iterator to modify sigma_c for all the quadrature points of a facet
     Array<Real>::vector_iterator sigma_c_iterator =
         sigma_c(type_facet).begin_reinterpret(nb_quad_per_facet, nb_facet);
 
     for (UInt f = 0; f < nb_facet; ++f, ++sigma_c_iterator) {
 
       const std::vector<Element> & element_list = facet_to_element(f);
 
       // compute bounding volume
       Real volume = 0;
 
       std::vector<Element>::const_iterator elem = element_list.begin();
       std::vector<Element>::const_iterator elem_end = element_list.end();
 
       for (; elem != elem_end; ++elem) {
         if (*elem == ElementNull)
           continue;
 
         // unit vector for integration in order to obtain the volume
         UInt nb_quadrature_points =
             fe_engine.getNbIntegrationPoints(elem->type);
         Vector<Real> unit_vector(nb_quadrature_points, 1);
 
         volume += fe_engine.integrate(unit_vector, elem->type, elem->element,
                                       elem->ghost_type);
       }
 
       // scale sigma_c
       *sigma_c_iterator -= base_sigma_c;
       *sigma_c_iterator *= std::pow(volume_s / volume, 1. / m_s);
       *sigma_c_iterator += base_sigma_c;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::checkInsertion(
     bool check_only) {
   AKANTU_DEBUG_IN();
 
   const Mesh & mesh_facets = model->getMeshFacets();
   CohesiveElementInserter & inserter = model->getElementInserter();
 
   Real tolerance = Math::getTolerance();
 
   Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1);
   Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1);
 
   for (; it != last; ++it) {
     ElementType type_facet = *it;
     ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
     const Array<bool> & facets_check = inserter.getCheckFacets(type_facet);
     Array<bool> & f_insertion = inserter.getInsertionFacets(type_facet);
     Array<UInt> & f_filter = facet_filter(type_facet);
     Array<Real> & sig_c_eff = sigma_c_eff(type_cohesive);
     Array<Real> & del_c = delta_c_eff(type_cohesive);
     Array<Real> & ins_stress = insertion_stress(type_cohesive);
     Array<Real> & trac_old = tractions_old(type_cohesive);
     Array<Real> & open_prec = opening_prec(type_cohesive);
     Array<bool> & red_penalty = reduction_penalty(type_cohesive);
     const Array<Real> & f_stress = model->getStressOnFacets(type_facet);
     const Array<Real> & sigma_lim = sigma_c(type_facet);
     Real max_ratio = 0.;
     UInt index_f = 0;
     UInt index_filter = 0;
     UInt nn = 0;
 
     UInt nb_quad_facet =
         model->getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet);
     UInt nb_quad_cohesive = model->getFEEngine("CohesiveFEEngine")
                                 .getNbIntegrationPoints(type_cohesive);
 
     AKANTU_DEBUG_ASSERT(nb_quad_cohesive == nb_quad_facet,
                         "The cohesive element and the corresponding facet do "
                         "not have the same numbers of integration points");
 
     UInt nb_facet = f_filter.getSize();
     //  if (nb_facet == 0) continue;
 
     Array<Real>::const_iterator<Real> sigma_lim_it = sigma_lim.begin();
 
     Matrix<Real> stress_tmp(spatial_dimension, spatial_dimension);
     Matrix<Real> normal_traction(spatial_dimension, nb_quad_facet);
     Vector<Real> stress_check(nb_quad_facet);
     UInt sp2 = spatial_dimension * spatial_dimension;
 
     const Array<Real> & tangents = model->getTangents(type_facet);
     const Array<Real> & normals =
         model->getFEEngine("FacetsFEEngine")
             .getNormalsOnIntegrationPoints(type_facet);
     Array<Real>::const_vector_iterator normal_begin =
         normals.begin(spatial_dimension);
     Array<Real>::const_vector_iterator tangent_begin =
         tangents.begin(tangents.getNbComponent());
     Array<Real>::const_matrix_iterator facet_stress_begin =
         f_stress.begin(spatial_dimension, spatial_dimension * 2);
 
     std::vector<Real> new_sigmas;
     std::vector<Vector<Real> > new_normal_traction;
     std::vector<Real> new_delta_c;
 
     // loop over each facet belonging to this material
     for (UInt f = 0; f < nb_facet; ++f, ++sigma_lim_it) {
       UInt facet = f_filter(f);
       // skip facets where check shouldn't be realized
       if (!facets_check(facet))
         continue;
 
       // compute the effective norm on each quadrature point of the facet
       for (UInt q = 0; q < nb_quad_facet; ++q) {
         UInt current_quad = facet * nb_quad_facet + q;
         const Vector<Real> & normal = normal_begin[current_quad];
         const Vector<Real> & tangent = tangent_begin[current_quad];
         const Matrix<Real> & facet_stress_it = facet_stress_begin[current_quad];
 
         // compute average stress on the current quadrature point
         Matrix<Real> stress_1(facet_stress_it.storage(), spatial_dimension,
                               spatial_dimension);
 
         Matrix<Real> stress_2(facet_stress_it.storage() + sp2,
                               spatial_dimension, spatial_dimension);
 
         stress_tmp.copy(stress_1);
         stress_tmp += stress_2;
         stress_tmp /= 2.;
 
         Vector<Real> normal_traction_vec(normal_traction(q));
 
         // compute normal and effective stress
         stress_check(q) = computeEffectiveNorm(stress_tmp, normal, tangent,
                                                normal_traction_vec);
       }
 
       // verify if the effective stress overcomes the threshold
       Real final_stress = stress_check.mean();
       if (max_quad_stress_insertion)
         final_stress = *std::max_element(
             stress_check.storage(), stress_check.storage() + nb_quad_facet);
 
       if (final_stress > (*sigma_lim_it - tolerance)) {
         if (model->isDefaultSolverExplicit()) {
           f_insertion(facet) = true;
 
           if (!check_only) {
             // store the new cohesive material parameters for each quadrature
             // point
             for (UInt q = 0; q < nb_quad_facet; ++q) {
               Real new_sigma = stress_check(q);
               Vector<Real> normal_traction_vec(normal_traction(q));
 
               if (spatial_dimension != 3)
                 normal_traction_vec *= -1.;
 
               new_sigmas.push_back(new_sigma);
               new_normal_traction.push_back(normal_traction_vec);
 
               Real new_delta;
 
               // set delta_c in function of G_c or a given delta_c value
               if (Math::are_float_equal(delta_c, 0.))
                 new_delta = 2 * G_c / new_sigma;
               else
                 new_delta = (*sigma_lim_it) / new_sigma * delta_c;
 
               new_delta_c.push_back(new_delta);
             }
           }
 
         } else {
           Real ratio = final_stress / (*sigma_lim_it);
           if (ratio > max_ratio) {
             ++nn;
             max_ratio = ratio;
             index_f = f;
             index_filter = f_filter(f);
           }
         }
       }
     }
 
     /// Insertion of only 1 cohesive element in case of implicit approach. The
     /// one subjected to the highest stress.
     if (!model->isDefaultSolverExplicit()) {
       StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
       Array<Real> abs_max(comm.getNbProc());
       abs_max(comm.whoAmI()) = max_ratio;
       comm.allGather(abs_max);
 
       Array<Real>::scalar_iterator it =
           std::max_element(abs_max.begin(), abs_max.end());
       Int pos = it - abs_max.begin();
 
       if (pos != comm.whoAmI()) {
         AKANTU_DEBUG_OUT();
         return;
       }
 
       if (nn) {
         f_insertion(index_filter) = true;
 
         if (!check_only) {
           //  Array<Real>::iterator<Matrix<Real> > normal_traction_it =
           //  normal_traction.begin_reinterpret(nb_quad_facet,
           //  spatial_dimension, nb_facet);
           Array<Real>::const_iterator<Real> sigma_lim_it = sigma_lim.begin();
 
           for (UInt q = 0; q < nb_quad_cohesive; ++q) {
 
             Real new_sigma = (sigma_lim_it[index_f]);
             Vector<Real> normal_traction_vec(spatial_dimension, 0.0);
 
             new_sigmas.push_back(new_sigma);
             new_normal_traction.push_back(normal_traction_vec);
 
             Real new_delta;
 
             // set delta_c in function of G_c or a given delta_c value
             if (!Math::are_float_equal(delta_c, 0.))
               new_delta = delta_c;
             else
               new_delta = 2 * G_c / (new_sigma);
 
             new_delta_c.push_back(new_delta);
           }
         }
       }
     }
 
     // update material data for the new elements
     UInt old_nb_quad_points = sig_c_eff.getSize();
     UInt new_nb_quad_points = new_sigmas.size();
     sig_c_eff.resize(old_nb_quad_points + new_nb_quad_points);
     ins_stress.resize(old_nb_quad_points + new_nb_quad_points);
     trac_old.resize(old_nb_quad_points + new_nb_quad_points);
     del_c.resize(old_nb_quad_points + new_nb_quad_points);
     open_prec.resize(old_nb_quad_points + new_nb_quad_points);
     red_penalty.resize(old_nb_quad_points + new_nb_quad_points);
 
     for (UInt q = 0; q < new_nb_quad_points; ++q) {
       sig_c_eff(old_nb_quad_points + q) = new_sigmas[q];
       del_c(old_nb_quad_points + q) = new_delta_c[q];
       red_penalty(old_nb_quad_points + q) = false;
       for (UInt dim = 0; dim < spatial_dimension; ++dim) {
         ins_stress(old_nb_quad_points + q, dim) = new_normal_traction[q](dim);
         trac_old(old_nb_quad_points + q, dim) = new_normal_traction[q](dim);
         open_prec(old_nb_quad_points + q, dim) = 0.;
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::computeTraction(
     const Array<Real> & normal, ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /// define iterators
   Array<Real>::vector_iterator traction_it =
       tractions(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator opening_it =
       opening(el_type, ghost_type).begin(spatial_dimension);
 
   /// opening_prec is the opening of the previous step in the
   /// Newton-Raphson loop
   Array<Real>::vector_iterator opening_prec_it =
       opening_prec(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator contact_traction_it =
       contact_tractions(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator contact_opening_it =
       contact_opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::const_vector_iterator normal_it =
       normal.begin(spatial_dimension);
 
   Array<Real>::vector_iterator traction_end =
       tractions(el_type, ghost_type).end(spatial_dimension);
 
   Array<Real>::scalar_iterator sigma_c_it =
       sigma_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator delta_max_it =
       delta_max(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator delta_max_prev_it =
       delta_max.previous(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator delta_c_it =
       delta_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator damage_it = damage(el_type, ghost_type).begin();
 
   Array<Real>::vector_iterator insertion_stress_it =
       insertion_stress(el_type, ghost_type).begin(spatial_dimension);
 
   Array<bool>::scalar_iterator reduction_penalty_it =
       reduction_penalty(el_type, ghost_type).begin();
 
   Vector<Real> normal_opening(spatial_dimension);
   Vector<Real> tangential_opening(spatial_dimension);
 
   if (!this->model->isDefaultSolverExplicit())
     this->delta_max(el_type, ghost_type)
         .copy(this->delta_max.previous(el_type, ghost_type));
 
   /// loop on each quadrature point
   for (; traction_it != traction_end;
        ++traction_it, ++opening_it, ++opening_prec_it, ++normal_it,
        ++sigma_c_it, ++delta_max_it, ++delta_c_it, ++damage_it,
        ++contact_traction_it, ++insertion_stress_it, ++contact_opening_it,
        ++delta_max_prev_it, ++reduction_penalty_it) {
 
     Real normal_opening_norm, tangential_opening_norm;
     bool penetration;
     Real current_penalty = 0.;
     this->computeTractionOnQuad(
         *traction_it, *delta_max_it, *delta_max_prev_it, *delta_c_it,
         *insertion_stress_it, *sigma_c_it, *opening_it, *opening_prec_it,
         *normal_it, normal_opening, tangential_opening, normal_opening_norm,
         tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it,
         current_penalty, *contact_traction_it, *contact_opening_it);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::checkDeltaMax(
     GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /**
   * This function set a predefined value to the parameter
   * delta_max_prev of the elements that have been inserted in the
   * last loading step for which convergence has not been
   * reached. This is done before reducing the loading and re-doing
   * the step.  Otherwise, the updating of delta_max_prev would be
   * done with reference to the non-convergent solution. In this
   * function also other variables related to the contact and
   * friction behavior are correctly set.
   */
 
   Mesh & mesh = fem_cohesive->getMesh();
   Mesh::type_iterator it =
       mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive);
   Mesh::type_iterator last_type =
       mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive);
 
   /**
   * the variable "recompute" is set to true to activate the
   * procedure that reduce the penalty parameter for
   * compression. This procedure is set true only during the phase of
   * load_reduction, that has to be set in the maiin file. The
   * penalty parameter will be reduced only for the elements having
   * reduction_penalty = true.
   */
   recompute = true;
 
   for (; it != last_type; ++it) {
     Array<UInt> & elem_filter = element_filter(*it, ghost_type);
 
     UInt nb_element = elem_filter.getSize();
     if (nb_element == 0)
       continue;
 
     ElementType el_type = *it;
 
     /// define iterators
     Array<Real>::scalar_iterator delta_max_it =
         delta_max(el_type, ghost_type).begin();
 
     Array<Real>::scalar_iterator delta_max_end =
         delta_max(el_type, ghost_type).end();
 
     Array<Real>::scalar_iterator delta_max_prev_it =
         delta_max.previous(el_type, ghost_type).begin();
 
     Array<Real>::scalar_iterator delta_c_it =
         delta_c_eff(el_type, ghost_type).begin();
 
     Array<Real>::vector_iterator opening_prec_it =
         opening_prec(el_type, ghost_type).begin(spatial_dimension);
 
     Array<Real>::vector_iterator opening_prec_prev_it =
         opening_prec.previous(el_type, ghost_type).begin(spatial_dimension);
 
     /// loop on each quadrature point
     for (; delta_max_it != delta_max_end; ++delta_max_it, ++delta_max_prev_it,
                                           ++delta_c_it, ++opening_prec_it,
                                           ++opening_prec_prev_it) {
 
       if (*delta_max_prev_it == 0)
         /// elements inserted in the last incremental step, that did
         /// not converge
         *delta_max_it = *delta_c_it / 1000;
       else
         /// elements introduced in previous incremental steps, for
         /// which a correct value of delta_max_prev already exists
         *delta_max_it = *delta_max_prev_it;
 
       /// in case convergence is not reached, set opening_prec to the
       /// value referred to the previous incremental step
       *opening_prec_it = *opening_prec_prev_it;
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::resetVariables(
     GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /**
   * This function set the variables "recompute" and
   * "reduction_penalty" to false. It is called by solveStepCohesive
   * when convergence is reached. Such variables, in fact, have to be
   * false at the beginning of a new incremental step.
   */
 
   Mesh & mesh = fem_cohesive->getMesh();
   Mesh::type_iterator it =
       mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive);
   Mesh::type_iterator last_type =
       mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive);
 
   recompute = false;
 
   for (; it != last_type; ++it) {
     Array<UInt> & elem_filter = element_filter(*it, ghost_type);
 
     UInt nb_element = elem_filter.getSize();
     if (nb_element == 0)
       continue;
 
     ElementType el_type = *it;
 
     Array<bool>::scalar_iterator reduction_penalty_it =
         reduction_penalty(el_type, ghost_type).begin();
 
     Array<bool>::scalar_iterator reduction_penalty_end =
         reduction_penalty(el_type, ghost_type).end();
 
     /// loop on each quadrature point
     for (; reduction_penalty_it != reduction_penalty_end;
          ++reduction_penalty_it) {
 
       *reduction_penalty_it = false;
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::computeTangentTraction(
     const ElementType & el_type, Array<Real> & tangent_matrix,
     const Array<Real> & normal, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /// define iterators
   Array<Real>::matrix_iterator tangent_it =
       tangent_matrix.begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::matrix_iterator tangent_end =
       tangent_matrix.end(spatial_dimension, spatial_dimension);
 
   Array<Real>::const_vector_iterator normal_it =
       normal.begin(spatial_dimension);
 
   Array<Real>::vector_iterator opening_it =
       opening(el_type, ghost_type).begin(spatial_dimension);
 
   /// NB: delta_max_it points on delta_max_previous, i.e. the
   /// delta_max related to the solution of the previous incremental
   /// step
   Array<Real>::scalar_iterator delta_max_it =
       delta_max.previous(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator sigma_c_it =
       sigma_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator delta_c_it =
       delta_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator damage_it = damage(el_type, ghost_type).begin();
 
   Array<Real>::vector_iterator contact_opening_it =
       contact_opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<bool>::scalar_iterator reduction_penalty_it =
       reduction_penalty(el_type, ghost_type).begin();
 
   Vector<Real> normal_opening(spatial_dimension);
   Vector<Real> tangential_opening(spatial_dimension);
 
   for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it,
                                     ++delta_max_it, ++sigma_c_it, ++delta_c_it,
                                     ++damage_it, ++contact_opening_it,
                                     ++reduction_penalty_it) {
 
     Real normal_opening_norm, tangential_opening_norm;
     bool penetration;
     Real current_penalty = 0.;
     this->computeTangentTractionOnQuad(
         *tangent_it, *delta_max_it, *delta_c_it, *sigma_c_it, *opening_it,
         *normal_it, normal_opening, tangential_opening, normal_opening_norm,
         tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it,
         current_penalty, *contact_opening_it);
 
     // check if the tangential stiffness matrix is symmetric
     //    for (UInt h = 0; h < spatial_dimension; ++h){
     //      for (UInt l = h; l < spatial_dimension; ++l){
     //        if (l > h){
     //          Real k_ls = (*tangent_it)[spatial_dimension*h+l];
     //          Real k_us =  (*tangent_it)[spatial_dimension*l+h];
     //          //          std::cout << "k_ls = " << k_ls << std::endl;
     //          //          std::cout << "k_us = " << k_us << std::endl;
     //          if (std::abs(k_ls) > 1e-13 && std::abs(k_us) > 1e-13){
     //            Real error = std::abs((k_ls - k_us) / k_us);
     //            if (error > 1e-10){
     //	      std::cout << "non symmetric cohesive matrix" << std::endl;
     //	      //  std::cout << "error " << error << std::endl;
     //            }
     //          }
     //        }
     //      }
     //    }
   }
 
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialCohesiveLinear);
+INSTANTIATE_MATERIAL(cohesive_linear, MaterialCohesiveLinear);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc
index 27b8ac4b5..7bf8ea644 100644
--- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc
+++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc
@@ -1,296 +1,296 @@
 /**
  * @file   material_cohesive_linear_fatigue.cc
  *
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Fri Feb 20 2015
  * @date last modification: Tue Jan 12 2016
  *
  * @brief  See material_cohesive_linear_fatigue.hh for information
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "material_cohesive_linear_fatigue.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialCohesiveLinearFatigue<spatial_dimension>
 ::MaterialCohesiveLinearFatigue(SolidMechanicsModel & model,
 				const ID & id) :
   MaterialCohesiveLinear<spatial_dimension>(model, id),
   delta_prec("delta_prec", *this),
   K_plus("K_plus", *this),
   K_minus("K_minus", *this),
   T_1d("T_1d", *this),
   switches("switches", *this),
   delta_dot_prec("delta_dot_prec", *this),
   normal_regime("normal_regime", *this) {
 
   this->registerParam("delta_f", delta_f, Real(-1.) ,
 		      _pat_parsable | _pat_readable,
 		      "delta_f");
 
   this->registerParam("progressive_delta_f", progressive_delta_f, false,
 		      _pat_parsable | _pat_readable,
 		      "Whether or not delta_f is equal to delta_max");
 
   this->registerParam("count_switches", count_switches, false,
 		      _pat_parsable | _pat_readable,
 		      "Count the opening/closing switches per element");
 
   this->registerParam("fatigue_ratio", fatigue_ratio, Real(1.),
 		      _pat_parsable | _pat_readable,
 		      "What portion of the cohesive law is subjected to fatigue");
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinearFatigue<spatial_dimension>::initMaterial() {
   MaterialCohesiveLinear<spatial_dimension>::initMaterial();
 
   // check that delta_f has a proper value or assign a defaul value
   if (delta_f < 0) delta_f = this->delta_c_eff;
   else if (delta_f < this->delta_c_eff)
     AKANTU_DEBUG_ERROR("Delta_f must be greater or equal to delta_c");
 
   delta_prec.initialize(1);
   K_plus.initialize(1);
   K_minus.initialize(1);
   T_1d.initialize(1);
   normal_regime.initialize(1);
 
   if (count_switches) {
     switches.initialize(1);
     delta_dot_prec.initialize(1);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialCohesiveLinearFatigue<spatial_dimension>
 ::computeTraction(const Array<Real> & normal,
 		  ElementType el_type,
 		  GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /// define iterators
   Array<Real>::vector_iterator traction_it =
     this->tractions(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator opening_it =
     this->opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator contact_traction_it =
     this->contact_tractions(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator contact_opening_it =
     this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension);
 
   Array<Real>::vector_iterator traction_end =
     this->tractions(el_type, ghost_type).end(spatial_dimension);
 
   const Array<Real> & sigma_c_array = this->sigma_c_eff(el_type, ghost_type);
   Array<Real> & delta_max_array = this->delta_max(el_type, ghost_type);
   const Array<Real> & delta_c_array = this->delta_c_eff(el_type, ghost_type);
   Array<Real> & damage_array = this->damage(el_type, ghost_type);
 
   Array<Real>::vector_iterator insertion_stress_it =
     this->insertion_stress(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real> & delta_prec_array = delta_prec(el_type, ghost_type);
   Array<Real> & K_plus_array = K_plus(el_type, ghost_type);
   Array<Real> & K_minus_array = K_minus(el_type, ghost_type);
   Array<Real> & T_1d_array = T_1d(el_type, ghost_type);
   Array<bool> & normal_regime_array = normal_regime(el_type, ghost_type);
 
   Array<UInt> * switches_array = NULL;
   Array<Real> * delta_dot_prec_array = NULL;
 
   if (count_switches) {
     switches_array = &switches(el_type, ghost_type);
     delta_dot_prec_array = &delta_dot_prec(el_type, ghost_type);
   }
 
   Real * memory_space = new Real[2*spatial_dimension];
   Vector<Real> normal_opening(memory_space, spatial_dimension);
   Vector<Real> tangential_opening(memory_space + spatial_dimension,
 				  spatial_dimension);
 
   Real tolerance = Math::getTolerance();
 
   /// loop on each quadrature point
   for (UInt q = 0; traction_it != traction_end;
        ++traction_it, ++opening_it, ++normal_it,
 	 ++contact_traction_it, ++insertion_stress_it, ++contact_opening_it, ++q) {
 
     /// compute normal and tangential opening vectors
     Real normal_opening_norm = opening_it->dot(*normal_it);
     normal_opening  = (*normal_it);
     normal_opening *= normal_opening_norm;
 
     tangential_opening  = *opening_it;
     tangential_opening -=  normal_opening;
 
     Real tangential_opening_norm = tangential_opening.norm();
 
     /**
      * compute effective opening displacement
      * @f$ \delta = \sqrt{
      * \frac{\beta^2}{\kappa^2} \Delta_t^2 + \Delta_n^2 } @f$
      */
     Real delta = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
 
     bool penetration = normal_opening_norm < -tolerance;
     if (this->contact_after_breaking == false && Math::are_float_equal(damage_array(q), 1.))
       penetration = false;
 
     if (penetration) {
       /// use penalty coefficient in case of penetration
       *contact_traction_it = normal_opening;
       *contact_traction_it *= this->penalty;
       *contact_opening_it = normal_opening;
       /// don't consider penetration contribution for delta
       *opening_it = tangential_opening;
       normal_opening.clear();
     }
     else {
       delta += normal_opening_norm * normal_opening_norm;
       contact_traction_it->clear();
       contact_opening_it->clear();
     }
 
     delta = std::sqrt(delta);
 
     /**
      * Compute traction @f$ \mathbf{T} = \left(
      * \frac{\beta^2}{\kappa} \Delta_t \mathbf{t} + \Delta_n
      * \mathbf{n} \right) \frac{\sigma_c}{\delta} \left( 1-
      * \frac{\delta}{\delta_c} \right)@f$
      */
 
 
     // update maximum displacement and damage
     delta_max_array(q) = std::max(delta, delta_max_array(q));
     damage_array(q) = std::min(delta_max_array(q) / delta_c_array(q), Real(1.));
 
     Real delta_dot = delta - delta_prec_array(q);
 
     // count switches if asked
     if (count_switches) {
       if ( (delta_dot > 0. && (*delta_dot_prec_array)(q) <= 0.) ||
 	   (delta_dot < 0. && (*delta_dot_prec_array)(q) >= 0.) )
 	++((*switches_array)(q));
 
       (*delta_dot_prec_array)(q) = delta_dot;
     }
 
     // set delta_f equal to delta_max if desired
     if (progressive_delta_f) delta_f = delta_max_array(q);
 
     // broken element case
     if (Math::are_float_equal(damage_array(q), 1.))
       traction_it->clear();
     // just inserted element case
     else if (Math::are_float_equal(damage_array(q), 0.)) {
       if (penetration)
 	traction_it->clear();
       else
 	*traction_it = *insertion_stress_it;
       // initialize the 1d traction to sigma_c
       T_1d_array(q) = sigma_c_array(q);
     }
     // normal case
     else {
       // if element is closed then there are zero tractions
       if (delta <= tolerance)
 	traction_it->clear();
       // otherwise compute new tractions if the new delta is different
       // than the previous one
       else if (std::abs(delta_dot) > tolerance) {
 	// loading case
 	if (delta_dot > 0.) {
 	  if (!normal_regime_array(q)) {
 	    // equation (4) of the article
 	    K_plus_array(q) *= 1. - delta_dot / delta_f;
 	    // equivalent to equation (2) of the article
 	    T_1d_array(q) += K_plus_array(q) * delta_dot;
 
 	    // in case of reloading, traction must not exceed that of the
 	    // envelop of the cohesive law
 	    Real max_traction = sigma_c_array(q) * (1 - delta / delta_c_array(q));
 	    bool max_traction_exceeded = T_1d_array(q) > max_traction;
 	    if (max_traction_exceeded) T_1d_array(q) = max_traction;
 
 	    // switch to standard linear cohesive law
 	    if (delta_max_array(q) > fatigue_ratio * delta_c_array(q)) {
 	      // reset delta_max to avoid big jumps in the traction
 	      delta_max_array(q) = sigma_c_array(q) / (T_1d_array(q) / delta + sigma_c_array(q) / delta_c_array(q));
 	      damage_array(q) = std::min(delta_max_array(q) / delta_c_array(q), Real(1.));
 	      K_minus_array(q) = sigma_c_array(q) / delta_max_array(q) * (1. - damage_array(q));
 	      normal_regime_array(q) = true;
 	    } else {
 	      // equation (3) of the article
 	      K_minus_array(q) = T_1d_array(q) / delta;
 
 	      // if the traction is following the cohesive envelop, then
 	      // K_plus has to be reset
 	      if (max_traction_exceeded) K_plus_array(q) = K_minus_array(q);
 	    }
 	  } else {
 	    // compute stiffness according to the standard law
 	    K_minus_array(q) = sigma_c_array(q) / delta_max_array(q) * (1. - damage_array(q));
 	  }
 	}
 	// unloading case
 	else if (!normal_regime_array(q)) {
 	  // equation (4) of the article
 	  K_plus_array(q) += (K_plus_array(q) - K_minus_array(q)) * delta_dot / delta_f;
 	  // equivalent to equation (2) of the article
 	  T_1d_array(q) = K_minus_array(q) * delta;
 	}
 
 	// applying the actual stiffness
 	*traction_it  = tangential_opening;
 	*traction_it *= this->beta2_kappa;
 	*traction_it += normal_opening;
 	*traction_it *= K_minus_array(q);
       }
     }
 
     // update precendent delta
     delta_prec_array(q) = delta;
   }
 
   delete [] memory_space;
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialCohesiveLinearFatigue);
+INSTANTIATE_MATERIAL(cohesive_linear_fatigue, MaterialCohesiveLinearFatigue);
 
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc
index d5d96e9cc..c21e2ff4b 100644
--- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc
+++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc
@@ -1,386 +1,386 @@
 /**
  * @file   material_cohesive_linear_friction.cc
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  *
  * @date creation: Tue Jan 12 2016
  * @date last modification: Thu Jan 14 2016
  *
  * @brief  Linear irreversible cohesive law of mixed mode loading with
  * random stress definition for extrinsic type
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "material_cohesive_linear_friction.hh"
 #include "solid_mechanics_model_cohesive.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialCohesiveLinearFriction<spatial_dimension>::
     MaterialCohesiveLinearFriction(SolidMechanicsModel & model, const ID & id)
     : MaterialParent(model, id), residual_sliding("residual_sliding", *this),
       friction_force("friction_force", *this) {
   AKANTU_DEBUG_IN();
 
   this->registerParam("mu", mu_max, Real(0.), _pat_parsable | _pat_readable,
                       "Maximum value of the friction coefficient");
 
   this->registerParam("penalty_for_friction", friction_penalty, Real(0.),
                       _pat_parsable | _pat_readable,
                       "Penalty parameter for the friction behavior");
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinearFriction<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
   MaterialParent::initMaterial();
 
   friction_force.initialize(spatial_dimension);
   residual_sliding.initialize(1);
   residual_sliding.initializeHistory();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinearFriction<spatial_dimension>::computeTraction(
     __attribute__((unused)) const Array<Real> & normal, ElementType el_type,
     GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   residual_sliding.resize();
   friction_force.resize();
 
   /// define iterators
   Array<Real>::vector_iterator traction_it =
       this->tractions(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator traction_end =
       this->tractions(el_type, ghost_type).end(spatial_dimension);
 
   Array<Real>::vector_iterator opening_it =
       this->opening(el_type, ghost_type).begin(spatial_dimension);
 
   /// opening_prec is the opening at the end of the previous step in
   /// the Newton-Raphson loop
   Array<Real>::vector_iterator opening_prec_it =
       this->opening_prec(el_type, ghost_type).begin(spatial_dimension);
 
   /// opening_prec_prev is the opening (opening + penetration)
   /// referred to the convergence of the previous incremental step
   Array<Real>::vector_iterator opening_prec_prev_it =
       this->opening_prec.previous(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator contact_traction_it =
       this->contact_tractions(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator contact_opening_it =
       this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::const_iterator<Vector<Real>> normal_it =
       this->normal.begin(spatial_dimension);
 
   Array<Real>::iterator<Real> sigma_c_it =
       this->sigma_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real> delta_max_it =
       this->delta_max(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real> delta_max_prev_it =
       this->delta_max.previous(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real> delta_c_it =
       this->delta_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real> damage_it =
       this->damage(el_type, ghost_type).begin();
 
   Array<Real>::vector_iterator insertion_stress_it =
       this->insertion_stress(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::iterator<Real> res_sliding_it =
       this->residual_sliding(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real> res_sliding_prev_it =
       this->residual_sliding.previous(el_type, ghost_type).begin();
 
   Array<Real>::vector_iterator friction_force_it =
       this->friction_force(el_type, ghost_type).begin(spatial_dimension);
 
   Array<bool>::iterator<bool> reduction_penalty_it =
       this->reduction_penalty(el_type, ghost_type).begin();
 
   Vector<Real> normal_opening(spatial_dimension);
   Vector<Real> tangential_opening(spatial_dimension);
 
   if (!this->model->isDefaultSolverExplicit())
     this->delta_max(el_type, ghost_type)
         .copy(this->delta_max.previous(el_type, ghost_type));
 
   /// loop on each quadrature point
   for (; traction_it != traction_end;
        ++traction_it, ++opening_it, ++opening_prec_prev_it, ++opening_prec_it,
        ++normal_it, ++sigma_c_it, ++delta_max_it, ++delta_c_it, ++damage_it,
        ++contact_traction_it, ++insertion_stress_it, ++contact_opening_it,
        ++delta_max_prev_it, ++res_sliding_it, ++res_sliding_prev_it,
        ++friction_force_it, ++reduction_penalty_it) {
 
     Real normal_opening_norm, tangential_opening_norm;
     bool penetration;
     Real current_penalty = 0.;
     this->computeTractionOnQuad(
         *traction_it, *delta_max_it, *delta_max_prev_it, *delta_c_it,
         *insertion_stress_it, *sigma_c_it, *opening_it, *opening_prec_it,
         *normal_it, normal_opening, tangential_opening, normal_opening_norm,
         tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it,
         current_penalty, *contact_traction_it, *contact_opening_it);
 
     if (penetration) {
 
       /// the friction coefficient mu increases with the damage. It
       /// equals the maximum value when damage = 1.
       //      Real damage = std::min(*delta_max_prev_it / *delta_c_it,
       //      Real(1.));
       Real mu = mu_max; // * damage;
 
       /// the definition of tau_max refers to the opening
       /// (penetration) of the previous incremental step
       Real normal_opening_prev_norm =
           std::min(opening_prec_prev_it->dot(*normal_it), Real(0.));
 
       //      Vector<Real> normal_opening_prev = (*normal_it);
       //      normal_opening_prev *= normal_opening_prev_norm;
 
       Real tau_max =
           mu * current_penalty * (std::abs(normal_opening_prev_norm));
       Real delta_sliding_norm =
           std::abs(tangential_opening_norm - *res_sliding_prev_it);
 
       /// tau is the norm of the friction force, acting tangentially to the
       /// surface
       Real tau = std::min(friction_penalty * delta_sliding_norm, tau_max);
 
       if ((tangential_opening_norm - *res_sliding_prev_it) < 0.0)
         tau = -tau;
 
       /// from tau get the x and y components of friction, to be added in the
       /// force vector
       Vector<Real> tangent_unit_vector(spatial_dimension);
       tangent_unit_vector = tangential_opening / tangential_opening_norm;
       *friction_force_it = tau * tangent_unit_vector;
 
       /// update residual_sliding
       *res_sliding_it =
           tangential_opening_norm - (std::abs(tau) / friction_penalty);
 
     } else {
 
       friction_force_it->clear();
     }
 
     *traction_it += *friction_force_it;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinearFriction<spatial_dimension>::checkDeltaMax(
     GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MaterialParent::checkDeltaMax();
 
   Mesh & mesh = this->fem_cohesive->getMesh();
   Mesh::type_iterator it =
       mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive);
   Mesh::type_iterator last_type =
       mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive);
 
   for (; it != last_type; ++it) {
     Array<UInt> & elem_filter = this->element_filter(*it, ghost_type);
 
     UInt nb_element = elem_filter.getSize();
     if (nb_element == 0)
       continue;
 
     ElementType el_type = *it;
 
     /// define iterators
     Array<Real>::iterator<Real> delta_max_it =
         this->delta_max(el_type, ghost_type).begin();
 
     Array<Real>::iterator<Real> delta_max_end =
         this->delta_max(el_type, ghost_type).end();
 
     Array<Real>::iterator<Real> res_sliding_it =
         this->residual_sliding(el_type, ghost_type).begin();
 
     Array<Real>::iterator<Real> res_sliding_prev_it =
         this->residual_sliding.previous(el_type, ghost_type).begin();
 
     /// loop on each quadrature point
     for (; delta_max_it != delta_max_end;
          ++delta_max_it, ++res_sliding_it, ++res_sliding_prev_it) {
 
       /**
        * in case convergence is not reached, set "residual_sliding"
        * for the friction behaviour to the value referred to the
        * previous incremental step
        */
       *res_sliding_it = *res_sliding_prev_it;
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinearFriction<spatial_dimension>::computeTangentTraction(
     const ElementType & el_type, Array<Real> & tangent_matrix,
     __attribute__((unused)) const Array<Real> & normal, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /// define iterators
   Array<Real>::matrix_iterator tangent_it =
       tangent_matrix.begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::matrix_iterator tangent_end =
       tangent_matrix.end(spatial_dimension, spatial_dimension);
 
   Array<Real>::const_vector_iterator normal_it =
       this->normal.begin(spatial_dimension);
 
   Array<Real>::vector_iterator opening_it =
       this->opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator opening_prec_prev_it =
       this->opening_prec.previous(el_type, ghost_type).begin(spatial_dimension);
 
   /**
    * NB: delta_max_it points on delta_max_previous, i.e. the
    * delta_max related to the solution of the previous incremental
    * step
    */
   Array<Real>::iterator<Real> delta_max_it =
       this->delta_max.previous(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real> sigma_c_it =
       this->sigma_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real> delta_c_it =
       this->delta_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real> damage_it =
       this->damage(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Vector<Real>> contact_opening_it =
       this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::iterator<Real> res_sliding_prev_it =
       this->residual_sliding.previous(el_type, ghost_type).begin();
 
   Array<bool>::iterator<bool> reduction_penalty_it =
       this->reduction_penalty(el_type, ghost_type).begin();
 
   Vector<Real> normal_opening(spatial_dimension);
   Vector<Real> tangential_opening(spatial_dimension);
 
   for (; tangent_it != tangent_end;
        ++tangent_it, ++normal_it, ++opening_it, ++opening_prec_prev_it,
        ++delta_max_it, ++sigma_c_it, ++delta_c_it, ++damage_it,
        ++contact_opening_it, ++res_sliding_prev_it, ++reduction_penalty_it) {
 
     Real normal_opening_norm, tangential_opening_norm;
     bool penetration;
     Real current_penalty = 0.;
     this->computeTangentTractionOnQuad(
         *tangent_it, *delta_max_it, *delta_c_it, *sigma_c_it, *opening_it,
         *normal_it, normal_opening, tangential_opening, normal_opening_norm,
         tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it,
         current_penalty, *contact_opening_it);
 
     if (penetration) {
       //      Real damage = std::min(*delta_max_it / *delta_c_it, Real(1.));
       Real mu = mu_max; // * damage;
 
       Real normal_opening_prev_norm =
           std::min(opening_prec_prev_it->dot(*normal_it), Real(0.));
       //      Vector<Real> normal_opening_prev = (*normal_it);
       //      normal_opening_prev *= normal_opening_prev_norm;
 
       Real tau_max =
           mu * current_penalty * (std::abs(normal_opening_prev_norm));
       Real delta_sliding_norm =
           std::abs(tangential_opening_norm - *res_sliding_prev_it);
 
       // tau is the norm of the friction force, acting tangentially to the
       // surface
       Real tau = std::min(friction_penalty * delta_sliding_norm, tau_max);
 
       if (tau < tau_max && tau_max > Math::getTolerance()) {
         Matrix<Real> I(spatial_dimension, spatial_dimension);
         I.eye(1.);
 
         Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
         n_outer_n.outerProduct(*normal_it, *normal_it);
 
         Matrix<Real> nn(n_outer_n);
         I -= nn;
         *tangent_it += I * friction_penalty;
       }
     }
 
     // check if the tangential stiffness matrix is symmetric
     //    for (UInt h = 0; h < spatial_dimension; ++h){
     //      for (UInt l = h; l < spatial_dimension; ++l){
     //        if (l > h){
     //          Real k_ls = (*tangent_it)[spatial_dimension*h+l];
     //          Real k_us =  (*tangent_it)[spatial_dimension*l+h];
     //          //          std::cout << "k_ls = " << k_ls << std::endl;
     //          //          std::cout << "k_us = " << k_us << std::endl;
     //          if (std::abs(k_ls) > 1e-13 && std::abs(k_us) > 1e-13){
     //            Real error = std::abs((k_ls - k_us) / k_us);
     //            if (error > 1e-10){
     //	      std::cout << "non symmetric cohesive matrix" << std::endl;
     //	      //  std::cout << "error " << error << std::endl;
     //            }
     //          }
     //        }
     //      }
     //    }
   }
 
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialCohesiveLinearFriction);
+INSTANTIATE_MATERIAL(cohesive_linear_friction, MaterialCohesiveLinearFriction);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc
index 1ff0268e4..aba88eece 100644
--- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc
+++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc
@@ -1,596 +1,596 @@
 /**
  * @file   material_cohesive_linear_uncoupled.cc
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  *
  * @date creation: Wed Feb 22 2012
  * @date last modification: Thu Jan 14 2016
  *
  * @brief  Linear irreversible cohesive law of mixed mode loading with
  * random stress definition for extrinsic type
  *
  * @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 <algorithm>
 #include <numeric>
 
 /* -------------------------------------------------------------------------- */
 #include "material_cohesive_linear_uncoupled.hh"
 #include "solid_mechanics_model_cohesive.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialCohesiveLinearUncoupled<spatial_dimension>::
     MaterialCohesiveLinearUncoupled(SolidMechanicsModel & model, const ID & id)
     : MaterialCohesiveLinear<spatial_dimension>(model, id),
       delta_n_max("delta_n_max", *this), delta_t_max("delta_t_max", *this),
       damage_n("damage_n", *this), damage_t("damage_t", *this) {
 
   AKANTU_DEBUG_IN();
 
   this->registerParam(
       "roughness", R, Real(1.), _pat_parsable | _pat_readable,
       "Roughness to define coupling between mode II and mode I");
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinearUncoupled<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
   MaterialCohesiveLinear<spatial_dimension>::initMaterial();
 
   delta_n_max.initialize(1);
   delta_t_max.initialize(1);
   damage_n.initialize(1);
   damage_t.initialize(1);
 
   delta_n_max.initializeHistory();
   delta_t_max.initializeHistory();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinearUncoupled<spatial_dimension>::computeTraction(
     const Array<Real> &, ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   delta_n_max.resize();
   delta_t_max.resize();
   damage_n.resize();
   damage_t.resize();
 
   /// define iterators
   Array<Real>::vector_iterator traction_it =
       this->tractions(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator traction_end =
       this->tractions(el_type, ghost_type).end(spatial_dimension);
 
   Array<Real>::vector_iterator opening_it =
       this->opening(el_type, ghost_type).begin(spatial_dimension);
 
   /// opening_prec is the opening of the previous step in the
   /// Newton-Raphson loop
   Array<Real>::vector_iterator opening_prec_it =
       this->opening_prec(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator contact_traction_it =
       this->contact_tractions(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::vector_iterator contact_opening_it =
       this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::const_vector_iterator normal_it =
       this->normal.begin(spatial_dimension);
 
   Array<Real>::scalar_iterator sigma_c_it =
       this->sigma_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator delta_n_max_it =
       delta_n_max(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator delta_t_max_it =
       delta_t_max(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator delta_c_it =
       this->delta_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator damage_n_it =
       damage_n(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator damage_t_it =
       damage_t(el_type, ghost_type).begin();
 
   Array<Real>::vector_iterator insertion_stress_it =
       this->insertion_stress(el_type, ghost_type).begin(spatial_dimension);
 
   Array<bool>::scalar_iterator reduction_penalty_it =
       this->reduction_penalty(el_type, ghost_type).begin();
 
   Vector<Real> normal_opening(spatial_dimension);
   Vector<Real> tangential_opening(spatial_dimension);
 
   if (!this->model->isDefaultSolverExplicit()) {
     this->delta_n_max(el_type, ghost_type)
         .copy(this->delta_n_max.previous(el_type, ghost_type));
     this->delta_t_max(el_type, ghost_type)
         .copy(this->delta_t_max.previous(el_type, ghost_type));
   }
 
   /// loop on each quadrature point
   for (; traction_it != traction_end;
        ++traction_it, ++opening_it, ++opening_prec_it, ++contact_traction_it,
        ++contact_opening_it, ++normal_it, ++sigma_c_it, ++delta_n_max_it,
        ++delta_t_max_it, ++delta_c_it, ++damage_n_it, ++damage_t_it,
        ++insertion_stress_it, ++reduction_penalty_it) {
 
     Real normal_opening_norm, tangential_opening_norm;
     bool penetration;
     Real current_penalty = 0.;
     Real delta_c2_R2 = *delta_c_it * (*delta_c_it) / R / R;
 
     /// compute normal and tangential opening vectors
     normal_opening_norm = opening_it->dot(*normal_it);
     Vector<Real> normal_opening = *normal_it;
     normal_opening *= normal_opening_norm;
 
     //    std::cout<< "normal_opening_norm = " << normal_opening_norm
     //    <<std::endl;
 
     Vector<Real> tangential_opening = *opening_it;
     tangential_opening -= normal_opening;
     tangential_opening_norm = tangential_opening.norm();
 
     /// compute effective opening displacement
     Real delta_n =
         tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
     Real delta_t =
         tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
 
     penetration = normal_opening_norm < 0.0;
     if (this->contact_after_breaking == false &&
         Math::are_float_equal(*damage_n_it, 1.))
       penetration = false;
 
     /**
      * If during the convergence loop a cohesive element continues to
      * jumps from penetration to opening, and convergence is not
      * reached, its penalty parameter will be reduced in the
      * recomputation of the same incremental step. Recompute is set
      * equal to true when convergence is not reached in the
      * solveStepCohesive function and the execution of the program
      * goes back to the main file where the variable load_reduction
      * is set equal to true.
      */
     Real normal_opening_prec_norm = opening_prec_it->dot(*normal_it);
     //    Vector<Real> normal_opening_prec  = *normal_it;
     //    normal_opening_prec *= normal_opening_prec_norm;
     if (!this->model->isDefaultSolverExplicit()) // && !this->recompute)
       if ((normal_opening_prec_norm * normal_opening_norm) < 0.0)
         *reduction_penalty_it = true;
 
     *opening_prec_it = *opening_it;
 
     if (penetration) {
       if (this->recompute && *reduction_penalty_it) {
         /// the penalty parameter is locally reduced
         current_penalty = this->penalty / 100.;
       } else
         current_penalty = this->penalty;
 
       /// use penalty coefficient in case of penetration
       *contact_traction_it = normal_opening;
       *contact_traction_it *= current_penalty;
       *contact_opening_it = normal_opening;
 
       /// don't consider penetration contribution for delta
       *opening_it = tangential_opening;
       normal_opening.clear();
 
     } else {
       delta_n += normal_opening_norm * normal_opening_norm;
       delta_t += normal_opening_norm * normal_opening_norm * delta_c2_R2;
       contact_traction_it->clear();
       contact_opening_it->clear();
     }
 
     delta_n = std::sqrt(delta_n);
     delta_t = std::sqrt(delta_t);
 
     /// update maximum displacement and damage
     *delta_n_max_it = std::max(*delta_n_max_it, delta_n);
     *damage_n_it = std::min(*delta_n_max_it / *delta_c_it, Real(1.));
 
     *delta_t_max_it = std::max(*delta_t_max_it, delta_t);
     *damage_t_it = std::min(*delta_t_max_it / *delta_c_it, Real(1.));
 
     Vector<Real> normal_traction(spatial_dimension);
     Vector<Real> shear_traction(spatial_dimension);
 
     /// NORMAL TRACTIONS
     if (Math::are_float_equal(*damage_n_it, 1.))
       normal_traction.clear();
     else if (Math::are_float_equal(*damage_n_it, 0.)) {
       if (penetration)
         normal_traction.clear();
       else
         normal_traction = *insertion_stress_it;
     } else {
       // the following formulation holds both in loading and in
       // unloading-reloading
       normal_traction = normal_opening;
 
       AKANTU_DEBUG_ASSERT(*delta_n_max_it != 0.,
                           "Division by zero, tolerance might be too low");
 
       normal_traction *= *sigma_c_it / (*delta_n_max_it) * (1. - *damage_n_it);
     }
 
     /// SHEAR TRACTIONS
     if (Math::are_float_equal(*damage_t_it, 1.))
       shear_traction.clear();
     else if (Math::are_float_equal(*damage_t_it, 0.)) {
       shear_traction.clear();
     } else {
       shear_traction = tangential_opening;
 
       AKANTU_DEBUG_ASSERT(*delta_t_max_it != 0.,
                           "Division by zero, tolerance might be too low");
 
       shear_traction *= this->beta2_kappa;
       shear_traction *= *sigma_c_it / (*delta_t_max_it) * (1. - *damage_t_it);
     }
 
     *traction_it = normal_traction;
     *traction_it += shear_traction;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinearUncoupled<spatial_dimension>::checkDeltaMax(
     GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /**
    * This function set a predefined value to the parameter
    * delta_max_prev of the elements that have been inserted in the
    * last loading step for which convergence has not been
    * reached. This is done before reducing the loading and re-doing
    * the step.  Otherwise, the updating of delta_max_prev would be
    * done with reference to the non-convergent solution. In this
    * function also other variables related to the contact and
    * friction behavior are correctly set.
    */
 
   Mesh & mesh = this->fem_cohesive->getMesh();
   Mesh::type_iterator it =
       mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive);
   Mesh::type_iterator last_type =
       mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive);
 
   /**
    * the variable "recompute" is set to true to activate the
    * procedure that reduces the penalty parameter for
    * compression. This procedure is available only during the phase of
    * load_reduction, that has to be set in the main file. The
    * penalty parameter will be reduced only for the elements having
    * reduction_penalty = true.
    */
   this->recompute = true;
 
   for (; it != last_type; ++it) {
     Array<UInt> & elem_filter = this->element_filter(*it, ghost_type);
 
     UInt nb_element = elem_filter.getSize();
     if (nb_element == 0)
       continue;
 
     ElementType el_type = *it;
 
     //    std::cout << "element type: " << el_type << std::endl;
 
     /// define iterators
     Array<Real>::scalar_iterator delta_n_max_it =
         delta_n_max(el_type, ghost_type).begin();
 
     Array<Real>::scalar_iterator delta_n_max_end =
         delta_n_max(el_type, ghost_type).end();
 
     Array<Real>::scalar_iterator delta_n_max_prev_it =
         delta_n_max.previous(el_type, ghost_type).begin();
 
     Array<Real>::scalar_iterator delta_t_max_it =
         delta_t_max(el_type, ghost_type).begin();
 
     Array<Real>::scalar_iterator delta_t_max_prev_it =
         delta_t_max.previous(el_type, ghost_type).begin();
 
     Array<Real>::scalar_iterator delta_c_it =
         this->delta_c_eff(el_type, ghost_type).begin();
 
     Array<Real>::vector_iterator opening_prec_it =
         this->opening_prec(el_type, ghost_type).begin(spatial_dimension);
 
     Array<Real>::vector_iterator opening_prec_prev_it =
         this->opening_prec.previous(el_type, ghost_type)
             .begin(spatial_dimension);
 
     Int it = 0;
 
     /// loop on each quadrature point
     for (; delta_n_max_it != delta_n_max_end;
          ++delta_n_max_it, ++delta_t_max_it, ++delta_c_it,
          ++delta_n_max_prev_it, ++delta_t_max_prev_it, ++opening_prec_it,
          ++opening_prec_prev_it) {
 
       ++it;
 
       if (*delta_n_max_prev_it == 0) {
         /// elements inserted in the last incremental step, that did
         /// not converge
         *delta_n_max_it = *delta_c_it / 1000.;
       } else
         /// elements introduced in previous incremental steps, for
         /// which a correct value of delta_max_prev already exists
         *delta_n_max_it = *delta_n_max_prev_it;
 
       if (*delta_t_max_prev_it == 0) {
         *delta_t_max_it = *delta_c_it * this->kappa / this->beta / 1000.;
       } else
         *delta_t_max_it = *delta_t_max_prev_it;
 
       /// in case convergence is not reached, set opening_prec to the
       /// value referred to the previous incremental step
       *opening_prec_it = *opening_prec_prev_it;
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinearUncoupled<spatial_dimension>::computeTangentTraction(
     const ElementType & el_type, Array<Real> & tangent_matrix,
     const Array<Real> &, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /// define iterators
   Array<Real>::matrix_iterator tangent_it =
       tangent_matrix.begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::matrix_iterator tangent_end =
       tangent_matrix.end(spatial_dimension, spatial_dimension);
 
   Array<Real>::const_vector_iterator normal_it =
       this->normal.begin(spatial_dimension);
 
   Array<Real>::vector_iterator opening_it =
       this->opening(el_type, ghost_type).begin(spatial_dimension);
 
   /// NB: delta_max_it points on delta_max_previous, i.e. the
   /// delta_max related to the solution of the previous incremental
   /// step
   Array<Real>::scalar_iterator delta_n_max_it =
       delta_n_max.previous(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator delta_t_max_it =
       delta_t_max.previous(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator sigma_c_it =
       this->sigma_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator delta_c_it =
       this->delta_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::scalar_iterator damage_n_it =
       damage_n(el_type, ghost_type).begin();
 
   Array<Real>::vector_iterator contact_opening_it =
       this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<bool>::scalar_iterator reduction_penalty_it =
       this->reduction_penalty(el_type, ghost_type).begin();
 
   Vector<Real> normal_opening(spatial_dimension);
   Vector<Real> tangential_opening(spatial_dimension);
 
   for (; tangent_it != tangent_end;
        ++tangent_it, ++normal_it, ++opening_it, ++sigma_c_it, ++delta_c_it,
        ++delta_n_max_it, ++delta_t_max_it, ++damage_n_it, ++contact_opening_it,
        ++reduction_penalty_it) {
 
     Real normal_opening_norm, tangential_opening_norm;
     bool penetration;
     Real current_penalty = 0.;
     Real delta_c2_R2 = *delta_c_it * (*delta_c_it) / R / R;
 
     /**
      * During the update of the residual the interpenetrations are
      * stored in the array "contact_opening", therefore, in the case
      * of penetration, in the array "opening" there are only the
      * tangential components.
      */
     *opening_it += *contact_opening_it;
 
     /// compute normal and tangential opening vectors
     normal_opening_norm = opening_it->dot(*normal_it);
     Vector<Real> normal_opening = *normal_it;
     normal_opening *= normal_opening_norm;
 
     Vector<Real> tangential_opening = *opening_it;
     tangential_opening -= normal_opening;
     tangential_opening_norm = tangential_opening.norm();
 
     Real delta_n =
         tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
     Real delta_t =
         tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
 
     penetration = normal_opening_norm < 0.0;
     if (this->contact_after_breaking == false &&
         Math::are_float_equal(*damage_n_it, 1.))
       penetration = false;
 
     Real derivative = 0; // derivative = d(t/delta)/ddelta
     Real T = 0;
 
     /// TANGENT STIFFNESS FOR NORMAL TRACTIONS
     Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
     n_outer_n.outerProduct(*normal_it, *normal_it);
 
     if (penetration) {
       if (this->recompute && *reduction_penalty_it)
         current_penalty = this->penalty / 100.;
       else
         current_penalty = this->penalty;
 
       /// stiffness in compression given by the penalty parameter
       *tangent_it = n_outer_n;
       *tangent_it *= current_penalty;
 
       *opening_it = tangential_opening;
       normal_opening.clear();
     } else {
       delta_n += normal_opening_norm * normal_opening_norm;
       delta_n = std::sqrt(delta_n);
 
       delta_t += normal_opening_norm * normal_opening_norm * delta_c2_R2;
 
       /**
        * Delta has to be different from 0 to have finite values of
        * tangential stiffness.  At the element insertion, delta =
        * 0. Therefore, a fictictious value is defined, for the
        * evaluation of the first value of K.
        */
       if (delta_n < Math::getTolerance())
         delta_n = *delta_c_it / 1000.;
 
       // loading
       if (delta_n >= *delta_n_max_it) {
         if (delta_n <= *delta_c_it) {
           derivative = -(*sigma_c_it) / (delta_n * delta_n);
           T = *sigma_c_it * (1 - delta_n / *delta_c_it);
         } else {
           derivative = 0.;
           T = 0.;
         }
         // unloading-reloading
       } else if (delta_n < *delta_n_max_it) {
         Real T_max = *sigma_c_it * (1 - *delta_n_max_it / *delta_c_it);
         derivative = 0.;
         T = T_max / *delta_n_max_it * delta_n;
       }
 
       /// computation of the derivative of the constitutive law (dT/ddelta)
       Matrix<Real> nn(n_outer_n);
       nn *= T / delta_n;
 
       Vector<Real> Delta_tilde(normal_opening);
       Delta_tilde *= (1. - this->beta2_kappa2);
       Vector<Real> mm(*opening_it);
       mm *= this->beta2_kappa2;
       Delta_tilde += mm;
 
       Vector<Real> Delta_hat(normal_opening);
       Matrix<Real> prov(spatial_dimension, spatial_dimension);
       prov.outerProduct(Delta_hat, Delta_tilde);
       prov *= derivative / delta_n;
       prov += nn;
 
       Matrix<Real> prov_t = prov.transpose();
 
       *tangent_it = prov_t;
     }
 
     derivative = 0.;
     T = 0.;
 
     /// TANGENT STIFFNESS FOR SHEAR TRACTIONS
     delta_t = std::sqrt(delta_t);
 
     /**
      * Delta has to be different from 0 to have finite values of
      * tangential stiffness.  At the element insertion, delta =
      * 0. Therefore, a fictictious value is defined, for the
      * evaluation of the first value of K.
      */
     if (delta_t < Math::getTolerance())
       delta_t = *delta_c_it / 1000.;
 
     // loading
     if (delta_t >= *delta_t_max_it) {
       if (delta_t <= *delta_c_it) {
         derivative = -(*sigma_c_it) / (delta_t * delta_t);
         T = *sigma_c_it * (1 - delta_t / *delta_c_it);
       } else {
         derivative = 0.;
         T = 0.;
       }
       // unloading-reloading
     } else if (delta_t < *delta_t_max_it) {
       Real T_max = *sigma_c_it * (1 - *delta_t_max_it / *delta_c_it);
       derivative = 0.;
       T = T_max / *delta_t_max_it * delta_t;
     }
 
     /// computation of the derivative of the constitutive law (dT/ddelta)
     Matrix<Real> I(spatial_dimension, spatial_dimension);
     I.eye();
     Matrix<Real> nn(n_outer_n);
     I -= nn;
     I *= T / delta_t;
 
     Vector<Real> Delta_tilde(normal_opening);
     Delta_tilde *= (delta_c2_R2 - this->beta2_kappa2);
     Vector<Real> mm(*opening_it);
     mm *= this->beta2_kappa2;
     Delta_tilde += mm;
 
     Vector<Real> Delta_hat(tangential_opening);
     Delta_hat *= this->beta2_kappa;
     Matrix<Real> prov(spatial_dimension, spatial_dimension);
     prov.outerProduct(Delta_hat, Delta_tilde);
     prov *= derivative / delta_t;
     prov += I;
 
     Matrix<Real> prov_t = prov.transpose();
 
     *tangent_it += prov_t;
   }
 
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialCohesiveLinearUncoupled);
+INSTANTIATE_MATERIAL(cohesive_linear_uncoupled, MaterialCohesiveLinearUncoupled);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo.cc b/src/model/solid_mechanics/materials/material_damage/material_marigo.cc
index cdf3cb3b3..83738f986 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo.cc
@@ -1,107 +1,107 @@
 /**
  * @file   material_marigo.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Marion Estelle Chambart <marion.chambart@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Thu Oct 08 2015
  *
  * @brief  Specialization of the material class for the marigo material
  *
  * @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 "material_marigo.hh"
 #include "solid_mechanics_model.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialMarigo<spatial_dimension>::MaterialMarigo(SolidMechanicsModel & model,
                                                   const ID & id)
     : MaterialDamage<spatial_dimension>(model, id), Yd("Yd", *this),
       damage_in_y(false), yc_limit(false) {
   AKANTU_DEBUG_IN();
 
   this->registerParam("Sd", Sd, Real(5000.), _pat_parsable | _pat_modifiable);
   this->registerParam("epsilon_c", epsilon_c, Real(0.), _pat_parsable,
                       "Critical strain");
   this->registerParam("Yc limit", yc_limit, false, _pat_internal,
                       "As the material a critical Y");
   this->registerParam("damage_in_y", damage_in_y, false, _pat_parsable,
                       "Use threshold (1-D)Y");
   this->registerParam("Yd", Yd, _pat_parsable, "Damaging energy threshold");
 
   this->Yd.initialize(1);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMarigo<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
   MaterialDamage<spatial_dimension>::initMaterial();
 
   updateInternalParameters();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMarigo<spatial_dimension>::updateInternalParameters() {
   MaterialDamage<spatial_dimension>::updateInternalParameters();
   Yc = .5 * epsilon_c * this->E * epsilon_c;
   if (std::abs(epsilon_c) > std::numeric_limits<Real>::epsilon())
     yc_limit = true;
   else
     yc_limit = false;
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMarigo<spatial_dimension>::computeStress(ElementType el_type,
                                                       GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Array<Real>::scalar_iterator dam = this->damage(el_type, ghost_type).begin();
   Array<Real>::scalar_iterator Yd_q = this->Yd(el_type, ghost_type).begin();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Real Y = 0.;
   computeStressOnQuad(grad_u, sigma, *dam, Y, *Yd_q);
 
   ++dam;
   ++Yd_q;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
-INSTANTIATE_MATERIAL(MaterialMarigo);
+INSTANTIATE_MATERIAL(marigo, MaterialMarigo);
 
 } // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc
similarity index 89%
rename from src/model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc
rename to src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc
index dedf2d443..7258ef8db 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc
@@ -1,114 +1,106 @@
 /**
- * @file   material_marigo_non_local_inline_impl.cc
+ * @file   material_marigo_non_local.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  Marigo non-local inline function implementation
  *
  * @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 "material_marigo_non_local.hh"
 #include "non_local_neighborhood_base.hh"
 /* -------------------------------------------------------------------------- */
-#if defined(AKANTU_DEBUG_TOOLS)
-#include "aka_debug_tools.hh"
-#include <string>
-#endif
-/* -------------------------------------------------------------------------- */
-
-#ifndef __AKANTU_MATERIAL_MARIGO_NON_LOCAL_INLINE_IMPL_CC__
-#define __AKANTU_MATERIAL_MARIGO_NON_LOCAL_INLINE_IMPL_CC__
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialMarigoNonLocal<spatial_dimension>::MaterialMarigoNonLocal(
     SolidMechanicsModel & model, const ID & id)
     : MaterialMarigoNonLocalParent(model, id),
       Y("Y", *this), Ynl("Y non local", *this) {
   AKANTU_DEBUG_IN();
   this->is_non_local = true;
   this->Y.initialize(1);
   this->Ynl.initialize(1);
   this->model.registerNonLocalVariable(this->Y.getName(), Ynl.getName(), 1);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMarigoNonLocal<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
   MaterialMarigoNonLocalParent::initMaterial();
   this->model.getNeighborhood(this->name).registerNonLocalVariable(Ynl.getName());
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMarigoNonLocal<spatial_dimension>::computeStress(
     ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Real * dam = this->damage(el_type, ghost_type).storage();
   Real * Yt = this->Y(el_type, ghost_type).storage();
   Real * Ydq = this->Yd(el_type, ghost_type).storage();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
   MaterialMarigo<spatial_dimension>::computeStressOnQuad(grad_u, sigma, *dam,
                                                          *Yt, *Ydq);
   ++dam;
   ++Yt;
   ++Ydq;
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMarigoNonLocal<spatial_dimension>::computeNonLocalStress(
     ElementType type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Real * dam = this->damage(type, ghost_type).storage();
   Real * Ydq = this->Yd(type, ghost_type).storage();
   Real * Ynlt = this->Ynl(type, ghost_type).storage();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(type, ghost_type);
   this->computeDamageAndStressOnQuad(sigma, *dam, *Ynlt, *Ydq);
 
   ++dam;
   ++Ynlt;
   ++Ydq;
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
-} // namespace akantu
+INSTANTIATE_MATERIAL(marigo_non_local, MaterialMarigoNonLocal);
 
-#endif /* __AKANTU_MATERIAL_MARIGO_NON_LOCAL_INLINE_IMPL_CC__ */
+} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh
index 76e170825..17743144b 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh
@@ -1,98 +1,96 @@
 /**
  * @file   material_marigo_non_local.hh
  *
  * @author Marion Estelle Chambart <marion.chambart@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  Marigo non-local description
  *
  * @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_common.hh"
 #include "material_damage_non_local.hh"
 #include "material_marigo.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH__
 #define __AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH__
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 
 /**
  * Material Marigo
  *
  * parameters in the material files :
  */
 template <UInt spatial_dimension>
 class MaterialMarigoNonLocal
     : public MaterialDamageNonLocal<spatial_dimension,
                                     MaterialMarigo<spatial_dimension>> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   typedef MaterialDamageNonLocal<spatial_dimension,
                                  MaterialMarigo<spatial_dimension>>
       MaterialMarigoNonLocalParent;
   MaterialMarigoNonLocal(SolidMechanicsModel & model, const ID & id = "");
 
   virtual ~MaterialMarigoNonLocal(){};
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   void initMaterial();
 
 protected:
   /// constitutive law
   void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
 
   void computeNonLocalStress(ElementType type,
                              GhostType ghost_type = _not_ghost);
 
 private:
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Y, Y, Real);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   InternalField<Real> Y;
   InternalField<Real> Ynl;
 };
 
 } // namespace akantu
 
-#include "material_marigo_non_local_inline_impl.cc"
-
 #endif /* __AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars.cc b/src/model/solid_mechanics/materials/material_damage/material_mazars.cc
index 52e5ddfbf..fdba78438 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_mazars.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_mazars.cc
@@ -1,82 +1,82 @@
 /**
  * @file   material_mazars.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Marion Estelle Chambart <marion.chambart@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Tue Aug 18 2015
  *
  * @brief  Specialization of the material class for the damage material
  *
  * @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 "material_mazars.hh"
 #include "solid_mechanics_model.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialMazars<spatial_dimension>::MaterialMazars(SolidMechanicsModel & model,
                                                   const ID & id)
     : MaterialDamage<spatial_dimension>(model, id), K0("K0", *this),
       damage_in_compute_stress(true) {
   AKANTU_DEBUG_IN();
 
   this->registerParam("K0", K0, _pat_parsable, "K0");
   this->registerParam("At", At, Real(0.8), _pat_parsable, "At");
   this->registerParam("Ac", Ac, Real(1.4), _pat_parsable, "Ac");
   this->registerParam("Bc", Bc, Real(1900.), _pat_parsable, "Bc");
   this->registerParam("Bt", Bt, Real(12000.), _pat_parsable, "Bt");
   this->registerParam("beta", beta, Real(1.06), _pat_parsable, "beta");
 
   this->K0.initialize(1);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMazars<spatial_dimension>::computeStress(ElementType el_type,
                                                       GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Real * dam = this->damage(el_type, ghost_type).storage();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Real Ehat = 0;
   computeStressOnQuad(grad_u, sigma, *dam, Ehat);
   ++dam;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialMazars);
+INSTANTIATE_MATERIAL(mazars, MaterialMazars);
 
 } // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc
index 93d3211d3..07e1f2a05 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc
@@ -1,147 +1,147 @@
 /**
  * @file   material_mazars_non_local.cc
  *
  * @author Marion Estelle Chambart <marion.chambart@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  Specialization of the material class for the non-local mazars
  * material
  *
  * @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 "material_mazars_non_local.hh"
 #include "solid_mechanics_model.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialMazarsNonLocal<spatial_dimension>::MaterialMazarsNonLocal(
     SolidMechanicsModel & model, const ID & id)
     : MaterialNonLocalParent(model, id), Ehat("epsilon_equ", *this) {
   AKANTU_DEBUG_IN();
 
   this->is_non_local = true;
   this->Ehat.initialize(1);
 
   this->registerParam("average_on_damage", this->damage_in_compute_stress,
                       false, _pat_parsable | _pat_modifiable,
                       "Is D the non local variable");
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMazarsNonLocal<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
   MaterialNonLocalParent::initMaterial();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMazarsNonLocal<spatial_dimension>::computeStress(
     ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Real * damage = this->damage(el_type, ghost_type).storage();
   Real * epsilon_equ = this->Ehat(el_type, ghost_type).storage();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   MaterialMazars<spatial_dimension>::computeStressOnQuad(grad_u, sigma, *damage,
                                                          *epsilon_equ);
   ++damage;
   ++epsilon_equ;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMazarsNonLocal<spatial_dimension>::computeNonLocalStresses(
     __attribute__((unused)) GhostType ghost_type) {
   AKANTU_DEBUG_IN();
   InternalField<Real> nl_var("Non local variable", *this);
   nl_var.initialize(1);
 
   // if(this->damage_in_compute_stress)
   //   this->weightedAvergageOnNeighbours(this->damage, nl_var, 1);
   // else
   //   this->weightedAvergageOnNeighbours(this->Ehat, nl_var, 1);
 
   // Mesh::type_iterator it =
   // this->model->getFEEngine().getMesh().firstType(spatial_dimension,
   // ghost_type);
   // Mesh::type_iterator last_type =
   // this->model->getFEEngine().getMesh().lastType(spatial_dimension,
   // ghost_type);
   // for(; it != last_type; ++it) {
   //   this->computeNonLocalStress(nl_var(*it, ghost_type), *it, ghost_type);
   // }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMazarsNonLocal<spatial_dimension>::computeNonLocalStress(
     Array<Real> & non_loc_var, ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Real * damage;
   Real * epsilon_equ;
   if (this->damage_in_compute_stress) {
     damage = non_loc_var.storage();
     epsilon_equ = this->Ehat(el_type, ghost_type).storage();
   } else {
     damage = this->damage(el_type, ghost_type).storage();
     epsilon_equ = non_loc_var.storage();
   }
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
   this->computeDamageAndStressOnQuad(grad_u, sigma, *damage, *epsilon_equ);
 
   ++damage;
   ++epsilon_equ;
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialMazarsNonLocal<
     spatial_dimension>::nonLocalVariableToNeighborhood() {}
 
-INSTANTIATE_MATERIAL(MaterialMazarsNonLocal);
+INSTANTIATE_MATERIAL(mazars_non_local, MaterialMazarsNonLocal);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_elastic.cc b/src/model/solid_mechanics/materials/material_elastic.cc
index 34a25ce7d..b108afe8b 100644
--- a/src/model/solid_mechanics/materials/material_elastic.cc
+++ b/src/model/solid_mechanics/materials/material_elastic.cc
@@ -1,254 +1,254 @@
 /**
  * @file   material_elastic.cc
  *
  * @author Lucas Frerot <lucas.frerot@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: Thu Oct 15 2015
  *
  * @brief  Specialization of the material class for the elastic material
  *
  * @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 "material_elastic.hh"
 #include "solid_mechanics_model.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model,
                                       const ID & id)
     : Parent(model, id), was_stiffness_assembled(false) {
   AKANTU_DEBUG_IN();
   this->initialize();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model,
                                       __attribute__((unused)) UInt a_dim,
                                       const Mesh & mesh, FEEngine & fe_engine,
                                       const ID & id)
     : Parent(model, dim, mesh, fe_engine, id), was_stiffness_assembled(false) {
   AKANTU_DEBUG_IN();
   this->initialize();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim> void MaterialElastic<dim>::initialize() {
   this->registerParam("lambda", lambda, _pat_readable,
                       "First Lamé coefficient");
   this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient");
   this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient");
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim> void MaterialElastic<dim>::initMaterial() {
   AKANTU_DEBUG_IN();
   Parent::initMaterial();
 
   if (dim == 1)
     this->nu = 0.;
 
   this->updateInternalParameters();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim> void MaterialElastic<dim>::updateInternalParameters() {
   MaterialThermal<dim>::updateInternalParameters();
 
   this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu));
   this->mu = this->E / (2 * (1 + this->nu));
 
   this->kpa = this->lambda + 2. / 3. * this->mu;
 
   this->was_stiffness_assembled = false;
 }
 
 /* -------------------------------------------------------------------------- */
 template <> void MaterialElastic<2>::updateInternalParameters() {
   MaterialThermal<2>::updateInternalParameters();
 
   this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu));
   this->mu = this->E / (2 * (1 + this->nu));
 
   if (this->plane_stress)
     this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - this->nu));
 
   this->kpa = this->lambda + 2. / 3. * this->mu;
 
   this->was_stiffness_assembled = false;
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialElastic<spatial_dimension>::computeStress(ElementType el_type,
                                                        GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Parent::computeStress(el_type, ghost_type);
 
   Array<Real>::const_scalar_iterator sigma_th_it =
       this->sigma_th(el_type, ghost_type).begin();
 
   if (!this->finite_deformation) {
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
     const Real & sigma_th = *sigma_th_it;
     this->computeStressOnQuad(grad_u, sigma, sigma_th);
     ++sigma_th_it;
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   } else {
     /// finite gradus
     Matrix<Real> E(spatial_dimension, spatial_dimension);
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
     /// compute E
     this->template gradUToGreenStrain<spatial_dimension>(grad_u, E);
 
     const Real & sigma_th = *sigma_th_it;
 
     /// compute second Piola-Kirchhoff stress tensor
     this->computeStressOnQuad(E, sigma, sigma_th);
 
     ++sigma_th_it;
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialElastic<spatial_dimension>::computeTangentModuli(
     const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
   this->computeTangentModuliOnQuad(tangent);
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
 
   this->was_stiffness_assembled = true;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 Real MaterialElastic<spatial_dimension>::getPushWaveSpeed(
     const Element &) const {
   return sqrt((lambda + 2 * mu) / this->rho);
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 Real MaterialElastic<spatial_dimension>::getShearWaveSpeed(
     const Element &) const {
   return sqrt(mu / this->rho);
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialElastic<spatial_dimension>::computePotentialEnergy(
     ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MaterialThermal<spatial_dimension>::computePotentialEnergy(el_type,
                                                              ghost_type);
 
   if (ghost_type != _not_ghost)
     return;
 
   auto epot = this->potential_energy(el_type, ghost_type).begin();
 
   if (!this->finite_deformation) {
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
     this->computePotentialEnergyOnQuad(grad_u, sigma, *epot);
     ++epot;
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   } else {
     Matrix<Real> E(spatial_dimension, spatial_dimension);
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
     this->template gradUToGreenStrain<spatial_dimension>(grad_u, E);
 
     this->computePotentialEnergyOnQuad(E, sigma, *epot);
     ++epot;
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialElastic<spatial_dimension>::computePotentialEnergyByElement(
     ElementType type, UInt index, Vector<Real> & epot_on_quad_points) {
   auto gradu_it = this->gradu(type).begin(spatial_dimension, spatial_dimension);
   auto gradu_end =
       this->gradu(type).begin(spatial_dimension, spatial_dimension);
   auto stress_it =
       this->stress(type).begin(spatial_dimension, spatial_dimension);
 
   if (this->finite_deformation)
     stress_it = this->piola_kirchhoff_2(type).begin(spatial_dimension,
                                                     spatial_dimension);
 
   UInt nb_quadrature_points =
       this->fem.getNbIntegrationPoints(type);
 
   gradu_it += index * nb_quadrature_points;
   gradu_end += (index + 1) * nb_quadrature_points;
   stress_it += index * nb_quadrature_points;
 
   Real * epot_quad = epot_on_quad_points.storage();
 
   Matrix<Real> grad_u(spatial_dimension, spatial_dimension);
 
   for (; gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) {
 
     if (this->finite_deformation)
       this->template gradUToGreenStrain<spatial_dimension>(*gradu_it, grad_u);
     else
       grad_u.copy(*gradu_it);
 
     this->computePotentialEnergyOnQuad(grad_u, *stress_it, *epot_quad);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialElastic);
+INSTANTIATE_MATERIAL(elastic, MaterialElastic);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc
index 3780a6fea..89ef1e5c9 100644
--- a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc
+++ b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc
@@ -1,313 +1,313 @@
 /**
  * @file   material_elastic_linear_anisotropic.cc
  *
  * @author Till Junge <till.junge@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Sep 25 2013
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  Anisotropic elastic material
  *
  * @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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 #include "material_elastic_linear_anisotropic.hh"
 #include "solid_mechanics_model.hh"
 #include <algorithm>
 #include <sstream>
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 MaterialElasticLinearAnisotropic<dim>::MaterialElasticLinearAnisotropic(
     SolidMechanicsModel & model, const ID & id, bool symmetric)
     : Material(model, id), rot_mat(dim, dim), Cprime(dim * dim, dim * dim),
       C(voigt_h::size, voigt_h::size), eigC(voigt_h::size),
       symmetric(symmetric), alpha(0), was_stiffness_assembled(false) {
   AKANTU_DEBUG_IN();
 
   this->dir_vecs.push_back(new Vector<Real>(dim));
   (*this->dir_vecs.back())[0] = 1.;
   this->registerParam("n1", *(this->dir_vecs.back()), _pat_parsmod,
                       "Direction of main material axis");
   this->dir_vecs.push_back(new Vector<Real>(dim));
   (*this->dir_vecs.back())[1] = 1.;
   this->registerParam("n2", *(this->dir_vecs.back()), _pat_parsmod,
                       "Direction of secondary material axis");
 
   if (dim > 2) {
     this->dir_vecs.push_back(new Vector<Real>(dim));
     (*this->dir_vecs.back())[2] = 1.;
     this->registerParam("n3", *(this->dir_vecs.back()), _pat_parsmod,
                         "Direction of tertiary material axis");
   }
 
   for (UInt i = 0; i < voigt_h::size; ++i) {
     UInt start = 0;
     if (this->symmetric) {
       start = i;
     }
     for (UInt j = start; j < voigt_h::size; ++j) {
       std::stringstream param("C");
       param << "C" << i + 1 << j + 1;
       this->registerParam(param.str(), this->Cprime(i, j), Real(0.),
                           _pat_parsmod, "Coefficient " + param.str());
     }
   }
 
   this->registerParam("alpha", this->alpha, _pat_parsmod,
                       "Proportion of viscous stress");
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 MaterialElasticLinearAnisotropic<dim>::~MaterialElasticLinearAnisotropic() {
   for (UInt i = 0; i < dim; ++i) {
     delete this->dir_vecs[i];
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim> void MaterialElasticLinearAnisotropic<dim>::initMaterial() {
   AKANTU_DEBUG_IN();
   Material::initMaterial();
 
   updateInternalParameters();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void MaterialElasticLinearAnisotropic<dim>::updateInternalParameters() {
   Material::updateInternalParameters();
   if (this->symmetric) {
     for (UInt i = 0; i < voigt_h::size; ++i) {
       for (UInt j = i + 1; j < voigt_h::size; ++j) {
         this->Cprime(j, i) = this->Cprime(i, j);
       }
     }
   }
   this->rotateCprime();
   this->C.eig(this->eigC);
 
   this->was_stiffness_assembled = false;
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt Dim> void MaterialElasticLinearAnisotropic<Dim>::rotateCprime() {
   // start by filling the empty parts fo Cprime
   UInt diff = Dim * Dim - voigt_h::size;
   for (UInt i = voigt_h::size; i < Dim * Dim; ++i) {
     for (UInt j = 0; j < Dim * Dim; ++j) {
       this->Cprime(i, j) = this->Cprime(i - diff, j);
     }
   }
   for (UInt i = 0; i < Dim * Dim; ++i) {
     for (UInt j = voigt_h::size; j < Dim * Dim; ++j) {
       this->Cprime(i, j) = this->Cprime(i, j - diff);
     }
   }
   // construction of rotator tensor
   // normalise rotation matrix
   for (UInt j = 0; j < Dim; ++j) {
     Vector<Real> rot_vec = this->rot_mat(j);
     rot_vec = *this->dir_vecs[j];
     rot_vec.normalize();
   }
 
   // make sure the vectors form a right-handed base
   Vector<Real> test_axis(3);
   Vector<Real> v1(3), v2(3), v3(3);
 
   if (Dim == 2) {
     for (UInt i = 0; i < Dim; ++i) {
       v1[i] = this->rot_mat(0, i);
       v2[i] = this->rot_mat(1, i);
       v3[i] = 0.;
     }
     v3[2] = 1.;
     v1[2] = 0.;
     v2[2] = 0.;
   } else if (Dim == 3) {
     v1 = this->rot_mat(0);
     v2 = this->rot_mat(1);
     v3 = this->rot_mat(2);
   }
 
   test_axis.crossProduct(v1, v2);
   test_axis -= v3;
   if (test_axis.norm() > 8 * std::numeric_limits<Real>::epsilon()) {
     AKANTU_DEBUG_ERROR("The axis vectors do not form a right-handed coordinate "
                        << "system. I. e., ||n1 x n2 - n3|| should be zero, but "
                        << "it is " << test_axis.norm() << ".");
   }
 
   // create the rotator and the reverse rotator
   Matrix<Real> rotator(Dim * Dim, Dim * Dim);
   Matrix<Real> revrotor(Dim * Dim, Dim * Dim);
   for (UInt i = 0; i < Dim; ++i) {
     for (UInt j = 0; j < Dim; ++j) {
       for (UInt k = 0; k < Dim; ++k) {
         for (UInt l = 0; l < Dim; ++l) {
           UInt I = voigt_h::mat[i][j];
           UInt J = voigt_h::mat[k][l];
           rotator(I, J) = this->rot_mat(k, i) * this->rot_mat(l, j);
           revrotor(I, J) = this->rot_mat(i, k) * this->rot_mat(j, l);
         }
       }
     }
   }
 
   // create the full rotated matrix
   Matrix<Real> Cfull(Dim * Dim, Dim * Dim);
   Cfull = rotator * Cprime * revrotor;
 
   for (UInt i = 0; i < voigt_h::size; ++i) {
     for (UInt j = 0; j < voigt_h::size; ++j) {
       this->C(i, j) = Cfull(i, j);
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void MaterialElasticLinearAnisotropic<dim>::computeStress(
     ElementType el_type, GhostType ghost_type) {
   // Wikipedia convention:
   // 2*eps_ij (i!=j) = voigt_eps_I
   // http://en.wikipedia.org/wiki/Voigt_notation
   AKANTU_DEBUG_IN();
 
   Array<Real>::iterator<Matrix<Real>> gradu_it =
       this->gradu(el_type, ghost_type).begin(dim, dim);
   Array<Real>::iterator<Matrix<Real>> gradu_end =
       this->gradu(el_type, ghost_type).end(dim, dim);
 
   UInt nb_quad_pts = gradu_end - gradu_it;
 
   // create array for strains and stresses of all dof of all gauss points
   // for efficient computation of stress
   Matrix<Real> voigt_strains(voigt_h::size, nb_quad_pts);
   Matrix<Real> voigt_stresses(voigt_h::size, nb_quad_pts);
 
   // copy strains
   Matrix<Real> strain(dim, dim);
 
   for (UInt q = 0; gradu_it != gradu_end; ++gradu_it, ++q) {
     Matrix<Real> & grad_u = *gradu_it;
 
     for (UInt I = 0; I < voigt_h::size; ++I) {
       Real voigt_factor = voigt_h::factors[I];
       UInt i = voigt_h::vec[I][0];
       UInt j = voigt_h::vec[I][1];
 
       voigt_strains(I, q) = voigt_factor * (grad_u(i, j) + grad_u(j, i)) / 2.;
     }
   }
 
   // compute the strain rate proportional part if needed
   // bool viscous = this->alpha == 0.; // only works if default value
   bool viscous = false;
   if (viscous) {
     Array<Real> strain_rate(0, dim * dim, "strain_rate");
 
     Array<Real> & velocity = this->model.getVelocity();
     const Array<UInt> & elem_filter = this->element_filter(el_type, ghost_type);
 
     this->fem.gradientOnIntegrationPoints(
         velocity, strain_rate, dim, el_type, ghost_type, elem_filter);
 
     Array<Real>::matrix_iterator gradu_dot_it = strain_rate.begin(dim, dim);
     Array<Real>::matrix_iterator gradu_dot_end = strain_rate.end(dim, dim);
 
     Matrix<Real> strain_dot(dim, dim);
     for (UInt q = 0; gradu_dot_it != gradu_dot_end; ++gradu_dot_it, ++q) {
       Matrix<Real> & grad_u_dot = *gradu_dot_it;
 
       for (UInt I = 0; I < voigt_h::size; ++I) {
         Real voigt_factor = voigt_h::factors[I];
         UInt i = voigt_h::vec[I][0];
         UInt j = voigt_h::vec[I][1];
 
         voigt_strains(I, q) = this->alpha * voigt_factor *
                               (grad_u_dot(i, j) + grad_u_dot(j, i)) / 2.;
       }
     }
   }
 
   // compute stresses
   voigt_stresses = this->C * voigt_strains;
 
   // copy stresses back
   Array<Real>::iterator<Matrix<Real>> stress_it =
       this->stress(el_type, ghost_type).begin(dim, dim);
 
   Array<Real>::iterator<Matrix<Real>> stress_end =
       this->stress(el_type, ghost_type).end(dim, dim);
 
   for (UInt q = 0; stress_it != stress_end; ++stress_it, ++q) {
     Matrix<Real> & stress = *stress_it;
 
     for (UInt I = 0; I < voigt_h::size; ++I) {
       UInt i = voigt_h::vec[I][0];
       UInt j = voigt_h::vec[I][1];
       stress(i, j) = stress(j, i) = voigt_stresses(I, q);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void MaterialElasticLinearAnisotropic<dim>::computeTangentModuli(
     const ElementType & el_type, Array<Real> & tangent_matrix,
     GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
   tangent.copy(this->C);
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
 
   this->was_stiffness_assembled = true;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 Real MaterialElasticLinearAnisotropic<dim>::getCelerity(
     __attribute__((unused)) const Element & element) const {
   return std::sqrt(this->eigC(0) / rho);
 }
 
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialElasticLinearAnisotropic);
+INSTANTIATE_MATERIAL(elastic_anisotropic, MaterialElasticLinearAnisotropic);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc
index 97c6db813..5b81ee1fe 100644
--- a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc
+++ b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc
@@ -1,213 +1,213 @@
 /**
  * @file   material_elastic_orthotropic.cc
  *
  * @author Till Junge <till.junge@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: Thu Oct 15 2015
  *
  * @brief  Orthotropic elastic material
  *
  * @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 "material_elastic_orthotropic.hh"
 #include "solid_mechanics_model.hh"
 #include <algorithm>
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template<UInt Dim>
 MaterialElasticOrthotropic<Dim>::MaterialElasticOrthotropic(SolidMechanicsModel & model,
                                                             const ID & id)  :
   Material(model, id),
   MaterialElasticLinearAnisotropic<Dim>(model, id) {
   AKANTU_DEBUG_IN();
   this->registerParam("E1",   E1  , Real(0.), _pat_parsmod, "Young's modulus (n1)");
   this->registerParam("E2",   E2  , Real(0.), _pat_parsmod, "Young's modulus (n2)");
   this->registerParam("nu12", nu12, Real(0.), _pat_parsmod, "Poisson's ratio (12)");
   this->registerParam("G12",  G12 , Real(0.), _pat_parsmod, "Shear modulus (12)");
 
   if (Dim > 2) {
     this->registerParam("E3"  , E3  , Real(0.), _pat_parsmod, "Young's modulus (n3)");
     this->registerParam("nu13", nu13, Real(0.), _pat_parsmod, "Poisson's ratio (13)");
     this->registerParam("nu23", nu23, Real(0.), _pat_parsmod, "Poisson's ratio (23)");
     this->registerParam("G13" , G13 , Real(0.), _pat_parsmod, "Shear modulus (13)");
     this->registerParam("G23" , G23 , Real(0.), _pat_parsmod, "Shear modulus (23)");
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt Dim>
 MaterialElasticOrthotropic<Dim>::~MaterialElasticOrthotropic() {
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt Dim>
 void MaterialElasticOrthotropic<Dim>::initMaterial() {
   AKANTU_DEBUG_IN();
   Material::initMaterial();
 
   updateInternalParameters();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 inline Real vector_norm(Vector<Real> & vec) {
   Real norm = 0;
   for (UInt i = 0 ;  i < vec.size() ; ++i) {
     norm += vec(i)*vec(i);
   }
   return std::sqrt(norm);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt Dim>
 void MaterialElasticOrthotropic<Dim>::updateInternalParameters() {
   /* 1) construction of temporary material frame stiffness tensor------------ */
   // http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
   Real nu21 = nu12 * E2 / E1;
   Real nu31 = nu13 * E3 / E1;
   Real nu32 = nu23 * E3 / E2;
 
   // Full (i.e. dim^2 by dim^2) stiffness tensor in material frame
   if (Dim == 1) {
     AKANTU_DEBUG_ERROR("Dimensions 1 not implemented: makes no sense to have orthotropy for 1D");
   }
 
   Real Gamma;
 
   if (Dim == 3)
     Gamma = 1/(1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 - 2 * nu21 * nu32 * nu13);
 
   if (Dim == 2)
     Gamma = 1/(1 - nu12 * nu21);
 
   // Lamé's first parameters
   this->Cprime(0, 0) = E1 * (1 - nu23 * nu32) * Gamma;
   this->Cprime(1, 1) = E2 * (1 - nu13 * nu31) * Gamma;
   if (Dim == 3)
     this->Cprime(2, 2) = E3 * (1 - nu12 * nu21) * Gamma;
 
   // normalised poisson's ratio's
   this->Cprime(1, 0) = this->Cprime(0, 1) = E1 * (nu21 + nu31 * nu23) * Gamma;
   if (Dim == 3) {
     this->Cprime(2, 0) = this->Cprime(0, 2) = E1 * (nu31 + nu21 * nu32) * Gamma;
     this->Cprime(2, 1) = this->Cprime(1, 2) = E2 * (nu32 + nu12 * nu31) * Gamma;
   }
 
   // Lamé's second parameters (shear moduli)
   if (Dim == 3) {
     this->Cprime(3, 3) = G23;
     this->Cprime(4, 4) = G13;
     this->Cprime(5, 5) = G12;
   }
   else
     this->Cprime(2, 2) = G12;
 
 
   /* 1) rotation of C into the global frame */
   this->rotateCprime();
   this->C.eig(this->eigC);
 
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 inline void MaterialElasticOrthotropic<dim>::computePotentialEnergyOnQuad(const Matrix<Real> & grad_u,
                                                                const Matrix<Real> & sigma,
                                                                Real & epot) {
   epot = .5 * sigma.doubleDot(grad_u);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialElasticOrthotropic<spatial_dimension>::computePotentialEnergy(ElementType el_type,
                                                                            GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Material::computePotentialEnergy(el_type, ghost_type);
   
   AKANTU_DEBUG_ASSERT(!this->finite_deformation,"finite deformation not possible in material orthotropic (TO BE IMPLEMENTED)");
 
 
   if(ghost_type != _not_ghost) return;
   Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   computePotentialEnergyOnQuad(grad_u, sigma, *epot);
   ++epot;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialElasticOrthotropic<spatial_dimension>::computePotentialEnergyByElement(ElementType type, UInt index,
 										    Vector<Real> & epot_on_quad_points) {
 
   AKANTU_DEBUG_ASSERT(!this->finite_deformation,"finite deformation not possible in material orthotropic (TO BE IMPLEMENTED)");
 
   Array<Real>::matrix_iterator gradu_it =
     this->gradu(type).begin(spatial_dimension,
                              spatial_dimension);
   Array<Real>::matrix_iterator gradu_end =
     this->gradu(type).begin(spatial_dimension,
                              spatial_dimension);
   Array<Real>::matrix_iterator stress_it =
     this->stress(type).begin(spatial_dimension,
                              spatial_dimension);
 
   UInt nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
 
   gradu_it  += index*nb_quadrature_points;
   gradu_end += (index+1)*nb_quadrature_points;
   stress_it  += index*nb_quadrature_points;
 
   Real * epot_quad = epot_on_quad_points.storage();
 
   Matrix<Real> grad_u(spatial_dimension, spatial_dimension);
 
   for(;gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) {
     grad_u.copy(*gradu_it);
 
     computePotentialEnergyOnQuad(grad_u, *stress_it, *epot_quad);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialElasticOrthotropic);
+INSTANTIATE_MATERIAL(elastic_orthotropic, MaterialElasticOrthotropic);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc
index 23bedea4a..b9af218c6 100644
--- a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc
+++ b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc
@@ -1,292 +1,292 @@
 /**
  * @file   material_neohookean.cc
  *
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  *
  * @date creation: Mon Apr 08 2013
  * @date last modification: Tue Aug 04 2015
  *
  * @brief  Specialization of the material class for finite deformation
  * neo-hookean material
  *
  * @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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_neohookean.hh"
 #include "solid_mechanics_model.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialNeohookean<spatial_dimension>::MaterialNeohookean(
     SolidMechanicsModel & model, const ID & id)
     : PlaneStressToolbox<spatial_dimension>(model, id) {
   AKANTU_DEBUG_IN();
 
   this->registerParam("E", E, Real(0.), _pat_parsable | _pat_modifiable,
                       "Young's modulus");
   this->registerParam("nu", nu, Real(0.5), _pat_parsable | _pat_modifiable,
                       "Poisson's ratio");
   this->registerParam("lambda", lambda, _pat_readable,
                       "First Lamé coefficient");
   this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient");
   this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient");
 
   this->finite_deformation = true;
   this->initialize_third_axis_deformation = true;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialNeohookean<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
   PlaneStressToolbox<spatial_dimension>::initMaterial();
   if (spatial_dimension == 1)
     nu = 0.;
   this->updateInternalParameters();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <> void MaterialNeohookean<2>::initMaterial() {
   AKANTU_DEBUG_IN();
   PlaneStressToolbox<2>::initMaterial();
   this->updateInternalParameters();
 
   if (this->plane_stress)
     this->third_axis_deformation.setDefaultValue(1.);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialNeohookean<spatial_dimension>::updateInternalParameters() {
   lambda = nu * E / ((1 + nu) * (1 - 2 * nu));
   mu = E / (2 * (1 + nu));
 
   kpa = lambda + 2. / 3. * mu;
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void MaterialNeohookean<dim>::computeCauchyStressPlaneStress(
     ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   PlaneStressToolbox<dim>::computeCauchyStressPlaneStress(el_type, ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void MaterialNeohookean<2>::computeCauchyStressPlaneStress(
     ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Array<Real>::matrix_iterator gradu_it =
       this->gradu(el_type, ghost_type).begin(2, 2);
 
   Array<Real>::matrix_iterator gradu_end =
       this->gradu(el_type, ghost_type).end(2, 2);
 
   Array<Real>::matrix_iterator piola_it =
       this->piola_kirchhoff_2(el_type, ghost_type).begin(2, 2);
 
   Array<Real>::matrix_iterator stress_it =
       this->stress(el_type, ghost_type).begin(2, 2);
 
   Array<Real>::const_scalar_iterator c33_it =
       this->third_axis_deformation(el_type, ghost_type).begin();
 
   Matrix<Real> F_tensor(2, 2);
 
   for (; gradu_it != gradu_end; ++gradu_it, ++piola_it, ++stress_it, ++c33_it) {
     Matrix<Real> & grad_u = *gradu_it;
     Matrix<Real> & piola = *piola_it;
     Matrix<Real> & sigma = *stress_it;
 
     gradUToF<2>(grad_u, F_tensor);
     computeCauchyStressOnQuad<2>(F_tensor, piola, sigma, *c33_it);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void MaterialNeohookean<dim>::computeStress(ElementType el_type,
                                             GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
   computeStressOnQuad(grad_u, sigma);
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void MaterialNeohookean<2>::computeStress(ElementType el_type,
                                           GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   if (this->plane_stress) {
     PlaneStressToolbox<2>::computeStress(el_type, ghost_type);
 
     Array<Real>::const_scalar_iterator c33_it =
         this->third_axis_deformation(el_type, ghost_type).begin();
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
     computeStressOnQuad(grad_u, sigma, *c33_it);
     ++c33_it;
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   } else {
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
     computeStressOnQuad(grad_u, sigma);
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void MaterialNeohookean<dim>::computeThirdAxisDeformation(
     __attribute__((unused)) ElementType el_type,
     __attribute__((unused)) GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void MaterialNeohookean<2>::computeThirdAxisDeformation(ElementType el_type,
                                                         GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(this->plane_stress, "The third component of the strain "
                                           "can only be computed for 2D "
                                           "problems in Plane Stress!!");
 
   Array<Real>::scalar_iterator c33_it =
       this->third_axis_deformation(el_type, ghost_type).begin();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
   computeThirdAxisDeformationOnQuad(grad_u, *c33_it);
   ++c33_it;
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialNeohookean<spatial_dimension>::computePotentialEnergy(
     ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Material::computePotentialEnergy(el_type, ghost_type);
 
   if (ghost_type != _not_ghost)
     return;
   Array<Real>::scalar_iterator epot =
       this->potential_energy(el_type, ghost_type).begin();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   computePotentialEnergyOnQuad(grad_u, *epot);
   ++epot;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialNeohookean<spatial_dimension>::computeTangentModuli(
     __attribute__((unused)) const ElementType & el_type,
     Array<Real> & tangent_matrix,
     __attribute__((unused)) GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
   computeTangentModuliOnQuad(tangent, grad_u);
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void MaterialNeohookean<2>::computeTangentModuli(__attribute__((unused))
                                                  const ElementType & el_type,
                                                  Array<Real> & tangent_matrix,
                                                  __attribute__((unused))
                                                  GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   if (this->plane_stress) {
     PlaneStressToolbox<2>::computeStress(el_type, ghost_type);
 
     Array<Real>::const_scalar_iterator c33_it =
         this->third_axis_deformation(el_type, ghost_type).begin();
 
     MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
     computeTangentModuliOnQuad(tangent, grad_u, *c33_it);
     ++c33_it;
     MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
 
   } else {
 
     MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
     computeTangentModuliOnQuad(tangent, grad_u);
     MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 Real MaterialNeohookean<spatial_dimension>::getPushWaveSpeed(
     __attribute__((unused)) const Element & element) const {
   return sqrt((this->lambda + 2 * this->mu) / this->rho);
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 Real MaterialNeohookean<spatial_dimension>::getShearWaveSpeed(
     __attribute__((unused)) const Element & element) const {
   return sqrt(this->mu / this->rho);
 }
 
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialNeohookean);
+INSTANTIATE_MATERIAL(neohookean, MaterialNeohookean);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_non_local_tmpl.hh b/src/model/solid_mechanics/materials/material_non_local_tmpl.hh
index 0ec5feca7..7b9d6f66a 100644
--- a/src/model/solid_mechanics/materials/material_non_local_tmpl.hh
+++ b/src/model/solid_mechanics/materials/material_non_local_tmpl.hh
@@ -1,132 +1,133 @@
 /**
  * @file   material_non_local.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Sat Sep 26 2015
  * @date last modification: Tue Dec 08 2015
  *
  * @brief  Implementation of material non-local
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "material.hh"
 #include "material_non_local.hh"
 #include "non_local_neighborhood.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim, class LocalParent>
 MaterialNonLocal<dim, LocalParent>::MaterialNonLocal(
     SolidMechanicsModel & model, const ID & id)
     : LocalParent(model, id) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim, class LocalParent>
 void MaterialNonLocal<dim, LocalParent>::initMaterial() {
   MaterialNonLocalInterface::initMaterial();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim, class LocalParent>
 void MaterialNonLocal<dim, LocalParent>::insertIntegrationPointsInNeighborhoods(
     const GhostType & ghost_type,
     const ElementTypeMapReal & quadrature_points_coordinates) {
 
   IntegrationPoint q;
   q.ghost_type = ghost_type;
   q.kind = _ek_regular;
 
+  auto & neighborhood = this->model.getNeighborhood(this->name);
+
   for (auto & type :
        this->element_filter.elementTypes(dim, ghost_type, _ek_regular)) {
     q.type = type;
     const auto & elem_filter = this->element_filter(type, ghost_type);
     UInt nb_element = elem_filter.getSize();
 
     if (nb_element) {
       UInt nb_quad =
           this->getFEEngine().getNbIntegrationPoints(type, ghost_type);
 
       const auto & quads = quadrature_points_coordinates(type, ghost_type);
 
       auto nb_total_element =
           this->model.getMesh().getNbElement(type, ghost_type);
       auto quads_it = quads.begin_reinterpret(dim, nb_quad, nb_total_element);
       for (auto & elem : elem_filter) {
         Matrix<Real> quads = quads_it[elem];
         q.element = elem;
         for (UInt nq = 0; nq < nb_quad; ++nq) {
           q.num_point = nq;
           q.global_num = q.element * nb_quad + nq;
-          this->model.getNeighborhood(this->name)
-              .insertIntegrationPoint(q, quads(nq));
+          neighborhood.insertIntegrationPoint(q, quads(nq));
         }
       }
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim, class LocalParent>
 void MaterialNonLocal<dim, LocalParent>::updateNonLocalInternals(
     ElementTypeMapReal & non_local_flattened, const ID & field_id,
     const GhostType & ghost_type, const ElementKind & kind) {
 
   /// loop over all types in the material
   for (auto & el_type :
        this->element_filter.elementTypes(dim, ghost_type, kind)) {
     Array<Real> & internal =
         this->template getInternal<Real>(field_id)(el_type, ghost_type);
 
     auto & internal_flat = non_local_flattened(el_type, ghost_type);
     auto nb_component = internal_flat.getNbComponent();
 
     auto internal_it = internal.begin(nb_component);
     auto internal_flat_it = internal_flat.begin(nb_component);
 
     /// loop all elements for the given type
     const auto & filter = this->element_filter(el_type, ghost_type);
     UInt nb_quads =
         this->getFEEngine().getNbIntegrationPoints(el_type, ghost_type);
     for (auto & elem : filter) {
       for (UInt q = 0; q < nb_quads; ++q, ++internal_it) {
         UInt global_quad = elem * nb_quads + q;
         *internal_it = internal_flat_it[global_quad];
       }
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim, class LocalParent>
 void MaterialNonLocal<dim, LocalParent>::registerNeighborhood() {
   this->model.registerNeighborhood(this->name, this->name);
 }
 
 } // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc
index bc16a9186..f209f0d85 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc
+++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc
@@ -1,200 +1,200 @@
 /**
  * @file   material_linear_isotropic_hardening.cc
  *
  * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  * @author Benjamin Paccaud <benjamin.paccaud@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Mon Apr 07 2014
  * @date last modification: Tue Aug 18 2015
  *
  * @brief  Specialization of the material class for isotropic finite deformation
  * linear hardening plasticity
  *
  * @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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_linear_isotropic_hardening.hh"
 #include "solid_mechanics_model.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 MaterialLinearIsotropicHardening<dim>::MaterialLinearIsotropicHardening(
     SolidMechanicsModel & model, const ID & id)
     : MaterialPlastic<dim>(model, id) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialLinearIsotropicHardening<spatial_dimension>::
     MaterialLinearIsotropicHardening(SolidMechanicsModel & model, UInt dim,
                                      const Mesh & mesh, FEEngine & fe_engine,
                                      const ID & id)
     :  MaterialPlastic<spatial_dimension>(model, dim, mesh, fe_engine, id) {}
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialLinearIsotropicHardening<spatial_dimension>::computeStress(
     ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MaterialThermal<spatial_dimension>::computeStress(el_type, ghost_type);
   // infinitesimal and finite deformation
   auto sigma_th_it = this->sigma_th(el_type, ghost_type).begin();
 
   auto previous_sigma_th_it =
       this->sigma_th.previous(el_type, ghost_type).begin();
 
   auto previous_gradu_it = this->gradu.previous(el_type, ghost_type)
                                .begin(spatial_dimension, spatial_dimension);
 
   auto previous_stress_it = this->stress.previous(el_type, ghost_type)
                                 .begin(spatial_dimension, spatial_dimension);
 
   auto inelastic_strain_it = this->inelastic_strain(el_type, ghost_type)
                                  .begin(spatial_dimension, spatial_dimension);
 
   auto previous_inelastic_strain_it =
       this->inelastic_strain.previous(el_type, ghost_type)
           .begin(spatial_dimension, spatial_dimension);
 
   auto iso_hardening_it = this->iso_hardening(el_type, ghost_type).begin();
 
   auto previous_iso_hardening_it =
       this->iso_hardening.previous(el_type, ghost_type).begin();
 
   //
   // Finite Deformations
   //
   if (this->finite_deformation) {
     auto previous_piola_kirchhoff_2_it =
         this->piola_kirchhoff_2.previous(el_type, ghost_type)
             .begin(spatial_dimension, spatial_dimension);
 
     auto green_strain_it = this->green_strain(el_type, ghost_type)
                                .begin(spatial_dimension, spatial_dimension);
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
     auto & inelastic_strain_tensor = *inelastic_strain_it;
     auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it;
     auto & previous_grad_u = *previous_gradu_it;
     auto & previous_sigma = *previous_piola_kirchhoff_2_it;
 
     auto & green_strain = *green_strain_it;
     this->template gradUToGreenStrain<spatial_dimension>(grad_u, green_strain);
     Matrix<Real> previous_green_strain(spatial_dimension, spatial_dimension);
     this->template gradUToGreenStrain<spatial_dimension>(previous_grad_u,
                                                          previous_green_strain);
     Matrix<Real> F_tensor(spatial_dimension, spatial_dimension);
     this->template gradUToF<spatial_dimension>(grad_u, F_tensor);
 
     computeStressOnQuad(green_strain, previous_green_strain, sigma,
                         previous_sigma, inelastic_strain_tensor,
                         previous_inelastic_strain_tensor, *iso_hardening_it,
                         *previous_iso_hardening_it, *sigma_th_it,
                         *previous_sigma_th_it, F_tensor);
 
     ++sigma_th_it;
     ++inelastic_strain_it;
     ++iso_hardening_it;
     ++previous_sigma_th_it;
     //++previous_stress_it;
     ++previous_gradu_it;
     ++green_strain_it;
     ++previous_inelastic_strain_it;
     ++previous_iso_hardening_it;
     ++previous_piola_kirchhoff_2_it;
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   }
   // Infinitesimal deformations
   else {
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
     auto & inelastic_strain_tensor = *inelastic_strain_it;
     auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it;
     auto & previous_grad_u = *previous_gradu_it;
     auto & previous_sigma = *previous_stress_it;
 
     computeStressOnQuad(
         grad_u, previous_grad_u, sigma, previous_sigma, inelastic_strain_tensor,
         previous_inelastic_strain_tensor, *iso_hardening_it,
         *previous_iso_hardening_it, *sigma_th_it, *previous_sigma_th_it);
     ++sigma_th_it;
     ++inelastic_strain_it;
     ++iso_hardening_it;
     ++previous_sigma_th_it;
     ++previous_stress_it;
     ++previous_gradu_it;
     ++previous_inelastic_strain_it;
     ++previous_iso_hardening_it;
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialLinearIsotropicHardening<spatial_dimension>::computeTangentModuli(
     const ElementType & el_type, Array<Real> & tangent_matrix,
     GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   auto previous_gradu_it = this->gradu.previous(el_type, ghost_type)
                                .begin(spatial_dimension, spatial_dimension);
 
   auto previous_stress_it = this->stress.previous(el_type, ghost_type)
                                 .begin(spatial_dimension, spatial_dimension);
 
   auto iso_hardening = this->iso_hardening(el_type, ghost_type).begin();
 
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
 
   computeTangentModuliOnQuad(tangent, grad_u, *previous_gradu_it, sigma_tensor,
                              *previous_stress_it, *iso_hardening);
 
   ++previous_gradu_it;
   ++previous_stress_it;
   ++iso_hardening;
 
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
 
   this->was_stiffness_assembled = true;
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialLinearIsotropicHardening);
+INSTANTIATE_MATERIAL(plastic_linear_isotropic_hardening, MaterialLinearIsotropicHardening);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc
index a16772bf5..2f407b6e0 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc
+++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc
@@ -1,209 +1,209 @@
 /**
  * @file   material_plastic.cc
  *
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Mon Apr 07 2014
  * @date last modification: Tue Aug 18 2015
  *
  * @brief  Implemantation of the akantu::MaterialPlastic class
  *
  * @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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_plastic.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model,
                                                     const ID & id)
     : MaterialElastic<spatial_dimension>(model, id),
       iso_hardening("iso_hardening", *this),
       inelastic_strain("inelastic_strain", *this),
       plastic_energy("plastic_energy", *this),
       d_plastic_energy("d_plastic_energy", *this) {
   AKANTU_DEBUG_IN();
   this->initialize();
   AKANTU_DEBUG_OUT();
 }
 
 template <UInt spatial_dimension>
 MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model,
                                                     UInt dim, const Mesh & mesh,
                                                     FEEngine & fe_engine,
                                                     const ID & id)
     : MaterialElastic<spatial_dimension>(model, dim, mesh, fe_engine, id),
       iso_hardening("iso_hardening", *this, dim, fe_engine,
                     this->element_filter),
       inelastic_strain("inelastic_strain", *this, dim, fe_engine,
                        this->element_filter),
       plastic_energy("plastic_energy", *this, dim, fe_engine,
                      this->element_filter),
       d_plastic_energy("d_plastic_energy", *this, dim, fe_engine,
                        this->element_filter) {
   AKANTU_DEBUG_IN();
   this->initialize();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialPlastic<spatial_dimension>::initialize() {
   this->registerParam("h", h, Real(0.), _pat_parsable | _pat_modifiable,
                       "Hardening  modulus");
   this->registerParam("sigma_y", sigma_y, Real(0.),
                       _pat_parsable | _pat_modifiable, "Yield stress");
 
   this->iso_hardening.initialize(1);
   this->iso_hardening.initializeHistory();
 
   this->plastic_energy.initialize(1);
   this->d_plastic_energy.initialize(1);
 
   this->use_previous_stress = true;
   this->use_previous_gradu = true;
   this->use_previous_stress_thermal = true;
 
   this->inelastic_strain.initialize(spatial_dimension * spatial_dimension);
   this->inelastic_strain.initializeHistory();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 Real MaterialPlastic<spatial_dimension>::getEnergy(std::string type) {
   if (type == "plastic")
     return getPlasticEnergy();
   else
     return MaterialElastic<spatial_dimension>::getEnergy(type);
 
   return 0.;
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 Real MaterialPlastic<spatial_dimension>::getPlasticEnergy() {
   AKANTU_DEBUG_IN();
 
   Real penergy = 0.;
 
   for (auto & type :
        this->element_filter.elementTypes(spatial_dimension, _not_ghost)) {
     penergy +=
         this->fem.integrate(plastic_energy(type, _not_ghost), type, _not_ghost,
                             this->element_filter(type, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return penergy;
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialPlastic<spatial_dimension>::computePotentialEnergy(
     ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   if (ghost_type != _not_ghost)
     return;
 
   Array<Real>::scalar_iterator epot =
       this->potential_energy(el_type, ghost_type).begin();
 
   Array<Real>::const_iterator<Matrix<Real>> inelastic_strain_it =
       this->inelastic_strain(el_type, ghost_type)
           .begin(spatial_dimension, spatial_dimension);
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Matrix<Real> elastic_strain(spatial_dimension, spatial_dimension);
   elastic_strain.copy(grad_u);
   elastic_strain -= *inelastic_strain_it;
 
   MaterialElastic<spatial_dimension>::computePotentialEnergyOnQuad(
       elastic_strain, sigma, *epot);
 
   ++epot;
   ++inelastic_strain_it;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialPlastic<spatial_dimension>::updateEnergies(ElementType el_type,
                                                         GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MaterialElastic<spatial_dimension>::updateEnergies(el_type, ghost_type);
 
   Array<Real>::iterator<> pe_it =
       this->plastic_energy(el_type, ghost_type).begin();
 
   Array<Real>::iterator<> wp_it =
       this->d_plastic_energy(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Matrix<Real>> inelastic_strain_it =
       this->inelastic_strain(el_type, ghost_type)
           .begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::iterator<Matrix<Real>> previous_inelastic_strain_it =
       this->inelastic_strain.previous(el_type, ghost_type)
           .begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::matrix_iterator previous_sigma =
       this->stress.previous(el_type, ghost_type)
           .begin(spatial_dimension, spatial_dimension);
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Matrix<Real> delta_strain_it(*inelastic_strain_it);
   delta_strain_it -= *previous_inelastic_strain_it;
 
   Matrix<Real> sigma_h(sigma);
   sigma_h += *previous_sigma;
 
   *wp_it = .5 * sigma_h.doubleDot(delta_strain_it);
 
   *pe_it += *wp_it;
 
   ++pe_it;
   ++wp_it;
   ++inelastic_strain_it;
   ++previous_inelastic_strain_it;
   ++previous_sigma;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialPlastic);
+INSTANTIATE_MATERIAL_ONLY(MaterialPlastic);
 
 } // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_thermal.cc b/src/model/solid_mechanics/materials/material_thermal.cc
index f0491b3a0..171a5aee3 100644
--- a/src/model/solid_mechanics/materials/material_thermal.cc
+++ b/src/model/solid_mechanics/materials/material_thermal.cc
@@ -1,123 +1,123 @@
 /**
  * @file   material_thermal.cc
  *
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Tue Aug 04 2015
  *
  * @brief  Specialization of the material class for the thermal material
  *
  * @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 "material_thermal.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 MaterialThermal<spatial_dimension>::MaterialThermal(SolidMechanicsModel & model, const ID & id)  :
   Material(model, id),
   delta_T("delta_T", *this),
   sigma_th("sigma_th", *this),
   use_previous_stress_thermal(false) {
   AKANTU_DEBUG_IN();
   this->initialize();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 MaterialThermal<spatial_dimension>::MaterialThermal(SolidMechanicsModel & model,
                                                     UInt dim,
                                                     const Mesh & mesh,
                                                     FEEngine & fe_engine,
                                                     const ID & id) :
   Material(model, dim, mesh, fe_engine, id),
   delta_T("delta_T", *this, dim, fe_engine, this->element_filter),
   sigma_th("sigma_th", *this, dim, fe_engine, this->element_filter),
   use_previous_stress_thermal(false) {
   AKANTU_DEBUG_IN();
   this->initialize();
   AKANTU_DEBUG_OUT();
 }
 
 template<UInt spatial_dimension>
 void MaterialThermal<spatial_dimension>::initialize() {
   this->registerParam("E"      , E      , Real(0. ) , _pat_parsable | _pat_modifiable, "Young's modulus"        );
   this->registerParam("nu"     , nu     , Real(0.5) , _pat_parsable | _pat_modifiable, "Poisson's ratio"        );
   this->registerParam("alpha"  , alpha  , Real(0. ) , _pat_parsable | _pat_modifiable, "Thermal expansion coefficient");
   this->registerParam("delta_T", delta_T,             _pat_parsable | _pat_modifiable, "Uniform temperature field");
 
   delta_T.initialize(1);
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialThermal<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
   sigma_th.initialize(1);
 
 
   if(use_previous_stress_thermal) {
     sigma_th.initializeHistory();
   }
 
   Material::initMaterial();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void MaterialThermal<dim>::computeStress(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Array<Real>::iterator<> delta_t_it = this->delta_T(el_type, ghost_type).begin();
   Array<Real>::iterator<> sigma_th_it = this->sigma_th(el_type, ghost_type).begin();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   /// TODO : implement with the matrix alpha
   if (dim == 1) {
     *sigma_th_it = - this->E * this->alpha * *delta_t_it;
   }
   else {
     *sigma_th_it = - this->E/(1.-2.*this->nu) * this->alpha * *delta_t_it;
   }
 
   ++delta_t_it;
   ++sigma_th_it;
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 
-INSTANTIATE_MATERIAL(MaterialThermal);
+INSTANTIATE_MATERIAL_ONLY(MaterialThermal);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc
index 3ed32f2d6..9aac29ef4 100644
--- a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc
+++ b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc
@@ -1,295 +1,295 @@
 /**
  * @file   material_standard_linear_solid_deviatoric.cc
  *
  * @author David Simon Kammer <david.kammer@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Vladislav Yastrebov <vladislav.yastrebov@epfl.ch>
  *
  * @date creation: Wed May 04 2011
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  Material Visco-elastic
  *
  * @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 "material_standard_linear_solid_deviatoric.hh"
 #include "solid_mechanics_model.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 MaterialStandardLinearSolidDeviatoric<spatial_dimension>::MaterialStandardLinearSolidDeviatoric(SolidMechanicsModel & model, const ID & id)  :
   MaterialElastic<spatial_dimension>(model, id),
   stress_dev("stress_dev", *this),
   history_integral("history_integral", *this),
   dissipated_energy("dissipated_energy", *this) {
 
   AKANTU_DEBUG_IN();
 
   this->registerParam("Eta",  eta,   Real(1.), _pat_parsable | _pat_modifiable, "Viscosity");
   this->registerParam("Ev",   Ev,    Real(1.), _pat_parsable | _pat_modifiable, "Stiffness of the viscous element");
   this->registerParam("Einf", E_inf, Real(1.), _pat_readable, "Stiffness of the elastic element");
 
   UInt stress_size = spatial_dimension * spatial_dimension;
 
   this->stress_dev       .initialize(stress_size);
   this->history_integral .initialize(stress_size);
   this->dissipated_energy.initialize(1);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
   updateInternalParameters();
   MaterialElastic<spatial_dimension>::initMaterial();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::updateInternalParameters() {
   MaterialElastic<spatial_dimension>::updateInternalParameters();
   E_inf = this->E - this->Ev;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::setToSteadyState(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Array<Real> & stress_dev_vect  = stress_dev(el_type, ghost_type);
   Array<Real> & history_int_vect = history_integral(el_type, ghost_type);
 
   Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(spatial_dimension, spatial_dimension);
   Array<Real>::matrix_iterator history_int = history_int_vect.begin(spatial_dimension, spatial_dimension);
 
   /// Loop on all quadrature points
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Matrix<Real> & dev_s = *stress_d;
   Matrix<Real> & h = *history_int;
 
   /// Compute the first invariant of strain
   Real Theta = grad_u.trace();
 
   for (UInt i = 0; i < spatial_dimension; ++i)
     for (UInt j = 0; j < spatial_dimension; ++j) {
       dev_s(i, j) = 2 * this->mu * (.5 * (grad_u(i,j) + grad_u(j,i)) - 1./3. * Theta *(i == j));
       h(i, j) = 0.;
     }
 
   /// Save the deviator of stress
   ++stress_d;
   ++history_int;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Real tau = 0.;
   // if(std::abs(Ev) > std::numeric_limits<Real>::epsilon())
   tau = eta / Ev;
 
   Array<Real> & stress_dev_vect  = stress_dev(el_type, ghost_type);
   Array<Real> & history_int_vect = history_integral(el_type, ghost_type);
 
   Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(spatial_dimension, spatial_dimension);
   Array<Real>::matrix_iterator history_int = history_int_vect.begin(spatial_dimension, spatial_dimension);
 
   Matrix<Real> s(spatial_dimension, spatial_dimension);
 
   Real dt = this->model.getTimeStep();
   Real exp_dt_tau = exp( -dt/tau );
   Real exp_dt_tau_2 = exp( -.5*dt/tau );
 
   Matrix<Real> epsilon_d(spatial_dimension, spatial_dimension);
   Matrix<Real> epsilon_v(spatial_dimension, spatial_dimension);
 
   /// Loop on all quadrature points
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Matrix<Real> & dev_s = *stress_d;
   Matrix<Real> & h = *history_int;
 
   s.clear();
   sigma.clear();
 
   /// Compute the first invariant of strain
   Real gamma_inf = E_inf / this->E;
   Real gamma_v   = Ev    / this->E;
 
   this->template gradUToEpsilon<spatial_dimension>(grad_u, epsilon_d);
   Real Theta = epsilon_d.trace();
   epsilon_v.eye(Theta / Real(3.));
   epsilon_d -= epsilon_v;
 
   Matrix<Real> U_rond_prim(spatial_dimension, spatial_dimension);
 
   U_rond_prim.eye(gamma_inf * this->kpa * Theta);
 
   for (UInt i = 0; i < spatial_dimension; ++i)
     for (UInt j = 0; j < spatial_dimension; ++j) {
       s(i, j) = 2 * this->mu * epsilon_d(i, j);
       h(i, j)  = exp_dt_tau * h(i, j) + exp_dt_tau_2 * (s(i, j) - dev_s(i, j));
       dev_s(i, j) = s(i, j);
       sigma(i, j) =  U_rond_prim(i,j) + gamma_inf * s(i, j) + gamma_v * h(i, j);
     }
 
   /// Save the deviator of stress
   ++stress_d;
   ++history_int;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   this->updateDissipatedEnergy(el_type, ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::updateDissipatedEnergy(ElementType el_type,
 										      GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   // if(ghost_type == _ghost) return 0.;
   
   Real tau = 0.;
   tau = eta / Ev;
   Real * dis_energy = dissipated_energy(el_type, ghost_type).storage();
 
   Array<Real> & stress_dev_vect  = stress_dev(el_type, ghost_type);
   Array<Real> & history_int_vect = history_integral(el_type, ghost_type);
 
   Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(spatial_dimension, spatial_dimension);
   Array<Real>::matrix_iterator history_int = history_int_vect.begin(spatial_dimension, spatial_dimension);
 
   Matrix<Real> q(spatial_dimension, spatial_dimension);
   Matrix<Real> q_rate(spatial_dimension, spatial_dimension);
   Matrix<Real> epsilon_d(spatial_dimension, spatial_dimension);
   Matrix<Real> epsilon_v(spatial_dimension, spatial_dimension);
 
   Real dt = this->model.getTimeStep();
 
   Real gamma_v   = Ev / this->E;
   Real alpha = 1. / (2. * this->mu * gamma_v);
 
   /// Loop on all quadrature points
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Matrix<Real> & dev_s = *stress_d;
   Matrix<Real> & h = *history_int;
 
   /// Compute the first invariant of strain
   this->template gradUToEpsilon<spatial_dimension>(grad_u, epsilon_d);
 
   Real Theta = epsilon_d.trace();
   epsilon_v.eye(Theta / Real(3.));
   epsilon_d -= epsilon_v;
 
   q.copy(dev_s);
   q -= h;
   q *= gamma_v;
 
   q_rate.copy(dev_s);
   q_rate *= gamma_v;
   q_rate -= q;
   q_rate /= tau;
 
   for (UInt i = 0; i < spatial_dimension; ++i)
     for (UInt j = 0; j < spatial_dimension; ++j)
       *dis_energy +=  (epsilon_d(i, j) - alpha * q(i, j)) * q_rate(i, j) * dt;
 
 
   /// Save the deviator of stress
   ++stress_d;
   ++history_int;
   ++dis_energy;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getDissipatedEnergy() const {
   AKANTU_DEBUG_IN();
 
   Real de = 0.;
 
   /// integrate the dissipated energy for each type of elements
   for(auto & type : this->element_filter.elementTypes(spatial_dimension, _not_ghost)) {
     de += this->fem.integrate(dissipated_energy(type, _not_ghost), type,
                               _not_ghost, this->element_filter(type, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return de;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getDissipatedEnergy(ElementType type, UInt index) const {
   AKANTU_DEBUG_IN();
 
   UInt nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
   Array<Real>::const_vector_iterator it = this->dissipated_energy(type, _not_ghost).begin(nb_quadrature_points);
   UInt gindex = (this->element_filter(type, _not_ghost))(index);
 
   AKANTU_DEBUG_OUT();
   return this->fem.integrate(it[index], type, gindex);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getEnergy(std::string type) {
   if(type == "dissipated") return getDissipatedEnergy();
   else if(type == "dissipated_sls_deviatoric") return getDissipatedEnergy();
   else return MaterialElastic<spatial_dimension>::getEnergy(type);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getEnergy(std::string energy_id, ElementType type, UInt index) {
   if(energy_id == "dissipated") return getDissipatedEnergy(type, index);
   else if(energy_id == "dissipated_sls_deviatoric") return getDissipatedEnergy(type, index);
   else return MaterialElastic<spatial_dimension>::getEnergy(energy_id, type, index);
 }
 
 /* -------------------------------------------------------------------------- */
 
-INSTANTIATE_MATERIAL(MaterialStandardLinearSolidDeviatoric);
+INSTANTIATE_MATERIAL(sls_deviatoric, MaterialStandardLinearSolidDeviatoric);
 
 } // akantu
diff --git a/src/model/solid_mechanics/materials/random_internal_field.hh b/src/model/solid_mechanics/materials/random_internal_field.hh
index dcca9ecb8..c18402786 100644
--- a/src/model/solid_mechanics/materials/random_internal_field.hh
+++ b/src/model/solid_mechanics/materials/random_internal_field.hh
@@ -1,109 +1,109 @@
 /**
  * @file   random_internal_field.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Tue Dec 08 2015
  *
  * @brief  Random internal material parameter
  *
  * @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_common.hh"
 #include "aka_random_generator.hh"
 #include "internal_field.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_RANDOM_INTERNAL_FIELD_HH__
 #define __AKANTU_RANDOM_INTERNAL_FIELD_HH__
 
 namespace akantu {
 
 /**
  * class for the internal fields of materials with a random
  * distribution
  */
 template<typename T,
 	 template<typename> class BaseField = InternalField,
-	 template<typename> class Generator = RandGenerator>
+	 template<typename> class Generator = RandomGenerator>
 class RandomInternalField : public BaseField<T> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   RandomInternalField(const ID & id, Material & material);
 
   virtual ~RandomInternalField();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 private:
   RandomInternalField operator=(__attribute__((unused)) const RandomInternalField & other) {};
 
 public:
   AKANTU_GET_MACRO(RandomParameter, random_parameter, const RandomParameter<T>);
 
   /// initialize the field to a given number of component
   virtual void initialize(UInt nb_component);
 
   /// set the field to a given value
   void setDefaultValue(const T & value);
 
   /// set the specified random distribution to a given parameter
   void setRandomDistribution(const RandomParameter<T> & param);
 
   /// print the content
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
 protected:
   virtual void setArrayValues(T * begin, T * end);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   inline operator Real() const;
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   /// random parameter containing the distribution and base value
   RandomParameter<T> random_parameter;
 };
 
 
 /// standard output stream operator
 template<typename T>
 inline std::ostream & operator <<(std::ostream & stream, const RandomInternalField<T> & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 } // akantu
 
 #endif /* __AKANTU_RANDOM_INTERNAL_FIELD_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc
index 9a99735a5..5411d7e5c 100644
--- a/src/model/solid_mechanics/solid_mechanics_model.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model.cc
@@ -1,1546 +1,1260 @@
 /**
  * @file   solid_mechanics_model.cc
  *
  * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author David Simon Kammer <david.kammer@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Clement Roux <clement.roux@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Tue Jul 27 2010
  * @date last modification: Tue Jan 19 2016
  *
  * @brief  Implementation of the SolidMechanicsModel class
  *
  * @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 "solid_mechanics_model.hh"
-#include "aka_math.hh"
 
-#include "element_group.hh"
 #include "element_synchronizer.hh"
-#include "group_manager_inline_impl.cc"
-#include "material_non_local.hh"
 #include "sparse_matrix.hh"
 #include "static_communicator.hh"
 #include "synchronizer_registry.hh"
 
 #include "dumpable_inline_impl.hh"
 #ifdef AKANTU_USE_IOHELPER
-#include "dumper_element_partition.hh"
-#include "dumper_elemental_field.hh"
-#include "dumper_field.hh"
-#include "dumper_homogenizing_field.hh"
-#include "dumper_internal_material_field.hh"
-#include "dumper_iohelper.hh"
-#include "dumper_material_padders.hh"
 #include "dumper_paraview.hh"
 #endif
 
+#include "material_non_local.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 /**
  * A solid mechanics model need a mesh  and a dimension to be created. the model
  * by it  self can not  do a lot,  the good init  functions should be  called in
  * order to configure the model depending on what we want to do.
  *
  * @param  mesh mesh  representing  the model  we  want to  simulate
  * @param dim spatial  dimension of the problem, if dim =  0 (default value) the
  * dimension of the problem is assumed to be the on of the mesh
  * @param id an id to identify the model
  */
 SolidMechanicsModel::SolidMechanicsModel(Mesh & mesh, UInt dim, const ID & id,
                                          const MemoryID & memory_id)
     : Model(mesh, dim, id, memory_id), BoundaryCondition<SolidMechanicsModel>(),
       NonLocalManager(*this, id + ":non_local_manager", memory_id), f_m2a(1.0),
       displacement(nullptr), previous_displacement(nullptr),
       displacement_increment(nullptr), mass(nullptr), velocity(nullptr),
       acceleration(nullptr), external_force(nullptr), internal_force(nullptr),
       blocked_dofs(nullptr), current_position(nullptr), mass_matrix(nullptr),
       velocity_damping_matrix(nullptr), stiffness_matrix(nullptr),
       jacobian_matrix(nullptr), material_index("material index", id, memory_id),
       material_local_numbering("material local numbering", id, memory_id),
       material_selector(new DefaultMaterialSelector(material_index)),
       is_default_material_selector(true), increment_flag(false),
       are_materials_instantiated(false) { //, pbc_synch(nullptr) {
   AKANTU_DEBUG_IN();
 
   this->registerFEEngineObject<MyFEEngineType>("SolidMechanicsFEEngine", mesh,
                                                Model::spatial_dimension);
 
   this->mesh.registerEventHandler(*this);
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.registerDumper<DumperParaview>("paraview_all", id, true);
   this->mesh.addDumpMesh(mesh, Model::spatial_dimension, _not_ghost,
                          _ek_regular);
 #endif
 
   this->initDOFManager();
 
   this->registerDataAccessor(*this);
 
   if (this->mesh.isDistributed()) {
     auto & synchronizer = this->mesh.getElementSynchronizer();
     this->registerSynchronizer(synchronizer, _gst_material_id);
     this->registerSynchronizer(synchronizer, _gst_smm_mass);
     this->registerSynchronizer(synchronizer, _gst_smm_stress);
     this->registerSynchronizer(synchronizer, _gst_smm_boundary);
     this->registerSynchronizer(synchronizer, _gst_for_dump);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 SolidMechanicsModel::~SolidMechanicsModel() {
   AKANTU_DEBUG_IN();
 
   if (is_default_material_selector) {
     delete material_selector;
     material_selector = nullptr;
   }
 
   for (auto & internal : this->registered_internals) {
     delete internal.second;
   }
 
   //  delete pbc_synch;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::setTimeStep(Real time_step, const ID & solver_id) {
   Model::setTimeStep(time_step, solver_id);
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.getDumper().setTimeStep(time_step);
 #endif
 }
 
 /* -------------------------------------------------------------------------- */
 /* Initialization                                                             */
 /* -------------------------------------------------------------------------- */
 /**
  * This function groups  many of the initialization in on  function. For most of
  * basics  case the  function should  be  enough. The  functions initialize  the
  * model, the internal  vectors, set them to 0, and  depending on the parameters
  * it also initialize the explicit or implicit solver.
  *
  * @param material_file the  file containing the materials to  use
  * @param method the analysis method wanted.  See the akantu::AnalysisMethod for
  * the different possibilities
  */
 void SolidMechanicsModel::initFull(const ModelOptions & options) {
   Model::initFull(options);
 
   const SolidMechanicsModelOptions & smm_options =
       dynamic_cast<const SolidMechanicsModelOptions &>(options);
 
   this->method = smm_options.analysis_method;
 
   // initialize the vectors
   this->initArrays();
 
   if (!this->hasDefaultSolver())
     this->initNewSolver(this->method);
 
   // initialize pbc
   if (this->pbc_pair.size() != 0)
     this->initPBC();
 
   // initialize the materials
   if (this->parser->getLastParsedFile() != "") {
     this->instantiateMaterials();
   }
 
   if (!smm_options.no_init_materials) {
     this->initMaterials();
   }
 
   // if (increment_flag)
   this->initBC(*this, *displacement, *displacement_increment, *external_force);
   // else
   // this->initBC(*this, *displacement, *external_force);
 }
 
 /* -------------------------------------------------------------------------- */
 TimeStepSolverType SolidMechanicsModel::getDefaultSolverType() const {
   return _tsst_dynamic_lumped;
 }
 
 /* -------------------------------------------------------------------------- */
 ModelSolverOptions SolidMechanicsModel::getDefaultSolverOptions(
     const TimeStepSolverType & type) const {
   ModelSolverOptions options;
 
   switch (type) {
   case _tsst_dynamic_lumped: {
     options.non_linear_solver_type = _nls_lumped;
     options.integration_scheme_type["displacement"] = _ist_central_difference;
     options.solution_type["displacement"] = IntegrationScheme::_acceleration;
     break;
   }
   case _tsst_static: {
     options.non_linear_solver_type = _nls_newton_raphson;
     options.integration_scheme_type["displacement"] = _ist_pseudo_time;
     options.solution_type["displacement"] = IntegrationScheme::_not_defined;
     break;
   }
   case _tsst_dynamic: {
     if (this->method == _explicit_consistent_mass) {
       options.non_linear_solver_type = _nls_newton_raphson;
       options.integration_scheme_type["displacement"] = _ist_central_difference;
       options.solution_type["displacement"] = IntegrationScheme::_acceleration;
     } else {
       options.non_linear_solver_type = _nls_newton_raphson;
       options.integration_scheme_type["displacement"] = _ist_trapezoidal_rule_2;
       options.solution_type["displacement"] = IntegrationScheme::_displacement;
     }
     break;
   }
   }
 
   return options;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initNewSolver(const AnalysisMethod & method) {
   ID solver_name;
   TimeStepSolverType tss_type;
 
   this->method = method;
 
   switch (this->method) {
   case _explicit_lumped_mass: {
     solver_name = "explicit_lumped";
     tss_type = _tsst_dynamic_lumped;
     break;
   }
   case _explicit_consistent_mass: {
     solver_name = "explicit";
     tss_type = _tsst_dynamic;
     break;
   }
   case _static: {
     solver_name = "static";
     tss_type = _tsst_static;
     break;
   }
   case _implicit_dynamic: {
     solver_name = "implicit";
     tss_type = _tsst_dynamic;
     break;
   }
   }
 
   if (!this->hasSolver(solver_name)) {
     ModelSolverOptions options = this->getDefaultSolverOptions(tss_type);
     this->getNewSolver(solver_name, tss_type, options.non_linear_solver_type);
     this->setIntegrationScheme(solver_name, "displacement",
                                options.integration_scheme_type["displacement"],
                                options.solution_type["displacement"]);
     this->setDefaultSolver(solver_name);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 void SolidMechanicsModel::allocNodalField(Array<T> *& array, const ID & name) {
   if (array == nullptr) {
     UInt nb_nodes = mesh.getNbNodes();
     std::stringstream sstr_disp;
     sstr_disp << id << ":" << name;
 
     array =
         &(alloc<T>(sstr_disp.str(), nb_nodes, Model::spatial_dimension, T()));
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initSolver(
     TimeStepSolverType time_step_solver_type,
     __attribute__((unused)) NonLinearSolverType non_linear_solver_type) {
   DOFManager & dof_manager = this->getDOFManager();
 
   /* ------------------------------------------------------------------------ */
   // for alloc type of solvers
   this->allocNodalField(this->displacement, "displacement");
   this->allocNodalField(this->previous_displacement, "previous_displacement");
   this->allocNodalField(this->displacement_increment, "displacement_increment");
   this->allocNodalField(this->internal_force, "internal_force");
   this->allocNodalField(this->external_force, "external_force");
   this->allocNodalField(this->blocked_dofs, "blocked_dofs");
   this->allocNodalField(this->current_position, "current_position");
 
   /* ------------------------------------------------------------------------ */
   if (!dof_manager.hasDOFs("displacement")) {
     dof_manager.registerDOFs("displacement", *this->displacement, _dst_nodal);
     dof_manager.registerBlockedDOFs("displacement", *this->blocked_dofs);
     dof_manager.registerDOFsIncrement("displacement",
                                       *this->displacement_increment);
     dof_manager.registerDOFsPrevious("displacement",
                                      *this->previous_displacement);
   }
 
   /* ------------------------------------------------------------------------ */
   // for dynamic
   if (time_step_solver_type == _tsst_dynamic ||
       time_step_solver_type == _tsst_dynamic_lumped) {
     this->allocNodalField(this->velocity, "velocity");
     this->allocNodalField(this->acceleration, "acceleration");
 
     if (!dof_manager.hasDOFsDerivatives("displacement", 1)) {
       dof_manager.registerDOFsDerivative("displacement", 1, *this->velocity);
       dof_manager.registerDOFsDerivative("displacement", 2,
                                          *this->acceleration);
     }
   }
 
   if (time_step_solver_type == _tsst_dynamic ||
       time_step_solver_type == _tsst_static) {
     if (!dof_manager.hasMatrix("K")) {
       dof_manager.getNewMatrix("K", _symmetric);
     }
 
     if (!dof_manager.hasMatrix("J")) {
       dof_manager.getNewMatrix("J", "K");
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 // void SolidMechanicsModel::initParallel(MeshPartition & partition,
 //                                        DataAccessor<Element> * data_accessor)
 //                                        {
 //   AKANTU_DEBUG_IN();
 
 //   if (data_accessor == nullptr)
 //     data_accessor = this;
 //   synch_parallel = &createParallelSynch(partition, *data_accessor);
 
 //   synch_registry->registerSynchronizer(*synch_parallel, _gst_material_id);
 //   synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_mass);
 //   synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_stress);
 //   synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_boundary);
 //   synch_registry->registerSynchronizer(*synch_parallel, _gst_for_dump);
 
 //   AKANTU_DEBUG_OUT();
 // }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initFEEngineBoundary() {
   FEEngine & fem_boundary = getFEEngineBoundary();
   fem_boundary.initShapeFunctions(_not_ghost);
   fem_boundary.initShapeFunctions(_ghost);
 
   fem_boundary.computeNormalsOnIntegrationPoints(_not_ghost);
   fem_boundary.computeNormalsOnIntegrationPoints(_ghost);
 }
 
 /* -------------------------------------------------------------------------- */
 // void SolidMechanicsModel::initArraysPreviousDisplacment() {
 //   AKANTU_DEBUG_IN();
 
 //   this->setIncrementFlagOn();
 //   if (not this->previous_displacement) {
 //     this->allocNodalField(this->previous_displacement, spatial_dimension,
 //                           "previous_displacement");
 
 //     this->getDOFManager().registerDOFsPrevious("displacement",
 //                                                *this->previous_displacement);
 //   }
 
 //   AKANTU_DEBUG_OUT();
 // }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Allocate all the needed vectors. By  default their are not necessarily set to
  * 0
  */
 void SolidMechanicsModel::initArrays() {
   AKANTU_DEBUG_IN();
 
   for (auto ghost_type : ghost_types) {
     for (auto type : mesh.elementTypes(Model::spatial_dimension, ghost_type,
                                        _ek_not_defined)) {
       UInt nb_element = mesh.getNbElement(type, ghost_type);
       this->material_index.alloc(nb_element, 1, type, ghost_type);
       this->material_local_numbering.alloc(nb_element, 1, type, ghost_type);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Initialize the model,basically it  pre-compute the shapes, shapes derivatives
  * and jacobian
  *
  */
 void SolidMechanicsModel::initModel() {
   /// \todo add  the current position  as a parameter to  initShapeFunctions for
   /// large deformation
   getFEEngine().initShapeFunctions(_not_ghost);
   getFEEngine().initShapeFunctions(_ghost);
 }
 
 /* -------------------------------------------------------------------------- */
 // void SolidMechanicsModel::initPBC() {
 //   Model::initPBC();
 //   registerPBCSynchronizer();
 
 //   // as long as there are ones on the diagonal of the matrix, we can put
 //   // boudandary true for slaves
 //   std::map<UInt, UInt>::iterator it = pbc_pair.begin();
 //   std::map<UInt, UInt>::iterator end = pbc_pair.end();
 //   UInt dim = mesh.getSpatialDimension();
 //   while (it != end) {
 //     for (UInt i = 0; i < dim; ++i)
 //       (*blocked_dofs)((*it).first, i) = true;
 //     ++it;
 //   }
 // }
 
 // /* --------------------------------------------------------------------------
 // */
 // void SolidMechanicsModel::registerPBCSynchronizer() {
 //   pbc_synch = new PBCSynchronizer(pbc_pair);
 //   synch_registry->registerSynchronizer(*pbc_synch, _gst_smm_uv);
 //   synch_registry->registerSynchronizer(*pbc_synch, _gst_smm_mass);
 //   synch_registry->registerSynchronizer(*pbc_synch, _gst_smm_res);
 //   synch_registry->registerSynchronizer(*pbc_synch, _gst_for_dump);
 //   //  changeLocalEquationNumberForPBC(pbc_pair, mesh.getSpatialDimension());
 // }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleResidual() {
   AKANTU_DEBUG_IN();
 
   /* ------------------------------------------------------------------------ */
   // computes the internal forces
   this->assembleInternalForces();
 
   /* ------------------------------------------------------------------------ */
   this->getDOFManager().assembleToResidual("displacement",
                                            *this->external_force, 1);
   this->getDOFManager().assembleToResidual("displacement",
                                            *this->internal_force, -1);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleJacobian() {
   this->assembleStiffnessMatrix();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::predictor() { ++displacement_release; }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::corrector() { ++displacement_release; }
 
 /* -------------------------------------------------------------------------- */
 /**
  * This function computes the internal forces as F_{int} = \int_{\Omega} N
  * \sigma d\Omega@f$
  */
 void SolidMechanicsModel::assembleInternalForces() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_INFO("Assemble the internal forces");
 
   this->internal_force->clear();
 
   // compute the stresses of local elements
   AKANTU_DEBUG_INFO("Compute local stresses");
   for (auto & material : materials) {
     material->computeAllStresses(_not_ghost);
   }
 
 #ifdef AKANTU_DAMAGE_NON_LOCAL
   /* ------------------------------------------------------------------------ */
   /* Computation of the non local part */
   this->computeAllNonLocalStresses();
 #endif
 
   // communicate the stresses
   AKANTU_DEBUG_INFO("Send data for residual assembly");
   this->asynchronousSynchronize(_gst_smm_stress);
 
   // assemble the forces due to local stresses
   AKANTU_DEBUG_INFO("Assemble residual for local elements");
   for (auto & material : materials) {
     material->assembleInternalForces(_not_ghost);
   }
 
   // finalize communications
   AKANTU_DEBUG_INFO("Wait distant stresses");
   this->waitEndSynchronize(_gst_smm_stress);
 
   // assemble the stresses due to ghost elements
   AKANTU_DEBUG_INFO("Assemble residual for ghost elements");
   for (auto & material : materials) {
     material->assembleInternalForces(_ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleStiffnessMatrix() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_INFO("Assemble the new stiffness matrix.");
 
   // Check if materials need to recompute the matrix
   bool need_to_reassemble = false;
 
   for (auto & material : materials) {
     need_to_reassemble |= material->hasStiffnessMatrixChanged();
   }
 
   if (need_to_reassemble) {
     this->getDOFManager().getMatrix("K").clear();
 
     // call compute stiffness matrix on each local elements
     for (auto & material : materials) {
       material->assembleStiffnessMatrix(_not_ghost);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateCurrentPosition() {
   if (this->current_position_release == this->displacement_release)
     return;
 
   this->current_position->copy(this->mesh.getNodes());
 
   auto cpos_it = this->current_position->begin(Model::spatial_dimension);
   auto cpos_end = this->current_position->end(Model::spatial_dimension);
   auto disp_it = this->displacement->begin(Model::spatial_dimension);
 
   for (; cpos_it != cpos_end; ++cpos_it, ++disp_it) {
     *cpos_it += *disp_it;
   }
 
   this->current_position_release = this->displacement_release;
 }
 
 /* -------------------------------------------------------------------------- */
 const Array<Real> & SolidMechanicsModel::getCurrentPosition() {
   this->updateCurrentPosition();
   return *this->current_position;
 }
 
 /* -------------------------------------------------------------------------- */
 // void SolidMechanicsModel::initializeUpdateResidualData() {
 //   AKANTU_DEBUG_IN();
 //   UInt nb_nodes = mesh.getNbNodes();
 //   internal_force->resize(nb_nodes);
 
 //   /// copy the forces in residual for boundary conditions
 //   this->getDOFManager().assembleToResidual("displacement",
 //                                            *this->external_force);
 
 //   // start synchronization
 //   this->asynchronousSynchronize(_gst_smm_uv);
 //   this->waitEndSynchronize(_gst_smm_uv);
 
 //   this->updateCurrentPosition();
 
 //   AKANTU_DEBUG_OUT();
 // }
 
 /* -------------------------------------------------------------------------- */
 /* Explicit scheme                                                            */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 // void SolidMechanicsModel::computeStresses() {
 //   if (isExplicit()) {
 //     // start synchronization
 //     this->asynchronousSynchronize(_gst_smm_uv);
 //     this->waitEndSynchronize(_gst_smm_uv);
 
 //     // compute stresses on all local elements for each materials
 //     std::vector<Material *>::iterator mat_it;
 //     for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
 //       Material & mat = **mat_it;
 //       mat.computeAllStresses(_not_ghost);
 //     }
 
 // #ifdef AKANTU_DAMAGE_NON_LOCAL
 //     /* Computation of the non local part */
 //     this->non_local_manager->computeAllNonLocalStresses();
 // #endif
 //   } else {
 //     std::vector<Material *>::iterator mat_it;
 //     for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
 //       Material & mat = **mat_it;
 //       mat.computeAllStressesFromTangentModuli(_not_ghost);
 //     }
 //   }
 // }
 
 /* -------------------------------------------------------------------------- */
 /* Implicit scheme                                                            */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 // /**
 //  * Initialize the solver and create the sparse matrices needed.
 //  *
 //  */
 // void SolidMechanicsModel::initSolver(__attribute__((unused))
 //                                      SolverOptions & options) {
 //   UInt nb_global_nodes = mesh.getNbGlobalNodes();
 
 //   jacobian_matrix = &(this->getDOFManager().getNewMatrix("jacobian",
 //   _symmetric));
 
 //   //  jacobian_matrix->buildProfile(mesh, *dof_synchronizer,
 //   spatial_dimension);
 
 //   if (!isExplicit()) {
 //     delete stiffness_matrix;
 //     std::stringstream sstr_sti;
 //     sstr_sti << id << ":stiffness_matrix";
 
 //     stiffness_matrix = &(this->getDOFManager().getNewMatrix("stiffness",
 //     _symmetric));
 //   }
 
 //   if (solver) solver->initialize(options);
 // }
 
 // /* --------------------------------------------------------------------------
 // */
 // void SolidMechanicsModel::initJacobianMatrix() {
 //   // @todo make it more flexible: this is an ugly patch to treat the case of
 //   non
 //   // fix profile of the K matrix
 //   delete jacobian_matrix;
 
 //   jacobian_matrix = &(this->getDOFManager().getNewMatrix("jacobian",
 //   "stiffness"));
 
 //   std::stringstream sstr_solv; sstr_solv << id << ":solver";
 //   delete solver;
 //   solver = new SolverMumps(*jacobian_matrix, sstr_solv.str());
 //   if(solver)
 //     solver->initialize(_solver_no_options);
 // }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Initialize the implicit solver, either for dynamic or static cases,
  *
  * @param dynamic
  */
 // void SolidMechanicsModel::initImplicit(bool dynamic) {
 //   AKANTU_DEBUG_IN();
 
 //   method = dynamic ? _implicit_dynamic : _static;
 
 //   if (!increment)
 //     setIncrementFlagOn();
 
 //   initSolver();
 
 //   // if(method == _implicit_dynamic) {
 //   //   if(integrator) delete integrator;
 //   //   integrator = new TrapezoidalRule2();
 //   // }
 
 //   AKANTU_DEBUG_OUT();
 // }
 
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 // SparseMatrix & SolidMechanicsModel::initVelocityDampingMatrix() {
 //   return this->getDOFManager().getNewMatrix("velocity_damping", "jacobian");
 // }
 
 // /* --------------------------------------------------------------------------
 // */
 // void SolidMechanicsModel::implicitPred() {
 //   AKANTU_DEBUG_IN();
 
 //   if(previous_displacement) previous_displacement->copy(*displacement);
 
 //   if(method == _implicit_dynamic)
 //     integrator->integrationSchemePred(time_step,
 //                                    *displacement,
 //                                    *velocity,
 //                                    *acceleration,
 //                                    *blocked_dofs);
 
 //   AKANTU_DEBUG_OUT();
 // }
 
 // /* --------------------------------------------------------------------------
 // */
 // void SolidMechanicsModel::implicitCorr() {
 //   AKANTU_DEBUG_IN();
 
 //   if(method == _implicit_dynamic) {
 //     integrator->integrationSchemeCorrDispl(time_step,
 //                                         *displacement,
 //                                         *velocity,
 //                                         *acceleration,
 //                                         *blocked_dofs,
 //                                         *increment);
 //   } else {
 //     UInt nb_nodes = displacement->getSize();
 //     UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes;
 
 //     Real * incr_val = increment->storage();
 //     Real * disp_val = displacement->storage();
 //     bool * boun_val = blocked_dofs->storage();
 
 //     for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++disp_val, ++incr_val,
 //     ++boun_val){
 //       *incr_val *= (1. - *boun_val);
 //       *disp_val += *incr_val;
 //     }
 //   }
 
 //   AKANTU_DEBUG_OUT();
 // }
 
 /* -------------------------------------------------------------------------- */
 // void SolidMechanicsModel::updateIncrement() {
 //   AKANTU_DEBUG_IN();
 
 //   auto incr_it = this->displacement_increment->begin(spatial_dimension);
 //   auto incr_end = this->displacement_increment->end(spatial_dimension);
 //   auto disp_it = this->displacement->begin(spatial_dimension);
 //   auto prev_disp_it = this->previous_displacement->begin(spatial_dimension);
 
 //   for (; incr_it != incr_end; ++incr_it) {
 //     *incr_it = *disp_it;
 //     *incr_it -= *prev_disp_it;
 //   }
 
 //   AKANTU_DEBUG_OUT();
 // }
 
 // /* --------------------------------------------------------------------------
 // */ void SolidMechanicsModel::updatePreviousDisplacement() {
 //   AKANTU_DEBUG_IN();
 
 //   AKANTU_DEBUG_ASSERT(
 //       previous_displacement,
 //       "The previous displacement has to be initialized."
 //           << " Are you working with Finite or Ineslactic deformations?");
 
 //   previous_displacement->copy(*displacement);
 
 //   AKANTU_DEBUG_OUT();
 // }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateDataForNonLocalCriterion(
     ElementTypeMapReal & criterion) {
   const ID field_name = criterion.getName();
   for (auto & material : materials) {
     if (!material->isInternal<Real>(field_name, _ek_regular))
       continue;
 
     for (auto ghost_type : ghost_types) {
       material->flattenInternal(field_name, criterion, ghost_type, _ek_regular);
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 /* Information                                                                */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 // void SolidMechanicsModel::synchronizeBoundaries() {
 //   AKANTU_DEBUG_IN();
 //   this->synchronize(_gst_smm_boundary);
 //   AKANTU_DEBUG_OUT();
 // }
 
 // /* --------------------------------------------------------------------------
 // */ void SolidMechanicsModel::synchronizeResidual() {
 //   AKANTU_DEBUG_IN();
 //   this->synchronize(_gst_smm_res);
 //   AKANTU_DEBUG_OUT();
 // }
 
 /* -------------------------------------------------------------------------- */
 // void SolidMechanicsModel::setIncrementFlagOn() {
 //   AKANTU_DEBUG_IN();
 
 //   if (!displacement_increment) {
 //     this->allocNodalField(displacement_increment, spatial_dimension,
 //                           "displacement_increment");
 
 //     this->getDOFManager().registerDOFsIncrement("displacement",
 //                                                 *this->displacement_increment);
 //   }
 
 //   increment_flag = true;
 
 //   AKANTU_DEBUG_OUT();
 // }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getStableTimeStep() {
   AKANTU_DEBUG_IN();
 
   Real min_dt = getStableTimeStep(_not_ghost);
 
   /// reduction min over all processors
   StaticCommunicator::getStaticCommunicator().allReduce(min_dt, _so_min);
 
   AKANTU_DEBUG_OUT();
   return min_dt;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getStableTimeStep(const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   Real min_dt = std::numeric_limits<Real>::max();
 
   this->updateCurrentPosition();
 
   Element elem;
   elem.ghost_type = ghost_type;
   elem.kind = _ek_regular;
 
   for (auto type :
        mesh.elementTypes(Model::spatial_dimension, ghost_type, _ek_regular)) {
     elem.type = type;
     UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
     UInt nb_element = mesh.getNbElement(type);
 
     auto mat_indexes = material_index(type, ghost_type).begin();
     auto mat_loc_num = material_local_numbering(type, ghost_type).begin();
 
     Array<Real> X(0, nb_nodes_per_element * Model::spatial_dimension);
     FEEngine::extractNodalToElementField(mesh, *current_position, X, type,
                                          _not_ghost);
 
     auto X_el = X.begin(Model::spatial_dimension, nb_nodes_per_element);
 
     for (UInt el = 0; el < nb_element;
          ++el, ++X_el, ++mat_indexes, ++mat_loc_num) {
       elem.element = *mat_loc_num;
       Real el_h = getFEEngine().getElementInradius(*X_el, type);
       Real el_c = this->materials[*mat_indexes]->getCelerity(elem);
       Real el_dt = el_h / el_c;
 
       min_dt = std::min(min_dt, el_dt);
     }
   }
 
   AKANTU_DEBUG_OUT();
   return min_dt;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getKineticEnergy() {
   AKANTU_DEBUG_IN();
 
   Real ekin = 0.;
   UInt nb_nodes = mesh.getNbNodes();
 
   if (this->getDOFManager().hasLumpedMatrix("M")) {
     auto m_it = this->mass->begin(Model::spatial_dimension);
     auto m_end = this->mass->end(Model::spatial_dimension);
     auto v_it = this->velocity->begin(Model::spatial_dimension);
 
     for (UInt n = 0; m_it != m_end; ++n, ++m_it, ++v_it) {
       const Vector<Real> & v = *v_it;
       const Vector<Real> & m = *m_it;
 
       Real mv2 = 0;
       bool is_local_node = mesh.isLocalOrMasterNode(n);
       // bool is_not_pbc_slave_node = !isPBCSlaveNode(n);
       bool count_node = is_local_node; // && is_not_pbc_slave_node;
       if (count_node) {
         for (UInt i = 0; i < Model::spatial_dimension; ++i) {
           if (m(i) > std::numeric_limits<Real>::epsilon())
             mv2 += v(i) * v(i) * m(i);
         }
       }
 
       ekin += mv2;
     }
   } else if (this->getDOFManager().hasMatrix("M")) {
     Array<Real> Mv(nb_nodes, Model::spatial_dimension);
     this->getDOFManager().getMatrix("M").matVecMul(*this->velocity, Mv);
 
     auto mv_it = Mv.begin(Model::spatial_dimension);
     auto mv_end = Mv.end(Model::spatial_dimension);
     auto v_it = this->velocity->begin(Model::spatial_dimension);
 
     for (; mv_it != mv_end; ++mv_it, ++v_it) {
       ekin += v_it->dot(*mv_it);
     }
   } else {
     AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix.");
   }
 
   StaticCommunicator::getStaticCommunicator().allReduce(ekin, _so_sum);
 
   AKANTU_DEBUG_OUT();
   return ekin * .5;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getKineticEnergy(const ElementType & type,
                                            UInt index) {
   AKANTU_DEBUG_IN();
 
   UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type);
 
   Array<Real> vel_on_quad(nb_quadrature_points, Model::spatial_dimension);
   Array<UInt> filter_element(1, 1, index);
 
   getFEEngine().interpolateOnIntegrationPoints(*velocity, vel_on_quad,
                                                Model::spatial_dimension, type,
                                                _not_ghost, filter_element);
 
   Array<Real>::vector_iterator vit =
       vel_on_quad.begin(Model::spatial_dimension);
   Array<Real>::vector_iterator vend = vel_on_quad.end(Model::spatial_dimension);
 
   Vector<Real> rho_v2(nb_quadrature_points);
 
   Real rho = materials[material_index(type)(index)]->getRho();
 
   for (UInt q = 0; vit != vend; ++vit, ++q) {
     rho_v2(q) = rho * vit->dot(*vit);
   }
 
   AKANTU_DEBUG_OUT();
 
   return .5 * getFEEngine().integrate(rho_v2, type, index);
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getExternalWork() {
   AKANTU_DEBUG_IN();
 
   auto incr_or_velo_it = this->velocity->begin(Model::spatial_dimension);
   if (this->method == _static) {
     incr_or_velo_it =
         this->displacement_increment->begin(Model::spatial_dimension);
   }
 
   auto ext_force_it = external_force->begin(Model::spatial_dimension);
   auto int_force_it = internal_force->begin(Model::spatial_dimension);
   auto boun_it = blocked_dofs->begin(Model::spatial_dimension);
 
   Real work = 0.;
 
   UInt nb_nodes = this->mesh.getNbNodes();
 
   for (UInt n = 0; n < nb_nodes;
        ++n, ++ext_force_it, ++int_force_it, ++boun_it, ++incr_or_velo_it) {
     const auto & int_force = *int_force_it;
     const auto & ext_force = *ext_force_it;
     const auto & boun = *boun_it;
     const auto & incr_or_velo = *incr_or_velo_it;
 
     bool is_local_node = this->mesh.isLocalOrMasterNode(n);
     // bool is_not_pbc_slave_node = !this->isPBCSlaveNode(n);
     bool count_node = is_local_node; // && is_not_pbc_slave_node;
 
     if (count_node) {
       for (UInt i = 0; i < Model::spatial_dimension; ++i) {
         if (boun(i))
           work -= int_force(i) * incr_or_velo(i);
         else
           work += ext_force(i) * incr_or_velo(i);
       }
     }
   }
 
   StaticCommunicator::getStaticCommunicator().allReduce(work, _so_sum);
 
   if (this->method != _static)
     work *= this->getTimeStep();
   AKANTU_DEBUG_OUT();
   return work;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getEnergy(const std::string & energy_id) {
   AKANTU_DEBUG_IN();
 
   if (energy_id == "kinetic") {
     return getKineticEnergy();
   } else if (energy_id == "external work") {
     return getExternalWork();
   }
 
   Real energy = 0.;
   for (auto & material : materials)
     energy += material->getEnergy(energy_id);
 
   /// reduction sum over all processors
   StaticCommunicator::getStaticCommunicator().allReduce(energy, _so_sum);
 
   AKANTU_DEBUG_OUT();
   return energy;
 }
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getEnergy(const std::string & energy_id,
                                     const ElementType & type, UInt index) {
   AKANTU_DEBUG_IN();
 
   if (energy_id == "kinetic") {
     return getKineticEnergy(type, index);
   }
 
   UInt mat_index = this->material_index(type, _not_ghost)(index);
   UInt mat_loc_num = this->material_local_numbering(type, _not_ghost)(index);
   Real energy =
       this->materials[mat_index]->getEnergy(energy_id, type, mat_loc_num);
 
   AKANTU_DEBUG_OUT();
   return energy;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::onElementsAdded(const Array<Element> & element_list,
                                           const NewElementsEvent & event) {
   AKANTU_DEBUG_IN();
 
   this->getFEEngine().initShapeFunctions(_not_ghost);
   this->getFEEngine().initShapeFunctions(_ghost);
 
   for (auto ghost_type : ghost_types) {
     for (auto type : mesh.elementTypes(Model::spatial_dimension, ghost_type,
                                        _ek_not_defined)) {
       UInt nb_element = this->mesh.getNbElement(type, ghost_type);
 
       if (!material_index.exists(type, ghost_type)) {
         this->material_index.alloc(nb_element, 1, type, ghost_type);
         this->material_local_numbering.alloc(nb_element, 1, type, ghost_type);
       } else {
         this->material_index(type, ghost_type).resize(nb_element);
         this->material_local_numbering(type, ghost_type).resize(nb_element);
       }
     }
   }
 
   ElementTypeMapArray<UInt> filter("new_element_filter", this->getID(),
                                    this->getMemoryID());
 
   for (auto & elem : element_list) {
     if (!filter.exists(elem.type, elem.ghost_type))
       filter.alloc(0, 1, elem.type, elem.ghost_type);
 
     filter(elem.type, elem.ghost_type).push_back(elem.element);
   }
 
   this->assignMaterialToElements(&filter);
 
   for (auto & material : materials)
     material->onElementsAdded(element_list, event);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::onElementsRemoved(
     __attribute__((unused)) const Array<Element> & element_list,
     const ElementTypeMapArray<UInt> & new_numbering,
     const RemovedElementsEvent & event) {
   this->getFEEngine().initShapeFunctions(_not_ghost);
   this->getFEEngine().initShapeFunctions(_ghost);
 
   for (auto & material : materials) {
     material->onElementsRemoved(element_list, new_numbering, event);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::onNodesAdded(const Array<UInt> & nodes_list,
                                        __attribute__((unused))
                                        const NewNodesEvent & event) {
   AKANTU_DEBUG_IN();
   UInt nb_nodes = mesh.getNbNodes();
 
   if (displacement)
     displacement->resize(nb_nodes, 0.);
   if (mass)
     mass->resize(nb_nodes, 0.);
   if (velocity)
     velocity->resize(nb_nodes, 0.);
   if (acceleration)
     acceleration->resize(nb_nodes, 0.);
   if (external_force)
     external_force->resize(nb_nodes, 0.);
   if (internal_force)
     internal_force->resize(nb_nodes, 0.);
   if (blocked_dofs)
     blocked_dofs->resize(nb_nodes, 0.);
 
   if (previous_displacement)
     previous_displacement->resize(nb_nodes, 0.);
   if (displacement_increment)
     displacement_increment->resize(nb_nodes, 0.);
 
   for (auto & material : materials) {
     material->onNodesAdded(nodes_list, event);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::onNodesRemoved(__attribute__((unused))
                                          const Array<UInt> & element_list,
                                          const Array<UInt> & new_numbering,
                                          __attribute__((unused))
                                          const RemovedNodesEvent & event) {
   if (displacement)
     mesh.removeNodesFromArray(*displacement, new_numbering);
   if (mass)
     mesh.removeNodesFromArray(*mass, new_numbering);
   if (velocity)
     mesh.removeNodesFromArray(*velocity, new_numbering);
   if (acceleration)
     mesh.removeNodesFromArray(*acceleration, new_numbering);
   if (internal_force)
     mesh.removeNodesFromArray(*internal_force, new_numbering);
   if (external_force)
     mesh.removeNodesFromArray(*external_force, new_numbering);
   if (blocked_dofs)
     mesh.removeNodesFromArray(*blocked_dofs, new_numbering);
 
   // if (increment_acceleration)
   //   mesh.removeNodesFromArray(*increment_acceleration, new_numbering);
   if (displacement_increment)
     mesh.removeNodesFromArray(*displacement_increment, new_numbering);
 
   if (previous_displacement)
     mesh.removeNodesFromArray(*previous_displacement, new_numbering);
 
   // if (method != _explicit_lumped_mass) {
   //   this->initSolver();
   // }
 }
 
-/* -------------------------------------------------------------------------- */
-bool SolidMechanicsModel::isInternal(const std::string & field_name,
-                                     const ElementKind & element_kind) {
-  /// check if at least one material contains field_id as an internal
-  for (auto & material : materials) {
-    bool is_internal = material->isInternal<Real>(field_name, element_kind);
-    if (is_internal)
-      return true;
-  }
-
-  return false;
-}
-/* -------------------------------------------------------------------------- */
-ElementTypeMap<UInt>
-SolidMechanicsModel::getInternalDataPerElem(const std::string & field_name,
-                                            const ElementKind & element_kind) {
-
-  if (!(this->isInternal(field_name, element_kind)))
-    AKANTU_EXCEPTION("unknown internal " << field_name);
-
-  for (auto & material : materials) {
-    if (material->isInternal<Real>(field_name, element_kind))
-      return material->getInternalDataPerElem<Real>(field_name, element_kind);
-  }
-
-  return ElementTypeMap<UInt>();
-}
-
-/* -------------------------------------------------------------------------- */
-ElementTypeMapArray<Real> &
-SolidMechanicsModel::flattenInternal(const std::string & field_name,
-                                     const ElementKind & kind,
-                                     const GhostType ghost_type) {
-  std::pair<std::string, ElementKind> key(field_name, kind);
-  if (this->registered_internals.count(key) == 0) {
-    this->registered_internals[key] =
-        new ElementTypeMapArray<Real>(field_name, this->id, this->memory_id);
-  }
-
-  ElementTypeMapArray<Real> * internal_flat = this->registered_internals[key];
-
-  for (auto type :
-       mesh.elementTypes(Model::spatial_dimension, ghost_type, kind)) {
-    if (internal_flat->exists(type, ghost_type)) {
-      auto & internal = (*internal_flat)(type, ghost_type);
-      // internal.clear();
-      internal.resize(0);
-    }
-  }
-
-  for (auto & material : materials) {
-    if (material->isInternal<Real>(field_name, kind))
-      material->flattenInternal(field_name, *internal_flat, ghost_type, kind);
-  }
-
-  return *internal_flat;
-}
-
-/* -------------------------------------------------------------------------- */
-void SolidMechanicsModel::flattenAllRegisteredInternals(
-    const ElementKind & kind) {
-  ElementKind _kind;
-  ID _id;
-
-  for (auto & internal : this->registered_internals) {
-    std::tie(_id, _kind) = internal.first;
-    if (kind == _kind)
-      this->flattenInternal(_id, kind);
-  }
-}
-
-/* -------------------------------------------------------------------------- */
-void SolidMechanicsModel::onDump() {
-  this->flattenAllRegisteredInternals(_ek_regular);
-}
-
-/* -------------------------------------------------------------------------- */
-#ifdef AKANTU_USE_IOHELPER
-dumper::Field * SolidMechanicsModel::createElementalField(
-    const std::string & field_name, const std::string & group_name,
-    bool padding_flag, const UInt & spatial_dimension,
-    const ElementKind & kind) {
-
-  dumper::Field * field = nullptr;
-
-  if (field_name == "partitions")
-    field = mesh.createElementalField<UInt, dumper::ElementPartitionField>(
-        mesh.getConnectivities(), group_name, spatial_dimension, kind);
-  else if (field_name == "material_index")
-    field = mesh.createElementalField<UInt, Vector, dumper::ElementalField>(
-        material_index, group_name, spatial_dimension, kind);
-  else {
-    // this copy of field_name is used to compute derivated data such as
-    // strain and von mises stress that are based on grad_u and stress
-    std::string field_name_copy(field_name);
-
-    if (field_name == "strain" || field_name == "Green strain" ||
-        field_name == "principal strain" ||
-        field_name == "principal Green strain")
-      field_name_copy = "grad_u";
-    else if (field_name == "Von Mises stress")
-      field_name_copy = "stress";
-
-    bool is_internal = this->isInternal(field_name_copy, kind);
-
-    if (is_internal) {
-      ElementTypeMap<UInt> nb_data_per_elem =
-          this->getInternalDataPerElem(field_name_copy, kind);
-      ElementTypeMapArray<Real> & internal_flat =
-          this->flattenInternal(field_name_copy, kind);
-      field = mesh.createElementalField<Real, dumper::InternalMaterialField>(
-          internal_flat, group_name, spatial_dimension, kind, nb_data_per_elem);
-      if (field_name == "strain") {
-        dumper::ComputeStrain<false> * foo =
-            new dumper::ComputeStrain<false>(*this);
-        field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
-      } else if (field_name == "Von Mises stress") {
-        dumper::ComputeVonMisesStress * foo =
-            new dumper::ComputeVonMisesStress(*this);
-        field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
-      } else if (field_name == "Green strain") {
-        dumper::ComputeStrain<true> * foo =
-            new dumper::ComputeStrain<true>(*this);
-        field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
-      } else if (field_name == "principal strain") {
-        dumper::ComputePrincipalStrain<false> * foo =
-            new dumper::ComputePrincipalStrain<false>(*this);
-        field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
-      } else if (field_name == "principal Green strain") {
-        dumper::ComputePrincipalStrain<true> * foo =
-            new dumper::ComputePrincipalStrain<true>(*this);
-        field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
-      }
-
-      // treat the paddings
-      if (padding_flag) {
-        if (field_name == "stress") {
-          if (spatial_dimension == 2) {
-            dumper::StressPadder<2> * foo = new dumper::StressPadder<2>(*this);
-            field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
-          }
-        } else if (field_name == "strain" || field_name == "Green strain") {
-          if (spatial_dimension == 2) {
-            dumper::StrainPadder<2> * foo = new dumper::StrainPadder<2>(*this);
-            field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
-          }
-        }
-      }
-
-      // homogenize the field
-      dumper::ComputeFunctorInterface * foo =
-          dumper::HomogenizerProxy::createHomogenizer(*field);
-
-      field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
-    }
-  }
-  return field;
-}
-
-/* -------------------------------------------------------------------------- */
-dumper::Field *
-SolidMechanicsModel::createNodalFieldReal(const std::string & field_name,
-                                          const std::string & group_name,
-                                          bool padding_flag) {
-
-  std::map<std::string, Array<Real> *> real_nodal_fields;
-  real_nodal_fields["displacement"] = this->displacement;
-  real_nodal_fields["mass"] = this->mass;
-  real_nodal_fields["velocity"] = this->velocity;
-  real_nodal_fields["acceleration"] = this->acceleration;
-  real_nodal_fields["external_force"] = this->external_force;
-  real_nodal_fields["internal_force"] = this->internal_force;
-  real_nodal_fields["increment"] = this->displacement_increment;
-
-  if (field_name == "force") {
-    AKANTU_EXCEPTION("The 'force' field has been renamed in 'external_force'");
-  } else if (field_name == "residual") {
-    AKANTU_EXCEPTION(
-        "The 'residual' field has been replaced by 'internal_force'");
-  }
-
-  dumper::Field * field = nullptr;
-  if (padding_flag)
-    field = this->mesh.createNodalField(real_nodal_fields[field_name],
-                                        group_name, 3);
-  else
-    field =
-        this->mesh.createNodalField(real_nodal_fields[field_name], group_name);
-
-  return field;
-}
-
-/* -------------------------------------------------------------------------- */
-dumper::Field * SolidMechanicsModel::createNodalFieldBool(
-    const std::string & field_name, const std::string & group_name,
-    __attribute__((unused)) bool padding_flag) {
-
-  std::map<std::string, Array<bool> *> uint_nodal_fields;
-  uint_nodal_fields["blocked_dofs"] = blocked_dofs;
-
-  dumper::Field * field = nullptr;
-  field = mesh.createNodalField(uint_nodal_fields[field_name], group_name);
-  return field;
-}
-/* -------------------------------------------------------------------------- */
-#else
-/* -------------------------------------------------------------------------- */
-dumper::Field * SolidMechanicsModel::createElementalField(const std::string &,
-                                                          const std::string &,
-                                                          bool, const UInt &,
-                                                          const ElementKind &) {
-  return nullptr;
-}
-/* --------------------------------------------------------------------------
- */
-dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string &,
-                                                          const std::string &,
-                                                          bool) {
-  return nullptr;
-}
-
-/* --------------------------------------------------------------------------
- */
-dumper::Field * SolidMechanicsModel::createNodalFieldBool(const std::string &,
-                                                          const std::string &,
-                                                          bool) {
-  return nullptr;
-}
-
-#endif
-/* --------------------------------------------------------------------------
- */
-void SolidMechanicsModel::dump(const std::string & dumper_name) {
-  this->onDump();
-  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
-  mesh.dump(dumper_name);
-}
-
-/* --------------------------------------------------------------------------
- */
-void SolidMechanicsModel::dump(const std::string & dumper_name, UInt step) {
-  this->onDump();
-  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
-  mesh.dump(dumper_name, step);
-}
-
-/* -------------------------------------------------------------------------
- */
-void SolidMechanicsModel::dump(const std::string & dumper_name, Real time,
-                               UInt step) {
-  this->onDump();
-  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
-  mesh.dump(dumper_name, time, step);
-}
-
-/* -------------------------------------------------------------------------- */
-void SolidMechanicsModel::dump() {
-  this->onDump();
-  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
-  mesh.dump();
-}
-
-/* -------------------------------------------------------------------------- */
-void SolidMechanicsModel::dump(UInt step) {
-  this->onDump();
-  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
-  mesh.dump(step);
-}
-
-/* -------------------------------------------------------------------------- */
-void SolidMechanicsModel::dump(Real time, UInt step) {
-  this->onDump();
-  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
-  mesh.dump(time, step);
-}
-
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::printself(std::ostream & stream, int indent) const {
   std::string space;
   for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
     ;
 
   stream << space << "Solid Mechanics Model [" << std::endl;
   stream << space << " + id                : " << id << std::endl;
   stream << space << " + spatial dimension : " << Model::spatial_dimension
          << std::endl;
   stream << space << " + fem [" << std::endl;
   getFEEngine().printself(stream, indent + 2);
   stream << space << AKANTU_INDENT << "]" << std::endl;
   stream << space << " + nodals information [" << std::endl;
   displacement->printself(stream, indent + 2);
   mass->printself(stream, indent + 2);
   velocity->printself(stream, indent + 2);
   acceleration->printself(stream, indent + 2);
   external_force->printself(stream, indent + 2);
   internal_force->printself(stream, indent + 2);
   blocked_dofs->printself(stream, indent + 2);
   stream << space << AKANTU_INDENT << "]" << std::endl;
 
   stream << space << " + material information [" << std::endl;
   material_index.printself(stream, indent + 2);
   stream << space << AKANTU_INDENT << "]" << std::endl;
 
   stream << space << " + materials [" << std::endl;
   for (auto & material : materials) {
     material->printself(stream, indent + 1);
   }
   stream << space << AKANTU_INDENT << "]" << std::endl;
 
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::insertIntegrationPointsInNeighborhoods(
     const GhostType & ghost_type) {
   for (auto & mat : materials) {
     try {
       ElementTypeMapArray<Real> quadrature_points_coordinates(
           "quadrature_points_coordinates_tmp_nl", this->id, this->memory_id);
       quadrature_points_coordinates.initialize(
           this->getFEEngine(), _spatial_dimension = Model::spatial_dimension,
           _nb_component = Model::spatial_dimension, _ghost_type = ghost_type);
       for (auto & type : quadrature_points_coordinates.elementTypes(
                Model::spatial_dimension, ghost_type)) {
         this->getFEEngine().computeIntegrationPointsCoordinates(
             quadrature_points_coordinates(type, ghost_type), type, ghost_type);
       }
 
       auto & mat_non_local = dynamic_cast<MaterialNonLocalInterface &>(*mat);
       mat_non_local.insertIntegrationPointsInNeighborhoods(
           ghost_type, quadrature_points_coordinates);
     } catch (std::bad_cast &) {
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::computeNonLocalStresses(
     const GhostType & ghost_type) {
   for (auto & mat : materials) {
     try {
       auto & mat_non_local = dynamic_cast<MaterialNonLocalInterface &>(*mat);
       mat_non_local.computeNonLocalStresses(ghost_type);
     } catch (std::bad_cast &) {
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateLocalInternal(
     ElementTypeMapReal & internal_flat, const GhostType & ghost_type,
     const ElementKind & kind) {
   const ID field_name = internal_flat.getName();
   for (auto & material : materials) {
     if (material->isInternal<Real>(field_name, kind))
       material->flattenInternal(field_name, internal_flat, ghost_type, kind);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateNonLocalInternal(
     ElementTypeMapReal & internal_flat, const GhostType & ghost_type,
     const ElementKind & kind) {
 
   const ID field_name = internal_flat.getName();
 
   for (auto & mat : materials) {
     try {
       auto & mat_non_local = dynamic_cast<MaterialNonLocalInterface &>(*mat);
       mat_non_local.updateNonLocalInternals(internal_flat, field_name, ghost_type, kind);
     } catch (std::bad_cast &) {
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 
 } // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model.hh b/src/model/solid_mechanics/solid_mechanics_model.hh
index 9e816c26c..ad7e9d873 100644
--- a/src/model/solid_mechanics/solid_mechanics_model.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model.hh
@@ -1,827 +1,809 @@
 /**
  * @file   solid_mechanics_model.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Tue Jul 27 2010
  * @date last modification: Tue Jan 19 2016
  *
  * @brief  Model of Solid Mechanics
  *
  * @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_SOLID_MECHANICS_MODEL_HH__
-#define __AKANTU_SOLID_MECHANICS_MODEL_HH__
-
-/* -------------------------------------------------------------------------- */
-#include <fstream>
 /* -------------------------------------------------------------------------- */
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "aka_named_argument.hh"
-#include "aka_types.hh"
 #include "boundary_condition.hh"
 #include "data_accessor.hh"
-#include "dumpable.hh"
-#include "integrator_gauss.hh"
-#include "material_selector.hh"
-#include "mesh.hh"
 #include "model.hh"
 #include "non_local_manager.hh"
-#include "shape_lagrange.hh"
 #include "solid_mechanics_model_event_handler.hh"
 /* -------------------------------------------------------------------------- */
+#include "integrator_gauss.hh"
+#include "shape_lagrange.hh"
+/* -------------------------------------------------------------------------- */
+
+#ifndef __AKANTU_SOLID_MECHANICS_MODEL_HH__
+#define __AKANTU_SOLID_MECHANICS_MODEL_HH__
+
 namespace akantu {
 class Material;
+class MaterialSelector;
 class DumperIOHelper;
 class NonLocalManager;
 } // namespace akantu
-/* -------------------------------------------------------------------------- */
 
+/* -------------------------------------------------------------------------- */
 namespace akantu {
 
 struct SolidMechanicsModelOptions : public ModelOptions {
   SolidMechanicsModelOptions(
-      AnalysisMethod analysis_method = _explicit_lumped_mass,
-      bool no_init_materials = false)
-      : analysis_method(analysis_method), no_init_materials(no_init_materials) {
-  }
+      AnalysisMethod analysis_method = _explicit_lumped_mass);
 
   template <typename... pack>
-  SolidMechanicsModelOptions(use_named_args_t, pack &&... _pack)
-      : SolidMechanicsModelOptions(
-            OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass),
-            OPTIONAL_NAMED_ARG(no_init_materials, false)) {}
+  SolidMechanicsModelOptions(use_named_args_t, pack &&... _pack);
 
   AnalysisMethod analysis_method;
   bool no_init_materials;
 };
 
-extern const SolidMechanicsModelOptions default_solid_mechanics_model_options;
-
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
 class SolidMechanicsModel
     : public Model,
       public DataAccessor<Element>,
       public DataAccessor<UInt>,
       public BoundaryCondition<SolidMechanicsModel>,
       public NonLocalManager,
       public EventHandlerManager<SolidMechanicsModelEventHandler> {
 
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   class NewMaterialElementsEvent : public NewElementsEvent {
   public:
     AKANTU_GET_MACRO_NOT_CONST(MaterialList, material, Array<UInt> &);
     AKANTU_GET_MACRO(MaterialList, material, const Array<UInt> &);
 
   protected:
     Array<UInt> material;
   };
 
-  typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange> MyFEEngineType;
+  using MyFEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
 
 protected:
-  typedef EventHandlerManager<SolidMechanicsModelEventHandler> EventManager;
+  using EventManager = EventHandlerManager<SolidMechanicsModelEventHandler>;
 
 public:
   SolidMechanicsModel(Mesh & mesh, UInt spatial_dimension = _all_dimensions,
                       const ID & id = "solid_mechanics_model",
                       const MemoryID & memory_id = 0);
 
   virtual ~SolidMechanicsModel();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   template <typename P, typename T, typename... pack>
   void initFull(named_argument::param_t<P, T &&> && first, pack &&... _pack) {
     this->initFull(SolidMechanicsModelOptions{use_named_args, first, _pack...});
   }
 
   /// initialize completely the model
   void initFull(
       const ModelOptions & options = SolidMechanicsModelOptions()) override;
 
   /// initialize the fem object needed for boundary conditions
   void initFEEngineBoundary();
 
   /// register the tags associated with the parallel synchronizer
   // virtual void initParallel(MeshPartition * partition,
   //                           DataAccessor<Element> * data_accessor = NULL);
 
   /// allocate all vectors
   virtual void initArrays();
 
   /// allocate all vectors
   // void initArraysPreviousDisplacment();
 
   /// initialize all internal arrays for materials
   virtual void initMaterials();
 
   /// initialize the model
   void initModel() override;
 
   /// init PBC synchronizer
   // void initPBC();
 
   /// initialize a new solver and sets it as the default one to use
   void initNewSolver(const AnalysisMethod & method);
 
   /// function to print the containt of the class
   void printself(std::ostream & stream, int indent = 0) const override;
 
 protected:
   /// allocate an array if needed
   template <typename T>
   void allocNodalField(Array<T> *& array, const ID & name);
 
   /* ------------------------------------------------------------------------ */
   /* PBC                                                                      */
   /* ------------------------------------------------------------------------ */
 public:
   /// change the equation number for proper assembly when using PBC
   //  void changeEquationNumberforPBC(std::map <UInt, UInt> & pbc_pair);
 
   /// synchronize Residual for output
   // void synchronizeResidual();
 
 protected:
   /// register PBC synchronizer
   //  void registerPBCSynchronizer();
 
   /* ------------------------------------------------------------------------ */
   /* Solver interface                                                         */
   /* ------------------------------------------------------------------------ */
 public:
   /// assembles the stiffness matrix,
   virtual void assembleStiffnessMatrix();
   /// assembles the internal forces in the array internal_forces
   virtual void assembleInternalForces();
 
 protected:
   /// callback for the solver, this adds f_{ext} - f_{int} to the residual
   void assembleResidual() override;
 
   /// callback for the solver, this assembles the stiffness matrix
   void assembleJacobian() override;
 
   /// callback for the solver, this is called at beginning of solve
   void predictor() override;
   /// callback for the solver, this is called at end of solve
   void corrector() override;
 
   /// Callback for the model to instantiate the matricees when needed
   void initSolver(TimeStepSolverType time_step_solver_type,
                   NonLinearSolverType non_linear_solver_type) override;
 
 protected:
   /* ------------------------------------------------------------------------ */
   TimeStepSolverType getDefaultSolverType() const override;
   /* ------------------------------------------------------------------------ */
   ModelSolverOptions
   getDefaultSolverOptions(const TimeStepSolverType & type) const override;
 
   /* ------------------------------------------------------------------------ */
   /* Explicit                                                                 */
   /* ------------------------------------------------------------------------ */
   // public:
   //   /// initialize the stuff for the explicit scheme
   //   void initExplicit(AnalysisMethod analysis_method =
   //   _explicit_lumped_mass);
 
 public:
   bool isDefaultSolverExplicit() {
     return method == _explicit_lumped_mass ||
            method == _explicit_consistent_mass;
   }
 
   //   /// initialize the array needed by updateResidual (residual,
   //   current_position)
   //   void initializeUpdateResidualData();
 
 protected:
   /// update the current position vector
   void updateCurrentPosition();
 
   //   /// assemble the residual for the explicit scheme
   //   virtual void updateResidual(bool need_initialize = true);
 
   //   /**
   //    * \brief compute the acceleration from the residual
   //    * this function is the explicit equivalent to solveDynamic in implicit
   //    * In the case of lumped mass just divide the residual by the mass
   //    * In the case of not lumped mass call
   //    solveDynamic<_acceleration_corrector>
   //    */
   //   void updateAcceleration();
 
   /// Update the increment of displacement
   // void updateIncrement();
 
   // /// Copy the actuel displacement into previous displacement
   // void updatePreviousDisplacement();
 
   //   /// Save stress and strain through EventManager
   //   void saveStressAndStrainBeforeDamage();
   //   /// Update energies through EventManager
   //   void updateEnergiesAfterDamage();
 
   //   /// Solve the system @f[ A x = \alpha b @f] with A a lumped matrix
   //   void solveLumped(Array<Real> & x, const Array<Real> & A,
   //                    const Array<Real> & b, const Array<bool> & blocked_dofs,
   //                    Real alpha);
 
   //   /// explicit integration predictor
   //   void explicitPred();
 
   //   /// explicit integration corrector
   //   void explicitCorr();
 
   // public:
   //   void solveStep();
 
   //   /*
   //   ------------------------------------------------------------------------
   //   */
   //   /* Implicit */
   //   /*
   //   ------------------------------------------------------------------------
   //   */
   // public:
   //   /// initialize the solver and the jacobian_matrix (called by
   //   initImplicit)
   //   void initSolver();
 
   //   /// initialize the stuff for the implicit solver
   //   void initImplicit(bool            dynamic = false);
 
   //   /// solve Ma = f to get the initial acceleration
   //   void initialAcceleration();
 
   //   /// assemble the stiffness matrix
   //   void assembleStiffnessMatrix();
 
   // public:
   //   /**
   //    * solve a step (predictor + convergence loop + corrector) using the
   //    * the given convergence method (see akantu::SolveConvergenceMethod)
   //    * and the given convergence criteria (see
   //    * akantu::SolveConvergenceCriteria)
   //    **/
   //   template <SolveConvergenceMethod method, SolveConvergenceCriteria
   //   criteria>
   //   bool solveStep(Real tolerance, UInt max_iteration = 100);
 
   //   template <SolveConvergenceMethod method, SolveConvergenceCriteria
   //   criteria>
   //   bool solveStep(Real tolerance, Real & error, UInt max_iteration = 100,
   //                  bool do_not_factorize = false);
 
   // public:
   //   /**
   //    * solve Ku = f using the the given convergence method (see
   //    * akantu::SolveConvergenceMethod) and the given convergence
   //    * criteria (see akantu::SolveConvergenceCriteria)
   //    **/
   //   template <SolveConvergenceMethod cmethod, SolveConvergenceCriteria
   //   criteria>
   //   bool solveStatic(Real tolerance, UInt max_iteration,
   //                    bool do_not_factorize = false);
 
   //   /// create and return the velocity damping matrix
   //   SparseMatrix & initVelocityDampingMatrix();
 
   //   /// implicit time integration predictor
   //   void implicitPred();
 
   //   /// implicit time integration corrector
   //   void implicitCorr();
 
   //   /// compute the Cauchy stress on user demand.
   //   void computeCauchyStresses();
 
   //   // /// compute A and solve @f[ A\delta u = f_ext - f_int @f]
   //   // template <NewmarkBeta::IntegrationSchemeCorrectorType type>
   //   // void solve(Array<Real> &increment, Real block_val = 1.,
   //   //            bool need_factorize = true, bool has_profile_changed =
   //   false);
 
   // protected:
   //   /// finish the computation of residual to solve in increment
   //   void updateResidualInternal();
 
   //   /// compute the support reaction and store it in force
   //   void updateSupportReaction();
 
   // private:
   //   /// re-initialize the J matrix (to use if the profile of K changed)
   //   void initJacobianMatrix();
 
   /* ------------------------------------------------------------------------ */
   // public:
   /// Update the stresses for the computation of the residual of the Stiffness
   /// matrix in the case of finite deformation
   // void computeStresses();
 
   /// synchronize the ghost element boundaries values
   // void synchronizeBoundaries();
 
   /* ------------------------------------------------------------------------ */
   /* Materials (solid_mechanics_model_material.cc)                            */
   /* ------------------------------------------------------------------------ */
 public:
   /// registers all the custom materials of a given type present in the input
   /// file
-  template <typename M> void registerNewCustomMaterials(const ID & mat_type);
+  // template <typename M> void registerNewCustomMaterials(const ID & mat_type);
 
   /// register an empty material of a given type
-  template <typename M>
-  Material & registerNewEmptyMaterial(const std::string & name);
-
-  // /// Use a UIntData in the mesh to specify the material to use per element
-  // void setMaterialIDsFromIntData(const std::string & data_name);
+  Material & registerNewMaterial(const ID & mat_name, const ID & mat_type,
+                                 const ID & opt_param);
+  // /// Use a UIntData in the mesh to specify the material to use per
+  // element void setMaterialIDsFromIntData(const std::string & data_name);
 
   /// reassigns materials depending on the material selector
   virtual void reassignMaterial();
 
   /// apply a constant eigen_grad_u on all quadrature points of a given material
   virtual void applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u,
                                const ID & material_name,
                                const GhostType ghost_type = _not_ghost);
 
 protected:
   /// register a material in the dynamic database
-  template <typename M>
   Material & registerNewMaterial(const ParserSection & mat_section);
 
   /// read the material files to instantiate all the materials
   void instantiateMaterials();
 
   /// set the element_id_by_material and add the elements to the good materials
   void
   assignMaterialToElements(const ElementTypeMapArray<UInt> * filter = NULL);
 
   /// reinitialize dof_synchronizer and solver (either in implicit or
   /// explicit) when cohesive elements are inserted
-  //void reinitializeSolver();
+  // void reinitializeSolver();
 
   /* ------------------------------------------------------------------------ */
   /* Mass (solid_mechanics_model_mass.cc)                                     */
   /* ------------------------------------------------------------------------ */
 public:
   /// assemble the lumped mass matrix
   void assembleMassLumped();
 
   /// assemble the mass matrix for consistent mass resolutions
   void assembleMass();
 
 protected:
   /// assemble the lumped mass matrix for local and ghost elements
   void assembleMassLumped(GhostType ghost_type);
 
   /// assemble the mass matrix for either _ghost or _not_ghost elements
   void assembleMass(GhostType ghost_type);
 
   /// fill a vector of rho
   void computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type);
 
   /// compute the kinetic energy
   Real getKineticEnergy();
   Real getKineticEnergy(const ElementType & type, UInt index);
 
   /// compute the external work (for impose displacement, the velocity should be
   /// given too)
   Real getExternalWork();
 
   /* ------------------------------------------------------------------------ */
   /* NonLocalManager inherited members                                        */
   /* ------------------------------------------------------------------------ */
 protected:
   void updateDataForNonLocalCriterion(ElementTypeMapReal & criterion) override;
 
   void computeNonLocalStresses(const GhostType & ghost_type) override;
 
   void
   insertIntegrationPointsInNeighborhoods(const GhostType & ghost_type) override;
 
   /// update the values of the non local internal
   void updateLocalInternal(ElementTypeMapReal & internal_flat,
                            const GhostType & ghost_type,
                            const ElementKind & kind) override;
 
   /// copy the results of the averaging in the materials
   void updateNonLocalInternal(ElementTypeMapReal & internal_flat,
                               const GhostType & ghost_type,
                               const ElementKind & kind) override;
 
   /* ------------------------------------------------------------------------ */
   /* Data Accessor 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;
 
   inline UInt getNbData(const Array<UInt> & dofs,
                         const SynchronizationTag & tag) const override;
 
   inline void packData(CommunicationBuffer & buffer, const Array<UInt> & dofs,
                        const SynchronizationTag & tag) const override;
 
   inline void unpackData(CommunicationBuffer & buffer, const Array<UInt> & dofs,
                          const SynchronizationTag & tag) override;
 
 protected:
   inline void splitElementByMaterial(const Array<Element> & elements,
                                      Array<Element> * elements_per_mat) const;
 
   /* ------------------------------------------------------------------------ */
   /* Mesh Event Handler inherited members                                     */
   /* ------------------------------------------------------------------------ */
 protected:
   void onNodesAdded(const Array<UInt> & nodes_list,
                     const NewNodesEvent & event) override;
   void onNodesRemoved(const Array<UInt> & element_list,
                       const Array<UInt> & new_numbering,
                       const RemovedNodesEvent & event) override;
   void onElementsAdded(const Array<Element> & nodes_list,
                        const NewElementsEvent & event) override;
   void onElementsRemoved(const Array<Element> & element_list,
                          const ElementTypeMapArray<UInt> & new_numbering,
                          const RemovedElementsEvent & event) override;
 
   void onElementsChanged(const Array<Element> &, const Array<Element> &,
                          const ElementTypeMapArray<UInt> &,
                          const ChangedElementsEvent &) override{};
 
   /* ------------------------------------------------------------------------ */
   /* Dumpable interface (kept for convenience) and dumper relative functions  */
   /* ------------------------------------------------------------------------ */
 public:
   virtual void onDump();
 
   //! decide wether a field is a material internal or not
   bool isInternal(const std::string & field_name,
                   const ElementKind & element_kind);
 #ifndef SWIG
   //! give the amount of data per element
   virtual ElementTypeMap<UInt>
   getInternalDataPerElem(const std::string & field_name,
                          const ElementKind & kind);
 
   //! flatten a given material internal field
   ElementTypeMapArray<Real> &
   flattenInternal(const std::string & field_name, const ElementKind & kind,
                   const GhostType ghost_type = _not_ghost);
   //! flatten all the registered material internals
   void flattenAllRegisteredInternals(const ElementKind & kind);
 #endif
 
   dumper::Field * createNodalFieldReal(const std::string & field_name,
                                        const std::string & group_name,
                                        bool padding_flag) override;
 
   dumper::Field * createNodalFieldBool(const std::string & field_name,
                                        const std::string & group_name,
                                        bool padding_flag) override;
 
   dumper::Field * createElementalField(const std::string & field_name,
                                        const std::string & group_name,
                                        bool padding_flag,
                                        const UInt & spatial_dimension,
                                        const ElementKind & kind) override;
 
   virtual void dump(const std::string & dumper_name);
 
   virtual void dump(const std::string & dumper_name, UInt step);
 
   virtual void dump(const std::string & dumper_name, Real time, UInt step);
 
   void dump() override;
 
   virtual void dump(UInt step);
 
   virtual void dump(Real time, UInt step);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// return the dimension of the system space
   AKANTU_GET_MACRO(SpatialDimension, Model::spatial_dimension, UInt);
 
   /// get the current value of the time step
   // AKANTU_GET_MACRO(TimeStep, time_step, Real);
 
   /// set the value of the time step
   void setTimeStep(Real time_step, const ID & solver_id = "") override;
   /// void setTimeStep(Real time_step);
 
   /// return the of iterations done in the last solveStep
   // AKANTU_GET_MACRO(NumberIter, n_iter, UInt);
 
   /// get the value of the conversion from forces/ mass to acceleration
   AKANTU_GET_MACRO(F_M2A, f_m2a, Real);
 
   /// set the value of the conversion from forces/ mass to acceleration
   AKANTU_SET_MACRO(F_M2A, f_m2a, Real);
 
   /// get the SolidMechanicsModel::displacement vector
   AKANTU_GET_MACRO(Displacement, *displacement, Array<Real> &);
 
   /// get the SolidMechanicsModel::previous_displacement vector
   AKANTU_GET_MACRO(PreviousDisplacement, *previous_displacement, Array<Real> &);
 
   /// get the SolidMechanicsModel::current_position vector \warn only consistent
   /// after a call to SolidMechanicsModel::updateCurrentPosition
   const Array<Real> & getCurrentPosition();
 
   /// get  the SolidMechanicsModel::increment  vector \warn  only  consistent if
   /// SolidMechanicsModel::setIncrementFlagOn has been called before
   AKANTU_GET_MACRO(Increment, *displacement_increment, Array<Real> &);
 
   /// get the lumped SolidMechanicsModel::mass vector
   AKANTU_GET_MACRO(Mass, *mass, Array<Real> &);
 
   /// get the SolidMechanicsModel::velocity vector
   AKANTU_GET_MACRO(Velocity, *velocity, Array<Real> &);
 
   /// get    the    SolidMechanicsModel::acceleration    vector,   updated    by
   /// SolidMechanicsModel::updateAcceleration
   AKANTU_GET_MACRO(Acceleration, *acceleration, Array<Real> &);
 
   /// get the SolidMechanicsModel::force vector (external forces)
   AKANTU_GET_MACRO(Force, *external_force, Array<Real> &);
 
   /// get the SolidMechanicsModel::internal_force vector (internal forces)
   AKANTU_GET_MACRO(InternalForce, *internal_force, Array<Real> &);
 
   /// get the SolidMechanicsModel::blocked_dofs vector
   AKANTU_GET_MACRO(BlockedDOFs, *blocked_dofs, Array<bool> &);
 
   /// get the SolidMechnicsModel::incrementAcceleration vector
   // AKANTU_GET_MACRO(IncrementAcceleration, *increment_acceleration,
   //                  Array<Real> &);
 
   /// get the value of the SolidMechanicsModel::increment_flag
   AKANTU_GET_MACRO(IncrementFlag, increment_flag, bool);
 
   /// get a particular material (by material index)
   inline Material & getMaterial(UInt mat_index);
 
   /// get a particular material (by material index)
   inline const Material & getMaterial(UInt mat_index) const;
 
   /// get a particular material (by material name)
   inline Material & getMaterial(const std::string & name);
 
   /// get a particular material (by material name)
   inline const Material & getMaterial(const std::string & name) const;
 
   /// get a particular material id from is name
   inline UInt getMaterialIndex(const std::string & name) const;
 
   /// give the number of materials
   inline UInt getNbMaterials() const { return materials.size(); }
 
   inline void setMaterialSelector(MaterialSelector & selector);
 
   /// give the material internal index from its id
   Int getInternalIndexFromID(const ID & id) const;
 
   /// compute the stable time step
   Real getStableTimeStep();
 
   /// get the energies
   Real getEnergy(const std::string & energy_id);
 
   /// compute the energy for energy
   Real getEnergy(const std::string & energy_id, const ElementType & type,
                  UInt index);
 
   /**
    * @brief set the SolidMechanicsModel::increment_flag  to on, the activate the
    * update of the SolidMechanicsModel::increment vector
    */
   // void setIncrementFlagOn();
 
   // /// get the stiffness matrix
   // AKANTU_GET_MACRO(StiffnessMatrix, *stiffness_matrix, SparseMatrix &);
 
   // /// get the global jacobian matrix of the system
   // AKANTU_GET_MACRO(GlobalJacobianMatrix, *jacobian_matrix, const SparseMatrix
   // &);
 
   // /// get the mass matrix
   // AKANTU_GET_MACRO(MassMatrix, *mass_matrix, SparseMatrix &);
 
   // /// get the velocity damping matrix
   // AKANTU_GET_MACRO(VelocityDampingMatrix, *velocity_damping_matrix,
   // SparseMatrix &);
 
   /// get the FEEngine object to integrate or interpolate on the boundary
   inline FEEngine & getFEEngineBoundary(const ID & name = "");
 
   // /// get integrator
   // AKANTU_GET_MACRO(Integrator, *integrator, const IntegrationScheme2ndOrder
   // &);
 
   // /// get synchronizer
   // AKANTU_GET_MACRO(Synchronizer, *synch_parallel, const ElementSynchronizer
   // &);
 
   AKANTU_GET_MACRO(MaterialByElement, material_index,
                    const ElementTypeMapArray<UInt> &);
 
   /// vectors containing local material element index for each global element
   /// index
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialByElement, material_index,
                                          UInt);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialByElement, material_index, UInt);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialLocalNumbering,
                                          material_local_numbering, UInt);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialLocalNumbering,
                                    material_local_numbering, UInt);
 
   /// Get the type of analysis method used
   AKANTU_GET_MACRO(AnalysisMethod, method, AnalysisMethod);
 
 protected:
   friend class Material;
 
 protected:
   /// compute the stable time step
   Real getStableTimeStep(const GhostType & ghost_type);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// number of iterations
   // UInt n_iter;
 
   /// time step
   //  Real time_step;
 
   /// conversion coefficient form force/mass to acceleration
   Real f_m2a;
 
   /// displacements array
   Array<Real> * displacement;
   UInt displacement_release{0};
 
   /// displacements array at the previous time step (used in finite deformation)
   Array<Real> * previous_displacement;
 
   /// increment of displacement
   Array<Real> * displacement_increment;
 
   /// lumped mass array
   Array<Real> * mass;
 
   /// velocities array
   Array<Real> * velocity;
 
   /// accelerations array
   Array<Real> * acceleration;
 
   /// accelerations array
   // Array<Real> * increment_acceleration;
 
   /// external forces array
   Array<Real> * external_force;
 
   /// internal forces array
   Array<Real> * internal_force;
 
   /// array specifing if a degree of freedom is blocked or not
   Array<bool> * blocked_dofs;
 
   /// array of current position used during update residual
   Array<Real> * current_position;
   UInt current_position_release{0};
 
   /// mass matrix
   SparseMatrix * mass_matrix;
 
   /// velocity damping matrix
   SparseMatrix * velocity_damping_matrix;
 
   /// stiffness matrix
   SparseMatrix * stiffness_matrix;
 
   /// jacobian matrix @f[A = cM + dD + K@f] with @f[c = \frac{1}{\beta \Delta
   /// t^2}, d = \frac{\gamma}{\beta \Delta t} @f]
   SparseMatrix * jacobian_matrix;
 
   /// Arrays containing the material index for each element
   ElementTypeMapArray<UInt> material_index;
 
   /// Arrays containing the position in the element filter of the material
   /// (material's local numbering)
   ElementTypeMapArray<UInt> material_local_numbering;
 
 #ifdef SWIGPYTHON
 public:
 #endif
   /// list of used materials
   std::vector<std::unique_ptr<Material>> materials;
 
   /// mapping between material name and material internal id
   std::map<std::string, UInt> materials_names_to_id;
 #ifdef SWIGPYTHON
 protected:
 #endif
 
   /// class defining of to choose a material
   MaterialSelector * material_selector;
 
   /// define if it is the default selector or not
   bool is_default_material_selector;
 
   // /// integration scheme of second order used
   // IntegrationScheme2ndOrder *integrator;
 
   /// flag defining if the increment must be computed or not
   bool increment_flag;
 
   /// analysis method check the list in akantu::AnalysisMethod
   AnalysisMethod method;
 
   /// tells if the material are instantiated
   bool are_materials_instantiated;
 
   typedef std::map<std::pair<std::string, ElementKind>,
                    ElementTypeMapArray<Real> *>
       flatten_internal_map;
 
   /// map a registered internals to be flattened for dump purposes
   flatten_internal_map registered_internals;
 
   /// pointer to the pbc synchronizer
   // PBCSynchronizer * pbc_synch;
 };
 
 /* -------------------------------------------------------------------------- */
 namespace BC {
   namespace Neumann {
     typedef FromHigherDim FromStress;
     typedef FromSameDim FromTraction;
   } // namespace Neumann
 } // namespace BC
 
 /// standard output stream operator
 inline std::ostream & operator<<(std::ostream & stream,
                                  const SolidMechanicsModel & _this) {
   _this.printself(stream);
   return stream;
 }
 
 } // namespace akantu
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 #include "material.hh"
 #include "parser.hh"
 
 #include "solid_mechanics_model_inline_impl.cc"
 #include "solid_mechanics_model_tmpl.hh"
 
 #include "material_selector_tmpl.hh"
 
 #endif /* __AKANTU_SOLID_MECHANICS_MODEL_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc
index 8755b8866..1ae1e3240 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc
@@ -1,780 +1,779 @@
 /**
  * @file   solid_mechanics_model_cohesive.cc
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Tue May 08 2012
  * @date last modification: Wed Jan 13 2016
  *
  * @brief  Solid mechanics model for cohesive elements
  *
  * @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 "solid_mechanics_model_cohesive.hh"
 #include "dumpable_inline_impl.hh"
 #include "material_cohesive.hh"
 #include "shape_cohesive.hh"
 #include <algorithm>
 
 #ifdef AKANTU_USE_IOHELPER
 #include "dumper_paraview.hh"
 #endif
 
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 const SolidMechanicsModelCohesiveOptions
-    default_solid_mechanics_model_cohesive_options(_explicit_lumped_mass, false,
-                                                   false);
+    default_solid_mechanics_model_cohesive_options(_explicit_lumped_mass, false);
 
 /* -------------------------------------------------------------------------- */
 
 SolidMechanicsModelCohesive::SolidMechanicsModelCohesive(
     Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id)
     : SolidMechanicsModel(mesh, dim, id, memory_id), tangents("tangents", id),
       facet_stress("facet_stress", id), facet_material("facet_material", id) {
   AKANTU_DEBUG_IN();
 
   inserter = NULL;
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   facet_synchronizer = NULL;
   facet_stress_synchronizer = NULL;
   cohesive_element_synchronizer = NULL;
   global_connectivity = NULL;
 #endif
 
   delete material_selector;
   material_selector = new DefaultMaterialCohesiveSelector(*this);
 
   this->registerEventHandler(*this);
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.registerDumper<DumperParaview>("cohesive elements", id);
   this->mesh.addDumpMeshToDumper("cohesive elements", mesh,
                                  Model::spatial_dimension, _not_ghost,
                                  _ek_cohesive);
 #endif
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 SolidMechanicsModelCohesive::~SolidMechanicsModelCohesive() {
   AKANTU_DEBUG_IN();
 
   delete inserter;
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   delete cohesive_element_synchronizer;
   delete facet_synchronizer;
   delete facet_stress_synchronizer;
 #endif
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::setTimeStep(Real time_step) {
   SolidMechanicsModel::setTimeStep(time_step);
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.getDumper("cohesive elements").setTimeStep(time_step);
 #endif
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initFull(const ModelOptions & options) {
   AKANTU_DEBUG_IN();
 
   const SolidMechanicsModelCohesiveOptions & smmc_options =
       dynamic_cast<const SolidMechanicsModelCohesiveOptions &>(options);
 
   this->is_extrinsic = smmc_options.extrinsic;
 
   if (!inserter)
     inserter = new CohesiveElementInserter(mesh, is_extrinsic,
                                            id + ":cohesive_element_inserter");
 
   SolidMechanicsModel::initFull(options);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initMaterials() {
   AKANTU_DEBUG_IN();
 
   // make sure the material are instantiated
   if (!are_materials_instantiated)
     instantiateMaterials();
 
   /// find the first cohesive material
   UInt cohesive_index = 0;
 
   while ((dynamic_cast<MaterialCohesive *>(materials[cohesive_index].get()) ==
           nullptr) &&
          cohesive_index <= materials.size())
     ++cohesive_index;
 
   AKANTU_DEBUG_ASSERT(cohesive_index != materials.size(),
                       "No cohesive materials in the material input file");
 
   material_selector->setFallback(cohesive_index);
 
   // set the facet information in the material in case of dynamic insertion
   if (is_extrinsic) {
     const Mesh & mesh_facets = inserter->getMeshFacets();
     facet_material.initialize(mesh_facets, _spatial_dimension =
                                                Model::spatial_dimension - 1);
     // mesh_facets.initElementTypeMapArray(facet_material, 1,
     //                                     spatial_dimension - 1);
 
     Element element;
     for (auto ghost_type : ghost_types) {
       element.ghost_type = ghost_type;
       for (auto & type :
            mesh_facets.elementTypes(Model::spatial_dimension - 1, ghost_type)) {
         element.type = type;
         Array<UInt> & f_material = facet_material(type, ghost_type);
         UInt nb_element = mesh_facets.getNbElement(type, ghost_type);
         f_material.resize(nb_element);
         f_material.set(cohesive_index);
         for (UInt el = 0; el < nb_element; ++el) {
           element.element = el;
           UInt mat_index = (*material_selector)(element);
           f_material(el) = mat_index;
           MaterialCohesive & mat =
               dynamic_cast<MaterialCohesive &>(*materials[mat_index]);
           mat.addFacet(element);
         }
       }
     }
     SolidMechanicsModel::initMaterials();
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
     if (facet_synchronizer != NULL)
       inserter->initParallel(facet_synchronizer, cohesive_element_synchronizer);
 //      inserter->initParallel(facet_synchronizer, synch_parallel);
 #endif
     initAutomaticInsertion();
   } else {
     // TODO think of something a bit mor consistant than just coding the first
     // thing that comes in Fabian's head....
     typedef ParserSection::const_section_iterator const_section_iterator;
     std::pair<const_section_iterator, const_section_iterator> sub_sections =
         this->parser->getSubSections(_st_mesh);
 
     if (sub_sections.first != sub_sections.second) {
       std::string cohesive_surfaces =
           sub_sections.first->getParameter("cohesive_surfaces");
       this->initIntrinsicCohesiveMaterials(cohesive_surfaces);
     } else {
       this->initIntrinsicCohesiveMaterials(cohesive_index);
     }
   }
 
   AKANTU_DEBUG_OUT();
 } // namespace akantu
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initIntrinsicCohesiveMaterials(
     std::string cohesive_surfaces) {
 
   AKANTU_DEBUG_IN();
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   if (facet_synchronizer != NULL)
     inserter->initParallel(facet_synchronizer, cohesive_element_synchronizer);
 //    inserter->initParallel(facet_synchronizer, synch_parallel);
 #endif
   std::istringstream split(cohesive_surfaces);
   std::string physname;
   while (std::getline(split, physname, ',')) {
     AKANTU_DEBUG_INFO(
         "Pre-inserting cohesive elements along facets from physical surface: "
         << physname);
     insertElementsFromMeshData(physname);
   }
 
   synchronizeInsertionData();
 
   SolidMechanicsModel::initMaterials();
 
   if (is_default_material_selector)
     delete material_selector;
   material_selector = new MeshDataMaterialCohesiveSelector(*this);
 
   //UInt nb_new_elements =
   inserter->insertElements();
   // if (nb_new_elements > 0) {
   //   this->reinitializeSolver();
   // }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::synchronizeInsertionData() {
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   if (facet_synchronizer != NULL) {
     facet_synchronizer->asynchronousSynchronize(*inserter, _gst_ce_groups);
     facet_synchronizer->waitEndSynchronize(*inserter, _gst_ce_groups);
   }
 #endif
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initIntrinsicCohesiveMaterials(
     UInt cohesive_index) {
 
   AKANTU_DEBUG_IN();
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
     Mesh::type_iterator first =
         mesh.firstType(Model::spatial_dimension, *gt, _ek_cohesive);
     Mesh::type_iterator last =
         mesh.lastType(Model::spatial_dimension, *gt, _ek_cohesive);
 
     for (; first != last; ++first) {
       Array<UInt> & mat_indexes = this->material_index(*first, *gt);
       Array<UInt> & mat_loc_num = this->material_local_numbering(*first, *gt);
       mat_indexes.set(cohesive_index);
       mat_loc_num.clear();
     }
   }
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   if (facet_synchronizer != NULL)
     inserter->initParallel(facet_synchronizer, cohesive_element_synchronizer);
 //    inserter->initParallel(facet_synchronizer, synch_parallel);
 #endif
 
   SolidMechanicsModel::initMaterials();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Initialize the model,basically it  pre-compute the shapes, shapes derivatives
  * and jacobian
  *
  */
 void SolidMechanicsModelCohesive::initModel() {
   AKANTU_DEBUG_IN();
 
   SolidMechanicsModel::initModel();
 
   registerFEEngineObject<MyFEEngineCohesiveType>("CohesiveFEEngine", mesh,
                                                  Model::spatial_dimension);
 
   /// add cohesive type connectivity
   ElementType type = _not_defined;
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType type_ghost = *gt;
 
     Mesh::type_iterator it =
         mesh.firstType(Model::spatial_dimension, type_ghost);
     Mesh::type_iterator last =
         mesh.lastType(Model::spatial_dimension, type_ghost);
 
     for (; it != last; ++it) {
       const Array<UInt> & connectivity = mesh.getConnectivity(*it, type_ghost);
       if (connectivity.getSize() != 0) {
         type = *it;
         ElementType type_facet = Mesh::getFacetType(type);
         ElementType type_cohesive =
             FEEngine::getCohesiveElementType(type_facet);
         mesh.addConnectivityType(type_cohesive, type_ghost);
       }
     }
   }
 
   AKANTU_DEBUG_ASSERT(type != _not_defined, "No elements in the mesh");
 
   getFEEngine("CohesiveFEEngine").initShapeFunctions(_not_ghost);
   getFEEngine("CohesiveFEEngine").initShapeFunctions(_ghost);
 
   registerFEEngineObject<MyFEEngineFacetType>(
       "FacetsFEEngine", mesh.getMeshFacets(), Model::spatial_dimension - 1);
 
   if (is_extrinsic) {
     getFEEngine("FacetsFEEngine").initShapeFunctions(_not_ghost);
     getFEEngine("FacetsFEEngine").initShapeFunctions(_ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::limitInsertion(BC::Axis axis,
                                                  Real first_limit,
                                                  Real second_limit) {
   AKANTU_DEBUG_IN();
   inserter->setLimit(axis, first_limit, second_limit);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::insertIntrinsicElements() {
   AKANTU_DEBUG_IN();
   //UInt nb_new_elements =
   inserter->insertIntrinsicElements();
   // if (nb_new_elements > 0) {
   //   this->reinitializeSolver();
   // }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::insertElementsFromMeshData(
     std::string physname) {
   AKANTU_DEBUG_IN();
 
   UInt material_index = SolidMechanicsModel::getMaterialIndex(physname);
   inserter->insertIntrinsicElements(physname, material_index);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initAutomaticInsertion() {
   AKANTU_DEBUG_IN();
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   if (facet_stress_synchronizer != NULL) {
     DataAccessor * data_accessor = this;
     const ElementTypeMapArray<UInt> & rank_to_element =
         synch_parallel->getPrankToElement();
 
     facet_stress_synchronizer->updateFacetStressSynchronizer(
         *inserter, rank_to_element, *data_accessor);
   }
 #endif
 
   facet_stress.initialize(inserter->getMeshFacets(),
                           _nb_component = 2 * Model::spatial_dimension *
                                           Model::spatial_dimension,
                           _spatial_dimension = Model::spatial_dimension - 1);
 
   // inserter->getMeshFacets().initElementTypeMapArray(
   //     facet_stress, 2 * spatial_dimension * spatial_dimension,
   //     spatial_dimension - 1);
 
   resizeFacetStress();
 
   /// compute normals on facets
   computeNormals();
 
   initStressInterpolation();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::updateAutomaticInsertion() {
   AKANTU_DEBUG_IN();
 
   inserter->limitCheckFacets();
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   if (facet_stress_synchronizer != NULL) {
     DataAccessor * data_accessor = this;
     const ElementTypeMapArray<UInt> & rank_to_element =
         synch_parallel->getPrankToElement();
 
     facet_stress_synchronizer->updateFacetStressSynchronizer(
         *inserter, rank_to_element, *data_accessor);
   }
 #endif
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initStressInterpolation() {
   Mesh & mesh_facets = inserter->getMeshFacets();
 
   /// compute quadrature points coordinates on facets
   Array<Real> & position = mesh.getNodes();
 
   ElementTypeMapArray<Real> quad_facets("quad_facets", id);
   quad_facets.initialize(mesh_facets, _nb_component = Model::spatial_dimension,
                          _spatial_dimension = Model::spatial_dimension - 1);
   // mesh_facets.initElementTypeMapArray(quad_facets, Model::spatial_dimension,
   //                                     Model::spatial_dimension - 1);
 
   getFEEngine("FacetsFEEngine")
       .interpolateOnIntegrationPoints(position, quad_facets);
 
   /// compute elements quadrature point positions and build
   /// element-facet quadrature points data structure
   ElementTypeMapArray<Real> elements_quad_facets("elements_quad_facets", id);
 
   elements_quad_facets.initialize(mesh, _nb_component = Model::spatial_dimension,
                                   _spatial_dimension = Model::spatial_dimension);
   // mesh.initElementTypeMapArray(elements_quad_facets, Model::spatial_dimension,
   //                              Model::spatial_dimension);
 
   for (auto elem_gt : ghost_types) {
     for(auto & type : mesh.elementTypes(Model::spatial_dimension, elem_gt)) {
       UInt nb_element = mesh.getNbElement(type, elem_gt);
       if (nb_element == 0)
         continue;
 
       /// compute elements' quadrature points and list of facet
       /// quadrature points positions by element
       Array<Element> & facet_to_element =
           mesh_facets.getSubelementToElement(type, elem_gt);
       UInt nb_facet_per_elem = facet_to_element.getNbComponent();
 
       Array<Real> & el_q_facet = elements_quad_facets(type, elem_gt);
 
       ElementType facet_type = Mesh::getFacetType(type);
 
       UInt nb_quad_per_facet =
           getFEEngine("FacetsFEEngine").getNbIntegrationPoints(facet_type);
 
       el_q_facet.resize(nb_element * nb_facet_per_elem * nb_quad_per_facet);
 
       for (UInt el = 0; el < nb_element; ++el) {
         for (UInt f = 0; f < nb_facet_per_elem; ++f) {
           Element global_facet_elem = facet_to_element(el, f);
           UInt global_facet = global_facet_elem.element;
           GhostType facet_gt = global_facet_elem.ghost_type;
           const Array<Real> & quad_f = quad_facets(facet_type, facet_gt);
 
           for (UInt q = 0; q < nb_quad_per_facet; ++q) {
             for (UInt s = 0; s < Model::spatial_dimension; ++s) {
               el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet +
                              f * nb_quad_per_facet + q,
                          s) = quad_f(global_facet * nb_quad_per_facet + q, s);
             }
           }
         }
       }
     }
   }
 
   /// loop over non cohesive materials
   for (UInt m = 0; m < materials.size(); ++m) {
     try {
       MaterialCohesive & mat __attribute__((unused)) =
           dynamic_cast<MaterialCohesive &>(*materials[m]);
     } catch (std::bad_cast &) {
       /// initialize the interpolation function
       materials[m]->initElementalFieldInterpolation(elements_quad_facets);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::assembleInternalForces() {
   AKANTU_DEBUG_IN();
 
   // f_int += f_int_cohe
   for (auto & material : this->materials) {
     try {
       MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*material);
       mat.computeTraction(_not_ghost);
     } catch (std::bad_cast & bce) {
     }
   }
 
   SolidMechanicsModel::assembleInternalForces();
 
   if (isDefaultSolverExplicit()) {
     for (auto & material : materials) {
       try {
         MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*material);
         mat.computeEnergies();
       } catch (std::bad_cast & bce) {
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::computeNormals() {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh_facets = this->inserter->getMeshFacets();
   this->getFEEngine("FacetsFEEngine")
       .computeNormalsOnIntegrationPoints(_not_ghost);
 
   /**
    *  @todo store tangents while computing normals instead of
    *  recomputing them as follows:
    */
   /* ------------------------------------------------------------------------ */
   UInt tangent_components =
       Model::spatial_dimension * (Model::spatial_dimension - 1);
 
   tangents.initialize(mesh_facets, _nb_component = tangent_components,
                       _spatial_dimension = Model::spatial_dimension - 1);
   // mesh_facets.initElementTypeMapArray(tangents, tangent_components,
   //                                     Model::spatial_dimension - 1);
 
   for (auto facet_type :
        mesh_facets.elementTypes(Model::spatial_dimension - 1)) {
     const Array<Real> & normals =
         this->getFEEngine("FacetsFEEngine")
             .getNormalsOnIntegrationPoints(facet_type);
 
     Array<Real> & tangents = this->tangents(facet_type);
 
     Math::compute_tangents(normals, tangents);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::interpolateStress() {
 
   ElementTypeMapArray<Real> by_elem_result("temporary_stress_by_facets", id);
 
   for (auto & material : materials) {
     try {
       MaterialCohesive & mat __attribute__((unused)) =
           dynamic_cast<MaterialCohesive &>(*material);
     } catch (std::bad_cast &) {
       /// interpolate stress on facet quadrature points positions
       material->interpolateStressOnFacets(facet_stress, by_elem_result);
     }
   }
 
 #if defined(AKANTU_DEBUG_TOOLS)
   debug::element_manager.printData(
       debug::_dm_model_cohesive, "Interpolated stresses before", facet_stress);
 #endif
 
   this->synchronize(_gst_smmc_facets_stress);
 
 #if defined(AKANTU_DEBUG_TOOLS)
   debug::element_manager.printData(debug::_dm_model_cohesive,
                                    "Interpolated stresses", facet_stress);
 #endif
 }
 
 /* -------------------------------------------------------------------------- */
 UInt SolidMechanicsModelCohesive::checkCohesiveStress() {
   interpolateStress();
 
   for (auto & mat : materials) {
     try {
       MaterialCohesive & mat_cohesive = dynamic_cast<MaterialCohesive &>(*mat);
       /// check which not ghost cohesive elements are to be created
       mat_cohesive.checkInsertion();
     } catch (std::bad_cast &) {
     }
   }
 
   /// communicate data among processors
   this->synchronize(_gst_smmc_facets);
 
   /// insert cohesive elements
   UInt nb_new_elements = inserter->insertElements();
 
   // if (nb_new_elements > 0) {
   //   this->reinitializeSolver();
   // }
 
   return nb_new_elements;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::onElementsAdded(
     const Array<Element> & element_list, const NewElementsEvent & event) {
   AKANTU_DEBUG_IN();
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   updateCohesiveSynchronizers();
 #endif
 
   SolidMechanicsModel::onElementsAdded(element_list, event);
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   if (cohesive_element_synchronizer != NULL)
     cohesive_element_synchronizer->computeAllBufferSizes(*this);
 #endif
 
   /// update shape functions
   getFEEngine("CohesiveFEEngine").initShapeFunctions(_not_ghost);
   getFEEngine("CohesiveFEEngine").initShapeFunctions(_ghost);
 
   if (is_extrinsic)
     resizeFacetStress();
 
   ///  if (method != _explicit_lumped_mass) {
   ///    this->initSolver();
   ///  }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::onNodesAdded(
     const Array<UInt> & doubled_nodes, const NewNodesEvent & event) {
   AKANTU_DEBUG_IN();
 
   UInt nb_new_nodes = doubled_nodes.getSize();
   Array<UInt> nodes_list(nb_new_nodes);
 
   for (UInt n = 0; n < nb_new_nodes; ++n)
     nodes_list(n) = doubled_nodes(n, 1);
 
   SolidMechanicsModel::onNodesAdded(nodes_list, event);
 
   for (UInt n = 0; n < nb_new_nodes; ++n) {
 
     UInt old_node = doubled_nodes(n, 0);
     UInt new_node = doubled_nodes(n, 1);
 
     for (UInt dim = 0; dim < Model::spatial_dimension; ++dim) {
       (*displacement)(new_node, dim) = (*displacement)(old_node, dim);
       (*velocity)(new_node, dim) = (*velocity)(old_node, dim);
       (*acceleration)(new_node, dim) = (*acceleration)(old_node, dim);
       (*blocked_dofs)(new_node, dim) = (*blocked_dofs)(old_node, dim);
 
       if (current_position)
         (*current_position)(new_node, dim) = (*current_position)(old_node, dim);
 
       // if (increment_acceleration)
       //   (*increment_acceleration)(new_node, dim) =
       //       (*increment_acceleration)(old_node, dim);
 
       // if (increment)
       //   (*increment)(new_node, dim) = (*increment)(old_node, dim);
 
       if (previous_displacement)
         (*previous_displacement)(new_node, dim) =
             (*previous_displacement)(old_node, dim);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::onEndSolveStep(const AnalysisMethod &) {
 
   AKANTU_DEBUG_IN();
 
   /*
    * This is required because the Cauchy stress is the stress measure that
    * is used to check the insertion of cohesive elements
    */
   for (auto & mat : materials) {
     if (mat->isFiniteDeformation())
       mat->computeAllCauchyStresses(_not_ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::printself(std::ostream & stream,
                                             int indent) const {
   std::string space;
   for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
     ;
 
   stream << space << "SolidMechanicsModelCohesive [" << std::endl;
 
   SolidMechanicsModel::printself(stream, indent + 1);
 
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::resizeFacetStress() {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh_facets = inserter->getMeshFacets();
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
     GhostType ghost_type = *gt;
 
     Mesh::type_iterator it =
         mesh_facets.firstType(Model::spatial_dimension - 1, ghost_type);
     Mesh::type_iterator end =
         mesh_facets.lastType(Model::spatial_dimension - 1, ghost_type);
     for (; it != end; ++it) {
       ElementType type = *it;
 
       UInt nb_facet = mesh_facets.getNbElement(type, ghost_type);
 
       UInt nb_quadrature_points = getFEEngine("FacetsFEEngine")
                                       .getNbIntegrationPoints(type, ghost_type);
 
       UInt new_size = nb_facet * nb_quadrature_points;
 
       facet_stress(type, ghost_type).resize(new_size);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::addDumpGroupFieldToDumper(
     const std::string & dumper_name, const std::string & field_id,
     const std::string & group_name, const ElementKind & element_kind,
     bool padding_flag) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = Model::spatial_dimension;
   ElementKind _element_kind = element_kind;
   if (dumper_name == "cohesive elements") {
     _element_kind = _ek_cohesive;
   } else if (dumper_name == "facets") {
     spatial_dimension = Model::spatial_dimension - 1;
   }
   SolidMechanicsModel::addDumpGroupFieldToDumper(
       dumper_name, field_id, group_name, spatial_dimension,
       _element_kind, padding_flag);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 void SolidMechanicsModelCohesive::onDump() {
   this->flattenAllRegisteredInternals(_ek_cohesive);
   SolidMechanicsModel::onDump();
 }
 
 /* -------------------------------------------------------------------------- */
 
 } // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh
index ffde2e79a..dbd59372a 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh
@@ -1,296 +1,297 @@
 /**
  * @file   solid_mechanics_model_cohesive.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Tue May 08 2012
  * @date last modification: Mon Dec 14 2015
  *
  * @brief  Solid mechanics model for cohesive elements
  *
  * @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_SOLID_MECHANICS_MODEL_COHESIVE_HH__
 #define __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__
 
 #include "cohesive_element_inserter.hh"
 #include "material_selector_cohesive.hh"
 #include "solid_mechanics_model.hh"
 #include "solid_mechanics_model_event_handler.hh"
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
 #include "facet_stress_synchronizer.hh"
 #include "facet_synchronizer.hh"
 #endif
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 struct FacetsCohesiveIntegrationOrderFunctor {
   template <ElementType type, ElementType cohesive_type =
                                   CohesiveFacetProperty<type>::cohesive_type>
   struct _helper {
     static constexpr int get() {
       return ElementClassProperty<cohesive_type>::polynomial_degree;
     }
   };
 
   template <ElementType type> struct _helper<type, _not_defined> {
     static constexpr int get() {
       return ElementClassProperty<type>::polynomial_degree;
     }
   };
 
   template <ElementType type> static inline constexpr int getOrder() {
     return _helper<type>::get();
   }
 };
 
 /* -------------------------------------------------------------------------- */
 struct SolidMechanicsModelCohesiveOptions : public SolidMechanicsModelOptions {
   SolidMechanicsModelCohesiveOptions(
       AnalysisMethod analysis_method = _explicit_lumped_mass,
-      bool extrinsic = false, bool no_init_materials = false)
-      : SolidMechanicsModelOptions(analysis_method, no_init_materials),
-        extrinsic(extrinsic) {}
+      bool extrinsic = false)
+      : SolidMechanicsModelOptions(analysis_method), extrinsic(extrinsic) {}
 
   template <typename... pack>
   SolidMechanicsModelCohesiveOptions(use_named_args_t, pack &&... _pack)
       : SolidMechanicsModelOptions(
             OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass),
-            OPTIONAL_NAMED_ARG(is_extrinsic, false),
-            OPTIONAL_NAMED_ARG(no_init_materials, false)) {}
+            OPTIONAL_NAMED_ARG(is_extrinsic, false)) {}
 
-  bool extrinsic;
+  bool extrinsic{false};
 };
 
 /* -------------------------------------------------------------------------- */
 /* Solid Mechanics Model for Cohesive elements                                */
 /* -------------------------------------------------------------------------- */
 
 class SolidMechanicsModelCohesive : public SolidMechanicsModel,
                                     public SolidMechanicsModelEventHandler {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   class NewCohesiveNodesEvent : public NewNodesEvent {
   public:
     AKANTU_GET_MACRO_NOT_CONST(OldNodesList, old_nodes, Array<UInt> &);
     AKANTU_GET_MACRO(OldNodesList, old_nodes, const Array<UInt> &);
 
   protected:
     Array<UInt> old_nodes;
   };
 
   typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive>
       MyFEEngineCohesiveType;
   typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular,
                            FacetsCohesiveIntegrationOrderFunctor>
       MyFEEngineFacetType;
 
   SolidMechanicsModelCohesive(Mesh & mesh,
                               UInt spatial_dimension = _all_dimensions,
                               const ID & id = "solid_mechanics_model_cohesive",
                               const MemoryID & memory_id = 0);
 
   virtual ~SolidMechanicsModelCohesive();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// set the value of the time step
   void setTimeStep(Real time_step);
 
   /// assemble the residual for the explicit scheme
   virtual void assembleInternalForces();
 
   /// function to print the contain of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /// function to perform a stress check on each facet and insert
   /// cohesive elements if needed (returns the number of new cohesive
   /// elements)
   UInt checkCohesiveStress();
 
   /// interpolate stress on facets
   void interpolateStress();
 
   /// initialize the cohesive model
-  void initFull(const ModelOptions & options = SolidMechanicsModelCohesiveOptions());
+  void
+  initFull(const ModelOptions & options = SolidMechanicsModelCohesiveOptions());
 
   template <typename P, typename T, typename... pack>
   void initFull(named_argument::param_t<P, T &&> && first, pack &&... _pack) {
-    this->initFull(SolidMechanicsModelCohesiveOptions{use_named_args, first, _pack...});
+    this->initFull(
+        SolidMechanicsModelCohesiveOptions{use_named_args, first, _pack...});
   }
 
   /// initialize the model
   void initModel();
 
   /// initialize cohesive material
   void initMaterials();
 
   /// init facet filters for cohesive materials
   void initFacetFilter();
 
   /// limit the cohesive element insertion to a given area
   void limitInsertion(BC::Axis axis, Real first_limit, Real second_limit);
 
   /// update automatic insertion after a change in the element inserter
   void updateAutomaticInsertion();
 
   /// insert intrinsic cohesive elements
   void insertIntrinsicElements();
 
   // synchronize facets physical data before insertion along physical surfaces
   void synchronizeInsertionData();
 
-  // template <SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria>
-  // bool solveStepCohesive(Real tolerance, Real & error, UInt max_iteration = 100,
+  // template <SolveConvergenceMethod cmethod, SolveConvergenceCriteria
+  // criteria> bool solveStepCohesive(Real tolerance, Real & error, UInt
+  // max_iteration = 100,
   //                        bool load_reduction = false,
   //                        Real tol_increase_factor = 1.0,
   //                        bool do_not_factorize = false);
 
   /// initialize stress interpolation
   void initStressInterpolation();
 
 private:
   /// initialize cohesive material with intrinsic insertion (by default)
   void initIntrinsicCohesiveMaterials(UInt cohesive_index);
 
   ///  initialize cohesive material with intrinsic insertion (if physical
   ///  surfaces are precised)
   void initIntrinsicCohesiveMaterials(std::string cohesive_surfaces);
 
   /// insert cohesive elements along a given physical surface of the mesh
   void insertElementsFromMeshData(std::string physical_name);
 
   /// initialize completely the model for extrinsic elements
   void initAutomaticInsertion();
 
   /// compute facets' normals
   void computeNormals();
 
   /// resize facet stress
   void resizeFacetStress();
 
   /// init facets_check array
   void initFacetsCheck();
 
   /* ------------------------------------------------------------------------ */
   /* Mesh Event Handler inherited members                                     */
   /* ------------------------------------------------------------------------ */
 
 protected:
   virtual void onNodesAdded(const Array<UInt> & nodes_list,
                             const NewNodesEvent & event);
   virtual void onElementsAdded(const Array<Element> & nodes_list,
                                const NewElementsEvent & event);
 
   /* ------------------------------------------------------------------------ */
   /* SolidMechanicsModelEventHandler inherited members                        */
   /* ------------------------------------------------------------------------ */
 public:
   virtual void onEndSolveStep(const AnalysisMethod & method);
 
   /* ------------------------------------------------------------------------ */
   /* Dumpable interface                                                       */
   /* ------------------------------------------------------------------------ */
 public:
   virtual void onDump();
 
   virtual void addDumpGroupFieldToDumper(const std::string & dumper_name,
                                          const std::string & field_id,
                                          const std::string & group_name,
                                          const ElementKind & element_kind,
                                          bool padding_flag);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// get facet mesh
   AKANTU_GET_MACRO(MeshFacets, mesh.getMeshFacets(), const Mesh &);
 
   /// get stress on facets vector
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(StressOnFacets, facet_stress, Real);
 
   /// get facet material
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetMaterial, facet_material, UInt);
 
   /// get facet material
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetMaterial, facet_material, UInt);
 
   /// get facet material
   AKANTU_GET_MACRO(FacetMaterial, facet_material,
                    const ElementTypeMapArray<UInt> &);
 
   /// @todo THIS HAS TO BE CHANGED
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Tangents, tangents, Real);
 
   /// get element inserter
   AKANTU_GET_MACRO_NOT_CONST(ElementInserter, *inserter,
                              CohesiveElementInserter &);
 
   /// get is_extrinsic boolean
   AKANTU_GET_MACRO(IsExtrinsic, is_extrinsic, bool);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   /// @todo store tangents when normals are computed:
   ElementTypeMapArray<Real> tangents;
 
   /// stress on facets on the two sides by quadrature point
   ElementTypeMapArray<Real> facet_stress;
 
   /// material to use if a cohesive element is created on a facet
   ElementTypeMapArray<UInt> facet_material;
 
   bool is_extrinsic;
 
   /// cohesive element inserter
   CohesiveElementInserter * inserter;
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
 #include "solid_mechanics_model_cohesive_parallel.hh"
 #endif
 };
 
 /* -------------------------------------------------------------------------- */
 /// standard output stream operator
 inline std::ostream & operator<<(std::ostream & stream,
                                  const SolidMechanicsModelCohesive & _this) {
   _this.printself(stream);
   return stream;
 }
 
-} // akantu
+} // namespace akantu
 
 #include "solid_mechanics_model_cohesive_inline_impl.cc"
 
 #endif /* __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc
index beba5e53b..4e25fafbd 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc
@@ -1,397 +1,426 @@
 /**
  * @file   solid_mechanics_model_inline_impl.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Aug 04 2010
  * @date last modification: Wed Nov 18 2015
  *
- * @brief  Implementation of the inline functions of the SolidMechanicsModel class
+ * @brief  Implementation of the inline functions of the SolidMechanicsModel
+ * class
  *
  * @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_named_argument.hh"
+#include "material_selector.hh"
 #include "solid_mechanics_model.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_SOLID_MECHANICS_MODEL_INLINE_IMPL_CC__
 #define __AKANTU_SOLID_MECHANICS_MODEL_INLINE_IMPL_CC__
 
 namespace akantu {
 
+/* -------------------------------------------------------------------------- */
+inline SolidMechanicsModelOptions::SolidMechanicsModelOptions(
+    AnalysisMethod analysis_method)
+    : analysis_method(analysis_method) {}
+
+/* -------------------------------------------------------------------------- */
+template <typename... pack>
+SolidMechanicsModelOptions::SolidMechanicsModelOptions(use_named_args_t,
+                                                       pack &&... _pack)
+    : SolidMechanicsModelOptions(
+          OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass)) {}
+
 /* -------------------------------------------------------------------------- */
 inline Material & SolidMechanicsModel::getMaterial(UInt mat_index) {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT(mat_index < materials.size(),
-                      "The model " << id << " has no material no "<< mat_index);
+                      "The model " << id << " has no material no "
+                                   << mat_index);
   AKANTU_DEBUG_OUT();
   return *materials[mat_index];
 }
 
 /* -------------------------------------------------------------------------- */
 inline const Material & SolidMechanicsModel::getMaterial(UInt mat_index) const {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT(mat_index < materials.size(),
-                     "The model " << id << " has no material no "<< mat_index);
+                      "The model " << id << " has no material no "
+                                   << mat_index);
   AKANTU_DEBUG_OUT();
   return *materials[mat_index];
 }
 
 /* -------------------------------------------------------------------------- */
 inline Material & SolidMechanicsModel::getMaterial(const std::string & name) {
   AKANTU_DEBUG_IN();
-  std::map<std::string, UInt>::const_iterator it = materials_names_to_id.find(name);
+  std::map<std::string, UInt>::const_iterator it =
+      materials_names_to_id.find(name);
   AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(),
-                     "The model " << id << " has no material named "<< name);
+                      "The model " << id << " has no material named " << name);
   AKANTU_DEBUG_OUT();
   return *materials[it->second];
 }
 
 /* -------------------------------------------------------------------------- */
-inline UInt SolidMechanicsModel::getMaterialIndex(const std::string & name) const {
+inline UInt
+SolidMechanicsModel::getMaterialIndex(const std::string & name) const {
   AKANTU_DEBUG_IN();
-  std::map<std::string, UInt>::const_iterator it = materials_names_to_id.find(name);
+  std::map<std::string, UInt>::const_iterator it =
+      materials_names_to_id.find(name);
   AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(),
-                      "The model " << id << " has no material named "<< name);
+                      "The model " << id << " has no material named " << name);
   AKANTU_DEBUG_OUT();
   return it->second;
 }
 
 /* -------------------------------------------------------------------------- */
-inline const Material & SolidMechanicsModel::getMaterial(const std::string & name) const {
+inline const Material &
+SolidMechanicsModel::getMaterial(const std::string & name) const {
   AKANTU_DEBUG_IN();
-  std::map<std::string, UInt>::const_iterator it = materials_names_to_id.find(name);
+  std::map<std::string, UInt>::const_iterator it =
+      materials_names_to_id.find(name);
   AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(),
-                      "The model " << id << " has no material named "<< name);
+                      "The model " << id << " has no material named " << name);
   AKANTU_DEBUG_OUT();
   return *materials[it->second];
 }
 
 /* -------------------------------------------------------------------------- */
-inline void SolidMechanicsModel::setMaterialSelector(MaterialSelector & selector) {
-  if(is_default_material_selector) delete material_selector;
+inline void
+SolidMechanicsModel::setMaterialSelector(MaterialSelector & selector) {
+  if (is_default_material_selector)
+    delete material_selector;
   material_selector = &selector;
   is_default_material_selector = false;
 }
 
 /* -------------------------------------------------------------------------- */
 inline FEEngine & SolidMechanicsModel::getFEEngineBoundary(const ID & name) {
-  return dynamic_cast<FEEngine &>(getFEEngineClassBoundary<MyFEEngineType>(name));
+  return dynamic_cast<FEEngine &>(
+      getFEEngineClassBoundary<MyFEEngineType>(name));
 }
 
 /* -------------------------------------------------------------------------- */
-inline void SolidMechanicsModel::splitElementByMaterial(const Array<Element> & elements,
-                                                       Array<Element> * elements_per_mat) const {
+inline void SolidMechanicsModel::splitElementByMaterial(
+    const Array<Element> & elements, Array<Element> * elements_per_mat) const {
   ElementType current_element_type = _not_defined;
   GhostType current_ghost_type = _casper;
   const Array<UInt> * mat_indexes = NULL;
   const Array<UInt> * mat_loc_num = NULL;
 
-  Array<Element>::const_iterator<Element> it  = elements.begin();
+  Array<Element>::const_iterator<Element> it = elements.begin();
   Array<Element>::const_iterator<Element> end = elements.end();
   for (; it != end; ++it) {
     Element el = *it;
 
-    if(el.type != current_element_type || el.ghost_type != current_ghost_type) {
+    if (el.type != current_element_type ||
+        el.ghost_type != current_ghost_type) {
       current_element_type = el.type;
-      current_ghost_type   = el.ghost_type;
+      current_ghost_type = el.ghost_type;
       mat_indexes = &(this->material_index(el.type, el.ghost_type));
       mat_loc_num = &(this->material_local_numbering(el.type, el.ghost_type));
     }
 
     UInt old_id = el.element;
     el.element = (*mat_loc_num)(old_id);
     elements_per_mat[(*mat_indexes)(old_id)].push_back(el);
   }
 }
 
 /* -------------------------------------------------------------------------- */
-inline UInt SolidMechanicsModel::getNbData(const Array<Element> & elements,
-                                           const SynchronizationTag & tag) const {
+inline UInt
+SolidMechanicsModel::getNbData(const Array<Element> & elements,
+                               const SynchronizationTag & tag) const {
   AKANTU_DEBUG_IN();
 
   UInt size = 0;
   UInt nb_nodes_per_element = 0;
 
-  Array<Element>::const_iterator<Element> it  = elements.begin();
+  Array<Element>::const_iterator<Element> it = elements.begin();
   Array<Element>::const_iterator<Element> end = elements.end();
   for (; it != end; ++it) {
     const Element & el = *it;
     nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type);
   }
 
-  switch(tag) {
+  switch (tag) {
   case _gst_material_id: {
     size += elements.getSize() * sizeof(UInt);
     break;
   }
   case _gst_smm_mass: {
-    size += nb_nodes_per_element * sizeof(Real) * Model::spatial_dimension; // mass vector
+    size += nb_nodes_per_element * sizeof(Real) *
+            Model::spatial_dimension; // mass vector
     break;
   }
   case _gst_smm_for_gradu: {
-    size += nb_nodes_per_element * Model::spatial_dimension * sizeof(Real); // displacement
-   break;
+    size += nb_nodes_per_element * Model::spatial_dimension *
+            sizeof(Real); // displacement
+    break;
   }
   case _gst_smm_boundary: {
     // force, displacement, boundary
-    size += nb_nodes_per_element * Model::spatial_dimension * (2 * sizeof(Real) + sizeof(bool));
+    size += nb_nodes_per_element * Model::spatial_dimension *
+            (2 * sizeof(Real) + sizeof(bool));
     break;
   }
   case _gst_for_dump: {
     // displacement, velocity, acceleration, residual, force
     size += nb_nodes_per_element * Model::spatial_dimension * sizeof(Real) * 5;
     break;
   }
-  default: {  }
+  default: {}
   }
 
-  if(tag != _gst_material_id) {
+  if (tag != _gst_material_id) {
     Array<Element> * elements_per_mat = new Array<Element>[materials.size()];
     this->splitElementByMaterial(elements, elements_per_mat);
 
     for (UInt i = 0; i < materials.size(); ++i) {
       size += materials[i]->getNbData(elements_per_mat[i], tag);
     }
-    delete [] elements_per_mat;
+    delete[] elements_per_mat;
   }
 
   AKANTU_DEBUG_OUT();
   return size;
 }
 
 /* -------------------------------------------------------------------------- */
-inline void SolidMechanicsModel::packData(CommunicationBuffer & buffer,
-                                          const Array<Element> & elements,
-                                          const SynchronizationTag & tag) const {
+inline void
+SolidMechanicsModel::packData(CommunicationBuffer & buffer,
+                              const Array<Element> & elements,
+                              const SynchronizationTag & tag) const {
   AKANTU_DEBUG_IN();
 
-  switch(tag) {
+  switch (tag) {
   case _gst_material_id: {
-    this->packElementalDataHelper(material_index, buffer, elements, false, getFEEngine());
+    this->packElementalDataHelper(material_index, buffer, elements, false,
+                                  getFEEngine());
     break;
   }
   case _gst_smm_mass: {
     packNodalDataHelper(*mass, buffer, elements, mesh);
     break;
   }
   case _gst_smm_for_gradu: {
     packNodalDataHelper(*displacement, buffer, elements, mesh);
     break;
   }
   case _gst_for_dump: {
     packNodalDataHelper(*displacement, buffer, elements, mesh);
     packNodalDataHelper(*velocity, buffer, elements, mesh);
     packNodalDataHelper(*acceleration, buffer, elements, mesh);
     packNodalDataHelper(*internal_force, buffer, elements, mesh);
     packNodalDataHelper(*external_force, buffer, elements, mesh);
     break;
   }
   case _gst_smm_boundary: {
     packNodalDataHelper(*external_force, buffer, elements, mesh);
     packNodalDataHelper(*velocity, buffer, elements, mesh);
     packNodalDataHelper(*blocked_dofs, buffer, elements, mesh);
     break;
   }
-  default: {
-  }
+  default: {}
   }
 
-  if(tag != _gst_material_id) {
+  if (tag != _gst_material_id) {
     Array<Element> * elements_per_mat = new Array<Element>[materials.size()];
     splitElementByMaterial(elements, elements_per_mat);
 
     for (UInt i = 0; i < materials.size(); ++i) {
       materials[i]->packData(buffer, elements_per_mat[i], tag);
     }
 
-    delete [] elements_per_mat;
+    delete[] elements_per_mat;
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 inline void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer,
                                             const Array<Element> & elements,
                                             const SynchronizationTag & tag) {
   AKANTU_DEBUG_IN();
 
-  switch(tag) {
+  switch (tag) {
   case _gst_material_id: {
-    unpackElementalDataHelper(material_index, buffer, elements,
-                             false, getFEEngine());
+    unpackElementalDataHelper(material_index, buffer, elements, false,
+                              getFEEngine());
     break;
   }
   case _gst_smm_mass: {
     unpackNodalDataHelper(*mass, buffer, elements, mesh);
     break;
   }
   case _gst_smm_for_gradu: {
     unpackNodalDataHelper(*displacement, buffer, elements, mesh);
     break;
   }
   case _gst_for_dump: {
     unpackNodalDataHelper(*displacement, buffer, elements, mesh);
     unpackNodalDataHelper(*velocity, buffer, elements, mesh);
     unpackNodalDataHelper(*acceleration, buffer, elements, mesh);
     unpackNodalDataHelper(*internal_force, buffer, elements, mesh);
     unpackNodalDataHelper(*external_force, buffer, elements, mesh);
     break;
   }
   case _gst_smm_boundary: {
     unpackNodalDataHelper(*external_force, buffer, elements, mesh);
     unpackNodalDataHelper(*velocity, buffer, elements, mesh);
     unpackNodalDataHelper(*blocked_dofs, buffer, elements, mesh);
     break;
   }
-  default: {
-  }
+  default: {}
   }
 
-  if(tag != _gst_material_id) {
+  if (tag != _gst_material_id) {
     Array<Element> * elements_per_mat = new Array<Element>[materials.size()];
     splitElementByMaterial(elements, elements_per_mat);
 
     for (UInt i = 0; i < materials.size(); ++i) {
       materials[i]->unpackData(buffer, elements_per_mat[i], tag);
     }
 
-    delete [] elements_per_mat;
+    delete[] elements_per_mat;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
-
 /* -------------------------------------------------------------------------- */
-inline UInt SolidMechanicsModel::getNbData(const Array<UInt> & dofs,
-                                           const SynchronizationTag & tag) const {
+inline UInt
+SolidMechanicsModel::getNbData(const Array<UInt> & dofs,
+                               const SynchronizationTag & tag) const {
   AKANTU_DEBUG_IN();
 
   UInt size = 0;
   //  UInt nb_nodes = mesh.getNbNodes();
 
-  switch(tag) {
+  switch (tag) {
   case _gst_smm_uv: {
     size += sizeof(Real) * Model::spatial_dimension * 2;
     break;
   }
   case _gst_smm_res: {
     size += sizeof(Real) * Model::spatial_dimension;
     break;
   }
   case _gst_smm_mass: {
     size += sizeof(Real) * Model::spatial_dimension;
     break;
   }
   case _gst_for_dump: {
     size += sizeof(Real) * Model::spatial_dimension * 5;
     break;
   }
   default: {
     AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
   AKANTU_DEBUG_OUT();
   return size * dofs.getSize();
 }
 
-
 /* -------------------------------------------------------------------------- */
-inline void SolidMechanicsModel::packData(CommunicationBuffer & buffer,
-                                          const Array<UInt> & dofs,
-                                          const SynchronizationTag & tag) const {
+inline void
+SolidMechanicsModel::packData(CommunicationBuffer & buffer,
+                              const Array<UInt> & dofs,
+                              const SynchronizationTag & tag) const {
   AKANTU_DEBUG_IN();
 
-  switch(tag) {
+  switch (tag) {
   case _gst_smm_uv: {
     packDOFDataHelper(*displacement, buffer, dofs);
-    packDOFDataHelper(*velocity    , buffer, dofs);
+    packDOFDataHelper(*velocity, buffer, dofs);
     break;
   }
   case _gst_smm_res: {
     packDOFDataHelper(*internal_force, buffer, dofs);
     break;
   }
   case _gst_smm_mass: {
     packDOFDataHelper(*mass, buffer, dofs);
     break;
   }
   case _gst_for_dump: {
-    packDOFDataHelper(*displacement  , buffer, dofs);
-    packDOFDataHelper(*velocity      , buffer, dofs);
-    packDOFDataHelper(*acceleration  , buffer, dofs);
+    packDOFDataHelper(*displacement, buffer, dofs);
+    packDOFDataHelper(*velocity, buffer, dofs);
+    packDOFDataHelper(*acceleration, buffer, dofs);
     packDOFDataHelper(*internal_force, buffer, dofs);
     packDOFDataHelper(*external_force, buffer, dofs);
     break;
   }
   default: {
     AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 inline void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer,
                                             const Array<UInt> & dofs,
                                             const SynchronizationTag & tag) {
   AKANTU_DEBUG_IN();
 
-
-  switch(tag) {
+  switch (tag) {
   case _gst_smm_uv: {
     unpackDOFDataHelper(*displacement, buffer, dofs);
-    unpackDOFDataHelper(*velocity    , buffer, dofs);
+    unpackDOFDataHelper(*velocity, buffer, dofs);
     break;
   }
   case _gst_smm_res: {
     unpackDOFDataHelper(*internal_force, buffer, dofs);
     break;
   }
   case _gst_smm_mass: {
     unpackDOFDataHelper(*mass, buffer, dofs);
     break;
   }
   case _gst_for_dump: {
-    unpackDOFDataHelper(*displacement  , buffer, dofs);
-    unpackDOFDataHelper(*velocity      , buffer, dofs);
-    unpackDOFDataHelper(*acceleration  , buffer, dofs);
+    unpackDOFDataHelper(*displacement, buffer, dofs);
+    unpackDOFDataHelper(*velocity, buffer, dofs);
+    unpackDOFDataHelper(*acceleration, buffer, dofs);
     unpackDOFDataHelper(*internal_force, buffer, dofs);
     unpackDOFDataHelper(*external_force, buffer, dofs);
     break;
   }
   default: {
     AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
-} // akantu
+} // namespace akantu
 
 #endif /* __AKANTU_SOLID_MECHANICS_MODEL_INLINE_IMPL_CC__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_io.cc b/src/model/solid_mechanics/solid_mechanics_model_io.cc
new file mode 100644
index 000000000..f1534d53c
--- /dev/null
+++ b/src/model/solid_mechanics/solid_mechanics_model_io.cc
@@ -0,0 +1,329 @@
+/**
+ * @file   solid_mechanics_model_io.cc
+ *
+ * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
+ * @author David Simon Kammer <david.kammer@epfl.ch>
+ *
+ * @date creation  Fri Jul 07 2017
+ *
+ * @brief Dumpable part of the SolidMechnicsModel
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free  software: you can redistribute it and/or  modify it under the
+ * terms  of the  GNU Lesser  General Public  License as  published by  the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
+ * details.
+ *
+ * You should  have received  a copy  of the GNU  Lesser General  Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+#include "solid_mechanics_model.hh"
+
+#include "group_manager_inline_impl.cc"
+
+#include "dumpable_inline_impl.hh"
+#ifdef AKANTU_USE_IOHELPER
+#include "dumper_element_partition.hh"
+#include "dumper_elemental_field.hh"
+#include "dumper_field.hh"
+#include "dumper_homogenizing_field.hh"
+#include "dumper_internal_material_field.hh"
+#include "dumper_iohelper.hh"
+#include "dumper_material_padders.hh"
+#include "dumper_paraview.hh"
+#endif
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+bool SolidMechanicsModel::isInternal(const std::string & field_name,
+                                     const ElementKind & element_kind) {
+  /// check if at least one material contains field_id as an internal
+  for (auto & material : materials) {
+    bool is_internal = material->isInternal<Real>(field_name, element_kind);
+    if (is_internal)
+      return true;
+  }
+
+  return false;
+}
+
+/* -------------------------------------------------------------------------- */
+ElementTypeMap<UInt>
+SolidMechanicsModel::getInternalDataPerElem(const std::string & field_name,
+                                            const ElementKind & element_kind) {
+
+  if (!(this->isInternal(field_name, element_kind)))
+    AKANTU_EXCEPTION("unknown internal " << field_name);
+
+  for (auto & material : materials) {
+    if (material->isInternal<Real>(field_name, element_kind))
+      return material->getInternalDataPerElem<Real>(field_name, element_kind);
+  }
+
+  return ElementTypeMap<UInt>();
+}
+
+/* -------------------------------------------------------------------------- */
+ElementTypeMapArray<Real> &
+SolidMechanicsModel::flattenInternal(const std::string & field_name,
+                                     const ElementKind & kind,
+                                     const GhostType ghost_type) {
+  std::pair<std::string, ElementKind> key(field_name, kind);
+  if (this->registered_internals.count(key) == 0) {
+    this->registered_internals[key] =
+        new ElementTypeMapArray<Real>(field_name, this->id, this->memory_id);
+  }
+
+  ElementTypeMapArray<Real> * internal_flat = this->registered_internals[key];
+
+  for (auto type :
+       mesh.elementTypes(Model::spatial_dimension, ghost_type, kind)) {
+    if (internal_flat->exists(type, ghost_type)) {
+      auto & internal = (*internal_flat)(type, ghost_type);
+      // internal.clear();
+      internal.resize(0);
+    }
+  }
+
+  for (auto & material : materials) {
+    if (material->isInternal<Real>(field_name, kind))
+      material->flattenInternal(field_name, *internal_flat, ghost_type, kind);
+  }
+
+  return *internal_flat;
+}
+
+/* -------------------------------------------------------------------------- */
+void SolidMechanicsModel::flattenAllRegisteredInternals(
+    const ElementKind & kind) {
+  ElementKind _kind;
+  ID _id;
+
+  for (auto & internal : this->registered_internals) {
+    std::tie(_id, _kind) = internal.first;
+    if (kind == _kind)
+      this->flattenInternal(_id, kind);
+  }
+}
+
+/* -------------------------------------------------------------------------- */
+void SolidMechanicsModel::onDump() {
+  this->flattenAllRegisteredInternals(_ek_regular);
+}
+
+/* -------------------------------------------------------------------------- */
+#ifdef AKANTU_USE_IOHELPER
+dumper::Field * SolidMechanicsModel::createElementalField(
+    const std::string & field_name, const std::string & group_name,
+    bool padding_flag, const UInt & spatial_dimension,
+    const ElementKind & kind) {
+
+  dumper::Field * field = nullptr;
+
+  if (field_name == "partitions")
+    field = mesh.createElementalField<UInt, dumper::ElementPartitionField>(
+        mesh.getConnectivities(), group_name, spatial_dimension, kind);
+  else if (field_name == "material_index")
+    field = mesh.createElementalField<UInt, Vector, dumper::ElementalField>(
+        material_index, group_name, spatial_dimension, kind);
+  else {
+    // this copy of field_name is used to compute derivated data such as
+    // strain and von mises stress that are based on grad_u and stress
+    std::string field_name_copy(field_name);
+
+    if (field_name == "strain" || field_name == "Green strain" ||
+        field_name == "principal strain" ||
+        field_name == "principal Green strain")
+      field_name_copy = "grad_u";
+    else if (field_name == "Von Mises stress")
+      field_name_copy = "stress";
+
+    bool is_internal = this->isInternal(field_name_copy, kind);
+
+    if (is_internal) {
+      ElementTypeMap<UInt> nb_data_per_elem =
+          this->getInternalDataPerElem(field_name_copy, kind);
+      ElementTypeMapArray<Real> & internal_flat =
+          this->flattenInternal(field_name_copy, kind);
+      field = mesh.createElementalField<Real, dumper::InternalMaterialField>(
+          internal_flat, group_name, spatial_dimension, kind, nb_data_per_elem);
+      if (field_name == "strain") {
+        dumper::ComputeStrain<false> * foo =
+            new dumper::ComputeStrain<false>(*this);
+        field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
+      } else if (field_name == "Von Mises stress") {
+        dumper::ComputeVonMisesStress * foo =
+            new dumper::ComputeVonMisesStress(*this);
+        field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
+      } else if (field_name == "Green strain") {
+        dumper::ComputeStrain<true> * foo =
+            new dumper::ComputeStrain<true>(*this);
+        field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
+      } else if (field_name == "principal strain") {
+        dumper::ComputePrincipalStrain<false> * foo =
+            new dumper::ComputePrincipalStrain<false>(*this);
+        field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
+      } else if (field_name == "principal Green strain") {
+        dumper::ComputePrincipalStrain<true> * foo =
+            new dumper::ComputePrincipalStrain<true>(*this);
+        field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
+      }
+
+      // treat the paddings
+      if (padding_flag) {
+        if (field_name == "stress") {
+          if (spatial_dimension == 2) {
+            dumper::StressPadder<2> * foo = new dumper::StressPadder<2>(*this);
+            field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
+          }
+        } else if (field_name == "strain" || field_name == "Green strain") {
+          if (spatial_dimension == 2) {
+            dumper::StrainPadder<2> * foo = new dumper::StrainPadder<2>(*this);
+            field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
+          }
+        }
+      }
+
+      // homogenize the field
+      dumper::ComputeFunctorInterface * foo =
+          dumper::HomogenizerProxy::createHomogenizer(*field);
+
+      field = dumper::FieldComputeProxy::createFieldCompute(field, *foo);
+    }
+  }
+  return field;
+}
+
+/* -------------------------------------------------------------------------- */
+dumper::Field *
+SolidMechanicsModel::createNodalFieldReal(const std::string & field_name,
+                                          const std::string & group_name,
+                                          bool padding_flag) {
+
+  std::map<std::string, Array<Real> *> real_nodal_fields;
+  real_nodal_fields["displacement"] = this->displacement;
+  real_nodal_fields["mass"] = this->mass;
+  real_nodal_fields["velocity"] = this->velocity;
+  real_nodal_fields["acceleration"] = this->acceleration;
+  real_nodal_fields["external_force"] = this->external_force;
+  real_nodal_fields["internal_force"] = this->internal_force;
+  real_nodal_fields["increment"] = this->displacement_increment;
+
+  if (field_name == "force") {
+    AKANTU_EXCEPTION("The 'force' field has been renamed in 'external_force'");
+  } else if (field_name == "residual") {
+    AKANTU_EXCEPTION(
+        "The 'residual' field has been replaced by 'internal_force'");
+  }
+
+  dumper::Field * field = nullptr;
+  if (padding_flag)
+    field = this->mesh.createNodalField(real_nodal_fields[field_name],
+                                        group_name, 3);
+  else
+    field =
+        this->mesh.createNodalField(real_nodal_fields[field_name], group_name);
+
+  return field;
+}
+
+/* -------------------------------------------------------------------------- */
+dumper::Field * SolidMechanicsModel::createNodalFieldBool(
+    const std::string & field_name, const std::string & group_name,
+    __attribute__((unused)) bool padding_flag) {
+
+  std::map<std::string, Array<bool> *> uint_nodal_fields;
+  uint_nodal_fields["blocked_dofs"] = blocked_dofs;
+
+  dumper::Field * field = nullptr;
+  field = mesh.createNodalField(uint_nodal_fields[field_name], group_name);
+  return field;
+}
+/* -------------------------------------------------------------------------- */
+#else
+/* -------------------------------------------------------------------------- */
+dumper::Field * SolidMechanicsModel::createElementalField(const std::string &,
+                                                          const std::string &,
+                                                          bool, const UInt &,
+                                                          const ElementKind &) {
+  return nullptr;
+}
+/* --------------------------------------------------------------------------
+ */
+dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string &,
+                                                          const std::string &,
+                                                          bool) {
+  return nullptr;
+}
+
+/* --------------------------------------------------------------------------
+ */
+dumper::Field * SolidMechanicsModel::createNodalFieldBool(const std::string &,
+                                                          const std::string &,
+                                                          bool) {
+  return nullptr;
+}
+
+#endif
+/* --------------------------------------------------------------------------
+ */
+void SolidMechanicsModel::dump(const std::string & dumper_name) {
+  this->onDump();
+  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
+  mesh.dump(dumper_name);
+}
+
+/* --------------------------------------------------------------------------
+ */
+void SolidMechanicsModel::dump(const std::string & dumper_name, UInt step) {
+  this->onDump();
+  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
+  mesh.dump(dumper_name, step);
+}
+
+/* -------------------------------------------------------------------------
+ */
+void SolidMechanicsModel::dump(const std::string & dumper_name, Real time,
+                               UInt step) {
+  this->onDump();
+  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
+  mesh.dump(dumper_name, time, step);
+}
+
+/* -------------------------------------------------------------------------- */
+void SolidMechanicsModel::dump() {
+  this->onDump();
+  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
+  mesh.dump();
+}
+
+/* -------------------------------------------------------------------------- */
+void SolidMechanicsModel::dump(UInt step) {
+  this->onDump();
+  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
+  mesh.dump(step);
+}
+
+/* -------------------------------------------------------------------------- */
+void SolidMechanicsModel::dump(Real time, UInt step) {
+  this->onDump();
+  EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
+  mesh.dump(time, step);
+}
+
+} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_material.cc b/src/model/solid_mechanics/solid_mechanics_model_material.cc
index fde420a9c..211e8f560 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_material.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_material.cc
@@ -1,334 +1,315 @@
 /**
  * @file   solid_mechanics_model_material.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Nov 26 2010
  * @date last modification: Mon Nov 16 2015
  *
  * @brief  instatiation of materials
  *
  * @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_factory.hh"
 #include "aka_math.hh"
-#include "material_list.hh"
+//#include "material_list.hh"
 #include "solid_mechanics_model.hh"
 #ifdef AKANTU_DAMAGE_NON_LOCAL
 #include "non_local_manager.hh"
 #endif
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
-#define AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL(dim, elem)                   \
-  registerNewMaterial<BOOST_PP_ARRAY_ELEM(1, elem) < dim>> (section)
-
-#define AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL_EACH(r, data, i, elem)          \
-  BOOST_PP_EXPR_IF(BOOST_PP_NOT_EQUAL(0, i), else)                             \
-  if (opt_param == BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem))) {      \
-    registerNewMaterial<BOOST_PP_ARRAY_ELEM(1, data) <                         \
-                            BOOST_PP_ARRAY_ELEM(0, data),                      \
-                        BOOST_PP_SEQ_ENUM(BOOST_PP_TUPLE_ELEM(2, 1, elem))>>   \
-        (section);                                                             \
+Material &
+SolidMechanicsModel::registerNewMaterial(const ParserSection & section) {
+  std::string mat_name;
+  std::string mat_type = section.getName();
+  std::string opt_param = section.getOption();
+
+  try {
+    std::string tmp = section.getParameter("name");
+    mat_name = tmp; /** this can seam weird, but there is an ambiguous operator
+                     * overload that i couldn't solve. @todo remove the
+                     * weirdness of this code
+                     */
+  } catch (debug::Exception &) {
+    AKANTU_DEBUG_ERROR(
+        "A material of type \'"
+        << mat_type << "\' in the input file has been defined without a name!");
   }
+  Material & mat = this->registerNewMaterial(mat_name, mat_type, opt_param);
 
-#define AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL(dim, elem)                      \
-  BOOST_PP_SEQ_FOR_EACH_I(AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL_EACH,         \
-                          (2, (dim, BOOST_PP_ARRAY_ELEM(1, elem))),            \
-                          BOOST_PP_ARRAY_ELEM(2, elem))                        \
-  else {                                                                       \
-    AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL(dim, elem);                      \
-  }
+  mat.parseSection(section);
 
-#define AKANTU_INTANTIATE_MATERIAL_BY_DIM(dim, elem)                           \
-  BOOST_PP_IF(BOOST_PP_EQUAL(3, BOOST_PP_ARRAY_SIZE(elem)),                    \
-              AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL,                          \
-              AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL)                       \
-  (dim, elem)
-
-#define AKANTU_INTANTIATE_MATERIAL(elem)                                       \
-  switch (Model::spatial_dimension) {                                          \
-  case 1: {                                                                    \
-    AKANTU_INTANTIATE_MATERIAL_BY_DIM(1, elem);                                \
-    break;                                                                     \
-  }                                                                            \
-  case 2: {                                                                    \
-    AKANTU_INTANTIATE_MATERIAL_BY_DIM(2, elem);                                \
-    break;                                                                     \
-  }                                                                            \
-  case 3: {                                                                    \
-    AKANTU_INTANTIATE_MATERIAL_BY_DIM(3, elem);                                \
-    break;                                                                     \
-  }                                                                            \
-  }
+  return mat;
+}
 
-#define AKANTU_INTANTIATE_MATERIAL_IF(elem)                                    \
-  if (mat_type == BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(0, elem))) {          \
-    AKANTU_INTANTIATE_MATERIAL(elem);                                          \
-  }
+/* -------------------------------------------------------------------------- */
+Material & SolidMechanicsModel::registerNewMaterial(const ID & mat_name,
+                                                    const ID & mat_type,
+                                                    const ID & opt_param) {
+  AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) ==
+                          materials_names_to_id.end(),
+                      "A material with this name '"
+                          << mat_name << "' has already been registered. "
+                          << "Please use unique names for materials");
 
-#define AKANTU_INTANTIATE_OTHER_MATERIAL(r, data, elem)                        \
-  else AKANTU_INTANTIATE_MATERIAL_IF(elem)
-
-#define AKANTU_INSTANTIATE_MATERIALS()                                         \
-  do {                                                                         \
-    AKANTU_INTANTIATE_MATERIAL_IF(BOOST_PP_SEQ_HEAD(AKANTU_MATERIAL_LIST))     \
-    BOOST_PP_SEQ_FOR_EACH(AKANTU_INTANTIATE_OTHER_MATERIAL, _,                 \
-                          BOOST_PP_SEQ_TAIL(AKANTU_MATERIAL_LIST))             \
-    else {                                                                     \
-      if (getStaticParser().isPermissive())                                    \
-        AKANTU_DEBUG_INFO("Malformed material file "                           \
-                          << ": unknown material type '" << mat_type << "'");  \
-      else                                                                     \
-        AKANTU_DEBUG_WARNING("Malformed material file "                        \
-                             << ": unknown material type " << mat_type         \
-                             << ". This is perhaps a user"                     \
-                             << " defined material ?");                        \
-    }                                                                          \
-  } while (0)
+  UInt mat_count = materials.size();
+  materials_names_to_id[mat_name] = mat_count;
+
+  std::stringstream sstr_mat;
+  sstr_mat << this->id << ":" << mat_count << ":" << mat_type;
+  ID mat_id = sstr_mat.str();
+
+  std::unique_ptr<Material> material = MaterialFactory::getInstance().allocate(
+      mat_type, Model::spatial_dimension, opt_param, *this, mat_id);
+
+  materials.push_back(std::move(material));
+
+  return *(materials.back());
+}
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::instantiateMaterials() {
   std::pair<Parser::const_section_iterator, Parser::const_section_iterator>
       sub_sect = this->parser->getSubSections(_st_material);
 
   Parser::const_section_iterator it = sub_sect.first;
   for (; it != sub_sect.second; ++it) {
     const ParserSection & section = *it;
-    std::string mat_type = section.getName();
-    std::string opt_param = section.getOption();
-    AKANTU_INSTANTIATE_MATERIALS();
+    registerNewMaterial(section);
   }
 
   are_materials_instantiated = true;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assignMaterialToElements(
     const ElementTypeMapArray<UInt> * filter) {
 
   Element element;
   element.ghost_type = _not_ghost;
 
   auto element_types =
       mesh.elementTypes(Model::spatial_dimension, _not_ghost, _ek_not_defined);
   if (filter != NULL) {
     element_types = filter->elementTypes(Model::spatial_dimension, _not_ghost,
                                          _ek_not_defined);
   }
 
   // Fill the element material array from the material selector
   for (auto type : element_types) {
     UInt nb_element = mesh.getNbElement(type, _not_ghost);
 
     const Array<UInt> * filter_array = NULL;
     if (filter != NULL) {
       filter_array = &((*filter)(type, _not_ghost));
       nb_element = filter_array->getSize();
     }
 
     element.type = type;
     element.kind = mesh.getKind(element.type);
     Array<UInt> & mat_indexes = material_index(type, _not_ghost);
     for (UInt el = 0; el < nb_element; ++el) {
       if (filter != NULL)
         element.element = (*filter_array)(el);
       else
         element.element = el;
 
       UInt mat_index = (*material_selector)(element);
       AKANTU_DEBUG_ASSERT(
           mat_index < materials.size(),
           "The material selector returned an index that does not exists");
       mat_indexes(element.element) = mat_index;
     }
   }
 
   // synchronize the element material arrays
   this->synchronize(_gst_material_id);
 
   /// fill the element filters of the materials using the element_material
   /// arrays
   for (auto ghost_type : ghost_types) {
     element_types = mesh.elementTypes(Model::spatial_dimension, ghost_type,
                                       _ek_not_defined);
 
     if (filter != NULL) {
       element_types = filter->elementTypes(Model::spatial_dimension, ghost_type,
                                            _ek_not_defined);
     }
 
     for (auto type : element_types) {
       UInt nb_element = mesh.getNbElement(type, ghost_type);
 
       const Array<UInt> * filter_array = NULL;
       if (filter != NULL) {
         filter_array = &((*filter)(type, ghost_type));
         nb_element = filter_array->getSize();
       }
 
       Array<UInt> & mat_indexes = material_index(type, ghost_type);
       Array<UInt> & mat_local_num = material_local_numbering(type, ghost_type);
       for (UInt el = 0; el < nb_element; ++el) {
         UInt element;
 
         if (filter != NULL)
           element = (*filter_array)(el);
         else
           element = el;
 
         UInt mat_index = mat_indexes(element);
         UInt index =
             materials[mat_index]->addElement(type, element, ghost_type);
         mat_local_num(element) = index;
       }
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initMaterials() {
   AKANTU_DEBUG_ASSERT(materials.size() != 0, "No material to initialize !");
 
   if (!are_materials_instantiated)
     instantiateMaterials();
 
   this->assignMaterialToElements();
 
   for (auto & material : materials) {
     /// init internals properties
     material->initMaterial();
   }
 
   this->synchronize(_gst_smm_init_mat);
 
   // initialize mass
   switch (method) {
   case _explicit_lumped_mass:
     assembleMassLumped();
     break;
   case _explicit_consistent_mass:
   case _implicit_dynamic:
     assembleMass();
     break;
   case _static:
     break;
   default:
     AKANTU_EXCEPTION("analysis method not recognised by SolidMechanicsModel");
     break;
   }
 
 // initialize the previous displacement array if at least on material needs it
 // for (auto & material : materials) {
 //   if (material->isFiniteDeformation() || material->isInelasticDeformation())
 //   {
 //     initArraysPreviousDisplacment();
 //     break;
 //   }
 // }
 
 #ifdef AKANTU_DAMAGE_NON_LOCAL
   /// initialize the non-local manager for non-local computations
   this->initializeNonLocal();
 #endif
 }
 
 /* -------------------------------------------------------------------------- */
 Int SolidMechanicsModel::getInternalIndexFromID(const ID & id) const {
   AKANTU_DEBUG_IN();
 
   auto it = materials.begin();
   auto end = materials.end();
 
   for (; it != end; ++it)
     if ((*it)->getID() == id) {
       AKANTU_DEBUG_OUT();
       return (it - materials.begin());
     }
 
   AKANTU_DEBUG_OUT();
   return -1;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::reassignMaterial() {
   AKANTU_DEBUG_IN();
 
   std::vector<Array<Element>> element_to_add(materials.size());
   std::vector<Array<Element>> element_to_remove(materials.size());
 
   Element element;
   for (auto ghost_type : ghost_types) {
     element.ghost_type = ghost_type;
 
     for (auto type : mesh.elementTypes(Model::spatial_dimension, ghost_type,
                                        _ek_not_defined)) {
       element.type = type;
       element.kind = Mesh::getKind(type);
 
       UInt nb_element = mesh.getNbElement(type, ghost_type);
       Array<UInt> & mat_indexes = material_index(type, ghost_type);
 
       for (UInt el = 0; el < nb_element; ++el) {
         element.element = el;
 
         UInt old_material = mat_indexes(el);
         UInt new_material = (*material_selector)(element);
 
         if (old_material != new_material) {
           element_to_add[new_material].push_back(element);
           element_to_remove[old_material].push_back(element);
         }
       }
     }
   }
 
   UInt mat_index = 0;
   for (auto mat_it = materials.begin(); mat_it != materials.end();
        ++mat_it, ++mat_index) {
     (*mat_it)->removeElements(element_to_remove[mat_index]);
     (*mat_it)->addElements(element_to_add[mat_index]);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::applyEigenGradU(
     const Matrix<Real> & prescribed_eigen_grad_u, const ID & material_name,
     const GhostType ghost_type) {
 
   AKANTU_DEBUG_ASSERT(prescribed_eigen_grad_u.size() ==
                           Model::spatial_dimension * Model::spatial_dimension,
                       "The prescribed grad_u is not of the good size");
   for (auto & material : materials) {
     if (material->getName() == material_name)
       material->applyEigenGradU(prescribed_eigen_grad_u, ghost_type);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 
-} // akantu
+} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh b/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh
index 96dc5bcc9..adfd3d86a 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh
@@ -1,120 +1,120 @@
 /**
  * @file   solid_mechanics_model_tmpl.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Dana Christen <dana.christen@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Fri Nov 13 2015
  *
  * @brief  template part of solid mechanics model
  *
  * @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 "solid_mechanics_model.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_SOLID_MECHANICS_MODEL_TMPL_HH__
 #define __AKANTU_SOLID_MECHANICS_MODEL_TMPL_HH__
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
-template <typename M>
-Material &
-SolidMechanicsModel::registerNewMaterial(const ParserSection & section) {
-  std::string mat_name;
-  std::string mat_type = section.getName();
-  try {
-    std::string tmp = section.getParameter("name");
-    mat_name = tmp; /** this can seam weird, but there is an ambiguous operator
-             * overload that i couldn't solve. @todo remove the
-             * weirdness of this code
-             */
-  } catch (debug::Exception &) {
-    AKANTU_DEBUG_ERROR(
-        "A material of type \'"
-        << mat_type << "\' in the input file has been defined without a name!");
-  }
-  AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) ==
-                          materials_names_to_id.end(),
-                      "A material with this name '"
-                          << mat_name << "' has already been registered. "
-                          << "Please use unique names for materials");
-
-  UInt mat_count = materials.size();
-  materials_names_to_id[mat_name] = mat_count;
-
-  std::stringstream sstr_mat;
-  sstr_mat << this->id << ":" << mat_count << ":" << mat_type;
-  ID mat_id = sstr_mat.str();
-
-  std::unique_ptr<Material> material(new M(*this, mat_id));
-  material->parseSection(section);
-
-  materials.push_back(std::move(material));
-
-  return *(materials.back());
-}
+// template <typename M>
+// Material &
+// SolidMechanicsModel::registerNewMaterial(const ParserSection & section) {
+//   std::string mat_name;
+//   std::string mat_type = section.getName();
+//   try {
+//     std::string tmp = section.getParameter("name");
+//     mat_name = tmp; /** this can seam weird, but there is an ambiguous operator
+//              * overload that i couldn't solve. @todo remove the
+//              * weirdness of this code
+//              */
+//   } catch (debug::Exception &) {
+//     AKANTU_DEBUG_ERROR(
+//         "A material of type \'"
+//         << mat_type << "\' in the input file has been defined without a name!");
+//   }
+//   AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) ==
+//                           materials_names_to_id.end(),
+//                       "A material with this name '"
+//                           << mat_name << "' has already been registered. "
+//                           << "Please use unique names for materials");
+
+//   UInt mat_count = materials.size();
+//   materials_names_to_id[mat_name] = mat_count;
+
+//   std::stringstream sstr_mat;
+//   sstr_mat << this->id << ":" << mat_count << ":" << mat_type;
+//   ID mat_id = sstr_mat.str();
+
+//   std::unique_ptr<Material> material(new M(*this, mat_id));
+//   material->parseSection(section);
+
+//   materials.push_back(std::move(material));
+
+//   return *(materials.back());
+// }
 
 /* -------------------------------------------------------------------------- */
-template <typename M>
-Material &
-SolidMechanicsModel::registerNewEmptyMaterial(const std::string & mat_name) {
+// template <typename M>
+// Material &
+// SolidMechanicsModel::registerNewEmptyMaterial(const std::string & mat_name) {
 
-  AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) ==
-                          materials_names_to_id.end(),
-                      "A material with this name '"
-                          << mat_name << "' has already been registered. "
-                          << "Please use unique names for materials");
+//   AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) ==
+//                           materials_names_to_id.end(),
+//                       "A material with this name '"
+//                           << mat_name << "' has already been registered. "
+//                           << "Please use unique names for materials");
 
-  UInt mat_count = materials.size();
-  materials_names_to_id[mat_name] = mat_count;
+//   UInt mat_count = materials.size();
+//   materials_names_to_id[mat_name] = mat_count;
 
-  std::stringstream sstr_mat;
-  sstr_mat << id << ":" << mat_count << ":" << mat_name;
-  ID mat_id = sstr_mat.str();
+//   std::stringstream sstr_mat;
+//   sstr_mat << id << ":" << mat_count << ":" << mat_name;
+//   ID mat_id = sstr_mat.str();
 
-  std::unique_ptr<Material> material(new M(*this, mat_id));
-  materials.push_back(std::move(material));
-  return *(materials.back());
-}
+//   std::unique_ptr<Material> material(new M(*this, mat_id));
+//   materials.push_back(std::move(material));
+//   return *(materials.back());
+// }
 
 /* -------------------------------------------------------------------------- */
-template <typename M>
-void SolidMechanicsModel::registerNewCustomMaterials(const ID & mat_type) {
-  std::pair<Parser::const_section_iterator, Parser::const_section_iterator>
-      sub_sect = getStaticParser().getSubSections(_st_material);
-
-  Parser::const_section_iterator it = sub_sect.first;
-  for (; it != sub_sect.second; ++it) {
-    if (it->getName() == mat_type) {
-      registerNewMaterial<M>(*it);
-    }
-  }
-}
+// template <typename M>
+// void SolidMechanicsModel::registerNewCustomMaterials(const ID & mat_type) {
+//   std::pair<Parser::const_section_iterator, Parser::const_section_iterator>
+//       sub_sect = getStaticParser().getSubSections(_st_material);
+
+//   Parser::const_section_iterator it = sub_sect.first;
+//   for (; it != sub_sect.second; ++it) {
+//     if (it->getName() == mat_type) {
+//       registerNewMaterial<M>(*it);
+//     }
+//   }
+// }
 
 /* -------------------------------------------------------------------------- */
 } // akantu
 
 #endif /* __AKANTU_SOLID_MECHANICS_MODEL_TMPL_HH__ */
diff --git a/test/test_io/test_parser/test_parser.cc b/test/test_io/test_parser/test_parser.cc
index d847058b9..8bede7ca3 100644
--- a/test/test_io/test_parser/test_parser.cc
+++ b/test/test_io/test_parser/test_parser.cc
@@ -1,76 +1,76 @@
 /**
  * @file   test_parser.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Nov 13 2013
  * @date last modification: Sun Oct 19 2014
  *
  * @brief  test the input file parser
  *
  * @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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "parser.hh"
 #include "aka_random_generator.hh"
 
 #include <iostream>
 
 using namespace akantu;
 
 int main(int argc, char *argv[]) {
   initialize("input_file.dat", argc, argv);
 
   const Parser & p = getStaticParser();
 
 
-  std::cout << RandGenerator<Real>::seed() <<"==123456" << std::endl;
+  std::cout << RandomGenerator<UInt>::seed() <<"==123456" << std::endl;
 
   std::cout << p << std::endl;
 
   Real toto = p.getParameter("toto");
   std::cout << toto;
   Real ref = 2*M_PI + std::max(2., 50.);
   if(std::abs(toto - ref) > std::numeric_limits<Real>::epsilon()) {
     std::cout << "!=" << ref << std::endl;
     return 1;
   }
 
   std::cout << "==" << ref << std::endl;
 
   Vector<Real> vect = p.getParameter("vect");
   std::cout << vect << std::endl;
 
   Matrix<Real> mat = p.getParameter("mat");
   std::cout << mat << std::endl;
 
   RandomParameter<Real> rand1 = p.getParameter("rand1");
   std::cout << rand1 << std::endl;
 
   RandomParameter<Real> rand2 = p.getParameter("rand2");
   std::cout << rand2 << std::endl;
 
   RandomParameter<Real> rand3 = p.getParameter("rand3");
   std::cout << rand3 << std::endl;
 
   finalize();
   return 0;
 }
diff --git a/test/test_model/test_model_solver/test_model_solver.cc b/test/test_model/test_model_solver/test_model_solver.cc
index f0d9a3f81..f8702519e 100644
--- a/test/test_model/test_model_solver/test_model_solver.cc
+++ b/test/test_model/test_model_solver/test_model_solver.cc
@@ -1,155 +1,155 @@
 /**
  * @file   test_dof_manager_default.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date   Wed Feb 24 12:28:44 2016
  *
  * @brief  Test default dof manager
  *
  * @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_random_generator.hh"
 #include "dof_manager.hh"
 #include "dof_synchronizer.hh"
 #include "mesh.hh"
 #include "mesh_accessor.hh"
 #include "model_solver.hh"
 #include "non_linear_solver_newton_raphson.hh"
 #include "sparse_matrix.hh"
 #include "sparse_solver_mumps.hh"
 
 /* -------------------------------------------------------------------------- */
 #include "test_model_solver_my_model.hh"
 /* -------------------------------------------------------------------------- */
 #include <cmath>
 /* -------------------------------------------------------------------------- */
 
 using namespace akantu;
 
 static void genMesh(Mesh & mesh, UInt nb_nodes);
 static void printResults(MyModel & model, UInt nb_nodes);
 
 Real F = -10;
 
 /* -------------------------------------------------------------------------- */
 int main(int argc, char * argv[]) {
   initialize(argc, argv);
 
   UInt prank = StaticCommunicator::getStaticCommunicator().whoAmI();
 
   std::cout << std::setprecision(7);
 
   UInt global_nb_nodes = 100;
   Mesh mesh(1);
 
-  RandGenerator<Real>::seed(1);
+  RandomGenerator<UInt>::seed(1);
 
   if (prank == 0) {
     genMesh(mesh, global_nb_nodes);
   }
 
   //std::cout << prank << RandGenerator<Real>::seed() << std::endl;
 
   mesh.distribute();
 
   MyModel model(F, mesh, false);
 
   model.getNewSolver("static", _tsst_static, _nls_newton_raphson);
   model.setIntegrationScheme("static", "disp", _ist_pseudo_time);
 
   NonLinearSolver & solver =
       model.getDOFManager().getNonLinearSolver("static");
   solver.set("max_iterations", 2);
 
 
   model.solveStep();
 
   dynamic_cast<NonLinearSolverNewtonRaphson &>(
       model.getDOFManager().getNonLinearSolver("static"))
       .getSolver()
       .analysis();
 
   printResults(model, global_nb_nodes);
 
   finalize();
   return EXIT_SUCCESS;
 }
 
 /* -------------------------------------------------------------------------- */
 void genMesh(Mesh & mesh, UInt nb_nodes) {
   MeshAccessor mesh_accessor(mesh);
   Array<Real> & nodes = mesh_accessor.getNodes();
   Array<UInt> & conn = mesh_accessor.getConnectivity(_segment_2);
 
   nodes.resize(nb_nodes);
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     nodes(n, _x) = n * (1. / (nb_nodes - 1));
   }
 
   conn.resize(nb_nodes - 1);
   for (UInt n = 0; n < nb_nodes - 1; ++n) {
     conn(n, 0) = n;
     conn(n, 1) = n + 1;
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void printResults(MyModel & model, UInt nb_nodes) {
   UInt prank = StaticCommunicator::getStaticCommunicator().whoAmI();
   auto & sync = dynamic_cast<DOFManagerDefault &>(model.getDOFManager())
     .getSynchronizer();
 
   if (prank == 0) {
     Array<Real> global_displacement(nb_nodes);
     Array<Real> global_forces(nb_nodes);
     Array<bool> global_blocked(nb_nodes);
 
     sync.gather(model.forces, global_forces);
     sync.gather(model.displacement, global_displacement);
     sync.gather(model.blocked, global_blocked);
 
     auto force_it = global_forces.begin();
     auto disp_it = global_displacement.begin();
     auto blocked_it = global_blocked.begin();
 
     std::cout << "node"
               << ", " << std::setw(8) << "disp"
               << ", " << std::setw(8) << "force"
               << ", " << std::setw(8) << "blocked" << std::endl;
 
     UInt node = 0;
     for (; disp_it != global_displacement.end();
          ++disp_it, ++force_it, ++blocked_it, ++node) {
       std::cout << node << ", " << std::setw(8) << *disp_it << ", "
                 << std::setw(8) << *force_it << ", " << std::setw(8)
                 << *blocked_it << std::endl;
 
       std::cout << std::flush;
     }
   } else {
     sync.gather(model.forces);
     sync.gather(model.displacement);
     sync.gather(model.blocked);
   }
 }
diff --git a/test/test_model/test_non_local_toolbox/test_build_neighborhood_parallel.cc b/test/test_model/test_non_local_toolbox/test_build_neighborhood_parallel.cc
index 08d0d5e54..08cb77e51 100644
--- a/test/test_model/test_non_local_toolbox/test_build_neighborhood_parallel.cc
+++ b/test/test_model/test_non_local_toolbox/test_build_neighborhood_parallel.cc
@@ -1,188 +1,195 @@
 /**
  * @file   test_build_neighborhood_parallel.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  *
  * @date creation: Sat Sep 26 2015
  * @date last modification: Wed Nov 25 2015
  *
  * @brief  test in parallel for the class NonLocalNeighborhood
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "dumper_paraview.hh"
+#include "non_local_neighborhood_base.hh"
 #include "solid_mechanics_model.hh"
 #include "test_material.hh"
-#include "non_local_neighborhood_base.hh"
-#include "dumper_paraview.hh"
 /* -------------------------------------------------------------------------- */
 using namespace akantu;
 /* -------------------------------------------------------------------------- */
-int main(int argc, char *argv[]) {
+int main(int argc, char * argv[]) {
   akantu::initialize("material_parallel_test.dat", argc, argv);
 
-  StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator();
+  StaticCommunicator & comm =
+      akantu::StaticCommunicator::getStaticCommunicator();
   Int psize = comm.getNbProc();
   Int prank = comm.whoAmI();
 
   // some configuration variables
   const UInt spatial_dimension = 2;
 
   // mesh creation and read
   Mesh mesh(spatial_dimension);
-  akantu::MeshPartition * partition = NULL;
-  if(prank == 0) {
-
+  if (prank == 0) {
     mesh.read("parallel_test.msh");
-
-
-    /// partition the mesh
-    partition = new MeshPartitionScotch(mesh, spatial_dimension);
-
-    partition->partitionate(psize);
   }
 
-  /// model creation
-  SolidMechanicsModel  model(mesh);
-  model.initParallel(partition);
-  delete partition;
+  mesh.distribute();
 
+  /// model creation
+  SolidMechanicsModel model(mesh);
 
   /// dump the ghost elements before the non-local part is intialized
   DumperParaview dumper_ghost("ghost_elements");
   dumper_ghost.registerMesh(mesh, spatial_dimension, _ghost);
-  if(psize > 1) {              
+  if (psize > 1) {
     dumper_ghost.dump();
   }
 
   /// creation of material selector
   MeshDataMaterialSelector<std::string> * mat_selector;
-  mat_selector = new MeshDataMaterialSelector<std::string>("physical_names", model);
+  mat_selector =
+      new MeshDataMaterialSelector<std::string>("physical_names", model);
   model.setMaterialSelector(*mat_selector);
 
   /// dump material index in paraview
   model.addDumpField("partitions");
   model.dump();
 
   /// model initialization changed to use our material
-  model.initFull(_no_init_materials = true);
-  
-  model.registerNewCustomMaterials< TestMaterial<spatial_dimension> >("test_material");
-  model.initMaterials();
+  model.initFull();
+
   /// dump the ghost elements after ghosts for non-local have been added
-  if(psize > 1)
+  if (psize > 1)
     dumper_ghost.dump();
 
   model.addDumpField("grad_u");
   model.addDumpField("grad_u non local");
   model.addDumpField("material_index");
 
- /// apply constant strain field everywhere in the plate
+  /// apply constant strain field everywhere in the plate
   Matrix<Real> applied_strain(spatial_dimension, spatial_dimension);
   applied_strain.clear();
   for (UInt i = 0; i < spatial_dimension; ++i)
-    applied_strain(i,i) = 2.;
+    applied_strain(i, i) = 2.;
 
   ElementType element_type = _triangle_3;
   GhostType ghost_type = _not_ghost;
   /// apply constant grad_u field in all elements
   for (UInt m = 0; m < model.getNbMaterials(); ++m) {
     Material & mat = model.getMaterial(m);
-    Array<Real> & grad_u = const_cast<Array<Real> &> (mat.getInternal<Real>("grad_u")(element_type, ghost_type));
-    Array<Real>::iterator< Matrix<Real> > grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension);
-    Array<Real>::iterator< Matrix<Real> > grad_u_end = grad_u.end(spatial_dimension, spatial_dimension);
-    for (; grad_u_it != grad_u_end; ++grad_u_it) 
+    Array<Real> & grad_u = const_cast<Array<Real> &>(
+        mat.getInternal<Real>("grad_u")(element_type, ghost_type));
+    Array<Real>::iterator<Matrix<Real>> grad_u_it =
+        grad_u.begin(spatial_dimension, spatial_dimension);
+    Array<Real>::iterator<Matrix<Real>> grad_u_end =
+        grad_u.end(spatial_dimension, spatial_dimension);
+    for (; grad_u_it != grad_u_end; ++grad_u_it)
       (*grad_u_it) += applied_strain;
   }
 
-  /// double the strain in the center: find the closed gauss point to the center 
+  /// double the strain in the center: find the closed gauss point to the center
   /// compute the quadrature points
   ElementTypeMapReal quad_coords("quad_coords");
-  mesh.initElementTypeMapArray(quad_coords, spatial_dimension, spatial_dimension, false, _ek_regular, true);
+  quad_coords.initialize(mesh, _nb_component = spatial_dimension,
+                         _spatial_dimension = spatial_dimension,  _with_nb_element = true);
   model.getFEEngine().computeIntegrationPointsCoordinates(quad_coords);
 
   Vector<Real> center(spatial_dimension, 0.);
-  Mesh::type_iterator it        = mesh.firstType(spatial_dimension, _not_ghost, _ek_regular);
-  Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _not_ghost, _ek_regular);
+  Mesh::type_iterator it =
+      mesh.firstType(spatial_dimension, _not_ghost, _ek_regular);
+  Mesh::type_iterator last_type =
+      mesh.lastType(spatial_dimension, _not_ghost, _ek_regular);
   Real min_distance = 2;
   IntegrationPoint q_min;
-  for(; it != last_type ; ++it) {
+  for (; it != last_type; ++it) {
     ElementType type = *it;
     UInt nb_elements = mesh.getNbElement(type, _not_ghost);
     UInt nb_quads = model.getFEEngine().getNbIntegrationPoints(type);
     Array<Real> & coords = quad_coords(type, _not_ghost);
-    Array<Real>::const_vector_iterator coord_it = coords.begin(spatial_dimension);
+    Array<Real>::const_vector_iterator coord_it =
+        coords.begin(spatial_dimension);
     for (UInt e = 0; e < nb_elements; ++e) {
       for (UInt q = 0; q < nb_quads; ++q, ++coord_it) {
-	Real dist = center.distance(*coord_it);
-	if (dist < min_distance) {
-	  min_distance = dist;
-	  q_min.element = e;
-	  q_min.num_point = q;
-	  q_min.global_num = nb_elements * nb_quads + q;
-	  q_min.type = type;
-	}	
+        Real dist = center.distance(*coord_it);
+        if (dist < min_distance) {
+          min_distance = dist;
+          q_min.element = e;
+          q_min.num_point = q;
+          q_min.global_num = nb_elements * nb_quads + q;
+          q_min.type = type;
+        }
       }
     }
   }
 
   Real global_min = min_distance;
-  comm.allReduce(&global_min, 1, _so_min);
+  comm.allReduce(global_min, _so_min);
 
-  if(Math::are_float_equal(global_min, min_distance)) {
-    UInt mat_index = model.getMaterialByElement(q_min.type, _not_ghost).begin()[q_min.element];
+  if (Math::are_float_equal(global_min, min_distance)) {
+    UInt mat_index = model.getMaterialByElement(q_min.type, _not_ghost)
+                         .begin()[q_min.element];
     Material & mat = model.getMaterial(mat_index);
     UInt nb_quads = model.getFEEngine().getNbIntegrationPoints(q_min.type);
-    UInt local_el_index = model.getMaterialLocalNumbering(q_min.type, _not_ghost).begin()[q_min.element];
+    UInt local_el_index =
+        model.getMaterialLocalNumbering(q_min.type, _not_ghost)
+            .begin()[q_min.element];
     UInt local_num = (local_el_index * nb_quads) + q_min.num_point;
-    Array<Real> & grad_u = const_cast<Array<Real> &> (mat.getInternal<Real>("grad_u")(q_min.type, _not_ghost));
-    Array<Real>::iterator< Matrix<Real> > grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension);
+    Array<Real> & grad_u = const_cast<Array<Real> &>(
+        mat.getInternal<Real>("grad_u")(q_min.type, _not_ghost));
+    Array<Real>::iterator<Matrix<Real>> grad_u_it =
+        grad_u.begin(spatial_dimension, spatial_dimension);
     grad_u_it += local_num;
     Matrix<Real> & g_u = *grad_u_it;
-    g_u +=  applied_strain;
+    g_u += applied_strain;
   }
 
   /// compute the non-local strains
-  model.getNonLocalManager().computeAllNonLocalStresses();
-  model.dump(); 
+  model.assembleInternalForces();
+  model.dump();
 
   /// damage the element with higher grad_u completely, so that it is
   /// not taken into account for the averaging
-  if(Math::are_float_equal(global_min, min_distance)) {
-    UInt mat_index = model.getMaterialByElement(q_min.type, _not_ghost).begin()[q_min.element];
+  if (Math::are_float_equal(global_min, min_distance)) {
+    UInt mat_index = model.getMaterialByElement(q_min.type, _not_ghost)
+                         .begin()[q_min.element];
     Material & mat = model.getMaterial(mat_index);
     UInt nb_quads = model.getFEEngine().getNbIntegrationPoints(q_min.type);
-    UInt local_el_index = model.getMaterialLocalNumbering(q_min.type, _not_ghost).begin()[q_min.element];
+    UInt local_el_index =
+        model.getMaterialLocalNumbering(q_min.type, _not_ghost)
+            .begin()[q_min.element];
     UInt local_num = (local_el_index * nb_quads) + q_min.num_point;
-    Array<Real> & damage = const_cast<Array<Real> &> (mat.getInternal<Real>("damage")(q_min.type, _not_ghost));
+    Array<Real> & damage = const_cast<Array<Real> &>(
+        mat.getInternal<Real>("damage")(q_min.type, _not_ghost));
     Real * dam_ptr = damage.storage();
     dam_ptr += local_num;
     *dam_ptr = 0.9;
   }
 
   /// compute the non-local strains
-  model.getNonLocalManager().computeAllNonLocalStresses();
-  model.dump();  
+  model.assembleInternalForces();
+  model.dump();
 
   finalize();
-  
+
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_non_local_toolbox/test_material.cc b/test/test_model/test_non_local_toolbox/test_material.cc
index df021a8a2..2e3b88433 100644
--- a/test/test_model/test_non_local_toolbox/test_material.cc
+++ b/test/test_model/test_non_local_toolbox/test_material.cc
@@ -1,125 +1,61 @@
 /**
  * @file   test_material.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  *
  * @date creation: Sat Sep 26 2015
  * @date last modification: Wed Nov 25 2015
  *
- * @brief  Implementation of test material for the non-local neighborhood base test
+ * @brief  Implementation of test material for the non-local neighborhood base
+ * test
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "test_material.hh"
 
-__BEGIN_AKANTU__
-
 /* -------------------------------------------------------------------------- */
-template<UInt dim>
-TestMaterial<dim>::TestMaterial(SolidMechanicsModel & model, const ID & id) :
-  Material(model, id),
-  MyLocalParent(model, id),
-  MyNonLocalParent(model, id),
-  grad_u_nl("grad_u non local", *this) {
+template <UInt dim>
+TestMaterial<dim>::TestMaterial(SolidMechanicsModel & model, const ID & id)
+    : Parent(model, id), grad_u_nl("grad_u non local", *this) {
   this->is_non_local = true;
-  this->grad_u_nl.initialize(dim*dim);
-  this->model->getNonLocalManager().registerNonLocalVariable(this->gradu.getName(), grad_u_nl.getName(), dim*dim);
-  
- }
+  this->grad_u_nl.initialize(dim * dim);
+  this->model.registerNonLocalVariable(
+      this->gradu.getName(), grad_u_nl.getName(), dim * dim);
+}
 
 /* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension>
+template <UInt spatial_dimension>
 void TestMaterial<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
-  this->registerNeighborhood();
-
-  MyLocalParent::initMaterial();
-  MyNonLocalParent::initMaterial();
+  Parent::initMaterial();
 
-  this->model->getNonLocalManager().nonLocalVariableToNeighborhood(grad_u_nl.getName(), "test_region");
+  this->model.getNeighborhood("test_region")
+      .registerNonLocalVariable(grad_u_nl.getName());
 
   AKANTU_DEBUG_OUT();
 }
 
-/* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension>
-void TestMaterial<spatial_dimension>::insertQuadsInNeighborhoods(GhostType ghost_type) {
-
-  /// this function will add all the quadrature points to the same
-  /// default neighborhood instead of using one neighborhood per
-  /// material
-  NonLocalManager & manager = this->model->getNonLocalManager();
-  InternalField<Real> quadrature_points_coordinates("quadrature_points_coordinates_tmp_nl", *this);
-  quadrature_points_coordinates.initialize(spatial_dimension);
-
-  /// intialize quadrature point object
-  IntegrationPoint q;
-  q.ghost_type = ghost_type;
-  q.kind = _ek_regular;
-
-  Mesh::type_iterator it = this->element_filter.firstType(spatial_dimension, ghost_type, _ek_regular);
-  Mesh::type_iterator last_type = this->element_filter.lastType(spatial_dimension, ghost_type, _ek_regular);
-  for(; it != last_type; ++it) {
-    q.type = *it;
-    const Array<UInt> & elem_filter = this->element_filter(*it, ghost_type);
-    UInt nb_element  = elem_filter.getSize();
-    if(nb_element) {
-      UInt nb_quad = this->fem->getNbIntegrationPoints(*it, ghost_type);
-      UInt nb_tot_quad = nb_quad * nb_element;
-      
-      Array<Real> & quads = quadrature_points_coordinates(*it, ghost_type);
-      quads.resize(nb_tot_quad);
-
-      this->model->getFEEngine().computeIntegrationPointsCoordinates(quads, *it, ghost_type, elem_filter);
-      
-      Array<Real>::const_vector_iterator quad = quads.begin(spatial_dimension);
-      UInt * elem = elem_filter.storage();
-
-      for (UInt e = 0; e < nb_element; ++e) {
-	q.element = *elem;
-	for (UInt nq = 0; nq < nb_quad; ++nq) {
-	  q.num_point = nq;
-	  q.global_num = q.element * nb_quad + nq;
-	  manager.insertQuad(q, *quad, "test_region");
-	  ++quad;
-	}
-	++elem;
-      }
-    }
-  }
-}
-
-/* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension>
-void TestMaterial<spatial_dimension>::registerNeighborhood() {
-  this->model->getNonLocalManager().registerNeighborhood("test_region", "test_region");
-}
-
 /* -------------------------------------------------------------------------- */
 // Instantiate the material for the 3 dimensions
-INSTANTIATE_MATERIAL(TestMaterial);
+INSTANTIATE_MATERIAL(test_material, TestMaterial);
 /* -------------------------------------------------------------------------- */
-
-__END_AKANTU__
-
-
diff --git a/test/test_model/test_non_local_toolbox/test_material.hh b/test/test_model/test_non_local_toolbox/test_material.hh
index e0c262d4f..a1cdd484a 100644
--- a/test/test_model/test_non_local_toolbox/test_material.hh
+++ b/test/test_model/test_non_local_toolbox/test_material.hh
@@ -1,72 +1,70 @@
 /**
  * @file   test_material.hh
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  *
  * @date creation: Thu Feb 21 2013
  * @date last modification: Wed Nov 25 2015
  *
  * @brief  test material for the non-local neighborhood base test
  *
  * @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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_damage.hh"
 #include "material_damage_non_local.hh"
 
 #ifndef __TEST_MATERIAL_HH__
 #define __TEST_MATERIAL_HH__
 
-namespace akantu {
+using namespace akantu;
 
 template <UInt dim>
-class TestMaterial : public MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>> {
+class TestMaterial
+    : public MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>> {
   /* ------------------------------------------------------------------------ */
   /* Constructor/Destructor */
   /* ------------------------------------------------------------------------ */
 public:
-  using Parent = MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>>;
+  using Parent =
+      MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>>;
 
   TestMaterial(SolidMechanicsModel & model, const ID & id);
   virtual ~TestMaterial(){};
 
   /* ------------------------------------------------------------------------ */
   /* Methods */
   /* ------------------------------------------------------------------------ */
 public:
-  void initMaterial();
+  void initMaterial() final;
 
-  void computeNonLocalStresses(GhostType){};
+  void computeNonLocalStress(ElementType, GhostType) final{};
 
-  void insertQuadsInNeighborhoods(GhostType ghost_type);
-
-  virtual void registerNeighborhood();
+  void computeNonLocalStresses(GhostType) final{};
 
   /* ------------------------------------------------------------------------ */
   /* Members */
   /* ------------------------------------------------------------------------ */
 private:
   InternalField<Real> grad_u_nl;
 };
 
-} // namespace akantu
-
 #endif /* __TEST_MATERIAL_HH__ */
diff --git a/test/test_model/test_non_local_toolbox/test_material_damage.cc b/test/test_model/test_non_local_toolbox/test_material_damage.cc
index b61c974c8..89c7cfdd9 100644
--- a/test/test_model/test_non_local_toolbox/test_material_damage.cc
+++ b/test/test_model/test_non_local_toolbox/test_material_damage.cc
@@ -1,116 +1,60 @@
 /**
  * @file   test_material_damage.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  *
  * @date creation: Sat Sep 26 2015
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  Implementation of test material damage
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "test_material_damage.hh"
-
-__BEGIN_AKANTU__
+/* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
-template<UInt dim>
-TestMaterialDamage<dim>::TestMaterialDamage(SolidMechanicsModel & model, const ID & id) :
-  Material(model, id),
-  MaterialDamage<dim>(model, id),
-  MyNonLocalParent(model, id),
-  grad_u_nl("grad_u non local", *this) {
+template <UInt dim>
+TestMaterialDamage<dim>::TestMaterialDamage(SolidMechanicsModel & model,
+                                            const ID & id)
+    : Parent(model, id), grad_u_nl("grad_u non local", *this) {
   this->is_non_local = true;
-  this->grad_u_nl.initialize(dim*dim);
-  this->model->getNonLocalManager().registerNonLocalVariable(this->gradu.getName(), grad_u_nl.getName(), dim*dim);
-
- }
+  this->grad_u_nl.initialize(dim * dim);
+  this->model.registerNonLocalVariable(this->gradu.getName(),
+                                       grad_u_nl.getName(), dim * dim);
+}
 
 /* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension>
+template <UInt spatial_dimension>
 void TestMaterialDamage<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
   MaterialDamage<spatial_dimension>::initMaterial();
-  MyNonLocalParent::initMaterial();
-  this->model->getNonLocalManager().nonLocalVariableToNeighborhood(grad_u_nl.getName(), this->name);
+  Parent::initMaterial();
+  this->model.getNeighborhood(this->name)
+      .registerNonLocalVariable(grad_u_nl.getName());
   AKANTU_DEBUG_OUT();
 }
 
-/* -------------------------------------------------------------------------- */
-template<UInt spatial_dimension>
-void TestMaterialDamage<spatial_dimension>::insertQuadsInNeighborhoods(GhostType ghost_type) {
-
-  /// this function will add all the quadrature points to the same
-  /// default neighborhood instead of using one neighborhood per
-  /// material
-  NonLocalManager & manager = this->model->getNonLocalManager();
-  InternalField<Real> quadrature_points_coordinates("quadrature_points_coordinates_tmp_nl", *this);
-  quadrature_points_coordinates.initialize(spatial_dimension);
-
-  /// intialize quadrature point object
-  IntegrationPoint q;
-  q.ghost_type = ghost_type;
-  q.kind = _ek_regular;
-
-  Mesh::type_iterator it = this->element_filter.firstType(spatial_dimension, ghost_type, _ek_regular);
-  Mesh::type_iterator last_type = this->element_filter.lastType(spatial_dimension, ghost_type, _ek_regular);
-  for(; it != last_type; ++it) {
-    q.type = *it;
-    const Array<UInt> & elem_filter = this->element_filter(*it, ghost_type);
-    UInt nb_element  = elem_filter.getSize();
-    if(nb_element) {
-      UInt nb_quad = this->fem->getNbIntegrationPoints(*it, ghost_type);
-      UInt nb_tot_quad = nb_quad * nb_element;
-      
-      Array<Real> & quads = quadrature_points_coordinates(*it, ghost_type);
-      quads.resize(nb_tot_quad);
-
-      this->model->getFEEngine().computeIntegrationPointsCoordinates(quads, *it, ghost_type, elem_filter);
-      
-      Array<Real>::const_vector_iterator quad = quads.begin(spatial_dimension);
-      UInt * elem = elem_filter.storage();
-
-      for (UInt e = 0; e < nb_element; ++e) {
-	q.element = *elem;
-	for (UInt nq = 0; nq < nb_quad; ++nq) {
-	  q.num_point = nq;
-	  q.global_num = q.element * nb_quad + nq;
-	  manager.insertQuad(q, *quad, this->name);
-	  ++quad;
-	}
-	++elem;
-      }
-    }
-  }
-}
-
-
 /* -------------------------------------------------------------------------- */
 // Instantiate the material for the 3 dimensions
-INSTANTIATE_MATERIAL(TestMaterialDamage);
+INSTANTIATE_MATERIAL(test_material, TestMaterialDamage);
 /* -------------------------------------------------------------------------- */
-
-__END_AKANTU__
-
-
diff --git a/test/test_model/test_non_local_toolbox/test_material_damage.hh b/test/test_model/test_non_local_toolbox/test_material_damage.hh
index 01d51bdf3..9afe91fc1 100644
--- a/test/test_model/test_non_local_toolbox/test_material_damage.hh
+++ b/test/test_model/test_non_local_toolbox/test_material_damage.hh
@@ -1,72 +1,70 @@
 /**
  * @file   test_material_damage.hh
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  *
  * @date creation: Thu Feb 21 2013
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  test material damage for the non-local remove damage test
  *
  * @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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_damage.hh"
-#include "material_non_local.hh"
+#include "material_damage_non_local.hh"
+/* -------------------------------------------------------------------------- */
 
 #ifndef __TEST_MATERIAL_DAMAGE_HH__
 #define __TEST_MATERIAL_DAMAGE_HH__
 
-__BEGIN_AKANTU__
+using namespace akantu;
 
 template <UInt dim>
-class TestMaterialDamage : public MaterialDamage<dim, MaterialElastic>,
-                           public MaterialNonLocal<dim> {
+class TestMaterialDamage
+    : public MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>> {
   /* ------------------------------------------------------------------------ */
   /* Constructor/Destructor */
   /* ------------------------------------------------------------------------ */
 public:
   TestMaterialDamage(SolidMechanicsModel & model, const ID & id);
   virtual ~TestMaterialDamage(){};
-  typedef MaterialNonLocal<dim> MyNonLocalParent;
+  using Parent = MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>>;
 
   /* ------------------------------------------------------------------------ */
   /* Methods */
   /* ------------------------------------------------------------------------ */
 public:
   void initMaterial();
 
-  // void computeNonLocalStress(ElementType type, GhostType ghost_type =
-  // _not_ghost);
+  void computeNonLocalStress(ElementType, GhostType) final{};
 
-  void computeNonLocalStresses(__attribute__((unused)) GhostType ghost_type){};
+  void computeNonLocalStresses(GhostType) final{};
   void insertQuadsInNeighborhoods(GhostType ghost_type);
 
   /* ------------------------------------------------------------------------ */
   /* Members */
   /* ------------------------------------------------------------------------ */
 private:
   InternalField<Real> grad_u_nl;
 };
 
-__END_AKANTU__
-
 #endif /* __TEST_MATERIAL_DAMAGE_HH__ */
diff --git a/test/test_model/test_non_local_toolbox/test_non_local_averaging.cc b/test/test_model/test_non_local_toolbox/test_non_local_averaging.cc
index 5e8094186..36e5c6647 100644
--- a/test/test_model/test_non_local_toolbox/test_non_local_averaging.cc
+++ b/test/test_model/test_non_local_toolbox/test_non_local_averaging.cc
@@ -1,112 +1,111 @@
 /**
  * @file   test_non_local_averaging.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  *
  * @date creation: Sat Sep 26 2015
  * @date last modification: Wed Oct 07 2015
  *
  * @brief  test for non-local averaging of strain
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "solid_mechanics_model.hh"
 #include "test_material.hh"
 #include "non_local_manager.hh"
 #include "non_local_neighborhood.hh"
 #include "dumper_paraview.hh"
 /* -------------------------------------------------------------------------- */
 using namespace akantu;
 /* -------------------------------------------------------------------------- */
 int main(int argc, char *argv[]) {
   akantu::initialize("material.dat", argc, argv);
 
   // some configuration variables
   const UInt spatial_dimension = 2;
   ElementType element_type = _quadrangle_4;
   GhostType ghost_type = _not_ghost;
 
   // mesh creation and read
   Mesh mesh(spatial_dimension);
   mesh.read("plate.msh");
 
   /// model creation
   SolidMechanicsModel  model(mesh);
 
   /// creation of material selector
   MeshDataMaterialSelector<std::string> * mat_selector;
   mat_selector = new MeshDataMaterialSelector<std::string>("physical_names", model);
   model.setMaterialSelector(*mat_selector);
 
   /// model initialization changed to use our material
-  model.initFull(_no_init_materials = true);
-  model.registerNewCustomMaterials< TestMaterial<spatial_dimension> >("test_material");
-  model.initMaterials();
+  model.initFull();
+  
   /// dump material index in paraview
   model.addDumpField("material_index");
   model.addDumpField("grad_u");
   model.addDumpField("grad_u non local");
   model.dump();
 
   /// apply constant strain field everywhere in the plate
   Matrix<Real> applied_strain(spatial_dimension, spatial_dimension);
   applied_strain.clear();
   for (UInt i = 0; i < spatial_dimension; ++i)
     applied_strain(i,i) = 2.;
 
   /// apply constant grad_u field in all elements
   for (UInt m = 0; m < model.getNbMaterials(); ++m) {
     Material & mat = model.getMaterial(m);
     Array<Real> & grad_u = const_cast<Array<Real> &> (mat.getInternal<Real>("grad_u")(element_type, ghost_type));
     Array<Real>::iterator< Matrix<Real> > grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension);
     Array<Real>::iterator< Matrix<Real> > grad_u_end = grad_u.end(spatial_dimension, spatial_dimension);
     for (; grad_u_it != grad_u_end; ++grad_u_it) 
       (*grad_u_it) += applied_strain;
   }
 
   /// compute the non-local strains
-  model.getNonLocalManager().computeAllNonLocalStresses();
+  model.assembleInternalForces();
   model.dump();
 
   /// verify the result: non-local averaging over constant field must
   /// yield same constant field
   Real test_result = 0.;
   Matrix<Real> difference(spatial_dimension, spatial_dimension, 0.);
   for (UInt m = 0; m < model.getNbMaterials(); ++m) {
-    MaterialNonLocal<spatial_dimension> & mat = dynamic_cast<MaterialNonLocal<spatial_dimension> & >(model.getMaterial(m));
-    Array<Real> & grad_u_nl = const_cast<Array<Real> &> (mat.getInternal<Real>("grad_u non local")(element_type, ghost_type));
+    auto & mat = model.getMaterial(m);
+    Array<Real> & grad_u_nl = mat.getInternal<Real>("grad_u non local")(element_type, ghost_type);
 
-    Array<Real>::iterator< Matrix<Real> > grad_u_nl_it = grad_u_nl.begin(spatial_dimension, spatial_dimension);
-    Array<Real>::iterator< Matrix<Real> > grad_u_nl_end = grad_u_nl.end(spatial_dimension, spatial_dimension);
+    auto grad_u_nl_it = grad_u_nl.begin(spatial_dimension, spatial_dimension);
+    auto grad_u_nl_end = grad_u_nl.end(spatial_dimension, spatial_dimension);
     for (; grad_u_nl_it != grad_u_nl_end; ++grad_u_nl_it) {
       difference = (*grad_u_nl_it) - applied_strain;
       test_result += difference.norm<L_2>();
     }
   }
 
   if (test_result > 10.e-13) {
     std::cout << "the total norm is: " << test_result << std::endl;
     return EXIT_FAILURE;
   }
 
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_non_local_toolbox/test_non_local_neighborhood_base.cc b/test/test_model/test_non_local_toolbox/test_non_local_neighborhood_base.cc
index d307b9366..2fadd32a3 100644
--- a/test/test_model/test_non_local_toolbox/test_non_local_neighborhood_base.cc
+++ b/test/test_model/test_non_local_toolbox/test_non_local_neighborhood_base.cc
@@ -1,89 +1,88 @@
 /**
  * @file   test_non_local_neighborhood_base.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  *
  * @date creation: Sat Sep 26 2015
  * @date last modification: Wed Oct 07 2015
  *
  * @brief  test for the class NonLocalNeighborhoodBase
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "solid_mechanics_model.hh"
 #include "test_material.hh"
 #include "non_local_neighborhood_base.hh"
 #include "dumper_paraview.hh"
 /* -------------------------------------------------------------------------- */
 using namespace akantu;
 /* -------------------------------------------------------------------------- */
 int main(int argc, char *argv[]) {
   akantu::initialize("material.dat", argc, argv);
 
   // some configuration variables
   const UInt spatial_dimension = 2;
 
   // mesh creation and read
   Mesh mesh(spatial_dimension);
   mesh.read("plate.msh");
 
   /// model creation
   SolidMechanicsModel  model(mesh);
 
   /// creation of material selector
   MeshDataMaterialSelector<std::string> * mat_selector;
   mat_selector = new MeshDataMaterialSelector<std::string>("physical_names", model);
   model.setMaterialSelector(*mat_selector);
  
   /// model initialization changed to use our material
-  model.initFull(_no_init_materials = true);
-  model.registerNewCustomMaterials< TestMaterial<spatial_dimension> >("test_material");
-  model.initMaterials();
+  model.initFull();
+  
   /// dump material index in paraview
   model.addDumpField("material_index");
   model.dump();
 
   NonLocalNeighborhoodBase & neighborhood = model.getNeighborhood("test_region");
 
   /// save the pair of quadrature points and the coords of all neighbors
   std::string output_1 = "quadrature_pairs";
   std::string output_2 = "neighborhoods";
   neighborhood.savePairs(output_1);
   neighborhood.saveNeighborCoords(output_2);
 
   /// print results to screen for validation
   std::ifstream quad_pairs;
   quad_pairs.open("quadrature_pairs.0");
   std::string current_line;
   while(getline(quad_pairs, current_line))
     std::cout << current_line << std::endl;
   quad_pairs.close();
   std::ifstream neighborhoods;
   neighborhoods.open("neighborhoods.0");
   while(getline(neighborhoods, current_line))
     std::cout << current_line << std::endl;
   neighborhoods.close();
 
   finalize();
   
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_non_local_toolbox/test_pair_computation.cc b/test/test_model/test_non_local_toolbox/test_pair_computation.cc
index 5d463925b..26d98969d 100644
--- a/test/test_model/test_non_local_toolbox/test_pair_computation.cc
+++ b/test/test_model/test_non_local_toolbox/test_pair_computation.cc
@@ -1,243 +1,233 @@
 /**
  * @file   test_pair_computation.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  *
  * @date creation: Wed Nov 25 2015
  *
  * @brief  test the weight computation with and without grid
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "dumper_paraview.hh"
 #include "non_local_manager.hh"
 #include "non_local_neighborhood.hh"
 #include "solid_mechanics_model.hh"
 #include "test_material_damage.hh"
 /* -------------------------------------------------------------------------- */
 using namespace akantu;
-typedef std::vector<std::pair<IntegrationPoint, IntegrationPoint> > PairList;
+typedef std::vector<std::pair<IntegrationPoint, IntegrationPoint>> PairList;
 
 /* -------------------------------------------------------------------------- */
 void computePairs(SolidMechanicsModel & model, PairList * pair_list);
 int main(int argc, char * argv[]) {
   akantu::initialize("material_remove_damage.dat", argc, argv);
 
   // some configuration variables
   const UInt spatial_dimension = 2;
 
   StaticCommunicator & comm =
-    akantu::StaticCommunicator::getStaticCommunicator();
-  Int psize = comm.getNbProc();
+      akantu::StaticCommunicator::getStaticCommunicator();
   Int prank = comm.whoAmI();
 
   // mesh creation and read
   Mesh mesh(spatial_dimension);
-  akantu::MeshPartition * partition = NULL;
   if (prank == 0) {
     mesh.read("pair_test.msh");
-    /// partition the mesh
-    partition = new MeshPartitionScotch(mesh, spatial_dimension);
-    partition->partitionate(psize);
   }
+  mesh.distribute();
 
   /// model creation
   SolidMechanicsModel model(mesh);
-  model.initParallel(partition);
-  delete partition;
 
   /// creation of material selector
   MeshDataMaterialSelector<std::string> * mat_selector;
   mat_selector =
       new MeshDataMaterialSelector<std::string>("physical_names", model);
   model.setMaterialSelector(*mat_selector);
 
   /// model initialization changed to use our material
-  model.initFull(_no_init_materials = true);
-  model.registerNewCustomMaterials<TestMaterialDamage<spatial_dimension> >(
-      "test_material");
-  model.initMaterials();
+  model.initFull();
+
   /// dump material index in paraview
   model.addDumpField("material_index");
   model.dump();
 
   /// compute the pairs by looping over all the quadrature points
   PairList pair_list[2];
   computePairs(model, pair_list);
 
-  NonLocalManager & manager = model.getNonLocalManager();
-  const PairList * pairs_mat_1 =
-      manager.getNeighborhood("mat_1").getPairLists();
-  const PairList * pairs_mat_2 =
-      manager.getNeighborhood("mat_2").getPairLists();
+  const PairList * pairs_mat_1 = model.getNeighborhood("mat_1").getPairLists();
+  const PairList * pairs_mat_2 = model.getNeighborhood("mat_2").getPairLists();
 
   /// compare the number of pairs
   UInt nb_not_ghost_pairs_grid = pairs_mat_1[0].size() + pairs_mat_2[0].size();
   UInt nb_ghost_pairs_grid = pairs_mat_1[1].size() + pairs_mat_2[1].size();
   UInt nb_not_ghost_pairs_no_grid = pair_list[0].size();
   UInt nb_ghost_pairs_no_grid = pair_list[1].size();
 
   if ((nb_not_ghost_pairs_grid != nb_not_ghost_pairs_no_grid) ||
       (nb_ghost_pairs_grid != nb_ghost_pairs_no_grid)) {
     std::cout << "The number of pairs is not correct: TEST FAILED!!!"
               << std::endl;
     finalize();
     return EXIT_FAILURE;
   }
 
   for (UInt i = 0; i < pairs_mat_1[0].size(); ++i) {
     std::pair<IntegrationPoint, IntegrationPoint> p = (pairs_mat_1[0])[i];
     PairList::const_iterator it = std::find(
         pair_list[0].begin(), pair_list[0].end(), (pairs_mat_1[0])[i]);
     if (it == pair_list[0].end()) {
       std::cout << "The pairs are not correct" << std::endl;
       finalize();
       return EXIT_FAILURE;
     }
   }
 
   for (UInt i = 0; i < pairs_mat_2[0].size(); ++i) {
     std::pair<IntegrationPoint, IntegrationPoint> p = (pairs_mat_2[0])[i];
     PairList::const_iterator it = std::find(
         pair_list[0].begin(), pair_list[0].end(), (pairs_mat_2[0])[i]);
     if (it == pair_list[0].end()) {
       std::cout << "The pairs are not correct" << std::endl;
       finalize();
       return EXIT_FAILURE;
     }
   }
 
   for (UInt i = 0; i < pairs_mat_1[1].size(); ++i) {
     std::pair<IntegrationPoint, IntegrationPoint> p = (pairs_mat_1[1])[i];
     PairList::const_iterator it = std::find(
         pair_list[1].begin(), pair_list[1].end(), (pairs_mat_1[1])[i]);
     if (it == pair_list[1].end()) {
       std::cout << "The pairs are not correct" << std::endl;
       finalize();
       return EXIT_FAILURE;
     }
   }
 
   for (UInt i = 0; i < pairs_mat_2[1].size(); ++i) {
     std::pair<IntegrationPoint, IntegrationPoint> p = (pairs_mat_2[1])[i];
     PairList::const_iterator it = std::find(
         pair_list[1].begin(), pair_list[1].end(), (pairs_mat_2[1])[i]);
     if (it == pair_list[1].end()) {
       std::cout << "The pairs are not correct" << std::endl;
       finalize();
       return EXIT_FAILURE;
     }
   }
 
   finalize();
 
   return 0;
 }
 
 /* -------------------------------------------------------------------------- */
 void computePairs(SolidMechanicsModel & model, PairList * pair_list) {
   ElementKind kind = _ek_regular;
   Mesh & mesh = model.getMesh();
   UInt spatial_dimension = model.getSpatialDimension();
   /// compute the quadrature points
   ElementTypeMapReal quad_coords("quad_coords");
-  mesh.initElementTypeMapArray(quad_coords, spatial_dimension,
-                               spatial_dimension, false, _ek_regular, true);
+  quad_coords.initialize(mesh, _nb_component = spatial_dimension,
+                         _spatial_dimension = spatial_dimension,
+                         _with_nb_element = true);
   model.getFEEngine().computeIntegrationPointsCoordinates(quad_coords);
 
   /// loop in a n^2 way over all the quads to generate the pairs
   Real neighborhood_radius = 0.5;
   Mesh::type_iterator it_1 =
       mesh.firstType(spatial_dimension, _not_ghost, kind);
   Mesh::type_iterator last_type_1 =
       mesh.lastType(spatial_dimension, _not_ghost, kind);
   IntegrationPoint q1;
   IntegrationPoint q2;
   q1.kind = kind;
   q2.kind = kind;
   GhostType ghost_type_1 = _not_ghost;
   q1.ghost_type = ghost_type_1;
   Vector<Real> q1_coords(spatial_dimension);
   Vector<Real> q2_coords(spatial_dimension);
 
   for (; it_1 != last_type_1; ++it_1) {
     ElementType type_1 = *it_1;
     q1.type = type_1;
     UInt nb_elements_1 = mesh.getNbElement(type_1, ghost_type_1);
     UInt nb_quads_1 = model.getFEEngine().getNbIntegrationPoints(type_1);
     Array<Real> & quad_coords_1 = quad_coords(q1.type, q1.ghost_type);
     Array<Real>::const_vector_iterator coord_it_1 =
         quad_coords_1.begin(spatial_dimension);
     for (UInt e_1 = 0; e_1 < nb_elements_1; ++e_1) {
       q1.element = e_1;
       UInt mat_index_1 = model.getMaterialByElement(q1.type, q1.ghost_type)
                              .begin()[q1.element];
       for (UInt q_1 = 0; q_1 < nb_quads_1; ++q_1) {
         q1.global_num = nb_quads_1 * e_1 + q_1;
         q1.num_point = q_1;
         q1_coords = coord_it_1[q1.global_num];
         /// loop over all other quads and create pairs for this given quad
         for (ghost_type_t::iterator gt = ghost_type_t::begin();
              gt != ghost_type_t::end(); ++gt) {
           GhostType ghost_type_2 = *gt;
           q2.ghost_type = ghost_type_2;
           Mesh::type_iterator it_2 =
               mesh.firstType(spatial_dimension, ghost_type_2, kind);
           Mesh::type_iterator last_type_2 =
               mesh.lastType(spatial_dimension, ghost_type_2, kind);
           for (; it_2 != last_type_2; ++it_2) {
             ElementType type_2 = *it_2;
             q2.type = type_2;
             UInt nb_elements_2 = mesh.getNbElement(type_2, ghost_type_2);
             UInt nb_quads_2 =
                 model.getFEEngine().getNbIntegrationPoints(type_2);
             Array<Real> & quad_coords_2 = quad_coords(q2.type, q2.ghost_type);
             Array<Real>::const_vector_iterator coord_it_2 =
                 quad_coords_2.begin(spatial_dimension);
             for (UInt e_2 = 0; e_2 < nb_elements_2; ++e_2) {
               q2.element = e_2;
               UInt mat_index_2 =
                   model.getMaterialByElement(q2.type, q2.ghost_type)
                       .begin()[q2.element];
               for (UInt q_2 = 0; q_2 < nb_quads_2; ++q_2) {
                 q2.global_num = nb_quads_2 * e_2 + q_2;
                 q2.num_point = q_2;
                 q2_coords = coord_it_2[q2.global_num];
                 Real distance = q1_coords.distance(q2_coords);
                 if (mat_index_1 != mat_index_2)
                   continue;
                 else if (distance <=
                              neighborhood_radius + Math::getTolerance() &&
                          (q2.ghost_type == _ghost ||
                           (q2.ghost_type == _not_ghost &&
                            q1.global_num <=
                                q2.global_num))) { // storing only half lists
                   pair_list[q2.ghost_type].push_back(std::make_pair(q1, q2));
                 }
               }
             }
           }
         }
       }
     }
   }
 }
diff --git a/test/test_model/test_non_local_toolbox/test_remove_damage_weight_function.cc b/test/test_model/test_non_local_toolbox/test_remove_damage_weight_function.cc
index fe070b933..961d9a9fa 100644
--- a/test/test_model/test_non_local_toolbox/test_remove_damage_weight_function.cc
+++ b/test/test_model/test_non_local_toolbox/test_remove_damage_weight_function.cc
@@ -1,202 +1,198 @@
 /**
  * @file   test_remove_damage_weight_function.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  *
  * @date creation: Wed Oct 07 2015
  *
  * @brief  Test the damage weight funcion for non local computations
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "dumper_paraview.hh"
 #include "non_local_manager.hh"
 #include "non_local_neighborhood.hh"
 #include "solid_mechanics_model.hh"
 #include "test_material_damage.hh"
 /* -------------------------------------------------------------------------- */
 using namespace akantu;
 /* -------------------------------------------------------------------------- */
 int main(int argc, char * argv[]) {
   akantu::initialize("material_remove_damage.dat", argc, argv);
 
   // some configuration variables
   const UInt spatial_dimension = 2;
   ElementType element_type = _quadrangle_4;
   GhostType ghost_type = _not_ghost;
 
   // mesh creation and read
   Mesh mesh(spatial_dimension);
   mesh.read("plate.msh");
 
   /// model creation
   SolidMechanicsModel model(mesh);
   /// creation of material selector
   MeshDataMaterialSelector<std::string> * mat_selector;
   mat_selector =
     new MeshDataMaterialSelector<std::string>("physical_names", model);
   model.setMaterialSelector(*mat_selector);
 
   /// model initialization changed to use our material
-  model.initFull(_no_init_materials = true);
-  model.registerNewCustomMaterials<TestMaterialDamage<spatial_dimension> >(
-      "test_material");
-  model.initMaterials();
+  model.initFull();
   /// dump material index in paraview
   model.addDumpField("material_index");
   model.addDumpField("grad_u");
   model.addDumpField("grad_u non local");
   model.addDumpField("damage");
   model.dump();
 
   /// apply constant strain field in all elements except element 3 and 15
   Matrix<Real> applied_strain(spatial_dimension, spatial_dimension);
   applied_strain.clear();
   for (UInt i = 0; i < spatial_dimension; ++i)
     applied_strain(i, i) = 2.;
 
   /// apply different strain in element 3 and 15
   Matrix<Real> modified_strain(spatial_dimension, spatial_dimension);
   modified_strain.clear();
   for (UInt i = 0; i < spatial_dimension; ++i)
     modified_strain(i, i) = 1.;
 
   /// apply constant grad_u field in all elements
   for (UInt m = 0; m < model.getNbMaterials(); ++m) {
     Material & mat = model.getMaterial(m);
     Array<Real> & grad_u = const_cast<Array<Real> &>(
         mat.getInternal<Real>("grad_u")(element_type, ghost_type));
 
     Array<Real>::iterator<Matrix<Real> > grad_u_it =
         grad_u.begin(spatial_dimension, spatial_dimension);
     Array<Real>::iterator<Matrix<Real> > grad_u_end =
         grad_u.end(spatial_dimension, spatial_dimension);
     UInt element_counter = 0;
     for (; grad_u_it != grad_u_end; ++grad_u_it, ++element_counter)
       if (element_counter == 12 || element_counter == 13 ||
           element_counter == 14 || element_counter == 15)
         (*grad_u_it) += modified_strain;
       else
         (*grad_u_it) += applied_strain;
   }
 
   /// compute the non-local strains
-  model.getNonLocalManager().computeAllNonLocalStresses();
+  model.assembleInternalForces();
   model.dump();
   /// save the weights in a file
   NonLocalNeighborhood<RemoveDamagedWeightFunction> & neighborhood_1 =
       dynamic_cast<NonLocalNeighborhood<RemoveDamagedWeightFunction> &>(
-          model.getNonLocalManager().getNeighborhood("mat_1"));
+          model.getNeighborhood("mat_1"));
   NonLocalNeighborhood<RemoveDamagedWeightFunction> & neighborhood_2 =
       dynamic_cast<NonLocalNeighborhood<RemoveDamagedWeightFunction> &>(
-          model.getNonLocalManager().getNeighborhood("mat_2"));
+          model.getNeighborhood("mat_2"));
   neighborhood_1.saveWeights("before_0");
   neighborhood_2.saveWeights("before_1");
   for (UInt n = 0; n < 2; ++n) {
     /// print results to screen for validation
     std::stringstream sstr;
     sstr << "before_" << n << ".0";
     std::ifstream weights;
     weights.open(sstr.str());
     std::string current_line;
     while (getline(weights, current_line))
       std::cout << current_line << std::endl;
     weights.close();
   }
 
   /// apply damage to not have the elements with lower strain impact the
   /// averaging
   for (UInt m = 0; m < model.getNbMaterials(); ++m) {
     MaterialDamage<spatial_dimension> & mat =
         dynamic_cast<MaterialDamage<spatial_dimension> &>(model.getMaterial(m));
 
     Array<Real> & damage = const_cast<Array<Real> &>(
         mat.getInternal<Real>("damage")(element_type, ghost_type));
 
     Array<Real>::scalar_iterator dam_it = damage.begin();
     Array<Real>::scalar_iterator dam_end = damage.end();
     UInt element_counter = 0;
     for (; dam_it != dam_end; ++dam_it, ++element_counter)
       if (element_counter == 12 || element_counter == 13 ||
           element_counter == 14 || element_counter == 15)
         *dam_it = 0.9;
   }
 
   /// compute the non-local strains
-  model.getNonLocalManager().computeAllNonLocalStresses();
+  model.assembleInternalForces();
   neighborhood_1.saveWeights("after_0");
   neighborhood_2.saveWeights("after_1");
   for (UInt n = 0; n < 2; ++n) {
     /// print results to screen for validation
     std::stringstream sstr;
     sstr << "after_" << n << ".0";
     std::ifstream weights;
     weights.open(sstr.str());
     std::string current_line;
     while (getline(weights, current_line))
       std::cout << current_line << std::endl;
     weights.close();
   }
 
   model.dump();
 
   /// verify the result: non-local averaging over constant field must
   /// yield same constant field
   Real test_result = 0.;
   Matrix<Real> difference(spatial_dimension, spatial_dimension, 0.);
   Matrix<Real> difference_in_damaged_elements(spatial_dimension,
                                               spatial_dimension, 0.);
   for (UInt m = 0; m < model.getNbMaterials(); ++m) {
     difference_in_damaged_elements.clear();
-    MaterialNonLocal<spatial_dimension> & mat =
-        dynamic_cast<MaterialNonLocal<spatial_dimension> &>(
-            model.getMaterial(m));
+    auto & mat =
+            model.getMaterial(m);
     Array<Real> & grad_u_nl = const_cast<Array<Real> &>(
         mat.getInternal<Real>("grad_u non local")(element_type, ghost_type));
 
     Array<Real>::iterator<Matrix<Real> > grad_u_nl_it =
         grad_u_nl.begin(spatial_dimension, spatial_dimension);
     Array<Real>::iterator<Matrix<Real> > grad_u_nl_end =
         grad_u_nl.end(spatial_dimension, spatial_dimension);
     UInt element_counter = 0;
     for (; grad_u_nl_it != grad_u_nl_end; ++grad_u_nl_it, ++element_counter) {
       if (element_counter == 12 || element_counter == 13 ||
           element_counter == 14 || element_counter == 15)
         difference_in_damaged_elements += (*grad_u_nl_it);
       else
         difference = (*grad_u_nl_it) - applied_strain;
       test_result += difference.norm<L_2>();
     }
     difference_in_damaged_elements *= (1 / 4.);
     difference_in_damaged_elements -= (1.41142 * modified_strain);
     test_result += difference_in_damaged_elements.norm<L_2>();
   }
 
   if (test_result > 10.e-5) {
     std::cout << "the total norm is: " << test_result << std::endl;
     return EXIT_FAILURE;
   }
 
   finalize();
 
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_non_local_toolbox/test_weight_computation.cc b/test/test_model/test_non_local_toolbox/test_weight_computation.cc
index 6ca55d14f..54ec60c78 100644
--- a/test/test_model/test_non_local_toolbox/test_weight_computation.cc
+++ b/test/test_model/test_non_local_toolbox/test_weight_computation.cc
@@ -1,78 +1,76 @@
 /**
  * @file   test_weight_computation.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  *
  * @date creation: Sat Sep 26 2015
  * @date last modification: Wed Oct 07 2015
  *
  * @brief  test for the weight computation with base weight function
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "dumper_paraview.hh"
 #include "non_local_manager.hh"
 #include "non_local_neighborhood.hh"
 #include "solid_mechanics_model.hh"
 #include "test_material.hh"
 /* -------------------------------------------------------------------------- */
 using namespace akantu;
 /* -------------------------------------------------------------------------- */
 int main(int argc, char * argv[]) {
   akantu::initialize("material_weight_computation.dat", argc, argv);
 
   // some configuration variables
   const UInt spatial_dimension = 2;
 
   // mesh creation and read
   Mesh mesh(spatial_dimension);
   mesh.read("plate.msh");
 
   /// model creation
   SolidMechanicsModel model(mesh);
 
   /// model initialization changed to use our material
-  model.initFull(_no_init_materials = true);
-  model.registerNewCustomMaterials<TestMaterial<spatial_dimension> >(
-      "test_material");
-  model.initMaterials();
+  model.initFull();
+
   /// dump material index in paraview
   model.addDumpField("material_index");
   model.dump();
 
   /// save the weights in a file
   NonLocalNeighborhood<BaseWeightFunction> & neighborhood =
     dynamic_cast<NonLocalNeighborhood<BaseWeightFunction> &>(
-        model.getNonLocalManager().getNeighborhood("test_region"));
+        model.getNeighborhood("test_region"));
 
   neighborhood.saveWeights("weights");
   /// print results to screen for validation
   std::ifstream weights;
   weights.open("weights.0");
   std::string current_line;
   while (getline(weights, current_line))
     std::cout << current_line << std::endl;
   weights.close();
   finalize();
 
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc
index dfa76b23f..1e199d191 100644
--- a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc
+++ b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc
@@ -1,312 +1,313 @@
 /**
  * @file   patch_test_explicit.cc
  *
  * @author David Simon Kammer <david.kammer@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Cyprien Wolff <cyprien.wolff@epfl.ch>
  *
  * @date creation: Sat Apr 16 2011
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  patch test for elastic material in solid mechanics model
  *
  * @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 <iostream>
-
 #include "solid_mechanics_model.hh"
+/* -------------------------------------------------------------------------- */
+#include <fstream>
+/* -------------------------------------------------------------------------- */
 
 using namespace akantu;
 
 Real alpha[3][4] = {{0.01, 0.02, 0.03, 0.04},
                     {0.05, 0.06, 0.07, 0.08},
                     {0.09, 0.10, 0.11, 0.12}};
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type, bool plane_strain>
 static Matrix<Real> prescribed_strain() {
   UInt spatial_dimension = ElementClass<type>::getSpatialDimension();
   Matrix<Real> strain(spatial_dimension, spatial_dimension);
 
   for (UInt i = 0; i < spatial_dimension; ++i) {
     for (UInt j = 0; j < spatial_dimension; ++j) {
       strain(i, j) = alpha[i][j + 1];
     }
   }
   return strain;
 }
 
 template <ElementType type, bool is_plane_strain>
 static Matrix<Real> prescribed_stress() {
   UInt spatial_dimension = ElementClass<type>::getSpatialDimension();
   Matrix<Real> stress(spatial_dimension, spatial_dimension);
 
   // plane strain in 2d
   Matrix<Real> strain(spatial_dimension, spatial_dimension);
   Matrix<Real> pstrain;
   pstrain = prescribed_strain<type, is_plane_strain>();
   Real nu = 0.3;
   Real E = 2.1e11;
   Real trace = 0;
 
   /// symetric part of the strain tensor
   for (UInt i = 0; i < spatial_dimension; ++i)
     for (UInt j = 0; j < spatial_dimension; ++j)
       strain(i, j) = 0.5 * (pstrain(i, j) + pstrain(j, i));
 
   for (UInt i = 0; i < spatial_dimension; ++i)
     trace += strain(i, i);
 
   if (spatial_dimension == 1) {
     stress(0, 0) = E * strain(0, 0);
   } else {
     if (is_plane_strain) {
       Real Ep = E / (1 + nu);
       for (UInt i = 0; i < spatial_dimension; ++i)
         for (UInt j = 0; j < spatial_dimension; ++j) {
           stress(i, j) = Ep * strain(i, j);
           if (i == j)
             stress(i, j) += Ep * (nu / (1 - 2 * nu)) * trace;
         }
     } else {
       Real Ep = E / (1 + nu);
       for (UInt i = 0; i < spatial_dimension; ++i)
         for (UInt j = 0; j < spatial_dimension; ++j) {
           stress(i, j) = Ep * strain(i, j);
           if (i == j)
             stress(i, j) += (nu * E) / (1 - (nu * nu)) * trace;
         }
     }
   }
 
   return stress;
 }
 
 /* -------------------------------------------------------------------------- */
 int main(int argc, char * argv[]) {
   std::string input_file;
   if (PLANE_STRAIN)
     input_file = "material_check_stress_plane_strain.dat";
   else
     input_file = "material_check_stress_plane_stress.dat";
 
   initialize(input_file, argc, argv);
 
   debug::setDebugLevel(dblWarning);
   UInt dim = ElementClass<TYPE>::getSpatialDimension();
   const ElementType element_type = TYPE;
 
   UInt damping_steps = 600000;
   UInt damping_interval = 50;
   Real damping_ratio = 0.99;
 
   UInt additional_steps = 20000;
   UInt max_steps = damping_steps + additional_steps;
 
   /// load mesh
   Mesh my_mesh(dim);
 
   std::stringstream filename;
   filename << TYPE << ".msh";
   my_mesh.read(filename.str());
 
   UInt nb_nodes = my_mesh.getNbNodes();
 
   /// declaration of model
   SolidMechanicsModel my_model(my_mesh);
   /// model initialization
   my_model.initFull();
 
   std::cout << my_model.getMaterial(0) << std::endl;
   Real time_step = my_model.getStableTimeStep() / 100.;
   my_model.setTimeStep(time_step);
   my_model.assembleMassLumped();
 
   std::cout << "The number of time steps is: " << max_steps << " (" << time_step
             << "s)" << std::endl;
 
   // boundary conditions
   const Array<Real> & coordinates = my_mesh.getNodes();
   Array<Real> & displacement = my_model.getDisplacement();
   Array<bool> & boundary = my_model.getBlockedDOFs();
 
   MeshUtils::buildFacets(my_mesh);
 
   my_mesh.createBoundaryGroupFromGeometry();
 
   // Loop over (Sub)Boundar(ies) to block the nodes
   for (GroupManager::const_element_group_iterator it(
            my_mesh.element_group_begin());
        it != my_mesh.element_group_end(); ++it)
     for (ElementGroup::const_node_iterator nodes_it(it->second->node_begin());
          nodes_it != it->second->node_end(); ++nodes_it)
       for (UInt i = 0; i < dim; ++i)
         boundary(*nodes_it, i) = true;
 
   // set the position of all nodes to the static solution
   for (UInt n = 0; n < nb_nodes; ++n) {
     for (UInt i = 0; i < dim; ++i) {
       displacement(n, i) = alpha[i][0];
       for (UInt j = 0; j < dim; ++j) {
         displacement(n, i) += alpha[i][j + 1] * coordinates(n, j);
       }
     }
   }
 
   Array<Real> & velocity = my_model.getVelocity();
 
   std::ofstream energy;
   std::stringstream energy_filename;
   energy_filename << "energy_" << TYPE << ".csv";
   energy.open(energy_filename.str().c_str());
   energy << "id,time,ekin" << std::endl;
   Real ekin_mean = 0.;
 
 //#define DEBUG_TEST
 #ifdef DEBUG_TEST
   my_model.solveStep();
   my_model.addDumpField("strain");
   my_model.addDumpField("stress");
   my_model.addDumpField("external_force");
   my_model.addDumpField("internal_force");
   my_model.addDumpField("velocity");
   my_model.addDumpField("acceleration");
   my_model.addDumpField("displacement");
   my_model.dump();
 #endif
   /* ------------------------------------------------------------------------ */
   /* Main loop                                                                */
   /* ------------------------------------------------------------------------ */
   UInt s;
   for (s = 1; s <= max_steps; ++s) {
     if (s % 10000 == 0)
       std::cout << "passing step " << s << "/" << max_steps << " ("
                 << s * time_step << "s)" << std::endl;
 
     // damp velocity in order to find equilibrium
     if ((s < damping_steps) && (s % damping_interval == 0)) {
       velocity *= damping_ratio;
     }
 
     if (s % 1000 == 0) {
       ekin_mean = ekin_mean / 1000.;
       std::cout << "Ekin mean = " << ekin_mean << std::endl;
       if (ekin_mean < 1e-10)
         break;
       ekin_mean = 0.;
     }
 
     my_model.solveStep();
 
     akantu::Real ekin = my_model.getEnergy("kinetic");
     ekin_mean += ekin;
 
     if (s % 1000 == 0)
       energy << s << "," << s * time_step << "," << ekin << std::endl;
   }
 
   energy.close();
 
   UInt nb_quadrature_points =
       my_model.getFEEngine().getNbIntegrationPoints(TYPE);
   Array<Real> & stress_vect = const_cast<Array<Real> &>(
       my_model.getMaterial(0).getStress(element_type));
   Array<Real> & strain_vect =
       const_cast<Array<Real> &>(my_model.getMaterial(0).getGradU(element_type));
 
   Array<Real>::matrix_iterator stress_it = stress_vect.begin(dim, dim);
   Array<Real>::matrix_iterator strain_it = strain_vect.begin(dim, dim);
 
   Matrix<Real> presc_stress;
   presc_stress = prescribed_stress<TYPE, PLANE_STRAIN>();
   Matrix<Real> presc_strain;
   presc_strain = prescribed_strain<TYPE, PLANE_STRAIN>();
 
   UInt nb_element = my_mesh.getNbElement(TYPE);
 
   Real strain_tolerance = 1e-13;
   Real stress_tolerance = 1e-13;
 
   for (UInt el = 0; el < nb_element; ++el) {
     for (UInt q = 0; q < nb_quadrature_points; ++q) {
       Matrix<Real> & stress = *stress_it;
       Matrix<Real> & strain = *strain_it;
 
       Matrix<Real> diff(dim, dim);
 
       diff = strain;
       diff -= presc_strain;
       Real strain_error = diff.norm<L_inf>() / strain.norm<L_inf>();
 
       if (strain_error > strain_tolerance) {
         std::cerr << "strain error: " << strain_error << " > "
                   << strain_tolerance << std::endl;
         std::cerr << "strain: " << strain << std::endl
                   << "prescribed strain: " << presc_strain << std::endl;
         return EXIT_FAILURE;
       } else {
         std::cerr << "strain error: " << strain_error << " < "
                   << strain_tolerance << std::endl;
       }
 
       diff = stress;
       diff -= presc_stress;
       Real stress_error = diff.norm<L_inf>() / stress.norm<L_inf>();
 
       if (stress_error > stress_tolerance) {
         std::cerr << "stress error: " << stress_error << " > "
                   << stress_tolerance << std::endl;
         std::cerr << "stress: " << stress << std::endl
                   << "prescribed stress: " << presc_stress << std::endl;
         return EXIT_FAILURE;
       } else {
         std::cerr << "stress error: " << stress_error << " < "
                   << stress_tolerance << std::endl;
       }
 
       ++stress_it;
       ++strain_it;
     }
   }
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     for (UInt i = 0; i < dim; ++i) {
       Real disp = alpha[i][0];
       for (UInt j = 0; j < dim; ++j) {
         disp += alpha[i][j + 1] * coordinates(n, j);
       }
 
       if (!(std::abs(displacement(n, i) - disp) < 1e-7)) {
         std::cerr << "displacement(" << n << ", " << i
                   << ")=" << displacement(n, i) << " should be equal to "
                   << disp << "(" << displacement(n, i) - disp << ")"
                   << std::endl;
         return EXIT_FAILURE;
       }
     }
   }
 
   finalize();
 
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit_anisotropic.cc b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit_anisotropic.cc
index 26751dd04..fde87d4e0 100644
--- a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit_anisotropic.cc
+++ b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit_anisotropic.cc
@@ -1,312 +1,314 @@
 /**
  * @file   patch_test_explicit_anisotropic.cc
  *
  * @author Till Junge <till.junge@epfl.ch>
  * @author David Simon Kammer <david.kammer@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Cyprien Wolff <cyprien.wolff@epfl.ch>
  *
  * @date creation: Sat Apr 16 2011
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  patch test for elastic material in solid mechanics model
  *
  * @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 <iostream>
-
 #include "solid_mechanics_model.hh"
+/* -------------------------------------------------------------------------- */
+#include <fstream>
+/* -------------------------------------------------------------------------- */
+
 
 using namespace akantu;
 
 Real alpha[3][4] = {{0.01, 0.02, 0.03, 0.04},
                     {0.05, 0.06, 0.07, 0.08},
                     {0.09, 0.10, 0.11, 0.12}};
 
 // Stiffness tensor, rotated by hand
 Real C[3][3][3][3] = {
     {{{112.93753505, 1.85842452538e-10, -4.47654358027e-10},
       {1.85847317471e-10, 54.2334345331, -3.69840984824},
       {-4.4764768395e-10, -3.69840984824, 56.848605217}},
      {{1.85847781609e-10, 25.429294233, -3.69840984816},
       {25.429294233, 3.31613847493e-10, -8.38797920011e-11},
       {-3.69840984816, -8.38804581349e-11, -1.97875715813e-10}},
      {{-4.47654358027e-10, -3.69840984816, 28.044464917},
       {-3.69840984816, 2.09374961813e-10, 9.4857455224e-12},
       {28.044464917, 9.48308098714e-12, -2.1367885239e-10}}},
     {{{1.85847781609e-10, 25.429294233, -3.69840984816},
       {25.429294233, 3.31613847493e-10, -8.38793479119e-11},
       {-3.69840984816, -8.38795699565e-11, -1.97876381947e-10}},
      {{54.2334345331, 3.31617400207e-10, 2.09372075233e-10},
       {3.3161562385e-10, 115.552705733, -3.15093728886e-10},
       {2.09372075233e-10, -3.15090176173e-10, 54.2334345333}},
      {{-3.69840984824, -8.38795699565e-11, 9.48219280872e-12},
       {-8.38795699565e-11, -3.1509195253e-10, 25.4292942335},
       {9.48441325477e-12, 25.4292942335, 3.69840984851}}},
     {{{-4.47653469848e-10, -3.69840984816, 28.044464917},
       {-3.69840984816, 2.09374073634e-10, 9.48752187924e-12},
       {28.044464917, 9.48552347779e-12, -2.1367885239e-10}},
      {{-3.69840984824, -8.3884899027e-11, 9.48219280872e-12},
       {-8.3884899027e-11, -3.150972816e-10, 25.4292942335},
       {9.48041645188e-12, 25.4292942335, 3.69840984851}},
      {{56.848605217, -1.97875493768e-10, -2.13681516925e-10},
       {-1.97877270125e-10, 54.2334345333, 3.69840984851},
       {-2.13683293282e-10, 3.69840984851, 112.93753505}}}};
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type> static Matrix<Real> prescribed_grad_u() {
   UInt spatial_dimension = ElementClass<type>::getSpatialDimension();
   Matrix<Real> grad_u(spatial_dimension, spatial_dimension);
 
   for (UInt i = 0; i < spatial_dimension; ++i) {
     for (UInt j = 0; j < spatial_dimension; ++j) {
       grad_u(i, j) = alpha[i][j + 1];
     }
   }
   return grad_u;
 }
 
 template <ElementType type> static Matrix<Real> prescribed_stress() {
   UInt spatial_dimension = ElementClass<type>::getSpatialDimension();
   Matrix<Real> stress(spatial_dimension, spatial_dimension);
 
   // plane strain in 2d
   Matrix<Real> strain(spatial_dimension, spatial_dimension);
   Matrix<Real> pstrain;
   pstrain = prescribed_grad_u<type>();
   Real trace = 0;
 
   /// symetric part of the strain tensor
   for (UInt i = 0; i < spatial_dimension; ++i)
     for (UInt j = 0; j < spatial_dimension; ++j)
       strain(i, j) = 0.5 * (pstrain(i, j) + pstrain(j, i));
 
   for (UInt i = 0; i < spatial_dimension; ++i)
     trace += strain(i, i);
 
   for (UInt i = 0; i < spatial_dimension; ++i) {
     for (UInt j = 0; j < spatial_dimension; ++j) {
       stress(i, j) = 0;
       for (UInt k = 0; k < spatial_dimension; ++k) {
         for (UInt l = 0; l < spatial_dimension; ++l) {
           stress(i, j) += C[i][j][k][l] * strain(k, l);
         }
       }
     }
   }
   return stress;
 }
 
 #define TYPE _tetrahedron_4
 /* -------------------------------------------------------------------------- */
 int main(int argc, char * argv[]) {
   initialize("material_anisotropic.dat", argc, argv);
 
   UInt dim = ElementClass<TYPE>::getSpatialDimension();
   const ElementType element_type = TYPE;
 
   UInt damping_steps = 600000;
   UInt damping_interval = 50;
   Real damping_ratio = 0.99;
 
   UInt additional_steps = 20000;
   UInt max_steps = damping_steps + additional_steps;
 
   /// load mesh
   Mesh my_mesh(dim);
 
   std::stringstream filename;
   filename << TYPE << ".msh";
   my_mesh.read(filename.str());
 
   UInt nb_nodes = my_mesh.getNbNodes();
 
   /// declaration of model
   SolidMechanicsModel model(my_mesh);
   /// model initialization
   model.initFull();
 
   std::cout << model.getMaterial(0) << std::endl;
   Real time_step = model.getStableTimeStep() / 5.;
   model.setTimeStep(time_step);
 
   std::cout << "The number of time steps is: " << max_steps << " (" << time_step
             << "s)" << std::endl;
 
   // boundary conditions
   const Array<Real> & coordinates = my_mesh.getNodes();
   Array<Real> & displacement = model.getDisplacement();
   Array<bool> & boundary = model.getBlockedDOFs();
 
   MeshUtils::buildFacets(my_mesh);
 
   my_mesh.createBoundaryGroupFromGeometry();
 
   // Loop over (Sub)Boundar(ies)
   // Loop over (Sub)Boundar(ies)
   for (GroupManager::const_element_group_iterator it(
            my_mesh.element_group_begin());
        it != my_mesh.element_group_end(); ++it) {
     for (ElementGroup::const_node_iterator nodes_it(it->second->node_begin());
          nodes_it != it->second->node_end(); ++nodes_it) {
       UInt n(*nodes_it);
       std::cout << "Node " << *nodes_it << std::endl;
       for (UInt i = 0; i < dim; ++i) {
         displacement(n, i) = alpha[i][0];
         for (UInt j = 0; j < dim; ++j) {
           displacement(n, i) += alpha[i][j + 1] * coordinates(n, j);
         }
         boundary(n, i) = true;
       }
     }
   }
 
   // Actually, loop over all nodes, since I wanna test a static solution
   for (UInt n = 0; n < nb_nodes; ++n) {
     for (UInt i = 0; i < dim; ++i) {
       displacement(n, i) = alpha[i][0];
       for (UInt j = 0; j < dim; ++j) {
         displacement(n, i) += alpha[i][j + 1] * coordinates(n, j);
       }
     }
   }
 
   Array<Real> & velocity = model.getVelocity();
 
   std::ofstream energy;
   std::stringstream energy_filename;
   energy_filename << "energy_" << TYPE << ".csv";
   energy.open(energy_filename.str().c_str());
   energy << "id,time,ekin" << std::endl;
   Real ekin_mean = 0.;
 
   /* ------------------------------------------------------------------------ */
   /* Main loop                                                                */
   /* ------------------------------------------------------------------------ */
   UInt s;
   for (s = 1; s <= max_steps; ++s) {
     if (s % 10000 == 0)
       std::cout << "passing step " << s << "/" << max_steps << " ("
                 << s * time_step << "s)" << std::endl;
 
     // damp velocity in order to find equilibrium
     if ((s < damping_steps) && (s % damping_interval == 0)) {
       velocity *= damping_ratio;
     }
 
     if (s % 1000 == 0) {
       ekin_mean = ekin_mean / 1000.;
       std::cout << "Ekin mean = " << ekin_mean << std::endl;
       if (ekin_mean < 1e-10)
         break;
       ekin_mean = 0.;
     }
 
     model.solveStep();
 
     Real ekin = model.getEnergy("kinetic");
     ekin_mean += ekin;
 
     if (s % 1000 == 0)
       energy << s << "," << s * time_step << "," << ekin << std::endl;
   }
 
   energy.close();
 
   UInt nb_quadrature_points = model.getFEEngine().getNbIntegrationPoints(TYPE);
   Array<Real> & stress_vect =
       const_cast<Array<Real> &>(model.getMaterial(0).getStress(element_type));
   Array<Real> & gradu_vect =
       const_cast<Array<Real> &>(model.getMaterial(0).getGradU(element_type));
 
   Array<Real>::iterator<Matrix<Real>> stress_it = stress_vect.begin(dim, dim);
   Array<Real>::iterator<Matrix<Real>> gradu_it = gradu_vect.begin(dim, dim);
 
   Matrix<Real> presc_stress;
   presc_stress = prescribed_stress<TYPE>();
   Matrix<Real> presc_gradu;
   presc_gradu = prescribed_grad_u<TYPE>();
 
   UInt nb_element = my_mesh.getNbElement(TYPE);
 
   Real gradu_tolerance = 1e-9;
   Real stress_tolerance = 1e-2;
   if (s > max_steps) {
     stress_tolerance = 1e-4;
     gradu_tolerance = 1e-7;
   }
 
   for (UInt el = 0; el < nb_element; ++el) {
     for (UInt q = 0; q < nb_quadrature_points; ++q) {
       Matrix<Real> & stress = *stress_it;
       Matrix<Real> & gradu = *gradu_it;
 
       for (UInt i = 0; i < dim; ++i) {
         for (UInt j = 0; j < dim; ++j) {
           if (!(std::abs(gradu(i, j) - presc_gradu(i, j)) < gradu_tolerance)) {
             std::cerr << "gradu[" << i << "," << j << "] = " << gradu(i, j)
                       << " but should be = " << presc_gradu(i, j) << " (-"
                       << std::abs(gradu(i, j) - presc_gradu(i, j))
                       << ") [el : " << el << " - q : " << q << "]" << std::endl;
             std::cerr << gradu << presc_gradu << std::endl;
             return EXIT_FAILURE;
           }
 
           if (!(std::abs(stress(i, j) - presc_stress(i, j)) <
                 stress_tolerance)) {
             std::cerr << "stress[" << i << "," << j << "] = " << stress(i, j)
                       << " but should be = " << presc_stress(i, j) << " (-"
                       << std::abs(stress(i, j) - presc_stress(i, j))
                       << ") [el : " << el << " - q : " << q << "]" << std::endl;
             std::cerr << stress << presc_stress << std::endl;
             return EXIT_FAILURE;
           }
         }
       }
 
       ++stress_it;
       ++gradu_it;
     }
   }
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     for (UInt i = 0; i < dim; ++i) {
       Real disp = alpha[i][0];
       for (UInt j = 0; j < dim; ++j) {
         disp += alpha[i][j + 1] * coordinates(n, j);
       }
 
       if (!(std::abs(displacement(n, i) - disp) < 1e-7)) {
         std::cerr << "displacement(" << n << ", " << i
                   << ")=" << displacement(n, i) << " should be equal to "
                   << disp << "(" << displacement(n, i) - disp << ")"
                   << std::endl;
         return EXIT_FAILURE;
       }
     }
   }
 
   finalize();
 
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc
index 1a035ea5b..62c37d21e 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc
@@ -1,121 +1,126 @@
 /**
  * @file   test_local_material.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Marion Estelle Chambart <marion.chambart@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Clement Roux <clement.roux@epfl.ch>
  *
  * @date creation: Wed Aug 04 2010
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  test of the class SolidMechanicsModel with custom local damage on a
  * notched plate
  *
  * @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 <iostream>
 
 /* -------------------------------------------------------------------------- */
 #include "local_material_damage.hh"
 #include "solid_mechanics_model.hh"
 /* -------------------------------------------------------------------------- */
 
 using namespace akantu;
 
 int main(int argc, char * argv[]) {
   akantu::initialize("material.dat", argc, argv);
   UInt max_steps = 1100;
 
   const UInt spatial_dimension = 2;
   Mesh mesh(spatial_dimension);
   mesh.read("mesh_section_gap.msh");
-  
+
   SolidMechanicsModel model(mesh);
 
   /// model initialization
-  model.initFull(_no_init_materials = true);
-  model.registerNewCustomMaterials<LocalMaterialDamage>("local_damage");
-  model.initMaterials();
+  MaterialFactory::getInstance().registerAllocator(
+      "local_damage",
+      [](UInt, const ID &, SolidMechanicsModel & model,
+         const ID & id) -> std::unique_ptr<Material> {
+        return std::make_unique<LocalMaterialDamage>(model, id);
+      });
+
+  model.initFull();
 
   Real time_step = model.getStableTimeStep();
   model.setTimeStep(time_step / 2.5);
 
   model.assembleMassLumped();
 
   std::cout << model << std::endl;
 
   /// Dirichlet boundary conditions
   model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "Fixed");
   // model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "Fixed");
 
   // Boundary condition (Neumann)
   Matrix<Real> stress(2, 2);
   stress.eye(7e5);
   model.applyBC(BC::Neumann::FromHigherDim(stress), "Traction");
 
   for (UInt s = 0; s < max_steps; ++s) {
     if (s < 100) {
       // Boundary condition (Neumann)
       stress.eye(7e5);
       model.applyBC(BC::Neumann::FromHigherDim(stress), "Traction");
     }
 
     model.solveStep();
   }
 
   const Vector<Real> & lower_bounds = mesh.getLowerBounds();
   const Vector<Real> & upper_bounds = mesh.getUpperBounds();
   Real L = upper_bounds(0) - lower_bounds(0);
 
   const ElementTypeMapArray<UInt> & filter =
       model.getMaterial(0).getElementFilter();
   ElementTypeMapArray<UInt>::type_iterator it =
       filter.firstType(spatial_dimension);
   ElementTypeMapArray<UInt>::type_iterator end =
       filter.lastType(spatial_dimension);
   Vector<Real> barycenter(spatial_dimension);
   bool is_fully_damaged = false;
   for (; it != end; ++it) {
     UInt nb_elem = mesh.getNbElement(*it);
     const UInt nb_gp = model.getFEEngine().getNbIntegrationPoints(*it);
     Array<Real> & material_damage_array =
         model.getMaterial(0).getArray<Real>("damage", *it);
     UInt cpt = 0;
     for (UInt nel = 0; nel < nb_elem; ++nel) {
       if (material_damage_array(cpt, 0) > 0.9) {
         is_fully_damaged = true;
         mesh.getBarycenter(nel, *it, barycenter.storage());
         if ((std::abs(barycenter(0) - (L / 2)) < (L / 10))) {
           return EXIT_FAILURE;
         }
       }
       cpt += nb_gp;
     }
   }
   if (!is_fully_damaged)
     return EXIT_FAILURE;
 
   akantu::finalize();
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc
index ab43b67d9..327c764f7 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc
@@ -1,294 +1,290 @@
 /**
  * @file   test_material_mazars.cc
  *
  * @author Clement Roux <clement.roux@epfl.ch>
  *
  * @date creation: Thu Oct 08 2015
  * @date last modification: Tue Dec 08 2015
  *
  * @brief  test for material mazars, dissymmetric
  *
  * @section LICENSE
  *
  * Copyright (©) 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_common.hh"
-#include "material.hh"
-#include "mesh.hh"
-#include "mesh_io.hh"
 #include "solid_mechanics_model.hh"
-//#include "io_helper_tools.hh"
-
 /* -------------------------------------------------------------------------- */
+#include <fstream>
+/* -------------------------------------------------------------------------- */
+
 using namespace akantu;
 
 /* -------------------------------------------------------------------------- */
 int main(int argc, char * argv[]) {
   debug::setDebugLevel(akantu::dblWarning);
 
   akantu::initialize("material_mazars.dat", argc, argv);
   const UInt spatial_dimension = 3;
 
   //  ElementType type = _quadrangle_4;
   ElementType type = _hexahedron_8;
   //  UInt compression_steps = 5e5;
   //  Real max_compression = 0.01;
 
   //  UInt traction_steps = 1e4;
   //  Real max_traction = 0.001;
 
   Mesh mesh(spatial_dimension);
   mesh.addConnectivityType(type);
 
   Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes());
   Array<UInt> & connectivity =
       const_cast<Array<UInt> &>(mesh.getConnectivity(type));
 
   const Real width = 1;
   UInt nb_dof = 0;
 
   connectivity.resize(1);
 
   if (type == _hexahedron_8) {
     nb_dof = 8;
     nodes.resize(nb_dof);
 
     nodes(0, 0) = 0.;
     nodes(0, 1) = 0.;
     nodes(0, 2) = 0.;
 
     nodes(1, 0) = width;
     nodes(1, 1) = 0.;
     nodes(1, 2) = 0.;
 
     nodes(2, 0) = width;
     nodes(2, 1) = width;
     nodes(2, 2) = 0;
 
     nodes(3, 0) = 0;
     nodes(3, 1) = width;
     nodes(3, 2) = 0;
 
     nodes(4, 0) = 0.;
     nodes(4, 1) = 0.;
     nodes(4, 2) = width;
 
     nodes(5, 0) = width;
     nodes(5, 1) = 0.;
     nodes(5, 2) = width;
 
     nodes(6, 0) = width;
     nodes(6, 1) = width;
     nodes(6, 2) = width;
 
     nodes(7, 0) = 0;
     nodes(7, 1) = width;
     nodes(7, 2) = width;
 
     connectivity(0, 0) = 0;
     connectivity(0, 1) = 1;
     connectivity(0, 2) = 2;
     connectivity(0, 3) = 3;
     connectivity(0, 4) = 4;
     connectivity(0, 5) = 5;
     connectivity(0, 6) = 6;
     connectivity(0, 7) = 7;
   } else if (type == _quadrangle_4) {
     nb_dof = 4;
     nodes.resize(nb_dof);
 
     nodes(0, 0) = 0.;
     nodes(0, 1) = 0.;
 
     nodes(1, 0) = width;
     nodes(1, 1) = 0;
 
     nodes(2, 0) = width;
     nodes(2, 1) = width;
 
     nodes(3, 0) = 0.;
     nodes(3, 1) = width;
 
     connectivity(0, 0) = 0;
     connectivity(0, 1) = 1;
     connectivity(0, 2) = 2;
     connectivity(0, 3) = 3;
   }
 
   SolidMechanicsModel model(mesh);
   model.initFull();
   Material & mat = model.getMaterial(0);
   std::cout << mat << std::endl;
 
   /// boundary conditions
   Array<Real> & disp = model.getDisplacement();
   Array<Real> & velo = model.getVelocity();
   Array<bool> & boun = model.getBlockedDOFs();
 
   for (UInt i = 0; i < nb_dof; ++i) {
     boun(i, 0) = true;
   }
 
   Real time_step = model.getStableTimeStep() * .5;
   // Real time_step = 1e-5;
 
   std::cout << "Time Step = " << time_step
             << "s - nb elements : " << mesh.getNbElement(type) << std::endl;
   model.setTimeStep(time_step);
 
   std::ofstream energy;
   energy.open("energies_and_scalar_mazars.csv");
   energy << "id,rtime,epot,ekin,u,wext,kin+pot,D,strain_xx,strain_yy,stress_xx,"
             "stress_yy,edis,tot"
          << std::endl;
 
   /// Set dumper
   model.setBaseName("uniaxial_comp-trac_mazars");
   model.addDumpFieldVector("displacement");
   model.addDumpField("velocity");
   model.addDumpField("acceleration");
   model.addDumpField("damage");
   model.addDumpField("strain");
   model.addDumpField("stress");
   model.addDumpField("partitions");
   model.dump();
 
   const Array<Real> & strain = mat.getGradU(type);
   const Array<Real> & stress = mat.getStress(type);
   const Array<Real> & damage = mat.getArray<Real>("damage", type);
 
   /* ------------------------------------------------------------------------ */
   /* Main loop                                                                */
   /* ------------------------------------------------------------------------ */
   Real wext = 0.;
   Real sigma_max = 0, sigma_min = 0;
 
   Real max_disp;
   Real stress_xx_compression_1;
   UInt nb_steps = 7e5 / 150;
 
   Real adisp = 0;
   for (UInt s = 0; s < nb_steps; ++s) {
     if (s == 0) {
       max_disp = 0.003;
       adisp = -(max_disp * 8. / nb_steps) / 2.;
       std::cout << "Step " << s << " compression: " << max_disp << std::endl;
     }
 
     if (s == (2 * nb_steps / 8)) {
       stress_xx_compression_1 = stress(0, 0);
       max_disp = 0 + max_disp;
       adisp = max_disp * 8. / nb_steps;
       std::cout << "Step " << s << " discharge" << std::endl;
     }
 
     if (s == (3 * nb_steps / 8)) {
       max_disp = 0.004;
       adisp = -max_disp * 8. / nb_steps;
       std::cout << "Step " << s << " compression: " << max_disp << std::endl;
     }
 
     if (s == (4 * nb_steps / 8)) {
       if (stress(0, 0) < stress_xx_compression_1) {
         std::cout << "after this second compression step softening should have "
                      "started"
                   << std::endl;
         return EXIT_FAILURE;
       }
       max_disp = 0.0015 + max_disp;
       adisp = max_disp * 8. / nb_steps;
       std::cout << "Step " << s << " discharge tension: " << max_disp
                 << std::endl;
     }
 
     if (s == (5 * nb_steps / 8)) {
       max_disp = 0. + 0.0005;
       adisp = -max_disp * 8. / nb_steps;
       std::cout << "Step " << s << " discharge" << std::endl;
     }
 
     if (s == (6 * nb_steps / 8)) {
       max_disp = 0.0035 - 0.001;
       adisp = max_disp * 8. / nb_steps;
       std::cout << "Step " << s << " tension: " << max_disp << std::endl;
     }
 
     if (s == (7 * nb_steps / 8)) {
       // max_disp = max_disp;
       adisp = -max_disp * 8. / nb_steps;
       std::cout << "Step " << s << " discharge" << std::endl;
     }
 
     for (UInt i = 0; i < nb_dof; ++i) {
       if (std::abs(nodes(i, 0) - width) <
           std::numeric_limits<Real>::epsilon()) {
         disp(i, 0) += adisp;
         velo(i, 0) = adisp / time_step;
       }
     }
 
     std::cout << "S: " << s << "/" << nb_steps << " inc disp: " << adisp
               << " disp: " << std::setw(5) << disp(2, 0) << "\r" << std::flush;
 
     model.solveStep();
 
     Real epot = model.getEnergy("potential");
     Real ekin = model.getEnergy("kinetic");
     Real edis = model.getEnergy("dissipated");
     wext += model.getEnergy("external work");
 
     sigma_max = std::max(sigma_max, stress(0, 0));
     sigma_min = std::min(sigma_min, stress(0, 0));
     if (s % 10 == 0)
       energy << s << ","             // 1
              << s * time_step << "," // 2
              << epot << ","          // 3
              << ekin << ","          // 4
              << disp(2, 0) << ","    // 5
              << wext << ","          // 6
              << epot + ekin << ","   // 7
              << damage(0) << ","     // 8
              << strain(0, 0) << ","  // 9
              << strain(0, 3) << ","  // 11
              << stress(0, 0) << ","  // 10
              << stress(0, 3) << ","  // 10
              << edis << ","          // 12
              << epot + ekin + edis   // 13
              << std::endl;
 
     if (s % 100 == 0)
       model.dump();
   }
 
   std::cout << std::endl
             << "sigma_max = " << sigma_max << ", sigma_min = " << sigma_min
             << std::endl;
   /// Verif the maximal/minimal stress values
   if ((std::abs(sigma_max) > std::abs(sigma_min)) ||
       (std::abs(sigma_max - 6.24e6) > 1e5) ||
       (std::abs(sigma_min + 2.943e7) > 1e6))
     return EXIT_FAILURE;
   energy.close();
 
   akantu::finalize();
 
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc
index 1ae75be0b..935159b21 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc
@@ -1,86 +1,86 @@
 /**
  * @file   custom_non_local_test_material.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Sun Mar 01 2015
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  Custom material to test the non local implementation
  *
  * @section LICENSE
  *
  * Copyright (©) 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 "custom_non_local_test_material.hh"
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 CustomNonLocalTestMaterial<dim>::CustomNonLocalTestMaterial(
     SolidMechanicsModel & model, const ID & id)
     : MyNonLocalParent(model, id), local_damage("local_damage", *this),
       damage("damage", *this) {
   // Initialize the internal field by specifying the number of components
   this->local_damage.initialize(1);
   this->damage.initialize(1);
   /// register the non-local variable in the manager
   this->model.registerNonLocalVariable(this->local_damage.getName(),
                                        this->damage.getName(), 1);
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim> void CustomNonLocalTestMaterial<dim>::initMaterial() {
   MyNonLocalParent::initMaterial();
   this->model.getNeighborhood(this->name).registerNonLocalVariable(damage.getName());
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void CustomNonLocalTestMaterial<dim>::computeStress(ElementType el_type,
                                                     GhostType ghost_type) {
   MyNonLocalParent::computeStress(el_type, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void CustomNonLocalTestMaterial<dim>::computeNonLocalStress(
     ElementType el_type, GhostType ghost_type) {
   Array<Real>::const_scalar_iterator dam =
       this->damage(el_type, ghost_type).begin();
   Array<Real>::matrix_iterator stress =
       this->stress(el_type, ghost_type).begin(dim, dim);
   Array<Real>::matrix_iterator stress_end =
       this->stress(el_type, ghost_type).end(dim, dim);
 
   // compute the damage and update the stresses
   for (; stress != stress_end; ++stress, ++dam) {
     *stress *= (1. - *dam);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 // Instantiate the material for the 3 dimensions
-INSTANTIATE_MATERIAL(CustomNonLocalTestMaterial);
+INSTANTIATE_MATERIAL(custom_non_local_test_material, CustomNonLocalTestMaterial);
 /* -------------------------------------------------------------------------- */
 } // namespace akantu
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc
index 409d04898..90cc88bf2 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc
@@ -1,104 +1,101 @@
 /**
  * @file   test_material_non_local.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Aug 31 2011
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  test of the main part of the non local materials
  *
  * @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 "solid_mechanics_model.hh"
 #include "custom_non_local_test_material.hh"
 /* -------------------------------------------------------------------------- */
 #include <iostream>
 /* -------------------------------------------------------------------------- */
 
 using namespace akantu;
 /* -------------------------------------------------------------------------- */
 int main(int argc, char *argv[]) {
   akantu::initialize("material.dat", argc, argv);
 
   // some configuration variables
   const UInt spatial_dimension = 2;
 
   Mesh mesh(spatial_dimension);
 
   StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator();
   Int prank = comm.whoAmI();
 
   // mesh creation and read
   if(prank == 0) {
     mesh.read("mesh.msh");
   }
   mesh.distribute();
 
   /// model creation
   SolidMechanicsModel  model(mesh);
 
   /// model initialization changed to use our material
-  model.initFull(_no_init_materials = true);
-
-  model.registerNewCustomMaterials< CustomNonLocalTestMaterial<spatial_dimension> >("custom_non_local_test_material");
-  model.initMaterials();
+  model.initFull();
 
   CustomNonLocalTestMaterial<spatial_dimension> & mat = dynamic_cast<CustomNonLocalTestMaterial<spatial_dimension> &>(model.getMaterial("test"));
 
   if(prank == 0) std::cout << mat << std::endl;
 
   // Setting up the dumpers + first dump
   model.setBaseName("non_local_material");
   model.addDumpFieldVector("displacement");
   model.addDumpFieldVector("external_force");
   model.addDumpFieldVector("internal_force");
   model.addDumpField("partitions"   );
   model.addDumpField("stress"      );
   model.addDumpField("stress"      );
   model.addDumpField("local_damage");
   model.addDumpField("damage"      );
 
 
   model.assembleInternalForces();
   model.dump();
 
 
   //Array<Real> & damage = mat.getArray("local_damage", _quadrangle_4);
   Array<Real> & damage = mat.getArray<Real>("local_damage", _triangle_3);
 
-  RandGenerator<UInt> gen;
+  RandomGenerator<UInt> gen;
 
   for (UInt i = 0; i < 1; ++i) {
-    UInt g = (gen() / Real(RandGenerator<UInt>::max() - RandGenerator<UInt>::min()))  * damage.getSize();
+    UInt g = (gen() / Real(RandomGenerator<UInt>::max() - RandomGenerator<UInt>::min()))  * damage.getSize();
     std::cout << prank << " -> " << g << std::endl;
     damage(g) = 1.;
   }
 
   model.assembleInternalForces();
   model.dump();
 
   akantu::finalize();
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc
index e6e632dc8..8353c4b9b 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc
@@ -1,100 +1,99 @@
 /**
  * @file   test_material_orthotropic.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Aug 04 2010
  * @date last modification: Tue Sep 01 2015
  *
  * @brief  test of the class SolidMechanicsModel
  *
  * @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 <iostream>
-
 /* -------------------------------------------------------------------------- */
 #include "solid_mechanics_model.hh"
+/* -------------------------------------------------------------------------- */
+#include <fstream>
+/* -------------------------------------------------------------------------- */
 
 using namespace akantu;
 
 int main(int argc, char *argv[]) {
   //  akantu::initialize("orthotropic.dat", argc, argv);
   akantu::initialize("orthotropic.dat", argc, argv);
   UInt max_steps = 1000;
   Real epot, ekin;
 
   Mesh mesh(2);
   mesh.read("square.msh");
   mesh.createBoundaryGroupFromGeometry();
 
   SolidMechanicsModel model(mesh);
 
   /// model initialization
   model.initFull();
 
   Real time_step = model.getStableTimeStep();
   model.setTimeStep(time_step/10.);
 
   model.assembleMassLumped();
 
   std::cout << model << std::endl;
 
   // Boundary condition (Neumann)
   Matrix<Real> stress(2,2);
   stress.eye(Real(1e3));
   model.applyBC(BC::Neumann::FromHigherDim(stress), "boundary_0");
 
   model.setBaseName       ("square-orthotrope"      );
   model.addDumpFieldVector("displacement");
   model.addDumpField      ("mass"        );
   model.addDumpField      ("velocity"    );
   model.addDumpField      ("acceleration");
   model.addDumpFieldVector("external_force");
   model.addDumpFieldVector("internal_force");
   model.addDumpField      ("stress"      );
   model.addDumpField      ("grad_u"      );
   model.dump();
 
   std::ofstream energy;
   energy.open("energy.csv");
   energy << "id,epot,ekin,tot" << std::endl;
 
   for(UInt s = 0; s < max_steps; ++s) {
     model.solveStep();
 
     epot = model.getEnergy("potential");
     ekin = model.getEnergy("kinetic");
 
     std::cerr << "passing step " << s << "/" << max_steps << std::endl;
     energy << s << "," << epot << "," << ekin << "," << epot + ekin
 	   << std::endl;
 
     if(s % 100 == 0) model.dump();
   }
 
   energy.close();
 
   finalize();
 
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc
index a265c2bd2..348076bd1 100644
--- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc
+++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc
@@ -1,108 +1,106 @@
 /**
  * @file   test_solid_mechanics_model_cube3d.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @date creation: Wed Aug 04 2010
  * @date last modification: Thu Aug 06 2015
  *
  * @brief  test of the class SolidMechanicsModel on the 3d cube
  *
  * @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 <iostream>
-
 /* -------------------------------------------------------------------------- */
 #include "solid_mechanics_model.hh"
-
+/* -------------------------------------------------------------------------- */
+#include <fstream>
 /* -------------------------------------------------------------------------- */
 
-int main(int argc, char *argv[])
-{
+int main(int argc, char * argv[]) {
   akantu::initialize("material.dat", argc, argv);
   akantu::UInt max_steps = 10000;
   akantu::Real epot, ekin;
 
   akantu::Mesh mesh(3);
   mesh.read("cube1.msh");
 
   akantu::SolidMechanicsModel model(mesh);
   model.initFull();
 
   akantu::Real time_step = model.getStableTimeStep();
-  model.setTimeStep(time_step/10.);
+  model.setTimeStep(time_step / 10.);
 
   model.assembleMassLumped();
 
   std::cout << model << std::endl;
 
-
   /// boundary conditions
   akantu::UInt nb_nodes = mesh.getNbNodes();
   akantu::Real eps = 1e-16;
   for (akantu::UInt i = 0; i < nb_nodes; ++i) {
-    model.getDisplacement().storage()[3*i] = model.getFEEngine().getMesh().getNodes().storage()[3*i] / 100.;
+    model.getDisplacement().storage()[3 * i] =
+        model.getFEEngine().getMesh().getNodes().storage()[3 * i] / 100.;
 
-    if(model.getFEEngine().getMesh().getNodes().storage()[3*i] <= eps) {
-      model.getBlockedDOFs().storage()[3*i    ] = true;
+    if (model.getFEEngine().getMesh().getNodes().storage()[3 * i] <= eps) {
+      model.getBlockedDOFs().storage()[3 * i] = true;
     }
 
-    if(model.getFEEngine().getMesh().getNodes().storage()[3*i + 1] <= eps) {
-      model.getBlockedDOFs().storage()[3*i + 1] = true;
+    if (model.getFEEngine().getMesh().getNodes().storage()[3 * i + 1] <= eps) {
+      model.getBlockedDOFs().storage()[3 * i + 1] = true;
     }
   }
 
   model.setBaseName("cube3d");
   model.addDumpField("displacement");
-  model.addDumpField("mass"        );
-  model.addDumpField("velocity"    );
+  model.addDumpField("mass");
+  model.addDumpField("velocity");
   model.addDumpField("acceleration");
   model.addDumpField("external_force");
   model.addDumpField("internal_force");
-  model.addDumpField("stress"      );
-  model.addDumpField("grad_u"      );
+  model.addDumpField("stress");
+  model.addDumpField("grad_u");
   model.addDumpField("element_index_by_material");
   model.dump();
 
   std::ofstream energy;
   energy.open("energy.csv");
   energy << "id,epot,ekin,tot" << std::endl;
 
-  for(akantu::UInt s = 0; s < max_steps; ++s) {
+  for (akantu::UInt s = 0; s < max_steps; ++s) {
     model.solveStep();
 
     epot = model.getEnergy("potential");
     ekin = model.getEnergy("kinetic");
 
     std::cerr << "passing step " << s << "/" << max_steps << std::endl;
     energy << s << "," << epot << "," << ekin << "," << epot + ekin
-	   << std::endl;
+           << std::endl;
 
-    if(s % 10 == 0) model.dump();
+    if (s % 10 == 0)
+      model.dump();
   }
 
   energy.close();
 
   akantu::finalize();
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc
index 8a2ea7205..35d67e1ad 100644
--- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc
+++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc
@@ -1,110 +1,107 @@
 /**
  * @file   test_solid_mechanics_model_cube3d_tetra10.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Peter Spijker <peter.spijker@epfl.ch>
  *
  * @date creation: Wed Aug 04 2010
  * @date last modification: Thu Aug 06 2015
  *
  * @brief  test of the class SolidMechanicsModel on the 3d cube
  *
  * @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 <iostream>
-
 /* -------------------------------------------------------------------------- */
 #include "solid_mechanics_model.hh"
-
+/* -------------------------------------------------------------------------- */
+#include <fstream>
 /* -------------------------------------------------------------------------- */
 
-int main(int argc, char *argv[])
-{
+int main(int argc, char * argv[]) {
   akantu::initialize("material.dat", argc, argv);
   akantu::UInt max_steps = 1000;
   akantu::Real epot, ekin;
 
   akantu::Mesh mesh(3);
 
   mesh.read("cube2.msh");
 
   akantu::SolidMechanicsModel model(mesh);
 
   /// model initialization
   model.initFull();
 
   akantu::Real time_step = model.getStableTimeStep();
-  model.setTimeStep(time_step/10.);
+  model.setTimeStep(time_step / 10.);
 
   model.assembleMassLumped();
 
   std::cout << model << std::endl;
 
-
   /// boundary conditions
   akantu::Real eps = 1e-2;
   akantu::UInt nb_nodes = model.getFEEngine().getMesh().getNbNodes();
   for (akantu::UInt i = 0; i < nb_nodes; ++i) {
-    model.getDisplacement().storage()[3*i] = model.getFEEngine().getMesh().getNodes().storage()[3*i] / 100.;
+    model.getDisplacement().storage()[3 * i] =
+        model.getFEEngine().getMesh().getNodes().storage()[3 * i] / 100.;
 
-    if(model.getFEEngine().getMesh().getNodes().storage()[3*i] <= eps) {
-      model.getBlockedDOFs().storage()[3*i    ] = true;
+    if (model.getFEEngine().getMesh().getNodes().storage()[3 * i] <= eps) {
+      model.getBlockedDOFs().storage()[3 * i] = true;
     }
 
-    if(model.getFEEngine().getMesh().getNodes().storage()[3*i + 1] <= eps) {
-      model.getBlockedDOFs().storage()[3*i + 1] = true;
+    if (model.getFEEngine().getMesh().getNodes().storage()[3 * i + 1] <= eps) {
+      model.getBlockedDOFs().storage()[3 * i + 1] = true;
     }
   }
   //  model.getDisplacement().storage()[1] = 0.1;
   model.setBaseName("cube3d_t10");
   model.addDumpField("displacement");
-  model.addDumpField("mass"        );
-  model.addDumpField("velocity"    );
+  model.addDumpField("mass");
+  model.addDumpField("velocity");
   model.addDumpField("acceleration");
   model.addDumpField("external_force");
   model.addDumpField("internal_force");
-  model.addDumpField("stress"      );
-  model.addDumpField("strain"      );
+  model.addDumpField("stress");
+  model.addDumpField("strain");
   model.dump();
 
   std::ofstream energy;
   energy.open("energy.csv");
   energy << "id,epot,ekin,tot" << std::endl;
 
-  for(akantu::UInt s = 0; s < max_steps; ++s) {
+  for (akantu::UInt s = 0; s < max_steps; ++s) {
     model.solveStep();
 
     epot = model.getEnergy("potential");
     ekin = model.getEnergy("kinetic");
 
     std::cerr << "passing step " << s << "/" << max_steps << std::endl;
     energy << s << "," << epot << "," << ekin << "," << epot + ekin
-	   << std::endl;
+           << std::endl;
 
-    if(s % 10 == 0) model.dump();
+    if (s % 10 == 0)
+      model.dump();
   }
 
   energy.close();
   akantu::finalize();
   return EXIT_SUCCESS;
 }
diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc
index 0a7ef5b3b..1a4d909fc 100644
--- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc
+++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc
@@ -1,99 +1,101 @@
 /**
  * @file   test_solid_mechanics_model_square.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Aug 04 2010
  * @date last modification: Thu Aug 06 2015
  *
  * @brief  test of the class SolidMechanicsModel
  *
  * @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 <iostream>
-
 /* -------------------------------------------------------------------------- */
 #include "solid_mechanics_model.hh"
+/* -------------------------------------------------------------------------- */
+#include <fstream>
+/* -------------------------------------------------------------------------- */
+
 
 using namespace akantu;
 
-int main(int argc, char *argv[]) {
+int main(int argc, char * argv[]) {
   akantu::initialize("material.dat", argc, argv);
   UInt max_steps = 1000;
   Real epot, ekin;
 
   Mesh mesh(2);
   mesh.read("square.msh");
   mesh.createBoundaryGroupFromGeometry();
 
   SolidMechanicsModel model(mesh);
 
   /// model initialization
   model.initFull();
 
   Real time_step = model.getStableTimeStep();
-  model.setTimeStep(time_step/10.);
+  model.setTimeStep(time_step / 10.);
 
   model.assembleMassLumped();
 
   std::cout << model << std::endl;
 
   // Boundary condition (Neumann)
-  Matrix<Real> stress(2,2);
+  Matrix<Real> stress(2, 2);
   stress.eye(Real(1e3));
   model.applyBC(BC::Neumann::FromHigherDim(stress), "boundary_0");
 
-  model.setBaseName       ("square"      );
+  model.setBaseName("square");
   model.addDumpFieldVector("displacement");
-  model.addDumpField      ("mass"        );
-  model.addDumpField      ("velocity"    );
-  model.addDumpField      ("acceleration");
+  model.addDumpField("mass");
+  model.addDumpField("velocity");
+  model.addDumpField("acceleration");
   model.addDumpFieldVector("external_force");
   model.addDumpFieldVector("internal_force");
-  model.addDumpField      ("stress"      );
-  model.addDumpField      ("strain"      );
+  model.addDumpField("stress");
+  model.addDumpField("strain");
   model.dump();
 
   std::ofstream energy;
   energy.open("energy.csv");
   energy << "id,epot,ekin,tot" << std::endl;
 
-  for(UInt s = 0; s < max_steps; ++s) {
+  for (UInt s = 0; s < max_steps; ++s) {
     model.solveStep();
 
     epot = model.getEnergy("potential");
     ekin = model.getEnergy("kinetic");
 
     std::cerr << "passing step " << s << "/" << max_steps << std::endl;
     energy << s << "," << epot << "," << ekin << "," << epot + ekin
-	   << std::endl;
+           << std::endl;
 
-    if(s % 100 == 0) model.dump();
+    if (s % 100 == 0)
+      model.dump();
   }
 
   energy.close();
 
   finalize();
 
   return EXIT_SUCCESS;
 }
diff --git a/test/test_synchronizer/test_data_accessor.hh b/test/test_synchronizer/test_data_accessor.hh
index c1859bd31..3791f52a6 100644
--- a/test/test_synchronizer/test_data_accessor.hh
+++ b/test/test_synchronizer/test_data_accessor.hh
@@ -1,135 +1,132 @@
 /**
  * @file   test_data_accessor.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Thu Apr 11 2013
  * @date last modification: Sun Oct 19 2014
  *
  * @brief  Data Accessor class for testing
  *
  * @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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #include "aka_common.hh"
 #include "data_accessor.hh"
 #include "mesh.hh"
 
+using namespace akantu;
 /* -------------------------------------------------------------------------- */
 
-__BEGIN_AKANTU__
-
 class TestAccessor : public DataAccessor<Element> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   inline TestAccessor(const Mesh & mesh,
                       const ElementTypeMapArray<Real> & barycenters);
 
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Barycenter, barycenters, Real);
 
   /* ------------------------------------------------------------------------ */
   /* Ghost Synchronizer inherited members                                     */
   /* ------------------------------------------------------------------------ */
 protected:
   inline UInt getNbData(const Array<Element> & elements,
                         const SynchronizationTag & tag) const;
   inline void packData(CommunicationBuffer & buffer,
                        const Array<Element> & elements,
                        const SynchronizationTag & tag) const;
   inline void unpackData(CommunicationBuffer & buffer,
                          const Array<Element> & elements,
                          const SynchronizationTag & tag);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   const ElementTypeMapArray<Real> & barycenters;
   const Mesh & mesh;
 };
 
 /* -------------------------------------------------------------------------- */
 /* TestSynchronizer implementation                                            */
 /* -------------------------------------------------------------------------- */
 inline TestAccessor::TestAccessor(const Mesh & mesh,
                                   const ElementTypeMapArray<Real> & barycenters)
     : barycenters(barycenters), mesh(mesh) {}
 
 inline UInt TestAccessor::getNbData(const Array<Element> & elements,
                                     const SynchronizationTag &) const {
   if (elements.getSize())
     // return Mesh::getSpatialDimension(elements(0).type) * sizeof(Real) *
     // elements.getSize();
     return mesh.getSpatialDimension() * sizeof(Real) * elements.getSize();
   else
     return 0;
 }
 
 inline void TestAccessor::packData(CommunicationBuffer & buffer,
                                    const Array<Element> & elements,
                                    const SynchronizationTag &) const {
   UInt spatial_dimension = mesh.getSpatialDimension();
   Array<Element>::const_iterator<Element> bit = elements.begin();
   Array<Element>::const_iterator<Element> bend = elements.end();
   for (; bit != bend; ++bit) {
     const Element & element = *bit;
 
     Vector<Real> bary(
         this->barycenters(element.type, element.ghost_type).storage() +
             element.element * spatial_dimension,
         spatial_dimension);
     buffer << bary;
   }
 }
 
 inline void TestAccessor::unpackData(CommunicationBuffer & buffer,
                                      const Array<Element> & elements,
                                      const SynchronizationTag & tag) {
   UInt spatial_dimension = mesh.getSpatialDimension();
   Array<Element>::const_iterator<Element> bit = elements.begin();
   Array<Element>::const_iterator<Element> bend = elements.end();
   for (; bit != bend; ++bit) {
     const Element & element = *bit;
 
     Vector<Real> barycenter_loc(
         this->barycenters(element.type, element.ghost_type).storage() +
             element.element * spatial_dimension,
         spatial_dimension);
 
     Vector<Real> bary(spatial_dimension);
     buffer >> bary;
     std::cout << element << barycenter_loc << std::endl;
     Real tolerance = 1e-15;
     for (UInt i = 0; i < spatial_dimension; ++i) {
       if (!(std::abs(bary(i) - barycenter_loc(i)) <= tolerance))
         AKANTU_DEBUG_ERROR("Unpacking an unknown value for the element: "
                            << element << "(barycenter[" << i
                            << "] = " << barycenter_loc(i) << " and buffer[" << i
                            << "] = " << bary(i) << ") - tag: " << tag);
     }
   }
 }
-
-__END_AKANTU__
diff --git a/test/test_synchronizer/test_synchronizer_communication.cc b/test/test_synchronizer/test_synchronizer_communication.cc
index 78fc98cbe..390b4616e 100644
--- a/test/test_synchronizer/test_synchronizer_communication.cc
+++ b/test/test_synchronizer/test_synchronizer_communication.cc
@@ -1,161 +1,160 @@
 /**
  * @file   test_synchronizer_communication.cc
  *
  * @author Dana Christen <dana.christen@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Sep 01 2010
  * @date last modification: Sun Oct 19 2014
  *
  * @brief  test to synchronize barycenters
  *
  * @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_common.hh"
 #include "aka_random_generator.hh"
 #include "element_synchronizer.hh"
 #include "mesh.hh"
 #include "mesh_partition_scotch.hh"
 #include "synchronizer_registry.hh"
 /* -------------------------------------------------------------------------- */
 
 //#define DUMP
 
 #if defined(AKANTU_USE_IOHELPER) && defined(DUMP)
 #include "dumper_paraview.hh"
 #endif // AKANTU_USE_IOHELPER
 
 #include "test_data_accessor.hh"
 
 using namespace akantu;
 
 /* -------------------------------------------------------------------------- */
 /* Main                                                                       */
 /* -------------------------------------------------------------------------- */
 int main(int argc, char * argv[]) {
   initialize(argc, argv);
 
   UInt spatial_dimension = 3;
 
   Mesh mesh(spatial_dimension);
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   Int prank = comm.whoAmI();
   bool wait = true;
   if (argc > 1) {
     if (prank == 0)
       while (wait)
         ;
   }
 
   if (prank == 0)
     mesh.read("cube.msh");
 
   mesh.distribute();
 
   /// compute barycenter for each facet
   ElementTypeMapArray<Real> barycenters("barycenters", "", 0);
-  mesh.initElementTypeMapArray(barycenters, spatial_dimension,
-                               spatial_dimension);
+  barycenters.initialize(mesh, _nb_component = spatial_dimension);
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
     GhostType ghost_type = *gt;
     Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
     Mesh::type_iterator last_type =
         mesh.lastType(spatial_dimension, ghost_type);
 
     for (; it != last_type; ++it) {
       UInt nb_element = mesh.getNbElement(*it, ghost_type);
       Array<Real> & barycenter = barycenters(*it, ghost_type);
       barycenter.resize(nb_element);
 
       Array<Real>::iterator<Vector<Real>> bary_it =
           barycenter.begin(spatial_dimension);
 
       for (UInt elem = 0; elem < nb_element; ++elem, ++bary_it)
         mesh.getBarycenter(elem, *it, bary_it->storage(), ghost_type);
     }
   }
 
   AKANTU_DEBUG_INFO("Creating TestAccessor");
   TestAccessor test_accessor(mesh, barycenters);
   SynchronizerRegistry synch_registry;
   synch_registry.registerDataAccessor(test_accessor);
   synch_registry.registerSynchronizer(mesh.getElementSynchronizer(), _gst_test);
 
   AKANTU_DEBUG_INFO("Synchronizing tag");
   synch_registry.synchronize(_gst_test);
 
   // Checking the tags in MeshData (not a very good test because they're all
   // identical,
   // but still...)
   Mesh::type_iterator it = mesh.firstType(_all_dimensions);
   Mesh::type_iterator last_type = mesh.lastType(_all_dimensions);
 
   for (; it != last_type; ++it) {
     Array<UInt> & tags = mesh.getData<UInt>("tag_0", *it);
     Array<UInt>::const_vector_iterator tags_it = tags.begin(1);
     Array<UInt>::const_vector_iterator tags_end = tags.end(1);
     AKANTU_DEBUG_ASSERT(
         mesh.getNbElement(*it) == tags.getSize(),
         "The number of tags does not match the number of elements on rank "
             << prank << ".");
     std::cout << std::dec << " I am rank " << prank
               << " and here's my MeshData dump for types " << *it
               << " (it should contain " << mesh.getNbElement(*it)
               << " elements and it has " << tags.getSize()
               << "!) :" << std::endl;
     std::cout << std::hex;
 
     debug::setDebugLevel(dblTest);
     for (; tags_it != tags_end; ++tags_it) {
       std::cout << tags_it->operator()(0) << " ";
     }
 
     debug::setDebugLevel(dblInfo);
     std::cout << std::endl;
   }
 
 #if defined(AKANTU_USE_IOHELPER) && defined(DUMP)
   DumperParaview dumper("test-scotch-partition");
   dumper.registerMesh(mesh, spatial_dimension, _not_ghost);
   dumper.registerField("partitions",
    		       new DumperIOHelper::ElementPartitionField<>(mesh,
                                                                    spatial_dimension, _not_ghost));
   dumper.dump();
 
   DumperParaview dumper_ghost("test-scotch-partition-ghost");
   dumper_ghost.registerMesh(mesh, spatial_dimension, _ghost);
   dumper_ghost.registerField("partitions",
    			     new DumperIOHelper::ElementPartitionField<>(mesh,
                                                                          spatial_dimension, _ghost));
   dumper_ghost.dump();
 #endif //AKANTU_USE_IOHELPER
 
   finalize();
 
   return EXIT_SUCCESS;
 }