diff --git a/packages/core.cmake b/packages/core.cmake
index 786549ef9..d57a5ef5a 100644
--- a/packages/core.cmake
+++ b/packages/core.cmake
@@ -1,596 +1,593 @@
 #===============================================================================
 # @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
   common/aka_iterators.hh
   common/aka_static_if.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/element_type_conversion.hh
 
   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_field.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.cc
   fe_engine/shape_functions_inline_impl.cc
   fe_engine/shape_lagrange_base.cc
   fe_engine/shape_lagrange_base.hh
   fe_engine/shape_lagrange_base_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/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/mesh_iterators.hh
 
   mesh_utils/mesh_partition.cc
   mesh_utils/mesh_partition.hh
   mesh_utils/mesh_partition/mesh_partition_mesh_data.cc
   mesh_utils/mesh_partition/mesh_partition_mesh_data.hh
   mesh_utils/mesh_partition/mesh_partition_scotch.hh
   mesh_utils/mesh_utils_pbc.cc
   mesh_utils/mesh_utils.cc
   mesh_utils/mesh_utils.hh
   mesh_utils/mesh_utils_distribution.cc
   mesh_utils/mesh_utils_distribution.hh
   mesh_utils/mesh_utils.hh
   mesh_utils/mesh_utils_inline_impl.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_manager_callback.hh
   model/common/non_local_toolbox/non_local_neighborhood_base.hh
   model/common/non_local_toolbox/non_local_neighborhood_base.cc
   model/common/non_local_toolbox/non_local_neighborhood.hh
   model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh
   model/common/non_local_toolbox/non_local_neighborhood_inline_impl.cc
   model/common/non_local_toolbox/base_weight_function.hh
   model/common/non_local_toolbox/base_weight_function_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
   lagrange_base
   )
 
 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/structural_mechanics.cmake b/packages/structural_mechanics.cmake
index bcf32ff94..3090ea633 100644
--- a/packages/structural_mechanics.cmake
+++ b/packages/structural_mechanics.cmake
@@ -1,76 +1,81 @@
 #===============================================================================
 # @file   structural_mechanics.cmake
 #
 # @author Nicolas Richart <nicolas.richart@epfl.ch>
 #
 # @date creation: Mon Nov 21 2011
 # @date last modification: Sun Jul 19 2015
 #
 # @brief  package description for structural 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/>.
 #
 #===============================================================================
 
 package_declare(structural_mechanics
   DESCRIPTION "Use Structural mechanics model package of Akantu"
   DEPENDS implicit)
 
 package_declare_sources(structural_mechanics
   fe_engine/element_class_structural.hh
   fe_engine/element_classes/element_class_bernoulli_beam_inline_impl.cc
-  fe_engine/fe_engine_template_tmpl_struct.hh
   fe_engine/element_classes/element_class_kirchhoff_shell_inline_impl.cc
+  fe_engine/fe_engine_template_tmpl_struct.hh
+  fe_engine/shape_structural.cc
+  fe_engine/shape_structural.hh
+  fe_engine/shape_structural_inline_impl.cc
   io/mesh_io/mesh_io_msh_struct.cc
   io/mesh_io/mesh_io_msh_struct.hh
-  io/model_io/model_io_ibarras.cc
-  io/model_io/model_io_ibarras.hh
+  model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_2.hh
+  model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_3.hh
+  model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_kirchhoff_shell.hh
   model/structural_mechanics/structural_mechanics_model.cc
   model/structural_mechanics/structural_mechanics_model.hh
   model/structural_mechanics/structural_mechanics_model_boundary.cc
   model/structural_mechanics/structural_mechanics_model_inline_impl.cc
   model/structural_mechanics/structural_mechanics_model_mass.cc
   )
 
 package_declare_elements(structural_mechanics
   ELEMENT_TYPES
   _bernoulli_beam_2
   _bernoulli_beam_3
   _kirchhoff_shell
   KIND structural
   INTERPOLATION_TYPES
-  _itp_bernoulli_beam
+  _itp_bernoulli_beam_2
+  _itp_bernoulli_beam_3
   _itp_kirchhoff_shell
   INTERPOLATION_KIND
   _itk_structural
   )
 
 package_declare_documentation_files(structural_mechanics
   manual-structuralmechanicsmodel.tex
   manual-structuralmechanicsmodel-elements.tex
 
   figures/beam_example.pdf
   figures/elements/bernoulli_2.pdf
   figures/elements/bernoulli_2.svg
   )
 
 package_declare_documentation(structural_mechanics
   "This package activates the compilation for the Structural Mechanics engine of Akantu"
   )
diff --git a/src/fe_engine/element_class_structural.hh b/src/fe_engine/element_class_structural.hh
index 4ef4c017c..a3d13ab6e 100644
--- a/src/fe_engine/element_class_structural.hh
+++ b/src/fe_engine/element_class_structural.hh
@@ -1,260 +1,197 @@
 /**
  * @file   element_class_structural.hh
  *
  * @author Fabian Barras <fabian.barras@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Damien Spielmann <damien.spielmann@epfl.ch>
  *
  * @date creation: Thu Feb 21 2013
  * @date last modification: Thu Oct 22 2015
  *
  * @brief  Specialization of the element classes for structural elements
  *
  * @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 "element_class.hh"
+/* -------------------------------------------------------------------------- */
+
+#ifndef __AKANTU_ELEMENT_CLASS_STRUCTURAL_HH__
+#define __AKANTU_ELEMENT_CLASS_STRUCTURAL_HH__
 
 namespace akantu {
 
+/// Macro to generate the InterpolationProperty structures for different
+/// interpolation types
+#define AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY(                  \
+    itp_type, parent_type, ndim, ndof)                                         \
+  template <> struct InterpolationProperty<itp_type> {                         \
+    static const InterpolationKind kind{_itk_structural};                      \
+    static const UInt nb_nodes_per_element{                                    \
+        InterpolationProperty<parent_type>::nb_nodes_per_element};             \
+    static const InterpolationType parent_element_type{parent_type};           \
+    static const UInt natural_space_dimension{ndim};                           \
+    static const UInt nb_degree_of_freedom{ndof};                              \
+  }
+
 /* -------------------------------------------------------------------------- */
 template <InterpolationType interpolation_type>
 class InterpolationElement<interpolation_type, _itk_structural> {
 public:
-  typedef InterpolationPorperty<interpolation_type> interpolation_property;
+  using interpolation_property = InterpolationProperty<interpolation_type>;
 
   /// compute the shape values for a given set of points in natural coordinates
   static inline void computeShapes(const Matrix<Real> & natural_coord,
-                                   Matrix<Real> & N,
-                                   const Matrix<Real> & real_nodal_coord,
-                                   UInt n = 0) {
+                                   Tensor3<Real> & N,
+                                   const Matrix<Real> & real_nodal_coord) {
     UInt nb_points = natural_coord.cols();
     for (UInt p = 0; p < nb_points; ++p) {
-      Vector<Real> Np = N(p);
-      computeShapes(natural_coord(p), Np, real_nodal_coord, n);
+      Matrix<Real> Np = N(p);
+      computeShapes(natural_coord(p), Np, real_nodal_coord);
     }
   }
 
   /// compute the shape values for a given point in natural coordinates
   static inline void computeShapes(const Vector<Real> & natural_coord,
-                                   Vector<Real> & N,
-                                   const Matrix<Real> & real_nodal_coord,
-                                   UInt n = 0);
+                                   Matrix<Real> & N,
+                                   const Matrix<Real> & real_nodal_coord);
   /**
    * compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of
    * shape functions along with variation of natural coordinates on a given set
    * of points in natural coordinates
    */
   static inline void computeDNDS(const Matrix<Real> & natural_coord,
                                  Tensor3<Real> & dnds,
-                                 const Matrix<Real> & real_nodal_coord,
-                                 UInt n = 0) {
+                                 const Matrix<Real> & real_nodal_coord) {
     for (UInt i = 0; i < natural_coord.cols(); ++i) {
       Matrix<Real> dnds_t = dnds(i);
-      computeDNDS(natural_coord(i), dnds_t, real_nodal_coord, n);
+      computeDNDS(natural_coord(i), dnds_t, real_nodal_coord);
     }
   }
 
   /**
    * compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of
    * shape functions along with
    * variation of natural coordinates on a given point in natural
    * coordinates
    */
   static inline void computeDNDS(const Vector<Real> & natural_coord,
                                  Matrix<Real> & dnds,
-                                 const Matrix<Real> & real_nodal_coord,
-                                 UInt n = 0);
+                                 const Matrix<Real> & real_nodal_coord);
 
 public:
-  static AKANTU_GET_MACRO_NOT_CONST(NbShapeFunctions, nb_shape_functions, UInt);
-  static AKANTU_GET_MACRO_NOT_CONST(NbShapeDerivatives, nb_shape_derivatives,
-                                    UInt);
   static AKANTU_GET_MACRO_NOT_CONST(
-      ShapeSize, interpolation_property::nb_nodes_per_element, UInt);
+      NbNodesPerInterpolationElement,
+      interpolation_property::nb_nodes_per_element, UInt);
+
   static AKANTU_GET_MACRO_NOT_CONST(
-      ShapeDerivativesSize, (interpolation_property::nb_nodes_per_element *
-                             interpolation_property::natural_space_dimension),
+      ShapeSize,
+      (interpolation_property::nb_nodes_per_element *
+       interpolation_property::nb_degree_of_freedom *
+       interpolation_property::nb_degree_of_freedom),
+      UInt);
+  static AKANTU_GET_MACRO_NOT_CONST(
+      ShapeDerivativesSize,
+      (interpolation_property::nb_nodes_per_element *
+       interpolation_property::nb_degree_of_freedom *
+       interpolation_property::natural_space_dimension),
       UInt);
   static AKANTU_GET_MACRO_NOT_CONST(
       NaturalSpaceDimension, interpolation_property::natural_space_dimension,
       UInt);
+    static AKANTU_GET_MACRO_NOT_CONST(
+      NbDegreeOfFreedom,
+      interpolation_property::nb_degree_of_freedom, UInt);
 
-protected:
-  /// nb shape functions
-  static const UInt nb_shape_functions;
-  static const UInt nb_shape_derivatives;
 };
 
 /// Macro to generate the element class structures for different structural
 /// element types
 /* -------------------------------------------------------------------------- */
 #define AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY(                       \
     elem_type, geom_type, interp_type, parent_el_type, elem_kind, sp,          \
     gauss_int_type, min_int_order)                                             \
   template <> struct ElementClassProperty<elem_type> {                         \
-    static const GeometricalType geometrical_type = geom_type;                 \
-    static const InterpolationType interpolation_type = interp_type;           \
-    static const ElementType parent_element_type = parent_el_type;             \
-    static const ElementKind element_kind = elem_kind;                         \
-    static const UInt spatial_dimension = sp;                                  \
-    static const GaussIntegrationType gauss_integration_type = gauss_int_type; \
-    static const UInt polynomial_degree = min_int_order;                       \
+    static const GeometricalType geometrical_type{geom_type};                  \
+    static const InterpolationType interpolation_type{interp_type};            \
+    static const ElementType parent_element_type{parent_el_type};              \
+    static const ElementKind element_kind{elem_kind};                          \
+    static const UInt spatial_dimension{sp};                                   \
+    static const GaussIntegrationType gauss_integration_type{gauss_int_type};  \
+    static const UInt polynomial_degree{min_int_order};                        \
   }
 
 /* -------------------------------------------------------------------------- */
 /* ElementClass for structural elements                                       */
 /* -------------------------------------------------------------------------- */
 template <ElementType element_type>
 class ElementClass<element_type, _ek_structural>
     : public GeometricalElement<
           ElementClassProperty<element_type>::geometrical_type>,
       public InterpolationElement<
           ElementClassProperty<element_type>::interpolation_type> {
 protected:
-  typedef GeometricalElement<
-      ElementClassProperty<element_type>::geometrical_type>
-      geometrical_element;
-  typedef InterpolationElement<
-      ElementClassProperty<element_type>::interpolation_type>
-      interpolation_element;
-  typedef ElementClass<ElementClassProperty<element_type>::parent_element_type>
-      parent_element;
+  using geometrical_element =
+      GeometricalElement<ElementClassProperty<element_type>::geometrical_type>;
+  using interpolation_element = InterpolationElement<
+      ElementClassProperty<element_type>::interpolation_type>;
+  using parent_element =
+      ElementClass<ElementClassProperty<element_type>::parent_element_type>;
 
 public:
   /// compute shape derivatives (input is dxds) for a set of points
   static inline void
   computeShapeDerivatives(const Matrix<Real> & natural_coord,
                           Tensor3<Real> & shape_deriv,
-                          const Matrix<Real> & real_nodal_coord, UInt n = 0) {
+                          const Matrix<Real> & real_nodal_coord) {
     UInt nb_points = natural_coord.cols();
-
-    if (element_type == _kirchhoff_shell) {
-      /// TO BE CONTINUED and moved in a _tmpl.hh
-
-      UInt spatial_dimension = real_nodal_coord.cols();
-      UInt nb_nodes = real_nodal_coord.rows();
-
-      const UInt projected_dim = natural_coord.rows();
-      Matrix<Real> rotation_matrix(real_nodal_coord);
-      Matrix<Real> rotated_nodal_coord(real_nodal_coord);
-      Matrix<Real> projected_nodal_coord(natural_coord);
-      /* --------------------------------------------------------------------------
-       */
-      /* --------------------------------------------------------------------------
-       */
-
-      Matrix<Real> Pe(real_nodal_coord);
-      Matrix<Real> Pg(real_nodal_coord);
-      Matrix<Real> inv_Pg(real_nodal_coord);
-
-      /// compute matrix Pe
-      Pe.eye();
-
-      /// compute matrix Pg
-      Vector<Real> Pg_col_1(spatial_dimension);
-      Pg_col_1(0) = real_nodal_coord(0, 1) - real_nodal_coord(0, 0);
-      Pg_col_1(1) = real_nodal_coord(1, 1) - real_nodal_coord(1, 0);
-      Pg_col_1(2) = real_nodal_coord(2, 1) - real_nodal_coord(2, 0);
-
-      Vector<Real> Pg_col_2(spatial_dimension);
-      Pg_col_2(0) = real_nodal_coord(0, 2) - real_nodal_coord(0, 0);
-      Pg_col_2(1) = real_nodal_coord(1, 2) - real_nodal_coord(1, 0);
-      Pg_col_2(2) = real_nodal_coord(2, 2) - real_nodal_coord(2, 0);
-
-      Vector<Real> Pg_col_3(spatial_dimension);
-      Pg_col_3.crossProduct(Pg_col_1, Pg_col_2);
-
-      for (UInt i = 0; i < nb_points; ++i) {
-        Pg(i, 0) = Pg_col_1(i);
-        Pg(i, 1) = Pg_col_2(i);
-        Pg(i, 2) = Pg_col_3(i);
-      }
-
-      /// compute inverse of Pg
-      inv_Pg.inverse(Pg);
-
-      /// compute rotation matrix
-      // rotation_matrix=Pe*inv_Pg;
-      rotation_matrix.eye();
-      /* --------------------------------------------------------------------------
-       */
-      /* --------------------------------------------------------------------------
-       */
-
-      rotated_nodal_coord.mul<false, false>(rotation_matrix, real_nodal_coord);
-
-      for (UInt i = 0; i < projected_dim; ++i) {
-        for (UInt j = 0; j < nb_points; ++j) {
-          projected_nodal_coord(i, j) = rotated_nodal_coord(i, j);
-        }
-      }
-
-      Tensor3<Real> dnds(projected_dim, nb_nodes, natural_coord.cols());
-      Tensor3<Real> J(projected_dim, projected_dim, natural_coord.cols());
-
-      parent_element::computeDNDS(natural_coord, dnds);
-
-      parent_element::computeJMat(dnds, projected_nodal_coord, J);
-
-      for (UInt p = 0; p < nb_points; ++p) {
-
-        Matrix<Real> shape_deriv_p = shape_deriv(p);
-
-        interpolation_element::computeDNDS(natural_coord(p), shape_deriv_p,
-                                           projected_nodal_coord, n);
-
-        Matrix<Real> dNdS = shape_deriv_p;
-        Matrix<Real> inv_J(projected_dim, projected_dim);
-        inv_J.inverse(J(p));
-        shape_deriv_p.mul<false, false>(inv_J, dNdS);
-      }
-    } else {
-
-      for (UInt p = 0; p < nb_points; ++p) {
-        Matrix<Real> shape_deriv_p = shape_deriv(p);
-        interpolation_element::computeDNDS(natural_coord(p), shape_deriv_p,
-                                           real_nodal_coord, n);
-      }
+    for (UInt p = 0; p < nb_points; ++p) {
+      Matrix<Real> shape_deriv_p = shape_deriv(p);
+      interpolation_element::computeDNDS(natural_coord(p), shape_deriv_p,
+                                         real_nodal_coord);
     }
   }
 
   /// compute jacobian (or integration variable change factor) for a given point
   static inline void computeJacobian(const Matrix<Real> & natural_coords,
                                      const Matrix<Real> & nodal_coords,
                                      Vector<Real> & jacobians) {
     parent_element::computeJacobian(natural_coords, nodal_coords, jacobians);
   }
 
 public:
   static AKANTU_GET_MACRO_NOT_CONST(Kind, _ek_structural, ElementKind);
   static AKANTU_GET_MACRO_NOT_CONST(P1ElementType, _not_defined, ElementType);
   static AKANTU_GET_MACRO_NOT_CONST(FacetType, _not_defined, ElementType);
   static ElementType getFacetType(__attribute__((unused)) UInt t = 0) {
     return _not_defined;
   }
   static AKANTU_GET_MACRO_NOT_CONST(
       SpatialDimension, ElementClassProperty<element_type>::spatial_dimension,
       UInt);
   static ElementType * getFacetTypeInternal() { return NULL; }
 };
 
+} // namespace akantu
+
 #include "element_classes/element_class_bernoulli_beam_inline_impl.cc"
 #include "element_classes/element_class_kirchhoff_shell_inline_impl.cc"
 
-} // akantu
+#endif /* __AKANTU_ELEMENT_CLASS_STRUCTURAL_HH__ */
diff --git a/src/fe_engine/element_classes/element_class_bernoulli_beam_inline_impl.cc b/src/fe_engine/element_classes/element_class_bernoulli_beam_inline_impl.cc
index 1b38affd4..f3ba7f621 100644
--- a/src/fe_engine/element_classes/element_class_bernoulli_beam_inline_impl.cc
+++ b/src/fe_engine/element_classes/element_class_bernoulli_beam_inline_impl.cc
@@ -1,195 +1,270 @@
 /**
  * @file   element_class_bernoulli_beam_inline_impl.cc
  *
  * @author Fabian Barras <fabian.barras@epfl.ch>
  *
  * @date creation: Fri Jul 15 2011
  * @date last modification: Sun Oct 19 2014
  *
- * @brief  Specialization of the element_class class for the type _bernoulli_beam_2
+ * @brief  Specialization of the element_class class for the type
+ _bernoulli_beam_2
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2012, 2014,  2015 EPFL  (Ecole Polytechnique  Fédérale de
  * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
  * Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  * @section DESCRIPTION
  *
  * @verbatim
    --x-----q1----|----q2-----x---> x
     -a          0            a
  @endverbatim
  *
  * @subsection coords Nodes coordinates
  *
  * @f[
  * \begin{array}{ll}
  *  x_{1}  = -a   &  x_{2} = a
  * \end{array}
  * @f]
  *
  * @subsection shapes Shape functions
  * @f[
  *   \begin{array}{ll}
  *     N_1(x) &= \frac{1-x}{2a}\\
  *     N_2(x) &= \frac{1+x}{2a}
  *   \end{array}
  *
  *   \begin{array}{ll}
  *     M_1(x) &= 1/4(x^{3}/a^{3}-3x/a+2)\\
  *     M_2(x) &= -1/4(x^{3}/a^{3}-3x/a-2)
  *   \end{array}
  *
  *   \begin{array}{ll}
  *     L_1(x) &= a/4(x^{3}/a^{3}-x^{2}/a^{2}-x/a+1)\\
  *     L_2(x) &= a/4(x^{3}/a^{3}+x^{2}/a^{2}-x/a-1)
  *   \end{array}
  *
  *   \begin{array}{ll}
  *     M'_1(x) &= 3/4a(x^{2}/a^{2}-1)\\
  *     M'_2(x) &= -3/4a(x^{2}/a^{2}-1)
  *   \end{array}
  *
  *   \begin{array}{ll}
  *     L'_1(x) &= 1/4(3x^{2}/a^{2}-2x/a-1)\\
  *     L'_2(x) &= 1/4(3x^{2}/a^{2}+2x/a-1)
  *   \end{array}
  *@f]
  *
  * @subsection dnds Shape derivatives
  *
  *@f[
  * \begin{array}{ll}
  *   N'_1(x) &= -1/2a\\
  *   N'_2(x) &= 1/2a
  * \end{array}]
  *
  * \begin{array}{ll}
  *   -M''_1(x) &= -3x/(2a^{3})\\
  *   -M''_2(x) &= 3x/(2a^{3})\\
  * \end{array}
  *
  * \begin{array}{ll}
  *   -L''_1(x) &= -1/2a(3x/a-1)\\
  *   -L''_2(x) &= -1/2a(3x/a+1)
  * \end{array}
  *@f]
  *
  * @subsection quad_points Position of quadrature points
  *
  * @f[
  * \begin{array}{ll}
  * x_{q1}  = -a/\sqrt{3} & x_{q2} = a/\sqrt{3}
  * \end{array}
  * @f]
  */
+/* -------------------------------------------------------------------------- */
+#include "aka_static_if.hh"
+#include "element_class_structural.hh"
+/* -------------------------------------------------------------------------- */
 
+#ifndef __AKANTU_ELEMENT_CLASS_BERNOULLI_BEAM_INLINE_IMPL_CC__
+#define __AKANTU_ELEMENT_CLASS_BERNOULLI_BEAM_INLINE_IMPL_CC__
+
+namespace akantu {
 /* -------------------------------------------------------------------------- */
+AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY(_itp_bernoulli_beam_2,
+                                                     _itp_lagrange_segment_2, 2,
+                                                     3);
+AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY(_itp_bernoulli_beam_3,
+                                                     _itp_lagrange_segment_2, 3,
+                                                     6);
+
 AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY(_bernoulli_beam_2,
-						_gt_segment_2,
-						_itp_bernoulli_beam,
-						_segment_2,
-						_ek_structural,
-						2,
-						_git_segment, 4);
+                                                _gt_segment_2,
+                                                _itp_bernoulli_beam_2,
+                                                _segment_2, _ek_structural, 2,
+                                                _git_segment, 5);
 
 AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY(_bernoulli_beam_3,
-						_gt_segment_2,
-						_itp_bernoulli_beam,
-						_segment_2,
-						_ek_structural,
-						3,
-						_git_segment, 4);
+                                                _gt_segment_2,
+                                                _itp_bernoulli_beam_3,
+                                                _segment_2, _ek_structural, 3,
+                                                _git_segment, 5);
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+namespace {
+  namespace details {
+    template <InterpolationType type>
+    void computeShapes(const Vector<Real> & natural_coords, Matrix<Real> & N,
+                       const Matrix<Real> & real_coord) {
+      /// Compute the dimension of the beam
+      Vector<Real> x1 = real_coord(0);
+      Vector<Real> x2 = real_coord(1);
+
+      Real a = x1.distance(x2) / 2.;
+      /// natural coordinate
+      Real c = natural_coords(0);
+
+      auto N0 = (1 - c) / 2.;
+      auto N1 = (1 + c) / 2.;
+
+      auto M0 = (c * c * c - 3. * c + 2.) / 4.;
+      auto M1 = -(c * c * c - 3. * c - 2.) / 4.;
+
+      auto L0 = a * (c * c * c - c * c - c + 1.) / 4.;
+      auto L1 = a * (c * c * c + c * c - c - 1.) / 4.;
+
+      auto Mp0 = 3. / a * (c * c - 1.) / 4.;
+      auto Mp1 = -3. / a * (c * c - 1.) / 4.;
+
+      auto Lp0 = (3. * c * c - 2. * c - 1.) / 4.;
+      auto Lp1 = (3. * c * c + 2. * c - 1.) / 4.;
+
+      static_if(type == _itp_bernoulli_beam_2)
+          .then([&](auto && N) {
+            // clang-format off
+            //     0    1    2   3    4    5
+            N = {{N0,  0.,  0., N1,  0.,  0.},
+                 {0.,  M0,  L0, 0.,  M1,  L1},
+                 {0., Mp0, Lp0, 0., Mp1, Lp1}};
+            // clang-format on
+          })
+          .else_if(type == _itp_bernoulli_beam_3)
+          .then([&](auto && N) {
+            // clang-format off
+            //     0    1    2    3     4    5    6    7    8   9    10   11
+            N = {{N0,   0.,  0.,  0.,   0.,  0., N1,   0.,  0., 0.,   0.,  0.},
+                 { 0., M0,   0.,  0.,   0.,  L0,  0.,  M1,  0., 0.,   0.,  L1},
+                 { 0.,  0.,  M0,  0.,  -L0,  0.,  0.,  0.,  M1, 0.,  -L1,  0.},
+                 { 0.,  0.,  0., N0,    0.,  0.,  0.,  0.,  0., N1,   0.,  0.},
+                 { 0.,  0., Mp0,  0., -Lp0,  0.,  0.,  0., Mp1, 0., -Lp1,  0.},
+                 { 0., Mp0,  0.,  0.,   0., Lp0,  0., Mp1,  0., 0.,   0., Lp1}};
+            // clang-format on
+          })
+          .else_([](auto && /*unused*/) {
+            AKANTU_EXCEPTION("Should not be in this part of the code");
+          })(std::forward<decltype(N)>(N));
+    }
+
+    /* ---------------------------------------------------------------------- */
+
+    template <InterpolationType type>
+    void computeDNDS(const Vector<Real> & natural_coords, Matrix<Real> & B,
+                     const Matrix<Real> & real_nodes_coord) {
+      /// Compute the dimension of the beam
+      Vector<Real> x1 = real_nodes_coord(0);
+      Vector<Real> x2 = real_nodes_coord(1);
+
+      Real a = .5 * x1.distance(x2);
+      /// natural coordinate
+      Real c = natural_coords(0) * a;
+
+      auto Np0 = -1. / (2. * a);
+      auto Np1 = 1. / (2. * a);
+
+      auto Mpp0 = -3. * c / (2. * pow(a, 3.));
+      auto Mpp1 = 3. * c / (2. * pow(a, 3.));
+
+      auto Lpp0 = -1. / (2. * a) * (3. * c / a - 1.);
+      auto Lpp1 = -1. / (2. * a) * (3. * c / a + 1.);
+
+      static_if(type == _itp_bernoulli_beam_2)
+          .then([&](auto && B) {
+            // clang-format off
+            //      0    1     2    3     4     5
+            B = {{Np0,   0.,   0., Np1,   0.,   0.},
+                 { 0., Mpp0, Lpp0,  0., Mpp1, Lpp1}};
+            // clang-format on
+          })
+          .else_if(type == _itp_bernoulli_beam_3)
+          .then([&](auto && B) {
+            // clang-format off
+            //      0    1     2    3      4     5     6    7     8    9     10    11
+            B = {{Np0,   0.,   0.,  0.,    0.,   0., Np1,   0.,   0.,  0.,    0.,   0.},
+                 { 0., Mpp0,   0.,  0.,    0., Lpp0,  0., Mpp1,   0.,  0.,    0., Lpp1},
+                 { 0.,   0., Mpp0,  0., -Lpp0,   0.,  0.,   0., Mpp1,  0., -Lpp1,   0.},
+                 { 0.,   0.,   0., Np0,    0.,   0.,  0.,   0.,   0., Np1,    0.,   0.}};
+            // clang-format on
+          })
+          .else_([](auto && /*unused*/) {
+            AKANTU_EXCEPTION("Should not be in this part of the code");
+          })(std::forward<decltype(B)>(B));
+    }
+  } // namespace details
+} // namespace
 
 /* -------------------------------------------------------------------------- */
 template <>
 inline void
-InterpolationElement<_itp_bernoulli_beam>::computeShapes(const Vector<Real> & natural_coords,
-							 Vector<Real> & N,
-							 const Matrix<Real> & real_coord,
-							 UInt id) {
-  /// Compute the dimension of the beam
-  Vector<Real> x1 = real_coord(0);
-  Vector<Real> x2 = real_coord(1);
-
-  Real a = .5 * x1.distance(x2);
-  /// natural coordinate
-  Real c = natural_coords(0);
-
-  switch (id) {
-  case 0: { // N
-    N(0) = 0.5*(1 - c);
-    N(1) = 0.5*(1 + c);
-    break;
-  }
-  case 1: { // M
-    N(0) =  0.25 * (c*c*c - 3*c + 2);
-    N(1) = -0.25 * (c*c*c - 3*c - 2);
-    break;
-  }
-  case 2: { // L
-    N(0) = 0.25*a * (c*c*c - c*c - c + 1);
-    N(1) = 0.25*a * (c*c*c + c*c - c - 1);
-    break;
-  }
-  case 3: { // M'
-    N(0) =  0.75/a * (c*c - 1);
-    N(1) = -0.75/a * (c*c - 1);
-    break;
-  }
-  case 4: { // L'
-    N(0) = 0.25 * (3*c*c - 2*c - 1);
-    N(1) = 0.25 * (3*c*c + 2*c - 1);
-    break;
-  }
-  }
- }
+InterpolationElement<_itp_bernoulli_beam_2, _itk_structural>::computeShapes(
+    const Vector<Real> & natural_coords, Matrix<Real> & N,
+    const Matrix<Real> & real_coord) {
+  details::computeShapes<_itp_bernoulli_beam_2>(natural_coords, N, real_coord);
+}
+
+template <>
+inline void
+InterpolationElement<_itp_bernoulli_beam_3, _itk_structural>::computeShapes(
+    const Vector<Real> & natural_coords, Matrix<Real> & N,
+    const Matrix<Real> & real_coord) {
+  details::computeShapes<_itp_bernoulli_beam_3>(natural_coords, N, real_coord);
+}
 
 /* -------------------------------------------------------------------------- */
 template <>
 inline void
-InterpolationElement<_itp_bernoulli_beam>::computeDNDS(const Vector<Real> & natural_coords,
-						       Matrix<Real> & dnds,
-						       const Matrix<Real> & real_nodes_coord,
-						       UInt id) {
-  /// Compute the dimension of the beam
-  Vector<Real> x1 = real_nodes_coord(0);
-  Vector<Real> x2 = real_nodes_coord(1);
-
-  Real a = .5 * x1.distance(x2);
-  /// natural coordinate
-  Real c = natural_coords(0)*a;
-
-
-  switch (id) {
-  case 0: { // N'
-    dnds(0, 0) = -0.5/a;
-    dnds(0, 1) =  0.5/a;
-    break;
-  }
-  case 1: { // M''
-    dnds(0, 0) = -3.*c/(2.*pow(a,3));
-    dnds(0, 1) =  3.*c/(2.*pow(a,3));
-    break;
-  }
-  case 2: { // L''
-    dnds(0, 0) = -0.5/a * (3*c/a - 1);
-    dnds(0, 1) =- 0.5/a * (3*c/a + 1);
-    break;
-  }
-  }
+InterpolationElement<_itp_bernoulli_beam_2, _itk_structural>::computeDNDS(
+    const Vector<Real> & natural_coords, Matrix<Real> & B,
+    const Matrix<Real> & real_nodes_coord) {
+  details::computeDNDS<_itp_bernoulli_beam_2>(natural_coords, B,
+                                              real_nodes_coord);
 }
+
+template <>
+inline void
+InterpolationElement<_itp_bernoulli_beam_3, _itk_structural>::computeDNDS(
+    const Vector<Real> & natural_coords, Matrix<Real> & B,
+    const Matrix<Real> & real_nodes_coord) {
+  details::computeDNDS<_itp_bernoulli_beam_3>(natural_coords, B,
+                       real_nodes_coord);
+}
+
+} // namespace akantu
+#endif /* __AKANTU_ELEMENT_CLASS_BERNOULLI_BEAM_INLINE_IMPL_CC__ */
diff --git a/src/fe_engine/element_classes/element_class_kirchhoff_shell_inline_impl.cc b/src/fe_engine/element_classes/element_class_kirchhoff_shell_inline_impl.cc
index f033f8184..299a36112 100644
--- a/src/fe_engine/element_classes/element_class_kirchhoff_shell_inline_impl.cc
+++ b/src/fe_engine/element_classes/element_class_kirchhoff_shell_inline_impl.cc
@@ -1,289 +1,368 @@
 /**
  * @file   element_class_kirchhoff_shell_inline_impl.cc
  *
  * @author Damien Spielmann <damien.spielmann@epfl.ch>
  *
  * @date creation: Fri Jul 04 2014
  * @date last modification: Sun Oct 19 2014
  *
  * @brief  Element class Kirchhoff Shell
  *
  * @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 "element_class_structural.hh"
+/* -------------------------------------------------------------------------- */
+
+#ifndef __AKANTU_ELEMENT_CLASS_KIRCHHOFF_SHELL_INLINE_IMPL_CC__
+#define __AKANTU_ELEMENT_CLASS_KIRCHHOFF_SHELL_INLINE_IMPL_CC__
+
+namespace akantu {
 
 /* -------------------------------------------------------------------------- */
+AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY(_itp_kirchhoff_shell,
+                                                     _itp_lagrange_triangle_3, 3, 6);
 AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY(_kirchhoff_shell,
                                                 _gt_triangle_3,
                                                 _itp_kirchhoff_shell,
                                                 _triangle_3, _ek_structural, 3,
                                                 _git_triangle, 2);
 
 /* -------------------------------------------------------------------------- */
 // cf. element_class_bernoulli...
 // element_class_triangle_3_inline... (pour compute Jacobian)
 template <>
 inline void InterpolationElement<_itp_kirchhoff_shell>::computeShapes(
-    const Vector<Real> & natural_coords, Vector<Real> & N,
-    const Matrix<Real> & projected_coord, UInt id) {
-  // projected_coord (x1 x2 x3) (y1 y2 y3)
-
-  // natural coordinate
-  Real xi = natural_coords(0);
-  Real eta = natural_coords(1);
-
-  Real x21 = projected_coord(0, 0) - projected_coord(0, 1); // x1-x2
-  Real x32 = projected_coord(0, 1) - projected_coord(0, 2);
-  Real x13 = projected_coord(0, 2) - projected_coord(0, 0);
-
-  Real y21 = projected_coord(1, 0) - projected_coord(1, 1); // y1-y2
-  Real y32 = projected_coord(1, 1) - projected_coord(1, 2);
-  Real y13 = projected_coord(1, 2) - projected_coord(1, 0);
-
-  /* Real x21=projected_coord(0,1)-projected_coord(0,0);
-  Real x32=projected_coord(0,2)-projected_coord(0,1);
-  Real x13=projected_coord(0,0)-projected_coord(0,2);
-
-  Real y21=projected_coord(1,1)-projected_coord(1,0);
-  Real y32=projected_coord(1,2)-projected_coord(1,1);
-  Real y13=projected_coord(1,0)-projected_coord(1,2);*/
-
-  // natural triangle side length
-  Real L4 = sqrt(x21 * x21 + y21 * y21);
-  Real L5 = sqrt(x32 * x32 + y32 * y32);
-  Real L6 = sqrt(x13 * x13 + y13 * y13);
-
-  // sinus and cosinus
-  Real C4 = x21 / L4; // 1
-  Real C5 = x32 / L5; //-1/sqrt(2);
-  Real C6 = x13 / L6; // 0
-  Real S4 = y21 / L4; // 0;
-  Real S5 = y32 / L5; // 1/sqrt(2);
-  Real S6 = y13 / L6; //-1;
-
-  Real N1 = 1 - xi - eta;
-  Real N2 = xi;
-  Real N3 = eta;
-
-  Real P4 = 4 * xi * (1 - xi - eta);
-  Real P5 = 4 * xi * eta;
-  Real P6 = 4 * eta * (1 - xi - eta);
-
-  switch (id) {
-  case 0: { // N
-    N(0) = N1;
-    N(1) = N2;
-    N(2) = N3;
-    break;
-  }
-  case 1: { // Nwi2
-    N(0) = -(1 / 8) * P4 * L4 * C4 + (1 / 8) * P6 * L6 * C6;
-    N(1) = -(1 / 8) * P5 * L5 * C5 + (1 / 8) * P4 * L4 * C4;
-    N(2) = -(1 / 8) * P6 * L6 * C6 + (1 / 8) * P5 * L5 * C5;
-    break;
-  }
-  case 2: { // Nwi3
-    N(0) = -(1 / 8) * P4 * L4 * S4 + (1 / 8) * P6 * L6 * S6;
-    N(1) = -(1 / 8) * P5 * L5 * S5 + (1 / 8) * P4 * L4 * S4;
-    N(2) = -(1 / 8) * P6 * L6 * S6 + (1 / 8) * P5 * L5 * S5;
-    break;
-  }
-  case 3: { // Nxi1
-    N(0) = 3 / (2 * L4) * P4 * C4 - 3 / (2 * L6) * P6 * C6;
-    N(1) = 3 / (2 * L5) * P5 * C5 - 3 / (2 * L4) * P4 * C4;
-    N(2) = 3 / (2 * L6) * P6 * C6 - 3 / (2 * L5) * P5 * C5;
-    break;
-  }
-  case 4: { // Nxi2
-    N(0) = N1 - (3. / 4.) * P4 * C4 * C4 - (3. / 4.) * P6 * C6 * C6;
-    N(1) = N2 - (3. / 4.) * P5 * C5 * C5 - (3. / 4.) * P4 * C4 * C4;
-    N(2) = N3 - (3. / 4.) * P6 * C6 * C6 - (3. / 4.) * P5 * C5 * C5;
-    break;
-  }
-  case 5: { // Nxi3
-    N(0) = -(3. / 4.) * P4 * C4 * S4 - (3. / 4.) * P6 * C6 * S6;
-    N(1) = -(3. / 4.) * P5 * C5 * S5 - (3. / 4.) * P4 * C4 * S4;
-    N(2) = -(3. / 4.) * P6 * C6 * S6 - (3. / 4.) * P5 * C5 * S5;
-    break;
-  }
-  case 6: { // Nyi1
-    N(0) = 3 / (2 * L4) * P4 * S4 - 3 / (2 * L6) * P6 * S6;
-    N(1) = 3 / (2 * L5) * P5 * S5 - 3 / (2 * L4) * P4 * S4;
-    N(2) = 3 / (2 * L6) * P6 * S6 - 3 / (2 * L5) * P5 * S5;
-    break;
-  }
-  case 7: { // Nyi2
-    N(0) = -(3. / 4.) * P4 * C4 * S4 - (3. / 4.) * P6 * C6 * S6;
-    N(1) = -(3. / 4.) * P5 * C5 * S5 - (3. / 4.) * P4 * C4 * S4;
-    N(2) = -(3. / 4.) * P6 * C6 * S6 - (3. / 4.) * P5 * C5 * S5;
-    break;
-  }
-  case 8: { // Nyi3
-    N(0) = N1 - (3. / 4.) * P4 * S4 * S4 - (3. / 4.) * P6 * S6 * S6;
-    N(1) = N2 - (3. / 4.) * P5 * S5 * S5 - (3. / 4.) * P4 * S4 * S4;
-    N(2) = N3 - (3. / 4.) * P6 * S6 * S6 - (3. / 4.) * P5 * S5 * S5;
-    break;
-  }
-  }
+    const Vector<Real> & /*natural_coords*/, Matrix<Real> & /*N*/,
+    const Matrix<Real> & /*projected_coord*/) {
+//   // projected_coord (x1 x2 x3) (y1 y2 y3)
+
+//   // natural coordinate
+//   Real xi = natural_coords(0);
+//   Real eta = natural_coords(1);
+
+//   Real x21 = projected_coord(0, 0) - projected_coord(0, 1); // x1-x2
+//   Real x32 = projected_coord(0, 1) - projected_coord(0, 2);
+//   Real x13 = projected_coord(0, 2) - projected_coord(0, 0);
+
+//   Real y21 = projected_coord(1, 0) - projected_coord(1, 1); // y1-y2
+//   Real y32 = projected_coord(1, 1) - projected_coord(1, 2);
+//   Real y13 = projected_coord(1, 2) - projected_coord(1, 0);
+
+//   /* Real x21=projected_coord(0,1)-projected_coord(0,0);
+//   Real x32=projected_coord(0,2)-projected_coord(0,1);
+//   Real x13=projected_coord(0,0)-projected_coord(0,2);
+
+//   Real y21=projected_coord(1,1)-projected_coord(1,0);
+//   Real y32=projected_coord(1,2)-projected_coord(1,1);
+//   Real y13=projected_coord(1,0)-projected_coord(1,2);*/
+
+//   // natural triangle side length
+//   Real L4 = sqrt(x21 * x21 + y21 * y21);
+//   Real L5 = sqrt(x32 * x32 + y32 * y32);
+//   Real L6 = sqrt(x13 * x13 + y13 * y13);
+
+//   // sinus and cosinus
+//   Real C4 = x21 / L4; // 1
+//   Real C5 = x32 / L5; //-1/sqrt(2);
+//   Real C6 = x13 / L6; // 0
+//   Real S4 = y21 / L4; // 0;
+//   Real S5 = y32 / L5; // 1/sqrt(2);
+//   Real S6 = y13 / L6; //-1;
+
+//   Real N1 = 1 - xi - eta;
+//   Real N2 = xi;
+//   Real N3 = eta;
+
+//   Real P4 = 4 * xi * (1 - xi - eta);
+//   Real P5 = 4 * xi * eta;
+//   Real P6 = 4 * eta * (1 - xi - eta);
+
+//   // switch (id) {
+//   // case 0: { // N
+//   //   N(0) = N1;
+//   //   N(1) = N2;
+//   //   N(2) = N3;
+//   //   break;
+//   // }
+//   // case 1: { // Nwi2
+//   //   N(0) = -(1 / 8) * P4 * L4 * C4 + (1 / 8) * P6 * L6 * C6;
+//   //   N(1) = -(1 / 8) * P5 * L5 * C5 + (1 / 8) * P4 * L4 * C4;
+//   //   N(2) = -(1 / 8) * P6 * L6 * C6 + (1 / 8) * P5 * L5 * C5;
+//   //   break;
+//   // }
+//   // case 2: { // Nwi3
+//   //   N(0) = -(1 / 8) * P4 * L4 * S4 + (1 / 8) * P6 * L6 * S6;
+//   //   N(1) = -(1 / 8) * P5 * L5 * S5 + (1 / 8) * P4 * L4 * S4;
+//   //   N(2) = -(1 / 8) * P6 * L6 * S6 + (1 / 8) * P5 * L5 * S5;
+//   //   break;
+//   // }
+//   // case 3: { // Nxi1
+//   //   N(0) = 3 / (2 * L4) * P4 * C4 - 3 / (2 * L6) * P6 * C6;
+//   //   N(1) = 3 / (2 * L5) * P5 * C5 - 3 / (2 * L4) * P4 * C4;
+//   //   N(2) = 3 / (2 * L6) * P6 * C6 - 3 / (2 * L5) * P5 * C5;
+//   //   break;
+//   // }
+//   // case 4: { // Nxi2
+//   //   N(0) = N1 - (3. / 4.) * P4 * C4 * C4 - (3. / 4.) * P6 * C6 * C6;
+//   //   N(1) = N2 - (3. / 4.) * P5 * C5 * C5 - (3. / 4.) * P4 * C4 * C4;
+//   //   N(2) = N3 - (3. / 4.) * P6 * C6 * C6 - (3. / 4.) * P5 * C5 * C5;
+//   //   break;
+//   // }
+//   // case 5: { // Nxi3
+//   //   N(0) = -(3. / 4.) * P4 * C4 * S4 - (3. / 4.) * P6 * C6 * S6;
+//   //   N(1) = -(3. / 4.) * P5 * C5 * S5 - (3. / 4.) * P4 * C4 * S4;
+//   //   N(2) = -(3. / 4.) * P6 * C6 * S6 - (3. / 4.) * P5 * C5 * S5;
+//   //   break;
+//   // }
+//   // case 6: { // Nyi1
+//   //   N(0) = 3 / (2 * L4) * P4 * S4 - 3 / (2 * L6) * P6 * S6;
+//   //   N(1) = 3 / (2 * L5) * P5 * S5 - 3 / (2 * L4) * P4 * S4;
+//   //   N(2) = 3 / (2 * L6) * P6 * S6 - 3 / (2 * L5) * P5 * S5;
+//   //   break;
+//   // }
+//   // case 7: { // Nyi2
+//   //   N(0) = -(3. / 4.) * P4 * C4 * S4 - (3. / 4.) * P6 * C6 * S6;
+//   //   N(1) = -(3. / 4.) * P5 * C5 * S5 - (3. / 4.) * P4 * C4 * S4;
+//   //   N(2) = -(3. / 4.) * P6 * C6 * S6 - (3. / 4.) * P5 * C5 * S5;
+//   //   break;
+//   // }
+//   // case 8: { // Nyi3
+//   //   N(0) = N1 - (3. / 4.) * P4 * S4 * S4 - (3. / 4.) * P6 * S6 * S6;
+//   //   N(1) = N2 - (3. / 4.) * P5 * S5 * S5 - (3. / 4.) * P4 * S4 * S4;
+//   //   N(2) = N3 - (3. / 4.) * P6 * S6 * S6 - (3. / 4.) * P5 * S5 * S5;
+//   //   break;
+//   // }
+//   // }
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
-inline void InterpolationElement<_itp_kirchhoff_shell>::computeDNDS(
-    const Vector<Real> & natural_coords, Matrix<Real> & dnds,
-    const Matrix<Real> & projected_coord, UInt id) {
+inline void
+InterpolationElement<_itp_kirchhoff_shell, _itk_structural>::computeDNDS(
+    const Vector<Real> & natural_coords, Matrix<Real> & B,
+    const Matrix<Real> & projected_coord) {
 
   // natural coordinate
   Real xi = natural_coords(0);
   Real eta = natural_coords(1);
 
   // projected_coord (x1 x2 x3) (y1 y2 y3)
 
   // donne juste pour pour le patch test 4_5_5 mais donne quelque changement de
   // signe dans la matrice de rotation
 
   Real x21 = projected_coord(0, 0) - projected_coord(0, 1); // x1-x2
   Real x32 = projected_coord(0, 1) - projected_coord(0, 2);
   Real x13 = projected_coord(0, 2) - projected_coord(0, 0);
 
   Real y21 = projected_coord(1, 0) - projected_coord(1, 1); // y1-y2
   Real y32 = projected_coord(1, 1) - projected_coord(1, 2);
   Real y13 = projected_coord(1, 2) - projected_coord(1, 0);
 
   // donne juste pour la matrice de rigidité... mais pas pour le patch test
   // 4_5_5
 
   /* Real x21=projected_coord(0,1)-projected_coord(0,0);
     Real x32=projected_coord(0,2)-projected_coord(0,1);
     Real x13=projected_coord(0,0)-projected_coord(0,2);
 
     Real y21=projected_coord(1,1)-projected_coord(1,0);
     Real y32=projected_coord(1,2)-projected_coord(1,1);
     Real y13=projected_coord(1,0)-projected_coord(1,2);*/
 
   // natural triangle side length
   Real L4 = sqrt(x21 * x21 + y21 * y21);
   Real L5 = sqrt(x32 * x32 + y32 * y32);
   Real L6 = sqrt(x13 * x13 + y13 * y13);
 
   // sinus and cosinus
   Real C4 = x21 / L4;
   Real C5 = x32 / L5;
   Real C6 = x13 / L6;
   Real S4 = y21 / L4;
   Real S5 = y32 / L5;
   Real S6 = y13 / L6;
 
   Real dN1xi = -1;
   Real dN2xi = 1;
   Real dN3xi = 0;
 
   Real dN1eta = -1;
   Real dN2eta = 0;
   Real dN3eta = 1;
 
   Real dP4xi = 4 - 8 * xi - 4 * eta;
   Real dP5xi = 4 * eta;
   Real dP6xi = -4 * eta;
 
   Real dP4eta = -4 * xi;
   Real dP5eta = 4 * xi;
   Real dP6eta = 4 - 4 * xi - 8 * eta;
 
-  switch (id) {
-  case 0: { // N'xi  N'eta
-    dnds(0, 0) = dN1xi;
-    dnds(0, 1) = dN2xi;
-    dnds(0, 2) = dN3xi;
-
-    dnds(1, 0) = dN1eta;
-    dnds(1, 1) = dN2eta;
-    dnds(1, 2) = dN3eta;
-    break;
-  }
-  case 1: { // Nxi1'xi    Nxi1'eta
-    dnds(0, 0) = 3 / (2 * L4) * dP4xi * C4 - 3 / (2 * L6) * dP6xi * C6;
-    dnds(0, 1) = 3 / (2 * L5) * dP5xi * C5 - 3 / (2 * L4) * dP4xi * C4;
-    dnds(0, 2) = 3 / (2 * L6) * dP6xi * C6 - 3 / (2 * L5) * dP5xi * C5;
-
-    dnds(1, 0) = 3 / (2 * L4) * dP4eta * C4 - 3 / (2 * L6) * dP6eta * C6;
-    dnds(1, 1) = 3 / (2 * L5) * dP5eta * C5 - 3 / (2 * L4) * dP4eta * C4;
-    dnds(1, 2) = 3 / (2 * L6) * dP6eta * C6 - 3 / (2 * L5) * dP5eta * C5;
-    break;
-  }
-  case 2: { // Nxi2'xi    Nxi2'eta
-    dnds(0, 0) = -1 - (3. / 4.) * dP4xi * C4 * C4 - (3. / 4.) * dP6xi * C6 * C6;
-    dnds(0, 1) = 1 - (3. / 4.) * dP5xi * C5 * C5 - (3. / 4.) * dP4xi * C4 * C4;
-    dnds(0, 2) = -(3. / 4.) * dP6xi * C6 * C6 - (3. / 4.) * dP5xi * C5 * C5;
-
-    dnds(1, 0) =
-        -1 - (3. / 4.) * dP4eta * C4 * C4 - (3. / 4.) * dP6eta * C6 * C6;
-    dnds(1, 1) = -(3. / 4.) * dP5eta * C5 * C5 - (3. / 4.) * dP4eta * C4 * C4;
-    dnds(1, 2) =
-        1 - (3. / 4.) * dP6eta * C6 * C6 - (3. / 4.) * dP5eta * C5 * C5;
-    break;
-  }
-  case 3: { // Nxi3'xi    Nxi3'eta
-    dnds(0, 0) = -(3. / 4.) * dP4xi * C4 * S4 - (3. / 4.) * dP6xi * C6 * S6;
-    dnds(0, 1) = -(3. / 4.) * dP5xi * C5 * S5 - (3. / 4.) * dP4xi * C4 * S4;
-    dnds(0, 2) = -(3. / 4.) * dP6xi * C6 * S6 - (3. / 4.) * dP5xi * C5 * S5;
-
-    dnds(1, 0) = -(3. / 4.) * dP4eta * C4 * S4 - (3. / 4.) * dP6eta * C6 * S6;
-    dnds(1, 1) = -(3. / 4.) * dP5eta * C5 * S5 - (3. / 4.) * dP4eta * C4 * S4;
-    dnds(1, 2) = -(3. / 4.) * dP6eta * C6 * S6 - (3. / 4.) * dP5eta * C5 * S5;
-    break;
-  }
-  case 4: { // Nyi1'xi    Nyi1'eta
-    dnds(0, 0) = 3 / (2 * L4) * dP4xi * S4 - 3 / (2 * L6) * dP6xi * S6;
-    dnds(0, 1) = 3 / (2 * L5) * dP5xi * S5 - 3 / (2 * L4) * dP4xi * S4;
-    dnds(0, 2) = 3 / (2 * L6) * dP6xi * S6 - 3 / (2 * L5) * dP5xi * S5;
-
-    dnds(1, 0) = 3 / (2 * L4) * dP4eta * S4 - 3 / (2 * L6) * dP6eta * S6;
-    dnds(1, 1) = 3 / (2 * L5) * dP5eta * S5 - 3 / (2 * L4) * dP4eta * S4;
-    dnds(1, 2) = 3 / (2 * L6) * dP6eta * S6 - 3 / (2 * L5) * dP5eta * S5;
-    break;
-  }
-  case 5: { // Nyi2'xi     Nyi2'eta
-    dnds(0, 0) = -(3. / 4.) * dP4xi * C4 * S4 - (3. / 4.) * dP6xi * C6 * S6;
-    dnds(0, 1) = -(3. / 4.) * dP5xi * C5 * S5 - (3. / 4.) * dP4xi * C4 * S4;
-    dnds(0, 2) = -(3. / 4.) * dP6xi * C6 * S6 - (3. / 4.) * dP5xi * C5 * S5;
-
-    dnds(1, 0) = -(3. / 4.) * dP4eta * C4 * S4 - (3. / 4.) * dP6eta * C6 * S6;
-    dnds(1, 1) = -(3. / 4.) * dP5eta * C5 * S5 - (3. / 4.) * dP4eta * C4 * S4;
-    dnds(1, 2) = -(3. / 4.) * dP6eta * C6 * S6 - (3. / 4.) * dP5eta * C5 * S5;
-    break;
-  }
-  case 6: { // Nyi3'xi     Nyi3'eta
-    dnds(0, 0) =
-        dN1xi - (3. / 4.) * dP4xi * S4 * S4 - (3. / 4.) * dP6xi * S6 * S6;
-    dnds(0, 1) =
-        dN2xi - (3. / 4.) * dP5xi * S5 * S5 - (3. / 4.) * dP4xi * S4 * S4;
-    dnds(0, 2) =
-        dN3xi - (3. / 4.) * dP6xi * S6 * S6 - (3. / 4.) * dP5xi * S5 * S5;
-
-    dnds(1, 0) =
-        dN1eta - (3. / 4.) * dP4eta * S4 * S4 - (3. / 4.) * dP6eta * S6 * S6;
-    dnds(1, 1) =
-        dN2eta - (3. / 4.) * dP5eta * S5 * S5 - (3. / 4.) * dP4eta * S4 * S4;
-    dnds(1, 2) =
-        dN3eta - (3. / 4.) * dP6eta * S6 * S6 - (3. / 4.) * dP5eta * S5 * S5;
-    break;
-  }
-  }
+  // N'xi
+  auto Np00 = dN1xi;
+  auto Np01 = dN2xi;
+  auto Np02 = dN3xi;
+  //   N'eta
+  auto Np10 = dN1eta;
+  auto Np11 = dN2eta;
+  auto Np12 = dN3eta;
+
+  // Nxi1'xi
+  auto Nx1p00 = 3. / (2 * L4) * dP4xi * C4 - 3. / (2. * L6) * dP6xi * C6;
+  auto Nx1p01 = 3. / (2 * L5) * dP5xi * C5 - 3. / (2. * L4) * dP4xi * C4;
+  auto Nx1p02 = 3. / (2 * L6) * dP6xi * C6 - 3. / (2. * L5) * dP5xi * C5;
+  //    Nxi1'eta
+  auto Nx1p10 = 3. / (2 * L4) * dP4eta * C4 - 3. / (2. * L6) * dP6eta * C6;
+  auto Nx1p11 = 3. / (2 * L5) * dP5eta * C5 - 3. / (2. * L4) * dP4eta * C4;
+  auto Nx1p12 = 3. / (2 * L6) * dP6eta * C6 - 3. / (2. * L5) * dP5eta * C5;
+
+  // Nxi2'xi
+  auto Nx2p00 = -1 - (3. / 4.) * dP4xi * C4 * C4 - (3. / 4.) * dP6xi * C6 * C6;
+  auto Nx2p01 = 1 - (3. / 4.) * dP5xi * C5 * C5 - (3. / 4.) * dP4xi * C4 * C4;
+  auto Nx2p02 = -(3. / 4.) * dP6xi * C6 * C6 - (3. / 4.) * dP5xi * C5 * C5;
+  //    Nxi2'eta
+  auto Nx2p10 =
+      -1 - (3. / 4.) * dP4eta * C4 * C4 - (3. / 4.) * dP6eta * C6 * C6;
+  auto Nx2p11 = -(3. / 4.) * dP5eta * C5 * C5 - (3. / 4.) * dP4eta * C4 * C4;
+  auto Nx2p12 = 1 - (3. / 4.) * dP6eta * C6 * C6 - (3. / 4.) * dP5eta * C5 * C5;
+
+  // Nxi3'xi
+  auto Nx3p00 = -(3. / 4.) * dP4xi * C4 * S4 - (3. / 4.) * dP6xi * C6 * S6;
+  auto Nx3p01 = -(3. / 4.) * dP5xi * C5 * S5 - (3. / 4.) * dP4xi * C4 * S4;
+  auto Nx3p02 = -(3. / 4.) * dP6xi * C6 * S6 - (3. / 4.) * dP5xi * C5 * S5;
+  //  Nxi3'eta
+  auto Nx3p10 = -(3. / 4.) * dP4eta * C4 * S4 - (3. / 4.) * dP6eta * C6 * S6;
+  auto Nx3p11 = -(3. / 4.) * dP5eta * C5 * S5 - (3. / 4.) * dP4eta * C4 * S4;
+  auto Nx3p12 = -(3. / 4.) * dP6eta * C6 * S6 - (3. / 4.) * dP5eta * C5 * S5;
+
+  // Nyi1'xi
+  auto Ny1p00 = 3 / (2 * L4) * dP4xi * S4 - 3 / (2 * L6) * dP6xi * S6;
+  auto Ny1p01 = 3 / (2 * L5) * dP5xi * S5 - 3 / (2 * L4) * dP4xi * S4;
+  auto Ny1p02 = 3 / (2 * L6) * dP6xi * S6 - 3 / (2 * L5) * dP5xi * S5;
+  //    Nyi1'eta
+  auto Ny1p10 = 3 / (2 * L4) * dP4eta * S4 - 3 / (2 * L6) * dP6eta * S6;
+  auto Ny1p11 = 3 / (2 * L5) * dP5eta * S5 - 3 / (2 * L4) * dP4eta * S4;
+  auto Ny1p12 = 3 / (2 * L6) * dP6eta * S6 - 3 / (2 * L5) * dP5eta * S5;
+
+  // Nyi2'xi
+  auto Ny2p00 = -(3. / 4.) * dP4xi * C4 * S4 - (3. / 4.) * dP6xi * C6 * S6;
+  auto Ny2p01 = -(3. / 4.) * dP5xi * C5 * S5 - (3. / 4.) * dP4xi * C4 * S4;
+  auto Ny2p02 = -(3. / 4.) * dP6xi * C6 * S6 - (3. / 4.) * dP5xi * C5 * S5;
+  //  Nyi2'eta
+  auto Ny2p10 = -(3. / 4.) * dP4eta * C4 * S4 - (3. / 4.) * dP6eta * C6 * S6;
+  auto Ny2p11 = -(3. / 4.) * dP5eta * C5 * S5 - (3. / 4.) * dP4eta * C4 * S4;
+  auto Ny2p12 = -(3. / 4.) * dP6eta * C6 * S6 - (3. / 4.) * dP5eta * C5 * S5;
+
+  // Nyi3'xi
+  auto Ny3p00 =
+      dN1xi - (3. / 4.) * dP4xi * S4 * S4 - (3. / 4.) * dP6xi * S6 * S6;
+  auto Ny3p01 =
+      dN2xi - (3. / 4.) * dP5xi * S5 * S5 - (3. / 4.) * dP4xi * S4 * S4;
+  auto Ny3p02 =
+      dN3xi - (3. / 4.) * dP6xi * S6 * S6 - (3. / 4.) * dP5xi * S5 * S5;
+  //      Nyi3'eta
+  auto Ny3p10 =
+      dN1eta - (3. / 4.) * dP4eta * S4 * S4 - (3. / 4.) * dP6eta * S6 * S6;
+  auto Ny3p11 =
+      dN2eta - (3. / 4.) * dP5eta * S5 * S5 - (3. / 4.) * dP4eta * S4 * S4;
+  auto Ny3p12 =
+      dN3eta - (3. / 4.) * dP6eta * S6 * S6 - (3. / 4.) * dP5eta * S5 * S5;
+
+  // clang-format off
+  //       0    1                2                3                4       5     6     7                8                9               10   11    12    13               14               15               16
+  B = {{Np00,   0.,              0.,              0.,              0.,     0., Np01,   0.,              0.,              0.,              0.,  0., Np02,   0.,              0.,              0.,              0., 0.},  // 0
+       {  0., Np10,              0.,              0.,              0.,     0.,   0., Np11,              0.,              0.,              0.,  0.,   0., Np12,              0.,              0.,              0., 0.},  // 1
+       {Np10, Np00,              0.,              0.,              0.,     0., Np11, Np01,              0.,              0.,              0.,  0., Np12, Np02,              0.,              0.,              0., 0.},  // 2
+       {  0.,   0.,          Nx1p00,          Nx2p00,          Nx3p00,     0.,   0.,   0.,          Nx1p01,          Nx2p01,          Nx3p01,  0.,   0.,   0.,          Nx1p02,          Nx2p02,          Nx3p02, 0.},  // 3
+       {  0.,   0.,          Ny1p10,          Ny2p10,          Ny3p10,     0.,   0.,   0.,          Ny1p11,          Ny2p11,          Ny3p11,  0.,   0.,   0.,          Ny1p12,          Ny2p12,          Ny3p12, 0.},  // 4
+       {  0.,   0., Nx1p10 + Ny1p00, Nx2p10 + Ny2p00, Nx3p10 + Ny3p00,     0.,   0.,   0., Nx1p11 + Ny1p01, Nx2p11 + Ny2p01, Nx3p11 + Ny3p01,  0.,   0.,   0., Nx1p12 + Ny1p02, Nx2p12 + Ny2p02, Nx3p12 + Ny3p02, 0.}};  // 5
+  // clang-format on
+}
+
+
+/* -------------------------------------------------------------------------- */
+template <>
+inline void ElementClass<_kirchhoff_shell,_ek_structural>::computeShapeDerivatives(
+    const Matrix<Real> & /*natural_coord*/, Tensor3<Real> & /*shape_deriv*/,
+    const Matrix<Real> & /*real_nodal_coord*/) {
+
+  /// TO BE CONTINUED and moved in a _tmpl.hh
+  //UInt spatial_dimension = real_nodal_coord.cols();
+//   UInt nb_nodes = real_nodal_coord.rows();
+
+//   const UInt projected_dim = natural_coord.rows();
+//   Matrix<Real> rotation_matrix(real_nodal_coord);
+//   Matrix<Real> rotated_nodal_coord(real_nodal_coord);
+//   Matrix<Real> projected_nodal_coord(natural_coord);
+//   /* ------------------------------------------------------------------------ */
+//   Matrix<Real> Pe(real_nodal_coord);
+//   Matrix<Real> Pg(real_nodal_coord);
+//   Matrix<Real> inv_Pg(real_nodal_coord);
+
+//   /// compute matrix Pe
+//   Pe.eye();
+
+//   // /// compute matrix Pg
+//   // Pg(0) = real_nodal_coord(1) - real_nodal_coord(0);
+//   // Pg(1) = real_nodal_coord(2) - real_nodal_coord(0);
+//   // Pg(2).crossProduct(Pg(0), Pg(1));
+
+//   // /// compute inverse of Pg
+//   // inv_Pg.inverse(Pg);
+
+//   /// compute rotation matrix
+//   // rotation_matrix=Pe*inv_Pg;
+//   rotation_matrix.eye();
+
+//   /* ------------------------------------------------------------------------ */
+//   rotated_nodal_coord.mul<false, false>(rotation_matrix, real_nodal_coord);
+
+//   UInt nb_points = shape_deriv.size(2);
+
+//   for (UInt i = 0; i < projected_dim; ++i) {
+//     for (UInt j = 0; j < nb_points; ++j) {
+//       projected_nodal_coord(i, j) = rotated_nodal_coord(i, j);
+//     }
+//   }
+
+//   Tensor3<Real> dnds(projected_dim, nb_nodes, natural_coord.cols());
+//   Tensor3<Real> J(projected_dim, projected_dim, natural_coord.cols());
+
+//   parent_element::computeDNDS(natural_coord, dnds);
+//   parent_element::computeJMat(dnds, projected_nodal_coord, J);
+
+//   for (UInt p = 0; p < nb_points; ++p) {
+//     Matrix<Real> shape_deriv_p = shape_deriv(p);
+
+//     interpolation_element::computeDNDS(natural_coord(p), shape_deriv_p,
+//                                        projected_nodal_coord);
+
+//     Matrix<Real> dNdS = shape_deriv_p;
+//     Matrix<Real> inv_J(projected_dim, projected_dim);
+//     inv_J.inverse(J(p));
+//     shape_deriv_p.mul<false, false>(inv_J, dNdS);
+//   }
 }
+
+}  // akantu
+
+#endif /* __AKANTU_ELEMENT_CLASS_KIRCHHOFF_SHELL_INLINE_IMPL_CC__ */
diff --git a/src/fe_engine/fe_engine_template_tmpl_struct.hh b/src/fe_engine/fe_engine_template_tmpl_struct.hh
index 3f1396218..8ffdd516f 100644
--- a/src/fe_engine/fe_engine_template_tmpl_struct.hh
+++ b/src/fe_engine/fe_engine_template_tmpl_struct.hh
@@ -1,246 +1,101 @@
 /**
  * @file   fe_engine_template_tmpl_struct.hh
  *
  * @author Fabian Barras <fabian.barras@epfl.ch>
  * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Mon Jul 07 2014
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  Template implementation of FEEngineTemplate for Structural Element
  * Kinds
  *
  * @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 "shape_linked.hh"
+#include "shape_structural.hh"
 
 namespace akantu {
 
-/* -------------------------------------------------------------------------- */
-template <>
-inline const Array<Real> &
-FEEngineTemplate<IntegratorGauss, ShapeLinked, _ek_structural,
-                 DefaultIntegrationOrderFunctor>::
-    getShapesDerivatives(const ElementType & type, const GhostType & ghost_type,
-                         UInt id) const {
-
-  AKANTU_DEBUG_IN();
-  const Array<Real> * ret = NULL;
-
-#define GET_SHAPES(type)                                                       \
-  ret = &(shape_functions.getShapesDerivatives(type, ghost_type, id));
-
-  AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(GET_SHAPES);
-#undef GET_SHAPES
-
-  AKANTU_DEBUG_OUT();
-  return *ret;
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline const Array<Real> & FEEngineTemplate<
-    IntegratorGauss, ShapeLinked, _ek_structural,
-    DefaultIntegrationOrderFunctor>::getShapes(const ElementType & type,
-                                               const GhostType & ghost_type,
-                                               UInt id) const {
-  AKANTU_DEBUG_IN();
-  const Array<Real> * ret = NULL;
-
-#define GET_SHAPES(type)                                                       \
-  ret = &(shape_functions.getShapes(type, ghost_type, id));
-
-  AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(GET_SHAPES);
-#undef GET_SHAPES
-
-  AKANTU_DEBUG_OUT();
-  return *ret;
-}
-
 /* -------------------------------------------------------------------------- */
 template <ElementKind kind, typename = void>
 struct AssembleFieldMatrixStructHelper {};
 
 template <ElementKind kind>
 struct AssembleFieldMatrixStructHelper<
     kind, typename std::enable_if<kind == _ek_structural>::type> {
   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, UInt nb_degree_of_freedom,
                    SparseMatrix & M, Array<Real> * n,
                    ElementTypeMapArray<Real> & rotation_mat,
                    const ElementType & type, const GhostType & ghost_type) {
 #define ASSEMBLE_MATRIX(type)                                                  \
   fem.template assembleFieldMatrix<type>(field_1, nb_degree_of_freedom, M, n,  \
                                          rotation_mat, ghost_type)
 
     AKANTU_BOOST_KIND_ELEMENT_SWITCH(ASSEMBLE_MATRIX, _ek_structural);
 #undef ASSEMBLE_MATRIX
   }
 };
 
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline void
 FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::assembleFieldMatrix(
     const Array<Real> & field_1, UInt nb_degree_of_freedom, SparseMatrix & M,
     Array<Real> * n, ElementTypeMapArray<Real> & rotation_mat,
     const ElementType & type, const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   AssembleFieldMatrixStructHelper<kind>::template call(
       *this, field_1, nb_degree_of_freedom, M, n, rotation_mat, type,
       ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 inline void
 FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapesMatrix(
     const ElementType &, UInt, UInt, Array<Real> *,
-    __attribute__((unused)) UInt, UInt, UInt, const bool,
+    UInt, UInt, UInt, const bool,
     const GhostType &) const {
 
   AKANTU_DEBUG_TO_IMPLEMENT();
 }
 
-/* -------------------------------------------------------------------------- */
-template <>
-inline void FEEngineTemplate<IntegratorGauss, ShapeLinked, _ek_structural,
-                             DefaultIntegrationOrderFunctor>::
-    computeShapesMatrix(const ElementType & type, UInt nb_degree_of_freedom,
-                        UInt nb_nodes_per_element, Array<Real> * n, UInt id,
-                        UInt degree_to_interpolate, UInt degree_interpolated,
-                        const bool sign, // true +, false -
-                        const GhostType & ghost_type) const {
-  AKANTU_DEBUG_IN();
-
-  UInt nb_element = mesh.getNbElement(type);
-  UInt nb_quadrature_points = getNbIntegrationPoints(type);
-
-  UInt nt_n_field_size = nb_degree_of_freedom * nb_nodes_per_element;
-  UInt n_size = n->getNbComponent() / nt_n_field_size;
-
-  Array<Real>::const_vector_iterator shape =
-      getShapes(type, ghost_type, id).begin(nb_nodes_per_element);
-  Array<Real>::matrix_iterator N_it = n->begin(n_size, nt_n_field_size);
-
-  int c;
-  if (sign == true) {
-    c = 1;
-  } else {
-    c = -1;
-  }
-
-  UInt line = degree_interpolated;
-  UInt coll = degree_to_interpolate;
-
-  for (UInt e = 0; e < nb_element; ++e) {
-    for (UInt q = 0; q < nb_quadrature_points; ++q, ++N_it, ++shape) {
-      const Vector<Real> & shapes = *shape;
-      Matrix<Real> & N = *N_it;
-      N(line, coll) = shapes(0) * c;
-      N(line, coll + nb_degree_of_freedom) = shapes(1) * c;
-    }
-  }
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-template <ElementType type>
-inline void FEEngineTemplate<IntegratorGauss, ShapeLinked, _ek_structural,
-                             DefaultIntegrationOrderFunctor>::
-    assembleFieldMatrix(const Array<Real> & field_1, UInt nb_degree_of_freedom,
-                        SparseMatrix & M, Array<Real> * n,
-                        ElementTypeMapArray<Real> & rotation_mat,
-                        const GhostType & ghost_type) const {
-  AKANTU_DEBUG_IN();
-
-  UInt nb_element = mesh.getNbElement(type);
-  UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
-  UInt nb_quadrature_points = getNbIntegrationPoints(type);
-
-  UInt nt_n_field_size = nb_degree_of_freedom * nb_nodes_per_element;
-  UInt n_size = n->getNbComponent() / nt_n_field_size;
-
-  Array<Real> * nt_n_field = new Array<Real>(
-      nb_element * nb_quadrature_points, // nt_n_size * nt_n_size, nb_elem *
-                                         // nb_quad_points?
-      nt_n_field_size * nt_n_field_size, "NT*N*field");
-  Array<Real> * nt = new Array<Real>(nb_element * nb_quadrature_points,
-                                     n_size * nt_n_field_size, "N*T");
-  Array<Real> t = rotation_mat(type);
-  nt_n_field->clear();
-  nt->clear();
-
-  Array<Real>::matrix_iterator N = n->begin(n_size, nt_n_field_size);
-  Array<Real>::matrix_iterator Nt_N_field =
-      nt_n_field->begin(nt_n_field_size, nt_n_field_size);
-  Array<Real>::matrix_iterator T =
-      rotation_mat(type).begin(nt_n_field_size, nt_n_field_size);
-  Array<Real>::matrix_iterator NT = nt->begin(n_size, nt_n_field_size);
-  Real * field_val = field_1.storage();
-
-  for (UInt e = 0; e < nb_element; ++e, ++T) {
-    for (UInt q = 0; q < nb_quadrature_points;
-         ++q, ++N, ++NT, ++Nt_N_field, /*++T,*/ ++field_val) {
-      NT->mul<false, false>(*N, *T);
-      Nt_N_field->mul<true, false>(*NT, *NT, *field_val);
-    }
-  }
-
-  Array<Real> * int_nt_n_field = new Array<Real>(
-      nb_element, nt_n_field_size * nt_n_field_size, "NT*N*field");
-  int_nt_n_field->clear();
-
-  integrate(*nt_n_field, *int_nt_n_field, nt_n_field_size * nt_n_field_size,
-            type);
-  //  integrate(*nt_n_field, *int_nt_n_field, nb_degree_of_freedom, type);
-
-  assembleMatrix(*int_nt_n_field, M, nb_degree_of_freedom, type);
-
-  delete nt;
-  delete nt_n_field;
-  delete int_nt_n_field;
-
-  AKANTU_DEBUG_OUT();
-}
-
 /* -------------------------------------------------------------------------- */
 template <template <ElementKind, class> class I, template <ElementKind> class S,
           ElementKind kind, class IntegrationOrderFunctor>
 template <ElementType type>
 inline void
 FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::assembleFieldMatrix(
-    const Array<Real> & field_1, UInt nb_degree_of_freedom, SparseMatrix & M,
-    Array<Real> * n, ElementTypeMapArray<Real> & rotation_mat,
-    const GhostType & ghost_type) const {
+    const Array<Real> & , UInt , SparseMatrix &,
+    Array<Real> * , ElementTypeMapArray<Real> & ,
+    const GhostType & ) const {
   AKANTU_DEBUG_TO_IMPLEMENT();
 }
 
 } // akantu
diff --git a/src/fe_engine/interpolation_element.cc b/src/fe_engine/interpolation_element.cc
index cf5b90ed8..0cc6d7d54 100644
--- a/src/fe_engine/interpolation_element.cc
+++ b/src/fe_engine/interpolation_element.cc
@@ -1,48 +1,44 @@
 /**
  * @file   interpolation_element.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Thu Feb 21 2013
  * @date last modification: Sun Oct 19 2014
  *
  * @brief  Common part of element_classes
  *
  * @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 "element_class.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 /* Structural elements                                                        */
 /* -------------------------------------------------------------------------- */
 #if defined(AKANTU_STRUCTURAL_MECHANICS)
-template<> const UInt InterpolationElement<_itp_bernoulli_beam>::nb_shape_functions = 5;
-template<> const UInt InterpolationElement<_itp_kirchhoff_shell>::nb_shape_functions = 9;
 
-template<> const UInt InterpolationElement<_itp_bernoulli_beam>::nb_shape_derivatives = 3;
-template<> const UInt InterpolationElement<_itp_kirchhoff_shell>::nb_shape_derivatives = 7;
 #endif
  
 } // akantu
diff --git a/src/fe_engine/shape_functions.cc b/src/fe_engine/shape_functions.cc
index 3bb25cffd..15d67f780 100644
--- a/src/fe_engine/shape_functions.cc
+++ b/src/fe_engine/shape_functions.cc
@@ -1,238 +1,243 @@
 /**
  * @file   shape_functions.cc
  *
  * @author Nicolas Richart
  *
  * @date creation  Thu Jul 27 2017
  *
  * @brief implementation of th shape functions interface
  *
  * @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 "shape_functions.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
+ShapeFunctions::ShapeFunctions(const Mesh & mesh, const ID & id,
+                               const MemoryID & memory_id)
+    : Memory(id, memory_id), shapes("shapes_generic", id, memory_id),
+      shapes_derivatives("shapes_derivatives_generic", id, memory_id),
+      mesh(mesh) {}
+
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 inline void
 ShapeFunctions::initElementalFieldInterpolationFromIntegrationPoints(
     const Array<Real> & interpolation_points_coordinates,
     ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
     ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
-    const Array<Real> & quadrature_points_coordinates, const GhostType & ghost_type,
-    const Array<UInt> & element_filter) const {
+    const Array<Real> & quadrature_points_coordinates,
+    const GhostType & ghost_type, const Array<UInt> & element_filter) const {
 
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = this->mesh.getSpatialDimension();
   UInt nb_element = this->mesh.getNbElement(type, ghost_type);
   UInt nb_element_filter;
 
   if (element_filter == empty_filter)
     nb_element_filter = nb_element;
   else
     nb_element_filter = element_filter.size();
 
   UInt nb_quad_per_element =
       GaussIntegrationElement<type>::getNbQuadraturePoints();
   UInt nb_interpolation_points_per_elem =
       interpolation_points_coordinates.size() / nb_element;
 
-  AKANTU_DEBUG_ASSERT(interpolation_points_coordinates.size() % nb_element ==
-                          0,
+  AKANTU_DEBUG_ASSERT(interpolation_points_coordinates.size() % nb_element == 0,
                       "Number of interpolation points should be a multiple of "
                       "total number of elements");
 
   if (!quad_points_coordinates_inv_matrices.exists(type, ghost_type))
     quad_points_coordinates_inv_matrices.alloc(
         nb_element_filter, nb_quad_per_element * nb_quad_per_element, type,
         ghost_type);
   else
     quad_points_coordinates_inv_matrices(type, ghost_type)
         .resize(nb_element_filter);
 
   if (!interpolation_points_coordinates_matrices.exists(type, ghost_type))
     interpolation_points_coordinates_matrices.alloc(
         nb_element_filter,
         nb_interpolation_points_per_elem * nb_quad_per_element, type,
         ghost_type);
   else
     interpolation_points_coordinates_matrices(type, ghost_type)
         .resize(nb_element_filter);
 
   Array<Real> & quad_inv_mat =
       quad_points_coordinates_inv_matrices(type, ghost_type);
   Array<Real> & interp_points_mat =
       interpolation_points_coordinates_matrices(type, ghost_type);
 
   Matrix<Real> quad_coord_matrix(nb_quad_per_element, nb_quad_per_element);
 
   Array<Real>::const_matrix_iterator quad_coords_it =
       quadrature_points_coordinates.begin_reinterpret(
           spatial_dimension, nb_quad_per_element, nb_element_filter);
 
   Array<Real>::const_matrix_iterator points_coords_begin =
       interpolation_points_coordinates.begin_reinterpret(
           spatial_dimension, nb_interpolation_points_per_elem, nb_element);
 
   Array<Real>::matrix_iterator inv_quad_coord_it =
       quad_inv_mat.begin(nb_quad_per_element, nb_quad_per_element);
 
   Array<Real>::matrix_iterator int_points_mat_it = interp_points_mat.begin(
       nb_interpolation_points_per_elem, nb_quad_per_element);
 
   /// loop over the elements of the current material and element type
   for (UInt el = 0; el < nb_element_filter;
        ++el, ++inv_quad_coord_it, ++int_points_mat_it, ++quad_coords_it) {
     /// matrix containing the quadrature points coordinates
     const Matrix<Real> & quad_coords = *quad_coords_it;
     /// matrix to store the matrix inversion result
     Matrix<Real> & inv_quad_coord_matrix = *inv_quad_coord_it;
 
     /// insert the quad coordinates in a matrix compatible with the
     /// interpolation
     buildElementalFieldInterpolationMatrix<type>(quad_coords,
                                                  quad_coord_matrix);
 
     /// invert the interpolation matrix
     inv_quad_coord_matrix.inverse(quad_coord_matrix);
 
     /// matrix containing the interpolation points coordinates
     const Matrix<Real> & points_coords =
         points_coords_begin[element_filter(el)];
     /// matrix to store the interpolation points coordinates
     /// compatible with these functions
     Matrix<Real> & inv_points_coord_matrix = *int_points_mat_it;
 
     /// insert the quad coordinates in a matrix compatible with the
     /// interpolation
     buildElementalFieldInterpolationMatrix<type>(points_coords,
                                                  inv_points_coord_matrix);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ShapeFunctions::initElementalFieldInterpolationFromIntegrationPoints(
     const ElementTypeMapArray<Real> & interpolation_points_coordinates,
     ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
     ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
     const ElementTypeMapArray<Real> & quadrature_points_coordinates,
     const ElementTypeMapArray<UInt> * element_filter) const {
 
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = this->mesh.getSpatialDimension();
 
   for (auto ghost_type : ghost_types) {
     Mesh::type_iterator it, last;
     if (element_filter) {
       it = element_filter->firstType(spatial_dimension, ghost_type);
       last = element_filter->lastType(spatial_dimension, ghost_type);
     } else {
       it = mesh.firstType(spatial_dimension, ghost_type);
       last = mesh.lastType(spatial_dimension, ghost_type);
     }
     for (; it != last; ++it) {
 
       ElementType type = *it;
       UInt nb_element = mesh.getNbElement(type, ghost_type);
       if (nb_element == 0)
         continue;
 
       const Array<UInt> * elem_filter;
       if (element_filter)
         elem_filter = &((*element_filter)(type, ghost_type));
       else
         elem_filter = &(empty_filter);
 
 #define AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS(type)          \
   this->initElementalFieldInterpolationFromIntegrationPoints<type>(            \
       interpolation_points_coordinates(type, ghost_type),                      \
       interpolation_points_coordinates_matrices,                               \
       quad_points_coordinates_inv_matrices,                                    \
       quadrature_points_coordinates(type, ghost_type), ghost_type,             \
       *elem_filter)
 
       AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(
           AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS);
 #undef AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ShapeFunctions::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 {
 
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = this->mesh.getSpatialDimension();
 
   Mesh::type_iterator it, last;
 
   if (element_filter) {
     it = element_filter->firstType(spatial_dimension, ghost_type);
     last = element_filter->lastType(spatial_dimension, ghost_type);
   } else {
     it = mesh.firstType(spatial_dimension, ghost_type);
     last = mesh.lastType(spatial_dimension, ghost_type);
   }
 
   for (; it != last; ++it) {
 
     ElementType type = *it;
     UInt nb_element = mesh.getNbElement(type, ghost_type);
     if (nb_element == 0)
       continue;
 
     const Array<UInt> * elem_filter;
     if (element_filter)
       elem_filter = &((*element_filter)(type, ghost_type));
     else
       elem_filter = &(empty_filter);
 
 #define AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS(type)                 \
   interpolateElementalFieldFromIntegrationPoints<type>(                        \
       field(type, ghost_type),                                                 \
       interpolation_points_coordinates_matrices(type, ghost_type),             \
       quad_points_coordinates_inv_matrices(type, ghost_type), result,          \
       ghost_type, *elem_filter)
 
     AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(
         AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS);
 #undef AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 } // namespace akantu
diff --git a/src/fe_engine/shape_functions.hh b/src/fe_engine/shape_functions.hh
index 9158ec11c..4459fbb2b 100644
--- a/src/fe_engine/shape_functions.hh
+++ b/src/fe_engine/shape_functions.hh
@@ -1,191 +1,213 @@
 /**
  * @file   shape_functions.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Thu Oct 22 2015
  *
  * @brief  shape function 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_memory.hh"
 #include "mesh.hh"
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_SHAPE_FUNCTIONS_HH__
 #define __AKANTU_SHAPE_FUNCTIONS_HH__
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 class ShapeFunctions : protected Memory {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   ShapeFunctions(const Mesh & mesh, const ID & id = "shape",
-                 const MemoryID & memory_id = 0)
-      : Memory(id, memory_id), mesh(mesh){};
-  virtual ~ShapeFunctions(){};
+                 const MemoryID & memory_id = 0);
+  virtual ~ShapeFunctions() = default;
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// function to print the contain of the class
   virtual void printself(std::ostream & stream, int indent = 0) const {
     std::string space;
     for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
       ;
     stream << space << "Shapes [" << std::endl;
     integration_points.printself(stream, indent + 1);
     stream << space << "]" << std::endl;
   };
 
   /// set the integration points for a given element
   template <ElementType type>
   void setIntegrationPointsByType(const Matrix<Real> & integration_points,
                                   const GhostType & ghost_type);
 
   /// Build pre-computed matrices for interpolation of field form integration
   /// points at other given positions (interpolation_points)
   void initElementalFieldInterpolationFromIntegrationPoints(
       const ElementTypeMapArray<Real> & interpolation_points_coordinates,
       ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
       ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
       const ElementTypeMapArray<Real> & quadrature_points_coordinates,
       const ElementTypeMapArray<UInt> * element_filter) const;
 
   /// Interpolate field at given position from given values of this field at
   /// integration points (field)
   /// using matrices precomputed with
   /// initElementalFieldInterplationFromIntegrationPoints
   void 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;
 
 protected:
   /// interpolate nodal values stored by element on the integration points
   template <ElementType type>
   void interpolateElementalFieldOnIntegrationPoints(
       const Array<Real> & u_el, Array<Real> & uq, const GhostType & ghost_type,
       const Array<Real> & shapes,
       const Array<UInt> & filter_elements = empty_filter) const;
 
   /// gradient of nodal values stored by element on the control points
   template <ElementType type>
   void gradientElementalFieldOnIntegrationPoints(
       const Array<Real> & u_el, Array<Real> & out_nablauq,
       const GhostType & ghost_type, const Array<Real> & shapes_derivatives,
       const Array<UInt> & filter_elements) const;
 
 protected:
   /// By element versions of non-templated eponym methods
   template <ElementType type>
   inline void interpolateElementalFieldFromIntegrationPoints(
       const Array<Real> & field,
       const Array<Real> & interpolation_points_coordinates_matrices,
       const Array<Real> & quad_points_coordinates_inv_matrices,
       ElementTypeMapArray<Real> & result, const GhostType & ghost_type,
       const Array<UInt> & element_filter) const;
 
   /// Interpolate field at given position from given values of this field at
   /// integration points (field)
   /// using matrices precomputed with
   /// initElementalFieldInterplationFromIntegrationPoints
   template <ElementType type>
   inline void initElementalFieldInterpolationFromIntegrationPoints(
       const Array<Real> & interpolation_points_coordinates,
       ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices,
       ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices,
       const Array<Real> & quadrature_points_coordinates,
       const GhostType & ghost_type, const Array<UInt> & element_filter) const;
 
   /// build matrix for the interpolation of field form integration points
   template <ElementType type>
   inline void buildElementalFieldInterpolationMatrix(
       const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix,
       UInt integration_order =
           ElementClassProperty<type>::polynomial_degree) const;
 
   /// build the so called interpolation matrix (first collumn is 1, then the
   /// other collumns are the traansposed coordinates)
   inline void buildInterpolationMatrix(const Matrix<Real> & coordinates,
                                        Matrix<Real> & coordMatrix,
                                        UInt integration_order) const;
 
 public:
-  virtual void onElementsAdded(const Array<Element> & elements) = 0;
-  virtual void
-  onElementsRemoved(const Array<Element> & elements,
-                    const ElementTypeMapArray<UInt> & new_numbering) = 0;
+  virtual void onElementsAdded(const Array<Element> &) {
+    AKANTU_DEBUG_TO_IMPLEMENT();
+  }
+  virtual void onElementsRemoved(const Array<Element> &,
+                                 const ElementTypeMapArray<UInt> &) {
+    AKANTU_DEBUG_TO_IMPLEMENT();
+  }
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// get the size of the shapes returned by the element class
   static inline UInt getShapeSize(const ElementType & type);
 
   /// get the size of the shapes derivatives returned by the element class
   static inline UInt getShapeDerivativesSize(const ElementType & type);
 
   inline const Matrix<Real> &
   getIntegrationPoints(const ElementType & type,
                        const GhostType & ghost_type) const {
     return integration_points(type, ghost_type);
   }
 
+    /* ------------------------------------------------------------------------ */
+  /* Accessors                                                                */
+  /* ------------------------------------------------------------------------ */
+public:
+  /// get a the shapes vector
+  inline const Array<Real> &
+  getShapes(const ElementType & el_type,
+            const GhostType & ghost_type = _not_ghost) const;
+
+  /// get a the shapes derivatives vector
+  inline const Array<Real> &
+  getShapesDerivatives(const ElementType & el_type,
+                       const GhostType & ghost_type = _not_ghost) const;
+
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
+  /// shape functions for all elements
+  ElementTypeMapArray<Real, InterpolationType> shapes;
+
+  /// shape functions derivatives for all elements
+  ElementTypeMapArray<Real, InterpolationType> shapes_derivatives;
+
   /// associated mesh
   const Mesh & mesh;
 
   /// shape functions for all elements
   ElementTypeMap<Matrix<Real>> integration_points;
 };
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 /// standard output stream operator
 inline std::ostream & operator<<(std::ostream & stream,
                                  const ShapeFunctions & _this) {
   _this.printself(stream);
   return stream;
 }
 
 } // namespace akantu
 #include "shape_functions_inline_impl.cc"
 
 #endif /* __AKANTU_SHAPE_FUNCTIONS_HH__ */
diff --git a/src/fe_engine/shape_functions_inline_impl.cc b/src/fe_engine/shape_functions_inline_impl.cc
index 031f8060c..4b4a8ac43 100644
--- a/src/fe_engine/shape_functions_inline_impl.cc
+++ b/src/fe_engine/shape_functions_inline_impl.cc
@@ -1,393 +1,398 @@
 /**
  * @file   shape_functions_inline_impl.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Fabian Barras <fabian.barras@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Wed Oct 27 2010
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  ShapeFunctions inline 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 "fe_engine.hh"
 #include "shape_functions.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_SHAPE_FUNCTIONS_INLINE_IMPL_CC__
 #define __AKANTU_SHAPE_FUNCTIONS_INLINE_IMPL_CC__
 
 namespace akantu {
 
+/* -------------------------------------------------------------------------- */
+inline const Array<Real> &
+ShapeFunctions::getShapes(const ElementType & el_type,
+                          const GhostType & ghost_type) const {
+  return shapes(FEEngine::getInterpolationType(el_type), ghost_type);
+}
+
+/* -------------------------------------------------------------------------- */
+inline const Array<Real> &
+ShapeFunctions::getShapesDerivatives(const ElementType & el_type,
+                                     const GhostType & ghost_type) const {
+  return shapes_derivatives(FEEngine::getInterpolationType(el_type),
+                            ghost_type);
+}
+
 /* -------------------------------------------------------------------------- */
 inline UInt ShapeFunctions::getShapeSize(const ElementType & type) {
   AKANTU_DEBUG_IN();
 
   UInt shape_size = 0;
 #define GET_SHAPE_SIZE(type) shape_size = ElementClass<type>::getShapeSize()
 
   AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_SHAPE_SIZE); // ,
 
 #undef GET_SHAPE_SIZE
 
   AKANTU_DEBUG_OUT();
   return shape_size;
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt ShapeFunctions::getShapeDerivativesSize(const ElementType & type) {
   AKANTU_DEBUG_IN();
 
   UInt shape_derivatives_size = 0;
 #define GET_SHAPE_DERIVATIVES_SIZE(type)                                       \
   shape_derivatives_size = ElementClass<type>::getShapeDerivativesSize()
 
   AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_SHAPE_DERIVATIVES_SIZE); // ,
 
 #undef GET_SHAPE_DERIVATIVES_SIZE
 
   AKANTU_DEBUG_OUT();
   return shape_derivatives_size;
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void ShapeFunctions::setIntegrationPointsByType(const Matrix<Real> & points,
                                                 const GhostType & ghost_type) {
   if (not this->integration_points.exists(type, ghost_type))
     this->integration_points(type, ghost_type).shallowCopy(points);
 }
 
 /* -------------------------------------------------------------------------- */
 inline void
 ShapeFunctions::buildInterpolationMatrix(const Matrix<Real> & coordinates,
                                          Matrix<Real> & coordMatrix,
                                          UInt integration_order) const {
   switch (integration_order) {
   case 1: {
     for (UInt i = 0; i < coordinates.cols(); ++i)
       coordMatrix(i, 0) = 1;
     break;
   }
   case 2: {
     UInt nb_quadrature_points = coordMatrix.cols();
 
     for (UInt i = 0; i < coordinates.cols(); ++i) {
       coordMatrix(i, 0) = 1;
       for (UInt j = 1; j < nb_quadrature_points; ++j)
         coordMatrix(i, j) = coordinates(j - 1, i);
     }
     break;
   }
   default: {
     AKANTU_DEBUG_TO_IMPLEMENT();
     break;
   }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 inline void ShapeFunctions::buildElementalFieldInterpolationMatrix(
     const Matrix<Real> &, Matrix<Real> &, UInt) const {
   AKANTU_DEBUG_TO_IMPLEMENT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_segment_2>(
     const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix,
     UInt integration_order) const {
   buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_segment_3>(
     const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix,
     UInt integration_order) const {
   buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_triangle_3>(
     const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix,
     UInt integration_order) const {
   buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 inline void ShapeFunctions::buildElementalFieldInterpolationMatrix<_triangle_6>(
     const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix,
     UInt integration_order) const {
   buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 inline void
 ShapeFunctions::buildElementalFieldInterpolationMatrix<_tetrahedron_4>(
     const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix,
     UInt integration_order) const {
   buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 inline void
 ShapeFunctions::buildElementalFieldInterpolationMatrix<_tetrahedron_10>(
     const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix,
     UInt integration_order) const {
   buildInterpolationMatrix(coordinates, coordMatrix, integration_order);
 }
 
 /**
  * @todo Write a more efficient interpolation for quadrangles by
  * dropping unnecessary quadrature points
  *
  */
 
 /* -------------------------------------------------------------------------- */
 template <>
 inline void
 ShapeFunctions::buildElementalFieldInterpolationMatrix<_quadrangle_4>(
     const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix,
     UInt integration_order) const {
 
   if (integration_order !=
       ElementClassProperty<_quadrangle_4>::polynomial_degree) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   } else {
     for (UInt i = 0; i < coordinates.cols(); ++i) {
       Real x = coordinates(0, i);
       Real y = coordinates(1, i);
 
       coordMatrix(i, 0) = 1;
       coordMatrix(i, 1) = x;
       coordMatrix(i, 2) = y;
       coordMatrix(i, 3) = x * y;
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 inline void
 ShapeFunctions::buildElementalFieldInterpolationMatrix<_quadrangle_8>(
     const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix,
     UInt integration_order) const {
 
   if (integration_order !=
       ElementClassProperty<_quadrangle_8>::polynomial_degree) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   } else {
     for (UInt i = 0; i < coordinates.cols(); ++i) {
       UInt j = 0;
       Real x = coordinates(0, i);
       Real y = coordinates(1, i);
 
       for (UInt e = 0; e <= 2; ++e) {
         for (UInt n = 0; n <= 2; ++n) {
           coordMatrix(i, j) = std::pow(x, e) * std::pow(y, n);
           ++j;
         }
       }
     }
   }
 }
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 inline void ShapeFunctions::interpolateElementalFieldFromIntegrationPoints(
     const Array<Real> & field,
     const Array<Real> & interpolation_points_coordinates_matrices,
     const Array<Real> & quad_points_coordinates_inv_matrices,
     ElementTypeMapArray<Real> & result, const GhostType & ghost_type,
     const Array<UInt> & element_filter) const {
   AKANTU_DEBUG_IN();
 
-  UInt nb_element = this->mesh.getNbElement(type, ghost_type);
+  auto nb_element = this->mesh.getNbElement(type, ghost_type);
 
-  UInt nb_quad_per_element =
+  auto nb_quad_per_element =
       GaussIntegrationElement<type>::getNbQuadraturePoints();
-  UInt nb_interpolation_points_per_elem =
+  auto nb_interpolation_points_per_elem =
       interpolation_points_coordinates_matrices.getNbComponent() /
       nb_quad_per_element;
 
   if (!result.exists(type, ghost_type))
     result.alloc(nb_element * nb_interpolation_points_per_elem,
                  field.getNbComponent(), type, ghost_type);
 
   if (element_filter != empty_filter)
     nb_element = element_filter.size();
 
   Matrix<Real> coefficients(nb_quad_per_element, field.getNbComponent());
 
-  Array<Real> & result_vec = result(type, ghost_type);
+  auto & result_vec = result(type, ghost_type);
 
-  Array<Real>::const_matrix_iterator field_it = field.begin_reinterpret(
-      field.getNbComponent(), nb_quad_per_element, nb_element);
+  auto field_it = field.begin_reinterpret(field.getNbComponent(),
+                                          nb_quad_per_element, nb_element);
 
-  Array<Real>::const_matrix_iterator interpolation_points_coordinates_it =
+  auto interpolation_points_coordinates_it =
       interpolation_points_coordinates_matrices.begin(
           nb_interpolation_points_per_elem, nb_quad_per_element);
 
-  Array<Real>::matrix_iterator result_begin = result_vec.begin_reinterpret(
+  auto result_begin = result_vec.begin_reinterpret(
       field.getNbComponent(), nb_interpolation_points_per_elem,
       result_vec.size() / nb_interpolation_points_per_elem);
 
-  Array<Real>::const_matrix_iterator inv_quad_coord_it =
-      quad_points_coordinates_inv_matrices.begin(nb_quad_per_element,
-                                                 nb_quad_per_element);
+  auto inv_quad_coord_it = quad_points_coordinates_inv_matrices.begin(
+      nb_quad_per_element, nb_quad_per_element);
 
   /// loop over the elements of the current filter and element type
   for (UInt el = 0; el < nb_element; ++el, ++field_it, ++inv_quad_coord_it,
             ++interpolation_points_coordinates_it) {
     /**
      * matrix containing the inversion of the quadrature points'
      * coordinates
      */
-    const Matrix<Real> & inv_quad_coord_matrix = *inv_quad_coord_it;
+    const auto & inv_quad_coord_matrix = *inv_quad_coord_it;
 
     /**
      * multiply it by the field values over quadrature points to get
      * the interpolation coefficients
      */
     coefficients.mul<false, true>(inv_quad_coord_matrix, *field_it);
 
     /// matrix containing the points' coordinates
-    const Matrix<Real> & coord = *interpolation_points_coordinates_it;
+    const auto & coord = *interpolation_points_coordinates_it;
 
     /// multiply the coordinates matrix by the coefficients matrix and store the
     /// result
     Matrix<Real> res(result_begin[element_filter(el)]);
     res.mul<true, true>(coefficients, coord);
   }
 
   AKANTU_DEBUG_OUT();
 }
+
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 inline void ShapeFunctions::interpolateElementalFieldOnIntegrationPoints(
     const Array<Real> & u_el, Array<Real> & uq, const GhostType & ghost_type,
     const Array<Real> & shapes, const Array<UInt> & filter_elements) const {
-  UInt nb_element;
-  UInt nb_nodes_per_element = ElementClass<type>::getShapeSize();
-
-  UInt nb_points = shapes.size() / mesh.getNbElement(type, ghost_type);
-  UInt nb_degree_of_freedom = u_el.getNbComponent() / nb_nodes_per_element;
+  auto nb_element = mesh.getNbElement(type, ghost_type);
+  auto nb_nodes_per_element = ElementClass<type>::getShapeSize();
+  auto nb_points = shapes.size() / mesh.getNbElement(type, ghost_type);
+  auto nb_degree_of_freedom = u_el.getNbComponent() / nb_nodes_per_element;
 
   Array<Real>::const_matrix_iterator N_it;
-  Array<Real>::const_matrix_iterator u_it;
-  Array<Real>::matrix_iterator inter_u_it;
-
-  Array<Real> * filtered_N = NULL;
+  Array<Real> * filtered_N = nullptr;
   if (filter_elements != empty_filter) {
     nb_element = filter_elements.size();
     filtered_N = new Array<Real>(0, shapes.getNbComponent());
     FEEngine::filterElementalData(mesh, shapes, *filtered_N, type, ghost_type,
                                   filter_elements);
     N_it = filtered_N->begin_reinterpret(nb_nodes_per_element, nb_points,
                                          nb_element);
   } else {
-    nb_element = mesh.getNbElement(type, ghost_type);
     N_it =
         shapes.begin_reinterpret(nb_nodes_per_element, nb_points, nb_element);
   }
 
   uq.resize(nb_element * nb_points);
 
-  u_it = u_el.begin(nb_degree_of_freedom, nb_nodes_per_element);
-  inter_u_it =
+  auto u_it = u_el.begin(nb_degree_of_freedom, nb_nodes_per_element);
+  auto inter_u_it =
       uq.begin_reinterpret(nb_degree_of_freedom, nb_points, nb_element);
 
   for (UInt el = 0; el < nb_element; ++el, ++N_it, ++u_it, ++inter_u_it) {
-    const Matrix<Real> & u = *u_it;
-    const Matrix<Real> & N = *N_it;
-    Matrix<Real> & inter_u = *inter_u_it;
+    const auto & u = *u_it;
+    const auto & N = *N_it;
+    auto & inter_u = *inter_u_it;
 
-    inter_u.mul<false, false>(u, N);
+    inter_u.template mul<false, false>(u, N);
   }
 
   delete filtered_N;
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void ShapeFunctions::gradientElementalFieldOnIntegrationPoints(
     const Array<Real> & u_el, Array<Real> & out_nablauq,
     const GhostType & ghost_type, const Array<Real> & shapes_derivatives,
     const Array<UInt> & filter_elements) const {
   AKANTU_DEBUG_IN();
 
-  UInt nb_nodes_per_element =
+  auto nb_nodes_per_element =
       ElementClass<type>::getNbNodesPerInterpolationElement();
-  UInt nb_points = integration_points(type, ghost_type).cols();
-  UInt element_dimension = ElementClass<type>::getNaturalSpaceDimension();
-  UInt nb_degree_of_freedom = u_el.getNbComponent() / nb_nodes_per_element;
+  auto nb_points = integration_points(type, ghost_type).cols();
+  auto element_dimension = ElementClass<type>::getNaturalSpaceDimension();
+  auto nb_degree_of_freedom = u_el.getNbComponent() / nb_nodes_per_element;
+  auto nb_element = mesh.getNbElement(type, ghost_type);
 
   Array<Real>::const_matrix_iterator B_it;
-  Array<Real>::const_matrix_iterator u_it;
-  Array<Real>::matrix_iterator nabla_u_it;
 
-  UInt nb_element;
-  Array<Real> * filtered_B = NULL;
+  Array<Real> * filtered_B = nullptr;
   if (filter_elements != empty_filter) {
     nb_element = filter_elements.size();
     filtered_B = new Array<Real>(0, shapes_derivatives.getNbComponent());
     FEEngine::filterElementalData(mesh, shapes_derivatives, *filtered_B, type,
                                   ghost_type, filter_elements);
     B_it = filtered_B->begin(element_dimension, nb_nodes_per_element);
   } else {
     B_it = shapes_derivatives.begin(element_dimension, nb_nodes_per_element);
-    nb_element = mesh.getNbElement(type, ghost_type);
   }
 
   out_nablauq.resize(nb_element * nb_points);
-
-  u_it = u_el.begin(nb_degree_of_freedom, nb_nodes_per_element);
-  nabla_u_it = out_nablauq.begin(nb_degree_of_freedom, element_dimension);
+  auto u_it = u_el.begin(nb_degree_of_freedom, nb_nodes_per_element);
+  auto nabla_u_it = out_nablauq.begin(nb_degree_of_freedom, element_dimension);
 
   for (UInt el = 0; el < nb_element; ++el, ++u_it) {
-    const Matrix<Real> & u = *u_it;
+    const auto & u = *u_it;
     for (UInt q = 0; q < nb_points; ++q, ++B_it, ++nabla_u_it) {
-      const Matrix<Real> & B = *B_it;
-      Matrix<Real> & nabla_u = *nabla_u_it;
-
-      nabla_u.mul<false, true>(u, B);
+      const auto & B = *B_it;
+     auto & nabla_u = *nabla_u_it;
+      nabla_u.template mul<false, true>(u, B);
     }
   }
 
   delete filtered_B;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 } // namespace akantu
 
 #endif /* __AKANTU_SHAPE_FUNCTIONS_INLINE_IMPL_CC__ */
diff --git a/src/fe_engine/shape_lagrange_base.cc b/src/fe_engine/shape_lagrange_base.cc
index 12c7fb0d8..2d9dcb7b0 100644
--- a/src/fe_engine/shape_lagrange_base.cc
+++ b/src/fe_engine/shape_lagrange_base.cc
@@ -1,161 +1,159 @@
 /**
  * @file   shape_lagrange_base.cc
  *
  * @author Nicolas Richart
  *
  * @date creation  Thu Jul 27 2017
  *
  * @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 "shape_lagrange_base.hh"
 #include "mesh_iterators.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 ShapeLagrangeBase::ShapeLagrangeBase(const Mesh & mesh,
                                      const ElementKind & kind, const ID & id,
                                      const MemoryID & memory_id)
     : ShapeFunctions(mesh, id, memory_id),
-      shapes("shapes_generic", id, memory_id),
-      shapes_derivatives("shapes_derivatives_generic", id, memory_id),
       _kind(kind) {}
 
 /* -------------------------------------------------------------------------- */
 ShapeLagrangeBase::~ShapeLagrangeBase() = default;
 
 /* -------------------------------------------------------------------------- */
 #define AKANTU_COMPUTE_SHAPES(type)                                            \
   _this.template computeShapesOnIntegrationPoints<type>(                       \
       nodes, integration_points, shapes, ghost_type, filter_elements)
 
 namespace shape_lagrange {
   namespace details {
     template <ElementKind kind> struct Helper {
       template <class S>
       static void call(const S &, const Array<Real> &, const Matrix<Real> &,
                        Array<Real> &, const ElementType &, const GhostType &,
                        const Array<UInt> &) {
         AKANTU_DEBUG_TO_IMPLEMENT();
       }
     };
 
 #define AKANTU_COMPUTE_SHAPES_KIND(kind)                                       \
   template <> struct Helper<kind> {                                            \
     template <class S>                                                         \
     static void call(const S & _this, const Array<Real> & nodes,               \
                      const Matrix<Real> & integration_points,                  \
                      Array<Real> & shapes, const ElementType & type,           \
                      const GhostType & ghost_type,                             \
                      const Array<UInt> & filter_elements) {                    \
       AKANTU_BOOST_KIND_ELEMENT_SWITCH(AKANTU_COMPUTE_SHAPES, kind);           \
     }                                                                          \
   };
 
     AKANTU_BOOST_ALL_KIND_LIST(AKANTU_COMPUTE_SHAPES_KIND,
                                AKANTU_FE_ENGINE_LIST_LAGRANGE_BASE)
 
   } // namespace details
 } // namespace shape_lagrange
 
 /* -------------------------------------------------------------------------- */
 void ShapeLagrangeBase::computeShapesOnIntegrationPoints(
     const Array<Real> & nodes, const Matrix<Real> & integration_points,
     Array<Real> & shapes, const ElementType & type,
     const GhostType & ghost_type, const Array<UInt> & filter_elements) const {
 
   auto kind = Mesh::getKind(type);
 
 #define AKANTU_COMPUTE_SHAPES_KIND_SWITCH(kind)                                \
   shape_lagrange::details::Helper<kind>::call(                                 \
       *this, nodes, integration_points, shapes, type, ghost_type,              \
       filter_elements);
 
   AKANTU_BOOST_LIST_SWITCH(
       AKANTU_COMPUTE_SHAPES_KIND_SWITCH,
       BOOST_PP_LIST_TO_SEQ(AKANTU_FE_ENGINE_LIST_LAGRANGE_BASE), kind);
 
 #undef AKANTU_COMPUTE_SHAPES
 #undef AKANTU_COMPUTE_SHAPES_KIND
 #undef AKANTU_COMPUTE_SHAPES_KIND_SWITCH
 }
 
 /* -------------------------------------------------------------------------- */
 void ShapeLagrangeBase::onElementsAdded(const Array<Element> & new_elements) {
   AKANTU_DEBUG_IN();
   const auto & nodes = mesh.getNodes();
 
   for (auto elements_range : MeshElementsByTypes(new_elements)) {
     auto type = elements_range.getType();
     auto ghost_type = elements_range.getGhostType();
 
     if (mesh.getKind(type) != _kind)
       continue;
 
     auto & elements = elements_range.getElements();
 
     auto itp_type = FEEngine::getInterpolationType(type);
 
     if (not this->shapes_derivatives.exists(itp_type, ghost_type)) {
       auto size_of_shapesd = this->getShapeDerivativesSize(type);
       this->shapes_derivatives.alloc(0, size_of_shapesd, itp_type, ghost_type);
     }
 
     if (not shapes.exists(itp_type, ghost_type)) {
       auto size_of_shapes = this->getShapeSize(type);
       this->shapes.alloc(0, size_of_shapes, itp_type, ghost_type);
     }
 
     const auto & natural_coords = integration_points(type, ghost_type);
     computeShapesOnIntegrationPoints(nodes, natural_coords,
                                      shapes(itp_type, ghost_type), type,
                                      ghost_type, elements);
 
     computeShapeDerivativesOnIntegrationPoints(
         nodes, natural_coords, shapes_derivatives(itp_type, ghost_type), type,
         ghost_type, elements);
   }
 #undef INIT_SHAPE_FUNCTIONS
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void ShapeLagrangeBase::onElementsRemoved(
     const Array<Element> &, const ElementTypeMapArray<UInt> & new_numbering) {
   this->shapes.onElementsRemoved(new_numbering);
   this->shapes_derivatives.onElementsRemoved(new_numbering);
 }
 
 /* -------------------------------------------------------------------------- */
 void ShapeLagrangeBase::printself(std::ostream & stream, int indent) const {
   std::string space;
   for (Int i = 0; i < indent; i++, space += AKANTU_INDENT)
     ;
 
   stream << space << "Shapes Lagrange [" << std::endl;
   ShapeFunctions::printself(stream, indent + 1);
   shapes.printself(stream, indent + 1);
   shapes_derivatives.printself(stream, indent + 1);
   stream << space << "]" << std::endl;
 }
 
 } // namespace akantu
diff --git a/src/fe_engine/shape_lagrange_base.hh b/src/fe_engine/shape_lagrange_base.hh
index 675215fb5..2d3a0ab8c 100644
--- a/src/fe_engine/shape_lagrange_base.hh
+++ b/src/fe_engine/shape_lagrange_base.hh
@@ -1,114 +1,91 @@
 
 /**
  * @file   shape_lagrange_base.hh
  *
  * @author Nicolas Richart
  *
  * @date creation  Thu Jul 27 2017
  *
  * @brief Base class for the shape lagrange
  *
  * @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 "shape_functions.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_SHAPE_LAGRANGE_BASE_HH__
 #define __AKANTU_SHAPE_LAGRANGE_BASE_HH__
 
 namespace akantu {
 
 class ShapeLagrangeBase : public ShapeFunctions {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   ShapeLagrangeBase(const Mesh & mesh, const ElementKind & kind,
                     const ID & id = "shape_lagrange",
                     const MemoryID & memory_id = 0);
   virtual ~ShapeLagrangeBase();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// computes the shape functions for given interpolation points
   virtual void computeShapesOnIntegrationPoints(
       const Array<Real> & nodes, const Matrix<Real> & integration_points,
       Array<Real> & shapes, const ElementType & type,
       const GhostType & ghost_type,
       const Array<UInt> & filter_elements = empty_filter) const;
 
   /// computes the shape functions derivatives for given interpolation points
   virtual void computeShapeDerivativesOnIntegrationPoints(
       const Array<Real> & nodes, const Matrix<Real> & integration_points,
       Array<Real> & shape_derivatives, const ElementType & type,
       const GhostType & ghost_type,
       const Array<UInt> & filter_elements = empty_filter) const = 0;
 
   /// function to print the containt of the class
   void printself(std::ostream & stream, int indent = 0) const override;
 
   template <ElementType type>
   void computeShapesOnIntegrationPoints(
       const Array<Real> & nodes, const Matrix<Real> & integration_points,
       Array<Real> & shapes, const GhostType & ghost_type,
       const Array<UInt> & filter_elements = empty_filter) const;
 
 public:
   void onElementsAdded(const Array<Element> & elements) override;
   void
   onElementsRemoved(const Array<Element> & elements,
                     const ElementTypeMapArray<UInt> & new_numbering) override;
 
-  /* ------------------------------------------------------------------------ */
-  /* Accessors                                                                */
-  /* ------------------------------------------------------------------------ */
-public:
-  /// get a the shapes vector
-  inline const Array<Real> &
-  getShapes(const ElementType & el_type,
-            const GhostType & ghost_type = _not_ghost) const;
-
-  /// get a the shapes derivatives vector
-  inline const Array<Real> &
-  getShapesDerivatives(const ElementType & el_type,
-                       const GhostType & ghost_type = _not_ghost) const;
-
-  /* ------------------------------------------------------------------------ */
-  /* Class Members                                                            */
-  /* ------------------------------------------------------------------------ */
 protected:
-  /// shape functions for all elements
-  ElementTypeMapArray<Real, InterpolationType> shapes;
-
-  /// shape functions derivatives for all elements
-  ElementTypeMapArray<Real, InterpolationType> shapes_derivatives;
-
   /// The kind to consider
   ElementKind _kind;
 };
 
 } // namespace akantu
 
 #include "shape_lagrange_base_inline_impl.cc"
 
 #endif /* __AKANTU_SHAPE_LAGRANGE_BASE_HH__ */
diff --git a/src/fe_engine/shape_lagrange_base_inline_impl.cc b/src/fe_engine/shape_lagrange_base_inline_impl.cc
index 1c09adcef..4b9ebbf08 100644
--- a/src/fe_engine/shape_lagrange_base_inline_impl.cc
+++ b/src/fe_engine/shape_lagrange_base_inline_impl.cc
@@ -1,97 +1,82 @@
 /**
  * @file   shape_lagrange_base_inline_impl.cc
  *
  * @author Nicolas Richart
  *
  * @date creation  Thu Jul 27 2017
  *
  * @brief A Documented file.
  *
  * @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 "shape_lagrange_base.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_SHAPE_LAGRANGE_BASE_INLINE_IMPL_CC__
 #define __AKANTU_SHAPE_LAGRANGE_BASE_INLINE_IMPL_CC__
 
 namespace akantu {
 
-/* -------------------------------------------------------------------------- */
-inline const Array<Real> &
-ShapeLagrangeBase::getShapes(const ElementType & el_type,
-                             const GhostType & ghost_type) const {
-  return shapes(FEEngine::getInterpolationType(el_type), ghost_type);
-}
-
-/* -------------------------------------------------------------------------- */
-inline const Array<Real> &
-ShapeLagrangeBase::getShapesDerivatives(const ElementType & el_type,
-                                        const GhostType & ghost_type) const {
-  return shapes_derivatives(FEEngine::getInterpolationType(el_type),
-                            ghost_type);
-}
-
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void ShapeLagrangeBase::computeShapesOnIntegrationPoints(
     const Array<Real> &, const Matrix<Real> & integration_points,
     Array<Real> & shapes, const GhostType & ghost_type,
     const Array<UInt> & filter_elements) const {
   AKANTU_DEBUG_IN();
 
   UInt nb_points = integration_points.cols();
   UInt nb_element = mesh.getConnectivity(type, ghost_type).size();
 
   shapes.resize(nb_element * nb_points);
 
 #if !defined(AKANTU_NDEBUG)
   UInt size_of_shapes = ElementClass<type>::getShapeSize();
   AKANTU_DEBUG_ASSERT(shapes.getNbComponent() == size_of_shapes,
                       "The shapes array does not have the correct "
                           << "number of component");
 #endif
 
   auto shapes_it = shapes.begin_reinterpret(
       ElementClass<type>::getNbNodesPerInterpolationElement(), nb_points,
       nb_element);
   auto shapes_begin = shapes_it;
   if (filter_elements != empty_filter) {
     nb_element = filter_elements.size();
   }
 
   for (UInt elem = 0; elem < nb_element; ++elem) {
     if (filter_elements != empty_filter)
       shapes_it = shapes_begin + filter_elements(elem);
 
     Matrix<Real> & N = *shapes_it;
     ElementClass<type>::computeShapes(integration_points, N);
 
     if (filter_elements == empty_filter)
       ++shapes_it;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 } // namespace akantu
 
 #endif /* __AKANTU_SHAPE_LAGRANGE_BASE_INLINE_IMPL_CC__ */
diff --git a/src/fe_engine/shape_linked.cc b/src/fe_engine/shape_linked.cc
deleted file mode 100644
index 86392fec7..000000000
--- a/src/fe_engine/shape_linked.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * @file   shape_linked.cc
- *
- * @author Fabian Barras <fabian.barras@epfl.ch>
- * @author Nicolas Richart <nicolas.richart@epfl.ch>
- *
- * @date creation: Fri Jul 15 2011
- * @date last modification: Sun Oct 19 2014
- *
- * @brief  ShapeLinked 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 "aka_memory.hh"
-#include "mesh.hh"
-#include "shape_linked.hh"
-/* -------------------------------------------------------------------------- */
-
-namespace akantu {
-
-#if defined(AKANTU_STRUCTURAL_MECHANICS)
-/* -------------------------------------------------------------------------- */
-template <>
-ShapeLinked<_ek_structural>::ShapeLinked(Mesh & mesh, const ID & id, const MemoryID & memory_id) :
-  ShapeFunctions(mesh, id, memory_id)
-{
-
-}
-
-
-/* -------------------------------------------------------------------------- */
-template <>
-ShapeLinked<_ek_structural>::~ShapeLinked() {
-  for (ghost_type_t::iterator gt = ghost_type_t::begin();
-       gt != ghost_type_t::end(); ++gt) {
-    GhostType ghost_type = *gt;
-
-    // delete all the shapes id
-    ElementTypeMapMultiReal::type_iterator s_type_it  =
-      shapes.firstType(_all_dimensions, ghost_type, _ek_structural);
-    ElementTypeMapMultiReal::type_iterator s_type_end =
-      shapes.lastType (_all_dimensions, ghost_type, _ek_structural);
-
-    for(; s_type_it != s_type_end; ++s_type_it) {
-      delete [] shapes(*s_type_it, ghost_type);
-    }
-
-
-    // delete all the shapes derivatives id
-    ElementTypeMapMultiReal::type_iterator sd_type_it  =
-      shapes_derivatives.firstType(_all_dimensions, ghost_type, _ek_structural);
-    ElementTypeMapMultiReal::type_iterator sd_type_end =
-      shapes_derivatives.lastType (_all_dimensions, ghost_type, _ek_structural);
-
-    for(; sd_type_it != sd_type_end; ++sd_type_it) {
-      delete [] shapes_derivatives(*sd_type_it, ghost_type);
-    }
-  }
-}
-#endif
-
-} // akantu
diff --git a/src/fe_engine/shape_linked_inline_impl.cc b/src/fe_engine/shape_linked_inline_impl.cc
deleted file mode 100644
index 2112762e6..000000000
--- a/src/fe_engine/shape_linked_inline_impl.cc
+++ /dev/null
@@ -1,319 +0,0 @@
-/**
- * @file   shape_linked_inline_impl.cc
- *
- * @author Fabian Barras <fabian.barras@epfl.ch>
- * @author Nicolas Richart <nicolas.richart@epfl.ch>
- *
- * @date creation: Mon Dec 13 2010
- * @date last modification: Thu Oct 15 2015
- *
- * @brief  ShapeLinked inline 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/>.
- *
- */
-
-template <ElementKind kind>
-inline void ShapeLinked<kind>::initShapeFunctions(
-    __attribute__((unused)) const Array<Real> & nodes,
-    __attribute__((unused)) const Matrix<Real> & integration_points,
-    __attribute__((unused)) const ElementType & type,
-    __attribute__((unused)) const GhostType & ghost_type) {
-  AKANTU_DEBUG_TO_IMPLEMENT();
-}
-
-#undef INIT_SHAPE_FUNCTIONS
-
-/* -------------------------------------------------------------------------- */
-#define INIT_SHAPE_FUNCTIONS(type)                                             \
-  setIntegrationPointsByType<type>(integration_points, ghost_type);            \
-  precomputeShapesOnIntegrationPoints<type>(nodes, ghost_type);                \
-  precomputeShapeDerivativesOnIntegrationPoints<type>(nodes, ghost_type);
-
-#if defined(AKANTU_STRUCTURAL_MECHANICS)
-template <>
-inline void ShapeLinked<_ek_structural>::initShapeFunctions(
-    __attribute__((unused)) const Array<Real> & nodes,
-    __attribute__((unused)) const Matrix<Real> & integration_points,
-    __attribute__((unused)) const ElementType & type,
-    __attribute__((unused)) const GhostType & ghost_type) {
-  AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(INIT_SHAPE_FUNCTIONS);
-}
-#endif
-
-#undef INIT_SHAPE_FUNCTIONS
-
-/* -------------------------------------------------------------------------- */
-template <ElementKind kind>
-inline const Array<Real> &
-ShapeLinked<kind>::getShapes(const ElementType & type,
-                             const GhostType & ghost_type, UInt id) const {
-  AKANTU_DEBUG_IN();
-  AKANTU_DEBUG_ASSERT(shapes.exists(type, ghost_type),
-                      "No shapes of type " << type << " in " << this->id);
-  AKANTU_DEBUG_OUT();
-  return *(shapes(type, ghost_type)[id]);
-}
-
-/* -------------------------------------------------------------------------- */
-template <ElementKind kind>
-inline const Array<Real> & ShapeLinked<kind>::getShapesDerivatives(
-    const ElementType & type, const GhostType & ghost_type, UInt id) const {
-  AKANTU_DEBUG_IN();
-  AKANTU_DEBUG_ASSERT(shapes_derivatives.exists(type, ghost_type),
-                      "No shapes_derivatives of type " << type << " in "
-                                                       << this->id);
-  AKANTU_DEBUG_OUT();
-  return *(shapes_derivatives(type, ghost_type)[id]);
-}
-
-#if defined(AKANTU_STRUCTURAL_MECHANICS)
-/* -------------------------------------------------------------------------- */
-template <>
-template <ElementType type>
-void ShapeLinked<_ek_structural>::precomputeShapesOnIntegrationPoints(
-    const Array<Real> & nodes, const GhostType & ghost_type) {
-  AKANTU_DEBUG_IN();
-
-  //  Real * coord = mesh.getNodes().storage();
-  UInt spatial_dimension = mesh.getSpatialDimension();
-  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
-
-  Matrix<Real> & natural_coords = integration_points(type, ghost_type);
-  UInt nb_points = integration_points(type, ghost_type).cols();
-
-  UInt size_of_shapes = ElementClass<type>::getShapeSize();
-
-  std::string ghost = "";
-  if (ghost_type == _ghost) {
-    ghost = "ghost_";
-  }
-
-  UInt nb_element = mesh.getNbElement(type, ghost_type);
-  UInt nb_shape_functions =
-      ElementClass<type, _ek_structural>::getNbShapeFunctions();
-
-  Array<Real> ** shapes_tmp = new Array<Real> * [nb_shape_functions];
-
-  Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
-  FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type);
-
-  for (UInt s = 0; s < nb_shape_functions; ++s) {
-    std::stringstream sstr_shapes;
-    sstr_shapes << id << ":" << ghost << "shapes:" << type << ":" << s;
-    shapes_tmp[s] = &(alloc<Real>(sstr_shapes.str(), nb_element * nb_points,
-                                  size_of_shapes));
-    Array<Real>::matrix_iterator x_it =
-        x_el.begin(spatial_dimension, nb_nodes_per_element);
-    Array<Real>::matrix_iterator shapes_it =
-        shapes_tmp[s]->begin_reinterpret(size_of_shapes, nb_points, nb_element);
-
-    for (UInt elem = 0; elem < nb_element; ++elem, ++shapes_it, ++x_it) {
-      Matrix<Real> & X = *x_it;
-      Matrix<Real> & N = *shapes_it;
-      ElementClass<type>::computeShapes(natural_coords, N, X, s);
-    }
-  }
-
-  shapes(type, ghost_type) = shapes_tmp;
-
-  AKANTU_DEBUG_OUT();
-}
-#endif
-
-/* -------------------------------------------------------------------------- */
-template <ElementKind kind>
-template <ElementType type>
-void ShapeLinked<kind>::precomputeShapeDerivativesOnIntegrationPoints(
-    const Array<Real> & nodes, const GhostType & ghost_type) {
-  AKANTU_DEBUG_IN();
-
-  // Real * coord = mesh.getNodes().storage();
-  UInt spatial_dimension = mesh.getSpatialDimension();
-  UInt natural_spatial_dimension =
-      ElementClass<type>::getNaturalSpaceDimension();
-
-  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
-  UInt size_of_shapesd = ElementClass<type>::getShapeDerivativesSize();
-  Matrix<Real> & natural_coords = integration_points(type, ghost_type);
-  UInt nb_points = natural_coords.cols();
-
-  UInt nb_element = mesh.getNbElement(type, ghost_type);
-  std::string ghost = "";
-
-  if (ghost_type == _ghost) {
-    ghost = "ghost_";
-  }
-
-  Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
-  FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type);
-
-  UInt nb_shape_functions = ElementClass<type>::getNbShapeDerivatives();
-
-  Array<Real> ** shapes_derivatives_tmp =
-      new Array<Real> * [nb_shape_functions];
-  for (UInt s = 0; s < nb_shape_functions; ++s) {
-    std::stringstream sstr_shapesd;
-    sstr_shapesd << id << ":" << ghost << "shapes_derivatives:" << type << ":"
-                 << s;
-    shapes_derivatives_tmp[s] = &(alloc<Real>(
-        sstr_shapesd.str(), nb_element * nb_points, size_of_shapesd));
-    Real * shapesd_val = shapes_derivatives_tmp[s]->storage();
-
-    Array<Real>::matrix_iterator x_it =
-        x_el.begin(spatial_dimension, nb_nodes_per_element);
-
-    for (UInt elem = 0; elem < nb_element; ++elem, ++x_it) {
-      // compute shape derivatives
-      Matrix<Real> & X = *x_it;
-      Tensor3<Real> B(shapesd_val, natural_spatial_dimension,
-                      nb_nodes_per_element, nb_points);
-      ElementClass<type>::computeShapeDerivatives(natural_coords, B, X, s);
-
-      shapesd_val += size_of_shapesd * nb_points;
-    }
-  }
-
-  shapes_derivatives(type, ghost_type) = shapes_derivatives_tmp;
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <ElementKind kind>
-template <ElementType type>
-void ShapeLinked<kind>::extractNodalToElementField(
-    const Array<Real> & nodal_f, Array<Real> & elemental_f,
-    UInt num_degre_of_freedom_to_extract, const GhostType & ghost_type,
-    const Array<UInt> & filter_elements) const {
-  AKANTU_DEBUG_IN();
-
-  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
-  UInt nb_degree_of_freedom = nodal_f.getNbComponent();
-  UInt nb_element = mesh.getNbElement(type, ghost_type);
-  UInt * conn_val = mesh.getConnectivity(type, ghost_type).storage();
-
-  if (filter_elements != empty_filter) {
-    nb_element = filter_elements.size();
-  }
-
-  elemental_f.resize(nb_element);
-
-  Real * nodal_f_val = nodal_f.storage();
-  Real * f_val = elemental_f.storage();
-
-  UInt * el_conn;
-  for (UInt el = 0; el < nb_element; ++el) {
-    if (filter_elements != empty_filter)
-      el_conn = conn_val + filter_elements(el) * nb_nodes_per_element;
-    else
-      el_conn = conn_val + el * nb_nodes_per_element;
-
-    for (UInt n = 0; n < nb_nodes_per_element; ++n) {
-      UInt node = *(el_conn + n);
-      *f_val = nodal_f_val[node * nb_degree_of_freedom +
-                           num_degre_of_freedom_to_extract];
-      f_val += 1;
-    }
-  }
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <ElementKind kind>
-template <ElementType type>
-void ShapeLinked<kind>::interpolateOnIntegrationPoints(
-    const Array<Real> & in_u, Array<Real> & out_uq,
-    __attribute__((unused)) UInt nb_degree_of_freedom,
-    const GhostType & ghost_type, const Array<UInt> & filter_elements,
-    bool accumulate, UInt id_shape, UInt num_degre_of_freedom_to_interpolate,
-    __attribute__((unused)) UInt num_degre_of_freedom_interpolated) const {
-  AKANTU_DEBUG_IN();
-
-  Array<Real> * shapes_loc = shapes(type, ghost_type)[id_shape];
-
-  AKANTU_DEBUG_ASSERT(shapes_loc != NULL, "No shapes for the type " << type);
-
-  UInt nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement();
-  Array<Real> u_el(0, nb_nodes_per_element);
-  extractNodalToElementField<type>(in_u, u_el,
-                                   num_degre_of_freedom_to_interpolate,
-                                   ghost_type, filter_elements);
-
-  if (!accumulate)
-    out_uq.clear();
-
-  UInt nb_points = integration_points(type, ghost_type).cols() * u_el.size();
-  Array<Real> uq(nb_points, 1, 0.);
-
-  this->template interpolateElementalFieldOnIntegrationPoints<type>(
-      u_el, uq, ghost_type, *shapes_loc, filter_elements);
-
-  for (UInt q = 0; q < nb_points; ++q) {
-    out_uq(q, num_degre_of_freedom_to_interpolate) += uq(q);
-  }
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <ElementKind kind>
-template <ElementType type>
-void ShapeLinked<kind>::gradientOnIntegrationPoints(
-    const Array<Real> & in_u, Array<Real> & out_nablauq,
-    UInt nb_degree_of_freedom, const GhostType & ghost_type,
-    const Array<UInt> & filter_elements, bool accumulate, UInt id_shape,
-    UInt num_degre_of_freedom_to_interpolate,
-    __attribute__((unused)) UInt num_degre_of_freedom_interpolated) const {
-  AKANTU_DEBUG_IN();
-
-  Array<Real> * shapesd_loc = shapes_derivatives(type, ghost_type)[id_shape];
-
-  AKANTU_DEBUG_ASSERT(shapesd_loc != NULL, "No shapes for the type " << type);
-
-  UInt nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement();
-  Array<Real> u_el(0, nb_nodes_per_element);
-  extractNodalToElementField<type>(in_u, u_el,
-                                   num_degre_of_freedom_to_interpolate,
-                                   ghost_type, filter_elements);
-
-  UInt nb_points = integration_points(type, ghost_type).cols() * u_el.size();
-  UInt element_dimension = ElementClass<type>::getSpatialDimension();
-
-  Array<Real> nablauq(nb_points, element_dimension, 0.);
-
-  if (!accumulate)
-    out_nablauq.clear();
-  this->template gradientElementalFieldOnIntegrationPoints<type>(
-      u_el, nablauq, ghost_type, *shapesd_loc, filter_elements);
-
-  Array<Real>::matrix_iterator nabla_u_it = nablauq.begin(1, element_dimension);
-  Array<Real>::matrix_iterator out_nabla_u_it =
-      out_nablauq.begin(nb_degree_of_freedom, element_dimension);
-  for (UInt q = 0; q < nb_points; ++q, ++nabla_u_it, ++out_nabla_u_it) {
-    for (UInt s = 0; s < element_dimension; ++s) {
-      (*out_nabla_u_it)(num_degre_of_freedom_to_interpolate, s) +=
-          (*nabla_u_it)(0, s);
-    }
-  }
-
-  AKANTU_DEBUG_OUT();
-}
diff --git a/src/io/model_io.cc b/src/fe_engine/shape_structural.cc
similarity index 63%
rename from src/io/model_io.cc
rename to src/fe_engine/shape_structural.cc
index edfd6c372..0bee5ec47 100644
--- a/src/io/model_io.cc
+++ b/src/fe_engine/shape_structural.cc
@@ -1,50 +1,53 @@
 /**
- * @file   model_io.cc
+ * @file   shape_structural.cc
  *
+ * @author Fabian Barras <fabian.barras@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
- * @date creation: Thu Feb 21 2013
+ * @date creation: Fri Jul 15 2011
  * @date last modification: Sun Oct 19 2014
  *
- * @brief  Reader for models (this is deprecated)
+ * @brief  ShapeStructural implementation
  *
  * @section LICENSE
  *
- * Copyright  (©)  2014,  2015 EPFL  (Ecole Polytechnique  Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ * 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 "model_io.hh"
-
+#include "shape_structural.hh"
+#include "aka_memory.hh"
+#include "mesh.hh"
 /* -------------------------------------------------------------------------- */
 
-
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
-ModelIO::ModelIO() {
-}
+template <>
+ShapeStructural<_ek_structural>::ShapeStructural(Mesh & mesh, const ID & id,
+                                         const MemoryID & memory_id)
+    : ShapeFunctions(mesh, id, memory_id) {}
 
 /* -------------------------------------------------------------------------- */
-ModelIO::~ModelIO() {
+template <> ShapeStructural<_ek_structural>::~ShapeStructural() = default;
 
-}
 /* -------------------------------------------------------------------------- */
 
-} // akantu
+
+} // namespace akantu
diff --git a/src/fe_engine/shape_linked.hh b/src/fe_engine/shape_structural.hh
similarity index 52%
rename from src/fe_engine/shape_linked.hh
rename to src/fe_engine/shape_structural.hh
index 1e0c6eae5..cd7e368d5 100644
--- a/src/fe_engine/shape_linked.hh
+++ b/src/fe_engine/shape_structural.hh
@@ -1,161 +1,123 @@
 /**
- * @file   shape_linked.hh
+ * @file   shape_structural.hh
  *
  * @author Fabian Barras <fabian.barras@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Tue Feb 15 2011
  * @date last modification: Thu Oct 22 2015
  *
  * @brief  shape class for element with different set of shapes functions
  *
  * @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
+  * 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 "shape_functions.hh"
 
-#ifndef __AKANTU_SHAPE_LINKED_HH__
-#define __AKANTU_SHAPE_LINKED_HH__
+#ifndef __AKANTU_SHAPE_STRUCTURAL_HH__
+#define __AKANTU_SHAPE_STRUCTURAL_HH__
 
 namespace akantu {
 
-template <ElementKind kind>
-class ShapeLinked : public ShapeFunctions {
+template <ElementKind kind> class ShapeStructural : public ShapeFunctions {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
-
   typedef ElementTypeMap<Array<Real> **> ElementTypeMapMultiReal;
 
-  ShapeLinked(Mesh & mesh, const ID & id = "shape_linked", const MemoryID & memory_id = 0);
-  virtual ~ShapeLinked();
+  ShapeStructural(Mesh & mesh, const ID & id = "shape_structural",
+              const MemoryID & memory_id = 0);
+  virtual ~ShapeStructural();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialization function for structural elements
   inline void initShapeFunctions(const Array<Real> & nodes,
-				 const Matrix<Real> & integration_points,
-				 const ElementType & type,
-				 const GhostType & ghost_type);
+                                 const Matrix<Real> & integration_points,
+                                 const ElementType & type,
+                                 const GhostType & ghost_type);
 
-  /// pre compute all shapes on the element integration points from natural coordinates
+  /// pre compute all shapes on the element integration points from natural
+  /// coordinates
   template <ElementType type>
   void precomputeShapesOnIntegrationPoints(const Array<Real> & nodes,
-				       const GhostType & ghost_type);
+                                           const GhostType & ghost_type);
 
-  /// pre compute all shapes on the element integration points from natural coordinates
+  /// pre compute all shapes on the element integration points from natural
+  /// coordinates
   template <ElementType type>
-  void precomputeShapeDerivativesOnIntegrationPoints(const Array<Real> & nodes,
-						 const GhostType & ghost_type);
+  void
+  precomputeShapeDerivativesOnIntegrationPoints(const Array<Real> & nodes,
+                                                const GhostType & ghost_type);
 
   /// interpolate nodal values on the integration points
   template <ElementType type>
-  void interpolateOnIntegrationPoints(const Array<Real> &u,
-				  Array<Real> &uq,
-				  UInt nb_degree_of_freedom,
-				  const GhostType & ghost_type = _not_ghost,
-				  const Array<UInt> & filter_elements = empty_filter,
-				  bool accumulate = false,
-				  UInt id_shape = 0,
-				  UInt num_degre_of_freedom_to_interpolate = 0,
-				  UInt num_degre_of_freedom_interpolated = 0) const;
-
+  void interpolateOnIntegrationPoints(
+      const Array<Real> & u, Array<Real> & uq, UInt nb_degree_of_freedom,
+      const GhostType & ghost_type = _not_ghost,
+      const Array<UInt> & filter_elements = empty_filter) const;
 
   /// compute the gradient of u on the integration points
   template <ElementType type>
-  void gradientOnIntegrationPoints(const Array<Real> &u,
-			       Array<Real> &nablauq,
-			       UInt nb_degree_of_freedom,
-			       const GhostType & ghost_type = _not_ghost,
-			       const Array<UInt> & filter_elements = empty_filter,
-			       bool accumulate = false,
-			       UInt id_shape = 0,
-			       UInt num_degre_of_freedom_to_interpolate = 0,
-			       UInt num_degre_of_freedom_interpolated = 0) const;
+  void gradientOnIntegrationPoints(
+      const Array<Real> & u, Array<Real> & nablauq, UInt nb_degree_of_freedom,
+      const GhostType & ghost_type = _not_ghost,
+      const Array<UInt> & filter_elements = empty_filter) const;
 
   /// multiply a field by shape functions
   template <ElementType type>
-  void fieldTimesShapes(__attribute__((unused)) const Array<Real> & field,
-			__attribute__((unused)) Array<Real> & fiedl_times_shapes,
-			__attribute__((unused)) const GhostType & ghost_type) const {
+  void
+  fieldTimesShapes(__attribute__((unused)) const Array<Real> & field,
+                   __attribute__((unused)) Array<Real> & fiedl_times_shapes,
+                   __attribute__((unused)) const GhostType & ghost_type) const {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
-private:
-  /// extract the nodal field value to fill an elemental field
-  template <ElementType type>
-  void extractNodalToElementField(const Array<Real> & nodal_f,
-				  Array<Real> & elemental_f,
-				  UInt num_degre_of_freedom_to_extract,
-				  const GhostType & ghost_type,
-				  const Array<UInt> & filter_elements) const;
-
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
-
   /// get a the shapes vector
   inline const Array<Real> & getShapes(const ElementType & type,
-					const GhostType & ghost_type,
-					UInt id = 0) const;
+                                       const GhostType & ghost_type,
+                                       UInt id = 0) const;
 
   /// get a the shapes derivatives vector
   inline const Array<Real> & getShapesDerivatives(const ElementType & type,
-						   const GhostType & ghost_type,
-						   UInt id = 0) const;
+                                                  const GhostType & ghost_type,
+                                                  UInt id = 0) const;
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
-  /// shape functions for all elements
-  ElementTypeMapMultiReal shapes;
-
-  /// shape derivatives for all elements
-  ElementTypeMapMultiReal shapes_derivatives;
 };
 
+} // namespace akantu
 
-/* -------------------------------------------------------------------------- */
-/* inline functions                                                           */
-/* -------------------------------------------------------------------------- */
-
-#if defined (AKANTU_INCLUDE_INLINE_IMPL)
-#  include "shape_linked_inline_impl.cc"
-#endif
-
-/// standard output stream operator
-// inline std::ostream & operator <<(std::ostream & stream, const ShapeLinked & _this)
-// {
-//   _this.printself(stream);
-//   return stream;
-// }
-
-
-} // akantu
+#include "shape_structural_inline_impl.cc"
 
-#endif /* __AKANTU_SHAPE_LINKED_HH__ */
+#endif /* __AKANTU_SHAPE_STRUCTURAL_HH__ */
diff --git a/src/fe_engine/shape_structural_inline_impl.cc b/src/fe_engine/shape_structural_inline_impl.cc
new file mode 100644
index 000000000..cf22aec85
--- /dev/null
+++ b/src/fe_engine/shape_structural_inline_impl.cc
@@ -0,0 +1,253 @@
+/**
+ * @file   shape_structural_inline_impl.cc
+ *
+ * @author Fabian Barras <fabian.barras@epfl.ch>
+ * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ *
+ * @date creation: Mon Dec 13 2010
+ * @date last modification: Thu Oct 15 2015
+ *
+ * @brief  ShapeStructural inline 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 "mesh_iterators.hh"
+#include "shape_structural.hh"
+/* -------------------------------------------------------------------------- */
+
+#ifndef __AKANTU_SHAPE_STRUCTURAL_INLINE_IMPL_CC__
+#define __AKANTU_SHAPE_STRUCTURAL_INLINE_IMPL_CC__
+
+namespace akantu {
+
+template <ElementKind kind>
+inline void ShapeStructural<kind>::initShapeFunctions(
+    const Array<Real> & /* unused */, const Matrix<Real> & /* unused */,
+    const ElementType & /* unused */, const GhostType & /* unused */) {
+  AKANTU_DEBUG_TO_IMPLEMENT();
+}
+
+/* -------------------------------------------------------------------------- */
+#define INIT_SHAPE_FUNCTIONS(type)                                             \
+  setIntegrationPointsByType<type>(integration_points, ghost_type);            \
+  precomputeShapesOnIntegrationPoints<type>(nodes, ghost_type);                \
+  precomputeShapeDerivativesOnIntegrationPoints<type>(nodes, ghost_type);
+
+template <>
+inline void ShapeStructural<_ek_structural>::initShapeFunctions(
+    const Array<Real> & nodes, const Matrix<Real> & integration_points,
+    const ElementType & type, const GhostType & ghost_type) {
+  AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(INIT_SHAPE_FUNCTIONS);
+}
+
+#undef INIT_SHAPE_FUNCTIONS
+
+/* -------------------------------------------------------------------------- */
+template <>
+template <ElementType type>
+void ShapeStructural<_ek_structural>::precomputeShapesOnIntegrationPoints(
+    const Array<Real> & nodes, const GhostType & ghost_type) {
+  AKANTU_DEBUG_IN();
+
+  const auto & natural_coords = integration_points(type, ghost_type);
+  auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+  auto spatial_dimension = mesh.getSpatialDimension();
+  auto nb_points = integration_points(type, ghost_type).cols();
+  auto nb_element = mesh.getNbElement(type, ghost_type);
+  auto nb_dof = ElementClass<type>::getNbDegreeOfFreedom();
+
+  Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
+  FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type);
+
+  auto itp_type = FEEngine::getInterpolationType(type);
+  if (not shapes.exists(itp_type, ghost_type)) {
+    auto size_of_shapes = this->getShapeSize(type);
+    this->shapes.alloc(0, size_of_shapes, itp_type, ghost_type);
+  }
+
+  auto & shapes_ = this->shapes(itp_type, ghost_type);
+  shapes_.resize(nb_element * nb_points);
+
+  auto x_it = x_el.begin(spatial_dimension, nb_nodes_per_element);
+
+  auto shapes_it = shapes_.begin_reinterpret(
+      nb_dof, nb_dof * nb_nodes_per_element, nb_points, nb_element);
+
+  for (UInt elem = 0; elem < nb_element; ++elem, ++shapes_it, ++x_it) {
+    auto & X = *x_it;
+    auto & N = *shapes_it;
+    ElementClass<type>::computeShapes(natural_coords, N, X);
+  }
+
+  AKANTU_DEBUG_OUT();
+} // namespace akantu
+
+/* -------------------------------------------------------------------------- */
+template <ElementKind kind>
+template <ElementType type>
+void ShapeStructural<kind>::precomputeShapeDerivativesOnIntegrationPoints(
+    const Array<Real> & nodes, const GhostType & ghost_type) {
+  AKANTU_DEBUG_IN();
+
+  const auto & natural_coords = integration_points(type, ghost_type);
+  auto spatial_dimension = mesh.getSpatialDimension();
+  auto natural_spatial_dimension =
+      ElementClass<type>::getNaturalSpaceDimension();
+  auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+  auto nb_points = natural_coords.cols();
+  auto nb_dof = ElementClass<type>::getNbDegreeOfFreedom();
+  auto nb_element = mesh.getNbElement(type, ghost_type);
+
+  auto itp_type = FEEngine::getInterpolationType(type);
+  if (not this->shapes_derivatives.exists(itp_type, ghost_type)) {
+    auto size_of_shapesd = this->getShapeDerivativesSize(type);
+    this->shapes_derivatives.alloc(0, size_of_shapesd, itp_type, ghost_type);
+  }
+
+  Array<Real> x_el(0, spatial_dimension * nb_nodes_per_element);
+  FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type);
+
+  auto & shapesd = this->shapes_derivatives(itp_type, ghost_type);
+  shapesd.resize(nb_element * nb_points);
+
+  auto x_it = x_el.begin(spatial_dimension, nb_nodes_per_element);
+  auto shapesd_it = shapesd.begin_reinterpret(natural_spatial_dimension,
+                                              nb_nodes_per_element * nb_dof,
+                                              nb_points, nb_element);
+
+  for (UInt elem = 0; elem < nb_element; ++elem, ++x_it, ++shapesd_it) {
+    // compute shape derivatives
+    auto & X = *x_it;
+    auto & B = *shapesd_it;
+    ElementClass<type>::computeShapeDerivatives(natural_coords, B, X);
+  }
+
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <ElementKind kind>
+template <ElementType type>
+void ShapeStructural<kind>::interpolateOnIntegrationPoints(
+    const Array<Real> & in_u, Array<Real> & out_uq, UInt nb_dof,
+    const GhostType & ghost_type, const Array<UInt> & filter_elements) const {
+  AKANTU_DEBUG_IN();
+
+  AKANTU_DEBUG_ASSERT(out_uq.getNbComponent() == nb_dof,
+                      "The output array shape is not correct");
+
+  auto itp_type = FEEngine::getInterpolationType(type);
+  const auto & shapes_ = shapes(itp_type, ghost_type);
+
+  auto nb_element = mesh.getNbElement(type, ghost_type);
+  auto nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement();
+  auto nb_quad_points_per_element = integration_points(type, ghost_type).cols();
+
+  Array<Real> u_el(0, nb_nodes_per_element * nb_dof);
+  FEEngine::extractNodalToElementField<type>(mesh, in_u, u_el, ghost_type, filter_elements);
+
+  auto nb_quad_points = nb_quad_points_per_element * u_el.size();
+  out_uq.resize(nb_quad_points);
+
+  auto out_it = out_uq.begin_reinterpret(nb_dof, 1, nb_quad_points_per_element,
+                                         u_el.size());
+  auto shapes_it =
+      shapes_.begin_reinterpret(nb_dof, nb_dof * nb_nodes_per_element,
+                                nb_quad_points_per_element, nb_element);
+  auto u_it = u_el.begin_reinterpret(nb_dof * nb_nodes_per_element, 1,
+                                     nb_quad_points_per_element, u_el.size());
+
+  for_each_elements(nb_element, filter_elements, [&](auto && el) {
+    auto & uq = *out_it;
+    const auto & u = *u_it;
+    auto N = Tensor3<Real>(shapes_it[el]);
+
+    for (auto && q : arange(uq.size(2))) {
+      auto uq_q = Matrix<Real>(uq(q));
+      auto u_q = Matrix<Real>(u(q));
+      auto N_q = Matrix<Real>(N(q));
+
+      uq_q.mul<false, false>(N, u);
+    }
+
+    ++out_it;
+    ++u_it;
+  });
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <ElementKind kind>
+template <ElementType type>
+void ShapeStructural<kind>::gradientOnIntegrationPoints(
+    const Array<Real> & in_u, Array<Real> & out_nablauq,
+    UInt nb_dof, const GhostType & ghost_type,
+    const Array<UInt> & filter_elements) const {
+  AKANTU_DEBUG_IN();
+
+  auto itp_type = FEEngine::getInterpolationType(type);
+  const auto & shapesd = shapes_derivatives(itp_type, ghost_type);
+
+  auto nb_element = mesh.getNbElement(type, ghost_type);
+  auto element_dimension = ElementClass<type>::getSpatialDimension();
+  auto nb_quad_points_per_element = integration_points(type, ghost_type).cols();
+  auto nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement();
+
+  Array<Real> u_el(0, nb_nodes_per_element * nb_dof);
+  FEEngine::extractNodalToElementField<type>(mesh, in_u, u_el,
+                                             ghost_type, filter_elements);
+
+  auto nb_quad_points = nb_quad_points_per_element * u_el.size();
+  out_nablauq.resize(nb_quad_points);
+
+  auto out_it = out_nablauq.begin_reinterpret(element_dimension, 1, nb_quad_points_per_element,
+                                              u_el.size());
+  auto shapesd_it =
+      shapesd.begin_reinterpret(element_dimension, nb_dof * nb_nodes_per_element,
+                                nb_quad_points_per_element, nb_element);
+  auto u_it = u_el.begin_reinterpret(nb_dof * nb_nodes_per_element, 1,
+                                     nb_quad_points_per_element, u_el.size());
+
+  for_each_elements(nb_element, filter_elements, [&](auto && el) {
+    auto & nablau = *out_it;
+    const auto & u = *u_it;
+    auto B = Tensor3<Real>(shapesd_it[el]);
+
+    for (auto && q : arange(nablau.size(2))) {
+      auto nablau_q = Matrix<Real>(uq(q));
+      auto u_q = Matrix<Real>(u(q));
+      auto B_q = Matrix<Real>(N(q));
+
+      nablau_q.mul<false, false>(B, u);
+    }
+
+    ++out_it;
+    ++u_it;
+  });
+
+
+  AKANTU_DEBUG_OUT();
+}
+
+} // namespace akantu
+
+#endif /* __AKANTU_SHAPE_STRUCTURAL_INLINE_IMPL_CC__ */
diff --git a/src/io/model_io.hh b/src/io/model_io.hh
deleted file mode 100644
index f008df2c5..000000000
--- a/src/io/model_io.hh
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * @file   model_io.hh
- *
- * @author Nicolas Richart <nicolas.richart@epfl.ch>
- *
- * @date creation: Fri Jun 18 2010
- * @date last modification: Sun Oct 19 2014
- *
- * @brief  Reader for models (this is deprecated)
- *
- * @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_MODEL_IO_HH__
-#define __AKANTU_MODEL_IO_HH__
-
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "mesh.hh"
-#include "model.hh"
-/* -------------------------------------------------------------------------- */
-
-namespace akantu {
-
-
-
-
-
-class ModelIO {
-  /* ------------------------------------------------------------------------ */
-  /* Constructors/Destructors                                                 */
-  /* ------------------------------------------------------------------------ */
-public:
-  
-  ModelIO();
-  virtual ~ModelIO();
-  
-  /* ------------------------------------------------------------------------ */
-  /* Methods                                                                  */
-  /* ------------------------------------------------------------------------ */
-public:
-  
-  /// read a model from file
-  virtual void read(const std::string & filename, Model & model) = 0;
-
-  /// write a mesh to a file
-  virtual void write(const std::string & filename, const Model & model) = 0;
-
-  
-  /* ------------------------------------------------------------------------ */
-  /* Accessors                                                                */
-  /* ------------------------------------------------------------------------ */
-public:
-  
-  /* ------------------------------------------------------------------------ */
-  /* Class Members                                                            */
-  /* ------------------------------------------------------------------------ */
-private:
-  
-};
-
-} // akantu
-
-#endif /* __AKANTU_MODEL_IO_HH__ */
diff --git a/src/io/model_io/model_io_ibarras.cc b/src/io/model_io/model_io_ibarras.cc
deleted file mode 100644
index e30831808..000000000
--- a/src/io/model_io/model_io_ibarras.cc
+++ /dev/null
@@ -1,313 +0,0 @@
-/**
- * @file   model_io_ibarras.cc
- *
- * @author Fabian Barras <fabian.barras@epfl.ch>
- *
- * @date creation: Thu Feb 21 2013
- * @date last modification: Fri Jan 22 2016
- *
- * @brief  Mesh Reader specially created for Wood's Tower analysis performed by
- * the Institute I-Barras
- *
- * @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 <fstream>
-#include <iostream>
-
-/* -------------------------------------------------------------------------- */
-#include "model_io_ibarras.hh"
-#include "static_communicator.hh"
-#include "aka_math.hh"
-#include "static_communicator.hh"
-#include "sparse_matrix.hh"
-#include "solver.hh"
-#include "integration_scheme_2nd_order.hh"
-/* -------------------------------------------------------------------------- */
-#include <string.h>
-/* -------------------------------------------------------------------------- */
-#include <stdio.h>
-
-namespace akantu {
-
-/* -------------------------------------------------------------------------- */
-/*   Methods Implentations                                                    */
-/* -------------------------------------------------------------------------- */
-
-void ModelIOIBarras::read(const std::string & filename, Model & mod) {
-
-  if (!dynamic_cast<StructuralMechanicsModel *>(&mod)) {
-    AKANTU_DEBUG_ERROR("");
-  }
-
-  StructuralMechanicsModel & model =
-      static_cast<StructuralMechanicsModel &>(mod);
-  Mesh * mesh = new Mesh(3);
-
-  std::ifstream infile;
-  infile.open(filename.c_str());
-
-  std::string line;
-  UInt current_line = 0;
-
-  if (!infile.good()) {
-    AKANTU_DEBUG_ERROR("Cannot open file " << filename);
-  }
-
-  // Get Nodes Position
-  std::getline(infile, line);
-  current_line++;
-  std::stringstream sstr(line);
-  UInt nb_nodes;
-  sstr >> nb_nodes;
-
-  const UInt spatial_dimension = 3;
-  Real coord[spatial_dimension];
-  Real * temp_nodes = new Real[nb_nodes * spatial_dimension];
-  UInt * connect_to_akantu = new UInt[nb_nodes];
-  std::fill_n(connect_to_akantu, 0, nb_nodes);
-  std::fill_n(temp_nodes, 0., nb_nodes * spatial_dimension);
-  for (UInt i = 0; i < nb_nodes; ++i) {
-    UInt offset = i * spatial_dimension;
-
-    std::getline(infile, line);
-    std::stringstream sstr_node(line);
-    sstr_node >> coord[0] >> coord[1] >> coord[2];
-    current_line++;
-
-    /// read the coordinates of structural nodes and help nodes
-    for (UInt j = 0; j < spatial_dimension; ++j)
-      temp_nodes[offset + j] = coord[j];
-  }
-
-  // Get Connectivities
-  std::getline(infile, line);
-  current_line++;
-  std::stringstream sstr_elem(line);
-  UInt nb_elements;
-  sstr_elem >> nb_elements;
-
-  mesh->addConnectivityType(_bernoulli_beam_3);
-  Array<UInt> & connectivity =
-      const_cast<Array<UInt> &>(mesh->getConnectivity(_bernoulli_beam_3));
-
-  connectivity.resize(nb_elements);
-
-  UInt nonodes[2];
-  UInt nb_struct_nodes = 1;
-  for (UInt i = 0; i < nb_elements; ++i) {
-
-    std::getline(infile, line);
-    std::stringstream sstr_element(line);
-    sstr_element >> nonodes[0] >> nonodes[1];
-    current_line++;
-
-    /// read the connectivities
-    for (UInt j = 0; j < 2; ++j) {
-
-      if (connect_to_akantu[nonodes[j] - 1] == 0) {
-        connect_to_akantu[nonodes[j] - 1] = nb_struct_nodes;
-        ++nb_struct_nodes;
-      }
-      connectivity(i, j) = connect_to_akantu[nonodes[j] - 1] - 1;
-    }
-  }
-  nb_struct_nodes -= 1;
-
-  /// read the coordinates of structural nodes
-  Array<Real> & nodes = const_cast<Array<Real> &>(mesh->getNodes());
-  nodes.resize(nb_struct_nodes);
-
-  for (UInt k = 0; k < nb_nodes; ++k) {
-    if (connect_to_akantu[k] != 0) {
-      for (UInt j = 0; j < spatial_dimension; ++j)
-        nodes(connect_to_akantu[k] - 1, j) =
-            temp_nodes[k * spatial_dimension + j];
-    }
-  }
-
-  // MeshPartitionScotch partition(*mesh, spatial_dimension);
-  // partition.reorder();
-
-  /// Apply Boundaries
-  model.registerFEEngineObject<StructuralMechanicsModel::MyFEEngineType>(
-      "StructuralMechanicsModel", *mesh, spatial_dimension);
-
-  model.initModel();
-
-  model.initArrays();
-
-  Array<bool> & blocked_dofs = model.getBlockedDOFs();
-
-  std::getline(infile, line);
-  std::stringstream sstr_nb_boundaries(line);
-  UInt nb_boundaries;
-  sstr_nb_boundaries >> nb_boundaries;
-  current_line++;
-
-  for (UInt i = 0; i < nb_boundaries; ++i) {
-    std::getline(infile, line);
-    std::stringstream sstr_boundary(line);
-    UInt boundnary_node;
-    sstr_boundary >> boundnary_node;
-    current_line++;
-
-    for (UInt j = 0; j < spatial_dimension; ++j)
-      blocked_dofs(connect_to_akantu[boundnary_node - 1] - 1, j) = true;
-  }
-
-  /// Define Materials
-
-  std::getline(infile, line);
-  std::stringstream sstr_nb_materials(line);
-  UInt nb_materials;
-  sstr_nb_materials >> nb_materials;
-  current_line++;
-
-  for (UInt i = 0; i < nb_materials; ++i) {
-
-    std::getline(infile, line);
-    std::stringstream sstr_material(line);
-    Real material[6];
-    sstr_material >> material[0] >> material[1] >> material[2] >> material[3] >>
-        material[4] >> material[5];
-    current_line++;
-
-    StructuralMaterial mat;
-    mat.E = material[0];
-    mat.GJ = material[1] * material[2];
-    mat.Iy = material[3];
-    mat.Iz = material[4];
-    mat.A = material[5];
-
-    model.addMaterial(mat);
-  }
-
-  /// Apply normals and Material TO IMPLEMENT
-
-  UInt property[2];
-
-  Array<UInt> & element_material = model.getElementMaterial(_bernoulli_beam_3);
-
-  mesh->initNormals();
-  Array<Real> & normals =
-      const_cast<Array<Real> &>(mesh->getNormals(_bernoulli_beam_3));
-  normals.resize(nb_elements);
-
-  for (UInt i = 0; i < nb_elements; ++i) {
-
-    std::getline(infile, line);
-    std::stringstream sstr_properties(line);
-    sstr_properties >> property[0] >> property[1];
-    current_line++;
-
-    /// Assign material
-    element_material(i) = property[0] - 1;
-
-    /// Compute normals
-
-    Real x[3];
-    Real v[3];
-    Real w[3];
-    Real n[3];
-
-    if (property[1] == 0) {
-      for (UInt j = 0; j < spatial_dimension; ++j) {
-        x[j] = nodes(connectivity(i, 1), j) - nodes(connectivity(i, 0), j);
-      }
-      n[0] = x[1];
-      n[1] = -x[0];
-      n[2] = 0.;
-
-    }
-
-    else {
-      for (UInt j = 0; j < spatial_dimension; ++j) {
-        x[j] = nodes(connectivity(i, 1), j) - nodes(connectivity(i, 0), j);
-        v[j] = nodes(connectivity(i, 1), j) -
-               temp_nodes[(property[1] - 1) * spatial_dimension + j];
-        Math::vectorProduct3(x, v, w);
-        Math::vectorProduct3(x, w, n);
-      }
-    }
-
-    Math::normalize3(n);
-    for (UInt j = 0; j < spatial_dimension; ++j) {
-      normals(i, j) = n[j];
-    }
-  }
-
-  model.computeRotationMatrix(_bernoulli_beam_3);
-  infile.close();
-}
-/* -------------------------------------------------------------------------- */
-void ModelIOIBarras::assign_sets(const std::string & filename,
-                                 StructuralMechanicsModel & model) {
-
-  std::ifstream infile;
-  infile.open(filename.c_str());
-
-  std::string line;
-  UInt current_line = 0;
-
-  if (!infile.good()) {
-    AKANTU_DEBUG_ERROR("Cannot open file " << filename);
-  }
-
-  // Define Sets of Beams
-
-  Array<UInt> & set_ID = model.getSet_ID(_bernoulli_beam_3);
-  set_ID.clear();
-
-  std::getline(infile, line);
-  std::stringstream sstr_nb_sets(line);
-  UInt nb_sets;
-  sstr_nb_sets >> nb_sets;
-  current_line++;
-
-  UInt no_element[2];
-
-  for (UInt i = 0; i < nb_sets; ++i) {
-    std::getline(infile, line);
-    std::stringstream sstr_set(line);
-    sstr_set >> no_element[0];
-    no_element[1] = no_element[0];
-    sstr_set >> no_element[1];
-
-    while (no_element[0] != 0) {
-
-      for (UInt j = no_element[0] - 1; j < no_element[1]; ++j) {
-        set_ID(j) = i + 1;
-      }
-      std::getline(infile, line);
-      std::stringstream sstr_sets(line);
-      sstr_sets >> no_element[0];
-      no_element[1] = no_element[0];
-      sstr_sets >> no_element[1];
-    }
-  }
-}
-
-} // akantu
diff --git a/src/io/model_io/model_io_ibarras.hh b/src/io/model_io/model_io_ibarras.hh
deleted file mode 100644
index b86399428..000000000
--- a/src/io/model_io/model_io_ibarras.hh
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * @file   model_io_ibarras.hh
- *
- * @author Fabian Barras <fabian.barras@epfl.ch>
- *
- * @date creation: Fri Jun 18 2010
- * @date last modification: Sun Oct 19 2014
- *
- * @brief  ModelIO implementation for IBarras input files
- *
- * @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_MODEL_IO_IBARRAS_HH__
-#define __AKANTU_MODEL_IO_IBARRAS_HH__
-
-/* -------------------------------------------------------------------------- */
-#include "model_io.hh"
-#include "structural_mechanics_model.hh"
-/* -------------------------------------------------------------------------- */
-
-namespace akantu {
-
-class ModelIOIBarras : public ModelIO {
-  /* ------------------------------------------------------------------------ */
-  /* Constructors/Destructors                                                 */
-  /* ------------------------------------------------------------------------ */
-public:
-  ModelIOIBarras(){};
-  virtual ~ModelIOIBarras(){};
-
-  /* ------------------------------------------------------------------------ */
-  /* Methods                                                                  */
-  /* ------------------------------------------------------------------------ */
-public:
-  /// read a model from the file
-  virtual void read(const std::string & filename, Model & model);
-
-  /// assign sets of member to an already constructed model
-  virtual void assign_sets(const std::string & filename,
-                           StructuralMechanicsModel & model);
-};
-
-} // akantu
-
-#endif /* __AKANTU_MODEL_IO_IBARRAS_HH__ */
diff --git a/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_2.hh b/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_2.hh
new file mode 100644
index 000000000..e70bd0a69
--- /dev/null
+++ b/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_2.hh
@@ -0,0 +1,206 @@
+/**
+ * @file   structural_element_bernoulli_beam_2.hh
+ *
+ * @author Fabian Barras <fabian.barras@epfl.ch>
+ * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
+ * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ * @author Damien Spielmann <damien.spielmann@epfl.ch>
+ *
+ * @date creation  Tue Sep 19 2017
+ *
+ * @brief Specific functions for bernoulli beam 2d
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free  software: you can redistribute it and/or  modify it under the
+ * terms  of the  GNU Lesser  General Public  License as  published by  the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
+ * details.
+ *
+ * You should  have received  a copy  of the GNU  Lesser General  Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+/* -------------------------------------------------------------------------- */
+#ifndef __AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_2_HH__
+#define __AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_2_HH__
+
+namespace akantu {
+
+inline UInt
+StructuralMechanicsModel::getTangentStiffnessVoigtSize<_bernoulli_beam_2>() {
+  return 2;
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+inline void StructuralMechanicsModel::assembleMass<_bernoulli_beam_2>() {
+  AKANTU_DEBUG_IN();
+
+  GhostType ghost_type = _not_ghost;
+  ElementType type = _bernoulli_beam_2;
+  MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>();
+  UInt nb_element = getFEEngine().getMesh().getNbElement(type);
+  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+  UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type);
+  UInt nb_fields_to_interpolate =
+      getTangentStiffnessVoigtSize<_bernoulli_beam_2>();
+
+  UInt nt_n_field_size = nb_degree_of_freedom * nb_nodes_per_element;
+
+  Array<Real> * n =
+      new Array<Real>(nb_element * nb_quadrature_points,
+                      nb_fields_to_interpolate * nt_n_field_size, "N");
+  n->clear();
+  Array<Real> * rho_field =
+      new Array<Real>(nb_element * nb_quadrature_points, "Rho");
+  rho_field->clear();
+  computeRho(*rho_field, type, _not_ghost);
+
+  bool sign = true;
+
+  /* ------------------------------------------------------------------------ */
+  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n,
+                          0, 0, 0, sign, ghost_type); // Ni ui -> u
+  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n,
+                          1, 1, 1, sign, ghost_type); // Mi vi -> v
+  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n,
+                          2, 2, 1, sign, ghost_type); // Li Theta_i -> v
+  /* ------------------------------------------------------------------------ */
+  fem.assembleFieldMatrix(*rho_field, nb_degree_of_freedom, *mass_matrix, n,
+                          rotation_matrix, type, ghost_type);
+
+  delete n;
+  delete rho_field;
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+void StructuralMechanicsModel::computeRotationMatrix<_bernoulli_beam_2>(
+    Array<Real> & rotations) {
+
+  ElementType type = _bernoulli_beam_2;
+  Mesh & mesh = getFEEngine().getMesh();
+  UInt nb_element = mesh.getNbElement(type);
+
+  Array<UInt>::iterator<Vector<UInt> > connec_it =
+      mesh.getConnectivity(type).begin(2);
+  Array<Real>::vector_iterator nodes_it =
+      mesh.getNodes().begin(spatial_dimension);
+  Array<Real>::matrix_iterator R_it =
+      rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom);
+
+  for (UInt e = 0; e < nb_element; ++e, ++R_it, ++connec_it) {
+    Matrix<Real> & R = *R_it;
+    Vector<UInt> & connec = *connec_it;
+
+    Vector<Real> x2;
+    x2 = nodes_it[connec(1)]; // X2
+    Vector<Real> x1;
+    x1 = nodes_it[connec(0)]; // X1
+
+    Real le = x1.distance(x2);
+    Real c = (x2(0) - x1(0)) / le;
+    Real s = (x2(1) - x1(1)) / le;
+
+    /// Definition of the rotation matrix
+    R(0, 0) = c;
+    R(0, 1) = s;
+    R(0, 2) = 0.;
+    R(1, 0) = -s;
+    R(1, 1) = c;
+    R(1, 2) = 0.;
+    R(2, 0) = 0.;
+    R(2, 1) = 0.;
+    R(2, 2) = 1.;
+  }
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+void StructuralMechanicsModel::computeTangentModuli<_bernoulli_beam_2>(
+    Array<Real> & tangent_moduli) {
+  UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_2);
+  UInt nb_quadrature_points =
+      getFEEngine().getNbIntegrationPoints(_bernoulli_beam_2);
+  UInt tangent_size = 2;
+
+  Array<Real>::matrix_iterator D_it =
+      tangent_moduli.begin(tangent_size, tangent_size);
+  Array<UInt> & el_mat = element_material(_bernoulli_beam_2, _not_ghost);
+
+  for (UInt e = 0; e < nb_element; ++e) {
+    UInt mat = el_mat(e);
+    Real E = materials[mat].E;
+    Real A = materials[mat].A;
+    Real I = materials[mat].I;
+    for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it) {
+      Matrix<Real> & D = *D_it;
+      D(0, 0) = E * A;
+      D(1, 1) = E * I;
+    }
+  }
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix<
+    _bernoulli_beam_2>(Array<Real> & b, bool) {
+  UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_2);
+  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_bernoulli_beam_2);
+  UInt nb_quadrature_points =
+      getFEEngine().getNbIntegrationPoints(_bernoulli_beam_2);
+
+  MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>();
+  Array<Real>::const_vector_iterator shape_Np =
+      fem.getShapesDerivatives(_bernoulli_beam_2, _not_ghost, 0)
+          .begin(nb_nodes_per_element);
+  Array<Real>::const_vector_iterator shape_Mpp =
+      fem.getShapesDerivatives(_bernoulli_beam_2, _not_ghost, 1)
+          .begin(nb_nodes_per_element);
+  Array<Real>::const_vector_iterator shape_Lpp =
+      fem.getShapesDerivatives(_bernoulli_beam_2, _not_ghost, 2)
+          .begin(nb_nodes_per_element);
+
+  UInt tangent_size = getTangentStiffnessVoigtSize<_bernoulli_beam_2>();
+  UInt bt_d_b_size = nb_nodes_per_element * nb_degree_of_freedom;
+  b.clear();
+  Array<Real>::matrix_iterator B_it = b.begin(tangent_size, bt_d_b_size);
+
+  for (UInt e = 0; e < nb_element; ++e) {
+    for (UInt q = 0; q < nb_quadrature_points; ++q) {
+      Matrix<Real> & B = *B_it;
+      const Vector<Real> & Np = *shape_Np;
+      const Vector<Real> & Lpp = *shape_Lpp;
+      const Vector<Real> & Mpp = *shape_Mpp;
+
+      B(0, 0) = Np(0);
+      B(0, 3) = Np(1);
+
+      B(1, 1) = Mpp(0);
+      B(1, 2) = Lpp(0);
+      B(1, 4) = Mpp(1);
+      B(1, 5) = Lpp(1);
+
+      ++B_it;
+      ++shape_Np;
+      ++shape_Mpp;
+      ++shape_Lpp;
+    }
+
+    // ++R_it;
+  }
+}
+
+}  // akantu
+
+#endif /* __AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_2_HH__ */
diff --git a/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_3.hh b/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_3.hh
new file mode 100644
index 000000000..65a0f7246
--- /dev/null
+++ b/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_3.hh
@@ -0,0 +1,250 @@
+/**
+ * @file   structural_element_bernoulli_beam_3.hh
+ *
+ * @author Fabian Barras <fabian.barras@epfl.ch>
+ * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
+ * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ * @author Damien Spielmann <damien.spielmann@epfl.ch>
+ *
+ * @date creation  Tue Sep 19 2017
+ *
+ * @brief Specific functions for bernoulli beam 3d
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free  software: you can redistribute it and/or  modify it under the
+ * terms  of the  GNU Lesser  General Public  License as  published by  the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
+ * details.
+ *
+ * You should  have received  a copy  of the GNU  Lesser General  Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+/* -------------------------------------------------------------------------- */
+#ifndef __AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_3_HH__
+#define __AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_3_HH__
+
+namespace akantu {
+
+inline UInt
+StructuralMechanicsModel::getTangentStiffnessVoigtSize<_bernoulli_beam_3>() {
+  return 4;
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+inline void StructuralMechanicsModel::assembleMass<_bernoulli_beam_3>() {
+  AKANTU_DEBUG_IN();
+
+  GhostType ghost_type = _not_ghost;
+  ElementType type = _bernoulli_beam_3;
+  MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>();
+  UInt nb_element = getFEEngine().getMesh().getNbElement(type);
+  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+  UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type);
+  UInt nb_fields_to_interpolate =
+      getTangentStiffnessVoigtSize<_bernoulli_beam_3>();
+
+  UInt nt_n_field_size = nb_degree_of_freedom * nb_nodes_per_element;
+
+  Array<Real> * n =
+      new Array<Real>(nb_element * nb_quadrature_points,
+                      nb_fields_to_interpolate * nt_n_field_size, "N");
+  n->clear();
+  Array<Real> * rho_field =
+      new Array<Real>(nb_element * nb_quadrature_points, "Rho");
+  rho_field->clear();
+  computeRho(*rho_field, type, _not_ghost);
+
+  /* --------------------------------------------------------------------------
+   */
+  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n,
+                          0, 0, 0, true, ghost_type); // Ni ui ->         u
+
+  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n,
+                          1, 1, 1, true, ghost_type); // Mi vi ->         v
+  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n,
+                          2, 5, 1, true, ghost_type); // Li Theta_z_i ->  v
+
+  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n,
+                          1, 2, 2, true, ghost_type); // Mi wi ->        w
+  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n,
+                          2, 4, 2, false, ghost_type); // -Li Theta_y_i ->  w
+
+  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n,
+                          0, 3, 3, true, ghost_type); // Ni Theta_x_i->Theta_x
+  /* --------------------------------------------------------------------------
+   */
+
+  fem.assembleFieldMatrix(*rho_field, nb_degree_of_freedom, *mass_matrix, n,
+                          rotation_matrix, type, ghost_type);
+
+  delete n;
+  delete rho_field;
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+void StructuralMechanicsModel::computeRotationMatrix<_bernoulli_beam_3>(
+    Array<Real> & rotations) {
+  ElementType type = _bernoulli_beam_3;
+  Mesh & mesh = getFEEngine().getMesh();
+  UInt nb_element = mesh.getNbElement(type);
+
+  Array<Real>::vector_iterator n_it =
+      mesh.getNormals(type).begin(spatial_dimension);
+  Array<UInt>::iterator<Vector<UInt> > connec_it =
+      mesh.getConnectivity(type).begin(2);
+  Array<Real>::vector_iterator nodes_it =
+      mesh.getNodes().begin(spatial_dimension);
+
+  Matrix<Real> Pe(spatial_dimension, spatial_dimension);
+  Matrix<Real> Pg(spatial_dimension, spatial_dimension);
+  Matrix<Real> inv_Pg(spatial_dimension, spatial_dimension);
+  Vector<Real> x_n(spatial_dimension); // x vect n
+
+  Array<Real>::matrix_iterator R_it =
+      rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom);
+
+  for (UInt e = 0; e < nb_element; ++e, ++n_it, ++connec_it, ++R_it) {
+    Vector<Real> & n = *n_it;
+    Matrix<Real> & R = *R_it;
+    Vector<UInt> & connec = *connec_it;
+
+    Vector<Real> x;
+    x = nodes_it[connec(1)]; // X2
+    Vector<Real> y;
+    y = nodes_it[connec(0)]; // X1
+
+    Real l = x.distance(y);
+    x -= y; // X2 - X1
+    x_n.crossProduct(x, n);
+
+    Pe.eye();
+    Pe(0, 0) *= l;
+    Pe(1, 1) *= -l;
+
+    Pg(0, 0) = x(0);
+    Pg(0, 1) = x_n(0);
+    Pg(0, 2) = n(0);
+    Pg(1, 0) = x(1);
+    Pg(1, 1) = x_n(1);
+    Pg(1, 2) = n(1);
+    Pg(2, 0) = x(2);
+    Pg(2, 1) = x_n(2);
+    Pg(2, 2) = n(2);
+
+    inv_Pg.inverse(Pg);
+
+    Pe *= inv_Pg;
+    for (UInt i = 0; i < spatial_dimension; ++i) {
+      for (UInt j = 0; j < spatial_dimension; ++j) {
+        R(i, j) = Pe(i, j);
+        R(i + spatial_dimension, j + spatial_dimension) = Pe(i, j);
+      }
+    }
+  }
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+void StructuralMechanicsModel::computeTangentModuli<_bernoulli_beam_3>(
+    Array<Real> & tangent_moduli) {
+  UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_3);
+  UInt nb_quadrature_points =
+      getFEEngine().getNbIntegrationPoints(_bernoulli_beam_3);
+  UInt tangent_size = 4;
+
+  Array<Real>::matrix_iterator D_it =
+      tangent_moduli.begin(tangent_size, tangent_size);
+
+  for (UInt e = 0; e < nb_element; ++e) {
+    UInt mat = element_material(_bernoulli_beam_3, _not_ghost)(e);
+    Real E = materials[mat].E;
+    Real A = materials[mat].A;
+    Real Iz = materials[mat].Iz;
+    Real Iy = materials[mat].Iy;
+    Real GJ = materials[mat].GJ;
+    for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it) {
+      Matrix<Real> & D = *D_it;
+      D(0, 0) = E * A;
+      D(1, 1) = E * Iz;
+      D(2, 2) = E * Iy;
+      D(3, 3) = GJ;
+    }
+  }
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix<
+    _bernoulli_beam_3>(Array<Real> & b, bool) {
+  MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>();
+
+  UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_3);
+  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_bernoulli_beam_3);
+  UInt nb_quadrature_points =
+      getFEEngine().getNbIntegrationPoints(_bernoulli_beam_3);
+
+  Array<Real>::const_vector_iterator shape_Np =
+      fem.getShapesDerivatives(_bernoulli_beam_3, _not_ghost, 0)
+          .begin(nb_nodes_per_element);
+  Array<Real>::const_vector_iterator shape_Mpp =
+      fem.getShapesDerivatives(_bernoulli_beam_3, _not_ghost, 1)
+          .begin(nb_nodes_per_element);
+  Array<Real>::const_vector_iterator shape_Lpp =
+      fem.getShapesDerivatives(_bernoulli_beam_3, _not_ghost, 2)
+          .begin(nb_nodes_per_element);
+
+  UInt tangent_size = getTangentStiffnessVoigtSize<_bernoulli_beam_3>();
+  UInt bt_d_b_size = nb_nodes_per_element * nb_degree_of_freedom;
+
+  b.clear();
+
+  Array<Real>::matrix_iterator B_it = b.begin(tangent_size, bt_d_b_size);
+
+  for (UInt e = 0; e < nb_element; ++e) {
+    for (UInt q = 0; q < nb_quadrature_points; ++q) {
+      Matrix<Real> & B = *B_it;
+
+      const Vector<Real> & Np = *shape_Np;
+      const Vector<Real> & Lpp = *shape_Lpp;
+      const Vector<Real> & Mpp = *shape_Mpp;
+
+      B(0, 0) = Np(0);
+      B(0, 6) = Np(1);
+
+      B(1, 1) = Mpp(0);
+      B(1, 5) = Lpp(0);
+      B(1, 7) = Mpp(1);
+      B(1, 11) = Lpp(1);
+
+      B(2, 2) = Mpp(0);
+      B(2, 4) = -Lpp(0);
+      B(2, 8) = Mpp(1);
+      B(2, 10) = -Lpp(1);
+
+      B(3, 3) = Np(0);
+      B(3, 9) = Np(1);
+
+      ++B_it;
+      ++shape_Np;
+      ++shape_Mpp;
+      ++shape_Lpp;
+    }
+  }
+}
+
+}  // akantu
+
+#endif /* __AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_BEAM_3_HH__ */
diff --git a/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_kirchhoff_shell.hh b/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_kirchhoff_shell.hh
new file mode 100644
index 000000000..68a9900dd
--- /dev/null
+++ b/src/model/structural_mechanics/structural_elements/structural_element_bernoulli_beam_kirchhoff_shell.hh
@@ -0,0 +1,250 @@
+/**
+ * @file   structural_element_bernoulli_kirchhoff_shell.hh
+ *
+ * @author Fabian Barras <fabian.barras@epfl.ch>
+ * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
+ * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ * @author Damien Spielmann <damien.spielmann@epfl.ch>
+ *
+ * @date creation  Tue Sep 19 2017
+ *
+ * @brief Specific functions for bernoulli kirchhoff shell
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free  software: you can redistribute it and/or  modify it under the
+ * terms  of the  GNU Lesser  General Public  License as  published by  the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
+ * details.
+ *
+ * You should  have received  a copy  of the GNU  Lesser General  Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+/* -------------------------------------------------------------------------- */
+#ifndef __AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_KIRCHHOFF_SHELL_HH__
+#define __AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_KIRCHHOFF_SHELL_HH__
+
+namespace akantu {
+
+inline UInt
+StructuralMechanicsModel::getTangentStiffnessVoigtSize<_bernoulli_kirchhoff_shell>() {
+  return 6;
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+inline void StructuralMechanicsModel::assembleMass<_kirchhoff_shell>() {
+
+  AKANTU_DEBUG_TO_IMPLEMENT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+void StructuralMechanicsModel::computeRotationMatrix<_kirchhoff_shell>(
+    Array<Real> & rotations) {
+  ElementType type = _kirchhoff_shell;
+  Mesh & mesh = getFEEngine().getMesh();
+  UInt nb_element = mesh.getNbElement(type);
+
+  Array<UInt>::iterator<Vector<UInt> > connec_it =
+      mesh.getConnectivity(type).begin(3);
+  Array<Real>::vector_iterator nodes_it =
+      mesh.getNodes().begin(spatial_dimension);
+
+  Matrix<Real> Pe(spatial_dimension, spatial_dimension);
+  Matrix<Real> Pg(spatial_dimension, spatial_dimension);
+  Matrix<Real> inv_Pg(spatial_dimension, spatial_dimension);
+
+  Array<Real>::matrix_iterator R_it =
+      rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom);
+
+  for (UInt e = 0; e < nb_element; ++e, ++connec_it, ++R_it) {
+
+    Pe.eye();
+
+    Matrix<Real> & R = *R_it;
+    Vector<UInt> & connec = *connec_it;
+
+    Vector<Real> x2;
+    x2 = nodes_it[connec(1)]; // X2
+    Vector<Real> x1;
+    x1 = nodes_it[connec(0)]; // X1
+    Vector<Real> x3;
+    x3 = nodes_it[connec(2)]; // X3
+
+    Vector<Real> Pg_col_1 = x2 - x1;
+
+    Vector<Real> Pg_col_2 = x3 - x1;
+
+    Vector<Real> Pg_col_3(spatial_dimension);
+    Pg_col_3.crossProduct(Pg_col_1, Pg_col_2);
+
+    for (UInt i = 0; i < spatial_dimension; ++i) {
+      Pg(i, 0) = Pg_col_1(i);
+      Pg(i, 1) = Pg_col_2(i);
+      Pg(i, 2) = Pg_col_3(i);
+    }
+
+    inv_Pg.inverse(Pg);
+    // Pe *= inv_Pg;
+    Pe.eye();
+
+    for (UInt i = 0; i < spatial_dimension; ++i) {
+      for (UInt j = 0; j < spatial_dimension; ++j) {
+        R(i, j) = Pe(i, j);
+        R(i + spatial_dimension, j + spatial_dimension) = Pe(i, j);
+      }
+    }
+  }
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+void StructuralMechanicsModel::computeTangentModuli<_bernoulli_beam_3>(
+    Array<Real> & tangent_moduli) {
+  UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_3);
+  UInt nb_quadrature_points =
+      getFEEngine().getNbIntegrationPoints(_bernoulli_beam_3);
+  UInt tangent_size = 4;
+
+  Array<Real>::matrix_iterator D_it =
+      tangent_moduli.begin(tangent_size, tangent_size);
+
+  for (UInt e = 0; e < nb_element; ++e) {
+    UInt mat = element_material(_bernoulli_beam_3, _not_ghost)(e);
+    Real E = materials[mat].E;
+    Real A = materials[mat].A;
+    Real Iz = materials[mat].Iz;
+    Real Iy = materials[mat].Iy;
+    Real GJ = materials[mat].GJ;
+    for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it) {
+      Matrix<Real> & D = *D_it;
+      D(0, 0) = E * A;
+      D(1, 1) = E * Iz;
+      D(2, 2) = E * Iy;
+      D(3, 3) = GJ;
+    }
+  }
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix<
+    _kirchhoff_shell>(Array<Real> & b, __attribute__((unused)) bool local) {
+  MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>();
+
+  UInt nb_element = getFEEngine().getMesh().getNbElement(_kirchhoff_shell);
+  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_kirchhoff_shell);
+  UInt nb_quadrature_points =
+      getFEEngine().getNbIntegrationPoints(_kirchhoff_shell);
+
+  Array<Real>::const_matrix_iterator shape_Np =
+      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 0)
+          .begin(2, nb_nodes_per_element);
+  Array<Real>::const_matrix_iterator shape_Nx1p =
+      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 1)
+          .begin(2, nb_nodes_per_element);
+  Array<Real>::const_matrix_iterator shape_Nx2p =
+      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 2)
+          .begin(2, nb_nodes_per_element);
+  Array<Real>::const_matrix_iterator shape_Nx3p =
+      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 3)
+          .begin(2, nb_nodes_per_element);
+  Array<Real>::const_matrix_iterator shape_Ny1p =
+      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 4)
+          .begin(2, nb_nodes_per_element);
+  Array<Real>::const_matrix_iterator shape_Ny2p =
+      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 5)
+          .begin(2, nb_nodes_per_element);
+  Array<Real>::const_matrix_iterator shape_Ny3p =
+      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 6)
+          .begin(2, nb_nodes_per_element);
+
+  UInt tangent_size = getTangentStiffnessVoigtSize<_kirchhoff_shell>();
+  UInt bt_d_b_size = nb_nodes_per_element * nb_degree_of_freedom;
+
+  b.clear();
+
+  Array<Real>::matrix_iterator B_it = b.begin(tangent_size, bt_d_b_size);
+
+  for (UInt e = 0; e < nb_element; ++e) {
+    for (UInt q = 0; q < nb_quadrature_points; ++q) {
+      Matrix<Real> & B = *B_it;
+
+      const Matrix<Real> & Np = *shape_Np;
+      const Matrix<Real> & Nx1p = *shape_Nx1p;
+      const Matrix<Real> & Nx2p = *shape_Nx2p;
+      const Matrix<Real> & Nx3p = *shape_Nx3p;
+      const Matrix<Real> & Ny1p = *shape_Ny1p;
+      const Matrix<Real> & Ny2p = *shape_Ny2p;
+      const Matrix<Real> & Ny3p = *shape_Ny3p;
+
+      B(0, 0) = Np(0, 0);
+      B(0, 6) = Np(0, 1);
+      B(0, 12) = Np(0, 2);
+
+      B(1, 1) = Np(1, 0);
+      B(1, 7) = Np(1, 1);
+      B(1, 13) = Np(1, 2);
+
+      B(2, 0) = Np(1, 0);
+      B(2, 1) = Np(0, 0);
+      B(2, 6) = Np(1, 1);
+      B(2, 7) = Np(0, 1);
+      B(2, 12) = Np(1, 2);
+      B(2, 13) = Np(0, 2);
+
+      B(3, 2) = Nx1p(0, 0);
+      B(3, 3) = Nx2p(0, 0);
+      B(3, 4) = Nx3p(0, 0);
+      B(3, 8) = Nx1p(0, 1);
+      B(3, 9) = Nx2p(0, 1);
+      B(3, 10) = Nx3p(0, 1);
+      B(3, 14) = Nx1p(0, 2);
+      B(3, 15) = Nx2p(0, 2);
+      B(3, 16) = Nx3p(0, 2);
+
+      B(4, 2) = Ny1p(1, 0);
+      B(4, 3) = Ny2p(1, 0);
+      B(4, 4) = Ny3p(1, 0);
+      B(4, 8) = Ny1p(1, 1);
+      B(4, 9) = Ny2p(1, 1);
+      B(4, 10) = Ny3p(1, 1);
+      B(4, 14) = Ny1p(1, 2);
+      B(4, 15) = Ny2p(1, 2);
+      B(4, 16) = Ny3p(1, 2);
+
+      B(5, 2) = Nx1p(1, 0) + Ny1p(0, 0);
+      B(5, 3) = Nx2p(1, 0) + Ny2p(0, 0);
+      B(5, 4) = Nx3p(1, 0) + Ny3p(0, 0);
+      B(5, 8) = Nx1p(1, 1) + Ny1p(0, 1);
+      B(5, 9) = Nx2p(1, 1) + Ny2p(0, 1);
+      B(5, 10) = Nx3p(1, 1) + Ny3p(0, 1);
+      B(5, 14) = Nx1p(1, 2) + Ny1p(0, 2);
+      B(5, 15) = Nx2p(1, 2) + Ny2p(0, 2);
+      B(5, 16) = Nx3p(1, 2) + Ny3p(0, 2);
+
+      ++B_it;
+      ++shape_Np;
+      ++shape_Nx1p;
+      ++shape_Nx2p;
+      ++shape_Nx3p;
+      ++shape_Ny1p;
+      ++shape_Ny2p;
+      ++shape_Ny3p;
+    }
+  }
+}
+
+}  // akantu
+
+#endif /* __AKANTU_STRUCTURAL_ELEMENT_BERNOULLI_KIRCHHOFF_SHELL_HH__ */
diff --git a/src/model/structural_mechanics/structural_mechanics_model.cc b/src/model/structural_mechanics/structural_mechanics_model.cc
index d9666b590..e54ec05f2 100644
--- a/src/model/structural_mechanics/structural_mechanics_model.cc
+++ b/src/model/structural_mechanics/structural_mechanics_model.cc
@@ -1,1225 +1,326 @@
 /**
  * @file   structural_mechanics_model.cc
  *
  * @author Fabian Barras <fabian.barras@epfl.ch>
  * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Damien Spielmann <damien.spielmann@epfl.ch>
  *
  * @date creation: Fri Jul 15 2011
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  Model implementation for StucturalMechanics 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 "structural_mechanics_model.hh"
-#include "group_manager_inline_impl.cc"
-#include "dumpable_inline_impl.hh"
-#include "aka_math.hh"
-#include "integration_scheme_2nd_order.hh"
-#include "static_communicator.hh"
+#include "dof_manager.hh"
 #include "sparse_matrix.hh"
-#include "solver.hh"
-
-#ifdef AKANTU_USE_MUMPS
-#include "solver_mumps.hh"
-#endif
+/* -------------------------------------------------------------------------- */
 
 #ifdef AKANTU_USE_IOHELPER
-#include "dumper_paraview.hh"
 #include "dumper_elemental_field.hh"
+#include "dumper_paraview.hh"
 #endif
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
-const StructuralMechanicsModelOptions
-    default_structural_mechanics_model_options(_static);
-
 /* -------------------------------------------------------------------------- */
 StructuralMechanicsModel::StructuralMechanicsModel(Mesh & mesh, UInt dim,
                                                    const ID & id,
                                                    const MemoryID & memory_id)
     : Model(mesh, dim, id, memory_id), time_step(NAN), f_m2a(1.0),
       stress("stress", id, memory_id),
       element_material("element_material", id, memory_id),
-      set_ID("beam sets", id, memory_id), stiffness_matrix(NULL),
-      mass_matrix(NULL), velocity_damping_matrix(NULL), jacobian_matrix(NULL),
-      solver(NULL), rotation_matrix("rotation_matices", id, memory_id),
-      increment_flag(false), integrator(NULL) {
+      set_ID("beam sets", id, memory_id),
+      rotation_matrix("rotation_matices", id, memory_id) {
   AKANTU_DEBUG_IN();
 
   registerFEEngineObject<MyFEEngineType>("StructuralMechanicsFEEngine", mesh,
                                          spatial_dimension);
 
-  this->displacement_rotation = NULL;
-  this->mass = NULL;
-  this->velocity = NULL;
-  this->acceleration = NULL;
-  this->force_momentum = NULL;
-  this->residual = NULL;
-  this->blocked_dofs = NULL;
-  this->increment = NULL;
-
-  this->previous_displacement = NULL;
-
   if (spatial_dimension == 2)
     nb_degree_of_freedom = 3;
   else if (spatial_dimension == 3)
     nb_degree_of_freedom = 6;
   else {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
+#ifdef AKANTU_USE_IOHELPER
   this->mesh.registerDumper<DumperParaview>("paraview_all", id, true);
+#endif
   this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_structural);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
-StructuralMechanicsModel::~StructuralMechanicsModel() {
-  AKANTU_DEBUG_IN();
-
-  delete integrator;
-  delete solver;
-  delete stiffness_matrix;
-  delete jacobian_matrix;
-  delete mass_matrix;
-  delete velocity_damping_matrix;
-
-  AKANTU_DEBUG_OUT();
-}
+StructuralMechanicsModel::~StructuralMechanicsModel() = default;
 
+/* -------------------------------------------------------------------------- */
 void StructuralMechanicsModel::setTimeStep(Real time_step) {
   this->time_step = time_step;
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.getDumper().setTimeStep(time_step);
 #endif
 }
 
 /* -------------------------------------------------------------------------- */
 /* Initialisation                                                             */
 /* -------------------------------------------------------------------------- */
+void StructuralMechanicsModel::initSolver(
+    TimeStepSolverType time_step_solver_type, NonLinearSolverType) {
+  AKANTU_DEBUG_IN();
 
-void StructuralMechanicsModel::initFull(const ModelOptions & options) {
-
-  const StructuralMechanicsModelOptions & stmm_options =
-      dynamic_cast<const StructuralMechanicsModelOptions &>(options);
-
-  method = stmm_options.analysis_method;
-
-  initModel();
-  initArrays();
-
-  displacement_rotation->clear();
-  velocity->clear();
-  acceleration->clear();
-  force_momentum->clear();
-  residual->clear();
-  blocked_dofs->clear();
-  increment->clear();
+  this->allocNodalField(displacement_rotation, nb_degree_of_freedom,
+                        "displacement");
+  this->allocNodalField(external_force_momentum, nb_degree_of_freedom,
+                        "external_force");
+  this->allocNodalField(internal_force_momentum, nb_degree_of_freedom,
+                        "internal_force");
+  this->allocNodalField(blocked_dofs, spatial_dimension, "blocked_dofs");
 
-  Mesh::type_iterator it = getFEEngine().getMesh().firstType(
-      spatial_dimension, _not_ghost, _ek_structural);
-  Mesh::type_iterator end = getFEEngine().getMesh().lastType(
-      spatial_dimension, _not_ghost, _ek_structural);
-  for (; it != end; ++it) {
-    computeRotationMatrix(*it);
-  }
+  auto & dof_manager = this->getDOFManager();
 
-  switch (method) {
-  case _implicit_dynamic:
-    initImplicit();
-    break;
-  case _static:
-    initSolver();
-    break;
-  default:
-    AKANTU_EXCEPTION(
-        "analysis method not recognised by StructuralMechanicsModel");
-    break;
+  if (!dof_manager.hasDOFs("displacement")) {
+    dof_manager.registerDOFs("displacement", *displacement_rotation,
+                             _dst_nodal);
+    dof_manager.registerBlockedDOFs("displacement", *this->blocked_dofs);
   }
-}
 
-/* -------------------------------------------------------------------------- */
-void StructuralMechanicsModel::initArrays() {
-  AKANTU_DEBUG_IN();
+  if (time_step_solver_type == _tsst_dynamic ||
+      time_step_solver_type == _tsst_dynamic_lumped) {
+    this->allocNodalField(velocity, spatial_dimension, "velocity");
+    this->allocNodalField(acceleration, spatial_dimension, "acceleration");
 
-  UInt nb_nodes = getFEEngine().getMesh().getNbNodes();
-  std::stringstream sstr_disp;
-  sstr_disp << id << ":displacement";
-  std::stringstream sstr_velo;
-  sstr_velo << id << ":velocity";
-  std::stringstream sstr_acce;
-  sstr_acce << id << ":acceleration";
-  std::stringstream sstr_forc;
-  sstr_forc << id << ":force";
-  std::stringstream sstr_resi;
-  sstr_resi << id << ":residual";
-  std::stringstream sstr_boun;
-  sstr_boun << id << ":blocked_dofs";
-  std::stringstream sstr_incr;
-  sstr_incr << id << ":increment";
-
-  displacement_rotation = &(alloc<Real>(sstr_disp.str(), nb_nodes,
-                                        nb_degree_of_freedom, REAL_INIT_VALUE));
-  velocity = &(alloc<Real>(sstr_velo.str(), nb_nodes, nb_degree_of_freedom,
-                           REAL_INIT_VALUE));
-  acceleration = &(alloc<Real>(sstr_acce.str(), nb_nodes, nb_degree_of_freedom,
-                               REAL_INIT_VALUE));
-  force_momentum = &(alloc<Real>(sstr_forc.str(), nb_nodes,
-                                 nb_degree_of_freedom, REAL_INIT_VALUE));
-  residual = &(alloc<Real>(sstr_resi.str(), nb_nodes, nb_degree_of_freedom,
-                           REAL_INIT_VALUE));
-  blocked_dofs =
-      &(alloc<bool>(sstr_boun.str(), nb_nodes, nb_degree_of_freedom, false));
-  increment = &(alloc<Real>(sstr_incr.str(), nb_nodes, nb_degree_of_freedom,
-                            REAL_INIT_VALUE));
-
-  Mesh::type_iterator it = getFEEngine().getMesh().firstType(
-      spatial_dimension, _not_ghost, _ek_structural);
-  Mesh::type_iterator end = getFEEngine().getMesh().lastType(
-      spatial_dimension, _not_ghost, _ek_structural);
-  for (; it != end; ++it) {
-    UInt nb_element = getFEEngine().getMesh().getNbElement(*it);
-    UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(*it);
-
-    element_material.alloc(nb_element, 1, *it, _not_ghost);
-    set_ID.alloc(nb_element, 1, *it, _not_ghost);
-
-    UInt size = getTangentStiffnessVoigtSize(*it);
-    stress.alloc(nb_element * nb_quadrature_points, size, *it, _not_ghost);
+    if (!dof_manager.hasDOFsDerivatives("displacement", 1)) {
+      dof_manager.registerDOFsDerivative("displacement", 1, *this->velocity);
+      dof_manager.registerDOFsDerivative("displacement", 2,
+                                         *this->acceleration);
+    }
   }
 
-  dof_synchronizer =
-      new DOFSynchronizer(getFEEngine().getMesh(), nb_degree_of_freedom);
-  dof_synchronizer->initLocalDOFEquationNumbers();
-  dof_synchronizer->initGlobalDOFEquationNumbers();
-
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void StructuralMechanicsModel::initModel() {
-  getFEEngine().initShapeFunctions(_not_ghost);
-}
-
-/* -------------------------------------------------------------------------- */
-void StructuralMechanicsModel::initSolver(__attribute__((unused))
-                                          SolverOptions & options) {
-  AKANTU_DEBUG_IN();
-
-  const Mesh & mesh = getFEEngine().getMesh();
-#if !defined(AKANTU_USE_MUMPS) // or other solver in the future \todo add
-                               // AKANTU_HAS_SOLVER in CMake
-  AKANTU_DEBUG_ERROR("You should at least activate one solver.");
-#else
-  UInt nb_global_node = mesh.getNbGlobalNodes();
-
-  std::stringstream sstr;
-  sstr << id << ":jacobian_matrix";
-  jacobian_matrix = new SparseMatrix(nb_global_node * nb_degree_of_freedom,
-                                     _symmetric, sstr.str(), memory_id);
-
-  jacobian_matrix->buildProfile(mesh, *dof_synchronizer, nb_degree_of_freedom);
-
-  std::stringstream sstr_sti;
-  sstr_sti << id << ":stiffness_matrix";
-  stiffness_matrix =
-      new SparseMatrix(*jacobian_matrix, sstr_sti.str(), memory_id);
-
-#ifdef AKANTU_USE_MUMPS
-  std::stringstream sstr_solv;
-  sstr_solv << id << ":solver";
-  solver = new SolverMumps(*jacobian_matrix, sstr_solv.str());
-
-  dof_synchronizer->initScatterGatherCommunicationScheme();
-#else
-  AKANTU_DEBUG_ERROR("You should at least activate one solver.");
-#endif // AKANTU_USE_MUMPS
-
-  solver->initialize(options);
-#endif // AKANTU_HAS_SOLVER
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-void StructuralMechanicsModel::initImplicit(
-    __attribute__((unused)) bool dynamic, SolverOptions & solver_options) {
-  AKANTU_DEBUG_IN();
-
-  if (!increment)
-    setIncrementFlagOn();
-
-  initSolver(solver_options);
-
-  if (integrator)
-    delete integrator;
-  integrator = new TrapezoidalRule2();
+  for (auto && type :
+       mesh.elementTypes(spatial_dimension, _not_ghost, _ek_structural)) {
+    computeRotationMatrix(type);
+  }
 
-  AKANTU_DEBUG_OUT();
+  getFEEngine().initShapeFunctions(_not_ghost);
+  getFEEngine().initShapeFunctions(_ghost);
 }
 
 /* -------------------------------------------------------------------------- */
 UInt StructuralMechanicsModel::getTangentStiffnessVoigtSize(
     const ElementType & type) {
   UInt size;
 #define GET_TANGENT_STIFFNESS_VOIGT_SIZE(type)                                 \
   size = getTangentStiffnessVoigtSize<type>();
 
   AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(GET_TANGENT_STIFFNESS_VOIGT_SIZE);
 #undef GET_TANGENT_STIFFNESS_VOIGT_SIZE
 
   return size;
 }
 
 /* -------------------------------------------------------------------------- */
 void StructuralMechanicsModel::assembleStiffnessMatrix() {
   AKANTU_DEBUG_IN();
 
-  stiffness_matrix->clear();
-
-  Mesh::type_iterator it = getFEEngine().getMesh().firstType(
-      spatial_dimension, _not_ghost, _ek_structural);
-  Mesh::type_iterator end = getFEEngine().getMesh().lastType(
-      spatial_dimension, _not_ghost, _ek_structural);
-  for (; it != end; ++it) {
-    ElementType type = *it;
+  getDOFManager().getMatrix("K").clear();
 
+  for (auto & type : mesh.elementTypes(_spatial_dimension = spatial_dimension,
+                     _element_kind = _ek_structural)) {
 #define ASSEMBLE_STIFFNESS_MATRIX(type) assembleStiffnessMatrix<type>();
 
     AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(ASSEMBLE_STIFFNESS_MATRIX);
 #undef ASSEMBLE_STIFFNESS_MATRIX
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
-template <>
-void StructuralMechanicsModel::computeRotationMatrix<_bernoulli_beam_2>(
-    Array<Real> & rotations) {
-
-  ElementType type = _bernoulli_beam_2;
-  Mesh & mesh = getFEEngine().getMesh();
-  UInt nb_element = mesh.getNbElement(type);
+void StructuralMechanicsModel::computeStresses() {
+  AKANTU_DEBUG_IN();
 
-  Array<UInt>::iterator<Vector<UInt> > connec_it =
-      mesh.getConnectivity(type).begin(2);
-  Array<Real>::vector_iterator nodes_it =
-      mesh.getNodes().begin(spatial_dimension);
-  Array<Real>::matrix_iterator R_it =
-      rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom);
-
-  for (UInt e = 0; e < nb_element; ++e, ++R_it, ++connec_it) {
-    Matrix<Real> & R = *R_it;
-    Vector<UInt> & connec = *connec_it;
-
-    Vector<Real> x2;
-    x2 = nodes_it[connec(1)]; // X2
-    Vector<Real> x1;
-    x1 = nodes_it[connec(0)]; // X1
-
-    Real le = x1.distance(x2);
-    Real c = (x2(0) - x1(0)) / le;
-    Real s = (x2(1) - x1(1)) / le;
-
-    /// Definition of the rotation matrix
-    R(0, 0) = c;
-    R(0, 1) = s;
-    R(0, 2) = 0.;
-    R(1, 0) = -s;
-    R(1, 1) = c;
-    R(1, 2) = 0.;
-    R(2, 0) = 0.;
-    R(2, 1) = 0.;
-    R(2, 2) = 1.;
-  }
-}
+  for (auto & type : mesh.elementTypes(_spatial_dimension = spatial_dimension,
+                     _element_kind = _ek_structural)) {
 
-/* -------------------------------------------------------------------------- */
-template <>
-void StructuralMechanicsModel::computeRotationMatrix<_bernoulli_beam_3>(
-    Array<Real> & rotations) {
-  ElementType type = _bernoulli_beam_3;
-  Mesh & mesh = getFEEngine().getMesh();
-  UInt nb_element = mesh.getNbElement(type);
+#define COMPUTE_STRESS_ON_QUAD(type) computeStressOnQuad<type>();
 
-  Array<Real>::vector_iterator n_it =
-      mesh.getNormals(type).begin(spatial_dimension);
-  Array<UInt>::iterator<Vector<UInt> > connec_it =
-      mesh.getConnectivity(type).begin(2);
-  Array<Real>::vector_iterator nodes_it =
-      mesh.getNodes().begin(spatial_dimension);
-
-  Matrix<Real> Pe(spatial_dimension, spatial_dimension);
-  Matrix<Real> Pg(spatial_dimension, spatial_dimension);
-  Matrix<Real> inv_Pg(spatial_dimension, spatial_dimension);
-  Vector<Real> x_n(spatial_dimension); // x vect n
-
-  Array<Real>::matrix_iterator R_it =
-      rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom);
-
-  for (UInt e = 0; e < nb_element; ++e, ++n_it, ++connec_it, ++R_it) {
-    Vector<Real> & n = *n_it;
-    Matrix<Real> & R = *R_it;
-    Vector<UInt> & connec = *connec_it;
-
-    Vector<Real> x;
-    x = nodes_it[connec(1)]; // X2
-    Vector<Real> y;
-    y = nodes_it[connec(0)]; // X1
-
-    Real l = x.distance(y);
-    x -= y; // X2 - X1
-    x_n.crossProduct(x, n);
-
-    Pe.eye();
-    Pe(0, 0) *= l;
-    Pe(1, 1) *= -l;
-
-    Pg(0, 0) = x(0);
-    Pg(0, 1) = x_n(0);
-    Pg(0, 2) = n(0);
-    Pg(1, 0) = x(1);
-    Pg(1, 1) = x_n(1);
-    Pg(1, 2) = n(1);
-    Pg(2, 0) = x(2);
-    Pg(2, 1) = x_n(2);
-    Pg(2, 2) = n(2);
-
-    inv_Pg.inverse(Pg);
-
-    Pe *= inv_Pg;
-    for (UInt i = 0; i < spatial_dimension; ++i) {
-      for (UInt j = 0; j < spatial_dimension; ++j) {
-        R(i, j) = Pe(i, j);
-        R(i + spatial_dimension, j + spatial_dimension) = Pe(i, j);
-      }
-    }
+    AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(COMPUTE_STRESS_ON_QUAD);
+#undef COMPUTE_STRESS_ON_QUAD
   }
+
+  AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
-template <>
-void StructuralMechanicsModel::computeRotationMatrix<_kirchhoff_shell>(
-    Array<Real> & rotations) {
-  ElementType type = _kirchhoff_shell;
-  Mesh & mesh = getFEEngine().getMesh();
-  UInt nb_element = mesh.getNbElement(type);
-
-  Array<UInt>::iterator<Vector<UInt> > connec_it =
-      mesh.getConnectivity(type).begin(3);
-  Array<Real>::vector_iterator nodes_it =
-      mesh.getNodes().begin(spatial_dimension);
-
-  Matrix<Real> Pe(spatial_dimension, spatial_dimension);
-  Matrix<Real> Pg(spatial_dimension, spatial_dimension);
-  Matrix<Real> inv_Pg(spatial_dimension, spatial_dimension);
-
-  Array<Real>::matrix_iterator R_it =
-      rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom);
-
-  for (UInt e = 0; e < nb_element; ++e, ++connec_it, ++R_it) {
-
-    Pe.eye();
-
-    Matrix<Real> & R = *R_it;
-    Vector<UInt> & connec = *connec_it;
-
-    Vector<Real> x2;
-    x2 = nodes_it[connec(1)]; // X2
-    Vector<Real> x1;
-    x1 = nodes_it[connec(0)]; // X1
-    Vector<Real> x3;
-    x3 = nodes_it[connec(2)]; // X3
-
-    Vector<Real> Pg_col_1 = x2 - x1;
+void StructuralMechanicsModel::updateResidual() {
+  AKANTU_DEBUG_IN();
 
-    Vector<Real> Pg_col_2 = x3 - x1;
+  auto & K = getDOFManager().getMatrix("K");
 
-    Vector<Real> Pg_col_3(spatial_dimension);
-    Pg_col_3.crossProduct(Pg_col_1, Pg_col_2);
+  internal_force_momentum->clear();
+  K.matVecMul(*displacement_rotation, *internal_force_momentum);
+  *internal_force_momentum *= -1.;
 
-    for (UInt i = 0; i < spatial_dimension; ++i) {
-      Pg(i, 0) = Pg_col_1(i);
-      Pg(i, 1) = Pg_col_2(i);
-      Pg(i, 2) = Pg_col_3(i);
-    }
+  getDOFManager().assembleToResidual("displacement", *external_force_momentum,
+                                     1.);
 
-    inv_Pg.inverse(Pg);
-    // Pe *= inv_Pg;
-    Pe.eye();
+  getDOFManager().assembleToResidual("displacement", *internal_force_momentum,
+                                     1.);
 
-    for (UInt i = 0; i < spatial_dimension; ++i) {
-      for (UInt j = 0; j < spatial_dimension; ++j) {
-        R(i, j) = Pe(i, j);
-        R(i + spatial_dimension, j + spatial_dimension) = Pe(i, j);
-      }
-    }
-  }
+  AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void StructuralMechanicsModel::computeRotationMatrix(const ElementType & type) {
   Mesh & mesh = getFEEngine().getMesh();
 
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
   UInt nb_element = mesh.getNbElement(type);
 
   if (!rotation_matrix.exists(type)) {
     rotation_matrix.alloc(nb_element,
                           nb_degree_of_freedom * nb_nodes_per_element *
                               nb_degree_of_freedom * nb_nodes_per_element,
                           type);
   } else {
     rotation_matrix(type).resize(nb_element);
   }
   rotation_matrix(type).clear();
 
   Array<Real> rotations(nb_element,
                         nb_degree_of_freedom * nb_degree_of_freedom);
   rotations.clear();
 
 #define COMPUTE_ROTATION_MATRIX(type) computeRotationMatrix<type>(rotations);
 
   AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(COMPUTE_ROTATION_MATRIX);
 #undef COMPUTE_ROTATION_MATRIX
 
-  Array<Real>::matrix_iterator R_it =
-      rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom);
-  Array<Real>::matrix_iterator T_it =
+  auto R_it = rotations.begin(nb_degree_of_freedom, nb_degree_of_freedom);
+  auto T_it =
       rotation_matrix(type).begin(nb_degree_of_freedom * nb_nodes_per_element,
                                   nb_degree_of_freedom * nb_nodes_per_element);
 
   for (UInt el = 0; el < nb_element; ++el, ++R_it, ++T_it) {
-    Matrix<Real> & T = *T_it;
-    Matrix<Real> & R = *R_it;
+    auto & T = *T_it;
+    auto & R = *R_it;
     T.clear();
     for (UInt k = 0; k < nb_nodes_per_element; ++k) {
       for (UInt i = 0; i < nb_degree_of_freedom; ++i)
         for (UInt j = 0; j < nb_degree_of_freedom; ++j)
           T(k * nb_degree_of_freedom + i, k * nb_degree_of_freedom + j) =
               R(i, j);
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
-void StructuralMechanicsModel::computeStresses() {
-  AKANTU_DEBUG_IN();
-
-  Mesh::type_iterator it = getFEEngine().getMesh().firstType(
-      spatial_dimension, _not_ghost, _ek_structural);
-  Mesh::type_iterator end = getFEEngine().getMesh().lastType(
-      spatial_dimension, _not_ghost, _ek_structural);
-  for (; it != end; ++it) {
-    ElementType type = *it;
-
-#define COMPUTE_STRESS_ON_QUAD(type) computeStressOnQuad<type>();
-
-    AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(COMPUTE_STRESS_ON_QUAD);
-#undef COMPUTE_STRESS_ON_QUAD
-  }
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-void StructuralMechanicsModel::updateResidual() {
-  AKANTU_DEBUG_IN();
-  residual->copy(*force_momentum);
-
-  Array<Real> ku(*displacement_rotation, true);
-  ku *= *stiffness_matrix;
-  *residual -= ku;
-
-  this->updateResidualInternal();
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-void StructuralMechanicsModel::implicitPred() {
-  AKANTU_DEBUG_IN();
-
-  if (previous_displacement)
-    previous_displacement->copy(*displacement_rotation);
-
-  if (method == _implicit_dynamic)
-    integrator->integrationSchemePred(time_step, *displacement_rotation,
-                                      *velocity, *acceleration, *blocked_dofs);
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-void StructuralMechanicsModel::implicitCorr() {
-  AKANTU_DEBUG_IN();
-
-  Real * incr_val = increment->storage();
-  bool * boun_val = blocked_dofs->storage();
-
-  UInt nb_nodes = displacement_rotation->size();
-
-  for (UInt j = 0; j < nb_nodes * nb_degree_of_freedom;
-       ++j, ++incr_val, ++boun_val) {
-    *incr_val *= (1. - *boun_val);
-  }
-
-  if (method == _implicit_dynamic) {
-    integrator->integrationSchemeCorrDispl(time_step, *displacement_rotation,
-                                           *velocity, *acceleration,
-                                           *blocked_dofs, *increment);
-  } else {
-
-    Real * disp_val = displacement_rotation->storage();
-    incr_val = increment->storage();
-
-    for (UInt j = 0; j < nb_nodes * nb_degree_of_freedom;
-         ++j, ++disp_val, ++incr_val) {
-      *disp_val += *incr_val;
-    }
-  }
-
-  AKANTU_DEBUG_OUT();
-}
-/* -------------------------------------------------------------------------- */
-void StructuralMechanicsModel::updateResidualInternal() {
-  AKANTU_DEBUG_IN();
-
-  AKANTU_DEBUG_INFO("Update the residual");
-  // f = f_ext - f_int - Ma - Cv = r - Ma - Cv;
-
-  if (method != _static) {
-    // f -= Ma
-    if (mass_matrix) {
-      // if full mass_matrix
-      Array<Real> * Ma = new Array<Real>(*acceleration, true, "Ma");
-      *Ma *= *mass_matrix;
-      /// \todo check unit conversion for implicit dynamics
-      //      *Ma /= f_m2a
-      *residual -= *Ma;
-      delete Ma;
-    } else if (mass) {
-
-      // else lumped mass
-      UInt nb_nodes = acceleration->size();
-      UInt nb_degree_of_freedom = acceleration->getNbComponent();
-
-      Real * mass_val = mass->storage();
-      Real * accel_val = acceleration->storage();
-      Real * res_val = residual->storage();
-      bool * blocked_dofs_val = blocked_dofs->storage();
-
-      for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) {
-        if (!(*blocked_dofs_val)) {
-          *res_val -= *accel_val ** mass_val / f_m2a;
-        }
-        blocked_dofs_val++;
-        res_val++;
-        mass_val++;
-        accel_val++;
-      }
-    } else {
-      AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix.");
-    }
-
-    // f -= Cv
-    if (velocity_damping_matrix) {
-      Array<Real> * Cv = new Array<Real>(*velocity);
-      *Cv *= *velocity_damping_matrix;
-      *residual -= *Cv;
-      delete Cv;
-    }
-  }
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-void StructuralMechanicsModel::setIncrementFlagOn() {
-  AKANTU_DEBUG_IN();
-
-  if (!increment) {
-    UInt nb_nodes = mesh.getNbNodes();
-    std::stringstream sstr_inc;
-    sstr_inc << id << ":increment";
-    increment = &(alloc<Real>(sstr_inc.str(), nb_nodes, spatial_dimension, 0.));
-  }
-
-  increment_flag = true;
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-void StructuralMechanicsModel::solve() {
-  AKANTU_DEBUG_IN();
-
-  AKANTU_DEBUG_INFO("Solving an implicit step.");
-
-  UInt nb_nodes = displacement_rotation->size();
-
-  /// todo residual = force - Kxr * d_bloq
-  jacobian_matrix->copyContent(*stiffness_matrix);
-  jacobian_matrix->applyBoundary(*blocked_dofs);
-
-  jacobian_matrix->saveMatrix("Kbound.mtx");
-
-  increment->clear();
-
-  solver->setRHS(*residual);
-
-  solver->factorize();
-  solver->solve(*increment);
-
-  Real * increment_val = increment->storage();
-  Real * displacement_val = displacement_rotation->storage();
-  bool * blocked_dofs_val = blocked_dofs->storage();
-
-  for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) {
-    if (!(*blocked_dofs_val)) {
-      *displacement_val += *increment_val;
-    } else {
-      *increment_val = 0.0;
-    }
-
-    displacement_val++;
-    blocked_dofs_val++;
-    increment_val++;
-  }
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-bool StructuralMechanicsModel::testConvergence<_scc_increment>(Real tolerance,
-                                                               Real & error) {
-  AKANTU_DEBUG_IN();
-
-  UInt nb_nodes = displacement_rotation->size();
-  UInt nb_degree_of_freedom = displacement_rotation->getNbComponent();
-
-  error = 0;
-  Real norm[2] = {0., 0.};
-  Real * increment_val = increment->storage();
-  bool * blocked_dofs_val = blocked_dofs->storage();
-  Real * displacement_val = displacement_rotation->storage();
-
-  for (UInt n = 0; n < nb_nodes; ++n) {
-    for (UInt d = 0; d < nb_degree_of_freedom; ++d) {
-      if (!(*blocked_dofs_val)) {
-        norm[0] += *increment_val * *increment_val;
-        norm[1] += *displacement_val * *displacement_val;
-      }
-      blocked_dofs_val++;
-      increment_val++;
-      displacement_val++;
-    }
-  }
-
-  StaticCommunicator::getStaticCommunicator().allReduce(norm, 2, _so_sum);
-
-  norm[0] = sqrt(norm[0]);
-  norm[1] = sqrt(norm[1]);
-  AKANTU_DEBUG_ASSERT(!Math::isnan(norm[0]),
-                      "Something went wrong in the solve phase");
-
-  AKANTU_DEBUG_OUT();
-  if (norm[1] > Math::getTolerance())
-    error = norm[0] / norm[1];
-  else
-    error = norm[0]; // In case the total displacement is zero!
-  return (error < tolerance);
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-bool StructuralMechanicsModel::testConvergence<_scc_residual>(Real tolerance,
-                                                              Real & norm) {
-  AKANTU_DEBUG_IN();
-
-  UInt nb_nodes = residual->size();
-
-  norm = 0;
-  Real * residual_val = residual->storage();
-  bool * blocked_dofs_val = blocked_dofs->storage();
-
-  for (UInt n = 0; n < nb_nodes; ++n) {
-    bool is_local_node = mesh.isLocalOrMasterNode(n);
-    if (is_local_node) {
-      for (UInt d = 0; d < nb_degree_of_freedom; ++d) {
-        if (!(*blocked_dofs_val)) {
-          norm += *residual_val * *residual_val;
-        }
-        blocked_dofs_val++;
-        residual_val++;
-      }
-    } else {
-      blocked_dofs_val += spatial_dimension;
-      residual_val += spatial_dimension;
-    }
-  }
-
-  StaticCommunicator::getStaticCommunicator().allReduce(&norm, 1, _so_sum);
-
-  norm = sqrt(norm);
-
-  AKANTU_DEBUG_ASSERT(!Math::isnan(norm),
-                      "Something goes wrong in the solve phase");
-
-  AKANTU_DEBUG_OUT();
-  return (norm < tolerance);
-}
-
-/* -------------------------------------------------------------------------- */
-bool StructuralMechanicsModel::testConvergenceIncrement(Real tolerance) {
-  Real error;
-  bool tmp = testConvergenceIncrement(tolerance, error);
-
-  AKANTU_DEBUG_INFO("Norm of increment : " << error);
-
-  return tmp;
-}
-
-/* -------------------------------------------------------------------------- */
-bool StructuralMechanicsModel::testConvergenceIncrement(Real tolerance,
-                                                        Real & error) {
-  AKANTU_DEBUG_IN();
-  Mesh & mesh = getFEEngine().getMesh();
-  UInt nb_nodes = displacement_rotation->size();
-  UInt nb_degree_of_freedom = displacement_rotation->getNbComponent();
-
-  Real norm = 0;
-  Real * increment_val = increment->storage();
-  bool * blocked_dofs_val = blocked_dofs->storage();
-
-  for (UInt n = 0; n < nb_nodes; ++n) {
-    bool is_local_node = mesh.isLocalOrMasterNode(n);
-    for (UInt d = 0; d < nb_degree_of_freedom; ++d) {
-      if (!(*blocked_dofs_val) && is_local_node) {
-        norm += *increment_val * *increment_val;
-      }
-      blocked_dofs_val++;
-      increment_val++;
-    }
-  }
-
-  StaticCommunicator::getStaticCommunicator().allReduce(&norm, 1, _so_sum);
-
-  error = sqrt(norm);
-  AKANTU_DEBUG_ASSERT(!Math::isnan(norm),
-                      "Something goes wrong in the solve phase");
-
-  AKANTU_DEBUG_OUT();
-  return (error < tolerance);
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-void StructuralMechanicsModel::computeTangentModuli<_bernoulli_beam_2>(
-    Array<Real> & tangent_moduli) {
-  UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_2);
-  UInt nb_quadrature_points =
-      getFEEngine().getNbIntegrationPoints(_bernoulli_beam_2);
-  UInt tangent_size = 2;
-
-  Array<Real>::matrix_iterator D_it =
-      tangent_moduli.begin(tangent_size, tangent_size);
-  Array<UInt> & el_mat = element_material(_bernoulli_beam_2, _not_ghost);
-
-  for (UInt e = 0; e < nb_element; ++e) {
-    UInt mat = el_mat(e);
-    Real E = materials[mat].E;
-    Real A = materials[mat].A;
-    Real I = materials[mat].I;
-    for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it) {
-      Matrix<Real> & D = *D_it;
-      D(0, 0) = E * A;
-      D(1, 1) = E * I;
-    }
-  }
-}
-/* -------------------------------------------------------------------------- */
-template <>
-void StructuralMechanicsModel::computeTangentModuli<_bernoulli_beam_3>(
-    Array<Real> & tangent_moduli) {
-  UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_3);
-  UInt nb_quadrature_points =
-      getFEEngine().getNbIntegrationPoints(_bernoulli_beam_3);
-  UInt tangent_size = 4;
-
-  Array<Real>::matrix_iterator D_it =
-      tangent_moduli.begin(tangent_size, tangent_size);
-
-  for (UInt e = 0; e < nb_element; ++e) {
-    UInt mat = element_material(_bernoulli_beam_3, _not_ghost)(e);
-    Real E = materials[mat].E;
-    Real A = materials[mat].A;
-    Real Iz = materials[mat].Iz;
-    Real Iy = materials[mat].Iy;
-    Real GJ = materials[mat].GJ;
-    for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it) {
-      Matrix<Real> & D = *D_it;
-      D(0, 0) = E * A;
-      D(1, 1) = E * Iz;
-      D(2, 2) = E * Iy;
-      D(3, 3) = GJ;
-    }
-  }
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-void StructuralMechanicsModel::computeTangentModuli<_kirchhoff_shell>(
-    Array<Real> & tangent_moduli) {
-  UInt nb_element = getFEEngine().getMesh().getNbElement(_kirchhoff_shell);
-  UInt nb_quadrature_points =
-      getFEEngine().getNbIntegrationPoints(_kirchhoff_shell);
-  UInt tangent_size = 6;
-
-  Array<Real>::matrix_iterator D_it =
-      tangent_moduli.begin(tangent_size, tangent_size);
-
-  for (UInt e = 0; e < nb_element; ++e) {
-    UInt mat = element_material(_kirchhoff_shell, _not_ghost)(e);
-    Real E = materials[mat].E;
-    Real nu = materials[mat].nu;
-    Real t = materials[mat].t;
-
-    Real HH = E * t / (1 - nu * nu);
-    Real DD = E * t * t * t / (12 * (1 - nu * nu));
-
-    for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it) {
-      Matrix<Real> & D = *D_it;
-      D(0, 0) = HH;
-      D(0, 1) = HH * nu;
-      D(1, 0) = HH * nu;
-      D(1, 1) = HH;
-      D(2, 2) = HH * (1 - nu) / 2;
-      D(3, 3) = DD;
-      D(3, 4) = DD * nu;
-      D(4, 3) = DD * nu;
-      D(4, 4) = DD;
-      D(5, 5) = DD * (1 - nu) / 2;
-    }
-  }
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix<
-    _bernoulli_beam_2>(Array<Real> & b, __attribute__((unused)) bool local) {
-  UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_2);
-  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_bernoulli_beam_2);
-  UInt nb_quadrature_points =
-      getFEEngine().getNbIntegrationPoints(_bernoulli_beam_2);
-
-  MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>();
-  Array<Real>::const_vector_iterator shape_Np =
-      fem.getShapesDerivatives(_bernoulli_beam_2, _not_ghost, 0)
-          .begin(nb_nodes_per_element);
-  Array<Real>::const_vector_iterator shape_Mpp =
-      fem.getShapesDerivatives(_bernoulli_beam_2, _not_ghost, 1)
-          .begin(nb_nodes_per_element);
-  Array<Real>::const_vector_iterator shape_Lpp =
-      fem.getShapesDerivatives(_bernoulli_beam_2, _not_ghost, 2)
-          .begin(nb_nodes_per_element);
-
-  UInt tangent_size = getTangentStiffnessVoigtSize<_bernoulli_beam_2>();
-  UInt bt_d_b_size = nb_nodes_per_element * nb_degree_of_freedom;
-  b.clear();
-  Array<Real>::matrix_iterator B_it = b.begin(tangent_size, bt_d_b_size);
-
-  for (UInt e = 0; e < nb_element; ++e) {
-    for (UInt q = 0; q < nb_quadrature_points; ++q) {
-      Matrix<Real> & B = *B_it;
-      const Vector<Real> & Np = *shape_Np;
-      const Vector<Real> & Lpp = *shape_Lpp;
-      const Vector<Real> & Mpp = *shape_Mpp;
-
-      B(0, 0) = Np(0);
-      B(0, 3) = Np(1);
-
-      B(1, 1) = Mpp(0);
-      B(1, 2) = Lpp(0);
-      B(1, 4) = Mpp(1);
-      B(1, 5) = Lpp(1);
-
-      ++B_it;
-      ++shape_Np;
-      ++shape_Mpp;
-      ++shape_Lpp;
-    }
-
-    // ++R_it;
-  }
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix<
-    _bernoulli_beam_3>(Array<Real> & b, __attribute__((unused)) bool local) {
-  MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>();
-
-  UInt nb_element = getFEEngine().getMesh().getNbElement(_bernoulli_beam_3);
-  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_bernoulli_beam_3);
-  UInt nb_quadrature_points =
-      getFEEngine().getNbIntegrationPoints(_bernoulli_beam_3);
-
-  Array<Real>::const_vector_iterator shape_Np =
-      fem.getShapesDerivatives(_bernoulli_beam_3, _not_ghost, 0)
-          .begin(nb_nodes_per_element);
-  Array<Real>::const_vector_iterator shape_Mpp =
-      fem.getShapesDerivatives(_bernoulli_beam_3, _not_ghost, 1)
-          .begin(nb_nodes_per_element);
-  Array<Real>::const_vector_iterator shape_Lpp =
-      fem.getShapesDerivatives(_bernoulli_beam_3, _not_ghost, 2)
-          .begin(nb_nodes_per_element);
-
-  UInt tangent_size = getTangentStiffnessVoigtSize<_bernoulli_beam_3>();
-  UInt bt_d_b_size = nb_nodes_per_element * nb_degree_of_freedom;
-
-  b.clear();
-
-  Array<Real>::matrix_iterator B_it = b.begin(tangent_size, bt_d_b_size);
-
-  for (UInt e = 0; e < nb_element; ++e) {
-    for (UInt q = 0; q < nb_quadrature_points; ++q) {
-      Matrix<Real> & B = *B_it;
-
-      const Vector<Real> & Np = *shape_Np;
-      const Vector<Real> & Lpp = *shape_Lpp;
-      const Vector<Real> & Mpp = *shape_Mpp;
-
-      B(0, 0) = Np(0);
-      B(0, 6) = Np(1);
-
-      B(1, 1) = Mpp(0);
-      B(1, 5) = Lpp(0);
-      B(1, 7) = Mpp(1);
-      B(1, 11) = Lpp(1);
-
-      B(2, 2) = Mpp(0);
-      B(2, 4) = -Lpp(0);
-      B(2, 8) = Mpp(1);
-      B(2, 10) = -Lpp(1);
-
-      B(3, 3) = Np(0);
-      B(3, 9) = Np(1);
-
-      ++B_it;
-      ++shape_Np;
-      ++shape_Mpp;
-      ++shape_Lpp;
-    }
-  }
-}
-/* -------------------------------------------------------------------------- */
-template <>
-void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix<
-    _kirchhoff_shell>(Array<Real> & b, __attribute__((unused)) bool local) {
-  MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>();
-
-  UInt nb_element = getFEEngine().getMesh().getNbElement(_kirchhoff_shell);
-  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_kirchhoff_shell);
-  UInt nb_quadrature_points =
-      getFEEngine().getNbIntegrationPoints(_kirchhoff_shell);
-
-  Array<Real>::const_matrix_iterator shape_Np =
-      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 0)
-          .begin(2, nb_nodes_per_element);
-  Array<Real>::const_matrix_iterator shape_Nx1p =
-      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 1)
-          .begin(2, nb_nodes_per_element);
-  Array<Real>::const_matrix_iterator shape_Nx2p =
-      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 2)
-          .begin(2, nb_nodes_per_element);
-  Array<Real>::const_matrix_iterator shape_Nx3p =
-      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 3)
-          .begin(2, nb_nodes_per_element);
-  Array<Real>::const_matrix_iterator shape_Ny1p =
-      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 4)
-          .begin(2, nb_nodes_per_element);
-  Array<Real>::const_matrix_iterator shape_Ny2p =
-      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 5)
-          .begin(2, nb_nodes_per_element);
-  Array<Real>::const_matrix_iterator shape_Ny3p =
-      fem.getShapesDerivatives(_kirchhoff_shell, _not_ghost, 6)
-          .begin(2, nb_nodes_per_element);
-
-  UInt tangent_size = getTangentStiffnessVoigtSize<_kirchhoff_shell>();
-  UInt bt_d_b_size = nb_nodes_per_element * nb_degree_of_freedom;
-
-  b.clear();
-
-  Array<Real>::matrix_iterator B_it = b.begin(tangent_size, bt_d_b_size);
-
-  for (UInt e = 0; e < nb_element; ++e) {
-    for (UInt q = 0; q < nb_quadrature_points; ++q) {
-      Matrix<Real> & B = *B_it;
-
-      const Matrix<Real> & Np = *shape_Np;
-      const Matrix<Real> & Nx1p = *shape_Nx1p;
-      const Matrix<Real> & Nx2p = *shape_Nx2p;
-      const Matrix<Real> & Nx3p = *shape_Nx3p;
-      const Matrix<Real> & Ny1p = *shape_Ny1p;
-      const Matrix<Real> & Ny2p = *shape_Ny2p;
-      const Matrix<Real> & Ny3p = *shape_Ny3p;
-
-      B(0, 0) = Np(0, 0);
-      B(0, 6) = Np(0, 1);
-      B(0, 12) = Np(0, 2);
-
-      B(1, 1) = Np(1, 0);
-      B(1, 7) = Np(1, 1);
-      B(1, 13) = Np(1, 2);
-
-      B(2, 0) = Np(1, 0);
-      B(2, 1) = Np(0, 0);
-      B(2, 6) = Np(1, 1);
-      B(2, 7) = Np(0, 1);
-      B(2, 12) = Np(1, 2);
-      B(2, 13) = Np(0, 2);
-
-      B(3, 2) = Nx1p(0, 0);
-      B(3, 3) = Nx2p(0, 0);
-      B(3, 4) = Nx3p(0, 0);
-      B(3, 8) = Nx1p(0, 1);
-      B(3, 9) = Nx2p(0, 1);
-      B(3, 10) = Nx3p(0, 1);
-      B(3, 14) = Nx1p(0, 2);
-      B(3, 15) = Nx2p(0, 2);
-      B(3, 16) = Nx3p(0, 2);
-
-      B(4, 2) = Ny1p(1, 0);
-      B(4, 3) = Ny2p(1, 0);
-      B(4, 4) = Ny3p(1, 0);
-      B(4, 8) = Ny1p(1, 1);
-      B(4, 9) = Ny2p(1, 1);
-      B(4, 10) = Ny3p(1, 1);
-      B(4, 14) = Ny1p(1, 2);
-      B(4, 15) = Ny2p(1, 2);
-      B(4, 16) = Ny3p(1, 2);
-
-      B(5, 2) = Nx1p(1, 0) + Ny1p(0, 0);
-      B(5, 3) = Nx2p(1, 0) + Ny2p(0, 0);
-      B(5, 4) = Nx3p(1, 0) + Ny3p(0, 0);
-      B(5, 8) = Nx1p(1, 1) + Ny1p(0, 1);
-      B(5, 9) = Nx2p(1, 1) + Ny2p(0, 1);
-      B(5, 10) = Nx3p(1, 1) + Ny3p(0, 1);
-      B(5, 14) = Nx1p(1, 2) + Ny1p(0, 2);
-      B(5, 15) = Nx2p(1, 2) + Ny2p(0, 2);
-      B(5, 16) = Nx3p(1, 2) + Ny3p(0, 2);
-
-      ++B_it;
-      ++shape_Np;
-      ++shape_Nx1p;
-      ++shape_Nx2p;
-      ++shape_Nx3p;
-      ++shape_Ny1p;
-      ++shape_Ny2p;
-      ++shape_Ny3p;
-    }
-  }
-}
-
-/* -------------------------------------------------------------------------- */
-
-dumper::Field *
-StructuralMechanicsModel::createNodalFieldBool(const std::string & field_name,
-                                               const std::string & group_name,
-                                               __attribute__((unused)) bool padding_flag) {
+dumper::Field * StructuralMechanicsModel::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 = NULL;
   field = mesh.createNodalField(uint_nodal_fields[field_name], group_name);
   return field;
 }
 
 /* -------------------------------------------------------------------------- */
-
 dumper::Field *
 StructuralMechanicsModel::createNodalFieldReal(const std::string & field_name,
                                                const std::string & group_name,
                                                bool padding_flag) {
 
   UInt n;
   if (spatial_dimension == 2) {
     n = 2;
   } else
     n = 3;
 
-  dumper::Field * field = NULL;
-
   if (field_name == "displacement") {
-    field = mesh.createStridedNodalField(displacement_rotation, group_name, n,
-                                         0, padding_flag);
+    return mesh.createStridedNodalField(displacement_rotation, group_name, n, 0,
+                                        padding_flag);
   }
+
   if (field_name == "rotation") {
-    field =
-        mesh.createStridedNodalField(displacement_rotation, group_name,
-                                     nb_degree_of_freedom - n, n, padding_flag);
+    return mesh.createStridedNodalField(displacement_rotation, group_name,
+                                        nb_degree_of_freedom - n, n,
+                                        padding_flag);
   }
+
   if (field_name == "force") {
-    field = mesh.createStridedNodalField(force_momentum, group_name, n, 0,
-                                         padding_flag);
+    return mesh.createStridedNodalField(external_force_momentum, group_name, n,
+                                        0, padding_flag);
   }
+
   if (field_name == "momentum") {
-    field = mesh.createStridedNodalField(
-        force_momentum, group_name, nb_degree_of_freedom - n, n, padding_flag);
+    return mesh.createStridedNodalField(external_force_momentum, group_name,
+                                        nb_degree_of_freedom - n, n,
+                                        padding_flag);
   }
-  if (field_name == "residual") {
-    field = mesh.createNodalField(residual, group_name, padding_flag);
+
+  if (field_name == "internal_force") {
+    return mesh.createStridedNodalField(internal_force_momentum, group_name, n,
+                                        0, padding_flag);
   }
 
-  return field;
+  if (field_name == "internal_momentum") {
+    return mesh.createStridedNodalField(internal_force_momentum, group_name,
+                                        nb_degree_of_freedom - n, n,
+                                        padding_flag);
+  }
+
+  return nullptr;
 }
 
 /* -------------------------------------------------------------------------- */
-
 dumper::Field * StructuralMechanicsModel::createElementalField(
-    const std::string & field_name, const std::string & group_name,
-    __attribute__((unused)) bool padding_flag, const ElementKind & kind,
-    __attribute__((unused)) const std::string & fe_engine_id) {
+    const std::string & field_name, const std::string & group_name, bool,
+    const ElementKind & kind, const std::string &) {
 
   dumper::Field * field = NULL;
 
   if (field_name == "element_index_by_material")
     field = mesh.createElementalField<UInt, Vector, dumper::ElementalField>(
         field_name, group_name, this->spatial_dimension, kind);
 
   return field;
 }
 
 /* -------------------------------------------------------------------------- */
 
-} // akantu
+} // namespace akantu
diff --git a/src/model/structural_mechanics/structural_mechanics_model.hh b/src/model/structural_mechanics/structural_mechanics_model.hh
index f884e79dd..8f96b2d9d 100644
--- a/src/model/structural_mechanics/structural_mechanics_model.hh
+++ b/src/model/structural_mechanics/structural_mechanics_model.hh
@@ -1,392 +1,292 @@
 /**
  * @file   structural_mechanics_model.hh
  *
  * @author Fabian Barras <fabian.barras@epfl.ch>
  * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Damien Spielmann <damien.spielmann@epfl.ch>
  *
  * @date creation: Fri Jul 15 2011
  * @date last modification: Thu Jan 21 2016
  *
  * @brief  Particular implementation of the structural elements in the
  * StructuralMechanicsModel
  *
  * @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 "model.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_STRUCTURAL_MECHANICS_MODEL_HH__
 #define __AKANTU_STRUCTURAL_MECHANICS_MODEL_HH__
 
-/* -------------------------------------------------------------------------- */
-#include "aka_common.hh"
-#include "model.hh"
-#include "integrator_gauss.hh"
-#include "shape_linked.hh"
-#include "aka_types.hh"
-#include "dumpable.hh"
-#include "solver.hh"
-#include "integration_scheme_2nd_order.hh"
-
 /* -------------------------------------------------------------------------- */
 namespace akantu {
-class SparseMatrix;
-}
+class Material;
+class MaterialSelector;
+class DumperIOHelper;
+class NonLocalManager;
+template <ElementKind kind, class IntegrationOrderFunctor>
+class IntegratorGauss;
+template <ElementKind kind> class ShapeStructural;
+} // namespace akantu
 
 namespace akantu {
 
 struct StructuralMaterial {
-  Real E;
-  Real A;
-  Real I;
-  Real Iz;
-  Real Iy;
-  Real GJ;
-  Real rho;
-  Real t;
-  Real nu;
+  Real E{0};
+  Real A{1};
+  Real I{0};
+  Real Iz{0};
+  Real Iy{0};
+  Real GJ{0};
+  Real rho{0};
+  Real t{0};
+  Real nu{0};
 };
 
-struct StructuralMechanicsModelOptions : public ModelOptions {
-  StructuralMechanicsModelOptions(AnalysisMethod analysis_method = _static)
-      : analysis_method(analysis_method) {}
-  AnalysisMethod analysis_method;
-};
-
-extern const StructuralMechanicsModelOptions
-    default_structural_mechanics_model_options;
-
 class StructuralMechanicsModel : public Model {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
-  typedef FEEngineTemplate<IntegratorGauss, ShapeLinked, _ek_structural>
-      MyFEEngineType;
+  using MyFEEngineType =
+      FEEngineTemplate<IntegratorGauss, ShapeStructural, _ek_structural>;
 
   StructuralMechanicsModel(Mesh & mesh,
                            UInt spatial_dimension = _all_dimensions,
                            const ID & id = "structural_mechanics_model",
                            const MemoryID & memory_id = 0);
 
   virtual ~StructuralMechanicsModel();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
-  /// initialize fully the model
-  void initFull(const ModelOptions & options =
-                    default_structural_mechanics_model_options);
-
-  /// initialize the internal vectors
-  void initArrays();
+  void initSolver(TimeStepSolverType, NonLinearSolverType);
 
   /// initialize the model
   void initModel();
 
-  /// initialize the solver
-  void initSolver(SolverOptions & options = _solver_no_options);
-
-  /// initialize the stuff for the implicit solver
-  void initImplicit(bool dynamic = false,
-                    SolverOptions & solver_options = _solver_no_options);
-
   /// compute the stresses per elements
   void computeStresses();
 
   /// assemble the stiffness matrix
   void assembleStiffnessMatrix();
 
   /// assemble the mass matrix for consistent mass resolutions
   void assembleMass();
 
-  /// implicit time integration predictor
-  void implicitPred();
-
-  /// implicit time integration corrector
-  void implicitCorr();
-
   /// update the residual vector
   void updateResidual();
 
   /// solve the system
   void solve();
 
-  bool testConvergenceIncrement(Real tolerance);
-  bool testConvergenceIncrement(Real tolerance, Real & error);
-
   void computeRotationMatrix(const ElementType & type);
 
 protected:
   UInt getTangentStiffnessVoigtSize(const ElementType & type);
 
   /// compute Rotation Matrices
   template <const ElementType type>
   void computeRotationMatrix(__attribute__((unused)) Array<Real> & rotations) {}
 
-  /// compute A and solve @f[ A\delta u = f_ext - f_int @f]
-  template <NewmarkBeta::IntegrationSchemeCorrectorType type>
-  void solve(Array<Real> & increment,
-             __attribute__((unused)) Real block_val = 1.);
-
   /* ------------------------------------------------------------------------ */
   /* Mass (structural_mechanics_model_mass.cc) */
   /* ------------------------------------------------------------------------ */
 
   /// assemble the mass matrix for either _ghost or _not_ghost elements
   void assembleMass(GhostType ghost_type);
 
   /// computes rho
   void computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type);
 
   /// finish the computation of residual to solve in increment
   void updateResidualInternal();
 
   /* ------------------------------------------------------------------------ */
 
 private:
   template <ElementType type> inline UInt getTangentStiffnessVoigtSize();
 
   template <ElementType type> void assembleStiffnessMatrix();
 
   template <ElementType type> void assembleMass();
 
   template <ElementType type> void computeStressOnQuad();
 
   template <ElementType type>
   void computeTangentModuli(Array<Real> & tangent_moduli);
 
   template <ElementType type>
   void transferBMatrixToSymVoigtBMatrix(Array<Real> & B, bool local = false);
 
   template <ElementType type>
   void transferNMatrixToSymVoigtNMatrix(Array<Real> & N_matrix);
 
   /* ------------------------------------------------------------------------ */
   /* Dumpable interface                                                       */
   /* ------------------------------------------------------------------------ */
 public:
   virtual dumper::Field * createNodalFieldReal(const std::string & field_name,
                                                const std::string & group_name,
                                                bool padding_flag);
 
   virtual dumper::Field * createNodalFieldBool(const std::string & field_name,
                                                const std::string & group_name,
                                                bool padding_flag);
 
   virtual dumper::Field *
   createElementalField(const std::string & field_name,
                        const std::string & group_name, bool padding_flag,
                        const ElementKind & kind,
                        const std::string & fe_engine_id = "");
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// set the value of the time step
   void setTimeStep(Real time_step);
 
   /// return the dimension of the system space
   AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt);
 
   /// get the StructuralMechanicsModel::displacement vector
   AKANTU_GET_MACRO(Displacement, *displacement_rotation, Array<Real> &);
 
   /// get the StructuralMechanicsModel::velocity vector
   AKANTU_GET_MACRO(Velocity, *velocity, Array<Real> &);
 
   /// get    the    StructuralMechanicsModel::acceleration    vector,   updated
   /// by
   /// StructuralMechanicsModel::updateAcceleration
   AKANTU_GET_MACRO(Acceleration, *acceleration, Array<Real> &);
 
-  /// get the StructuralMechanicsModel::force vector (boundary forces)
-  AKANTU_GET_MACRO(Force, *force_momentum, Array<Real> &);
+  /// get the StructuralMechanicsModel::external_force vector
+  AKANTU_GET_MACRO(ExternalForce, *external_force_momentum, Array<Real> &);
+
+  /// get the StructuralMechanicsModel::internal_force vector (boundary forces)
+  AKANTU_GET_MACRO(InternalForce, *internal_force_momentum, Array<Real> &);
 
-  /// get the StructuralMechanicsModel::residual vector, computed by
-  /// StructuralMechanicsModel::updateResidual
-  AKANTU_GET_MACRO(Residual, *residual, const Array<Real> &);
   /// get the StructuralMechanicsModel::boundary vector
   AKANTU_GET_MACRO(BlockedDOFs, *blocked_dofs, Array<bool> &);
 
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(RotationMatrix, rotation_matrix, Real);
 
-  AKANTU_GET_MACRO(StiffnessMatrix, *stiffness_matrix, const SparseMatrix &);
-
-  AKANTU_GET_MACRO(MassMatrix, *mass_matrix, const SparseMatrix &);
-
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real);
 
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementMaterial, element_material, UInt);
 
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Set_ID, set_ID, UInt);
 
   void addMaterial(StructuralMaterial & material) {
     materials.push_back(material);
   }
 
   /**
    * @brief set the StructuralMechanicsModel::increment_flag  to on, the
    * activate the
    * update of the StructuralMechanicsModel::increment vector
    */
   void setIncrementFlagOn();
 
   /* ------------------------------------------------------------------------ */
   /* Boundaries (structural_mechanics_model_boundary.cc)                      */
   /* ------------------------------------------------------------------------ */
 public:
   /// Compute Linear load function set in global axis
   template <ElementType type>
   void computeForcesByGlobalTractionArray(const Array<Real> & tractions);
 
   /// Compute Linear load function set in local axis
   template <ElementType type>
   void computeForcesByLocalTractionArray(const Array<Real> & tractions);
 
   /// compute force vector from a function(x,y,momentum) that describe stresses
-  template <ElementType type>
-  void computeForcesFromFunction(BoundaryFunction in_function,
-                                 BoundaryFunctionType function_type);
-
-  /**
-    * 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);
-
-  /// test if the system is converged
-  template <SolveConvergenceCriteria criteria>
-  bool testConvergence(Real tolerance, Real & error);
+  // template <ElementType type>
+  // void computeForcesFromFunction(BoundaryFunction in_function,
+  //                                BoundaryFunctionType function_type);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   /// time step
   Real time_step;
 
   /// conversion coefficient form force/mass to acceleration
   Real f_m2a;
 
   /// displacements array
-  Array<Real> * displacement_rotation;
-
-  /// displacements array at the previous time step (used in finite deformation)
-  Array<Real> * previous_displacement;
+  Array<Real> * displacement_rotation{nullptr};
 
   /// velocities array
-  Array<Real> * velocity;
+  Array<Real> * velocity{nullptr};
 
   /// accelerations array
-  Array<Real> * acceleration;
+  Array<Real> * acceleration{nullptr};
 
   /// forces array
-  Array<Real> * force_momentum;
-
-  /// lumped mass array
-  Array<Real> * mass;
-
-  /// stress arraz
+  Array<Real> * internal_force_momentum{nullptr};
 
-  ElementTypeMapArray<Real> stress;
+  /// forces array
+  Array<Real> * external_force_momentum{nullptr};
 
-  /// residuals array
-  Array<Real> * residual;
+  /// lumped mass array
+  Array<Real> * mass{nullptr};
 
   /// boundaries array
-  Array<bool> * blocked_dofs;
+  Array<bool> * blocked_dofs{nullptr};
 
-  /// position of a dof in the K matrix
-  Array<Int> * equation_number;
+  /// stress array
+  ElementTypeMapArray<Real> stress;
 
   ElementTypeMapArray<UInt> element_material;
 
   // Define sets of beams
   ElementTypeMapArray<UInt> set_ID;
 
-  /// local equation_number to global
-  unordered_map<UInt, UInt>::type local_eq_num_to_global;
-
-  /// stiffness matrix
-  SparseMatrix * stiffness_matrix;
-
-  /// mass matrix
-  SparseMatrix * mass_matrix;
-
-  /// velocity damping matrix
-  SparseMatrix * velocity_damping_matrix;
-
-  /// jacobian matrix
-  SparseMatrix * jacobian_matrix;
-
-  /// increment of displacement
-  Array<Real> * increment;
-
-  /// solver for implicit
-  Solver * solver;
-
   /// number of degre of freedom
   UInt nb_degree_of_freedom;
 
   // Rotation matrix
   ElementTypeMapArray<Real> rotation_matrix;
 
   /// analysis method check the list in akantu::AnalysisMethod
   AnalysisMethod method;
 
   /// flag defining if the increment must be computed or not
   bool increment_flag;
 
-  /// integration scheme of second order used
-  IntegrationScheme2ndOrder * integrator;
-
-  /* --------------------------------------------------------------------------
-   */
+  /* ------------------------------------------------------------------------ */
   std::vector<StructuralMaterial> materials;
 };
 
-/* -------------------------------------------------------------------------- */
-/* inline functions                                                           */
-/* -------------------------------------------------------------------------- */
+} // namespace akantu
 
 #include "structural_mechanics_model_inline_impl.cc"
 
-/// standard output stream operator
-inline std::ostream & operator<<(std::ostream & stream,
-                                 const StructuralMechanicsModel & _this) {
-  _this.printself(stream);
-  return stream;
-}
-
-} // akantu
-
 #endif /* __AKANTU_STRUCTURAL_MECHANICS_MODEL_HH__ */
diff --git a/src/model/structural_mechanics/structural_mechanics_model_inline_impl.cc b/src/model/structural_mechanics/structural_mechanics_model_inline_impl.cc
index f75781a8e..0de86744a 100644
--- a/src/model/structural_mechanics/structural_mechanics_model_inline_impl.cc
+++ b/src/model/structural_mechanics/structural_mechanics_model_inline_impl.cc
@@ -1,615 +1,379 @@
 /**
  * @file   structural_mechanics_model_inline_impl.cc
  *
  * @author Fabian Barras <fabian.barras@epfl.ch>
  * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Damien Spielmann <damien.spielmann@epfl.ch>
  *
  * @date creation: Fri Jul 15 2011
  * @date last modification: Thu Oct 15 2015
  *
  * @brief  Implementation of inline functions of StructuralMechanicsModel
  *
  * @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/>.
  *
  */
-
 /* -------------------------------------------------------------------------- */
-template<ElementType type>
-inline UInt StructuralMechanicsModel::getTangentStiffnessVoigtSize() {
-  AKANTU_DEBUG_TO_IMPLEMENT();
-  return 0;
-}
+#include "structural_mechanics_model.hh"
+/* -------------------------------------------------------------------------- */
 
-template<>
-inline UInt StructuralMechanicsModel::getTangentStiffnessVoigtSize<_bernoulli_beam_2>() {
-  return 2;
-}
+#ifndef __AKANTU_STRUCTURAL_MECHANICS_MODEL_INLINE_IMPL_CC__
+#define __AKANTU_STRUCTURAL_MECHANICS_MODEL_INLINE_IMPL_CC__
 
-template<>
-inline UInt StructuralMechanicsModel::getTangentStiffnessVoigtSize<_bernoulli_beam_3>() {
-  return 4;
-}
+namespace akantu {
 
 /* -------------------------------------------------------------------------- */
-
-template<>
-inline UInt StructuralMechanicsModel::getTangentStiffnessVoigtSize<_kirchhoff_shell>() {
-  return 6;
+template <ElementType type>
+inline UInt StructuralMechanicsModel::getTangentStiffnessVoigtSize() {
+  AKANTU_DEBUG_TO_IMPLEMENT();
+  return 0;
 }
 
-
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void StructuralMechanicsModel::assembleStiffnessMatrix() {
   AKANTU_DEBUG_IN();
 
-  SparseMatrix & K = *stiffness_matrix;
-
-  UInt nb_element                 = getFEEngine().getMesh().getNbElement(type);
-  UInt nb_nodes_per_element       = Mesh::getNbNodesPerElement(type);
-  UInt nb_quadrature_points       = getFEEngine().getNbIntegrationPoints(type);
+  UInt nb_element = getFEEngine().getMesh().getNbElement(type);
+  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+  UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type);
 
   UInt tangent_size = getTangentStiffnessVoigtSize<type>();
 
-  Array<Real> * tangent_moduli =
-    new Array<Real>(nb_element * nb_quadrature_points, tangent_size * tangent_size,
-		     "tangent_stiffness_matrix");
+  Array<Real> tangent_moduli(nb_element * nb_quadrature_points,
+                             tangent_size * tangent_size, 0.,
+                             "tangent_stiffness_matrix");
 
-  tangent_moduli->clear();
-
-  computeTangentModuli<type>(*tangent_moduli);
+  computeTangentModuli<type>(tangent_moduli);
 
   /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
   UInt bt_d_b_size = nb_degree_of_freedom * nb_nodes_per_element;
 
-  Array<Real> * bt_d_b = new Array<Real>(nb_element*nb_quadrature_points,
-					   bt_d_b_size * bt_d_b_size,
-					   "B^t*D*B");
+  Array<Real> bt_d_b(nb_element * nb_quadrature_points,
+                     bt_d_b_size * bt_d_b_size, "B^t*D*B");
 
-  Array<Real> * b = new Array<Real>(nb_element*nb_quadrature_points,
-				      tangent_size*bt_d_b_size,
-				      "B");
+  Array<Real> b(nb_element * nb_quadrature_points, tangent_size * bt_d_b_size,
+                "B");
 
-  transferBMatrixToSymVoigtBMatrix<type>(*b);
+  transferBMatrixToSymVoigtBMatrix<type>(b);
 
   Matrix<Real> Bt_D(bt_d_b_size, tangent_size);
   Matrix<Real> BT(tangent_size, bt_d_b_size);
 
-  Array<Real>::matrix_iterator B = b->begin(tangent_size, bt_d_b_size);
-  Array<Real>::matrix_iterator D = tangent_moduli->begin(tangent_size, tangent_size);
-  Array<Real>::matrix_iterator Bt_D_B = bt_d_b->begin(bt_d_b_size, bt_d_b_size);
-  Array<Real>::matrix_iterator T = rotation_matrix(type).begin(bt_d_b_size, bt_d_b_size);
+  auto B = b.begin(tangent_size, bt_d_b_size);
+  auto D = tangent_moduli.begin(tangent_size, tangent_size);
+  auto Bt_D_B = bt_d_b.begin(bt_d_b_size, bt_d_b_size);
+  auto T = rotation_matrix(type).begin(bt_d_b_size, bt_d_b_size);
 
   for (UInt e = 0; e < nb_element; ++e, ++T) {
     for (UInt q = 0; q < nb_quadrature_points; ++q, ++B, ++D, ++Bt_D_B) {
       BT.mul<false, false>(*B, *T);
       Bt_D.mul<true, false>(BT, *D);
       Bt_D_B->mul<false, false>(Bt_D, BT);
     }
   }
 
-  delete b;
-  delete tangent_moduli;
-
   /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
-  Array<Real> * int_bt_d_b = new Array<Real>(nb_element,
-					   bt_d_b_size * bt_d_b_size,
-					   "int_B^t*D*B");
-
-  getFEEngine().integrate(*bt_d_b, *int_bt_d_b,
-		     bt_d_b_size * bt_d_b_size,
-		     type);
+  Array<Real> int_bt_d_b(nb_element, bt_d_b_size * bt_d_b_size, "int_B^t*D*B");
 
-  delete bt_d_b;
+  getFEEngine().integrate(bt_d_b, int_bt_d_b, bt_d_b_size * bt_d_b_size, type);
 
-  getFEEngine().assembleMatrix(*int_bt_d_b, K, nb_degree_of_freedom, type);
-
-  delete int_bt_d_b;
+  getDOFManager().assembleElementalMatricesToMatrix("K", "displacement",
+                                                    int_bt_d_b, type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
-template<ElementType type>
-void StructuralMechanicsModel::computeTangentModuli(Array<Real> & tangent_moduli) {
+template <ElementType type>
+void StructuralMechanicsModel::computeTangentModuli(Array<Real> &) {
   AKANTU_DEBUG_TO_IMPLEMENT();
 }
 
-
 /* -------------------------------------------------------------------------- */
-template<ElementType type>
-void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix(Array<Real> & b, bool local) {
+template <ElementType type>
+void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix(Array<Real> &,
+                                                                bool) {
   AKANTU_DEBUG_TO_IMPLEMENT();
 }
 
 /* -------------------------------------------------------------------------- */
-template<ElementType type>
+template <ElementType type>
 void StructuralMechanicsModel::computeStressOnQuad() {
   AKANTU_DEBUG_IN();
 
-  Array<Real> & sigma  = stress(type, _not_ghost);
+  Array<Real> & sigma = stress(type, _not_ghost);
 
   sigma.clear();
   const Mesh & mesh = getFEEngine().getMesh();
 
-  UInt nb_element                 = mesh.getNbElement(type);
-  UInt nb_nodes_per_element       = Mesh::getNbNodesPerElement(type);
-  UInt nb_quadrature_points       = getFEEngine().getNbIntegrationPoints(type);
+  UInt nb_element = mesh.getNbElement(type);
+  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+  UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type);
 
   UInt tangent_size = getTangentStiffnessVoigtSize<type>();
 
   Array<Real> * tangent_moduli =
-    new Array<Real>(nb_element*nb_quadrature_points, tangent_size * tangent_size,
-		     "tangent_stiffness_matrix");
+      new Array<Real>(nb_element * nb_quadrature_points,
+                      tangent_size * tangent_size, "tangent_stiffness_matrix");
   tangent_moduli->clear();
 
   computeTangentModuli<type>(*tangent_moduli);
 
   /// compute DB
   UInt d_b_size = nb_degree_of_freedom * nb_nodes_per_element;
 
-  Array<Real> * d_b = new Array<Real>(nb_element*nb_quadrature_points,
-					d_b_size * tangent_size,
-					"D*B");
+  Array<Real> * d_b = new Array<Real>(nb_element * nb_quadrature_points,
+                                      d_b_size * tangent_size, "D*B");
 
-  Array<Real> * b = new Array<Real>(nb_element*nb_quadrature_points,
-				      tangent_size*d_b_size,
-				      "B");
+  Array<Real> * b = new Array<Real>(nb_element * nb_quadrature_points,
+                                    tangent_size * d_b_size, "B");
 
   transferBMatrixToSymVoigtBMatrix<type>(*b);
 
   Array<Real>::matrix_iterator B = b->begin(tangent_size, d_b_size);
-  Array<Real>::matrix_iterator D = tangent_moduli->begin(tangent_size, tangent_size);
+  Array<Real>::matrix_iterator D =
+      tangent_moduli->begin(tangent_size, tangent_size);
   Array<Real>::matrix_iterator D_B = d_b->begin(tangent_size, d_b_size);
 
   for (UInt e = 0; e < nb_element; ++e) {
     for (UInt q = 0; q < nb_quadrature_points; ++q, ++B, ++D, ++D_B) {
       D_B->mul<false, false>(*D, *B);
     }
   }
 
   delete b;
   delete tangent_moduli;
 
   /// compute DBu
   D_B = d_b->begin(tangent_size, d_b_size);
-  Array<Real>::iterator< Vector<Real> > DBu = sigma.begin(tangent_size);
-  Vector<Real> ul (d_b_size);
+  Array<Real>::iterator<Vector<Real>> DBu = sigma.begin(tangent_size);
+  Vector<Real> ul(d_b_size);
 
   Array<Real> u_el(0, d_b_size);
-  FEEngine::extractNodalToElementField(mesh, *displacement_rotation, u_el, type);
+  FEEngine::extractNodalToElementField(mesh, *displacement_rotation, u_el,
+                                       type);
 
   Array<Real>::vector_iterator ug = u_el.begin(d_b_size);
-  Array<Real>::matrix_iterator T = rotation_matrix(type).begin(d_b_size, d_b_size);
+  Array<Real>::matrix_iterator T =
+      rotation_matrix(type).begin(d_b_size, d_b_size);
 
   for (UInt e = 0; e < nb_element; ++e, ++T, ++ug) {
     ul.mul<false>(*T, *ug);
     for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_B, ++DBu) {
       DBu->mul<false>(*D_B, ul);
     }
   }
 
   delete d_b;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
-template<ElementType type>
-void StructuralMechanicsModel::computeForcesByLocalTractionArray(const Array<Real> & tractions) {
+template <ElementType type>
+void StructuralMechanicsModel::computeForcesByLocalTractionArray(
+    const Array<Real> & tractions) {
   AKANTU_DEBUG_IN();
 
   UInt nb_element = getFEEngine().getMesh().getNbElement(type);
-  UInt nb_nodes_per_element = getFEEngine().getMesh().getNbNodesPerElement(type);
+  UInt nb_nodes_per_element =
+      getFEEngine().getMesh().getNbNodesPerElement(type);
   UInt nb_quad = getFEEngine().getNbIntegrationPoints(type);
 
   // check dimension match
-  AKANTU_DEBUG_ASSERT(Mesh::getSpatialDimension(type) == getFEEngine().getElementDimension(),
-		      "element type dimension does not match the dimension of boundaries : " <<
-		      getFEEngine().getElementDimension() << " != " <<
-		      Mesh::getSpatialDimension(type));
+  AKANTU_DEBUG_ASSERT(
+      Mesh::getSpatialDimension(type) == getFEEngine().getElementDimension(),
+      "element type dimension does not match the dimension of boundaries : "
+          << getFEEngine().getElementDimension()
+          << " != " << Mesh::getSpatialDimension(type));
 
   // check size of the vector
-  AKANTU_DEBUG_ASSERT(tractions.size() == nb_quad*nb_element,
-		      "the size of the vector should be the total number of quadrature points");
+  AKANTU_DEBUG_ASSERT(
+      tractions.size() == nb_quad * nb_element,
+      "the size of the vector should be the total number of quadrature points");
 
   // check number of components
   AKANTU_DEBUG_ASSERT(tractions.getNbComponent() == nb_degree_of_freedom,
-		      "the number of components should be the spatial dimension of the problem");
-
+                      "the number of components should be the spatial "
+                      "dimension of the problem");
 
-  Array<Real> Nvoigt(nb_element * nb_quad, nb_degree_of_freedom * nb_degree_of_freedom * nb_nodes_per_element);
+  Array<Real> Nvoigt(nb_element * nb_quad, nb_degree_of_freedom *
+                                               nb_degree_of_freedom *
+                                               nb_nodes_per_element);
   transferNMatrixToSymVoigtNMatrix<type>(Nvoigt);
 
-  Array<Real>::const_matrix_iterator N_it = Nvoigt.begin(nb_degree_of_freedom,
-								   nb_degree_of_freedom * nb_nodes_per_element);
-  Array<Real>::const_matrix_iterator T_it = rotation_matrix(type).begin(nb_degree_of_freedom * nb_nodes_per_element,
-										  nb_degree_of_freedom * nb_nodes_per_element);
-  Array<Real>::const_vector_iterator te_it = tractions.begin(nb_degree_of_freedom);
+  auto N_it = Nvoigt.begin(nb_degree_of_freedom,
+                           nb_degree_of_freedom * nb_nodes_per_element);
+  auto T_it =
+      rotation_matrix(type).begin(nb_degree_of_freedom * nb_nodes_per_element,
+                                  nb_degree_of_freedom * nb_nodes_per_element);
+  auto te_it = tractions.begin(nb_degree_of_freedom);
 
-  Array<Real> funct(nb_element * nb_quad, nb_degree_of_freedom * nb_nodes_per_element, 0.);
-  Array<Real>::iterator< Vector<Real> > Fe_it = funct.begin(nb_degree_of_freedom * nb_nodes_per_element);
+  Array<Real> funct(nb_element * nb_quad,
+                    nb_degree_of_freedom * nb_nodes_per_element, 0.);
+  auto Fe_it = funct.begin(nb_degree_of_freedom * nb_nodes_per_element);
 
   Vector<Real> fe(nb_degree_of_freedom * nb_nodes_per_element);
   for (UInt e = 0; e < nb_element; ++e, ++T_it) {
     const Matrix<Real> & T = *T_it;
     for (UInt q = 0; q < nb_quad; ++q, ++N_it, ++te_it, ++Fe_it) {
       const Matrix<Real> & N = *N_it;
       const Vector<Real> & te = *te_it;
       Vector<Real> & Fe = *Fe_it;
 
       // compute N^t tl
       fe.mul<true>(N, te);
       // turn N^t tl back in the global referential
       Fe.mul<true>(T, fe);
     }
   }
 
   // allocate the vector that will contain the integrated values
-  std::stringstream name;
-  name << id << type << ":integral_boundary";
-  Array<Real> int_funct(nb_element, nb_degree_of_freedom * nb_nodes_per_element, name.str());
+  Array<Real> int_funct(nb_element, nb_degree_of_freedom * nb_nodes_per_element,
+                        std::string(id + ":integral_boundary"));
 
-  //do the integration
-  getFEEngine().integrate(funct, int_funct, nb_degree_of_freedom*nb_nodes_per_element, type);
+  // do the integration
+  getFEEngine().integrate(funct, int_funct,
+                          nb_degree_of_freedom * nb_nodes_per_element, type);
 
   // assemble the result into force vector
-  getFEEngine().assembleArray(int_funct,*force_momentum,
-			  dof_synchronizer->getLocalDOFEquationNumbers(),
-			  nb_degree_of_freedom, type);
+  getDOFManager().assembleElementalArrayLocalArray(
+      int_funct, *internal_force_momentum, type, _not_ghost);
+
   AKANTU_DEBUG_OUT();
 }
 
-
 /* -------------------------------------------------------------------------- */
-template<ElementType type>
-void StructuralMechanicsModel::computeForcesByGlobalTractionArray(const Array<Real> & traction_global){
- AKANTU_DEBUG_IN();
+template <ElementType type>
+void StructuralMechanicsModel::computeForcesByGlobalTractionArray(
+    const Array<Real> & traction_global) {
+  AKANTU_DEBUG_IN();
   UInt nb_element = getFEEngine().getMesh().getNbElement(type);
   UInt nb_quad = getFEEngine().getNbIntegrationPoints(type);
-  UInt nb_nodes_per_element = getFEEngine().getMesh().getNbNodesPerElement(type);
+  UInt nb_nodes_per_element =
+      getFEEngine().getMesh().getNbNodesPerElement(type);
 
   std::stringstream name;
   name << id << ":structuralmechanics:imposed_linear_load";
-  Array<Real> traction_local(nb_element*nb_quad, nb_degree_of_freedom, name.str());
+  Array<Real> traction_local(nb_element * nb_quad, nb_degree_of_freedom,
+                             name.str());
 
-  Array<Real>::const_matrix_iterator T_it = rotation_matrix(type).begin(nb_degree_of_freedom * nb_nodes_per_element,
-										  nb_degree_of_freedom * nb_nodes_per_element);
+  auto T_it =
+      rotation_matrix(type).begin(nb_degree_of_freedom * nb_nodes_per_element,
+                                  nb_degree_of_freedom * nb_nodes_per_element);
 
-  Array<Real>::const_iterator< Vector<Real> > Te_it = traction_global.begin(nb_degree_of_freedom);
-  Array<Real>::iterator< Vector<Real> > te_it = traction_local.begin(nb_degree_of_freedom);
+  auto Te_it = traction_global.begin(nb_degree_of_freedom);
+  auto te_it = traction_local.begin(nb_degree_of_freedom);
 
   Matrix<Real> R(nb_degree_of_freedom, nb_degree_of_freedom);
   for (UInt e = 0; e < nb_element; ++e, ++T_it) {
     const Matrix<Real> & T = *T_it;
     for (UInt i = 0; i < nb_degree_of_freedom; ++i)
       for (UInt j = 0; j < nb_degree_of_freedom; ++j)
-	R(i, j) = T(i, j);
+        R(i, j) = T(i, j);
 
     for (UInt q = 0; q < nb_quad; ++q, ++Te_it, ++te_it) {
       const Vector<Real> & Te = *Te_it;
       Vector<Real> & te = *te_it;
       // turn the traction in the local referential
       te.mul<false>(R, Te);
     }
   }
 
   computeForcesByLocalTractionArray<type>(traction_local);
 
   AKANTU_DEBUG_OUT();
-
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * @param myf pointer  to a function that fills a  vector/tensor with respect to
  * passed coordinates
  */
-template<ElementType type>
-inline void StructuralMechanicsModel::computeForcesFromFunction(BoundaryFunction myf,
-							 BoundaryFunctionType function_type){
-  /** function type is
-   ** _bft_forces : linear load is given
-   ** _bft_stress : stress function is given -> Not already done for this kind of model
-   */
-
-  std::stringstream name;
-  name << id << ":structuralmechanics:imposed_linear_load";
-  Array<Real> lin_load(0, nb_degree_of_freedom,name.str());
-  name.clear();
-
-  UInt offset = nb_degree_of_freedom;
-
-  //prepare the loop over element types
-  UInt nb_quad           = getFEEngine().getNbIntegrationPoints(type);
-  UInt nb_element        = getFEEngine().getMesh().getNbElement(type);
-
-  name.clear();
-  name << id << ":structuralmechanics:quad_coords";
-  Array<Real> quad_coords(nb_element * nb_quad, spatial_dimension, "quad_coords");
-
-
-  getFEEngineClass<MyFEEngineType>().getShapeFunctions().interpolateOnIntegrationPoints<type>(getFEEngine().getMesh().getNodes(),
-										quad_coords,
-										spatial_dimension);
-  getFEEngineClass<MyFEEngineType>().getShapeFunctions().interpolateOnIntegrationPoints<type>(getFEEngine().getMesh().getNodes(),
-										quad_coords,
-										spatial_dimension,
-										_not_ghost,
-										empty_filter,
-										true,
-										0,
-										1,
-										1);
-  if(spatial_dimension == 3)
-    getFEEngineClass<MyFEEngineType>().getShapeFunctions().interpolateOnIntegrationPoints<type>(getFEEngine().getMesh().getNodes(),
-										  quad_coords,
-										  spatial_dimension,
-										  _not_ghost,
-										  empty_filter,
-										  true,
-										  0,
-										  2,
-										  2);
-  lin_load.resize(nb_element*nb_quad);
-  Real * imposed_val = lin_load.storage();
-
-  /// sigma/load on each quadrature points
-  Real * qcoord = quad_coords.storage();
-  for (UInt el = 0; el < nb_element; ++el) {
-    for (UInt q = 0; q < nb_quad; ++q) {
-      myf(qcoord, imposed_val, NULL, 0);
-      imposed_val += offset;
-      qcoord += spatial_dimension;
-    }
-  }
-
-  switch(function_type) {
-  case _bft_traction_local:
-    computeForcesByLocalTractionArray<type>(lin_load); break;
-  case _bft_traction:
-    computeForcesByGlobalTractionArray<type>(lin_load); break;
-  default: break;
-  }
-}
-
-/* -------------------------------------------------------------------------- */
-template<>
-inline void StructuralMechanicsModel::assembleMass<_bernoulli_beam_2>() {
-  AKANTU_DEBUG_IN();
-  
-  GhostType ghost_type = _not_ghost;
-  ElementType type = _bernoulli_beam_2;
-  MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>();
-  UInt nb_element                 = getFEEngine().getMesh().getNbElement(type);
-  UInt nb_nodes_per_element       = Mesh::getNbNodesPerElement(type);
-  UInt nb_quadrature_points       = getFEEngine().getNbIntegrationPoints(type);
-  UInt nb_fields_to_interpolate = getTangentStiffnessVoigtSize<_bernoulli_beam_2>();
-
-  UInt nt_n_field_size = nb_degree_of_freedom * nb_nodes_per_element;
-
-  Array<Real> * n = new Array<Real>(nb_element*nb_quadrature_points,
-				    nb_fields_to_interpolate * nt_n_field_size,
-				    "N");
-  n->clear();
-  Array<Real> * rho_field = new Array<Real>(nb_element*nb_quadrature_points,
-					  "Rho");
-  rho_field->clear();
-  computeRho(*rho_field, type, _not_ghost);
-  
-  bool sign = true;
-  
-/* -------------------------------------------------------------------------- */
-  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n, 0, 0, 0, sign, ghost_type); // Ni ui -> u
-
-  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n, 1, 1, 1, sign, ghost_type); // Mi vi -> v
-  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n, 2, 2, 1, sign, ghost_type); // Li Theta_i -> v
-/* -------------------------------------------------------------------------- */
-
-  fem.assembleFieldMatrix(*rho_field, nb_degree_of_freedom, *mass_matrix, n, rotation_matrix, type, ghost_type);
-  
-  delete n;
-  delete rho_field;
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template<>
-inline void StructuralMechanicsModel::assembleMass<_bernoulli_beam_3>() {
-  AKANTU_DEBUG_IN();
-
-  GhostType ghost_type = _not_ghost;
-  ElementType type = _bernoulli_beam_3;
-  MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>();
-  UInt nb_element                 = getFEEngine().getMesh().getNbElement(type);
-  UInt nb_nodes_per_element       = Mesh::getNbNodesPerElement(type);
-  UInt nb_quadrature_points       = getFEEngine().getNbIntegrationPoints(type);
-  UInt nb_fields_to_interpolate = getTangentStiffnessVoigtSize<_bernoulli_beam_3>();
-
-  UInt nt_n_field_size = nb_degree_of_freedom * nb_nodes_per_element; 
-
-  Array<Real> * n = new Array<Real>(nb_element*nb_quadrature_points,
-				    nb_fields_to_interpolate * nt_n_field_size,
-				    "N");
-  n->clear();
-  Array<Real> * rho_field = new Array<Real>(nb_element * nb_quadrature_points,
-					   "Rho");
-  rho_field->clear();
-  computeRho(*rho_field, type, _not_ghost);
-  
-/* -------------------------------------------------------------------------- */
-  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n, 0, 0, 0, true, ghost_type); // Ni ui ->         u
-
-  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n, 1, 1, 1, true, ghost_type); // Mi vi ->         v
-  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n, 2, 5, 1, true, ghost_type); // Li Theta_z_i ->  v
-
-  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n, 1, 2, 2, true, ghost_type); // Mi wi ->        w
-  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n, 2, 4, 2, false,ghost_type);// -Li Theta_y_i ->  w
-
-  fem.computeShapesMatrix(type, nb_degree_of_freedom, nb_nodes_per_element, n, 0, 3, 3, true, ghost_type); // Ni Theta_x_i->Theta_x
-/* -------------------------------------------------------------------------- */
-
-  fem.assembleFieldMatrix(*rho_field, nb_degree_of_freedom, *mass_matrix, n, rotation_matrix, type, ghost_type);
-  
-  delete n;
-  delete rho_field;
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template<>
-inline void StructuralMechanicsModel::assembleMass<_kirchhoff_shell>() {
-
-  AKANTU_DEBUG_TO_IMPLEMENT();
-
-}
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria>
-bool StructuralMechanicsModel::solveStep(Real tolerance,
-					 UInt max_iteration) {
-  Real error = 0.;
-  return this->template solveStep<cmethod,criteria>(tolerance,
-						    error,
-						    max_iteration);
-}
-
-/* -------------------------------------------------------------------------- */
-template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria>
-bool StructuralMechanicsModel::solveStep(Real tolerance, Real & error, UInt max_iteration) {
-  
-  this->implicitPred();
-  this->updateResidual();
-
-  AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL,
-		      "You should first initialize the implicit solver and assemble the stiffness matrix");
-
-  if (method==_implicit_dynamic) {
-    AKANTU_DEBUG_ASSERT(mass_matrix != NULL,
-			"You should first initialize the implicit solver and assemble the mass matrix");
-  }
-
-  switch (cmethod) {
-  case _scm_newton_raphson_tangent:
-  case _scm_newton_raphson_tangent_not_computed:
-    break;
-  case _scm_newton_raphson_tangent_modified:
-    this->assembleStiffnessMatrix();
-    break;
-  default:
-    AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not been implemented!");
-  }
-
-  UInt iter = 0;
-  bool converged = false;
-  error = 0.;
-  if(criteria == _scc_residual) {
-    converged = this->testConvergence<criteria> (tolerance, error);
-    if(converged) return converged;
-  }
-
-  do {
-    if (cmethod == _scm_newton_raphson_tangent)
-      this->assembleStiffnessMatrix();
-
-    solve<NewmarkBeta::_displacement_corrector> (*increment);
-
-    this->implicitCorr();
-
-    if(criteria == _scc_residual) this->updateResidual();
-
-    converged = this->testConvergence<criteria> (tolerance, error);
-
-    if(criteria == _scc_increment && !converged) this->updateResidual();
-    //this->dump();
-
-    iter++;
-    AKANTU_DEBUG_INFO("[" << criteria << "] Convergence iteration "
-		      << std::setw(std::log10(max_iteration)) << iter
-		      << ": error " << error << (converged ? " < " : " > ") << tolerance);
-
-  } while (!converged && iter < max_iteration);
-
-
-  if (converged) {
-    
-  } else if(iter == max_iteration) {
-    AKANTU_DEBUG_WARNING("[" << criteria << "] Convergence not reached after "
-                         << std::setw(std::log10(max_iteration)) << iter <<
-                         " iteration" << (iter == 1 ? "" : "s") << "!" << std::endl);
-  }
-
-  return converged;
-}
-/* -------------------------------------------------------------------------- */
-template<NewmarkBeta::IntegrationSchemeCorrectorType type>
-void StructuralMechanicsModel::solve(Array<Real> & increment,
-                                Real block_val) {
-  jacobian_matrix->clear();
-
-  //updateResidualInternal(); //doesn't do anything for static
-
-  Real c = 0.,d = 0.,e = 0.;
-
-  if(method == _static) {
-    AKANTU_DEBUG_INFO("Solving K inc = r");
-    e = 1.;
-  } else {
-    AKANTU_DEBUG_INFO("Solving (c M + d C + e K) inc = r");
-
-    NewmarkBeta * nmb_int = dynamic_cast<NewmarkBeta *>(integrator);
-    c = nmb_int->getAccelerationCoefficient<type>(time_step);
-    d = nmb_int->getVelocityCoefficient<type>(time_step);
-    e = nmb_int->getDisplacementCoefficient<type>(time_step);
-  }
-
-  // J = c M + d C + e K
-  if(stiffness_matrix)
-    jacobian_matrix->add(*stiffness_matrix, e);
-
-//  if(type != NewmarkBeta::_acceleration_corrector)
-//    jacobian_matrix->add(*stiffness_matrix, e);
-
-  if(mass_matrix)
-    jacobian_matrix->add(*mass_matrix, c);
-
-#if !defined(AKANTU_NDEBUG)
-  if(mass_matrix && AKANTU_DEBUG_TEST(dblDump))
-    mass_matrix->saveMatrix("M.mtx");
-#endif
-
-  if(velocity_damping_matrix)
-    jacobian_matrix->add(*velocity_damping_matrix, d);
-
-  jacobian_matrix->applyBoundary(*blocked_dofs);
-
-#if !defined(AKANTU_NDEBUG)
-  if(AKANTU_DEBUG_TEST(dblDump))
-    jacobian_matrix->saveMatrix("J.mtx");
-#endif
-
-  solver->setRHS(*residual);
-  // solve @f[ J \delta w = r @f]
-  solver->factorize();
-  solver->solve(increment);
-}
+// template <ElementType type>
+// inline void StructuralMechanicsModel::computeForcesFromFunction(
+//     BoundaryFunction myf, BoundaryFunctionType function_type) {
+//   /** function type is
+//    ** _bft_forces : linear load is given
+//    ** _bft_stress : stress function is given -> Not already done for this kind
+//    *of model
+//    */
+
+//   std::stringstream name;
+//   name << id << ":structuralmechanics:imposed_linear_load";
+//   Array<Real> lin_load(0, nb_degree_of_freedom, name.str());
+//   name.clear();
+
+//   UInt offset = nb_degree_of_freedom;
+
+//   // prepare the loop over element types
+//   UInt nb_quad = getFEEngine().getNbIntegrationPoints(type);
+//   UInt nb_element = getFEEngine().getMesh().getNbElement(type);
+
+//   name.clear();
+//   name << id << ":structuralmechanics:quad_coords";
+//   Array<Real> quad_coords(nb_element * nb_quad, spatial_dimension,
+//                           "quad_coords");
+
+//   getFEEngineClass<MyFEEngineType>()
+//       .getShapeFunctions()
+//       .interpolateOnIntegrationPoints<type>(mesh.getNodes(), quad_coords,
+//                                             spatial_dimension);
+//   getFEEngineClass<MyFEEngineType>()
+//       .getShapeFunctions()
+//       .interpolateOnIntegrationPoints<type>(mesh.getNodes(), quad_coords,
+//                                             spatial_dimension, _not_ghost,
+//                                             empty_filter, true, 0, 1, 1);
+//   if (spatial_dimension == 3)
+//     getFEEngineClass<MyFEEngineType>()
+//         .getShapeFunctions()
+//         .interpolateOnIntegrationPoints<type>(
+//             getFEEngine().getMesh().getNodes(), quad_coords, spatial_dimension,
+//             _not_ghost, empty_filter, true, 0, 2, 2);
+//   lin_load.resize(nb_element * nb_quad);
+//   Real * imposed_val = lin_load.storage();
+
+//   /// sigma/load on each quadrature points
+//   Real * qcoord = quad_coords.storage();
+//   for (UInt el = 0; el < nb_element; ++el) {
+//     for (UInt q = 0; q < nb_quad; ++q) {
+//       myf(qcoord, imposed_val, NULL, 0);
+//       imposed_val += offset;
+//       qcoord += spatial_dimension;
+//     }
+//   }
+
+//   switch (function_type) {
+//   case _bft_traction_local:
+//     computeForcesByLocalTractionArray<type>(lin_load);
+//     break;
+//   case _bft_traction:
+//     computeForcesByGlobalTractionArray<type>(lin_load);
+//     break;
+//   default:
+//     break;
+//   }
+// }
+
+} // namespace akantu
+
+#endif /* __AKANTU_STRUCTURAL_MECHANICS_MODEL_INLINE_IMPL_CC__ */
diff --git a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_kirchhoff_shell_patch_test_4_5_5.cc b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_kirchhoff_shell_patch_test_4_5_5.cc
index a9a18f2ef..30cd35597 100644
--- a/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_kirchhoff_shell_patch_test_4_5_5.cc
+++ b/test/test_model/test_structural_mechanics_model/test_structural_mechanics_model_kirchhoff_shell_patch_test_4_5_5.cc
@@ -1,252 +1,249 @@
 /**
  * @file   test_structural_mechanics_model_kirchhoff_shell_patch_test_4_5_5.cc
  *
  * @author Damien Spielmann <damien.spielmann@epfl.ch>
  *
  * @date creation: Thu Feb 21 2013
  * @date last modification: Sun Oct 19 2014
  *
- * @brief  patch test exemple 4.5.5 c.f. modelisation des structures par éléments finis J.-L. Batoz/G Dhatt
+ * @brief  patch test exemple 4.5.5 c.f. modelisation des structures par
+ * éléments finis J.-L. Batoz/G Dhatt
  *
  * @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 <limits>
 #include <fstream>
+#include <limits>
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
+#include "material.hh"
 #include "mesh.hh"
 #include "mesh_io.hh"
 #include "mesh_io_msh.hh"
 #include "structural_mechanics_model.hh"
-#include "material.hh"
 /* -------------------------------------------------------------------------- */
 
 #define TYPE _kirchhoff_shell
 
 using namespace akantu;
 
-
-int main(int argc, char *argv[]){
+int main(int argc, char * argv[]) {
   initialize(argc, argv);
   Mesh shell(3);
   debug::setDebugLevel(dblWarning);
-  std::cout<<"Initialisation"<<std::endl;
-  /* -------------------------------------------------------------------------- */
+  std::cout << "Initialisation" << std::endl;
+  /* --------------------------------------------------------------------------
+   */
   // Defining the mesh
-  
-  UInt nb_nodes=5;
-  UInt nb_element=4;
+
+  UInt nb_nodes = 5;
+  UInt nb_element = 4;
 
   Array<Real> & nodes = const_cast<Array<Real> &>(shell.getNodes());
   nodes.resize(nb_nodes);
 
-  Real a=20.;
-  Real b=10.;
+  Real a = 20.;
+  Real b = 10.;
 
-  nodes(0,0)=0.;
-  nodes(0,1)=0.;
-  nodes(0,2)=0.;
+  nodes(0, 0) = 0.;
+  nodes(0, 1) = 0.;
+  nodes(0, 2) = 0.;
 
-  nodes(1,0)=2*a;
-  nodes(1,1)=0.;
-  nodes(1,2)=0.;
+  nodes(1, 0) = 2 * a;
+  nodes(1, 1) = 0.;
+  nodes(1, 2) = 0.;
 
-  nodes(2,0)=0.;
-  nodes(2,1)=2*b;
-  nodes(2,2)=0.;
+  nodes(2, 0) = 0.;
+  nodes(2, 1) = 2 * b;
+  nodes(2, 2) = 0.;
 
-  nodes(3,0)=2*a;
-  nodes(3,1)=2*b;
-  nodes(3,2)=0.;
+  nodes(3, 0) = 2 * a;
+  nodes(3, 1) = 2 * b;
+  nodes(3, 2) = 0.;
 
-  nodes(4,0)=15.;
-  nodes(4,1)=15.;
-  nodes(4,2)=0.;
+  nodes(4, 0) = 15.;
+  nodes(4, 1) = 15.;
+  nodes(4, 2) = 0.;
 
   shell.addConnectivityType(TYPE);
-  Array<UInt> & connectivity = const_cast<Array<UInt> &>(shell.getConnectivity(TYPE));
+  Array<UInt> & connectivity =
+      const_cast<Array<UInt> &>(shell.getConnectivity(TYPE));
 
   connectivity.resize(nb_element);
 
-  
-  
-    
-  connectivity(0,0)=1;
-  connectivity(0,1)=3;
-  connectivity(0,2)=4;
-
-  connectivity(1,0)=3;
-  connectivity(1,1)=2;
-  connectivity(1,2)=4;
+  connectivity(0, 0) = 1;
+  connectivity(0, 1) = 3;
+  connectivity(0, 2) = 4;
 
-  connectivity(2,0)=2;
-  connectivity(2,1)=4;
-  connectivity(2,2)=0;
+  connectivity(1, 0) = 3;
+  connectivity(1, 1) = 2;
+  connectivity(1, 2) = 4;
 
-  connectivity(3,0)=0;
-  connectivity(3,1)=1;
-  connectivity(3,2)=4;
+  connectivity(2, 0) = 2;
+  connectivity(2, 1) = 4;
+  connectivity(2, 2) = 0;
 
-  
+  connectivity(3, 0) = 0;
+  connectivity(3, 1) = 1;
+  connectivity(3, 2) = 4;
 
   akantu::MeshIOMSH mesh_io;
   mesh_io.write("b_beam_3_12_10_13.msh", shell);
-  std::cout<<"Mesh definition"<<std::endl;
-  /* -------------------------------------------------------------------------- */
+  std::cout << "Mesh definition" << std::endl;
+  /* --------------------------------------------------------------------------
+   */
   // Defining the materials
 
-
   akantu::StructuralMechanicsModel model(shell); // ä döfinir
 
   StructuralMaterial mat1;
-  mat1.E=1000;
-  mat1.nu=0.3;
-  mat1.t=1;
+  mat1.E = 1000;
+  mat1.nu = 0.3;
+  mat1.t = 1;
 
   model.addMaterial(mat1);
 
-  std::cout<<"Material Definition"<<std::endl;
-  /* -------------------------------------------------------------------------- */
+  std::cout << "Material Definition" << std::endl;
+  /* --------------------------------------------------------------------------
+   */
   // Defining the deplacement
 
   model.initFull();
 
   // Array<Real> & forces = model.getForce();
   Array<Real> & displacement = model.getDisplacement();
   Array<bool> & boundary = model.getBlockedDOFs();
 
-
-  displacement(0,0)=0;
-  displacement(0,1)=0;
-  displacement(0,2)=0;
-  displacement(0,3)=0;
-  displacement(0,4)=0;
-
-  displacement(1,0)=0;
-  displacement(1,1)=0;
-  displacement(1,2)=-800;
-  displacement(1,3)=-40;
-  displacement(1,4)=-20;
-
-  displacement(2,0)=0;
-  displacement(2,1)=0;
-  displacement(2,2)=-200;
-  displacement(2,3)=-10;
-  displacement(2,4)=-20;
-
-  displacement(3,0)=0;
-  displacement(3,1)=0;
-  displacement(3,2)=-1400;
-  displacement(3,3)=-50;
-  displacement(3,4)=-40;
+  displacement(0, 0) = 0;
+  displacement(0, 1) = 0;
+  displacement(0, 2) = 0;
+  displacement(0, 3) = 0;
+  displacement(0, 4) = 0;
+
+  displacement(1, 0) = 0;
+  displacement(1, 1) = 0;
+  displacement(1, 2) = -800;
+  displacement(1, 3) = -40;
+  displacement(1, 4) = -20;
+
+  displacement(2, 0) = 0;
+  displacement(2, 1) = 0;
+  displacement(2, 2) = -200;
+  displacement(2, 3) = -10;
+  displacement(2, 4) = -20;
+
+  displacement(3, 0) = 0;
+  displacement(3, 1) = 0;
+  displacement(3, 2) = -1400;
+  displacement(3, 3) = -50;
+  displacement(3, 4) = -40;
 
   /*displacement(4,0)=0;
     displacement(4,1)=0;*/
   /* displacement(4,2)=;
   displacement(4,3)=;
   displacement(4,4)=;*/
-    
- /* -------------------------------------------------------------------------- */
+
+  /* --------------------------------------------------------------------------
+   */
   // Defining the boundary conditions
 
- boundary(0,0) = true;
-  boundary(0,1) = true;
-  boundary(0,2) = true;
-  boundary(0,3) = true;
-  boundary(0,4) = true;
-  boundary(0,5) = true;
-
-  boundary(1,0) = true;
-  boundary(1,1) = true;
-  boundary(1,2) = true;
-  boundary(1,3) = true;
-  boundary(1,4) = true;
-  boundary(1,5) = true;
-
-  boundary(2,0) = true;
-  boundary(2,1) = true;
-  boundary(2,2) = true;
-  boundary(2,3) = true;
-  boundary(2,4) = true;
-  boundary(2,5) = true;
-
-  boundary(3,0) = true;
-  boundary(3,1) = true;
-  boundary(3,2) = true;
-  boundary(3,3) = true;
-  boundary(3,4) = true;
-  boundary(3,5) = true;
+  boundary(0, 0) = true;
+  boundary(0, 1) = true;
+  boundary(0, 2) = true;
+  boundary(0, 3) = true;
+  boundary(0, 4) = true;
+  boundary(0, 5) = true;
+
+  boundary(1, 0) = true;
+  boundary(1, 1) = true;
+  boundary(1, 2) = true;
+  boundary(1, 3) = true;
+  boundary(1, 4) = true;
+  boundary(1, 5) = true;
+
+  boundary(2, 0) = true;
+  boundary(2, 1) = true;
+  boundary(2, 2) = true;
+  boundary(2, 3) = true;
+  boundary(2, 4) = true;
+  boundary(2, 5) = true;
+
+  boundary(3, 0) = true;
+  boundary(3, 1) = true;
+  boundary(3, 2) = true;
+  boundary(3, 3) = true;
+  boundary(3, 4) = true;
+  boundary(3, 5) = true;
 
   // boundary(4,0) = true;
   // boundary(4,1) = true;
   // boundary(4,2) = true;
   // boundary(4,3) = true;
   // boundary(4,4) = true;
-  boundary(4,5) = true;
+  boundary(4, 5) = true;
 
-  std::cout<<"BC Definition"<<std::endl;
-  /* -------------------------------------------------------------------------- */
+  std::cout << "BC Definition" << std::endl;
+  /* --------------------------------------------------------------------------
+   */
   // Solve
-  
+
   Real error;
 
   model.assembleStiffnessMatrix();
-  std::cout<<"Assemble Done"<<std::endl;
+  std::cout << "Assemble Done" << std::endl;
   model.getStiffnessMatrix().saveMatrix("K_4_5_5.mtx");
-  
-  
+
   UInt count = 0;
-  std::cout<<"Matrix saved"<<std::endl;
+  std::cout << "Matrix saved" << std::endl;
 
   model.addDumpField("displacement");
   model.addDumpField("rotation");
   model.addDumpField("force");
   model.addDumpField("momentum");
 
   do {
     model.updateResidual();
     model.solve();
     count++;
   } while (!model.testConvergenceIncrement(1e-10, error) && count < 10);
-   
 
-  /* -------------------------------------------------------------------------- */
+  /* --------------------------------------------------------------------------
+   */
   // Post-Processing
 
   model.computeStresses();
-  
-  //const SparseMatrix = model.getStiffnessMatrix();
-  std::cout<< "u  = " << displacement(4,0) << std::endl;
-  std::cout<< "v  = " << displacement(4,1) << std::endl;
-  std::cout<< "w5  = " << displacement(4,2) << std::endl;
-  std::cout<< "betax  = " << displacement(4,3) << std::endl;
-  std::cout<< "betay  = " << displacement(4,4) << std::endl;
-  std::cout<< "betaz  = " << displacement(4,5) << std::endl;
-  
-  
-  //model.dump();
+
+  // const SparseMatrix = model.getStiffnessMatrix();
+  std::cout << "u  = " << displacement(4, 0) << std::endl;
+  std::cout << "v  = " << displacement(4, 1) << std::endl;
+  std::cout << "w5  = " << displacement(4, 2) << std::endl;
+  std::cout << "betax  = " << displacement(4, 3) << std::endl;
+  std::cout << "betay  = " << displacement(4, 4) << std::endl;
+  std::cout << "betaz  = " << displacement(4, 5) << std::endl;
+
+  // model.dump();
 }