diff --git a/cmake/AkantuTestAndExamples.cmake b/cmake/AkantuTestAndExamples.cmake
index da4351c65..d5a82c54a 100644
--- a/cmake/AkantuTestAndExamples.cmake
+++ b/cmake/AkantuTestAndExamples.cmake
@@ -1,321 +1,336 @@
 #===============================================================================
 # @file   AkantuTestAndExamples.cmake
 #
 # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
 # @author Nicolas Richart <nicolas.richart@epfl.ch>
 #
 # @date creation: Mon Oct 25 2010
 # @date last modification: Tue Jun 24 2014
 #
 # @brief  macros for tests and examples
 #
 # @section LICENSE
 #
 # Copyright (©) 2010-2012, 2014 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
 #
 #===============================================================================
 
 set(AKANTU_DIFF_SCRIPT ${AKANTU_CMAKE_DIR}/akantu_diff.sh)
 
 #===============================================================================
 function(manage_test_and_example et_name desc build_all label)
   string(TOUPPER ${et_name} upper_name)
 
   cmake_parse_arguments(manage_test_and_example
     ""
     "PACKAGE"
     ""
     ${ARGN}
     )
 
   set(_activated ON)
   if(manage_test_and_example_PACKAGE)
     list(FIND ${_project}_PACKAGE_SYSTEM_PACKAGES_ON ${manage_test_and_example_PACKAGE} _ret)
     if(_ret EQUAL -1)
       set(_activated OFF)
       file(RELATIVE_PATH _dir ${PROJECT_SOURCE_DIR}  ${CMAKE_CURRENT_SOURCE_DIR}/${et_name})
       list(APPEND AKANTU_TESTS_EXCLUDE_FILES /${_dir})
       set(AKANTU_TESTS_EXCLUDE_FILES ${AKANTU_TESTS_EXCLUDE_FILES} CACHE INTERNAL "")
     endif()
   endif()
 
   if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${et_name} AND _activated)
     #    message("Example or test ${et_name} not present")
     return()
   endif()
 
   option(AKANTU_BUILD${label}${upper_name} "${desc}")
   mark_as_advanced(AKANTU_BUILD_${upper_name})
 
   if(${build_all} OR NOT _activated)
     set(AKANTU_BUILD${label}${upper_name}_OLD
       ${AKANTU_BUILD${label}${upper_name}}
       CACHE INTERNAL "${desc}" FORCE)
 
     set(AKANTU_BUILD${label}${upper_name} ${_activated}
       CACHE INTERNAL "${desc}" FORCE)
   else()
     if(DEFINED AKANTU_BUILD${label}${upper_name}_OLD)
       set(AKANTU_BUILD${label}${upper_name}
 	${AKANTU_BUILD${label}${upper_name}_OLD}
 	CACHE BOOL "${desc}" FORCE)
 
       unset(AKANTU_BUILD${label}${upper_name}_OLD
 	CACHE)
     endif(DEFINED AKANTU_BUILD${label}${upper_name}_OLD)
   endif()
 
   if(AKANTU_BUILD${label}${upper_name})
     add_subdirectory(${et_name})
   endif(AKANTU_BUILD${label}${upper_name})
 endfunction()
 
 #===============================================================================
 # Tests
 #===============================================================================
 if(AKANTU_TESTS)
   option(AKANTU_BUILD_ALL_TESTS "Build all tests" ON)
+  option(AKANTU_BUILD_UNSTABLE_TESTS "Build the tests marked as unstable" OFF)
   mark_as_advanced(AKANTU_BUILD_ALL_TESTS)
+  mark_as_advanced(AKANTU_BUILD_UNSTABLE_TESTS)
 endif(AKANTU_TESTS)
 
 #===============================================================================
 # Examples
 #===============================================================================
 if(AKANTU_EXAMPLES)
   option(AKANTU_BUILD_ALL_EXAMPLES "Build all examples")
   #  mark_as_advanced(AKANTU_BUILD_ALL_EXAMPLES)
 endif(AKANTU_EXAMPLES)
 
 #===============================================================================
 macro(register_example example_name)
   add_executable(${example_name} ${ARGN})
   target_link_libraries(${example_name} akantu ${AKANTU_EXTERNAL_LIBRARIES})
 endmacro()
 
 #===============================================================================
 macro(add_example example_name desc)
   manage_test_and_example(${example_name} ${desc} AKANTU_BUILD_ALL_EXAMPLES _EXAMPLE_ ${ARGN})
 endmacro()
 
 
 # ==============================================================================
 # this should be a macro due to the enable_testing
 macro(add_test_tree dir)
   if(AKANTU_TESTS)
     enable_testing()
     include(CTest)
     mark_as_advanced(BUILD_TESTING)
 
     set(AKANTU_TESTS_EXCLUDE_FILES "" CACHE INTERNAL "")
 
     set(_akantu_current_parent_test ${dir} CACHE INTERNAL "Current test folder" FORCE)
     set(_akantu_${dir}_tests_count 0 CACHE INTERNAL "" FORCE)
 
     string(TOUPPER ${dir} _u_dir)
     set(AKANTU_BUILD_${_u_dir} ON CACHE INTERNAL "${desc}" FORCE)
 
     package_get_all_test_folders(_test_dirs)
 
     foreach(_dir ${_test_dirs})
       add_subdirectory(${_dir})
     endforeach()
   else()
     set(AKANTU_TESTS_EXCLUDE_FILES "${CMAKE_CURRENT_BINARY_DIR}/${dir}" CACHE INTERNAL "")
   endif()
 endmacro()
 
 # ==============================================================================
 function(add_akantu_test dir desc)
   set(_my_parent_dir ${_akantu_current_parent_test})
 
   # initialize variables
   set(_akantu_current_parent_test ${dir} CACHE INTERNAL "Current test folder" FORCE)
   set(_akantu_${dir}_tests_count 0 CACHE INTERNAL "" FORCE)
 
   # set the option for this directory
   string(TOUPPER ${dir} _u_dir)
   option(AKANTU_BUILD_${_u_dir} "${desc}")
   mark_as_advanced(AKANTU_BUILD_${_u_dir})
 
   # add the sub-directory
   add_subdirectory(${dir})
 
   # if no test can be activated make the option disappear
   set(_force_deactivate_count FALSE)
   if(${_akantu_${dir}_tests_count} EQUAL 0)
     set(_force_deactivate_count TRUE)
   endif()
 
   # if parent off make the option disappear
   set(_force_deactivate_parent FALSE)
   string(TOUPPER ${_my_parent_dir} _u_parent_dir)
   if(NOT AKANTU_BUILD_${_u_parent_dir})
     set(_force_deactivate_parent TRUE)
   endif()
 
   if(_force_deactivate_parent OR _force_deactivate_count OR AKANTU_BUILD_ALL_TESTS)
     if(NOT DEFINED _AKANTU_BUILD_${_u_dir}_SAVE)
       set(_AKANTU_BUILD_${_u_dir}_SAVE ${AKANTU_BUILD_${_u_dir}} CACHE INTERNAL "" FORCE)
     endif()
     unset(AKANTU_BUILD_${_u_dir} CACHE)
     if(AKANTU_BUILD_ALL_TESTS AND NOT _force_deactivate_count)
       set(AKANTU_BUILD_${_u_dir} ON CACHE INTERNAL "${desc}" FORCE)
     else()
       set(AKANTU_BUILD_${_u_dir} OFF CACHE INTERNAL "${desc}" FORCE)
     endif()
   else()
     if(DEFINED _AKANTU_BUILD_${_u_dir}_SAVE)
       unset(AKANTU_BUILD_${_u_dir} CACHE)
       set(AKANTU_BUILD_${_u_dir} ${_AKANTU_BUILD_${_u_dir}_SAVE} CACHE BOOL "${desc}")
       unset(_AKANTU_BUILD_${_u_dir}_SAVE CACHE)
     endif()
   endif()
 
   # adding up to the parent count
   math(EXPR _tmp_parent_count "${_akantu_${dir}_tests_count} + ${_akantu_${_my_parent_dir}_tests_count}")
   set(_akantu_${_my_parent_dir}_tests_count ${_tmp_parent_count} CACHE INTERNAL "" FORCE)
 
   # restoring the parent current dir
   set(_akantu_current_parent_test ${_my_parent_dir} CACHE INTERNAL "Current test folder" FORCE)
 endfunction()
 
 
 # ==============================================================================
 function(register_test test_name)
    set(multi_variables
-    SOURCES FILES_TO_COPY DEPENDENCIES DIRECTORIES_TO_CREATE COMPILE_OPTIONS EXTRA_FILES
+    SOURCES FILES_TO_COPY DEPENDENCIES DIRECTORIES_TO_CREATE COMPILE_OPTIONS EXTRA_FILES PACKAGE
     )
 
   cmake_parse_arguments(_register_test
+    "UNSTABLE"
     ""
-    "PACKAGE"
     "${multi_variables}"
     ${ARGN}
     )
 
   if(NOT _register_test_PACKAGE)
     message(FATAL_ERROR "No reference package was defined for the test ${test_name} in folder ${CMAKE_CURRENT_SOURCE_DIR}")
   endif()
 
-  package_is_activated(${_register_test_PACKAGE} _act)
+  set(_test_act TRUE)
+  # Activate the test anly if all packages associated to the test are activated
+  foreach(_package ${_register_test_PACKAGE})
+    package_is_activated(${_package} _act)
+    if(NOT _act)
+      set(_test_act FALSE)
+    endif()
+  endforeach()
+
+  # check if the test is marked unstable and if the unstable test should be run
+  if(_register_test_UNSTABLE AND NOT AKANTU_BUILD_UNSTABLE_TESTS)
+    set(_test_act FALSE)
+  endif()
 
-  if(_act)
+  # todo this should be checked for the build package_sources since the file will not be listed.
+  if(_test_act)
     math(EXPR _tmp_parent_count "${_akantu_${_akantu_current_parent_test}_tests_count} + 1")
     set(_akantu_${_akantu_current_parent_test}_tests_count ${_tmp_parent_count} CACHE INTERNAL "" FORCE)
 
     string(TOUPPER ${_akantu_current_parent_test} _u_parent)
     if(AKANTU_BUILD_${_u_parent} OR AKANTU_BUILD_ALL_TESTS)
       # get the include directories for sources in activated directories
       package_get_all_include_directories(
 	AKANTU_LIBRARY_INCLUDE_DIRS
 	)
 
       # get the external packages compilation and linking informations
       package_get_all_external_informations(
 	AKANTU_EXTERNAL_INCLUDE_DIR
 	AKANTU_EXTERNAL_LIBRARIES
 	)
 
       # set the proper includes to build most of the tests
       include_directories(
 	${AKANTU_INCLUDE_DIRS}
 	${AKANTU_EXTERNAL_LIB_INCLUDE_DIR}
 	)
 
       # Register the executable to compile
       add_executable(${test_name} ${_register_test_SOURCES} ${_register_test_UNPARSED_ARGUMENTS})
       set_property(TARGET ${test_name}  APPEND
 	PROPERTY INCLUDE_DIRECTORIES ${AKANTU_LIBRARY_INCLUDE_DIRS} ${AKANTU_EXTERNAL_INCLUDE_DIR})
       target_link_libraries(${test_name} akantu ${AKANTU_EXTERNAL_LIBRARIES})
 
       # add the extra compilation options
       if(_register_test_COMPILE_OPTIONS)
 	set_target_properties(${test_name}
 	  PROPERTIES COMPILE_DEFINITIONS "${_register_test_COMPILE_OPTIONS}")
       endif()
 
       set(_test_all_files)
       # add the different dependencies (meshes, local libraries, ...)
       foreach(_dep ${_register_test_DEPENDENCIES})
 	add_dependencies(${test_name} ${_dep})
 	get_target_property(_dep_in_ressources ${_dep} RESSOURCES)
 
 	if(_dep_in_ressources)
 	  list(APPEND _test_all_files ${_dep_in_ressources})
 	endif()
       endforeach()
 
       # copy the needed files to the build folder
       if(_register_test_FILES_TO_COPY)
 	foreach(_file ${_register_test_FILES_TO_COPY})
 	  file(COPY ${_file} DESTINATION .)
 	  list(APPEND _test_all_files ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
 	endforeach()
       endif()
 
       # create the needed folders in the build folder
       if(_register_test_DIRECTORIES_TO_CREATE)
 	foreach(_dir ${_register_test_DIRECTORIES_TO_CREATE})
 	  if(IS_ABSOLUTE ${dir})
 	    file(MAKE_DIRECTORY ${_dir})
 	  else()
   	    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${_dir})
 	  endif()
 	endforeach()
       endif()
 
       # add the source files in the list of all files
       foreach(_file ${_register_test_SOURCES} ${_register_test_UNPARSED_ARGUMENTS} ${_register_test_EXTRA_FILES})
 	if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
           list(APPEND _test_all_files ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
 	else()
           message("The file \"${_file}\" registred by the test \"${test_name}\" does not exists")
 	endif()
       endforeach()
 
       # register the test for ctest
       if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.sh)
 	file(COPY ${test_name}.sh DESTINATION .)
 	list(APPEND _test_all_files ${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.sh)
 	add_test(${test_name}_run
 	  ${CMAKE_CURRENT_BINARY_DIR}/${test_name}.sh)
       elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.verified)
 	list(APPEND _test_all_files ${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.verified)
 	add_test(${test_name}_run
 	  ${AKANTU_DIFF_SCRIPT} ${test_name} ${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.verified)
       else()
 	add_test(${test_name}_run
 	  ${CMAKE_CURRENT_BINARY_DIR}/${test_name})
       endif()
 
       # add the executable as a dependency of the run
       set_tests_properties(${test_name}_run PROPERTIES DEPENDS ${test_name})
 
       # clean the list of all files for this test and add them in the total list
       set(_tmp ${AKANTU_TESTS_FILES})
       foreach(_file ${_source_file})
 	get_filename_component(_full ${_file} ABSOLUTE)
 	file(RELATIVE_PATH __file ${PROJECT_SOURCE_DIR} ${_full})
 	list(APPEND _tmp ${__file})
 	list(APPEND _pkg_tmp ${__file})
       endforeach()
       set(AKANTU_TESTS_FILES ${_tmp} CACHE INTERNAL "")
     endif()
   endif()
 endfunction()
\ No newline at end of file
diff --git a/cmake/Modules/CMakePackagesSystem.cmake b/cmake/Modules/CMakePackagesSystem.cmake
index 7e7dce30d..fb9148fda 100644
--- a/cmake/Modules/CMakePackagesSystem.cmake
+++ b/cmake/Modules/CMakePackagesSystem.cmake
@@ -1,1639 +1,1642 @@
 #===============================================================================
 # @file   CMakePackagesSystem.cmake
 #
 # @author Nicolas Richart <nicolas.richart@epfl.ch>
 # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
 #
 # @date creation: Thu Dec 20 2012
 # @date last modification: Wed Sep 10 2014
 #
 # @brief  Set of macros used by akantu to handle the package system
 #
 # @section DESCRIPTION
 #
 # This package defines multiple function to handle packages. This packages can
 # be of two kinds regular ones and extra_packages (ex: in akantu the LGPL part
 # is regular packages and extra packages are on Propetary license)
 #
 # Package are loaded with the help of the command:
 # package_list_packages(<regular_package_folder>
 #                       [ EXTRA_PACKAGE_FOLDER <extra_package_folder> ]
 #                       [ SOURCE_FOLDER <source_folder>]
 #                       [ TEST_FOLDER <test_folder> ]
 #                       [ MANUAL_FOLDER <manual_folder> ]
 #                      )
 #
 # This command will look for packages name like
 #         <regular_package_folder>/<package>.cmake
 #      OR <extra_package_folder>/<package>/package.cmake
 #
 # A package is a cmake script that should contain at list the declaration of a
 # package
 #
 # package_declare(<package real name>
 #                 [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL]
 #                 [DESCRIPTION <description>] [DEFAULT <default_value>]
 #                 [DEPENDS <pkg> ...]
 #                 [BOOST_COMPONENTS <pkg> ...]
 #                 [EXTRA_PACKAGE_OPTIONS <opt> ...]
 #                 [COMPILE_FLAGS <flags>]
 #                 [SYSTEM <bool> [ <script_to_compile> ]])
 #
 # It can also declare multiple informations:
 # source files:
 #    package_declare_sources(<package real name>
 #                            <src1> <src2> ... <srcn>)
 #
 # a LaTeX documentation:
 #    package_declare_documentation(<package real name>
 #                                  <line1> <line2> ...<linen>)
 #
 # LaTeX documentation files
 #    package_declare_documentation_files(<package real name>
 #                                        <file1> <file2> ... <filen>)
 #
 # Different function can also be retrieved from the package system by using the
 # different accessors
 #     package_get_name(<pkg> <retval>)
 #     package_get_real_name(<pkg> <retval>)
 #
 #     package_get_option_name(<pkg> <retval>)
 #
 #     package_use_system(<pkg> <retval>)
 #
 #     package_get_nature(<pkg> <retval>)
 #
 #     package_get_description(<pkg> <retval>)
 #
 #     package_get_filename(<pkg> <retval>)
 #
 #     package_get_sources_folder(<pkg> <retval>)
 #     package_get_tests_folder(<pkg> <retval>)
 #     package_get_manual_folder(<pkg> <retval>)
 #
 #     package_get_find_package_extra_options(<pkg> <retval>)
 #
 #     package_get_compile_flags(<pkg> <retval>)
 #
 #     package_get_include_dir(<pkg> <retval>)
 #     package_set_include_dir(<pkg> <inc1> <inc2> ... <incn>)
 #
 #     package_get_libraries(<pkg> <retval>)
 #     package_set_libraries(<pkg> <lib1> <lib2> ... <libn>)
 #
 #     package_add_extra_dependency(pkg <dep1> <dep2> ... <depn>)
 #     package_rm_extra_dependency(<pkg> <dep>)
 #     package_get_extra_dependencies(<pkg> <retval>)
 #
 #     package_is_activated(<pkg> <retval>)
 #     package_is_deactivated(<pkg> <retval>)
 #
 #     package_get_dependencies(<pkg> <retval>)
 #     package_add_dependencies(<pkg> <dep1> <dep2> ... <depn>)
 #
 #     package_get_all_source_files(<srcs> <public_headers> <private_headers>)
 #     package_get_all_include_directories(<inc_dirs>)
 #     package_get_all_external_informations(<include_dir> <libraries>)
 #     package_get_all_definitions(<definitions>)
 #     package_get_all_extra_dependencies(<dependencies>)
 #     package_get_all_test_folders(<test_dirs>)
 #     package_get_all_documentation_files(<doc_files>)
 #     package_get_all_activated_packages(<activated_list>)
 #     package_get_all_packages(<packages_list>)
 #
 #
 # @section LICENSE
 #
 # Copyright (©) 2014 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(CMakeParseArguments)
 
 #===============================================================================
 # Package Management
 #===============================================================================
 if(__CMAKE_PACKAGES_SYSTEM)
   return()
 endif()
 set(__CMAKE_PACKAGES_SYSTEM TRUE)
 
+if(CMAKE_VERSION VERSION_GREATER 3.1.2)
+  cmake_policy(SET CMP0054 NEW)
+endif()
 
 include(CMakeDebugMessages)
 cmake_register_debug_message_module(PackagesSystem)
 
 #===============================================================================
 option(AUTO_MOVE_UNKNOWN_FILES
   "Give to cmake the permission to move the unregistered files to the ${PROJECT_SOURCE_DIR}/tmp directory" FALSE)
 
 mark_as_advanced(AUTO_MOVE_UNKNOWN_FILES)
 
 # ==============================================================================
 # "Public" Accessors
 # ==============================================================================
 # ------------------------------------------------------------------------------
 # Package name
 # ------------------------------------------------------------------------------
 function(package_get_name pkg pkg_name)
   string(TOUPPER ${PROJECT_NAME} _project)
   string(REPLACE "-" "_" _str_pkg "${pkg}")
   string(TOUPPER ${_str_pkg} _u_package)
   set(${pkg_name} ${_project}_PKG_${_u_package} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Real name
 # ------------------------------------------------------------------------------
 function(package_get_real_name pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_real_name(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Option name
 # ------------------------------------------------------------------------------
 function(package_get_option_name pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_option_name(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Set if system package or compile external lib
 # ------------------------------------------------------------------------------
 function(package_use_system pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_use_system(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 function(package_add_third_party_script_variable pkg var)
   package_get_name(${pkg} _pkg_name)
   _package_add_third_party_script_variable(${_pkg_name} ${var} ${ARGN})
   set(${var} ${ARGN} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Nature
 # ------------------------------------------------------------------------------
 function(package_get_nature pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_nature(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Description
 # ------------------------------------------------------------------------------
 function(package_get_description pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_description(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Package file name
 # ------------------------------------------------------------------------------
 function(package_get_filename pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_filename(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Source folder
 # ------------------------------------------------------------------------------
 function(package_get_sources_folder pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_sources_folder(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Test folder
 # ------------------------------------------------------------------------------
 function(package_get_tests_folder pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_tests_folder(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Manual folder
 # ------------------------------------------------------------------------------
 function(package_get_manual_folder pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_manual_folder(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Extra option for the find_package
 # ------------------------------------------------------------------------------
 function(package_get_find_package_extra_options pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_find_package_extra_options(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 function(package_set_find_package_extra_options pkg)
   package_get_name(${pkg} _pkg_name)
   _package_set_find_package_extra_options(${_pkg_name} ${ARGN})
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Compilation flags
 # ------------------------------------------------------------------------------
 function(package_get_compile_flags pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_compile_flags(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Include dir
 # ------------------------------------------------------------------------------
 function(package_get_include_dir pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_include_dir(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 function(package_set_include_dir pkg)
   package_get_name(${pkg} _pkg_name)
   _package_set_include_dir(${_pkg_name} ${ARGN})
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Libraries
 # ------------------------------------------------------------------------------
 function(package_get_libraries pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_libraries(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 function(package_set_libraries pkg)
   package_get_name(${pkg} _pkg_name)
   _package_set_libraries(${_pkg_name} ${ARGN})
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Extra dependencies like custom commands of ExternalProject
 # ------------------------------------------------------------------------------
 function(package_add_extra_dependency pkg)
   package_get_name(${pkg} _pkg_name)
   set(_tmp_dep ${${_pkg_name}_EXTRA_DEPENDS})
   list(APPEND _tmp_dep ${ARGN})
   list(REMOVE_DUPLICATES _tmp_dep)
   set(${_pkg_name}_EXTRA_DEPENDENCY "${_tmp_dep}"
     CACHE INTERNAL "External dependencies")
 endfunction()
 
 function(package_rm_extra_dependency pkg DEP)
   package_get_name(${pkg} _pkg_name)
   if(${_pkg_name}_EXTRA_DEPENDENCY)
     set(_tmp_dep ${${_pkg_name}_EXTRA_DEPENDENCY})
     list(REMOVE_ITEM _tmp_dep ${DEP})
     set(${_pkg_name}_EXTRA_DEPENDENCY "${_tmp_dep}"
       CACHE INTERNAL "External dependencies" FORCE)
   endif()
 endfunction()
 
 function(package_get_extra_dependencies pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_extra_dependencies(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Activate/deactivate
 # ------------------------------------------------------------------------------
 function(package_is_activated pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_is_activated(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 function(package_is_deactivated pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_is_deactivated(${_pkg_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Direct dependencies
 # ------------------------------------------------------------------------------
 function(package_get_dependencies pkg ret)
   package_get_name(${pkg} _pkg_name)
   _package_get_dependencies(${_pkg_name} _tmp_name)
   _package_get_real_name(${_tmp_name} _tmp)
   set(${ret} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 function(package_add_dependencies pkg)
   package_get_name(${pkg} _pkg_name)
   foreach(_dep ${ARGN})
     package_get_name(${_dep} _dep_pkg_name)
     list(APPEND _tmp_deps ${_dep_pkg_name})
   endforeach()
 
   _package_add_dependencies(${_pkg_name} ${_tmp_deps})
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Documentation related functions
 # ------------------------------------------------------------------------------
 function(package_declare_documentation pkg)
   # \n replaced by && and \\ by ££ to avoid cache problems
   set(_doc_str "")
   foreach(_str ${ARGN})
     set(_doc_str "${_doc_str}&&${_str}")
   endforeach()
 
   string(REPLACE "\\" "££" _doc_escaped "${_doc_str}")
   package_get_name(${pkg} _pkg_name)
   set(${_pkg_name}_DOCUMENTATION "${_doc_escaped}"
     CACHE INTERNAL "Latex doc of package ${pkg}" FORCE)
 endfunction()
 
 function(package_declare_documentation_files pkg)
   package_get_name(${pkg} _pkg_name)
   set(${_pkg_name}_DOCUMENTATION_FILES "${ARGN}"
     CACHE INTERNAL "Latex doc files for package ${pkg}" FORCE)
 endfunction()
 
 # ==============================================================================
 # Global accessors
 # ==============================================================================
 # ------------------------------------------------------------------------------
 # get the list of source files
 # ------------------------------------------------------------------------------
 function(package_get_all_source_files SRCS PUBLIC_HEADERS PRIVATE_HEADERS)
   string(TOUPPER ${PROJECT_NAME} _project)
 
   set(tmp_SRCS)
   set(tmp_PUBLIC_HEADERS)
   set(tmp_PRIVATE_HEADERS)
 
   package_get_all_activated_packages(_activated_list)
   foreach(_pkg_name ${_activated_list})
     _package_get_source_files(${_pkg_name}
       _tmp_SRCS
       _tmp_PUBLIC_HEADERS
       _tmp_PRIVATE_HEADERS
       )
     list(APPEND tmp_SRCS ${_tmp_SRCS})
     list(APPEND tmp_PUBLIC_HEADERS ${tmp_PUBLIC_HEADERS})
     list(APPEND tmp_PRIVATE_HEADERS ${tmp_PRIVATE_HEADERS})
   endforeach()
 
   set(${SRCS}            ${tmp_SRCS}            PARENT_SCOPE)
   set(${PUBLIC_HEADERS}  ${tmp_PUBLIC_HEADERS}  PARENT_SCOPE)
   set(${PRIVATE_HEADERS} ${tmp_PRIVATE_HEADERS} PARENT_SCOPE)
 endfunction()
 
 
 # ------------------------------------------------------------------------------
 # Get include directories
 # ------------------------------------------------------------------------------
 function(package_get_all_include_directories inc_dirs)
   string(TOUPPER ${PROJECT_NAME} _project)
 
   set(_tmp)
 
   package_get_all_activated_packages(_activated_list)
   foreach(_pkg_name ${_activated_list})
     foreach(_type SRCS PUBLIC_HEADERS PRIVATE_HEADERS)
       foreach(_file ${${_pkg_name}_${_type}})
 	get_filename_component(_path "${_file}" PATH)
 	list(APPEND _tmp "${_path}")
       endforeach()
     endforeach()
   endforeach()
 
   list(REMOVE_DUPLICATES _tmp)
 
   set(${inc_dirs} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Get external libraries informations
 # ------------------------------------------------------------------------------
 function(package_get_all_external_informations INCLUDE_DIR LIBRARIES)
   string(TOUPPER ${PROJECT_NAME} _project)
 
   set(tmp_INCLUDE_DIR)
   set(tmp_LIBRARIES)
 
   package_get_all_activated_packages(_activated_list)
   foreach(_pkg_name ${_activated_list})
     _package_get_nature(${_pkg_name} _nature)
     if(${_nature} MATCHES "external")
       _package_get_include_dir(${_pkg_name} _inc)
       _package_get_libraries  (${_pkg_name} _libraries)
 
       list(APPEND tmp_INCLUDE_DIR ${_inc})
       list(APPEND tmp_LIBRARIES   ${_libraries})
     endif()
   endforeach()
 
   set(${INCLUDE_DIR} ${tmp_INCLUDE_DIR} PARENT_SCOPE)
   set(${LIBRARIES}   ${tmp_LIBRARIES}   PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Get definitions like external projects
 # ------------------------------------------------------------------------------
 function(package_get_all_definitions definitions)
   set(_tmp)
   string(TOUPPER ${PROJECT_NAME} _project)
 
   package_get_all_activated_packages(_activated_list)
   foreach(_pkg_name ${_activated_list})
     _package_get_option_name(${_pkg_name} _option_name)
     list(APPEND _tmp ${_option_name})
   endforeach()
 
   set(${definitions} ${_tmp} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Get extra dependencies like external projects
 # ------------------------------------------------------------------------------
 function(package_get_all_extra_dependencies DEPS)
   string(TOUPPER ${PROJECT_NAME} _project)
   set(_tmp_DEPS)
 
   package_get_all_activated_packages(_activated_list)
   foreach(_pkg_name ${_activated_list})
     _package_get_extra_dependencies(${_pkg_name} _dep)
     list(APPEND _tmp_DEPS ${_dep})
   endforeach()
 
   if(_tmp_DEPS)
     list(REMOVE_DUPLICATES _tmp_DEPS)
   endif()
   set(${DEPS} ${_tmp_DEPS} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Get extra infos
 # ------------------------------------------------------------------------------
 function(package_get_all_test_folders TEST_DIRS)
   string(TOUPPER ${PROJECT_NAME} _project)
   set(_tmp_TEST_DIRS)
 
   package_get_all_activated_packages(_activated_list)
   foreach(_pkg_name ${_activated_list})
     _package_get_tests_folder(${_pkg_name} _test_dir)
     list(APPEND _tmp_TEST_DIRS ${_test_dir})
   endforeach()
 
   if(_tmp_TEST_DIRS)
     list(REMOVE_DUPLICATES _tmp_TEST_DIRS)
   endif()
   set(${TEST_DIRS} ${_tmp_TEST_DIRS} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Documentation informations
 # ------------------------------------------------------------------------------
 function(package_get_all_documentation_files doc_files)
   string(TOUPPER ${PROJECT_NAME} _project)
   set(_tmp_DOC_FILES)
 
   package_get_all_activated_packages(_activated_list)
   foreach(_pkg_name ${_activated_list})
     _package_get_manual_folder(${_pkg_name} _doc_dir)
     _package_get_documentation_files(${_pkg_name} _doc_files)
 
     foreach(_doc_file ${_doc_files})
       list(APPEND _tmp_DOC_FILES ${_doc_dir}/${_doc_file})
     endforeach()
   endforeach()
 
   if(_tmp_DOC_FILES)
     list(REMOVE_DUPLICATES _tmp_DOC_FILES)
   endif()
 
   set(${doc_files} ${_tmp_DOC_FILES} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # List packages
 # ------------------------------------------------------------------------------
 function(package_get_all_activated_packages activated_list)
   string(TOUPPER ${PROJECT_NAME} _project)
   set(${activated_list} ${${_project}_ACTIVATED_PACKAGE_LIST} PARENT_SCOPE)
 endfunction()
 
 function(package_get_all_packages packages_list)
   string(TOUPPER ${PROJECT_NAME} _project)
   set(${packages_list} ${${_project}_ALL_PACKAGES_LIST} PARENT_SCOPE)
 endfunction()
 
 
 # ==============================================================================
 # User Functions
 # ==============================================================================
 
 # ------------------------------------------------------------------------------
 # list all the packages in the PACKAGE_FOLDER
 # extra packages can be given with an EXTRA_PACKAGE_FOLDER
 # <package_folder>/<package>.cmake
 #
 # Extra packages folder structure
 # <extra_package_folder>/<package>/package.cmake
 #                                 /src
 #                                 /test
 #                                 /manual
 #
 # ------------------------------------------------------------------------------
 function(package_list_packages PACKAGE_FOLDER)
   cmake_parse_arguments(_opt_pkg
     ""
     "SOURCE_FOLDER;EXTRA_PACKAGES_FOLDER;TEST_FOLDER;MANUAL_FOLDER"
     ""
     ${ARGN})
 
   string(TOUPPER ${PROJECT_NAME} _project)
 
   # Cleaning some states to start correctly
   package_get_all_packages(_already_loaded_pkg)
   foreach(_pkg_name ${_already_loaded_pkg})
     _package_unset_extra_dependencies(${_pkg_name})
     _package_unset_dependencies(${_pkg_name})
     _package_unset_activated(${_pkg_name})
   endforeach()
 
 
   if(_opt_pkg_SOURCE_FOLDER)
     set(_src_folder "${_opt_pkg_SOURCE_FOLDER}")
   else()
     set(_src_folder "src/")
   endif()
 
   get_filename_component(_abs_src_folder ${_src_folder} ABSOLUTE)
 
   if(_opt_pkg_TEST_FOLDER)
     set(_test_folder "${_opt_pkg_TEST_FOLDER}")
   else()
     set(_test_folder "test/")
   endif()
 
   if(_opt_pkg_MANUAL_FOLDER)
     set(_manual_folder "${_opt_pkg_MANUAL_FOLDER}")
   else()
     set(_manual_folder "doc/manual")
   endif()
 
   get_filename_component(_abs_test_folder ${_test_folder} ABSOLUTE)
   get_filename_component(_abs_manual_folder ${_manual_folder} ABSOLUTE)
 
   # check all the packages in the <package_folder>
   file(GLOB _package_list "${PACKAGE_FOLDER}/*.cmake")
 
   set(_package_files)
   foreach(_pkg ${_package_list})
     get_filename_component(_basename ${_pkg} NAME)
     if(NOT _basename MATCHES "^\\.#.*")
       list(APPEND _package_files ${_basename})
     endif()
   endforeach()
 
   if(_package_files)
     list(SORT _package_files)
   endif()
 
   # check all packages
   set(_packages_list_all)
   foreach(_pkg_file ${_package_files})
     string(REGEX REPLACE "[0-9]+_" "" _pkg_file_stripped ${_pkg_file})
     string(REGEX REPLACE "\\.cmake" "" _pkg ${_pkg_file_stripped})
 
     package_get_name(${_pkg} _pkg_name)
     _package_set_filename(${_pkg_name} "${PACKAGE_FOLDER}/${_pkg_file}")
 
     _package_set_sources_folder(${_pkg_name} "${_abs_src_folder}")
     _package_set_tests_folder(${_pkg_name} "${_abs_test_folder}")
     _package_set_manual_folder(${_pkg_name} "${_abs_manual_folder}")
 
     list(APPEND _packages_list_all ${_pkg_name})
     include("${PACKAGE_FOLDER}/${_pkg_file}")
   endforeach()
 
   # check the extra_packages if they exists
   if(_opt_pkg_EXTRA_PACKAGES_FOLDER)
     file(GLOB _extra_package_list RELATIVE
       "${_opt_pkg_EXTRA_PACKAGES_FOLDER}" "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/*")
     foreach(_pkg ${_extra_package_list})
       if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake")
 
 	package_get_name(${_pkg} _pkg_name)
 
 	_package_set_filename(${_pkg_name}
 	  "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake")
 
 	_package_set_sources_folder(${_pkg_name}
 	  "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/src")
 
 	if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/test")
 	  _package_set_tests_folder(${_pkg_name}
 	    "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/test")
 	endif()
 
 	if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/manual")
 	  _package_set_manual_folder(${_pkg_name}
 	    "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/manual")
 	endif()
 
 	list(APPEND _extra_pkg_src_folders "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/src")
 
 	list(APPEND _packages_list_all ${_pkg_name})
 	include("${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake")
       endif()
     endforeach()
   endif()
 
   # Store the list of packages
   string(TOUPPER ${PROJECT_NAME} _project)
   set(${_project}_ALL_PACKAGES_LIST ${_packages_list_all}
     CACHE INTERNAL "List of available packages" FORCE)
 
   _package_build_rdependencies()
   _package_load_packages()
   _package_check_files_exists()
   _package_check_files_registered(${_abs_src_folder} ${_extra_pkg_src_folders})
 
   # Load boost components if boost was loaded
   package_is_activated(Boost _ret)
   if(_ret)
     _package_load_boost_components()
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # macro to include internal/external packages packages
 # package_declare(<package real name>
 #                 [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL]
 #                 [DESCRIPTION <description>] [DEFAULT <default_value>]
 #                 [DEPENDS <pkg> ...]
 #                 [BOOST_COMPONENTS <pkg> ...]
 #                 [EXTRA_PACKAGE_OPTIONS <opt> ...]
 #                 [COMPILE_FLAGS <flags>]
 #                 [SYSTEM <bool> [ <script_to_compile> ]])
 # ------------------------------------------------------------------------------
 function(package_declare pkg)
   package_get_name(${pkg} _pkg_name)
   _package_set_real_name(${_pkg_name} ${pkg})
 
   cmake_parse_arguments(_opt_pkg
     "EXTERNAL;NOT_OPTIONAL;META;ADVANCED"
     "DEFAULT;DESCRIPTION"
     "DEPENDS;EXTRA_PACKAGE_OPTIONS;COMPILE_FLAGS;BOOST_COMPONENTS;SYSTEM"
     ${ARGN})
 
   if(_opt_pkg_UNPARSED_ARGUMENTS)
     message("You gave to many arguments while registering the package ${pkg} \"${_opt_pkg_UNPARSED_ARGUMENTS}\"")
   endif()
 
   # set description
   if(_opt_pkg_DESCRIPTION)
     _package_set_description(${_pkg_name} ${_opt_pkg_DESCRIPTION})
   else()
     _package_set_description(${_pkg_name} "")
   endif()
 
   # set the nature
   if(_opt_pkg_EXTERNAL)
     _package_set_nature(${_pkg_name} "external")
   elseif(_opt_pkg_META)
     _package_set_nature(${_pkg_name} "meta")
   else()
     _package_set_nature(${_pkg_name} "internal")
   endif()
 
   _package_get_option_name(${_pkg_name} _option_name)
   _package_get_description(${_pkg_name} _description)
 
   # get the default value
   if(DEFINED _opt_pkg_DEFAULT)
     set(_default ${_opt_pkg_DEFAULT})
   else()
     if(_opt_pkg_NOT_OPTIONAL)
       set(_default ON)
     else()
       set(_default OFF)
     endif()
   endif()
 
   # set the option if needed
   if(_opt_pkg_NOT_OPTIONAL)
     _package_get_nature(${_pkg_name} _nature)
     _package_set_nature(${_pkg_name} "${_nature}_not_optional")
     set(${_option_name} ${_default} CACHE INTERNAL "${_description}" FORCE)
   else()
     option(${_option_name} "${_description}" ${_default})
     if(_opt_pkg_ADVANCED OR _opt_pkg_EXTERNAL)
       mark_as_advanced(${_option_name})
     endif()
   endif()
 
   # Set the option for third-partie that can be compiled as an ExternalProject
   if(DEFINED _opt_pkg_SYSTEM)
     list(LENGTH _opt_pkg_SYSTEM _length)
     list(GET _opt_pkg_SYSTEM 0 _bool)
     _package_set_system_option(${_pkg_name} ${_bool})
     if(_length GREATER 1)
       list(GET _opt_pkg_SYSTEM 1 _script)
       _package_set_system_script(${_pkg_name} ${_script})
     endif()
   endif()
 
   # set the dependecies
   if(_opt_pkg_DEPENDS)
     set(_depends)
     foreach(_dep ${_opt_pkg_DEPENDS})
       package_get_name(${_dep} _dep_pkg_name)
       list(APPEND _depends ${_dep_pkg_name})
     endforeach()
     _package_add_dependencies(${_pkg_name} ${_depends})
   endif()
 
   # keep the extra option for the future find package
   if(_opt_pkg_EXTRA_PACKAGE_OPTIONS)
     _package_set_find_package_extra_options(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGE_OPTIONS}")
   endif()
 
   # register the compilation flags
   if(_opt_pkg_COMPILE_FLAGS)
     _package_set_compile_flags(${_pkg_name} "${_opt_pkg_COMPILE_FLAGS}")
   endif()
 
   # set the boost dependencies
   if(_opt_pkg_BOOST_COMPONENTS)
     _package_set_boost_component_needed(${_pkg_name} "${_opt_pkg_BOOST_COMPONENTS}")
   endif()
 
 endfunction()
 
 # ------------------------------------------------------------------------------
 # declare the source files of a given package
 #
 # package_declare_sources(<package> <list of sources>
 #                         SOURCES <source file> ...
 #                         PUBLIC_HEADER <header file> ...
 #                         PRIVATE_HEADER <header file> ...)
 # ------------------------------------------------------------------------------
 function(package_declare_sources pkg)
   package_get_name(${pkg} _pkg_name)
 
   # get 3 lists, if none of the options given try to distinguish the different lists
   cmake_parse_arguments(_opt_pkg
     ""
     ""
     "SOURCES;PUBLIC_HEADERS;PRIVATE_HEADERS"
     ${ARGN})
 
   set(_tmp_srcs     ${_opt_pkg_SOURCES})
   set(_tmp_pub_hdrs ${_opt_pkg_PUBLIC_HEADER})
   set(_tmp_pri_hdrs ${_opt_pkg_PRIVATE_HEADERS})
 
   foreach(_file ${_opt_pkg_UNPARSED_ARGUMENTS})
     if(${_file} MATCHES ".*inline.*\\.cc")
       list(APPEND _tmp_pub_hdrs ${_file})
     elseif(${_file} MATCHES ".*\\.h+")
       list(APPEND _tmp_pub_hdrs ${_file})
     else()
       list(APPEND _tmp_srcs ${_file})
     endif()
   endforeach()
 
   _package_get_sources_folder(${_pkg_name} _src_folder)
 
   foreach(_type _srcs _pub_hdrs _pri_hdrs)
     set(${_type})
     foreach(_file ${_tmp${_type}})
       # get the full name
       list(APPEND ${_type} "${_src_folder}/${_file}")
     endforeach()
   endforeach()
 
   set(${_pkg_name}_SRCS "${_srcs}"
     CACHE INTERNAL "List of sources files" FORCE)
   set(${_pkg_name}_PUBLIC_HEADERS  "${_pub_hdrs}"
     CACHE INTERNAL "List of public header files" FORCE)
   set(${_pkg_name}_PRIVATE_HEADERS "${_pri_hdrs}"
     CACHE INTERNAL "List of private header files" FORCE)
 endfunction()
 
 
 # ==============================================================================
 # "Private" Accessors
 # ==============================================================================
 # ------------------------------------------------------------------------------
 # Real name
 # ------------------------------------------------------------------------------
 function(_package_get_real_name pkg_name real_name)
   set(${real_name} ${${pkg_name}} PARENT_SCOPE)
 endfunction()
 
 function(_package_set_real_name pkg_name real_name)
   set(${pkg_name} ${real_name} CACHE INTERNAL "" FORCE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Option name
 # ------------------------------------------------------------------------------
 function(_package_get_option_name pkg_name opt_name)
   string(TOUPPER "${PROJECT_NAME}" _project)
   _package_get_real_name(${pkg_name} _real_name)
   string(TOUPPER "${_real_name}" _u_package)
 
   _package_get_nature(${pkg_name} _nature)
 
   if(${_nature} MATCHES "internal" OR ${_nature} MATCHES "meta")
     set(${opt_name} ${_project}_${_u_package} PARENT_SCOPE)
   elseif(${_nature} MATCHES "external")
     set(${opt_name} ${_project}_USE_${_u_package} PARENT_SCOPE)
   else()
     set(${opt_name} UNKNOWN_NATURE_${_project}_${_u_package} PARENT_SCOPE)
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Set if system package or compile external lib
 # ------------------------------------------------------------------------------
 function(_package_set_system_option pkg_name default)
   string(TOUPPER "${PROJECT_NAME}" _project)
   _package_get_real_name(${pkg_name} _real_name)
   string(TOUPPER "${_real_name}" _u_package)
 
   option(${_project}_USE_SYSTEM_${_u_package}
     "Should akantu compile the third-party: \"${_real_name}\"" ${default})
   mark_as_advanced(${_project}_USE_SYSTEM_${_u_package})
 endfunction()
 
 function(_package_use_system pkg_name use)
   string(TOUPPER "${PROJECT_NAME}" _project)
   _package_get_real_name(${pkg_name} _real_name)
   string(TOUPPER "${_real_name}" _u_package)
   if(DEFINED ${_project}_USE_SYSTEM_${_u_package})
     set(${use} ${${_project}_USE_SYSTEM_${_u_package}} PARENT_SCOPE)
   else()
     set(${use} TRUE PARENT_SCOPE)
   endif()
 endfunction()
 
 function(_package_set_system_script pkg_name script)
   set(${_pkg_name}_COMPILE_SCRIPT "${script}"
     CACHE INTERNAL "Script associated to package ${pkg_name}" FORCE)
 endfunction()
 
 function(_package_add_third_party_script_variable pkg var)
   set(${_pkg_name}_VARIABLE_${var} "${ARGN}"
     CACHE INTERNAL "Script associated to package ${pkg_name}" FORCE)
   set(${var} ${ARGN} PARENT_SCOPE)
 endfunction()
 
 function(_package_load_third_party_script pkg_name)
   if(${pkg_name}_COMPILE_SCRIPT)
     # set the stored variable
     get_cmake_property(_all_vars VARIABLES)
     foreach(_var ${_all_vars})
       if(_var MATCHES "^${pkg_name}_VARIABLE_.*")
 	string(REPLACE "${pkg_name}_VARIABLE_" "" _orig_var "${_var}")
 	set(${_orig_var} ${${_var}})
       endif()
     endforeach()
 
     _package_get_real_name(${pkg_name} _name)
     string(TOUPPER "${_name}" _u_name)
 
     _package_get_option_name(${pkg_name} _opt_name)
     if(${_opt_name}_VERSION)
       set(_version " (version ${${_opt_name}_VERSION})")
     elseif(${_u_name}_VERSION)
       set(_version " (version ${${_u_name}_VERSION})")
     endif()
 
     # load the script
     message(STATUS "${_name}: building as third-party${_version}")
     include(ExternalProject)
     include(${${pkg_name}_COMPILE_SCRIPT})
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Nature
 # ------------------------------------------------------------------------------
 function(_package_set_nature pkg_name NATURE)
   set(${pkg_name}_NATURE ${NATURE} CACHE INTERNAL "" FORCE)
 endfunction()
 
 function(_package_get_nature pkg_name NATURE)
   if(${pkg_name}_NATURE)
     set(${NATURE} ${${pkg_name}_NATURE} PARENT_SCOPE)
   else()
     set(${NATURE} "unknown" PARENT_SCOPE)
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Description
 # ------------------------------------------------------------------------------
 function(_package_set_description pkg_name DESC)
   set(${pkg_name}_DESC ${DESC} CACHE INTERNAL "" FORCE)
 endfunction()
 
 function(_package_get_description pkg_name DESC)
   if(${pkg_name}_DESC)
     set(${DESC} ${${pkg_name}_DESC} PARENT_SCOPE)
   else()
     message("No description set for the package ${${pkg_name}} (${pkg_name})")
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Package file name
 # ------------------------------------------------------------------------------
 function(_package_set_filename pkg_name FILE)
   set(${pkg_name}_FILE ${FILE} CACHE INTERNAL "" FORCE)
 endfunction()
 
 function(_package_get_filename pkg_name FILE)
   if(${pkg_name}_FILE)
     set(${FILE} ${${pkg_name}_FILE} PARENT_SCOPE)
   else()
     message(ERROR "No filename set for the package ${${pkg_name}}")
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Source folder
 # ------------------------------------------------------------------------------
 function(_package_set_sources_folder pkg_name src_folder)
   set(${pkg_name}_SRCS_FOLDER "${src_folder}" CACHE INTERNAL "" FORCE)
 endfunction()
 
 function(_package_get_sources_folder pkg_name src_folder)
   set(${src_folder} ${${pkg_name}_SRCS_FOLDER} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Test folder
 # ------------------------------------------------------------------------------
 function(_package_set_tests_folder pkg_name test_folder)
   set(${pkg_name}_TESTS_FOLDER "${test_folder}" CACHE INTERNAL "" FORCE)
 endfunction()
 
 function(_package_get_tests_folder pkg_name test_folder)
   set(${test_folder} ${${pkg_name}_TESTS_FOLDER} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Manual folder
 # ------------------------------------------------------------------------------
 function(_package_set_manual_folder pkg_name manual_folder)
   set(${pkg_name}_MANUAL_FOLDER "${manual_folder}" CACHE INTERNAL "" FORCE)
 endfunction()
 
 function(_package_get_manual_folder pkg_name manual_folder)
   set(${manual_folder} ${${pkg_name}_MANUAL_FOLDER} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Extra option for the find_package
 # ------------------------------------------------------------------------------
 function(_package_set_find_package_extra_options pkg_name)
   set(${pkg_name}_FIND_PKG_OPTIONS "${ARGN}"
     CACHE INTERNAL "Extra option for the fin_package function" FORCE)
 endfunction()
 
 function(_package_get_find_package_extra_options pkg_name options)
   set(${options} "${${pkg_name}_FIND_PKG_OPTIONS}" PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Compilation flags
 # ------------------------------------------------------------------------------
 function(_package_set_compile_flags pkg_name)
   set(${pkg_name}_COMPILE_FLAGS ${ARGN}
     CACHE INTERNAL "Additional compile flags" FORCE)
 endfunction()
 
 function(_package_get_compile_flags pkg_name flags)
   set(${flags} "${${pkg_name}_COMPILE_FLAGS}" PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Include dir
 # ------------------------------------------------------------------------------
 function(_package_set_include_dir pkg_name)
   _package_get_real_name(${pkg_name} _real_name)
   set(${pkg_name}_INCLUDE_DIR "${ARGN}"
     CACHE INTERNAL "Include folder for the package ${_real_name}" FORCE)
 endfunction()
 
 function(_package_get_include_dir pkg_name include_dir)
   set(${include_dir} ${${pkg_name}_INCLUDE_DIR} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Libraries
 # ------------------------------------------------------------------------------
 function(_package_set_libraries pkg_name)
   _package_get_real_name(${pkg_name} _real_name)
   set(${pkg_name}_LIBRARIES "${ARGN}"
     CACHE INTERNAL "Libraries for the package ${_real_name}" FORCE)
 endfunction()
 
 function(_package_get_libraries pkg_name libraries)
   if(${pkg_name}_LIBRARIES)
     set(${libraries} ${${pkg_name}_LIBRARIES} PARENT_SCOPE)
   else()
     set(${libraries} "" PARENT_SCOPE)
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Extra dependencies like custom commands of ExternalProject
 # ------------------------------------------------------------------------------
 function(_package_get_extra_dependencies pkg deps)
   if(${_pkg_name}_EXTRA_DEPENDENCY)
     set(${deps} ${${_pkg_name}_EXTRA_DEPENDENCY} PARENT_SCOPE)
   else()
     set(${deps} PARENT_SCOPE)
   endif()
 endfunction()
 
 function(_package_unset_extra_dependencies pkg_name)
   unset(${pkg_name}_EXTRA_DEPENDENCY CACHE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Activate/deactivate
 # ------------------------------------------------------------------------------
 function(_package_activate pkg_name)
   set(${pkg_name}_STATE ON CACHE INTERNAL "" FORCE)
 endfunction()
 
 function(_package_deactivate pkg_name)
   set(${pkg_name}_STATE OFF CACHE INTERNAL "" FORCE)
 endfunction()
 
 function(_package_is_activated pkg_name _act)
   if(DEFINED ${pkg_name}_STATE AND ${pkg_name}_STATE)
     set(${_act} TRUE PARENT_SCOPE)
   else()
     set(${_act} FALSE PARENT_SCOPE)
   endif()
 endfunction()
 
 function(_package_is_deactivated pkg_name _act)
   if(DEFINED ${pkg_name}_STATE AND NOT ${pkg_name}_STATE)
     set(${_act} TRUE PARENT_SCOPE)
   else()
     set(${_act} FALSE PARENT_SCOPE)
   endif()
 endfunction()
 
 function(_package_unset_activated pkg_name)
   unset(${pkg_name}_STATE CACHE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Direct dependencies
 # ------------------------------------------------------------------------------
 function(_package_add_dependencies pkg_name)
   set(_tmp_deps ${${pkg_name}_DEPENDENCIES})
   list(APPEND _tmp_deps ${ARGN})
   list(REMOVE_DUPLICATES _tmp_deps)
   set(${pkg_name}_DEPENDENCIES "${_tmp_deps}"
     CACHE INTERNAL "List of dependencies for package ${_opt_name}" FORCE)
 endfunction()
 
 function(_package_get_dependencies pkg_name dependencies)
   set(${dependencies} "${${pkg_name}_DEPENDENCIES}" PARENT_SCOPE)
 endfunction()
 
 function(_package_unset_dependencies pkg_name)
   unset(${pkg_name}_DEPENDENCIES CACHE)
 endfunction()
 
 
 # ------------------------------------------------------------------------------
 # Functions to handle reverse dependencies
 # ------------------------------------------------------------------------------
 function(_package_set_rdependencies pkg_name)
   set(${pkg_name}_RDEPENDENCIES "${ARGN}"
     CACHE INTERNAL "Dependencies ON with package ${pkg_name}" FORCE)
 endfunction()
 
 function(_package_get_rdependencies pkg_name RDEPENDENCIES)
   set(${RDEPENDENCIES} "${${pkg_name}_RDEPENDENCIES}" PARENT_SCOPE)
 endfunction()
 
 function(_package_add_rdependency pkg_name rdep)
   # store the reverse dependency
   set(_rdeps ${${pkg_name}_RDEPENDENCIES})
   list(APPEND _rdeps ${rdep})
   list(REMOVE_DUPLICATES _rdeps)
   _package_set_rdependencies(${pkg_name} ${_rdeps})
 endfunction()
 
 function(_package_remove_rdependency pkg_name rdep)
   set(_rdeps ${${pkg_name}_RDEPENDENCIES})
   list(FIND _rdeps ${rdep} pos)
   if(NOT pos EQUAL -1)
     list(REMOVE_AT _rdeps ${pos})
     _package_set_rdependencies(${pkg_name} ${_rdeps})
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Function to handle forcing dependencies (Package turn ON that enforce their
 # dependencies ON)
 # ------------------------------------------------------------------------------
 function(_package_set_fdependencies pkg_name)
   set(${pkg_name}_FDEPENDENCIES "${ARGN}"
     CACHE INTERNAL "Dependencies ON with package ${pkg_name}" FORCE)
 endfunction()
 
 function(_package_get_fdependencies pkg_name fdependencies)
   set(${fdependencies} "${${pkg_name}_FDEPENDENCIES}" PARENT_SCOPE)
 endfunction()
 
 function(_package_add_fdependency pkg_name fdep)
   # store the enforcing dependency
   set(_fdeps ${${pkg_name}_FDEPENDENCIES})
   list(APPEND _fdeps ${fdep})
   list(REMOVE_DUPLICATES _fdeps)
   _package_set_fdependencies(${pkg_name} ${_fdeps})
 endfunction()
 
 function(_package_remove_fdependency pkg_name fdep)
   set(_fdeps ${${pkg_name}_FDEPENDENCIES})
   list(FIND _fdeps ${fdep} pos)
   if(NOT pos EQUAL -1)
     list(REMOVE_AT _fdeps ${pos})
     _package_set_fdependencies(${pkg_name} ${_fdeps})
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Documentation related functions
 # ------------------------------------------------------------------------------
 function(_package_get_documentation_files pkg_name doc_files)
   if(DEFINED ${pkg_name}_DOCUMENTATION_FILES)
     set(${doc_files} ${${pkg_name}_DOCUMENTATION_FILES} PARENT_SCOPE)
   else()
     set(${doc_files} "" PARENT_SCOPE)
   endif()
 endfunction()
 
 function(_package_get_documentation pkg_name _doc)
   # \n replaced by && and \\ by ££ to avoid cache problems
   if (DEFINED ${_pkg_name}_DOCUMENTATION)
     set(_doc_tmp ${${_pkg_name}_DOCUMENTATION})
 
     string(REPLACE "££" "\\" _doc_escaped "${_doc_tmp}")
     string(REPLACE "&&" "\n" _doc_newlines "${_doc_escaped}")
     set(${_doc} "${_doc_newlines}" PARENT_SCOPE)
   else()
     set(${_doc} "" PARENT_SCOPE)
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Special boost thingy
 # ------------------------------------------------------------------------------
 function(_package_set_boost_component_needed pkg_name)
   set(_tmp ${${pkg_name}_BOOST_COMPONENTS_NEEDED})
   list(APPEND _tmp ${ARGN})
   list(REMOVE_DUPLICATES _tmp)
   set(${pkg_name}_BOOST_NEEDED_COMPONENTS ${_tmp}
     CACHE INTERNAL "List of Boost component needed by package ${${pkg_name}}" FORCE)
 
   package_get_name(Boost _boost_pkg_name)
   _package_add_dependencies(${pkg_name} ${_boost_pkg_name})
 endfunction()
 
 function(_package_get_boost_component_needed pkg_name needed)
   if(${pkg_name}_BOOST_NEEDED_COMPONENTS)
     set(${needed} ${${pkg_name}_BOOST_NEEDED_COMPONENTS} PARENT_SCOPE)
   else()
     set(${needed} PARENT_SCOPE)
   endif()
 endfunction()
 
 function(_package_load_boost_components)
   string(TOUPPER ${PROJECT_NAME} _project)
   package_get_name(Boost _pkg_name)
 
   set(_boost_needed_components)
 
   package_get_all_activated_packages(_activated_list)
   foreach(_pkg_name ${_activated_list})
     _package_get_boost_component_needed(${_pkg_name} _boost_comp)
 
     list(APPEND _boost_needed_components ${_boost_comp})
   endforeach()
 
   if(_boost_needed_components)
     message(STATUS "Looking for Boost liraries: ${_boost_needed_components}")
     foreach(_comp ${_boost_needed_components})
       find_package(Boost COMPONENTS ${_comp} QUIET)
       string(TOUPPER ${_comp} _u_comp)
       if(Boost_${_u_comp}_FOUND)
 	message(STATUS "   ${_comp}: FOUND")
 	set(${_project}_BOOST_${_u_comp} TRUE CACHE INTERNAL "" FORCE)
 
 	# Generate the libraries for the package
 	_package_set_libraries(${_pkg_name} ${Boost_${_u_comp}_LIBRARY})
       else()
 	message(STATUS "   ${_comp}: NOT FOUND")
       endif()
     endforeach()
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # get the list of source files for a given package
 # ------------------------------------------------------------------------------
 function(_package_get_source_files pkg_name SRCS PUBLIC_HEADERS PRIVATE_HEADERS)
   string(TOUPPER ${PROJECT_NAME} _project)
 
   set(tmp_SRCS)
   set(tmp_PUBLIC_HEADERS)
   set(tmp_PRIVATE_HEADERS)
 
   foreach(_type SRCS PUBLIC_HEADERS PRIVATE_HEADERS)
     foreach(_file ${${pkg_name}_${_type}})
       string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" _rel_file "${_file}")
       list(APPEND tmp_${_type} "${_rel_file}")
     endforeach()
   endforeach()
 
   set(${SRCS}            ${tmp_SRCS}            PARENT_SCOPE)
   set(${PUBLIC_HEADERS}  ${tmp_PUBLIC_HEADERS}  PARENT_SCOPE)
   set(${PRIVATE_HEADERS} ${tmp_PRIVATE_HEADERS} PARENT_SCOPE)
 endfunction()
 
 # ==============================================================================
 # Internal functions
 # ==============================================================================
 # ------------------------------------------------------------------------------
 # Build the reverse dependencies from the dependencies
 # ------------------------------------------------------------------------------
 function(_package_build_rdependencies)
   string(TOUPPER ${PROJECT_NAME} _project)
 
   # set empty lists
   foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST})
     set(${_pkg_name}_rdeps)
   endforeach()
 
   # fill the dependencies list
   foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST})
     _package_get_dependencies(${_pkg_name} _deps)
     foreach(_dep_name ${_deps})
       list(APPEND ${_dep_name}_rdeps ${_pkg_name})
     endforeach()
   endforeach()
 
   # clean and set the reverse dependencies
   foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST})
     if(${_pkg_name}_rdeps)
       list(REMOVE_DUPLICATES ${_pkg_name}_rdeps)
       _package_set_rdependencies(${_pkg_name} ${${_pkg_name}_rdeps})
     endif()
   endforeach()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # This function resolve the dependance order run the needed find_packages
 # ------------------------------------------------------------------------------
 function(_package_load_packages)
   string(TOUPPER ${PROJECT_NAME} _project)
 
   # Activate the dependencies of activated package and generate an ordered list
   # of dependencies
   set(ordered_loading_list)
   foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST})
     _package_load_dependencies_package(${_pkg_name} ordered_loading_list)
   endforeach()
 
   # Load the packages in the propoer order
   foreach(_pkg_name ${ordered_loading_list})
     _package_get_option_name(${_pkg_name} _option_name)
 
     if(${_option_name})
       _package_load_package(${_pkg_name})
     else()
       # deactivate the packages than can already be deactivated
       _package_deactivate(${_pkg_name})
     endif()
   endforeach()
 
   # generates the activated and unactivated lists of packages
   set(_packages_activated)
   set(_packages_deactivated)
   foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST})
     _package_is_activated(${_pkg_name} _act)
     if(_act)
       list(APPEND _packages_activated ${_pkg_name})
     else()
       list(APPEND _packages_deactivated ${_pkg_name})
     endif()
   endforeach()
 
   # generate the list usable by the calling code
   set(${_project}_ACTIVATED_PACKAGE_LIST "${_packages_activated}"
     CACHE INTERNAL "List of activated packages" FORCE)
   set(${_project}_DEACTIVATED_PACKAGE_LIST "${_packages_deactivated}"
     CACHE INTERNAL "List of deactivated packages" FORCE)
 endfunction()
 
 
 
 # ------------------------------------------------------------------------------
 # This load an external package and recursively all its dependencies
 # ------------------------------------------------------------------------------
 function(_package_load_dependencies_package pkg_name loading_list)
   # Get packages informations
   _package_get_option_name(${pkg_name} _pkg_option_name)
   _package_get_dependencies(${pkg_name} _dependencies)
 
   # handle the dependencies
   foreach(_dep_name ${_dependencies})
     _package_get_description(${_dep_name} _dep_desc)
     _package_get_option_name(${_dep_name} _dep_option_name)
 
     _package_get_fdependencies(${_dep_name} _fdeps)
     if(${_pkg_option_name})
       if("${_fdeps}" STREQUAL "")
 	set(${_dep_name}_OLD ${${_dep_option_name}} CACHE INTERNAL "" FORCE)
       endif()
 
       # set the option to on
       set(${_dep_option_name} ON CACHE BOOL "${_dep_desc}" FORCE)
 
       # store the reverse dependency
       _package_add_fdependency(${_dep_name} ${pkg_name})
     else()
       # check if this is the last reverse dependency
       list(LENGTH _fdeps len)
       list(FIND _fdeps ${pkg_name} pos)
       if((len EQUAL 1) AND (NOT pos EQUAL -1))
 	set(${_dep_option_name} ${${_dep_name}_OLD} CACHE BOOL "${_dep_desc}" FORCE)
 	unset(${_dep_name}_OLD CACHE)
       endif()
 
       # remove the pkg_name form the reverse dependency
       _package_remove_fdependency(${_dep_name} ${pkg_name})
     endif()
 
     # recusively load the dependencies
     _package_load_dependencies_package(${_dep_name} ${loading_list})
   endforeach()
 
   # get the compile flags
   _package_get_compile_flags(${pkg_name} _pkg_comile_flags)
 
   # if package option is on add it in the list
   if(${_pkg_option_name})
     list(FIND ${loading_list} ${pkg_name} _pos)
     if(_pos EQUAL -1)
       set(_tmp_loading_list ${${loading_list}})
       list(APPEND _tmp_loading_list ${pkg_name})
       set(${loading_list} "${_tmp_loading_list}" PARENT_SCOPE)
     endif()
 
     #add the comilation flags if needed
     if(_pkg_comile_flags)
       add_flags(cxx ${_pkg_comile_flags})
     endif()
   else()
     #remove the comilation flags if needed
     if(_pkg_comile_flags)
       remove_flags(cxx ${_pkg_comile_flags})
     endif()
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Load the package if it is an external one
 # ------------------------------------------------------------------------------
 function(_package_load_package pkg_name)
   # load the package if it is an external
   _package_get_nature(${pkg_name} _nature)
   if(${_nature} MATCHES "external")
     _package_use_system(${pkg_name} _use_system)
 
     set(_activated TRUE)
     if(_use_system)
       _package_load_external_package(${pkg_name} _activated)
     else()
       _package_load_third_party_script(${pkg_name})
     endif()
 
     if(_activated)
       _package_activate(${pkg_name})
     elseif()
       _package_deactivate(${pkg_name})
     endif()
   else(${_nature})
     _package_activate(${pkg_name})
   endif()
 endfunction()
 
 
 # ------------------------------------------------------------------------------
 # Load external packages
 # ------------------------------------------------------------------------------
 function(_package_load_external_package pkg_name activate)
   string(TOUPPER ${PROJECT_NAME} _project)
 
   _package_get_find_package_extra_options(${pkg_name} _options)
   if(_options)
     cmake_parse_arguments(_opt_pkg "" "LANGUAGE" "PREFIX;FOUND;ARGS" ${_options})
     if(_opt_pkg_UNPARSED_ARGUMENTS)
       message("You passed too many options for the find_package related to ${${pkg_name}} \"${_opt_pkg_UNPARSED_ARGUMENTS}\"")
     endif()
   endif()
 
   if(_opt_pkg_LANGUAGE)
     foreach(_language ${_opt_pkg_LANGUAGE})
       enable_language(${_language})
     endforeach()
   endif()
 
   _package_get_real_name(${pkg_name} _real_name)
 
   # find the package
   find_package(${_real_name} REQUIRED ${_opt_pkg_ARGS})
 
   # check if the package is found
   if(_opt_pkg_PREFIX)
     set(_package_prefix ${_opt_pkg_PREFIX})
   else()
     string(TOUPPER ${${pkg_name}} _u_package)
     set(_package_prefix ${_u_package})
   endif()
 
   set(_act FALSE)
   set(_prefix_to_consider)
   if(_opt_pkg_FOUND)
     set(_act TRUE)
     set(_prefix_to_consider ${_package_prefix})
   else()
     foreach(_prefix ${_package_prefix})
       if(${_prefix}_FOUND)
 	set(_act TRUE)
 	list(APPEND _prefix_to_consider ${_prefix})
       endif()
     endforeach()
   endif()
 
   if(_act)
     foreach(_prefix ${_prefix_to_consider})
       # Generate the include dir for the package
       if(DEFINED ${_prefix}_INCLUDE_DIRS)
 	_package_set_include_dir(${_pkg_name} ${${_prefix}_INCLUDE_DIRS})
       elseif(DEFINED ${_prefix}_INCLUDE_DIR)
 	_package_set_include_dir(${_pkg_name} ${${_prefix}_INCLUDE_DIR})
       elseif(DEFINED ${_prefix}_INCLUDE_PATH)
 	_package_set_include_dir(${_pkg_name} ${${_prefix}_INCLUDE_PATH})
       endif()
 
       # Generate the libraries for the package
       if(DEFINED ${_prefix}_LIBRARIES)
 	_package_set_libraries(${_pkg_name} ${${_prefix}_LIBRARIES})
       elseif(DEFINED ${_prefix}_LIBRARY)
 	_package_set_libraries(${_pkg_name} ${${_prefix}_LIBRARY})
       endif()
     endforeach()
   endif()
   set(${activate} ${_act} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Sanity check functions
 # ------------------------------------------------------------------------------
 function(_package_check_files_exists)
   string(TOUPPER ${PROJECT_NAME} _project)
 
   set(_message FALSE)
 
   foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST})
     set(_pkg_files
       ${${_pkg_name}_SRCS}
       ${${_pkg_name}_PUBLIC_HEADERS}
       ${${_pkg_name}_PRIVATE_HEADERS}
       )
 
     _package_get_real_name(${_pkg_name} _real_name)
 
     foreach(_file ${_pkg_files})
       if(NOT EXISTS "${_file}")
 	if(NOT _message)
 	  set(_message TRUE)
 	  message("This file(s) is(are) present in a package but are not present on disk.")
 	endif()
 
 	message(" PACKAGE ${_real_name} FILE ${_file}")
       endif()
     endforeach()
   endforeach()
 
   if(_message)
     message(SEND_ERROR "Please check the content of your packages to correct this warnings")
   endif()
 endfunction()
 
 # ------------------------------------------------------------------------------
 function(_package_check_files_registered)
   set(_pkg_files)
   # generates a file list of registered files
   foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST})
     list(APPEND _pkg_files
       ${${_pkg_name}_SRCS}
       ${${_pkg_name}_PUBLIC_HEADERS}
       ${${_pkg_name}_PRIVATE_HEADERS}
       )
   endforeach()
 
   # generates the list of files in the source folders
   set(_all_src_files)
   foreach(_src_folder ${ARGN})
     foreach(_ext "cc" "hh" "c" "h" "hpp")
       file(GLOB_RECURSE _src_files "${_src_folder}/*.${_ext}")
       list(APPEND _all_src_files ${_src_files})
     endforeach()
   endforeach()
 
   if(_all_src_files)
     list(REMOVE_DUPLICATES _all_src_files)
   endif()
 
   set(_not_registerd_files)
   # check only sources files ine the source folders
   foreach(_src_folder ${ARGN})
     foreach(_file ${_all_src_files})
       if("${_file}" MATCHES  "${_src_folder}")
 	list(FIND _pkg_files "${_file}" _index)
 	if (_index EQUAL -1)
 	  list(APPEND _not_registerd_files ${_file})
 	endif()
       endif()
     endforeach()
   endforeach()
 
   if(AUTO_MOVE_UNKNOWN_FILES)
     file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/unknown_files)
   endif()
 
   # warn the user and move the files if needed
   if(_not_registerd_files)
     if(EXISTS ${PROJECT_BINARY_DIR}/missing_files_in_packages)
       file(REMOVE ${PROJECT_BINARY_DIR}/missing_files_in_packages)
     endif()
 
     message("This files are present in the source folders but are not registered in any package")
     foreach(_file ${_not_registerd_files})
       message(" ${_file}")
       if(AUTO_MOVE_UNKNOWN_FILES)
 	get_filename_component(_file_name ${_file} NAME)
 	file(RENAME ${_file} ${PROJECT_BINARY_DIR}/unknown_files/${_file_name})
       endif()
 
       file(APPEND ${PROJECT_BINARY_DIR}/missing_files_in_packages "${_file}
 ")
     endforeach()
 
     if(AUTO_MOVE_UNKNOWN_FILES)
       message(SEND_ERROR "The files where moved in the followinf folder ${PROJECT_BINARY_DIR}/unknown_files\n
 Please register them in the good package or clean the sources")
     else()
       message(SEND_ERROR "Please register them in the good package or clean the sources")
     endif()
 
   endif()
 endfunction()
diff --git a/extra_packages/students-extra-package b/extra_packages/students-extra-package
index d1c4780c2..05c0a753f 160000
--- a/extra_packages/students-extra-package
+++ b/extra_packages/students-extra-package
@@ -1 +1 @@
-Subproject commit d1c4780c20ef5e5f6aaa49f8242770d03f817911
+Subproject commit 05c0a753ff1d0ba7650bc6671894bae570d0f593
diff --git a/packages/embedded.cmake b/packages/embedded.cmake
index a25bcb541..df0eeb3ae 100644
--- a/packages/embedded.cmake
+++ b/packages/embedded.cmake
@@ -1,55 +1,55 @@
 #===============================================================================
 # @file   embedded.cmake
 #
 # @author Lucas Frérot <lucas.frerot@epfl.ch>
 #
 # @date creation: Tue Oct 16 2012
 # @date last modification: Thu Jun 12 2014
 #
 # @brief  package descrition for embedded model use
 #
 # @section LICENSE
 #
 # Copyright (©) 2010-2012, 2014 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(embedded 
   DESCRIPTION "Add support for the embedded solid mechanics model"
   DEPENDS CGAL)
 
 package_declare_sources(embedded
   model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh
 
   model/solid_mechanics/embedded_interface_intersector.hh
   model/solid_mechanics/embedded_interface_intersector.cc
   model/solid_mechanics/embedded_interface_model.hh
   model/solid_mechanics/embedded_interface_model.cc
 
   model/solid_mechanics/materials/material_embedded/embedded_internal_field.hh
 
   model/solid_mechanics/materials/material_embedded/material_reinforcement.hh
   model/solid_mechanics/materials/material_embedded/material_reinforcement.cc
   model/solid_mechanics/materials/material_embedded/material_reinforcement_inline_impl.cc
 
   model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh
-  model/solid_mechanics/materials/material_embedded/material_reinforcement_template_inline_impl.cc
+  model/solid_mechanics/materials/material_embedded/material_reinforcement_template_tmpl.hh
   )
 
 package_declare_documentation(embedded
 "This package allows the use of the embedded model in solid mechanics. This package depends on the CGAL package."
 )
diff --git a/src/common/aka_types.hh b/src/common/aka_types.hh
index dd98e4a82..0bc0ed8e9 100644
--- a/src/common/aka_types.hh
+++ b/src/common/aka_types.hh
@@ -1,1073 +1,1076 @@
 /**
  * @file   aka_types.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Thu Feb 17 2011
  * @date last modification: Tue Aug 19 2014
  *
  * @brief  description of the "simple" types
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_error.hh"
 #include "aka_fwd.hh"
 #include "aka_math.hh"
 #include "aka_array.hh"
 
 /* -------------------------------------------------------------------------- */
 #include <iomanip>
 
 #ifndef __INTEL_COMPILER
 #include <tr1/unordered_map>
 #else
 #include <map>
 #endif
 
 /* -------------------------------------------------------------------------- */
 #ifndef __AKANTU_AKA_TYPES_HH__
 #define __AKANTU_AKA_TYPES_HH__
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /* maps                                                                       */
 /* -------------------------------------------------------------------------- */
 #ifndef __INTEL_COMPILER
 template<class Key, class Ty>
 struct unordered_map { typedef typename std::tr1::unordered_map<Key, Ty> type; };
 #else
 template<class Key, class Ty>
 struct unordered_map { typedef typename std::map<Key, Ty> type; };
 #endif
 
 enum NormType {
   L_1 = 1,
   L_2 = 2,
   L_inf = UInt(-1)
 };
 
 
 /**
  * DimHelper is a class to generalize the setup of a dim array from 3
  * values. This gives a common interface in the TensorStorage class
  * independently of its derived inheritance (Vector, Matrix, Tensor3)
  */
 template<UInt dim>
 struct DimHelper {
   static inline void setDims(UInt m, UInt n, UInt p, UInt dims[dim]);
 };
 
 /* -------------------------------------------------------------------------- */
 template<>
 struct DimHelper<1> {
   static inline void setDims(UInt m,
 			     __attribute__((unused)) UInt n,
 			     __attribute__((unused)) UInt p,
 			     UInt dims[1]) {
     dims[0] = m;
   }
 };
 
 /* -------------------------------------------------------------------------- */
 template<>
 struct DimHelper<2> {
   static inline void setDims(UInt m,
 			     UInt n,
 			     __attribute__((unused)) UInt p,
 			     UInt dims[2]) {
     dims[0] = m;
     dims[1] = n;
   }
 };
 
 /* -------------------------------------------------------------------------- */
 template<>
 struct DimHelper<3> {
   static inline void setDims(UInt m,
 			     UInt n,
 			     UInt p,
 			     UInt dims[3]) {
     dims[0] = m;
     dims[1] = n;
     dims[2] = p;
   }
 };
 
 
 /* -------------------------------------------------------------------------- */
 template<typename T, UInt ndim, class RetType>
 class TensorStorage;
 
 /* -------------------------------------------------------------------------- */
 /* Proxy classes                                                              */
 /* -------------------------------------------------------------------------- */
 
 /**
  * The TensorProxy class is a proxy class to the TensorStorage it handles the
  * wrapped case. That is to say if an accessor should give access to a Tensor
  * wrapped on some data, like the Array<T>::iterator they can return a
  * TensorProxy that will be automatically transformed as a TensorStorage wrapped
  * on the same data
  */
 template<typename T, UInt ndim, class RetType>
 class TensorProxy {
 protected:
   TensorProxy(T * data, UInt m, UInt n, UInt p) {
     DimHelper<ndim>::setDims(m, n, p, this->n);
     this->values = data;
   }
 
   TensorProxy(const TensorProxy & other) {
     this->values = other.storage();
     for (UInt i = 0; i < ndim; ++i)
       this->n[i] = other.n[i];
   }
 
   inline TensorProxy(const TensorStorage<T, ndim, RetType> & other);
 
 public:
   UInt size(UInt i) const {
     AKANTU_DEBUG_ASSERT(i < ndim,
 			"This tensor has only "
 			<< ndim << " dimensions, not " << (i + 1));
     return n[i];
   }
 
   inline UInt size() const{
     UInt _size = 1;
     for (UInt d = 0; d < ndim; ++d) _size *= this->n[d];
     return _size;
   }
 
   T * storage() const { return values; }
 
   inline TensorProxy & operator=(const RetType & src) {
     AKANTU_DEBUG_ASSERT(src.size() == this->size(),
 			"You are trying to copy two tensors with different sizes");
     memcpy(this->values, src.storage(), this->size() * sizeof(T));
     return *this;
   }
 
   inline TensorProxy & operator=(const TensorProxy & src) {
     AKANTU_DEBUG_ASSERT(src.size() == this->size(),
 			"You are trying to copy two tensors with different sizes");
     memcpy(this->values, src.storage(), this->size() * sizeof(T));
     return *this;
   }
 
 protected:
   T * values;
   UInt n[ndim];
 };
 
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 class VectorProxy : public TensorProxy<T, 1, Vector<T> > {
   typedef TensorProxy<T, 1, Vector<T> > parent;
   typedef Vector<T> type;
 public:
   VectorProxy(T * data, UInt n) : parent(data, n, 0, 0) { }
   VectorProxy(const VectorProxy & src) : parent(src) {  }
   VectorProxy(const Vector<T> & src) : parent(src) { }
   VectorProxy & operator=(const type & src) {
     parent::operator=(src);
     return *this;
   }
   VectorProxy & operator=(const VectorProxy & src) {
     parent::operator=(src);
     return *this;
   }
+
+  T & operator()(UInt index){return this->values[index];};
+  const T & operator()(UInt index) const {return this->values[index];};
 };
 
 template<typename T>
 class MatrixProxy : public TensorProxy<T, 2, Matrix<T> > {
   typedef TensorProxy<T, 2, Matrix<T> > parent;
   typedef Matrix<T> type;
 public:
   MatrixProxy(T * data, UInt m, UInt n) : parent(data, m, n, 0) { }
   MatrixProxy(const MatrixProxy & src) : parent(src) {  }
   MatrixProxy(const type & src) : parent(src) { }
   MatrixProxy & operator=(const type & src) {
     parent::operator=(src);
     return *this;
   }
   MatrixProxy & operator=(const MatrixProxy & src) {
     parent::operator=(src);
     return *this;
   }
 };
 
 template<typename T>
 class Tensor3Proxy : public TensorProxy<T, 3, Tensor3<T> > {
   typedef TensorProxy<T, 3, Tensor3<T> > parent;
   typedef Tensor3<T> type;
 public:
   Tensor3Proxy(T * data, UInt m, UInt n, UInt k) :
     parent(data, m, n, k) { }
   Tensor3Proxy(const Tensor3Proxy & src) : parent(src) {  }
   Tensor3Proxy(const Tensor3<T> & src) : parent(src) { }
   Tensor3Proxy & operator=(const type & src) {
     parent::operator=(src);
     return *this;
   }
   Tensor3Proxy & operator=(const Tensor3Proxy & src) {
     parent::operator=(src);
     return *this;
   }
 };
 
 /* -------------------------------------------------------------------------- */
 /* Tensor base class                                                          */
 /* -------------------------------------------------------------------------- */
 template<typename T, UInt ndim, class RetType>
 class TensorStorage {
 public:
   typedef T value_type;
 protected:
   template<class TensorType>
   void copySize(const TensorType & src) {
     for (UInt d = 0; d < ndim; ++d) this->n[d] = src.size(d);
     this->_size = src.size();
   }
 
   TensorStorage() :
     values(NULL), wrapped(false) {
     for (UInt d = 0; d < ndim; ++d) this->n[d] = 0;
     _size = 0;
   }
 
   TensorStorage(const TensorProxy<T, ndim, RetType> & proxy) {
     this->copySize(proxy);
     this->values = proxy.storage();
     this->wrapped = true;
   }
 
 protected:
   TensorStorage(const TensorStorage & src) { }
 
 public:
 
   TensorStorage(const TensorStorage & src, bool deep_copy) :
     values(NULL), wrapped(false) {
     if(deep_copy) this->deepCopy(src);
     else this->shallowCopy(src);
   }
 
 protected:
   TensorStorage(UInt m, UInt n, UInt p, const T & def) {
     DimHelper<ndim>::setDims(m, n, p, this->n);
 
     this->computeSize();
     this->values = new T[this->_size];
     this->set(def);
     this->wrapped = false;
   }
 
   TensorStorage(T * data, UInt m, UInt n, UInt p) {
     DimHelper<ndim>::setDims(m, n, p, this->n);
 
     this->computeSize();
     this->values = data;
     this->wrapped = true;
   }
 
 public:
   /* ------------------------------------------------------------------------ */
   template<class TensorType>
   inline void shallowCopy(const TensorType & src) {
     this->copySize(src);
     if(!this->wrapped) delete[] this->values;
     this->values = src.storage();
     this->wrapped = true;
   }
 
   /* ------------------------------------------------------------------------ */
   template<class TensorType>
   inline void deepCopy(const TensorType & src) {
     this->copySize(src);
     if(!this->wrapped) delete [] this->values;
     this->values = new T[this->_size];
     memcpy(this->values, src.storage(), this->_size * sizeof(T));
     this->wrapped = false;
   }
 
   virtual ~TensorStorage() {
     if(!this->wrapped)
       delete [] this->values;
   }
 
   /* ------------------------------------------------------------------------ */
   inline TensorStorage & operator=(const RetType & src) {
     if(this != &src) {
       if (this->wrapped) {
 	// this test is not sufficient for Tensor of order higher than 1
 	AKANTU_DEBUG_ASSERT(this->_size == src.size(), "Tensors of different size");
 	memcpy(this->values, src.storage(), this->_size * sizeof(T));
       } else {
 	deepCopy(src);
       }
     }
     return *this;
   }
 
   /* ------------------------------------------------------------------------ */
   template<class R>
   inline RetType & operator+=(const TensorStorage<T, ndim, R> & other) {
     T * a = this->storage();
     T * b = other.storage();
     AKANTU_DEBUG_ASSERT(_size == other.size(),
 			"The two tensors do not have the same size, they cannot be subtracted");
     for (UInt i = 0; i < _size; ++i) *(a++) += *(b++);
     return *(static_cast<RetType *>(this));
   }
 
   /* ------------------------------------------------------------------------ */
   template<class R>
   inline RetType & operator-=(const TensorStorage<T, ndim, R> & other) {
     T * a = this->storage();
     T * b = other.storage();
     AKANTU_DEBUG_ASSERT(_size == other.size(),
 			"The two tensors do not have the same size, they cannot be subtracted");
     for (UInt i = 0; i < _size; ++i) *(a++) -= *(b++);
     return *(static_cast<RetType *>(this));
   }
 
   /* ------------------------------------------------------------------------ */
   inline RetType & operator+=(const T & x) {
     T * a = this->values;
     for (UInt i = 0; i < _size; ++i) *(a++) += x;
     return *(static_cast<RetType *>(this));
   }
 
   /* ------------------------------------------------------------------------ */
   inline RetType & operator-=(const T & x) {
     T * a = this->values;
     for (UInt i = 0; i < _size; ++i) *(a++) -= x;
     return *(static_cast<RetType *>(this));
   }
 
   /* ------------------------------------------------------------------------ */
   inline RetType & operator*=(const T & x) {
     T * a = this->storage();
     for (UInt i = 0; i < _size; ++i) *(a++) *= x;
     return *(static_cast<RetType *>(this));
   }
 
   /* ---------------------------------------------------------------------- */
   inline RetType & operator/=(const T & x) {
     T * a = this->values;
     for (UInt i = 0; i < _size; ++i) *(a++) /= x;
     return *(static_cast<RetType *>(this));
   }
 
   /* ------------------------------------------------------------------------ */
   T * storage() const { return values; }
   UInt size() const { return _size; }
   UInt size(UInt i) const {
     AKANTU_DEBUG_ASSERT(i < ndim,
 			"This tensor has only "
 			<< ndim << " dimensions, not " << (i + 1));
     return n[i];
   };
   /* ------------------------------------------------------------------------ */
   inline void clear() { memset(values, 0, _size * sizeof(T)); };
   inline void set(const T & t) { std::fill_n(values, _size, t); };
 
 
   template<class TensorType>
   inline void copy(const TensorType & other) {
     AKANTU_DEBUG_ASSERT(_size == other.size(),
 			"The two tensors do not have the same size, they cannot be copied");
     memcpy(values, other.storage(), _size * sizeof(T));
   }
 
 
   bool isWrapped() const { return this->wrapped; }
 protected:
   friend class Array<T>;
 
   inline void computeSize() {
     _size = 1;
     for (UInt d = 0; d < ndim; ++d) _size *= this->n[d];
   }
 
 protected:
   template<typename R, NormType norm_type>
   struct NormHelper {
     template<class Ten>
     static R norm(const Ten & ten) {
       R _norm = 0.;
       R * it = ten.storage();
       R * end = ten.storage() + ten.size();
       for (; it < end; ++it) _norm += std::pow(std::abs(*it), norm_type);
       return std::pow(_norm, 1./norm_type);
     }
   };
 
   template<typename R>
   struct NormHelper<R, L_1> {
     template<class Ten>
     static R norm(const Ten & ten) {
       R _norm = 0.;
       R * it = ten.storage();
       R * end = ten.storage() + ten.size();
       for (; it < end; ++it) _norm += std::abs(*it);
       return _norm;
     }
   };
 
   template<typename R>
   struct NormHelper<R, L_2> {
     template<class Ten>
     static R norm(const Ten & ten) {
       R _norm = 0.;
       R * it = ten.storage();
       R * end = ten.storage() + ten.size();
       for (; it < end; ++it) _norm += *it * *it;
       return sqrt(_norm);
     }
   };
 
   template<typename R>
   struct NormHelper<R, L_inf> {
     template<class Ten>
     static R norm(const Ten & ten) {
       R _norm = 0.;
       R * it = ten.storage();
       R * end = ten.storage() + ten.size();
       for (; it < end; ++it) _norm = std::max(std::abs(*it), _norm);
       return _norm;
     }
   };
 
 public:
 
   /*----------------------------------------------------------------------- */
   /// "Entrywise" norm norm<L_p> @f[ \|\boldsymbol{T}\|_p = \left(
   /// \sum_i^{n[0]}\sum_j^{n[1]}\sum_k^{n[2]} |T_{ijk}|^p \right)^{\frac{1}{p}}
   /// @f]
   template<NormType norm_type>
   inline T norm() const { return NormHelper<T, norm_type>::norm(*this); }
 
 protected:
   UInt n[ndim];
   UInt _size;
   T * values;
   bool wrapped;
 };
 
 
 template<typename T, UInt ndim, class RetType>
 inline TensorProxy<T, ndim, RetType>::TensorProxy(const TensorStorage<T, ndim, RetType> & other) {
   this->values = other.storage();
   for (UInt i = 0; i < ndim; ++i)
     this->n[i] = other.size(i);
 }
 
 /* -------------------------------------------------------------------------- */
 /* Vector                                                                     */
 /* -------------------------------------------------------------------------- */
 template<typename T>
 class Vector : public TensorStorage< T, 1, Vector<T> > {
   typedef TensorStorage< T, 1, Vector<T> > parent;
 public:
   typedef typename parent::value_type value_type;
   typedef VectorProxy<T> proxy;
 public:
   Vector() : parent() {}
   Vector(UInt n, const T & def = T()) : parent(n, 0, 0, def) { }
   Vector(T * data, UInt n) : parent(data, n, 0, 0) { }
   Vector(const Vector & src, bool deep_copy = true) : parent(src, deep_copy) { }
   Vector(const VectorProxy<T> & src) : parent(src) { }
 
 public:
   virtual ~Vector() { };
 
   /* ------------------------------------------------------------------------ */
   inline Vector & operator=(const Vector & src) {
     parent::operator=(src);
     return *this;
   }
 
   /* ------------------------------------------------------------------------ */
   inline T& operator()(UInt i) { return *(this->values + i); };
   inline const T& operator()(UInt i) const { return *(this->values + i); };
   inline T& operator[](UInt i) { return *(this->values + i); };
   inline const T& operator[](UInt i) const { return *(this->values + i); };
 
   /* ------------------------------------------------------------------------ */
   inline Vector<T> & operator*=(Real x) { return parent::operator*=(x); }
   inline Vector<T> & operator/=(Real x) { return parent::operator/=(x); }
 
   /* ------------------------------------------------------------------------ */
   inline Vector<T> & operator*=(const Vector<T> & vect) {
     T * a = this->storage();
     T * b = vect.storage();
     for (UInt i = 0; i < this->_size; ++i) *(a++) *= *(b++);
     return *this;
   }
 
   /* ------------------------------------------------------------------------ */
   inline Real dot(const Vector<T> & vect) const {
     return Math::vectorDot(this->values, vect.storage(), this->_size);
   }
 
   /* ------------------------------------------------------------------------ */
   inline Real mean() const {
     Real mean = 0;
     T * a = this->storage();
     for (UInt i = 0; i < this->_size; ++i) mean += *(a++);
     return mean / this->_size;
   }
 
   /* ------------------------------------------------------------------------ */
   inline Vector & crossProduct(const Vector<T> & v1,
 			       const Vector<T> & v2) {
     AKANTU_DEBUG_ASSERT(this->size() == 3,
 			"crossProduct is only defined in 3D (n=" << this->size() << ")");
     AKANTU_DEBUG_ASSERT(this->size() == v1.size() && this->size() == v2.size(),
 			"crossProduct is not a valid operation non matching size vectors");
     Math::vectorProduct3(v1.storage(), v2.storage(), this->values);
     return *this;
   }
 
   /* ------------------------------------------------------------------------ */
   inline void solve(Matrix<T> & A, const Vector<T> & b) {
     AKANTU_DEBUG_ASSERT(this->size() == A.rows() && this->_size = A.cols(),
 			"The size of the solution vector mismatches the size of the matrix");
     AKANTU_DEBUG_ASSERT(this->_size == b._size, "The rhs vector has a mismatch in size with the matrix");
     Math::solve(this->_size, A.storage(), this->values, b.storage());
   }
 
   /* ------------------------------------------------------------------------ */
   template<bool tr_A>
   inline void mul(const Matrix<T> & A,
 		  const Vector<T> & x,
 		  Real alpha = 1.0);
   /* ------------------------------------------------------------------------ */
   inline Real norm() const {
     return parent::template norm<L_2>();
   }
 
   template<NormType nt>
   inline Real norm() const {
     return parent::template norm<nt>();
   }
 
   /* ------------------------------------------------------------------------ */
   inline void normalize() {
     Real n = norm();
     operator/=(n);
   }
 
   /* ------------------------------------------------------------------------ */
   /// norm of (*this - x)
   inline Real distance(const Vector<T> & y) const {
     Real * vx = this->values; Real * vy = y.storage();
     Real sum_2 = 0;
     for (UInt i = 0; i < this->_size; ++i, ++vx, ++vy) sum_2 += (*vx - *vy)*(*vx - *vy);
     return sqrt(sum_2);
   }
 
   /* ------------------------------------------------------------------------ */
   inline bool equal(const Vector<T> & v, Real tolerance = Math::getTolerance()) const {
     T * a = this->storage();
     T * b = v.storage();
     UInt i = 0;
     while (i < this->_size && (std::abs(*(a++) - *(b++)) < tolerance)) ++i;
     return i == this->_size;
   }
 
   /* ------------------------------------------------------------------------ */
   inline short compare(const Vector<T> & v, Real tolerance = Math::getTolerance()) const {
     T * a = this->storage();
     T * b = v.storage();
     for (UInt i(0); i < this->_size; ++i, ++a, ++b) {
       if(std::abs(*a - *b) > tolerance)
 	return (((*a - *b) > tolerance) ? 1 : -1);
     }
     return 0;
   }
 
   /* ------------------------------------------------------------------------ */
   inline bool operator==(const Vector<T> & v) const { return equal(v); }
   inline bool operator<(const Vector<T> & v) const { return compare(v) == -1; }
   inline bool operator>(const Vector<T> & v) const { return compare(v) == 1; }
 
   /* ------------------------------------------------------------------------ */
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const {
     std::string space;
     for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
     stream << "[";
     for (UInt i = 0; i < this->_size; ++i) {
       if(i != 0) stream << ", ";
       stream << this->values[i];
     }
     stream << "]";
   }
 
   friend class ::akantu::Array<T>;
 };
 
 typedef Vector<Real> RVector;
 
 /* ------------------------------------------------------------------------ */
 template<>
 inline bool Vector<UInt>::equal(const Vector<UInt> & v, __attribute__((unused)) Real tolerance) const {
   UInt * a = this->storage();
   UInt * b = v.storage();
   UInt i = 0;
   while (i < this->_size && (*(a++) == *(b++))) ++i;
   return i == this->_size;
 }
 
 
 /* ------------------------------------------------------------------------ */
 /* Matrix                                                                   */
 /* ------------------------------------------------------------------------ */
 template<typename T>
 class Matrix : public TensorStorage< T, 2, Matrix<T> > {
   typedef TensorStorage< T, 2, Matrix<T> > parent;
 public:
   typedef typename parent::value_type value_type;
   typedef MatrixProxy<T> proxy;
 public:
   Matrix() : parent() {}
   Matrix(UInt m, UInt n, const T & def = T()) : parent(m, n, 0, def) { }
   Matrix(T * data, UInt m, UInt n) : parent(data, m, n, 0) { }
   Matrix(const Matrix & src, bool deep_copy = true) : parent(src, deep_copy) { }
   Matrix(const MatrixProxy<T> & src) : parent(src) { }
 
   virtual ~Matrix() { }
   /* ------------------------------------------------------------------------ */
   inline Matrix & operator=(const Matrix & src) {
     parent::operator=(src);
     return *this;
   }
 
 public:
   /* ---------------------------------------------------------------------- */
   UInt rows() const { return this->n[0]; }
   UInt cols() const { return this->n[1]; }
 
   /* ---------------------------------------------------------------------- */
   inline T& at(UInt i, UInt j) {
     return *(this->values + i + j*this->n[0]);
   }
 
   inline const T & at(UInt i, UInt j) const {
     return *(this->values + i + j*this->n[0]);
   }
 
   /* ---------------------------------------------------------------------- */
   inline T & operator()(UInt i, UInt j) { return this->at(i,j); }
   inline const T & operator()(UInt i, UInt j) const { return this->at(i,j); }
 
   /// give a line vector wrapped on the column i
   inline VectorProxy<T> operator()(UInt j) {
     return VectorProxy<T>(this->values + j*this->n[0], this->n[0]);
   }
   inline const VectorProxy<T> operator()(UInt j) const {
     return VectorProxy<T>(this->values + j*this->n[0], this->n[0]);
   }
 
   inline T& operator[](UInt idx) { return *(this->values + idx); };
   inline const T& operator[](UInt idx) const { return *(this->values + idx); };
 
   /* ---------------------------------------------------------------------- */
   inline Matrix operator* (const Matrix & B) {
     Matrix C(this->rows(), B.cols());
     C.mul<false, false>(*this, B);
     return C;
   }
 
   /* ----------------------------------------------------------------------- */
   inline Matrix & operator*= (const T & x) {
     return parent::operator*= (x);
   }
 
   inline Matrix & operator*= (const Matrix & B) {
     Matrix C(*this);
     this->mul<false, false>(C, B);
     return *this;
   }
 
   /* ---------------------------------------------------------------------- */
   template<bool tr_A, bool tr_B>
   inline void mul(const Matrix & A, const Matrix & B, T alpha = 1.0) {
     UInt k = A.cols();
     if(tr_A) k = A.rows();
 
 #ifndef AKANTU_NDEBUG
     if (tr_B){
       AKANTU_DEBUG_ASSERT(k == B.cols(),
 			  "matrices to multiply have no fit dimensions");
       AKANTU_DEBUG_ASSERT(this->cols() == B.rows(),
 			  "matrices to multiply have no fit dimensions");
     }
     else {
       AKANTU_DEBUG_ASSERT(k == B.rows(),
 			  "matrices to multiply have no fit dimensions");
       AKANTU_DEBUG_ASSERT(this->cols() == B.cols(),
 			  "matrices to multiply have no fit dimensions");
     }
     if (tr_A){
       AKANTU_DEBUG_ASSERT(this->rows() == A.cols(),
 			  "matrices to multiply have no fit dimensions");
     }
     else{
       AKANTU_DEBUG_ASSERT(this->rows() == A.rows(),
 			  "matrices to multiply have no fit dimensions");
     }
 #endif //AKANTU_NDEBUG
 
     Math::matMul<tr_A, tr_B>(this->rows(), this->cols(), k,
 			     alpha, A.storage(), B.storage(),
 			     0., this->storage());
   }
 
   /* ---------------------------------------------------------------------- */
   inline void outerProduct(const Vector<T> & A,
 			   const Vector<T> & B) {
     AKANTU_DEBUG_ASSERT(A.size() == this->rows() && B.size() == this->cols(),
 			"A and B are not compatible with the size of the matrix");
     for (UInt i = 0; i < this->rows(); ++i) {
       for (UInt j = 0; j < this->cols(); ++j) {
 	this->values[i + j * this->rows()] += A[i] * B[j];
       }
     }
   }
 
 private:
   class EigenSorter {
   public:
     EigenSorter(const Vector<T> & eigs) : eigs(eigs) { }
 
     bool operator()(const UInt & a, const UInt & b) const {
       return (eigs(a) > eigs(b));
     }
 
   private:
     const Vector<T> & eigs;
   };
 
 public:
   /* ---------------------------------------------------------------------- */
   inline void eig(Vector<T> & eigenvalues, Matrix<T> & eigenvectors) const {
     AKANTU_DEBUG_ASSERT(this->cols() == this->rows(),
 			"eig is not a valid operation on a rectangular matrix");
     AKANTU_DEBUG_ASSERT(eigenvalues.size() == this->cols(),
 			"eigenvalues should be of size " << this->cols() << ".");
 #ifndef AKANTU_NDEBUG
     if(eigenvectors.storage() != NULL)
       AKANTU_DEBUG_ASSERT((eigenvectors.rows() == eigenvectors.cols()) &&
 			  (eigenvectors.rows() == this->cols()),
 			  "Eigenvectors needs to be a square matrix of size "
 			  << this->cols() << " x " << this->cols() << ".");
 #endif
 
     Matrix<T> tmp = *this;
     Vector<T> tmp_eigs(eigenvalues.size());
     Matrix<T> tmp_eig_vects(eigenvectors.rows(), eigenvectors.cols());
 
     if(tmp_eig_vects.rows() == 0 || tmp_eig_vects.cols() == 0)
       Math::matrixEig(tmp.cols(), tmp.storage(), tmp_eigs.storage());
     else
       Math::matrixEig(tmp.cols(), tmp.storage(), tmp_eigs.storage(), tmp_eig_vects.storage());
 
     Vector<UInt> perm(eigenvalues.size());
     for (UInt i = 0; i < perm.size(); ++i) perm(i) = i;
 
     std::sort(perm.storage(), perm.storage() + perm.size(), EigenSorter(tmp_eigs));
 
     for (UInt i = 0; i < perm.size(); ++i) eigenvalues(i) = tmp_eigs(perm(i));
 
     if(tmp_eig_vects.rows() != 0 && tmp_eig_vects.cols() != 0)
       for (UInt i = 0; i < perm.size(); ++i) {
 	for (UInt j = 0; j < eigenvectors.rows(); ++j) {
 	  eigenvectors(j, i) = tmp_eig_vects(j, perm(i));
 	}
       }
   }
 
   /* ---------------------------------------------------------------------- */
   inline void eig(Vector<T> & eigenvalues) const {
     Matrix<T> empty;
     eig(eigenvalues, empty);
   }
 
   /* ---------------------------------------------------------------------- */
   inline void eye(T alpha = 1.) {
     AKANTU_DEBUG_ASSERT(this->cols() == this->rows(),
 			"eye is not a valid operation on a rectangular matrix");
     this->clear();
     for (UInt i = 0; i < this->cols(); ++i) {
       this->values[i + i * this->rows()] = alpha;
     }
   }
 
   /* ---------------------------------------------------------------------- */
   static inline Matrix<T> eye(UInt m, T alpha = 1.) {
     Matrix<T> tmp(m, m);
     tmp.eye(alpha);
     return tmp;
   }
 
   /* ---------------------------------------------------------------------- */
   inline T trace() const {
     AKANTU_DEBUG_ASSERT(this->cols() == this->rows(),
 			"trace is not a valid operation on a rectangular matrix");
     T trace = 0.;
     for (UInt i = 0; i < this->rows(); ++i) {
       trace += this->values[i + i * this->rows()];
     }
     return trace;
   }
 
   /* ---------------------------------------------------------------------- */
   inline Matrix transpose() const {
     Matrix tmp(this->cols(), this->rows());
     for (UInt i = 0; i < this->rows(); ++i) {
       for (UInt j = 0; j < this->cols(); ++j) {
 	tmp(j,i) = operator()(i, j);
       }
     }
     return tmp;
   }
 
   /* ---------------------------------------------------------------------- */
   inline void inverse(const Matrix & A) {
     AKANTU_DEBUG_ASSERT(A.cols() == A.rows(),
 			"inv is not a valid operation on a rectangular matrix");
     AKANTU_DEBUG_ASSERT(this->cols() == A.cols(),
 			"the matrix should have the same size as its inverse");
 
     if(this->cols() == 1) *this->values = 1./ *A.storage();
     else if(this->cols() == 2) Math::inv2(A.storage(), this->values);
     else if(this->cols() == 3) Math::inv3(A.storage(), this->values);
     else Math::inv(this->cols(), A.storage(), this->values);
   }
 
   /* --------------------------------------------------------------------- */
   inline T det() const {
     AKANTU_DEBUG_ASSERT(this->cols() == this->rows(),
 			"inv is not a valid operation on a rectangular matrix");
     if(this->cols() == 1) return *(this->values);
     else if(this->cols() == 2) return Math::det2(this->values);
     else if(this->cols() == 3) return Math::det3(this->values);
     else return Math::det(this->cols(), this->values);
   }
 
   /* --------------------------------------------------------------------- */
   inline T doubleDot(const Matrix<T> & other) const {
      AKANTU_DEBUG_ASSERT(this->cols() == this->rows(),
 			 "doubleDot is not a valid operation on a rectangular matrix");
      if(this->cols() == 1) return *(this->values) * *(other.storage());
      else if(this->cols() == 2) return Math::matrixDoubleDot22(this->values, other.storage());
      else if(this->cols() == 3) return Math::matrixDoubleDot33(this->values, other.storage());
      else AKANTU_DEBUG_ERROR("doubleDot is not defined for other spatial dimensions"
 			     << " than 1, 2 or 3.");
      return T();
   }
 
   /* ---------------------------------------------------------------------- */
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const {
     std::string space;
     for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
     stream << "[";
     for (UInt i = 0; i < this->n[0]; ++i) {
       if(i != 0) stream << ", ";
       stream << "[";
       for (UInt j = 0; j < this->n[1]; ++j) {
 	if(j != 0) stream << ", ";
 	stream << operator()(i, j);
       }
       stream << "]";
     }
     stream << "]";
   };
 };
 
 /* ------------------------------------------------------------------------ */
 template<typename T>
 template<bool tr_A>
 inline void Vector<T>::mul(const Matrix<T> & A,
 			  const Vector<T> & x,
 			  Real alpha) {
 #ifndef AKANTU_NDEBUG
   UInt n = x.size();
   if (tr_A){
     AKANTU_DEBUG_ASSERT(n == A.rows(), "matrix and vector to multiply have no fit dimensions");
     AKANTU_DEBUG_ASSERT(this->size() == A.cols(), "matrix and vector to multiply have no fit dimensions");
   } else {
     AKANTU_DEBUG_ASSERT(n == A.cols(), "matrix and vector to multiply have no fit dimensions");
     AKANTU_DEBUG_ASSERT(this->size() == A.rows(), "matrix and vector to multiply have no fit dimensions");
   }
 #endif
   Math::matVectMul<tr_A>(A.rows(), A.cols(), alpha, A.storage(), x.storage(), 0., this->storage());
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline std::ostream & operator<<(std::ostream & stream, const Matrix<T> & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline std::ostream & operator<<(std::ostream & stream, const Vector<T> & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 /* ------------------------------------------------------------------------ */
 /* Tensor3                                                                  */
 /* ------------------------------------------------------------------------ */
 template<typename T>
 class Tensor3 : public TensorStorage< T, 3, Tensor3<T> > {
   typedef TensorStorage< T, 3, Tensor3<T> > parent;
 public:
   typedef typename parent::value_type value_type;
   typedef Tensor3Proxy<T> proxy;
 public:
   Tensor3() : parent() { };
 
   Tensor3(UInt m, UInt n, UInt p, const T & def = T()) : parent(m, n, p, def) {  }
 
   Tensor3(T * data, UInt m, UInt n, UInt p) : parent(data, m, n, p) {  }
 
   Tensor3(const Tensor3 & src, bool deep_copy = true) : parent(src, deep_copy) { }
 
 public:
   /* ------------------------------------------------------------------------ */
   inline Tensor3 & operator=(const Tensor3 & src) {
     parent::operator=(src);
     return *this;
   }
 
   /* ---------------------------------------------------------------------- */
   inline T& operator()(UInt i, UInt j, UInt k)
   { return *(this->values + (k*this->n[0] + i)*this->n[1] + j); };
   inline const T& operator()(UInt i, UInt j, UInt k) const
   { return *(this->values + (k*this->n[0] + i)*this->n[1] + j); };
 
   inline MatrixProxy<T> operator()(UInt k)
   { return MatrixProxy<T>(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); }
   inline const MatrixProxy<T> operator()(UInt k) const
   { return MatrixProxy<T>(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); }
 
   inline MatrixProxy<T> operator[](UInt k)
   { return Matrix<T>(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); }
   inline const MatrixProxy<T> operator[](UInt k) const
   { return MatrixProxy<T>(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); }
 };
 
 
 /* -------------------------------------------------------------------------- */
 // support operations for the creation of other vectors
 /* -------------------------------------------------------------------------- */
 template <typename T>
 Vector<T> operator*(const T & scalar, const Vector<T> & a) {
   Vector<T> r(a);
   r *= scalar;
   return r;
 }
 
 template <typename T>
 Vector<T> operator*(const Vector<T> & a, const T & scalar) {
   Vector<T> r(a);
   r *= scalar;
   return r;
 }
 
 template <typename T>
 Vector<T> operator/(const Vector<T> & a, const T & scalar) {
   Vector<T> r(a);
   r /= scalar;
   return r;
 }
 
 template <typename T>
 Vector<T> operator+(const Vector<T> & a, const Vector<T> & b) {
   Vector<T> r(a);
   r += b;
   return r;
 }
 
 template <typename T>
 Vector<T> operator-(const Vector<T>& a, const Vector<T>& b) {
   Vector<T> r(a);
   r -= b;
   return r;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 Matrix<T> operator*(const T & scalar, const Matrix<T>& a) {
   Matrix<T> r(a);
   r *= scalar;
   return r;
 }
 
 template <typename T>
 Matrix<T> operator*(const Matrix<T>& a, const T & scalar) {
   Matrix<T> r(a);
   r *= scalar;
   return r;
 }
 
 template <typename T>
 Matrix<T> operator/(const Matrix<T>& a, const T & scalar) {
   Matrix<T> r(a);
   r /= scalar;
   return r;
 }
 
 template <typename T>
 Matrix<T> operator+(const Matrix<T>& a, const Matrix<T>& b) {
   Matrix<T> r(a);
   r += b;
   return r;
 }
 
 template <typename T>
 Matrix<T> operator-(const Matrix<T>& a, const Matrix<T>& b) {
   Matrix<T> r(a);
   r -= b;
   return r;
 }
 
 
 
 __END_AKANTU__
 
 #endif /* __AKANTU_AKA_TYPES_HH__ */
diff --git a/src/io/mesh_io.cc b/src/io/mesh_io.cc
index 7263bc2df..913385b26 100644
--- a/src/io/mesh_io.cc
+++ b/src/io/mesh_io.cc
@@ -1,95 +1,152 @@
 /**
  * @file   mesh_io.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Thu Jul 15 2010
  * @date last modification: Fri Jun 13 2014
  *
  * @brief  common part for all mesh io classes
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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 "mesh_io.hh"
 
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 MeshIO::MeshIO() {
   canReadSurface      = false;
   canReadExtendedData = false;
 }
 
 /* -------------------------------------------------------------------------- */
 MeshIO::~MeshIO() {
 
 }
 
 /* -------------------------------------------------------------------------- */
 MeshIO * MeshIO::getMeshIO(const std::string & filename, const MeshIOType & type) {
   MeshIOType t = type;
   if(type == _miot_auto) {
     std::string::size_type idx = filename.rfind('.');
     std::string ext;
     if(idx != std::string::npos) {
       ext = filename.substr(idx+1);
     }
 
     if(ext == "msh") { t = _miot_gmsh;
     } else if(ext == "diana") { t = _miot_diana;
     } else if(ext == "inp")   { t = _miot_abaqus;
     } else AKANTU_EXCEPTION("Cannot guess the type of file of "
 			    << filename << " (ext "<< ext <<"). "
 			    << "Please provide the MeshIOType to the read function");
   }
 
   switch(t) {
   case _miot_gmsh         : return new MeshIOMSH();
 #if defined(AKANTU_STRUCTURAL_MECHANICS)
   case _miot_gmsh_struct  : return new MeshIOMSHStruct();
 #endif
   case _miot_diana        : return new MeshIODiana();
   case _miot_abaqus       : return new MeshIOAbaqus();
   default:
     return NULL;
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshIO::read(const std::string & filename, Mesh & mesh, const MeshIOType & type) {
   MeshIO * mesh_io = getMeshIO(filename, type);
   mesh_io->read(filename, mesh);
   delete mesh_io;
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshIO::write(const std::string & filename, Mesh & mesh, const MeshIOType & type) {
   MeshIO * mesh_io = getMeshIO(filename, type);
   mesh_io->write(filename, mesh);
   delete mesh_io;
 }
 
+/* -------------------------------------------------------------------------- */
+void MeshIO::constructPhysicalNames(const std::string & tag_name,
+				    Mesh & mesh) {
+
+  if(!phys_name_map.empty()) {
+    for(Mesh::type_iterator type_it = mesh.firstType();
+	type_it != mesh.lastType();
+	++type_it) {
+      
+      Array<std::string> * name_vec =
+	mesh.getDataPointer<std::string>("physical_names", *type_it);
+
+      const Array<UInt> & tags_vec =
+	mesh.getData<UInt>(tag_name, *type_it);
+      
+      for(UInt i(0); i < tags_vec.getSize(); i++) {
+        std::map<UInt, std::string>::const_iterator map_it
+	  = phys_name_map.find(tags_vec(i));
+
+        if(map_it == phys_name_map.end()) {
+          std::stringstream sstm;
+          sstm << tags_vec(i);
+          name_vec->operator()(i) = sstm.str();
+        } else {
+          name_vec->operator()(i) = map_it->second;
+        }
+      }
+    }
+  }
+}
+
+/* -------------------------------------------------------------------------- */
+
+
+void MeshIO::printself(std::ostream & stream, int indent) const{
+
+  std::string space;
+  for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
+
+  if (phys_name_map.size()){
+
+    stream << space << "Physical map:" << std::endl;
+    
+    std::map<UInt, std::string>::const_iterator it = phys_name_map.begin();
+    std::map<UInt, std::string>::const_iterator end = phys_name_map.end();
+
+    
+    for (; it!=end; ++it) {
+      stream << space << it->first << ": " << it->second << std::endl;
+    }
+  }
+
+}
+
+/* -------------------------------------------------------------------------- */
+
+
 __END_AKANTU__
diff --git a/src/io/mesh_io.hh b/src/io/mesh_io.hh
index 3cc8c32f7..d7916f62d 100644
--- a/src/io/mesh_io.hh
+++ b/src/io/mesh_io.hh
@@ -1,102 +1,125 @@
 /**
  * @file   mesh_io.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Fri Jun 13 2014
  *
  * @brief  interface of a mesh io class, reader and writer
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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_MESH_IO_HH__
 #define __AKANTU_MESH_IO_HH__
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "mesh.hh"
 
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 class MeshIO {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   MeshIO();
 
   virtual ~MeshIO();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   void read(const std::string & filename, Mesh & mesh, const MeshIOType & type);
   void write(const std::string & filename, Mesh & mesh, const MeshIOType & type);
 
   /// read a mesh from the file
   virtual void read(__attribute__((unused)) const std::string & filename,
 		    __attribute__((unused))  Mesh & mesh) {
   }
 
   /// write a mesh to a file
   virtual void write(__attribute__((unused)) const std::string & filename,
 		     __attribute__((unused)) const Mesh & mesh) {}
 
-private:
-  MeshIO * getMeshIO(const std::string & filename, const MeshIOType & type);
 
+  /// function to request the manual construction of the physical names maps
+  virtual void constructPhysicalNames(const std::string & tag_name,
+				      Mesh & mesh);
+
+
+  /// method to permit to be printed to a generic stream
+  virtual void printself(std::ostream & stream, int indent = 0) const;
+
+  /// static contruction of a meshio object
+  static MeshIO * getMeshIO(const std::string & filename, const MeshIOType & type);
+  
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
+  std::map<UInt, std::string> & getPhysicalNameMap(){
+    return phys_name_map;
+  }
+  
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   bool canReadSurface;
 
   bool canReadExtendedData;
 
-  //  std::string filename;
+  /// correspondance between a tag and physical names (if applicable)
+  std::map<UInt, std::string> phys_name_map;
 
-  //  Mesh & mesh;
 };
 
+/* -------------------------------------------------------------------------- */
+
+inline std::ostream & operator <<(std::ostream & stream, const MeshIO &_this) {
+  _this.printself(stream);
+  return stream;
+}
+
+/* -------------------------------------------------------------------------- */
+
+
+
 __END_AKANTU__
 
 #include "mesh_io_msh.hh"
 #include "mesh_io_diana.hh"
 #include "mesh_io_abaqus.hh"
 
 #if defined(AKANTU_STRUCTURAL_MECHANICS)
 #  include "mesh_io_msh_struct.hh"
 #endif
 
 #endif /* __AKANTU_MESH_IO_HH__ */
-
diff --git a/src/io/mesh_io/mesh_io_diana.cc b/src/io/mesh_io/mesh_io_diana.cc
index 4030c42b4..ae4fe08b0 100644
--- a/src/io/mesh_io/mesh_io_diana.cc
+++ b/src/io/mesh_io/mesh_io_diana.cc
@@ -1,529 +1,743 @@
 /**
  * @file   mesh_io_diana.cc
  *
  * @author David Simon Kammer <david.kammer@epfl.ch>
  * @author Alodie Schneuwly <alodie.schneuwly@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Sat Mar 26 2011
  * @date last modification: Thu Mar 27 2014
  *
  * @brief  handles diana meshes
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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 "mesh_io_diana.hh"
-
+#include "mesh_utils.hh"
+#include "element_group.hh"
 /* -------------------------------------------------------------------------- */
 #include <string.h>
 /* -------------------------------------------------------------------------- */
 #include <stdio.h>
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /*   Methods Implentations                                                    */
 /* -------------------------------------------------------------------------- */
 
 MeshIODiana::MeshIODiana() {
   canReadSurface      = true;
   canReadExtendedData = true;
   _diana_to_akantu_element_types["T9TM"] = _triangle_3;
+  _diana_to_akantu_element_types["CT6CM"] = _triangle_6;
   _diana_to_akantu_element_types["Q12TM"] = _quadrangle_4;
+  _diana_to_akantu_element_types["CQ8CM"] = _quadrangle_8;
   _diana_to_akantu_element_types["TP18L"] = _pentahedron_6;
+  _diana_to_akantu_element_types["CTP45"] = _pentahedron_15;
   _diana_to_akantu_element_types["TE12L"] = _tetrahedron_4;
   _diana_to_akantu_element_types["HX24L"] = _hexahedron_8;
+  _diana_to_akantu_element_types["CHX60"] = _hexahedron_20;
   _diana_to_akantu_mat_prop["YOUNG"] = "E";
   _diana_to_akantu_mat_prop["DENSIT"] = "rho";
   _diana_to_akantu_mat_prop["POISON"] = "nu";
 }
 
 /* -------------------------------------------------------------------------- */
 MeshIODiana::~MeshIODiana() {
   std::map<std::string, Array<UInt> *>::iterator ng_it;
   std::map<std::string, std::vector<Element> *>::iterator eg_it;
 
   for (ng_it = node_groups.begin(); ng_it != node_groups.end(); ++ng_it) {
     delete ng_it->second;
   }
 
   for (eg_it = element_groups.begin(); eg_it != element_groups.end(); ++eg_it) {
     delete eg_it->second;
   }
 
 }
 
 /* -------------------------------------------------------------------------- */
 inline void my_getline(std::ifstream & infile, std::string & line) {
   std::getline(infile, line); //read the line
   size_t pos = line.find("\r"); /// remove the extra \r if needed
   line = line.substr(0, pos);
 }
 
 
 /* -------------------------------------------------------------------------- */
 void MeshIODiana::read(const std::string & filename, Mesh & mesh) {
   AKANTU_DEBUG_IN();
 
   std::ifstream infile;
   infile.open(filename.c_str());
 
   std::string line;
   UInt first_node_number = std::numeric_limits<UInt>::max();
-  std::vector<Element> global_to_local_index;
+  diana_element_number_to_elements.clear();
 
   if(!infile.good()) {
     AKANTU_DEBUG_ERROR("Cannot open file " << filename);
   }
 
   while(infile.good()) {
     my_getline(infile, line);
 
     /// read all nodes
     if(line == "'COORDINATES'") {
       line = readCoordinates(infile, mesh, first_node_number);
     }
 
     /// read all elements
     if (line == "'ELEMENTS'") {
-      line = readElements(infile, mesh, global_to_local_index, first_node_number);
+      line = readElements(infile, mesh, first_node_number);
     }
 
     /// read the material properties and write a .dat file
     if (line == "'MATERIALS'") {
       line = readMaterial(infile, filename);
     }
 
     /// read the material properties and write a .dat file
     if (line == "'GROUPS'") {
-      line = readGroups(infile, global_to_local_index, first_node_number);
+      line = readGroups(infile, first_node_number);
     }
 
   }
   infile.close();
 
   mesh.nb_global_nodes = mesh.nodes->getSize();
 
-  mesh.registerEventHandler(*this);
+  createGroupsInMesh(mesh);
+  
+  MeshUtils::fillElementToSubElementsData(mesh);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshIODiana::write(__attribute__((unused)) const std::string & filename,
 			__attribute__((unused)) const Mesh & mesh) {
   AKANTU_DEBUG_TO_IMPLEMENT();
 }
 
 /* -------------------------------------------------------------------------- */
 std::string MeshIODiana::readCoordinates(std::ifstream & infile, Mesh & mesh, UInt & first_node_number) {
   AKANTU_DEBUG_IN();
 
   Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes());
 
   std::string line;
 
   UInt index;
   Real coord[3];
 
   do {
     my_getline(infile, line);
     if("'ELEMENTS'" == line)
       break;
     //end = true;
     //else {
     /// for each node, read the coordinates
 
     std::stringstream sstr_node(line);
 
     sstr_node >> index >> coord[0] >> coord[1] >> coord[2];
 
     //if (!sstr_node.fail())
     //break;
 
     first_node_number = first_node_number < index ? first_node_number : index;
 
     nodes.push_back(coord);
     // }
   } while(true);//!end);
 
   AKANTU_DEBUG_OUT();
   return line;
 }
 
 /* -------------------------------------------------------------------------- */
 UInt MeshIODiana::readInterval(std::stringstream & line,
 			       std::set<UInt> & interval) {
+
+  int space;
+  space = line.get();
+  while (space == ' '){
+    space = line.get();
+    if(line.fail()) {
+      line.clear(std::ios::eofbit);
+      return 0;
+    }
+  }
+  if(!line.fail()) line.unget();
+  else {
+    line.clear(std::ios::eofbit);
+    return 0;
+  }
+  
   UInt first;
   line >> first;
   if(line.fail()) { return 0; }
   interval.insert(first);
 
+  //  std::cerr << "first: " << first << std::endl;
+  
   UInt second;
   int dash;
   dash = line.get();
   if(dash == '-') {
     line >> second;
     interval.insert(second);
+
+    //    std::cerr << "second: " << second << std::endl;
+    
+    int bracket;
+    UInt unknown_stuff;
+    bracket = line.get();
+    if(bracket == '('){
+      line >> unknown_stuff;
+      bracket = line.get();
+    }
+    else{
+      if(line.fail()) line.clear(std::ios::eofbit);
+      else line.unget();
+    }
     return 2;
   }
 
   if(line.fail())
     line.clear(std::ios::eofbit);  // in case of get at end of the line
   else line.unget();
   return 1;
 }
 
 /* -------------------------------------------------------------------------- */
 std::string MeshIODiana::readGroups(std::ifstream & infile,
-				      std::vector<Element> & global_to_local_index,
-				      UInt first_node_number) {
+				    UInt first_node_number) {
   AKANTU_DEBUG_IN();
 
   std::string line;
   my_getline(infile, line);
 
   bool reading_nodes_group = false;
 
   while(line != "'SUPPORTS'") {
     if(line == "NODES") {
       reading_nodes_group   = true;
       my_getline(infile, line);
     }
 
     if(line == "ELEMEN") {
       reading_nodes_group   = false;
       my_getline(infile, line);
     }
 
+    //    std::cerr << line << std::endl;
     std::stringstream *str = new std::stringstream(line);
 
     UInt id;
     std::string name;
     char c;
     *str >> id >> name >> c;
 
+    //    std::cerr << "AAAA " << id << " " << name << " " << c << std::endl;
+    
     Array<UInt> * list_ids = new Array<UInt>(0, 1, name);
 
     UInt s = 1; bool end = false;
     while(!end) {
       while(!str->eof() && s != 0) {
 	std::set<UInt> interval;
 	s = readInterval(*str, interval);
 	std::set<UInt>::iterator it = interval.begin();
 	if(s == 1) list_ids->push_back(*it);
 	if(s == 2) {
 	  UInt first = *it;
 	  ++it;
 	  UInt second = *it;
 	  for(UInt i = first; i <= second; ++i) {
 	    list_ids->push_back(i);
 	  }
 	}
       }
       if(str->fail()) end = true;
       else {
 	my_getline(infile, line);
 	delete str;
 	str = new std::stringstream(line);
+	s = 1;
       }
     }
 
     delete str;
 
     if(reading_nodes_group) {
+
+      // reading a node group
+
       for (UInt i = 0; i < list_ids->getSize(); ++i) {
 	(*list_ids)(i) -= first_node_number;
       }
       node_groups[name] = list_ids;
     } else {
+      
+      // reading an element group
+
       std::vector<Element> * elem = new std::vector<Element>;
       elem->reserve(list_ids->getSize());
       for (UInt i = 0; i < list_ids->getSize(); ++i) {
-	Element & e = global_to_local_index[(*list_ids)(i)-1];
+	Element & e = diana_element_number_to_elements[(*list_ids)(i)];
 	if(e.type != _not_defined)
 	  elem->push_back(e);
       }
 
       element_groups[name] = elem;
       delete list_ids;
     }
 
     my_getline(infile, line);
   }
 
   AKANTU_DEBUG_OUT();
   return line;
 }
 
 /* -------------------------------------------------------------------------- */
 std::string MeshIODiana::readElements(std::ifstream & infile,
 				      Mesh & mesh,
-				      std::vector<Element> & global_to_local_index,
 				      UInt first_node_number) {
   AKANTU_DEBUG_IN();
 
   std::string line;
   my_getline(infile, line);
 
   if("CONNECTIVITY" == line) {
-    line = readConnectivity(infile, mesh, global_to_local_index, first_node_number);
+    line = readConnectivity(infile, mesh, first_node_number);
   }
 
   /// read the line corresponding to the materials
   if ("MATERIALS" == line) {
-    line = readMaterialElement(infile, mesh, global_to_local_index);
+    line = readMaterialElement(infile, mesh);
   }
 
   AKANTU_DEBUG_OUT();
   return line;
 }
 
 
 /* -------------------------------------------------------------------------- */
 std::string MeshIODiana::readConnectivity(std::ifstream & infile,
 					  Mesh & mesh,
-					  std::vector<Element> & global_to_local_index,
 					  UInt first_node_number) {
   AKANTU_DEBUG_IN();
 
   Int index;
   std::string lline;
 
   std::string diana_type;
   ElementType akantu_type, akantu_type_old = _not_defined;
   Array<UInt> *connectivity = NULL;
   UInt node_per_element = 0;
   Element elem;
 
-  bool end = false;
-  do {
+  while (1) {
     my_getline(infile, lline);
+    //    std::cerr << lline << std::endl;
     std::stringstream sstr_elem(lline);
-    if(lline == "MATERIALS") end = true;
-    else {
-      /// traiter les coordonnees
-      sstr_elem >> index;
-      sstr_elem >> diana_type;
-
-      akantu_type = _diana_to_akantu_element_types[diana_type];
-
-      if(akantu_type != _not_defined) {
-	if(akantu_type != akantu_type_old) {
-	  connectivity = mesh.getConnectivityPointer(akantu_type);
-
-	  node_per_element = connectivity->getNbComponent();
-	  akantu_type_old = akantu_type;
-	}
-
-	UInt local_connect[node_per_element];
-	for(UInt j = 0; j < node_per_element; ++j) {
-	  UInt node_index;
-	  sstr_elem >> node_index;
-
-	  node_index -= first_node_number;
-	  local_connect[j] = node_index;
-	}
-	connectivity->push_back(local_connect);
+    if(lline == "MATERIALS") break;
+
+    /// traiter les coordonnees
+    sstr_elem >> index;
+    sstr_elem >> diana_type;
+    
+    akantu_type = _diana_to_akantu_element_types[diana_type];
+   
+    if(akantu_type == _not_defined) continue;
+
+    if(akantu_type != akantu_type_old) {
+      connectivity = mesh.getConnectivityPointer(akantu_type);
+      
+      node_per_element = connectivity->getNbComponent();
+      akantu_type_old = akantu_type;
+    }
+    
+    UInt local_connect[node_per_element];
+    
+    //used if element is written on two lines
+    UInt j_last;
+    
+    for(UInt j = 0; j < node_per_element; ++j) {
+      UInt node_index;
+      sstr_elem >> node_index;
+      
+      // check s'il y a pas plus rien après un certain point
+      
+      if (sstr_elem.fail()) {
+	sstr_elem.clear();
+	sstr_elem.ignore();
+	break;
+      }
+      
+      node_index -= first_node_number;
+      local_connect[j] = node_index;
+      j_last = j;
+    }
 
-	elem.type = akantu_type;
-	elem.element = connectivity->getSize() - 1;
-      } else {
-	elem.type = _not_defined;
-	elem.element = UInt(-1);
+    // check if element is written in two lines
+    
+    if(j_last != (node_per_element-1)){
+      
+      //if this is the case, read on more line
+      
+      my_getline(infile, lline);
+      std::stringstream sstr_elem(lline);
+      
+      for(UInt j = (j_last+1); j < node_per_element; ++j) {
+	
+	UInt node_index;
+	sstr_elem >> node_index;
+	
+	node_index -= first_node_number;
+	local_connect[j] = node_index;
       }
+    }
+    
+    // Exceptions
+    UInt local_connect_non_modified[node_per_element];
+    
+    // Create a new unmodified vector
+    for(UInt k = 0; k < node_per_element; ++k) {
+      local_connect_non_modified[k] = local_connect[k];
+    }
+    
+    switch(akantu_type){
+      
+    case _pentahedron_15:
+      local_connect[0] = local_connect_non_modified[2];
+      local_connect[1] = local_connect_non_modified[4];
+      local_connect[2] = local_connect_non_modified[0];
+      local_connect[3] = local_connect_non_modified[11];
+      local_connect[4] = local_connect_non_modified[13];
+      local_connect[5] = local_connect_non_modified[9];
+      local_connect[6] = local_connect_non_modified[3];
+      local_connect[7] = local_connect_non_modified[5];
+      local_connect[8] = local_connect_non_modified[1];
+      local_connect[9] = local_connect_non_modified[7];
+      local_connect[10] =local_connect_non_modified[8];
+      local_connect[11] =local_connect_non_modified[6];
+      local_connect[12] =local_connect_non_modified[12];
+      local_connect[13] =local_connect_non_modified[14];
+      local_connect[14] =local_connect_non_modified[10];
+      break;
+      
+    case _hexahedron_20:
+      local_connect[0] = local_connect_non_modified[14];
+      local_connect[8] = local_connect_non_modified[13];
+      local_connect[1] = local_connect_non_modified[12];
+      local_connect[9] = local_connect_non_modified[19];
+      local_connect[2] = local_connect_non_modified[18];
+      local_connect[10] = local_connect_non_modified[17];
+      local_connect[3] = local_connect_non_modified[16];
+      local_connect[11] = local_connect_non_modified[15];
+      local_connect[12] = local_connect_non_modified[9];
+      local_connect[13] = local_connect_non_modified[8];
+      local_connect[14] = local_connect_non_modified[11];
+      local_connect[15] = local_connect_non_modified[10];
+      local_connect[4] = local_connect_non_modified[2];
+      local_connect[16] = local_connect_non_modified[1];
+      local_connect[5] = local_connect_non_modified[0];
+      local_connect[17] = local_connect_non_modified[7];
+      local_connect[6] = local_connect_non_modified[6];
+      local_connect[18] = local_connect_non_modified[5];
+      local_connect[7] = local_connect_non_modified[4];
+      local_connect[19] = local_connect_non_modified[3];
+      break;
 
-      global_to_local_index.push_back(elem);
+    default:
+      //nothing to change
+      break;
     }
+      
+    connectivity->push_back(local_connect);
+    
+    elem.type = akantu_type;
+    elem.element = connectivity->getSize() - 1;
+
+    diana_element_number_to_elements[index] = elem;
+    akantu_number_to_diana_number[elem] = index;
   }
-  while(!end);
 
   AKANTU_DEBUG_OUT();
   return lline;
 }
 
 /* -------------------------------------------------------------------------- */
 std::string MeshIODiana::readMaterialElement(std::ifstream & infile,
-					     Mesh & mesh,
-					     std::vector<Element> & global_to_local_index) {
+					     Mesh & mesh) {
   AKANTU_DEBUG_IN();
 
 
   std::string line;
   std::stringstream sstr_tag_name; sstr_tag_name << "tag_" << 0;
 
   Mesh::type_iterator it  = mesh.firstType();
   Mesh::type_iterator end = mesh.lastType();
   for(; it != end; ++it) {
     UInt nb_element = mesh.getNbElement(*it);
     mesh.getDataPointer<UInt>("material", *it, _not_ghost, 1)->resize(nb_element);
   }
 
   my_getline(infile, line);
   while(line != "'MATERIALS'") {
     line = line.substr(line.find('/') + 1, std::string::npos); // erase the first slash / of the line
     char tutu[250];
     strcpy(tutu, line.c_str());
+
+    //    AKANTU_DEBUG_WARNING("reading line " << line);
     Array<UInt> temp_id(0, 2);
     UInt mat;
     while(true){
       std::stringstream sstr_intervals_elements(line);
       UInt id[2];
       char temp;
       while(sstr_intervals_elements.good()) {
 	sstr_intervals_elements >> id[0] >> temp >> id[1]; // >> "/" >> mat;
 	if(!sstr_intervals_elements.fail())
 	  temp_id.push_back(id);
       }
       if (sstr_intervals_elements.fail()) {
 	sstr_intervals_elements.clear();
 	sstr_intervals_elements.ignore();
 	sstr_intervals_elements >> mat;
 	break;
       }
       my_getline(infile, line);
     }
 
     // loop over elements
     //    UInt * temp_id_val = temp_id.storage();
     for (UInt i = 0; i < temp_id.getSize(); ++i)
       for (UInt j = temp_id(i, 0); j <= temp_id(i, 1); ++j) {
-	Element & element = global_to_local_index[j - 1];
+	Element & element = diana_element_number_to_elements[j];
 	if(element.type == _not_defined) continue;
 	UInt elem = element.element;
 	ElementType type = element.type;
 	Array<UInt> & data = *(mesh.getDataPointer<UInt>("material", type, _not_ghost));
 	data(elem) = mat;
       }
 
     my_getline(infile, line);
   }
 
   AKANTU_DEBUG_OUT();
   return line;
 }
 
 /* -------------------------------------------------------------------------- */
 std::string MeshIODiana::readMaterial(std::ifstream & infile,
 				      const std::string & filename) {
   AKANTU_DEBUG_IN();
 
   std::stringstream mat_file_name;
 
   mat_file_name << "material_" << filename;
 
   std::ofstream material_file;
   material_file.open(mat_file_name.str().c_str());//mat_file_name.str());
 
   UInt mat_index;
   std::string line;
 
   bool first_mat = true;
   bool end = false;
 
   UInt mat_id = 0;
 
   typedef std::map<std::string, Real> MatProp;
   MatProp mat_prop;
   do{
     my_getline(infile, line);
     std::stringstream sstr_material(line);
-    if("'GROUPS'" == line) {
+    if(("'GROUPS'" == line) || ( "'END'" == line)) {
       if(!mat_prop.empty()) {
 	material_file << "material elastic [" << std::endl;
 	material_file << "\tname = material" << ++mat_id << std::endl;
 	for(MatProp::iterator it = mat_prop.begin();
 	    it != mat_prop.end(); ++it)
 	  material_file << "\t" << it->first << " = " << it->second << std::endl;
 	material_file << "]" << std::endl;
 	mat_prop.clear();
       }
       end = true;
     }
     else {
       /// traiter les caractéristiques des matériaux
       sstr_material >> mat_index;
 
       if(!sstr_material.fail()) {
 	if(!first_mat) {
 	  if(!mat_prop.empty()) {
 	    material_file << "material elastic [" << std::endl;
 	    material_file << "\tname = material" << ++mat_id << std::endl;
 	    for(MatProp::iterator it = mat_prop.begin();
 		it != mat_prop.end(); ++it)
 	      material_file << "\t" << it->first << " = " << it->second << std::endl;
 	    material_file << "]" << std::endl;
 	    mat_prop.clear();
 	  }
 	}
 	first_mat = false;
       } else {
 	sstr_material.clear();
       }
 
       std::string prop_name;
       sstr_material >> prop_name;
 
       std::map<std::string, std::string>::iterator it;
       it = _diana_to_akantu_mat_prop.find(prop_name);
 
       if(it != _diana_to_akantu_mat_prop.end()) {
 	Real value;
 	sstr_material >> value;
 	mat_prop[it->second] = value;
       } else {
 	AKANTU_DEBUG_INFO("In material reader, property " << prop_name << "not recognized");
       }
     }
   } while (!end);
 
   AKANTU_DEBUG_OUT();
   return line;
 }
 
+/* -------------------------------------------------------------------------- */
+
+void MeshIODiana::createGroupsInMesh(Mesh & mesh) {
+
+  /* ------------------------------------------------------------------------ */
+  // create the element groups
+  /* ------------------------------------------------------------------------ */
+  
+  {
+    std::map<std::string, std::vector<Element> *>::iterator git
+      = element_groups.begin();
+    std::map<std::string, std::vector<Element> *>::iterator gend
+      = element_groups.end();
+
+    for (;git != gend; ++git) {
+      std::string group_name = git->first;
+      std::vector<Element> & element_group = *git->second; 
+
+      if (element_group.size() == 0) continue;
+      Element & first_element = element_group[0];
+    
+      UInt group_dim = mesh.getSpatialDimension(first_element.type);
+      mesh.createElementGroup(group_name, group_dim);
+      ElementGroup & group = mesh.getElementGroup(git->first);
+
+      std::vector<Element>::iterator it = element_group.begin();
+      std::vector<Element>::iterator end = element_group.end();
+    
+      for(; it != end; ++it){
+	group.add(*it);
+      }
+  
+    }
+  }
+  
+  /* ------------------------------------------------------------------------ */
+  // create the node groups
+  /* ------------------------------------------------------------------------ */
+
+  {
+    std::map<std::string, Array<UInt> *>::iterator git
+      = node_groups.begin();
+    std::map<std::string, Array<UInt> *>::iterator gend
+      = node_groups.end();
+
+    for (;git != gend; ++git) {
+      std::string group_name = git->first;
+      Array<UInt> & node_group = *git->second; 
+
+      if (node_group.getSize() == 0) continue;
+      //      Element & first_element = element_group[0];
+    
+      UInt group_dim = 1;//mesh.getSpatialDimension(first_element.type);
+      mesh.createNodeGroup(group_name, group_dim);
+      NodeGroup & group = mesh.getNodeGroup(git->first);
+
+      Array<UInt>::iterator<UInt> it = node_group.begin();
+      Array<UInt>::iterator<UInt> end = node_group.end();
+    
+      for(; it != end; ++it){
+	group.add(*it);
+      }
+  
+    }
+  }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+void MeshIODiana::printself(std::ostream & stream,int indent) const {
+
+  MeshIO::printself(stream,indent);
+  
+  std::string space;
+  for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
+  
+  if (node_groups.size()){
+    stream << space << "Read node groups: ";
+    std::map<std::string, Array<UInt> *>::const_iterator it = node_groups.begin();
+    std::map<std::string, Array<UInt> *>::const_iterator end = node_groups.end();
+
+    for (;it != end; ++it) {
+      stream << "'" << it->first << "' ";
+    }
+    stream << std::endl;
+  }
+
+  if (element_groups.size()){
+    stream << space << "Read element groups: ";
+    std::map<std::string, std::vector<Element> *>::const_iterator it = element_groups.begin();
+    std::map<std::string, std::vector<Element> *>::const_iterator end = element_groups.end();
 
-void MeshIODiana::onNodesRemoved(const Array<UInt> & element_list,
-				 const Array<UInt> & new_numbering,
-				 const RemovedNodesEvent & event) {
-  std::map<std::string, Array<UInt> *>::iterator it = node_groups.begin();
-  std::map<std::string, Array<UInt> *>::iterator end = node_groups.end();
-  for (; it != end; ++it) {
-    Array<UInt> & group = *(it->second);
-    Array<UInt>::iterator<> git = group.begin();
-    Array<UInt>::iterator<> gend = group.end();
-    for (; git != gend; ++git) {
-      UInt new_id = new_numbering(*git);
-      AKANTU_DEBUG_ASSERT(new_id != UInt(-1), "Argh " << *git << " was suppressed!");
-      *git = new_id;
+    for (;it != end; ++it) {
+      stream << "'" << it->first << "' ";
     }
+    stream << std::endl;
   }
 }
 
 
 __END_AKANTU__
diff --git a/src/io/mesh_io/mesh_io_diana.hh b/src/io/mesh_io/mesh_io_diana.hh
index 0c827ccb3..bc349764f 100644
--- a/src/io/mesh_io/mesh_io_diana.hh
+++ b/src/io/mesh_io/mesh_io_diana.hh
@@ -1,154 +1,150 @@
 /**
  * @file   mesh_io_diana.hh
  *
  * @author David Simon Kammer <david.kammer@epfl.ch>
  * @author Alodie Schneuwly <alodie.schneuwly@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Sat Mar 26 2011
  * @date last modification: Mon Aug 19 2013
  *
  * @brief  diana mesh reader description
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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_MESH_IO_DIANA_HH__
 #define __AKANTU_MESH_IO_DIANA_HH__
 
 /* -------------------------------------------------------------------------- */
 #include "mesh_io.hh"
 
 /* -------------------------------------------------------------------------- */
 #include <vector>
 
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
-class MeshIODiana : public MeshIO, public MeshEventHandler {
+class MeshIODiana : public MeshIO {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   MeshIODiana();
   virtual ~MeshIODiana();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// read a mesh from the file
   virtual void read(const std::string & filename, Mesh&mesh);
 
   /// write a mesh to a file
   virtual void write(const std::string & filename, const Mesh & mesh);
 
 private:
   std::string readCoordinates(std::ifstream & infile,
 			      Mesh & mesh,
 			      UInt & first_node_number);
 
   std::string readElements(std::ifstream & infile,
 			   Mesh & mesh,
-			   std::vector<Element> & global_to_local_index,
 			   UInt first_node_number);
 
   std::string readGroups(std::ifstream & infile,
-			 std::vector<Element> & global_to_local_index,
 			 UInt first_node_number);
 
   std::string readConnectivity(std::ifstream & infile,
 			       Mesh & mesh,
-			       std::vector<Element> & global_to_local_index,
 			       UInt first_node_number);
 
   std::string readMaterialElement(std::ifstream & infile,
-				  Mesh & mesh,
-				  std::vector<Element> & global_to_local_index);
+				  Mesh & mesh);
 
   std::string readMaterial(std::ifstream & infile,
 			   const std::string & filename);
 
   UInt readInterval(std::stringstream & line,
 		    std::set<UInt> & interval);
 
+  void createGroupsInMesh(Mesh & mesh);
+
+  virtual void printself(std::ostream & stream, int indent = 0) const;
+
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   const Array<UInt> & getNodeGroup(const std::string & group_name) const {
     std::map<std::string, Array<UInt> *>::const_iterator it = node_groups.find(group_name);
     AKANTU_DEBUG_ASSERT(it != node_groups.end(), "There is no nodes group named : " << group_name);
     return *it->second;
   }
 
   const std::vector<Element> & getElementGroup(const std::string & group_name) const {
     std::map<std::string, std::vector<Element> *>::const_iterator it = element_groups.find(group_name);
     AKANTU_DEBUG_ASSERT(it != element_groups.end(), "There is no elements group named : " << group_name);
     return *it->second;
   }
 
   std::vector<std::string> getNodeGroupsNames() const {
     std::vector<std::string> names;
     std::map<std::string, Array<UInt> *>::const_iterator it;
     for(it = node_groups.begin(); it != node_groups.end(); ++it)
       names.push_back(it->first);
 
     return names;
   }
 
   std::vector<std::string> getElementGroupsNames() const {
     std::vector<std::string> names;
     std::map<std::string, std::vector<Element> *>::const_iterator it;
     for(it = element_groups.begin(); it != element_groups.end(); ++it)
       names.push_back(it->first);
 
     return names;
   }
 
-  /* ------------------------------------------------------------------------ */
-  /* Mesh Event Handler inherited members                                     */
-  /* ------------------------------------------------------------------------ */
-protected:
-  virtual void onNodesRemoved(const Array<UInt> & element_list,
-                              const Array<UInt> & new_numbering,
-                              const RemovedNodesEvent & event);
-
+ 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   std::map<std::string, ElementType> _diana_to_akantu_element_types;
 
   std::map<std::string, std::string> _diana_to_akantu_mat_prop;
 
 
   std::map<std::string, Array<UInt> *> node_groups;
   std::map<std::string, std::vector<Element> *> element_groups;
+
+  std::map<UInt,Element> diana_element_number_to_elements;
+  std::map<Element,UInt> akantu_number_to_diana_number;
 };
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MESH_IO_DIANA_HH__ */
diff --git a/src/io/mesh_io/mesh_io_msh.cc b/src/io/mesh_io/mesh_io_msh.cc
index adb970b39..071407a96 100644
--- a/src/io/mesh_io/mesh_io_msh.cc
+++ b/src/io/mesh_io/mesh_io_msh.cc
@@ -1,572 +1,555 @@
 /**
  * @file   mesh_io_msh.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Fri Jul 04 2014
  *
  * @brief  Read/Write for MSH files generated by gmsh
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 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/>.
  *
  */
 
 /* -----------------------------------------------------------------------------
    Version (Legacy) 1.0
 
    $NOD
    number-of-nodes
    node-number x-coord y-coord z-coord
    ...
    $ENDNOD
    $ELM
    number-of-elements
    elm-number elm-type reg-phys reg-elem number-of-nodes node-number-list
    ...
    $ENDELM
    -----------------------------------------------------------------------------
    Version 2.1
 
    $MeshFormat
    version-number file-type data-size
    $EndMeshFormat
    $Nodes
    number-of-nodes
    node-number x-coord y-coord z-coord
    ...
    $EndNodes
    $Elements
    number-of-elements
    elm-number elm-type number-of-tags < tag > ... node-number-list
    ...
    $EndElements
    $PhysicalNames
    number-of-names
    physical-dimension physical-number "physical-name"
    ...
    $EndPhysicalNames
    $NodeData
    number-of-string-tags
    < "string-tag" >
    ...
    number-of-real-tags
    < real-tag >
    ...
    number-of-integer-tags
    < integer-tag >
    ...
    node-number value ...
    ...
    $EndNodeData
    $ElementData
    number-of-string-tags
    < "string-tag" >
    ...
    number-of-real-tags
    < real-tag >
    ...
    number-of-integer-tags
    < integer-tag >
    ...
    elm-number value ...
    ...
    $EndElementData
    $ElementNodeData
    number-of-string-tags
    < "string-tag" >
    ...
    number-of-real-tags
    < real-tag >
    ...
    number-of-integer-tags
    < integer-tag >
    ...
    elm-number number-of-nodes-per-element value ...
    ...
    $ElementEndNodeData
 
    -----------------------------------------------------------------------------
    elem-type
 
    1:  2-node line.
    2:  3-node triangle.
    3:  4-node quadrangle.
    4:  4-node tetrahedron.
    5:  8-node hexahedron.
    6:  6-node prism.
    7:  5-node pyramid.
    8:  3-node second order line
    9:  6-node second order triangle
    10: 9-node second order quadrangle
    11: 10-node second order tetrahedron
    12: 27-node second order hexahedron
    13: 18-node second order prism
    14: 14-node second order pyramid
    15: 1-node point.
    16: 8-node second order quadrangle
    17: 20-node second order hexahedron
    18: 15-node second order prism
    19: 13-node second order pyramid
    20: 9-node third order incomplete triangle
    21: 10-node third order triangle
    22: 12-node fourth order incomplete triangle
    23: 15-node fourth order triangle
    24: 15-node fifth order incomplete triangle
    25: 21-node fifth order complete triangle
    26: 4-node third order edge
    27: 5-node fourth order edge
    28: 6-node fifth order edge
    29: 20-node third order tetrahedron
    30: 35-node fourth order tetrahedron
    31: 56-node fifth order tetrahedron
    -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 #include <fstream>
 
 /* -------------------------------------------------------------------------- */
 #include "mesh_io.hh"
 #include "mesh_utils.hh"
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /*   Methods Implentations                                                    */
 /* -------------------------------------------------------------------------- */
 
 MeshIOMSH::MeshIOMSH() {
   canReadSurface      = true;
   canReadExtendedData = true;
 
   _msh_nodes_per_elem[_msh_not_defined   ] = 0;
   _msh_nodes_per_elem[_msh_segment_2     ] = 2;
   _msh_nodes_per_elem[_msh_triangle_3    ] = 3;
   _msh_nodes_per_elem[_msh_quadrangle_4  ] = 4;
   _msh_nodes_per_elem[_msh_tetrahedron_4 ] = 4;
   _msh_nodes_per_elem[_msh_hexahedron_8  ] = 8;
   _msh_nodes_per_elem[_msh_prism_1       ] = 6;
   _msh_nodes_per_elem[_msh_pyramid_1     ] = 1;
   _msh_nodes_per_elem[_msh_segment_3     ] = 3;
   _msh_nodes_per_elem[_msh_triangle_6    ] = 6;
   _msh_nodes_per_elem[_msh_quadrangle_9  ] = 9;
   _msh_nodes_per_elem[_msh_tetrahedron_10] = 10;
   _msh_nodes_per_elem[_msh_hexahedron_27 ] = 27;
   _msh_nodes_per_elem[_msh_hexahedron_20 ] = 20;
   _msh_nodes_per_elem[_msh_prism_18      ] = 18;
   _msh_nodes_per_elem[_msh_prism_15      ] = 15;
   _msh_nodes_per_elem[_msh_pyramid_14    ] = 14;
   _msh_nodes_per_elem[_msh_point         ] = 1;
   _msh_nodes_per_elem[_msh_quadrangle_8  ] = 8;
 
   _msh_to_akantu_element_types[_msh_not_defined   ] = _not_defined;
   _msh_to_akantu_element_types[_msh_segment_2     ] = _segment_2;
   _msh_to_akantu_element_types[_msh_triangle_3    ] = _triangle_3;
   _msh_to_akantu_element_types[_msh_quadrangle_4  ] = _quadrangle_4;
   _msh_to_akantu_element_types[_msh_tetrahedron_4 ] = _tetrahedron_4;
   _msh_to_akantu_element_types[_msh_hexahedron_8  ] = _hexahedron_8;
   _msh_to_akantu_element_types[_msh_prism_1       ] = _pentahedron_6;
   _msh_to_akantu_element_types[_msh_pyramid_1     ] = _not_defined;
   _msh_to_akantu_element_types[_msh_segment_3     ] = _segment_3;
   _msh_to_akantu_element_types[_msh_triangle_6    ] = _triangle_6;
   _msh_to_akantu_element_types[_msh_quadrangle_9  ] = _not_defined;
   _msh_to_akantu_element_types[_msh_tetrahedron_10] = _tetrahedron_10;
   _msh_to_akantu_element_types[_msh_hexahedron_27 ] = _not_defined;
   _msh_to_akantu_element_types[_msh_prism_18      ] = _not_defined;
   _msh_to_akantu_element_types[_msh_hexahedron_20 ] = _hexahedron_20;
   _msh_to_akantu_element_types[_msh_prism_15      ] = _pentahedron_15;
   _msh_to_akantu_element_types[_msh_pyramid_14    ] = _not_defined;
   _msh_to_akantu_element_types[_msh_point         ] = _point_1;
   _msh_to_akantu_element_types[_msh_quadrangle_8  ] = _quadrangle_8;
 
   _akantu_to_msh_element_types[_not_defined     ] = _msh_not_defined;
   _akantu_to_msh_element_types[_segment_2       ] = _msh_segment_2;
   _akantu_to_msh_element_types[_segment_3       ] = _msh_segment_3;
   _akantu_to_msh_element_types[_triangle_3      ] = _msh_triangle_3;
   _akantu_to_msh_element_types[_triangle_6      ] = _msh_triangle_6;
   _akantu_to_msh_element_types[_tetrahedron_4   ] = _msh_tetrahedron_4;
   _akantu_to_msh_element_types[_tetrahedron_10  ] = _msh_tetrahedron_10;
   _akantu_to_msh_element_types[_quadrangle_4    ] = _msh_quadrangle_4;
   _akantu_to_msh_element_types[_quadrangle_8    ] = _msh_quadrangle_8;
   _akantu_to_msh_element_types[_hexahedron_8    ] = _msh_hexahedron_8;
   _akantu_to_msh_element_types[_hexahedron_20   ] = _msh_hexahedron_20;
   _akantu_to_msh_element_types[_pentahedron_6   ] = _msh_prism_1;
   _akantu_to_msh_element_types[_pentahedron_15  ] = _msh_prism_15;
   _akantu_to_msh_element_types[_point_1         ] = _msh_point;
 #if defined(AKANTU_STRUCTURAL_MECHANICS)
   _akantu_to_msh_element_types[_bernoulli_beam_2] = _msh_segment_2;
   _akantu_to_msh_element_types[_bernoulli_beam_3] = _msh_segment_2;
   _akantu_to_msh_element_types[_kirchhoff_shell] = _msh_triangle_3;
 #endif
 
   std::map<ElementType, MSHElementType>::iterator it;
   for(it = _akantu_to_msh_element_types.begin();
       it != _akantu_to_msh_element_types.end(); ++it) {
     UInt nb_nodes = _msh_nodes_per_elem[it->second];
 
     UInt * tmp = new UInt[nb_nodes];
     for (UInt i = 0; i < nb_nodes; ++i) {
       tmp[i] = i;
     }
 
     switch(it->first) {
     case _tetrahedron_10:
       tmp[8] = 9;
       tmp[9] = 8;
       break;
     case _pentahedron_15:
       tmp[ 0] =  2;
       tmp[ 1] =  0;
       tmp[ 2] =  1;
       tmp[ 3] =  5;
       tmp[ 4] =  3;
       tmp[ 5] =  4;
       tmp[ 6] =  8;
       tmp[ 8] = 11;
       tmp[ 9] =  6;
       tmp[10] =  9;
       tmp[11] = 10;
       tmp[12] = 14;
       tmp[14] = 12;
       break;
     case _hexahedron_20:
       tmp[ 9] = 11;
       tmp[10] = 12;
       tmp[11] =  9;
       tmp[12] = 13;
       tmp[13] = 10;
       tmp[17] = 19;
       tmp[18] = 17;
       tmp[19] = 18;
       break;
     default:
       //nothing to change
       break;
     }
     _read_order[it->first] = tmp;
   }
 }
 
 /* -------------------------------------------------------------------------- */
 MeshIOMSH::~MeshIOMSH() {
   std::map<ElementType, MSHElementType>::iterator it;
   for(it = _akantu_to_msh_element_types.begin();
       it != _akantu_to_msh_element_types.end(); ++it) {
     delete [] _read_order[it->first];
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshIOMSH::read(const std::string & filename, Mesh & mesh) {
 
   std::ifstream infile;
   infile.open(filename.c_str());
 
   std::string line;
   UInt first_node_number = std::numeric_limits<UInt>::max(), last_node_number = 0,
     file_format = 1, current_line = 0;
 
 
   if(!infile.good()) {
     AKANTU_DEBUG_ERROR("Cannot open file " << filename);
   }
 
   while(infile.good()) {
     std::getline(infile, line);
     current_line++;
 
     /// read the header
     if(line == "$MeshFormat") {
       std::getline(infile, line); /// the format line
       std::stringstream sstr(line);
       std::string version; sstr >> version;
       Int format; sstr >> format;
       if(format != 0) AKANTU_DEBUG_ERROR("This reader can only read ASCII files.");
       std::getline(infile, line); /// the end of block line
       current_line += 2;
       file_format = 2;
     }
 
     /// read the physical names
     if(line == "$PhysicalNames") {
       std::getline(infile, line); /// the format line
       std::stringstream sstr(line);
 
       UInt num_of_phys_names;
       sstr >> num_of_phys_names;
 
 
       for(UInt k(0); k < num_of_phys_names; k++) {
         std::getline(infile, line);
         std::stringstream sstr_phys_name(line);
         UInt phys_name_id;
         UInt phys_dim;
 
         sstr_phys_name >> phys_dim >> phys_name_id;
 
 	std::size_t b = line.find("\"");
 	std::size_t e = line.rfind("\"");
         std::string phys_name = line.substr(b + 1, e - b -1);
 
         phys_name_map[phys_name_id] = phys_name;
       }
     }
 
     /// read all nodes
     if(line == "$Nodes" || line == "$NOD") {
       UInt nb_nodes;
 
       std::getline(infile, line);
       std::stringstream sstr(line);
       sstr >> nb_nodes;
       current_line++;
 
       Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes());
       nodes.resize(nb_nodes);
       mesh.nb_global_nodes = nb_nodes;
 
 
       UInt index;
       Real coord[3];
       UInt spatial_dimension = nodes.getNbComponent();
       /// for each node, read the coordinates
       for(UInt i = 0; i < nb_nodes; ++i) {
         UInt offset = i * spatial_dimension;
 
         std::getline(infile, line);
         std::stringstream sstr_node(line);
         sstr_node >> index >> coord[0] >> coord[1] >> coord[2];
         current_line++;
 
         first_node_number = std::min(first_node_number,index);
         last_node_number  = std::max(last_node_number, index);
 
         /// read the coordinates
         for(UInt j = 0; j < spatial_dimension; ++j)
           nodes.storage()[offset + j] = coord[j];
       }
       std::getline(infile, line); /// the end of block line
     }
 
 
     /// read all elements
     if(line == "$Elements" || line == "$ELM") {
       UInt nb_elements;
 
       UInt * read_order = NULL;
 
       std::getline(infile, line);
       std::stringstream sstr(line);
       sstr >> nb_elements;
       current_line++;
 
       Int index;
       UInt msh_type;
       ElementType akantu_type, akantu_type_old = _not_defined;
       Array<UInt> *connectivity = NULL;
       UInt node_per_element = 0;
 
       for(UInt i = 0; i < nb_elements; ++i) {
         std::getline(infile, line);
         std::stringstream sstr_elem(line);
         current_line++;
 
         sstr_elem >> index;
         sstr_elem >> msh_type;
 
         /// get the connectivity vector depending on the element type
         akantu_type = _msh_to_akantu_element_types[(MSHElementType) msh_type];
 
         if(akantu_type == _not_defined) {
           AKANTU_DEBUG_WARNING("Unsuported element kind " << msh_type
                                << " at line " << current_line);
           continue;
         }
 
         if(akantu_type != akantu_type_old) {
           connectivity = mesh.getConnectivityPointer(akantu_type);
 //          connectivity->resize(0);
 
           node_per_element = connectivity->getNbComponent();
           akantu_type_old = akantu_type;
           read_order = _read_order[akantu_type];
         }
 
         /// read tags informations
         if(file_format == 2) {
           UInt nb_tags;
           sstr_elem >> nb_tags;
           for(UInt j = 0; j < nb_tags; ++j) {
             Int tag;
             sstr_elem >> tag;
             std::stringstream sstr_tag_name; sstr_tag_name << "tag_" << j;
             Array<UInt> * data = mesh.getDataPointer<UInt>(sstr_tag_name.str(), akantu_type, _not_ghost);
             data->push_back(tag);
           }
         } else if (file_format == 1) {
           Int tag;
           sstr_elem >> tag; //reg-phys
           std::string tag_name = "tag_0";
           Array<UInt> * data = mesh.getDataPointer<UInt>(tag_name, akantu_type, _not_ghost);
           data->push_back(tag);
 
           sstr_elem >> tag; //reg-elem
           tag_name = "tag_1";
           data = mesh.getDataPointer<UInt>(tag_name, akantu_type, _not_ghost);
           data->push_back(tag);
 
           sstr_elem >> tag; //number-of-nodes
         }
 
         UInt local_connect[node_per_element];
         for(UInt j = 0; j < node_per_element; ++j) {
           UInt node_index;
           sstr_elem >> node_index;
 
           AKANTU_DEBUG_ASSERT(node_index <= last_node_number,
                              "Node number not in range : line " << current_line);
 
           node_index -= first_node_number;
           local_connect[read_order[j]] = node_index;
         }
         connectivity->push_back(local_connect);
       }
       std::getline(infile, line); /// the end of block line
     }
 
     if((line[0] == '$') && (line.find("End") == std::string::npos)) {
       AKANTU_DEBUG_WARNING("Unsuported block_kind " << line
                           << " at line " << current_line);
     }
   }
 
   mesh.updateTypesOffsets(_not_ghost);
 
   infile.close();
 
-  if(!phys_name_map.empty()) {
-    for(Mesh::type_iterator type_it = mesh.firstType(); type_it != mesh.lastType(); ++type_it) {
-      Array<std::string> * name_vec = mesh.getDataPointer<std::string>("physical_names", *type_it);
-      const Array<UInt> & tags_vec = mesh.getData<UInt>("tag_0", *type_it);
-
-      for(UInt i(0); i < tags_vec.getSize(); i++) {
-        std::map<UInt, std::string>::const_iterator map_it = phys_name_map.find(tags_vec(i));
-
-        if(map_it == phys_name_map.end()) {
-          std::stringstream sstm;
-          sstm << tags_vec(i);
-          name_vec->operator()(i) = sstm.str();
-        } else {
-          name_vec->operator()(i) = map_it->second;
-        }
-      }
-    }
-  }
+  this->constructPhysicalNames("tag_0",mesh);
 
   MeshUtils::fillElementToSubElementsData(mesh);
 }
 
 /* -------------------------------------------------------------------------- */
 void MeshIOMSH::write(const std::string & filename, const Mesh & mesh) {
   std::ofstream outfile;
   const Array<Real> & nodes = mesh.getNodes();
 
   outfile.open(filename.c_str());
 
   outfile << "$MeshFormat" << std::endl;
   outfile << "2.1 0 8" << std::endl;;
   outfile << "$EndMeshFormat" << std::endl;;
 
 
   outfile << std::setprecision(std::numeric_limits<Real>::digits10);
   outfile << "$Nodes" << std::endl;;
   outfile << nodes.getSize() << std::endl;;
 
   outfile << std::uppercase;
   for(UInt i = 0; i < nodes.getSize(); ++i) {
     Int offset = i * nodes.getNbComponent();
     outfile << i+1;
     for(UInt j = 0; j < nodes.getNbComponent(); ++j) {
       outfile << " " << nodes.storage()[offset + j];
     }
 
     for (UInt p = nodes.getNbComponent(); p < 3; ++p)
       outfile << " " << 0.;
     outfile << std::endl;;
   }
   outfile << std::nouppercase;
   outfile << "$EndNodes" << std::endl;;
 
 
   outfile << "$Elements" << std::endl;;
 
   Mesh::type_iterator it  = mesh.firstType(_all_dimensions, _not_ghost, _ek_not_defined);
   Mesh::type_iterator end = mesh.lastType(_all_dimensions, _not_ghost, _ek_not_defined);
 
   Int nb_elements = 0;
   for(; it != end; ++it) {
     const Array<UInt> & connectivity = mesh.getConnectivity(*it, _not_ghost);
     nb_elements += connectivity.getSize();
   }
   outfile << nb_elements << std::endl;
 
   UInt element_idx = 1;
   for(it  = mesh.firstType(_all_dimensions, _not_ghost, _ek_not_defined); it != end; ++it) {
     ElementType type = *it;
     const Array<UInt> & connectivity = mesh.getConnectivity(type, _not_ghost);
 
     UInt * tag[2] = {NULL, NULL};
     try {
       const Array<UInt> & data_tag_0 = mesh.getData<UInt>("tag_0", type, _not_ghost);
       tag[0] = data_tag_0.storage();
     } catch(...) { tag[0] = NULL; }
 
     try {
       const Array<UInt> & data_tag_1 = mesh.getData<UInt>("tag_1", type, _not_ghost);
       tag[1] = data_tag_1.storage();
     } catch(...) { tag[1] = NULL; }
 
     for(UInt i = 0; i < connectivity.getSize(); ++i) {
       UInt offset = i * connectivity.getNbComponent();
       outfile << element_idx << " " << _akantu_to_msh_element_types[type] << " 2";
 
       /// \todo write the real data in the file
       for (UInt t = 0; t < 2; ++t)
         if(tag[t]) outfile << " " << tag[t][i];
         else outfile << " 0";
 
       for(UInt j = 0; j < connectivity.getNbComponent(); ++j) {
         outfile << " " << connectivity.storage()[offset + j] + 1;
       }
       outfile << std::endl;
       element_idx++;
     }
   }
 
   outfile << "$EndElements" << std::endl;;
 
   outfile.close();
 
 }
 
 /* -------------------------------------------------------------------------- */
 
 __END_AKANTU__
diff --git a/src/io/mesh_io/mesh_io_msh.hh b/src/io/mesh_io/mesh_io_msh.hh
index fa4bceab9..6f766701f 100644
--- a/src/io/mesh_io/mesh_io_msh.hh
+++ b/src/io/mesh_io/mesh_io_msh.hh
@@ -1,117 +1,115 @@
 /**
  * @file   mesh_io_msh.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Fri Jun 13 2014
  *
  * @brief  Read/Write for MSH files
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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_MESH_IO_MSH_HH__
 #define __AKANTU_MESH_IO_MSH_HH__
 
 /* -------------------------------------------------------------------------- */
 #include "mesh_io.hh"
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 class MeshIOMSH : public MeshIO {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   MeshIOMSH();
 
   virtual ~MeshIOMSH();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// read a mesh from the file
   virtual void read(const std::string & filename, Mesh & mesh);
 
   /// write a mesh to a file
   virtual void write(const std::string & filename, const Mesh & mesh);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
 
   /// MSH element types
   enum MSHElementType {
     _msh_not_defined    = 0,
     _msh_segment_2      = 1,   // 2-node line.
     _msh_triangle_3     = 2,   // 3-node triangle.
     _msh_quadrangle_4   = 3,   // 4-node quadrangle.
     _msh_tetrahedron_4  = 4,   // 4-node tetrahedron.
     _msh_hexahedron_8   = 5,   // 8-node hexahedron.
     _msh_prism_1        = 6,   // 6-node prism.
     _msh_pyramid_1      = 7,   // 5-node pyramid.
     _msh_segment_3      = 8,   // 3-node second order line
     _msh_triangle_6     = 9,   // 6-node second order triangle
     _msh_quadrangle_9   = 10,  // 9-node second order quadrangle
     _msh_tetrahedron_10 = 11,  // 10-node second order tetrahedron
     _msh_hexahedron_27  = 12,  // 27-node second order hexahedron
     _msh_prism_18       = 13,  // 18-node second order prism
     _msh_pyramid_14     = 14,  // 14-node second order pyramid
     _msh_point          = 15,  // 1-node point.
     _msh_quadrangle_8   = 16,   // 8-node second order quadrangle
     _msh_hexahedron_20  = 17,   // 20-node second order hexahedron
     _msh_prism_15       = 18   // 15-node second order prism
   };
 
 #define MAX_NUMBER_OF_NODE_PER_ELEMENT 10 // tetrahedron of second order
 
   /// order in witch element as to be read
   std::map<ElementType, UInt*> _read_order;
 
   /// number of nodes per msh element
   std::map<MSHElementType, UInt> _msh_nodes_per_elem;
 
   /// correspondence between msh element types and akantu element types
   std::map<MSHElementType, ElementType> _msh_to_akantu_element_types;
 
   /// correspondence between akantu element types and msh element types
   std::map<ElementType, MSHElementType> _akantu_to_msh_element_types;
 
-  /// correspondance between tag_0 and physical name (if applicable)
-  std::map<UInt, std::string> phys_name_map;
 };
 
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MESH_IO_MSH_HH__ */
diff --git a/src/mesh/group_manager.cc b/src/mesh/group_manager.cc
index 1b3bd0114..edc078e99 100644
--- a/src/mesh/group_manager.cc
+++ b/src/mesh/group_manager.cc
@@ -1,1032 +1,1032 @@
 /**
  * @file   group_manager.cc
  *
  * @author Dana Christen <dana.christen@gmail.com>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author David Simon Kammer <david.kammer@epfl.ch>
  *
  * @date creation: Fri May 03 2013
  * @date last modification: Tue Sep 02 2014
  *
  * @brief  Stores information about ElementGroup and NodeGroup
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "group_manager.hh"
 #include "mesh.hh"
 #include "aka_csr.hh"
 #include "mesh_utils.hh"
 
 #include "element_group.hh"
 #include "node_group.hh"
 #include "data_accessor.hh"
 #include "distributed_synchronizer.hh"
 
 /* -------------------------------------------------------------------------- */
 #include <sstream>
 #include <algorithm>
 #include <iterator>
 #include <list>
 #include <queue>
 #include <numeric>
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 GroupManager::GroupManager(const Mesh & mesh,
 			   const ID & id,
 			   const MemoryID & mem_id) : id(id),
 						      memory_id(mem_id),
 						      mesh(mesh) {
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 GroupManager::~GroupManager() {
   ElementGroups::iterator eit = element_groups.begin();
   ElementGroups::iterator eend = element_groups.end();
   for(; eit != eend ; ++eit) delete (eit->second);
 
   NodeGroups::iterator nit = node_groups.begin();
   NodeGroups::iterator nend = node_groups.end();
   for(; nit != nend ; ++nit) delete (nit->second);
 }
 
 /* -------------------------------------------------------------------------- */
 NodeGroup & GroupManager::createNodeGroup(const std::string & group_name,
 					  bool replace_group) {
   AKANTU_DEBUG_IN();
 
   NodeGroups::iterator it = node_groups.find(group_name);
 
   if(it != node_groups.end()) {
     if (replace_group) {
       it->second->empty();
       AKANTU_DEBUG_OUT();
       return *(it->second);
     }
     else
-      AKANTU_EXCEPTION("Trying to create a node group that already exists:" << group_name << "_nodes");
+      AKANTU_EXCEPTION("Trying to create a node group that already exists:" << group_name);
   }
 
   NodeGroup * node_group = new NodeGroup(group_name, id + ":" + group_name + "_node_group",
 					 memory_id);
 
   node_groups[group_name] = node_group;
 
   AKANTU_DEBUG_OUT();
 
   return *node_group;
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 NodeGroup & GroupManager::createFilteredNodeGroup(const std::string & group_name,
 						  const NodeGroup & source_node_group,
 						  T & filter) {
   AKANTU_DEBUG_IN();
 
   NodeGroup & node_group = this->createNodeGroup(group_name);
   node_group.append(source_node_group);
   if (T::type == FilterFunctor::_node_filter_functor) {
     node_group.applyNodeFilter(filter);
   }
   else {
     AKANTU_DEBUG_ERROR("ElementFilter cannot be applied to NodeGroup yet."
 		       << " Needs to be implemented.");
   }
 
   AKANTU_DEBUG_OUT();
   return node_group;
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::destroyNodeGroup(const std::string & group_name) {
   AKANTU_DEBUG_IN();
 
   NodeGroups::iterator nit = node_groups.find(group_name);
   NodeGroups::iterator nend = node_groups.end();
   if (nit != nend) {
     delete (nit->second);
     node_groups.erase(nit);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 ElementGroup & GroupManager::createElementGroup(const std::string & group_name,
 						UInt dimension,
 						bool replace_group) {
   AKANTU_DEBUG_IN();
 
   NodeGroup & new_node_group = createNodeGroup(group_name + "_nodes", replace_group);
 
   ElementGroups::iterator it = element_groups.find(group_name);
 
   if(it != element_groups.end()) {
     if (replace_group) {
       it->second->empty();
       AKANTU_DEBUG_OUT();
       return *(it->second);
     }
     else
       AKANTU_EXCEPTION("Trying to create a element group that already exists:" << group_name);
   }
 
   ElementGroup * element_group = new ElementGroup(group_name, mesh, new_node_group,
 						  dimension,
 						  id + ":" + group_name + "_element_group",
 						  memory_id);
 
   node_groups[group_name + "_nodes"] = &new_node_group;
   element_groups[group_name] = element_group;
 
   AKANTU_DEBUG_OUT();
 
   return *element_group;
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::destroyElementGroup(const std::string & group_name,
 				       bool destroy_node_group) {
   AKANTU_DEBUG_IN();
 
   ElementGroups::iterator eit = element_groups.find(group_name);
   ElementGroups::iterator eend = element_groups.end();
   if (eit != eend) {
     if (destroy_node_group)
       destroyNodeGroup(eit->second->getNodeGroup().getName());
     delete (eit->second);
     element_groups.erase(eit);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::destroyAllElementGroups(bool destroy_node_groups) {
   AKANTU_DEBUG_IN();
 
   ElementGroups::iterator eit = element_groups.begin();
   ElementGroups::iterator eend = element_groups.end();
   for(; eit != eend ; ++eit) {
     if (destroy_node_groups)
       destroyNodeGroup(eit->second->getNodeGroup().getName());
     delete (eit->second);
   }
   element_groups.clear();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 ElementGroup & GroupManager::createElementGroup(const std::string & group_name,
 						UInt dimension,
 						NodeGroup & node_group) {
   AKANTU_DEBUG_IN();
 
   if(element_groups.find(group_name) != element_groups.end())
     AKANTU_EXCEPTION("Trying to create a element group that already exists:" << group_name);
 
   ElementGroup * element_group = new ElementGroup(group_name, mesh, node_group,
 						  dimension,
 						  id + ":" + group_name + "_element_group",
 						  memory_id);
 
   element_groups[group_name] = element_group;
 
   AKANTU_DEBUG_OUT();
 
   return *element_group;
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 ElementGroup & GroupManager::createFilteredElementGroup(const std::string & group_name,
 							UInt dimension,
 							const NodeGroup & node_group,
 							T & filter) {
   AKANTU_DEBUG_IN();
 
   ElementGroup * element_group = NULL;
 
   if (T::type == FilterFunctor::_node_filter_functor) {
     NodeGroup & filtered_node_group = this->createFilteredNodeGroup(group_name + "_nodes",
 								    node_group,
 								    filter);
     element_group = &(this->createElementGroup(group_name,
 					       dimension,
 					       filtered_node_group));
   }
   else if (T::type == FilterFunctor::_element_filter_functor) {
     AKANTU_DEBUG_ERROR("Cannot handle an ElementFilter yet. Needs to be implemented.");
   }
 
   AKANTU_DEBUG_OUT();
 
   return *element_group;
 }
 
 /* -------------------------------------------------------------------------- */
 class ClusterSynchronizer : public DataAccessor {
   typedef std::set< std::pair<UInt, UInt> > DistantIDs;
 
 public:
   ClusterSynchronizer(GroupManager & group_manager,
 		      UInt element_dimension,
 		      std::string cluster_name_prefix,
 		      ElementTypeMapArray<UInt> & element_to_fragment,
 		      DistributedSynchronizer & distributed_synchronizer,
 		      UInt nb_cluster) :
     group_manager(group_manager),
     element_dimension(element_dimension),
     cluster_name_prefix(cluster_name_prefix),
     element_to_fragment(element_to_fragment),
     distributed_synchronizer(distributed_synchronizer),
     nb_cluster(nb_cluster) { }
 
   UInt synchronize() {
     StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
     UInt rank = comm.whoAmI();
     UInt nb_proc = comm.getNbProc();
 
     /// find starting index to renumber local clusters
     Array<UInt> nb_cluster_per_proc(nb_proc);
     nb_cluster_per_proc(rank) = nb_cluster;
     comm.allGather(nb_cluster_per_proc.storage(), 1);
 
     starting_index = std::accumulate(nb_cluster_per_proc.begin(),
 				     nb_cluster_per_proc.begin() + rank,
 				     0);
 
     UInt global_nb_fragment = std::accumulate(nb_cluster_per_proc.begin() + rank,
 					      nb_cluster_per_proc.end(),
 					      starting_index);
 
     /// create the local to distant cluster pairs with neighbors
     distributed_synchronizer.computeBufferSize(*this, _gst_gm_clusters);
     distributed_synchronizer.asynchronousSynchronize(*this, _gst_gm_clusters);
     distributed_synchronizer.waitEndSynchronize(*this, _gst_gm_clusters);
 
     /// count total number of pairs
     Array<Int> nb_pairs(nb_proc);
     nb_pairs(rank) = distant_ids.size();
     comm.allGather(nb_pairs.storage(), 1);
 
     UInt total_nb_pairs = std::accumulate(nb_pairs.begin(), nb_pairs.end(), 0);
 
     /// generate pairs global array
     UInt local_pair_index = std::accumulate(nb_pairs.storage(),
 					    nb_pairs.storage() + rank, 0);
 
     Array<UInt> total_pairs(total_nb_pairs, 2);
 
     DistantIDs::iterator ids_it = distant_ids.begin();
     DistantIDs::iterator ids_end = distant_ids.end();
 
     for (; ids_it != ids_end; ++ids_it, ++local_pair_index) {
       total_pairs(local_pair_index, 0) = ids_it->first;
       total_pairs(local_pair_index, 1) = ids_it->second;
     }
 
     /// communicate pairs to all processors
     nb_pairs *= 2;
     comm.allGatherV(total_pairs.storage(), nb_pairs.storage());
 
     /// renumber clusters
 
     /// generate fragment list
     std::vector< std::set<UInt> > global_clusters;
     UInt total_nb_cluster = 0;
 
     Array<bool> is_fragment_in_cluster(global_nb_fragment, 1, false);
     std::queue<UInt> fragment_check_list;
 
     while (total_pairs.getSize() != 0) {
       /// create a new cluster
       ++total_nb_cluster;
       global_clusters.resize(total_nb_cluster);
       std::set<UInt> & current_cluster = global_clusters[total_nb_cluster - 1];
 
       UInt first_fragment = total_pairs(0, 0);
       UInt second_fragment = total_pairs(0, 1);
       total_pairs.erase(0);
 
       fragment_check_list.push(first_fragment);
       fragment_check_list.push(second_fragment);
 
       while (!fragment_check_list.empty()) {
 	UInt current_fragment = fragment_check_list.front();
 
 	UInt * total_pairs_end = total_pairs.storage() + total_pairs.getSize() * 2;
 
 	UInt * fragment_found = std::find(total_pairs.storage(),
 					  total_pairs_end,
 					  current_fragment);
 
 	if (fragment_found != total_pairs_end) {
 	  UInt position = fragment_found - total_pairs.storage();
 	  UInt pair = position / 2;
 	  UInt other_index = (position + 1) % 2;
 	  fragment_check_list.push(total_pairs(pair, other_index));
 	  total_pairs.erase(pair);
 	}
 	else {
 	  fragment_check_list.pop();
 	  current_cluster.insert(current_fragment);
 	  is_fragment_in_cluster(current_fragment) = true;
 	}
       }
     }
 
     /// add to FragmentToCluster all local fragments
     for (UInt c = 0; c < global_nb_fragment; ++c) {
       if (!is_fragment_in_cluster(c)) {
 	++total_nb_cluster;
 	global_clusters.resize(total_nb_cluster);
 	std::set<UInt> & current_cluster = global_clusters[total_nb_cluster - 1];
 
 	current_cluster.insert(c);
       }
     }
 
     /// reorganize element groups to match global clusters
     for (UInt c = 0; c < global_clusters.size(); ++c) {
 
       /// create new element group corresponding to current cluster
       std::stringstream sstr;
       sstr << cluster_name_prefix << "_" << c;
       ElementGroup & cluster = group_manager.createElementGroup(sstr.str(),
 								element_dimension,
 								true);
 
       std::set<UInt>::iterator it = global_clusters[c].begin();
       std::set<UInt>::iterator end = global_clusters[c].end();
 
       /// append to current element group all fragments that belong to
       /// the same cluster if they exist
       for (; it != end; ++it) {
 	Int local_index = *it - starting_index;
 
 	if (local_index < 0 || local_index >= Int(nb_cluster)) continue;
 
 	std::stringstream tmp_sstr;
 	tmp_sstr << "tmp_" << cluster_name_prefix << "_" << local_index;
 	GroupManager::element_group_iterator eg_it
 	  = group_manager.element_group_find(tmp_sstr.str());
 
 	AKANTU_DEBUG_ASSERT(eg_it != group_manager.element_group_end(),
 			    "Temporary fragment \""<< tmp_sstr.str() << "\" not found");
 
 	cluster.append(*(eg_it->second));
 	group_manager.destroyElementGroup(tmp_sstr.str(), true);
       }
     }
 
     return total_nb_cluster;
   }
 
 private:
   /// functions for parallel communications
   inline UInt getNbDataForElements(const Array<Element> & elements,
 				   SynchronizationTag tag) const {
     if (tag == _gst_gm_clusters)
       return elements.getSize() * sizeof(UInt);
 
     return 0;
   }
 
   inline void packElementData(CommunicationBuffer & buffer,
 			      const Array<Element> & elements,
 			      SynchronizationTag tag) const {
     if (tag != _gst_gm_clusters) return;
 
     Array<Element>::const_iterator<> el_it = elements.begin();
     Array<Element>::const_iterator<> el_end = elements.end();
 
     for (; el_it != el_end; ++el_it) {
 
       const Element & el = *el_it;
 
       /// for each element pack its global cluster index
       buffer << element_to_fragment(el.type, el.ghost_type)(el.element) + starting_index;
     }
   }
 
   inline void unpackElementData(CommunicationBuffer & buffer,
 				const Array<Element> & elements,
 				SynchronizationTag tag) {
     if (tag != _gst_gm_clusters) return;
 
     Array<Element>::const_iterator<> el_it = elements.begin();
     Array<Element>::const_iterator<> el_end = elements.end();
 
     for (; el_it != el_end; ++el_it) {
       UInt distant_cluster;
 
       buffer >> distant_cluster;
 
       const Element & el = *el_it;
       UInt local_cluster = element_to_fragment(el.type, el.ghost_type)(el.element) + starting_index;
 
       distant_ids.insert(std::make_pair(local_cluster, distant_cluster));
     }
   }
 
 private:
   GroupManager & group_manager;
   UInt element_dimension;
   std::string cluster_name_prefix;
   ElementTypeMapArray<UInt> & element_to_fragment;
   DistributedSynchronizer & distributed_synchronizer;
 
   UInt nb_cluster;
   DistantIDs distant_ids;
 
   UInt starting_index;
 };
 
 /* -------------------------------------------------------------------------- */
 /// \todo this function doesn't work in 1D
 UInt GroupManager::createBoundaryGroupFromGeometry() {
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   return createClusters(spatial_dimension - 1, "boundary");
 }
 
 /* -------------------------------------------------------------------------- */
 //// \todo if needed element list construction can be optimized by
 //// templating the filter class
 UInt GroupManager::createClusters(UInt element_dimension,
 				  std::string cluster_name_prefix,
 				  const GroupManager::ClusteringFilter & filter,
 				  DistributedSynchronizer * distributed_synchronizer,
 				  Mesh * mesh_facets) {
   AKANTU_DEBUG_IN();
 
   UInt nb_proc = StaticCommunicator::getStaticCommunicator().getNbProc();
   std::string tmp_cluster_name_prefix = cluster_name_prefix;
 
   ElementTypeMapArray<UInt> * element_to_fragment = NULL;
 
   if (nb_proc > 1 && distributed_synchronizer) {
     element_to_fragment = new ElementTypeMapArray<UInt>;
     mesh.initElementTypeMapArray(*element_to_fragment, 1, element_dimension,
 				false, _ek_not_defined, true);
     tmp_cluster_name_prefix = "tmp_" + tmp_cluster_name_prefix;
   }
 
   /// Get facets
   bool mesh_facets_created = false;
 
   if (!mesh_facets && element_dimension > 0) {
     mesh_facets = new Mesh(mesh.getSpatialDimension(),
 			   mesh.getNodes().getID(),
 			   "mesh_facets_for_clusters");
 
     mesh_facets->defineMeshParent(mesh);
 
     MeshUtils::buildAllFacets(mesh, *mesh_facets,
 			      element_dimension,
 			      element_dimension - 1,
 			      distributed_synchronizer);
   }
 
   ElementTypeMapArray<bool> seen_elements("seen_elements");
   mesh.initElementTypeMapArray(seen_elements, 1, element_dimension,
 			       false, _ek_not_defined, true);
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType ghost_type = *gt;
     Element el;
     el.ghost_type = ghost_type;
 
     Mesh::type_iterator type_it  = mesh.firstType(element_dimension,
 						  ghost_type, _ek_not_defined);
     Mesh::type_iterator type_end = mesh.lastType (element_dimension,
 						  ghost_type, _ek_not_defined);
 
     for (; type_it != type_end; ++type_it) {
       el.type = *type_it;
       el.kind = Mesh::getKind(*type_it);
       UInt nb_element = mesh.getNbElement(*type_it, ghost_type);
       Array<bool> & seen_elements_array = seen_elements(el.type, ghost_type);
 
       for (UInt e = 0; e < nb_element; ++e) {
 	el.element = e;
 	if (!filter(el))
 	  seen_elements_array(e) = true;
       }
     }
   }
 
   Array<bool> checked_node(mesh.getNbNodes(), 1, false);
 
   UInt nb_cluster = 0;
 
   /// keep looping until all elements are seen
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType ghost_type = *gt;
     Element uns_el;
     uns_el.ghost_type = ghost_type;
 
     Mesh::type_iterator type_it = mesh.firstType(element_dimension,
 						 ghost_type,
 						 _ek_not_defined);
     Mesh::type_iterator type_end = mesh.lastType(element_dimension,
 						 ghost_type,
 						 _ek_not_defined);
 
     for (; type_it != type_end; ++type_it) {
       uns_el.type = *type_it;
       Array<bool> & seen_elements_vec = seen_elements(uns_el.type, uns_el.ghost_type);
 
       for (UInt e = 0; e < seen_elements_vec.getSize(); ++e) {
 	// skip elements that have been already seen
 	if (seen_elements_vec(e) == true) continue;
 
 	// set current element
 	uns_el.element = e;
 	seen_elements_vec(e) = true;
 
 	/// create a new cluster
 	std::stringstream sstr;
 	sstr << tmp_cluster_name_prefix << "_" << nb_cluster;
 	ElementGroup & cluster = createElementGroup(sstr.str(),
 						    element_dimension,
 						    true);
 	++nb_cluster;
 
 	// point element are cluster by themself
 	if(element_dimension == 0) {
 	  cluster.add(uns_el);
 
 	  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(uns_el.type);
 	  Vector<UInt> connect =
 	    mesh.getConnectivity(uns_el.type, uns_el.ghost_type).begin(nb_nodes_per_element)[uns_el.element];
 	  for (UInt n = 0; n < nb_nodes_per_element; ++n) {
 	    /// add element's nodes to the cluster
 	    UInt node = connect[n];
 	    if (!checked_node(node)) {
 	      cluster.addNode(node);
 	      checked_node(node) = true;
 	    }
 	  }
 
 	  continue;
 	}
 
 	std::queue<Element> element_to_add;
 	element_to_add.push(uns_el);
 
 	/// keep looping until current cluster is complete (no more
 	/// connected elements)
 	while(!element_to_add.empty()) {
 
 	  /// take first element and erase it in the queue
 	  Element el = element_to_add.front();
 	  element_to_add.pop();
 
 	  /// if parallel, store cluster index per element
 	  if (nb_proc > 1 && distributed_synchronizer)
 	    (*element_to_fragment)(el.type, el.ghost_type)(el.element) = nb_cluster - 1;
 
 	  /// add current element to the cluster
 	  cluster.add(el);
 
 	  const Array<Element> & element_to_facet
 	    = mesh_facets->getSubelementToElement(el.type, el.ghost_type);
 
 	  UInt nb_facet_per_element = element_to_facet.getNbComponent();
 
 	  for (UInt f = 0; f < nb_facet_per_element; ++f) {
 	    const Element & facet = element_to_facet(el.element, f);
 
 	    if (facet == ElementNull) continue;
 
 	    const std::vector<Element> & connected_elements
 	      = mesh_facets->getElementToSubelement(facet.type, facet.ghost_type)(facet.element);
 
 	    for (UInt elem = 0; elem < connected_elements.size(); ++elem) {
 	      const Element & check_el = connected_elements[elem];
 
 	      // check if this element has to be skipped
 	      if (check_el == ElementNull || check_el == el) continue;
 
 	      Array<bool> & seen_elements_vec_current
 		= seen_elements(check_el.type, check_el.ghost_type);
 
 	      if (seen_elements_vec_current(check_el.element) == false) {
 		seen_elements_vec_current(check_el.element) = true;
 		element_to_add.push(check_el);
 	      }
 	    }
 	  }
 
 
 	  UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type);
 	  Vector<UInt> connect =
 	    mesh.getConnectivity(el.type, el.ghost_type).begin(nb_nodes_per_element)[el.element];
 	  for (UInt n = 0; n < nb_nodes_per_element; ++n) {
 	    /// add element's nodes to the cluster
 	    UInt node = connect[n];
 	    if (!checked_node(node)) {
 	      cluster.addNode(node, false);
 	      checked_node(node) = true;
 	    }
 	  }
 	}
       }
     }
   }
 
   if (nb_proc > 1 && distributed_synchronizer) {
     ClusterSynchronizer cluster_synchronizer(*this, element_dimension,
 					     cluster_name_prefix,
 					     *element_to_fragment,
 					     *distributed_synchronizer,
 					     nb_cluster);
     nb_cluster = cluster_synchronizer.synchronize();
     delete element_to_fragment;
   }
 
   if (mesh_facets_created)
     delete mesh_facets;
 
   if(mesh.isDistributed())
     this->synchronizeGroupNames();
 
   AKANTU_DEBUG_OUT();
   return nb_cluster;
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void GroupManager::createGroupsFromMeshData(const std::string & dataset_name) {
   std::set<std::string> group_names;
   const ElementTypeMapArray<T> & datas = mesh.getData<T>(dataset_name);
   typedef typename ElementTypeMapArray<T>::type_iterator type_iterator;
 
   std::map<std::string, UInt> group_dim;
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();  gt != ghost_type_t::end(); ++gt) {
     type_iterator type_it = datas.firstType(_all_dimensions, *gt);
     type_iterator type_end  = datas.lastType(_all_dimensions, *gt);
     for (; type_it != type_end; ++type_it) {
       const Array<T> & dataset = datas(*type_it, *gt);
       UInt nb_element = mesh.getNbElement(*type_it, *gt);
       AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element,
 			  "Not the same number of elements ("<< *type_it << ":" << *gt <<
 			  ") in the map from MeshData (" << dataset.getSize() << ") "
 			  << dataset_name <<" and in the mesh (" << nb_element << ")!");
       for(UInt e(0); e < nb_element; ++e) {
 	std::stringstream sstr; sstr << dataset(e);
 	std::string gname = sstr.str();
 	group_names.insert(gname);
 
 	std::map<std::string, UInt>::iterator it = group_dim.find(gname);
 	if(it == group_dim.end()) {
 	  group_dim[gname] = mesh.getSpatialDimension(*type_it);
 	} else {
 	  it->second = std::max(it->second, mesh.getSpatialDimension(*type_it));
 	}
       }
     }
   }
 
   std::set<std::string>::iterator git  = group_names.begin();
   std::set<std::string>::iterator gend = group_names.end();
   for (;git != gend; ++git) createElementGroup(*git, group_dim[*git]);
 
   if(mesh.isDistributed())
     this->synchronizeGroupNames();
 
   Element el;
   for (ghost_type_t::iterator gt = ghost_type_t::begin();  gt != ghost_type_t::end(); ++gt) {
     el.ghost_type = *gt;
 
     type_iterator type_it = datas.firstType(_all_dimensions, *gt);
     type_iterator type_end  = datas.lastType(_all_dimensions, *gt);
     for (; type_it != type_end; ++type_it) {
       el.type = *type_it;
 
       const Array<T> & dataset = datas(*type_it, *gt);
       UInt nb_element = mesh.getNbElement(*type_it, *gt);
       AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element,
 			  "Not the same number of elements in the map from MeshData and in the mesh!");
 
       UInt nb_nodes_per_element = mesh.getNbNodesPerElement(el.type);
 
       Array<UInt>::const_iterator< Vector<UInt> > cit =
 	mesh.getConnectivity(*type_it, *gt).begin(nb_nodes_per_element);
 
       for(UInt e(0); e < nb_element; ++e, ++cit) {
 	el.element = e;
 	std::stringstream sstr; sstr << dataset(e);
 	ElementGroup & group = getElementGroup(sstr.str());
 	group.add(el, false, false);
 
 	const Vector<UInt> & connect = *cit;
 	for (UInt n = 0; n < nb_nodes_per_element; ++n) {
 	  UInt node = connect[n];
 	  group.addNode(node, false);
 	}
 
       }
     }
   }
 
   git  = group_names.begin();
   for (;git != gend; ++git) {
     getElementGroup(*git).optimize();
   }
 }
 
 template void GroupManager::createGroupsFromMeshData<std::string>(const std::string & dataset_name);
 template void GroupManager::createGroupsFromMeshData<UInt>(const std::string & dataset_name);
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::createElementGroupFromNodeGroup(const std::string & name,
 						   const std::string & node_group_name,
 						   UInt dimension) {
   NodeGroup & node_group = getNodeGroup(node_group_name);
   ElementGroup & group = createElementGroup(name, dimension, node_group);
 
   CSR<Element> node_to_elem;
   MeshUtils::buildNode2Elements(mesh, node_to_elem, dimension);
 
   std::set<Element> seen;
 
   Array<UInt>::const_iterator<> itn  = node_group.begin();
   Array<UInt>::const_iterator<> endn = node_group.end();
   for (;itn != endn; ++itn) {
     CSR<Element>::iterator ite = node_to_elem.begin(*itn);
     CSR<Element>::iterator ende = node_to_elem.end(*itn);
     for (;ite != ende; ++ite) {
       const Element & elem = *ite;
       if(dimension != _all_dimensions && dimension != Mesh::getSpatialDimension(elem.type)) continue;
       if(seen.find(elem) != seen.end()) continue;
 
       UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(elem.type);
       Array<UInt>::const_iterator< Vector<UInt> > conn_it =
 	mesh.getConnectivity(elem.type, elem.ghost_type).begin(nb_nodes_per_element);
       const Vector<UInt> & conn = conn_it[elem.element];
 
       UInt count = 0;
       for (UInt n = 0; n < conn.size(); ++n) {
 	count += (node_group.getNodes().find(conn(n)) != -1 ? 1 : 0);
       }
 
       if(count == nb_nodes_per_element) group.add(elem);
 
       seen.insert(elem);
     }
   }
 
   group.optimize();
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   stream << space << "GroupManager [" << std::endl;
 
   std::set<std::string> node_group_seen;
   for(const_element_group_iterator it(element_group_begin()); it != element_group_end(); ++it) {
     it->second->printself(stream, indent + 1);
     node_group_seen.insert(it->second->getNodeGroup().getName());
   }
 
   for(const_node_group_iterator it(node_group_begin()); it != node_group_end(); ++it) {
     if(node_group_seen.find(it->second->getName()) == node_group_seen.end())
       it->second->printself(stream, indent + 1);
   }
 
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 UInt GroupManager::getNbElementGroups(UInt dimension) const {
   if(dimension == _all_dimensions) return element_groups.size();
 
   ElementGroups::const_iterator it  = element_groups.begin();
   ElementGroups::const_iterator end = element_groups.end();
   UInt count = 0;
   for(;it != end; ++it) count += (it->second->getDimension() == dimension);
   return count;
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::checkAndAddGroups(CommunicationBuffer & buffer) {
   AKANTU_DEBUG_IN();
 
   UInt nb_node_group; buffer >> nb_node_group;
   AKANTU_DEBUG_INFO("Received " << nb_node_group << " node group names");
 
   for (UInt ng = 0; ng < nb_node_group; ++ng) {
     std::string node_group_name;
     buffer >> node_group_name;
 
     if(node_groups.find(node_group_name) == node_groups.end()) {
       this->createNodeGroup(node_group_name);
     }
 
     AKANTU_DEBUG_INFO("Received node goup name: " << node_group_name);
   }
 
 
   UInt nb_element_group; buffer >> nb_element_group;
   AKANTU_DEBUG_INFO("Received " << nb_element_group << " element group names");
   for (UInt eg = 0; eg < nb_element_group; ++eg) {
     std::string element_group_name; buffer >> element_group_name;
     std::string node_group_name;    buffer >> node_group_name;
     UInt dim;                       buffer >> dim;
 
     AKANTU_DEBUG_INFO("Received element group name: " << element_group_name
 		      << " corresponding to a "
 		      << Int(dim) << "D group with node group "
 		      << node_group_name);
 
     NodeGroup & node_group = *node_groups[node_group_name];
 
     if(element_groups.find(element_group_name) == element_groups.end()) {
       this->createElementGroup(element_group_name, dim, node_group);
     }
 
   }
 
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::fillBufferWithGroupNames(DynamicCommunicationBuffer & comm_buffer) const {
   AKANTU_DEBUG_IN();
 
   // packing node group names;
   UInt nb_groups = this->node_groups.size();
   comm_buffer << nb_groups;
   AKANTU_DEBUG_INFO("Sending " << nb_groups << " node group names");
 
   NodeGroups::const_iterator nnames_it  = node_groups.begin();
   NodeGroups::const_iterator nnames_end = node_groups.end();
   for (; nnames_it != nnames_end; ++nnames_it) {
     std::string node_group_name = nnames_it->first;
     comm_buffer << node_group_name;
     AKANTU_DEBUG_INFO("Sending node goupe name: " << node_group_name);
   }
 
   // packing element group names with there associated node group name
   nb_groups = this->element_groups.size();
   comm_buffer << nb_groups;
   AKANTU_DEBUG_INFO("Sending " << nb_groups << " element group names");
   ElementGroups::const_iterator gnames_it  = this->element_groups.begin();
   ElementGroups::const_iterator gnames_end = this->element_groups.end();
   for (; gnames_it != gnames_end; ++gnames_it) {
     ElementGroup & element_group = *(gnames_it->second);
     std::string element_group_name = gnames_it->first;
     std::string node_group_name = element_group.getNodeGroup().getName();
     UInt dim = element_group.getDimension();
 
     comm_buffer << element_group_name;
     comm_buffer << node_group_name;
     comm_buffer << dim;
 
     AKANTU_DEBUG_INFO("Sending element group name: " << element_group_name
 		       << " corresponding to a "
 		       << Int(dim) << "D group with the node group "
 		       << node_group_name);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void GroupManager::synchronizeGroupNames() {
   AKANTU_DEBUG_IN();
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   UInt nb_proc = comm.getNbProc();
   UInt my_rank = comm.whoAmI();
 
   if(nb_proc == 1) return;
 
   if(my_rank == 0) {
     for (UInt p = 1; p < nb_proc; ++p) {
       CommunicationStatus status;
       comm.probe<char>(p, p, status);
       AKANTU_DEBUG_INFO("Got " << printMemorySize<char>(status.getSize()) << " from proc " << p);
 
       CommunicationBuffer recv_buffer(status.getSize());
       comm.receive(recv_buffer.storage(), recv_buffer.getSize(), p, p);
 
       this->checkAndAddGroups(recv_buffer);
     }
 
     DynamicCommunicationBuffer comm_buffer;
     this->fillBufferWithGroupNames(comm_buffer);
 
     UInt buffer_size = comm_buffer.getSize();
 
     comm.broadcast(&buffer_size, 1, 0);
 
     AKANTU_DEBUG_INFO("Initiating broadcast with " << printMemorySize<char>(comm_buffer.getSize()));
     comm.broadcast(comm_buffer.storage(), buffer_size, 0);
 
   } else {
     DynamicCommunicationBuffer comm_buffer;
     this->fillBufferWithGroupNames(comm_buffer);
 
     AKANTU_DEBUG_INFO("Sending " << printMemorySize<char>(comm_buffer.getSize()) << " to proc " << 0);
     comm.send(comm_buffer.storage(), comm_buffer.getSize(), 0, my_rank);
 
     UInt buffer_size = 0;
     comm.broadcast(&buffer_size, 1, 0);
 
     AKANTU_DEBUG_INFO("Receiving broadcast with " << printMemorySize<char>(comm_buffer.getSize()));
     CommunicationBuffer recv_buffer(buffer_size);
     comm.broadcast(recv_buffer.storage(), recv_buffer.getSize(), 0);
 
     this->checkAndAddGroups(recv_buffer);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 const ElementGroup & GroupManager::getElementGroup(const std::string & name) const {
   const_element_group_iterator it = element_group_find(name);
   if(it == element_group_end()) {
     AKANTU_EXCEPTION("There are no element groups named " << name
 		     << " associated to the group manager: " << id);
   }
 
   return *(it->second);
 }
 
 /* -------------------------------------------------------------------------- */
 ElementGroup & GroupManager::getElementGroup(const std::string & name) {
   element_group_iterator it = element_group_find(name);
   if(it == element_group_end()) {
     AKANTU_EXCEPTION("There are no element groups named " << name
 		     << " associated to the group manager: " << id);
   }
 
   return *(it->second);
 }
 
 
 /* -------------------------------------------------------------------------- */
 const NodeGroup & GroupManager::getNodeGroup(const std::string & name) const {
    const_node_group_iterator it = node_group_find(name);
   if(it == node_group_end()) {
     AKANTU_EXCEPTION("There are no node groups named " << name
 		     << " associated to the group manager: " << id);
   }
 
   return *(it->second);
 }
 
 /* -------------------------------------------------------------------------- */
 NodeGroup & GroupManager::getNodeGroup(const std::string & name) {
   node_group_iterator it = node_group_find(name);
   if(it == node_group_end()) {
     AKANTU_EXCEPTION("There are no node groups named " << name
 		     << " associated to the group manager: " << id);
   }
 
   return *(it->second);
 }
 
 
 __END_AKANTU__
diff --git a/src/mesh/node_group.hh b/src/mesh/node_group.hh
index 07fc695ad..348be708d 100644
--- a/src/mesh/node_group.hh
+++ b/src/mesh/node_group.hh
@@ -1,126 +1,128 @@
 /**
  * @file   node_group.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Nov 13 2013
  * @date last modification: Mon Jun 09 2014
  *
  * @brief  Node group definition
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "aka_array.hh"
 #include "aka_memory.hh"
 #include "mesh_filter.hh"
 /* -------------------------------------------------------------------------- */
 
 
 
 #ifndef __AKANTU_NODE_GROUP_HH__
 #define __AKANTU_NODE_GROUP_HH__
 
 __BEGIN_AKANTU__
 
 class NodeGroup : Memory {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   NodeGroup(const std::string & name,
             const std::string & id = "node_group",
             const MemoryID & memory_id = 0);
   virtual ~NodeGroup();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   typedef Array<UInt>::const_iterator<UInt> const_node_iterator;
 
   /// empty the node group
   void empty();
 
   /// iterator to the beginning of the node group
   inline const_node_iterator begin() const;
   /// iterator to the end of the node group
   inline const_node_iterator end() const;
 
   /// add a node and give the local position through an iterator
   inline const_node_iterator add(UInt node, bool check_for_duplicate = true);
 
   /// remove duplicated nodes
   void optimize();
 
   /// append a group to current one
   void append(const NodeGroup & other_group);
 
   /// apply a filter on current node group
   template <typename T>
   void applyNodeFilter(T & filter);
 
   /// function to print the contain of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   AKANTU_GET_MACRO_NOT_CONST(Nodes, node_group, Array<UInt> &);
   AKANTU_GET_MACRO(Nodes, node_group, const Array<UInt> &);
   AKANTU_GET_MACRO(Name, name, const std::string &);
 
   /// give the number of nodes in the current group
   inline UInt getSize() const;
 
+  UInt * storage(){return node_group.storage();};
+  
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   /// name of the group
   std::string name;
 
   /// list of nodes in the group
   Array<UInt> & node_group;
 };
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const NodeGroup & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 __END_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 #include "node_group_inline_impl.cc"
 
 
 
 #endif /* __AKANTU_NODE_GROUP_HH__ */
diff --git a/src/model/solid_mechanics/embedded_interface_model.cc b/src/model/solid_mechanics/embedded_interface_model.cc
index b0744fe05..351ec4d15 100644
--- a/src/model/solid_mechanics/embedded_interface_model.cc
+++ b/src/model/solid_mechanics/embedded_interface_model.cc
@@ -1,185 +1,160 @@
 /**
  * @file   embedded_interface_model.cc
  *
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @date creation: Mon Mar 9 2015
  * @date last modification: Mon Mar 9 2015
  *
  * @brief  Model of Solid Mechanics with embedded interfaces
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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 "embedded_interface_model.hh"
 #include "material_reinforcement.hh"
 
 #ifdef AKANTU_USE_IOHELPER
 #  include "dumper_paraview.hh"
 #  include "dumpable_inline_impl.hh"
 #endif
 
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
-const EmbeddedInterfaceModelOptions default_embedded_interface_model_options(_explicit_lumped_mass, false, false);
+const EmbeddedInterfaceModelOptions
+  default_embedded_interface_model_options(_explicit_lumped_mass, false, false);
 
 EmbeddedInterfaceModel::EmbeddedInterfaceModel(Mesh & mesh,
                                                Mesh & primitive_mesh,
                                                UInt spatial_dimension,
                                                const ID & id,
                                                const MemoryID & memory_id) :
   SolidMechanicsModel(mesh, spatial_dimension, id, memory_id),
+  intersector(mesh, primitive_mesh),
   interface_mesh(NULL),
   primitive_mesh(primitive_mesh),
-  interface_material_selector(NULL),
-  intersector(mesh, primitive_mesh)
+  interface_material_selector(NULL)
 {
   // This pointer should be deleted by ~SolidMechanicsModel()
-  MaterialSelector * mat_sel_pointer = new MeshDataMaterialSelector<std::string>("physical_names", *this);
+  MaterialSelector * mat_sel_pointer =
+    new MeshDataMaterialSelector<std::string>("physical_names", *this);
+
   this->setMaterialSelector(*mat_sel_pointer);
+
+  interface_mesh = &(intersector.getInterfaceMesh());
+  registerFEEngineObject<MyFEEngineType>("EmbeddedInterfaceFEEngine", *interface_mesh, 1);
 }
 
 EmbeddedInterfaceModel::~EmbeddedInterfaceModel() {
   delete interface_material_selector;
 }
 
 void EmbeddedInterfaceModel::initFull(const ModelOptions & options) {
   const EmbeddedInterfaceModelOptions & eim_options =
     dynamic_cast<const EmbeddedInterfaceModelOptions &>(options);
 
   // We don't want to initiate materials before shape functions are initialized
   SolidMechanicsModelOptions dummy_options(eim_options.analysis_method, true);
 
-  interface_mesh = &(intersector.getInterfaceMesh());
-  registerFEEngineObject<MyFEEngineType>("EmbeddedInterfaceFEEngine", *interface_mesh, 1);
-
-  SolidMechanicsModel::initFull(dummy_options);
-
   if (!eim_options.no_init_intersections)
     intersector.constructData();
 
   FEEngine & engine = getFEEngine("EmbeddedInterfaceFEEngine");
   engine.initShapeFunctions(_not_ghost);
   engine.initShapeFunctions(_ghost);
 
+  SolidMechanicsModel::initFull(dummy_options);
+
   this->initMaterials();
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.registerDumper<DumperParaview>("reinforcement", id);
   this->mesh.addDumpMeshToDumper("reinforcement", *interface_mesh,
                                  1, _not_ghost, _ek_regular);
 #endif
 }
 
 void EmbeddedInterfaceModel::initMaterials() {
   Element element;
 
   delete interface_material_selector;
-  interface_material_selector = new InterfaceMeshDataMaterialSelector<std::string>("physical_names", *this);
+  interface_material_selector =
+    new InterfaceMeshDataMaterialSelector<std::string>("physical_names", *this);
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) {
     element.ghost_type = *gt;
 
     Mesh::type_iterator it = interface_mesh->firstType(1, *gt);
     Mesh::type_iterator end = interface_mesh->lastType(1, *gt);
 
     for (; it != end ; ++it) {
       UInt nb_element = interface_mesh->getNbElement(*it, *gt);
 
       element.type = *it;
 
       Array<UInt> & mat_indexes = material_index.alloc(nb_element, 1, *it, *gt);
 
       for (UInt el = 0 ; el < nb_element ; el++) {
         element.element = el;
         UInt mat_index = (*interface_material_selector)(element);
 
         AKANTU_DEBUG_ASSERT(mat_index < materials.size(),
             "The material selector returned an index that does not exist");
         mat_indexes(element.element) = mat_index;
         materials.at(mat_index)->addElement(*it, el, *gt);
       }
     }
   }
 
   SolidMechanicsModel::initMaterials();
 }
 
-ElementTypeMap<UInt> EmbeddedInterfaceModel::getInternalDataPerElem(const std::string & field_name,
-                                                                    const ElementKind & kind) {
-  if (!(this->isInternal(field_name,kind))) AKANTU_EXCEPTION("unknown internal " << field_name);
-
-  for (UInt m = 0; m < materials.size() ; ++m) {
-    if (materials[m]->isInternal(field_name, kind)) {
-      Material * mat = NULL;
-
-      switch(this->spatial_dimension) {
-        case 1:
-          mat = dynamic_cast<MaterialReinforcement<1> *>(materials[m]);
-          break;
-
-        case 2:
-          mat = dynamic_cast<MaterialReinforcement<2> *>(materials[m]);
-          break;
-
-        case 3:
-          mat = dynamic_cast<MaterialReinforcement<3> *>(materials[m]);
-          break;
-      }
-
-      if (mat == NULL && field_name != "stress_embedded")
-        return materials[m]->getInternalDataPerElem(field_name,kind);
-      else if (mat != NULL && field_name == "stress_embedded")
-        return mat->getInternalDataPerElem(field_name, kind, "EmbeddedInterfaceFEEngine");
-    }
-  }
-
-  return ElementTypeMap<UInt>();
-}
-
 void EmbeddedInterfaceModel::addDumpGroupFieldToDumper(const std::string & dumper_name,
                                                        const std::string & field_id,
                                                        const std::string & group_name,
                                                        const ElementKind & element_kind,
                                                        bool padding_flag) {
 #ifdef AKANTU_USE_IOHELPER
   dumper::Field * field = NULL;
 
-  if (field_id == "stress_embedded")
+  if (dumper_name == "reinforcement" &&
+      (field_id == "stress_embedded"  ||
+       field_id == "inelastic_strain" ||
+       field_id == "material_index"))
     field = this->createElementalField(field_id, group_name, padding_flag, 1, element_kind);
   else
     SolidMechanicsModel::addDumpGroupFieldToDumper(dumper_name, field_id, group_name, element_kind, padding_flag);
 
   if (field) {
     DumperIOHelper & dumper = mesh.getGroupDumper(dumper_name,group_name);
     Model::addDumpGroupFieldToDumper(field_id,field,dumper);
   }
 
 #endif
 }
 
 __END_AKANTU__
 
diff --git a/src/model/solid_mechanics/embedded_interface_model.hh b/src/model/solid_mechanics/embedded_interface_model.hh
index ceafa6ffe..bfaed5e8f 100644
--- a/src/model/solid_mechanics/embedded_interface_model.hh
+++ b/src/model/solid_mechanics/embedded_interface_model.hh
@@ -1,160 +1,153 @@
 /**
  * @file   embedded_interface_model.hh
  *
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @date creation: Mon Mar 9 2015
  * @date last modification: Mon Mar 9 2015
  *
  * @brief  Model of Solid Mechanics with embedded interfaces
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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_EMBEDDED_INTERFACE_MODEL_HH__
 #define __AKANTU_EMBEDDED_INTERFACE_MODEL_HH__
 
 #include "aka_common.hh"
 
 #include "solid_mechanics_model.hh"
 #include "mesh.hh"
 
 #include "embedded_interface_intersector.hh"
 
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 /// Options for the EmbeddedInterfaceModel
 struct EmbeddedInterfaceModelOptions : SolidMechanicsModelOptions {
   EmbeddedInterfaceModelOptions(AnalysisMethod analysis_method = _explicit_lumped_mass,
                                 bool no_init_intersections = false,
                                 bool no_init_materials = false):
     SolidMechanicsModelOptions(analysis_method, no_init_materials),
     no_init_intersections(no_init_intersections)
   {}
 
   bool no_init_intersections;
 };
 
 extern const EmbeddedInterfaceModelOptions default_embedded_interface_model_options;
 
 /**
  * @brief Solid mechanics model using the embedded model.
  *
  * This SolidMechanicsModel subclass implements the embedded model,
  * a method used to represent 1D elements in a finite elements model
  * (eg. reinforcements in concrete).
  *
  * In addition to the SolidMechanicsModel properties, this model has
  * a mesh of the 1D elements embedded in the model, and an instance of the
  * EmbeddedInterfaceIntersector class for the computation of the intersections of the
  * 1D elements with the background (bulk) mesh.
  *
  * @see MaterialReinforcement
  */
 class EmbeddedInterfaceModel : public SolidMechanicsModel {
 
   typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular> MyFEEngineType;
 
 
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   /**
    * @brief Constructor
    *
    * @param mesh main mesh (concrete)
    * @param primitive_mesh mesh of the embedded reinforcement
    */
   EmbeddedInterfaceModel(Mesh & mesh,
                          Mesh & primitive_mesh,
                          UInt spatial_dimension = _all_dimensions,
                          const ID & id = "embedded_interface_model",
                          const MemoryID & memory_id = 0);
 
   /// Destructor
   virtual ~EmbeddedInterfaceModel();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// Initialise the model
   virtual void initFull(const ModelOptions & options = default_embedded_interface_model_options);
 
   /// Initialise the materials
   virtual void initMaterials();
 
-#ifndef SWIG
-  /// give the amount of data per element
-  ElementTypeMap<UInt> getInternalDataPerElem(const std::string & field_name,
-                                              const ElementKind & kind);
-#endif
-
   virtual void addDumpGroupFieldToDumper(const std::string & dumper_name,
                                          const std::string & field_id,
                                          const std::string & group_name,
                                          const ElementKind & element_kind,
                                          bool padding_flag);
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// get interface mesh
   AKANTU_GET_MACRO(InterfaceMesh, *interface_mesh, Mesh &);
 
   /// get associated elements
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(InterfaceAssociatedElements,
                                    interface_mesh->getData<Element>("associated_element"),
                                    Element);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
+  /// Intersector object to build the interface mesh
+  EmbeddedInterfaceIntersector intersector;
+
   /// Interface mesh (weak reference)
   Mesh * interface_mesh;
 
   /// Mesh used to create the CGAL primitives for intersections
   Mesh & primitive_mesh;
 
   /// Material selector for interface
   MaterialSelector * interface_material_selector;
-  
-  /// Intersector object to build the interface mesh
-  EmbeddedInterfaceIntersector intersector;
-
 };
 
 template<typename T>
 class InterfaceMeshDataMaterialSelector : public ElementDataMaterialSelector<T> {
 public:
   InterfaceMeshDataMaterialSelector(const std::string & name, const EmbeddedInterfaceModel & model, UInt first_index = 1) :
     ElementDataMaterialSelector<T>(model.getInterfaceMesh().getData<T>(name), model, first_index)
   {}
 };
 
 __END_AKANTU__
 
 #endif // __AKANTU_EMBEDDED_INTERFACE_MODEL_HH__
diff --git a/src/model/solid_mechanics/material.cc b/src/model/solid_mechanics/material.cc
index 2a3041210..d40ae7712 100644
--- a/src/model/solid_mechanics/material.cc
+++ b/src/model/solid_mechanics/material.cc
@@ -1,1667 +1,1710 @@
 /**
  * @file   material.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  *
  * @date creation: Tue Jul 27 2010
  * @date last modification: Tue Sep 16 2014
  *
  * @brief  Implementation of the common part of the material class
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material.hh"
 #include "solid_mechanics_model.hh"
 #include "sparse_matrix.hh"
 #include "dof_synchronizer.hh"
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 Material::Material(SolidMechanicsModel & model, const ID & id) :
   Memory(id, model.getMemoryID()),
   Parsable(_st_material, id),
   is_init(false),
   finite_deformation(false),
   name(""),
   model(&model),
   spatial_dimension(this->model->getSpatialDimension()),
   element_filter("element_filter", id, this->memory_id),
   stress("stress", *this),
   eigenstrain("eigenstrain", *this),
   gradu("grad_u", *this),
   green_strain("green_strain",*this),
   piola_kirchhoff_2("piola_kirchhoff_2", *this),
   //  potential_energy_vector(false),
   potential_energy("potential_energy", *this),
   is_non_local(false),
   use_previous_stress(false),
   use_previous_gradu(false),
   interpolation_inverse_coordinates("interpolation inverse coordinates", *this),
   interpolation_points_matrices("interpolation points matrices", *this) {
   AKANTU_DEBUG_IN();
 
   /// for each connectivity types allocate the element filer array of the material
   model.getMesh().initElementTypeMapArray(element_filter,
 					 1,
 					 spatial_dimension,
 					 false,
 					 _ek_regular);
 
 
-  registerParam("rho"                  , rho                  , 0.           , _pat_parsable | _pat_modifiable, "Density");
-  registerParam("name"                 , name                 , std::string(), _pat_parsable | _pat_readable);
-  registerParam("finite_deformation"   , finite_deformation   , false        , _pat_parsable | _pat_readable, "Is finite deformation");
-  registerParam("inelastic_deformation", inelastic_deformation, false        ,  _pat_internal, "Is inelastic deformation");
+  this->initialize();
+  AKANTU_DEBUG_OUT();
+}
 
-  /// allocate gradu stress for local elements
-  eigenstrain.initialize(spatial_dimension * spatial_dimension);
-  gradu.initialize(spatial_dimension * spatial_dimension);
-  stress.initialize(spatial_dimension * spatial_dimension);
+/* -------------------------------------------------------------------------- */
+Material::Material(SolidMechanicsModel & model,
+                   UInt dim,
+                   const Mesh & mesh,
+                   FEEngine & fe_engine,
+                   const ID & id) :
+  Memory(id, model.getMemoryID()),
+  Parsable(_st_material, id),
+  is_init(false),
+  finite_deformation(false),
+  name(""),
+  model(&model),
+  spatial_dimension(dim),
+  element_filter("element_filter", id, this->memory_id),
+  stress("stress", *this, dim, fe_engine, this->element_filter),
+  eigenstrain("eignestrain", *this, dim, fe_engine, this->element_filter),
+  gradu("gradu", *this, dim, fe_engine, this->element_filter),
+  green_strain("green_strain", *this, dim, fe_engine, this->element_filter),
+  piola_kirchhoff_2("poila_kirchhoff_2", *this, dim, fe_engine, this->element_filter),
+  potential_energy("potential_energy", *this, dim, fe_engine, this->element_filter),
+  is_non_local(false),
+  use_previous_stress(false),
+  use_previous_gradu(false),
+  interpolation_inverse_coordinates("interpolation inverse_coordinates", *this,
+                                    dim, fe_engine, this->element_filter),
+  interpolation_points_matrices("interpolation points matrices", *this,
+                                dim, fe_engine, this->element_filter) {
 
-  model.registerEventHandler(*this);
+  AKANTU_DEBUG_IN();
+  mesh.initElementTypeMapArray(element_filter,
+                               1,
+                               spatial_dimension,
+                               false,
+                               _ek_regular);
 
+  this->initialize();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Material::~Material() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
+/* -------------------------------------------------------------------------- */
+void Material::initialize() {
+  registerParam("rho"                  , rho                  , 0.           , _pat_parsable | _pat_modifiable, "Density");
+  registerParam("name"                 , name                 , std::string(), _pat_parsable | _pat_readable);
+  registerParam("finite_deformation"   , finite_deformation   , false        , _pat_parsable | _pat_readable, "Is finite deformation");
+  registerParam("inelastic_deformation", inelastic_deformation, false        ,  _pat_internal, "Is inelastic deformation");
+
+  /// allocate gradu stress for local elements
+  eigenstrain.initialize(spatial_dimension * spatial_dimension);
+  gradu.initialize(spatial_dimension * spatial_dimension);
+  stress.initialize(spatial_dimension * spatial_dimension);
+
+  this->model->registerEventHandler(*this);
+}
+
 /* -------------------------------------------------------------------------- */
 void Material::initMaterial() {
   AKANTU_DEBUG_IN();
 
   if(finite_deformation) {
     this->piola_kirchhoff_2.initialize(spatial_dimension * spatial_dimension);
     if(use_previous_stress) this->piola_kirchhoff_2.initializeHistory();
     this->green_strain.initialize(spatial_dimension * spatial_dimension);
   }
 
   if(use_previous_stress) this->stress.initializeHistory();
   if(use_previous_gradu) this->gradu.initializeHistory();
 
   for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin();
        it != internal_vectors_real.end();
        ++it) it->second->resize();
 
   for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin();
        it != internal_vectors_uint.end();
        ++it) it->second->resize();
 
   is_init = true;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::savePreviousState() {
   AKANTU_DEBUG_IN();
 
   for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin();
        it != internal_vectors_real.end();
        ++it) {
     if(it->second->hasHistory()) it->second->saveCurrentValues();
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /**
  * Compute  the  residual  by  assembling  @f$\int_{e}  \sigma_e  \frac{\partial
  * \varphi}{\partial X} dX @f$
  *
  * @param[in] displacements nodes displacements
  * @param[in] ghost_type compute the residual for _ghost or _not_ghost element
  */
 void Material::updateResidual(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   computeAllStresses(ghost_type);
   assembleResidual(ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void Material::assembleResidual(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model->getSpatialDimension();
 
   if(!finite_deformation){
 
     Array<Real> & residual = const_cast<Array<Real> &>(model->getResidual());
 
     Mesh & mesh = model->getFEEngine().getMesh();
     Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type);
     Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension, ghost_type);
     for(; it != last_type; ++it) {
       const Array<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(*it, ghost_type);
       Array<UInt> & elem_filter = element_filter(*it, ghost_type);
 
       UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent();
       UInt nb_nodes_per_element       = Mesh::getNbNodesPerElement(*it);
       UInt nb_quadrature_points       = model->getFEEngine().getNbQuadraturePoints(*it, ghost_type);
 
       UInt nb_element = elem_filter.getSize();
       /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by @f$\mathbf{B}^t \mathbf{\sigma}_q@f$
       Array<Real> * sigma_dphi_dx =
 	new Array<Real>(nb_element*nb_quadrature_points,
 			size_of_shapes_derivatives, "sigma_x_dphi_/_dX");
 
       Array<Real> * shapesd_filtered =
 	new Array<Real>(0, size_of_shapes_derivatives, "filtered shapesd");
 
       FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered,
 			       *it, ghost_type, elem_filter);
 
       Array<Real> & stress_vect = stress(*it, ghost_type);
 
       Array<Real>::matrix_iterator sigma =
 	stress_vect.begin(spatial_dimension, spatial_dimension);
       Array<Real>::matrix_iterator B =
 	shapesd_filtered->begin(spatial_dimension, nb_nodes_per_element);
       Array<Real>::matrix_iterator Bt_sigma_it =
 	sigma_dphi_dx->begin(spatial_dimension, nb_nodes_per_element);
 
       for (UInt q = 0; q < nb_element*nb_quadrature_points; ++q, ++sigma, ++B, ++Bt_sigma_it)
 	Bt_sigma_it->mul<false,false>(*sigma, *B);
 
 
       delete shapesd_filtered;
 
       /**
        * compute @f$\int \sigma  * \frac{\partial \varphi}{\partial X}dX@f$ by  @f$ \sum_q \mathbf{B}^t
        * \mathbf{\sigma}_q \overline w_q J_q@f$
        */
       Array<Real> * int_sigma_dphi_dx = new Array<Real>(nb_element,
 							nb_nodes_per_element * spatial_dimension,
 							"int_sigma_x_dphi_/_dX");
 
       model->getFEEngine().integrate(*sigma_dphi_dx, *int_sigma_dphi_dx,
 				size_of_shapes_derivatives,
 				*it, ghost_type,
 				elem_filter);
       delete sigma_dphi_dx;
 
 
       /// assemble
       model->getFEEngine().assembleArray(*int_sigma_dphi_dx, residual,
 				    model->getDOFSynchronizer().getLocalDOFEquationNumbers(),
 				    residual.getNbComponent(),
 				    *it, ghost_type, elem_filter, -1);
       delete int_sigma_dphi_dx;
     }
 
   }
   else{
     switch (spatial_dimension){
     case 1:
       this->assembleResidual<1>(ghost_type);
       break;
     case 2:
       this->assembleResidual<2>(ghost_type);
       break;
     case 3:
       this->assembleResidual<3>(ghost_type);
       break;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Compute  the  stress from the gradu
  *
  * @param[in] current_position nodes postition + displacements
  * @param[in] ghost_type compute the residual for _ghost or _not_ghost element
  */
 void Material::computeAllStresses(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model->getSpatialDimension();
 
   Mesh::type_iterator it = model->getFEEngine().getMesh().firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = model->getFEEngine().getMesh().lastType(spatial_dimension, ghost_type);
 
   for(; it != last_type; ++it) {
     Array<UInt> & elem_filter = element_filter(*it, ghost_type);
     Array<Real> & gradu_vect = gradu(*it, ghost_type);
 
     /// compute @f$\nabla u@f$
     model->getFEEngine().gradientOnQuadraturePoints(model->getDisplacement(), gradu_vect,
 						    spatial_dimension,
 						    *it, ghost_type, elem_filter);
 
     gradu_vect -= eigenstrain(*it, ghost_type);
 
     /// compute @f$\mathbf{\sigma}_q@f$ from @f$\nabla u@f$
     computeStress(*it, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::computeAllCauchyStresses(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(finite_deformation,"The Cauchy stress can only be computed if you are working in finite deformation.");
 
   //resizeInternalArray(stress);
 
   Mesh::type_iterator it = model->getFEEngine().getMesh().firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = model->getFEEngine().getMesh().lastType(spatial_dimension, ghost_type);
 
   for(; it != last_type; ++it)
     switch (spatial_dimension){
     case 1:
       this->computeCauchyStress<1>(*it, ghost_type);
       break;
     case 2:
       this->computeCauchyStress<2>(*it, ghost_type);
       break;
     case 3:
       this->computeCauchyStress<3>(*it, ghost_type);
       break;
     }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 void Material::computeCauchyStress(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Array<Real>::matrix_iterator gradu_it =
     this->gradu(el_type, ghost_type).begin(dim, dim);
 
   Array<Real>::matrix_iterator gradu_end =
     this->gradu(el_type, ghost_type).end(dim, dim);
 
   Array<Real>::matrix_iterator piola_it =
     this->piola_kirchhoff_2(el_type, ghost_type).begin(dim, dim);
 
   Array<Real>::matrix_iterator stress_it =
     this->stress(el_type, ghost_type).begin(dim, dim);
 
   Matrix<Real> F_tensor(dim, dim);
 
   for (; gradu_it != gradu_end; ++gradu_it, ++piola_it, ++stress_it) {
     Matrix<Real> & grad_u = *gradu_it;
     Matrix<Real> & piola  = *piola_it;
     Matrix<Real> & sigma  = *stress_it;
 
     gradUToF<dim > (grad_u, F_tensor);
     this->computeCauchyStressOnQuad<dim >(F_tensor, piola, sigma);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::setToSteadyState(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   const Array<Real> & displacement = model->getDisplacement();
 
   //resizeInternalArray(gradu);
 
   UInt spatial_dimension = model->getSpatialDimension();
 
   Mesh::type_iterator it = model->getFEEngine().getMesh().firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = model->getFEEngine().getMesh().lastType(spatial_dimension, ghost_type);
 
   for(; it != last_type; ++it) {
     Array<UInt> & elem_filter = element_filter(*it, ghost_type);
     Array<Real> & gradu_vect = gradu(*it, ghost_type);
 
     /// compute @f$\nabla u@f$
     model->getFEEngine().gradientOnQuadraturePoints(displacement, gradu_vect,
 					       spatial_dimension,
 					       *it, ghost_type, elem_filter);
 
     setToSteadyState(*it, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /**
  * Compute  the stiffness  matrix by  assembling @f$\int_{\omega}  B^t  \times D
  * \times B d\omega @f$
  *
  * @param[in] current_position nodes postition + displacements
  * @param[in] ghost_type compute the residual for _ghost or _not_ghost element
  */
 void Material::assembleStiffnessMatrix(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model->getSpatialDimension();
 
   Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension, ghost_type);
   for(; it != last_type; ++it) {
     if(finite_deformation){
       switch (spatial_dimension) {
       case 1:
 	{
 	  assembleStiffnessMatrixNL < 1 > (*it, ghost_type);
 	  assembleStiffnessMatrixL2 < 1 > (*it, ghost_type);
 	  break;
 	}
       case 2:
 	{
 	  assembleStiffnessMatrixNL < 2 > (*it, ghost_type);
 	  assembleStiffnessMatrixL2 < 2 > (*it, ghost_type);
 	  break;
 	}
       case 3:
 	{
 	  assembleStiffnessMatrixNL < 3 > (*it, ghost_type);
 	  assembleStiffnessMatrixL2 < 3 > (*it, ghost_type);
 	  break;
 	}
       }
     } else {
       switch(spatial_dimension) {
       case 1: { assembleStiffnessMatrix<1>(*it, ghost_type); break; }
       case 2: { assembleStiffnessMatrix<2>(*it, ghost_type); break; }
       case 3: { assembleStiffnessMatrix<3>(*it, ghost_type); break; }
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 void Material::assembleStiffnessMatrix(const ElementType & type,
 				       GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   SparseMatrix & K = const_cast<SparseMatrix &>(model->getStiffnessMatrix());
 
   const Array<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(type,
 										ghost_type);
 
   Array<UInt> & elem_filter = element_filter(type, ghost_type);
   Array<Real> & gradu_vect = gradu(type, ghost_type);
 
   UInt nb_element           = elem_filter.getSize();
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
   UInt nb_quadrature_points = model->getFEEngine().getNbQuadraturePoints(type,
 								    ghost_type);
 
   gradu_vect.resize(nb_quadrature_points * nb_element);
 
   model->getFEEngine().gradientOnQuadraturePoints(model->getDisplacement(),
 					     gradu_vect, dim, type, ghost_type,
 					     elem_filter);
 
   UInt tangent_size = getTangentStiffnessVoigtSize(dim);
 
   Array<Real> * tangent_stiffness_matrix =
     new Array<Real>(nb_element*nb_quadrature_points, tangent_size * tangent_size,
 		    "tangent_stiffness_matrix");
 
   tangent_stiffness_matrix->clear();
 
   computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type);
 
   Array<Real> * shapesd_filtered =
     new Array<Real>(0, dim * nb_nodes_per_element, "filtered shapesd");
 
   FEEngine::filterElementalData(model->getFEEngine().getMesh(), shapes_derivatives,
 			   *shapesd_filtered, type, ghost_type, elem_filter);
 
 
   /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
   UInt bt_d_b_size = dim * 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");
 
   Matrix<Real> B(tangent_size, dim * nb_nodes_per_element);
   Matrix<Real> Bt_D(dim * nb_nodes_per_element, tangent_size);
 
   Array<Real>::matrix_iterator shapes_derivatives_filtered_it =
     shapesd_filtered->begin(dim, nb_nodes_per_element);
 
   Array<Real>::matrix_iterator Bt_D_B_it
     = bt_d_b->begin(dim*nb_nodes_per_element, dim*nb_nodes_per_element);
 
   Array<Real>::matrix_iterator D_it
     = tangent_stiffness_matrix->begin(tangent_size, tangent_size);
 
   Array<Real>::matrix_iterator D_end
     = tangent_stiffness_matrix->end  (tangent_size, tangent_size);
 
 
   for(; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_filtered_it) {
     Matrix<Real> & D = *D_it;
     Matrix<Real> & Bt_D_B = *Bt_D_B_it;
 
     VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(
 						       *shapes_derivatives_filtered_it, B, nb_nodes_per_element);
     Bt_D.mul<true, false>(B, D);
     Bt_D_B.mul<false, false>(Bt_D, B);
   }
 
   delete tangent_stiffness_matrix;
   delete shapesd_filtered;
 
   /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
   Array<Real> * K_e = new Array<Real>(nb_element,
 				      bt_d_b_size * bt_d_b_size,
 				      "K_e");
 
   model->getFEEngine().integrate(*bt_d_b, *K_e,
 			    bt_d_b_size * bt_d_b_size,
 			    type, ghost_type,
 			    elem_filter);
 
   delete bt_d_b;
 
   model->getFEEngine().assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type,
 				 elem_filter);
   delete K_e;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 void Material::assembleStiffnessMatrixNL(const ElementType & type,
 					 GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   SparseMatrix & K = const_cast<SparseMatrix &> (model->getStiffnessMatrix());
 
   const Array<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(type, ghost_type);
 
   Array<UInt> & elem_filter = element_filter(type, ghost_type);
   //Array<Real> & gradu_vect = delta_gradu(type, ghost_type);
 
   UInt nb_element = elem_filter.getSize();
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
   UInt nb_quadrature_points = model->getFEEngine().getNbQuadraturePoints(type, ghost_type);
 
   //gradu_vect.resize(nb_quadrature_points * nb_element);
 
   // model->getFEEngine().gradientOnQuadraturePoints(model->getIncrement(), gradu_vect,
   //        dim, type, ghost_type, &elem_filter);
 
   Array<Real> * shapes_derivatives_filtered = new Array<Real > (nb_element * nb_quadrature_points,
 								dim * nb_nodes_per_element,
 								"shapes derivatives filtered");
 
 
   Array<Real>::const_matrix_iterator shapes_derivatives_it = shapes_derivatives.begin(spatial_dimension,
 											       nb_nodes_per_element);
 
   Array<Real>::matrix_iterator shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension,
 													    nb_nodes_per_element);
   UInt * elem_filter_val = elem_filter.storage();
   for (UInt e = 0; e < nb_element; ++e, ++elem_filter_val)
     for (UInt q = 0; q < nb_quadrature_points; ++q, ++shapes_derivatives_filtered_it)
       *shapes_derivatives_filtered_it = shapes_derivatives_it[*elem_filter_val * nb_quadrature_points + q];
 
   /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
   UInt bt_s_b_size = dim * nb_nodes_per_element;
 
   Array<Real> * bt_s_b = new Array<Real > (nb_element * nb_quadrature_points,
 					   bt_s_b_size * bt_s_b_size,
 					   "B^t*D*B");
 
   UInt piola_matrix_size = getCauchyStressMatrixSize(dim);
 
   Matrix<Real> B(piola_matrix_size, bt_s_b_size);
   Matrix<Real> Bt_S(bt_s_b_size, piola_matrix_size);
   Matrix<Real> S(piola_matrix_size, piola_matrix_size);
 
   shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element);
 
   Array<Real>::matrix_iterator Bt_S_B_it = bt_s_b->begin(bt_s_b_size,
 								  bt_s_b_size);
   Array<Real>::matrix_iterator Bt_S_B_end = bt_s_b->end(bt_s_b_size,
 								 bt_s_b_size);
 
   Array<Real>::matrix_iterator piola_it = piola_kirchhoff_2(type, ghost_type).begin(dim, dim);
 
   for (; Bt_S_B_it != Bt_S_B_end; ++Bt_S_B_it, ++shapes_derivatives_filtered_it, ++piola_it) {
     Matrix<Real> & Bt_S_B = *Bt_S_B_it;
     Matrix<Real> & Piola_kirchhoff_matrix = *piola_it;
 
     setCauchyStressMatrix< dim >(Piola_kirchhoff_matrix, S);
     VoigtHelper<dim>::transferBMatrixToBNL(*shapes_derivatives_filtered_it, B, nb_nodes_per_element);
     Bt_S.mul < true, false > (B, S);
     Bt_S_B.mul < false, false > (Bt_S, B);
   }
 
   delete shapes_derivatives_filtered;
 
   /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
   Array<Real> * K_e = new Array<Real > (nb_element,
 					bt_s_b_size * bt_s_b_size,
 					"K_e");
 
   model->getFEEngine().integrate(*bt_s_b, *K_e,
 			    bt_s_b_size * bt_s_b_size,
 			    type, ghost_type,
 			    elem_filter);
 
   delete bt_s_b;
 
   model->getFEEngine().assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, elem_filter);
   delete K_e;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 void Material::assembleStiffnessMatrixL2(const ElementType & type,
 					 GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   SparseMatrix & K = const_cast<SparseMatrix &> (model->getStiffnessMatrix());
 
   const Array<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(type, ghost_type);
 
   Array<UInt> & elem_filter = element_filter(type, ghost_type);
   Array<Real> & gradu_vect = gradu(type, ghost_type);
 
   UInt nb_element = elem_filter.getSize();
   UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
   UInt nb_quadrature_points = model->getFEEngine().getNbQuadraturePoints(type, ghost_type);
 
   gradu_vect.resize(nb_quadrature_points * nb_element);
 
   model->getFEEngine().gradientOnQuadraturePoints(model->getDisplacement(), gradu_vect,
 					     dim, type, ghost_type, elem_filter);
 
   UInt tangent_size = getTangentStiffnessVoigtSize(dim);
 
   Array<Real> * tangent_stiffness_matrix =
     new Array<Real > (nb_element*nb_quadrature_points, tangent_size * tangent_size,
 		      "tangent_stiffness_matrix");
 
   tangent_stiffness_matrix->clear();
 
   computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type);
 
 
   Array<Real> * shapes_derivatives_filtered = new Array<Real > (nb_element * nb_quadrature_points,
 								dim * nb_nodes_per_element,
 								"shapes derivatives filtered");
 
 
   Array<Real>::const_matrix_iterator shapes_derivatives_it = shapes_derivatives.begin(spatial_dimension,
 											       nb_nodes_per_element);
 
   Array<Real>::matrix_iterator shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension,
 													    nb_nodes_per_element);
   UInt * elem_filter_val = elem_filter.storage();
   for (UInt e = 0; e < nb_element; ++e, ++elem_filter_val)
     for (UInt q = 0; q < nb_quadrature_points; ++q, ++shapes_derivatives_filtered_it)
       *shapes_derivatives_filtered_it = shapes_derivatives_it[*elem_filter_val * nb_quadrature_points + q];
 
   /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
   UInt bt_d_b_size = dim * 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");
 
   Matrix<Real> B(tangent_size, dim * nb_nodes_per_element);
   Matrix<Real> B2(tangent_size, dim * nb_nodes_per_element);
   Matrix<Real> Bt_D(dim * nb_nodes_per_element, tangent_size);
 
   shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element);
 
   Array<Real>::matrix_iterator Bt_D_B_it = bt_d_b->begin(dim*nb_nodes_per_element,
 								  dim * nb_nodes_per_element);
 
   Array<Real>::matrix_iterator grad_u_it = gradu_vect.begin(dim, dim);
 
   Array<Real>::matrix_iterator D_it = tangent_stiffness_matrix->begin(tangent_size,
 									       tangent_size);
   Array<Real>::matrix_iterator D_end = tangent_stiffness_matrix->end(tangent_size,
 									      tangent_size);
 
 
   for (; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_filtered_it, ++grad_u_it) {
     Matrix<Real> & grad_u = *grad_u_it;
     Matrix<Real> & D = *D_it;
     Matrix<Real> & Bt_D_B = *Bt_D_B_it;
 
     //transferBMatrixToBL1<dim > (*shapes_derivatives_filtered_it, B, nb_nodes_per_element);
     VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B, nb_nodes_per_element);
     VoigtHelper<dim>::transferBMatrixToBL2(*shapes_derivatives_filtered_it, grad_u, B2, nb_nodes_per_element);
     B += B2;
     Bt_D.mul < true, false > (B, D);
     Bt_D_B.mul < false, false > (Bt_D, B);
   }
 
   delete tangent_stiffness_matrix;
   delete shapes_derivatives_filtered;
 
   /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
   Array<Real> * K_e = new Array<Real > (nb_element,
 					bt_d_b_size * bt_d_b_size,
 					"K_e");
 
   model->getFEEngine().integrate(*bt_d_b, *K_e,
 			    bt_d_b_size * bt_d_b_size,
 			    type, ghost_type,
 			    elem_filter);
 
   delete bt_d_b;
 
   model->getFEEngine().assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, elem_filter);
   delete K_e;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 void Material::assembleResidual(GhostType ghost_type){
 
   AKANTU_DEBUG_IN();
 
   Array<Real> & residual = const_cast<Array<Real> &> (model->getResidual());
 
   Mesh & mesh = model->getFEEngine().getMesh();
   Mesh::type_iterator it = element_filter.firstType(dim, ghost_type);
   Mesh::type_iterator last_type = element_filter.lastType(dim, ghost_type);
   for (; it != last_type; ++it) {
     const Array<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(*it, ghost_type);
 
     Array<UInt> & elem_filter = element_filter(*it, ghost_type);
 
     UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent();
     UInt nb_element = elem_filter.getSize();
     UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it);
     UInt nb_quadrature_points = model->getFEEngine().getNbQuadraturePoints(*it, ghost_type);
 
     Array<Real> * shapesd_filtered =
       new Array<Real>(0, size_of_shapes_derivatives, "filtered shapesd");
 
     FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered,
 			     *it, ghost_type, elem_filter);
 
     Array<Real>::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim,
 												   nb_nodes_per_element);
 
     //Set stress vectors
 
     UInt stress_size = getTangentStiffnessVoigtSize(dim);
 
     //Set matrices B and BNL*
     UInt bt_s_size = dim * nb_nodes_per_element;
 
     Array<Real> * bt_s = new Array<Real > (nb_element * nb_quadrature_points,
 					   bt_s_size,
 					   "B^t*S");
 
     Array<Real>::matrix_iterator grad_u_it = this->gradu(*it, ghost_type).begin(dim, dim);
 
     Array<Real>::matrix_iterator grad_u_end = this->gradu(*it, ghost_type).end(dim, dim);
 
     Array<Real>::matrix_iterator stress_it = this->piola_kirchhoff_2(*it, ghost_type).begin(dim, dim);
 
     shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element);
 
     Array<Real>::matrix_iterator bt_s_it = bt_s->begin(bt_s_size, 1);
 
     Matrix<Real> S_vect(stress_size, 1);
     Matrix<Real> B_tensor(stress_size, bt_s_size);
     Matrix<Real> B2_tensor(stress_size, bt_s_size);
 
     for (; grad_u_it != grad_u_end; ++grad_u_it, ++stress_it, ++shapes_derivatives_filtered_it, ++bt_s_it) {
       Matrix<Real> & grad_u = *grad_u_it;
       Matrix<Real> & r_it = *bt_s_it;
       Matrix<Real> & S_it = *stress_it;
 
       SetCauchyStressArray <dim> (S_it, S_vect);
       VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B_tensor, nb_nodes_per_element);
       VoigtHelper<dim>::transferBMatrixToBL2(*shapes_derivatives_filtered_it, grad_u, B2_tensor, nb_nodes_per_element);
 
       B_tensor += B2_tensor;
 
       r_it.mul < true, false > (B_tensor, S_vect);
     }
 
     delete shapesd_filtered;
 
     /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
     Array<Real> * r_e = new Array<Real > (nb_element,
 					  bt_s_size, "r_e");
 
     model->getFEEngine().integrate(*bt_s, *r_e,
 			      bt_s_size,
 			      *it, ghost_type,
 			      elem_filter);
 
     delete bt_s;
 
     model->getFEEngine().assembleArray(*r_e, residual,
 				  model->getDOFSynchronizer().getLocalDOFEquationNumbers(),
 				  residual.getNbComponent(),
 				  *it, ghost_type, elem_filter, -1);
 
     delete r_e;
 
   }
   AKANTU_DEBUG_OUT();
 
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::computeAllStressesFromTangentModuli(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model->getSpatialDimension();
 
   Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension, ghost_type);
   for(; it != last_type; ++it) {
     switch(spatial_dimension) {
     case 1: { computeAllStressesFromTangentModuli<1>(*it, ghost_type); break; }
     case 2: { computeAllStressesFromTangentModuli<2>(*it, ghost_type); break; }
     case 3: { computeAllStressesFromTangentModuli<3>(*it, ghost_type); break; }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 void Material::computeAllStressesFromTangentModuli(const ElementType & type,
 						   GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   const Array<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(type, ghost_type);
   Array<UInt> & elem_filter = element_filter(type, ghost_type);
   Array<Real> & gradu_vect = gradu(type, ghost_type);
 
   UInt nb_element                 = elem_filter.getSize();
   UInt nb_nodes_per_element       = Mesh::getNbNodesPerElement(type);
   UInt nb_quadrature_points       = model->getFEEngine().getNbQuadraturePoints(type, ghost_type);
 
 
   gradu_vect.resize(nb_quadrature_points * nb_element);
 
   Array<Real> & disp = model->getDisplacement();
 
   model->getFEEngine().gradientOnQuadraturePoints(disp, gradu_vect,
 					     dim, type, ghost_type, elem_filter);
 
   UInt tangent_moduli_size = getTangentStiffnessVoigtSize(dim);
 
   Array<Real> * tangent_moduli_tensors =
     new Array<Real>(nb_element*nb_quadrature_points, tangent_moduli_size * tangent_moduli_size,
 		    "tangent_moduli_tensors");
 
   tangent_moduli_tensors->clear();
   computeTangentModuli(type, *tangent_moduli_tensors, ghost_type);
 
   Array<Real> * shapesd_filtered =
     new Array<Real>(0, dim* nb_nodes_per_element, "filtered shapesd");
 
   FEEngine::filterElementalData(model->getFEEngine().getMesh(), shapes_derivatives, *shapesd_filtered,
 			   type, ghost_type, elem_filter);
 
   Array<Real> filtered_u(nb_element, nb_nodes_per_element * spatial_dimension);
 
   FEEngine::extractNodalToElementField(model->getFEEngine().getMesh(), disp, filtered_u,
 				  type, ghost_type, elem_filter);
 
   /// compute @f$\mathbf{D} \mathbf{B} \mathbf{u}@f$
   Array<Real>::matrix_iterator shapes_derivatives_filtered_it =
     shapesd_filtered->begin(dim, nb_nodes_per_element);
 
   Array<Real>::matrix_iterator D_it  = tangent_moduli_tensors->begin(tangent_moduli_size,
 								     tangent_moduli_size);
   Array<Real>::matrix_iterator sigma_it  = stress(type, ghost_type).begin(spatial_dimension,
 									  spatial_dimension);
   Array<Real>::vector_iterator u_it = filtered_u.begin(spatial_dimension * nb_nodes_per_element);
 
   Matrix<Real> B(tangent_moduli_size, spatial_dimension * nb_nodes_per_element);
   Vector<Real> Bu(tangent_moduli_size);
   Vector<Real> DBu(tangent_moduli_size);
 
   for (UInt e = 0; e < nb_element; ++e, ++u_it) {
     for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it, ++shapes_derivatives_filtered_it, ++sigma_it) {
       Vector<Real> & u = *u_it;
       Matrix<Real> & sigma = *sigma_it;
       Matrix<Real> & D = *D_it;
 
       VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B, nb_nodes_per_element);
 
       Bu.mul<false>(B, u);
       DBu.mul<false>(D, Bu);
 
       // Voigt notation to full symmetric tensor
       for (UInt i = 0; i < dim; ++i) sigma(i, i) = DBu(i);
       if(dim == 2) {
 	sigma(0,1) = sigma(1,0) = DBu(2);
       } else if(dim == 3) {
 	sigma(1,2) = sigma(2,1) = DBu(3);
 	sigma(0,2) = sigma(2,0) = DBu(4);
 	sigma(0,1) = sigma(1,0) = DBu(5);
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void Material::computePotentialEnergyByElements() {
   AKANTU_DEBUG_IN();
 
   Mesh::type_iterator it = element_filter.firstType(spatial_dimension);
   Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension);
   for(; it != last_type; ++it) {
     computePotentialEnergy(*it);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::computePotentialEnergy(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   if(!potential_energy.exists(el_type, ghost_type)) {
       UInt nb_element = element_filter(el_type, ghost_type).getSize();
       UInt nb_quadrature_points = model->getFEEngine().getNbQuadraturePoints(el_type, _not_ghost);
 
       potential_energy.alloc(nb_element * nb_quadrature_points, 1,
 			     el_type, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 Real Material::getPotentialEnergy() {
   AKANTU_DEBUG_IN();
   Real epot = 0.;
 
   computePotentialEnergyByElements();
 
   /// integrate the potential energy for each type of elements
   Mesh::type_iterator it = element_filter.firstType(spatial_dimension);
   Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension);
   for(; it != last_type; ++it) {
 
     epot += model->getFEEngine().integrate(potential_energy(*it, _not_ghost), *it,
 				      _not_ghost, element_filter(*it, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return epot;
 }
 
 /* -------------------------------------------------------------------------- */
 Real Material::getPotentialEnergy(ElementType & type, UInt index) {
   AKANTU_DEBUG_IN();
   Real epot = 0.;
 
   Vector<Real> epot_on_quad_points(model->getFEEngine().getNbQuadraturePoints(type));
 
   computePotentialEnergyByElement(type, index, epot_on_quad_points);
 
   epot = model->getFEEngine().integrate(epot_on_quad_points, type, element_filter(type)(index));
 
   AKANTU_DEBUG_OUT();
   return epot;
 }
 
 /* -------------------------------------------------------------------------- */
 Real Material::getEnergy(std::string type) {
   AKANTU_DEBUG_IN();
   if(type == "potential") return getPotentialEnergy();
   AKANTU_DEBUG_OUT();
   return 0.;
 }
 
 /* -------------------------------------------------------------------------- */
 Real Material::getEnergy(std::string energy_id, ElementType type, UInt index) {
   AKANTU_DEBUG_IN();
   if(energy_id == "potential") return getPotentialEnergy(type, index);
   AKANTU_DEBUG_OUT();
   return 0.;
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::computeQuadraturePointsCoordinates(ElementTypeMapArray<Real> & quadrature_points_coordinates,
 						  const GhostType & ghost_type) const {
   AKANTU_DEBUG_IN();
 
   const Mesh & mesh = this->model->getMesh();
 
   Array<Real> nodes_coordinates(mesh.getNodes(), true);
   nodes_coordinates += this->model->getDisplacement();
 
   Mesh::type_iterator it = this->element_filter.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = this->element_filter.lastType(spatial_dimension, ghost_type);
   for(; it != last_type; ++it) {
     const Array<UInt> & elem_filter = this->element_filter(*it, ghost_type);
 
     UInt nb_element  = elem_filter.getSize();
     UInt nb_tot_quad = this->model->getFEEngine().getNbQuadraturePoints(*it, ghost_type) * nb_element;
 
     Array<Real> & quads = quadrature_points_coordinates(*it, ghost_type);
     quads.resize(nb_tot_quad);
 
     this->model->getFEEngine().interpolateOnQuadraturePoints(nodes_coordinates,
 							     quads, spatial_dimension,
 							     *it, ghost_type, elem_filter);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::initElementalFieldInterpolation(const ElementTypeMapArray<Real> & interpolation_points_coordinates) {
   AKANTU_DEBUG_IN();
   const Mesh & mesh = model->getFEEngine().getMesh();
 
   ElementTypeMapArray<Real> quadrature_points_coordinates("quadrature_points_coordinates_for_interpolation", getID());
   mesh.initElementTypeMapArray(quadrature_points_coordinates, spatial_dimension, spatial_dimension);
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType ghost_type = *gt;
 
     computeQuadraturePointsCoordinates(quadrature_points_coordinates, ghost_type);
 
     Mesh::type_iterator it   = element_filter.firstType(spatial_dimension, ghost_type);
     Mesh::type_iterator last = element_filter.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<Real> & interp_points_coord = interpolation_points_coordinates(type, ghost_type);
       UInt nb_interpolation_points_per_elem = interp_points_coord.getSize() / nb_element;
 
       AKANTU_DEBUG_ASSERT(interp_points_coord.getSize() % nb_element == 0,
 			  "Number of interpolation points is wrong");
 
 #define AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD(type)			\
       initElementalFieldInterpolation<type>(quadrature_points_coordinates(type, ghost_type), \
 					    interp_points_coord,	\
 					    nb_interpolation_points_per_elem, \
 					    ghost_type)			\
 
       AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD);
 #undef AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void Material::initElementalFieldInterpolation(const Array<Real> & quad_coordinates,
 					       const Array<Real> & interpolation_points_coordinates,
 					       const UInt nb_interpolation_points_per_elem,
 					       const GhostType ghost_type) {
   AKANTU_DEBUG_IN();
   Array<UInt> & elem_fil = element_filter(type, ghost_type);
   UInt nb_element = elem_fil.getSize();
   UInt nb_quad_per_element = model->getFEEngine().getNbQuadraturePoints(type, ghost_type);
 
   if(!interpolation_inverse_coordinates.exists(type, ghost_type))
     interpolation_inverse_coordinates.alloc(nb_element,
 					    nb_quad_per_element*nb_quad_per_element,
 					    type, ghost_type);
   else
     interpolation_inverse_coordinates(type, ghost_type).resize(nb_element);
 
   if(!interpolation_points_matrices.exists(type, ghost_type))
     interpolation_points_matrices.alloc(nb_element,
 					nb_interpolation_points_per_elem * nb_quad_per_element,
 					type, ghost_type);
   else
     interpolation_points_matrices(type, ghost_type).resize(nb_element);
 
   Array<Real> & interp_inv_coord = interpolation_inverse_coordinates(type, ghost_type);
   Array<Real> & interp_points_mat = interpolation_points_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 =
     quad_coordinates.begin_reinterpret(spatial_dimension,
 				       nb_quad_per_element,
 				       nb_element);
 
   Array<Real>::const_matrix_iterator points_coords_begin =
     interpolation_points_coordinates.begin_reinterpret(spatial_dimension,
 						       nb_interpolation_points_per_elem,
 						       interpolation_points_coordinates.getSize() / nb_interpolation_points_per_elem);
 
   Array<Real>::matrix_iterator inv_quad_coord_it =
     interp_inv_coord.begin(nb_quad_per_element, nb_quad_per_element);
 
   Array<Real>::matrix_iterator inv_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; ++el, ++inv_quad_coord_it,
 	 ++inv_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
     buildElementalFieldInterpolationCoodinates<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[elem_fil(el)];
     /// matrix to store the interpolation points coordinates
     /// compatible with these functions
     Matrix<Real> & inv_points_coord_matrix = *inv_points_mat_it;
 
     /// insert the quad coordinates in a matrix compatible with the interpolation
     buildElementalFieldInterpolationCoodinates<type>(points_coords,
 						     inv_points_coord_matrix);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::interpolateStress(ElementTypeMapArray<Real> & result,
 				 const GhostType ghost_type) {
   interpolateElementalField(stress, result, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::interpolateElementalField(const ElementTypeMapArray<Real> & field,
 					 ElementTypeMapArray<Real> & result,
 					 const GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Mesh::type_iterator it   = element_filter.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last = element_filter.lastType(spatial_dimension, ghost_type);
   for (; it != last; ++it) {
     ElementType type = *it;
 
     Array<UInt> & elem_fil = element_filter(type, ghost_type);
     UInt nb_element = elem_fil.getSize();
     UInt nb_quad_per_element = model->getFEEngine().getNbQuadraturePoints(type, ghost_type);
 
     const Array<Real> & field_vec = field(type, ghost_type);
     Array<Real> & result_vec = result(type, ghost_type);
 
     Matrix<Real> coefficients(nb_quad_per_element, field_vec.getNbComponent());
 
     const Array<Real> & interp_inv_coord = interpolation_inverse_coordinates(type, ghost_type);
     const Array<Real> & interp_points_coord = interpolation_points_matrices(type, ghost_type);
 
     UInt nb_interpolation_points_per_elem
       = interp_points_coord.getNbComponent() / nb_quad_per_element;
 
     Array<Real>::const_matrix_iterator field_it
       = field_vec.begin_reinterpret(field_vec.getNbComponent(),
 				    nb_quad_per_element,
 				    nb_element);
 
     Array<Real>::const_matrix_iterator interpolation_points_coordinates_it =
       interp_points_coord.begin(nb_interpolation_points_per_elem, nb_quad_per_element);
 
     Array<Real>::matrix_iterator result_begin
       = result_vec.begin_reinterpret(field_vec.getNbComponent(),
 				     nb_interpolation_points_per_elem,
 				     result_vec.getSize() / nb_interpolation_points_per_elem);
 
     Array<Real>::const_matrix_iterator inv_quad_coord_it =
       interp_inv_coord.begin(nb_quad_per_element, nb_quad_per_element);
 
     /// loop over the elements of the current material 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;
 
       /**
        * 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;
 
       /// multiply the coordinates matrix by the coefficients matrix and store the result
       Matrix<Real> res(result_begin[elem_fil(el)]);
       res.mul<true, true>(coefficients, coord);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::interpolateStressOnFacets(ElementTypeMapArray<Real> & result,
 					 const GhostType ghost_type) {
   interpolateElementalFieldOnFacets(stress, result, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::interpolateElementalFieldOnFacets(const ElementTypeMapArray<Real> & field,
 						 ElementTypeMapArray<Real> & result,
 						 const GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   UInt sp2 = spatial_dimension * spatial_dimension;
 
   const Mesh & mesh = this->model->getMesh();
   const Mesh & mesh_facets = mesh.getMeshFacets();
 
   Mesh::type_iterator it   = element_filter.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last = element_filter.lastType(spatial_dimension, ghost_type);
   for (; it != last; ++it) {
     ElementType type = *it;
 
     Array<UInt> & elem_fil = element_filter(type, ghost_type);
     UInt nb_element = elem_fil.getSize();
     UInt nb_quad_per_element = model->getFEEngine().getNbQuadraturePoints(type, ghost_type);
 
     const Array<Real> & field_vec = field(type, ghost_type);
 
     Matrix<Real> coefficients(nb_quad_per_element, field_vec.getNbComponent());
 
     const Array<Real> & interp_inv_coord = interpolation_inverse_coordinates(type, ghost_type);
     const Array<Real> & interp_points_coord = interpolation_points_matrices(type, ghost_type);
 
     UInt nb_interpolation_points_per_elem
       = interp_points_coord.getNbComponent() / nb_quad_per_element;
 
     Array<Real>::const_matrix_iterator field_it
       = field_vec.begin_reinterpret(field_vec.getNbComponent(),
 				    nb_quad_per_element,
 				    nb_element);
 
     Array<Real>::const_matrix_iterator interpolation_points_coordinates_it =
       interp_points_coord.begin(nb_interpolation_points_per_elem, nb_quad_per_element);
 
     Array<Real>::const_matrix_iterator inv_quad_coord_it =
       interp_inv_coord.begin(nb_quad_per_element, nb_quad_per_element);
 
     Matrix<Real> result_tmp(sp2, nb_interpolation_points_per_elem);
 
     const Array<Element> & facet_to_element =
       mesh_facets.getSubelementToElement(type, ghost_type);
     ElementType type_facet = Mesh::getFacetType(type);
     UInt nb_facet_per_elem = facet_to_element.getNbComponent();
     UInt nb_quad_per_facet = nb_interpolation_points_per_elem / nb_facet_per_elem;
     Element element_for_comparison(type, 0, ghost_type);
     const Array< std::vector<Element> > * element_to_facet = NULL;
     GhostType current_ghost_type = _casper;
     Array<Real> * result_vec = NULL;
 
     /// loop over the elements of the current material 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;
 
       /**
        * 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;
 
       /// multiply the coordinates matrix by the coefficients matrix and store the result
       result_tmp.mul<true, true>(coefficients, coord);
 
       UInt global_el = elem_fil(el);
       element_for_comparison.element = global_el;
       for (UInt f = 0; f < nb_facet_per_elem; ++f) {
 	Element facet_elem = facet_to_element(global_el, f);
 	UInt global_facet = facet_elem.element;
 	if (facet_elem.ghost_type != current_ghost_type) {
 	  current_ghost_type = facet_elem.ghost_type;
 	  element_to_facet = &mesh_facets.getElementToSubelement(type_facet,
 								 current_ghost_type);
 	  result_vec = &result(type_facet, current_ghost_type);
 	}
 
 	bool is_second_element = (*element_to_facet)(global_facet)[0] != element_for_comparison;
 
 	for (UInt q = 0; q < nb_quad_per_facet; ++q) {
 	  Vector<Real> result_local(result_vec->storage()
 				    + (global_facet * nb_quad_per_facet + q) * result_vec->getNbComponent()
 				    + is_second_element * sp2,
 				    sp2);
 
 	  result_local = result_tmp(f * nb_quad_per_facet + q);
 	}
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 const Array<Real> & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) const {
   std::stringstream sstr;
   std::string ghost_id = "";
   if (ghost_type == _ghost) ghost_id = ":ghost";
   sstr << getID() << ":" << vect_id << ":" << type << ghost_id;
 
   ID fvect_id = sstr.str();
   try {
     return Memory::getArray<Real>(fvect_id);
   } catch(debug::Exception & e) {
     AKANTU_EXCEPTION("The material " << name << "(" <<getID() << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]");
   }
 }
 
 /* -------------------------------------------------------------------------- */
 Array<Real> & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) {
   std::stringstream sstr;
   std::string ghost_id = "";
   if (ghost_type == _ghost) ghost_id = ":ghost";
   sstr << getID() << ":" << vect_id << ":" << type << ghost_id;
 
   ID fvect_id = sstr.str();
   try {
     return Memory::getArray<Real>(fvect_id);
   } catch(debug::Exception & e) {
     AKANTU_EXCEPTION("The material " << name << "(" << getID() << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]");
   }
 }
 
 /* -------------------------------------------------------------------------- */
 const InternalField<Real> & Material::getInternal(const ID & int_id) const {
   std::map<ID, InternalField<Real> *>::const_iterator it = internal_vectors_real.find(getID() + ":" + int_id);
   if(it == internal_vectors_real.end()) {
     AKANTU_EXCEPTION("The material " << name << "(" << getID()
 		     << ") does not contain an internal "
 		     << int_id << " (" << (getID() + ":" + int_id) << ")");
   }
   return *it->second;
 }
 
 /* -------------------------------------------------------------------------- */
 InternalField<Real> & Material::getInternal(const ID & int_id) {
   std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.find(getID() + ":" + int_id);
   if(it == internal_vectors_real.end()) {
     AKANTU_EXCEPTION("The material " << name << "(" << getID()
 		     << ") does not contain an internal "
 		     << int_id << " (" << (getID() + ":" + int_id) << ")");
   }
   return *it->second;
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::addElements(const Array<Element> & elements_to_add) {
   AKANTU_DEBUG_IN();
   UInt mat_id = model->getInternalIndexFromID(getID());
   Array<Element>::const_iterator<Element> el_begin = elements_to_add.begin();
   Array<Element>::const_iterator<Element> el_end   = elements_to_add.end();
   for(;el_begin != el_end; ++el_begin) {
     const Element & element = *el_begin;
     Array<UInt> & mat_indexes = model->getMaterialByElement     (element.type, element.ghost_type);
     Array<UInt> & mat_loc_num = model->getMaterialLocalNumbering(element.type, element.ghost_type);
 
     UInt index = this->addElement(element.type, element.element, element.ghost_type);
     mat_indexes(element.element) = mat_id;
     mat_loc_num(element.element) = index;
   }
 
   this->resizeInternals();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::removeElements(const Array<Element> & elements_to_remove) {
   AKANTU_DEBUG_IN();
 
   Array<Element>::const_iterator<Element> el_begin = elements_to_remove.begin();
   Array<Element>::const_iterator<Element> el_end   = elements_to_remove.end();
 
   if(el_begin==el_end)
     return;
 
   ElementTypeMapArray<UInt> material_local_new_numbering("remove mat filter elem", getID());
 
   Element element;
   for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) {
     GhostType ghost_type = *gt;
     element.ghost_type = ghost_type;
 
     ElementTypeMapArray<UInt>::type_iterator it  = element_filter.firstType(_all_dimensions, ghost_type, _ek_not_defined);
     ElementTypeMapArray<UInt>::type_iterator end = element_filter.lastType(_all_dimensions, ghost_type, _ek_not_defined);
 
     for(; it != end; ++it) {
       ElementType type = *it;
       element.type = type;
 
       Array<UInt> & elem_filter = this->element_filter(type, ghost_type);
       Array<UInt> & mat_loc_num = this->model->getMaterialLocalNumbering(type, ghost_type);
 
       if(!material_local_new_numbering.exists(type, ghost_type))
 	material_local_new_numbering.alloc(elem_filter.getSize(), 1, type, ghost_type);
       Array<UInt> & mat_renumbering = material_local_new_numbering(type, ghost_type);
 
       UInt nb_element = elem_filter.getSize();
       element.kind=(*el_begin).kind;
       Array<UInt> elem_filter_tmp;
 
       UInt new_id = 0;
       for (UInt el = 0; el < nb_element; ++el) {
 	element.element = elem_filter(el);
 
 	if(std::find(el_begin, el_end, element) == el_end) {
 	  elem_filter_tmp.push_back(element.element);
 
 	  mat_renumbering(el) = new_id;
 	  mat_loc_num(element.element) = new_id;
 	  ++new_id;
 	} else {
 	  mat_renumbering(el) = UInt(-1);
 	}
       }
 
       elem_filter.resize(elem_filter_tmp.getSize());
       elem_filter.copy(elem_filter_tmp);
     }
   }
 
   for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin();
        it != internal_vectors_real.end();
        ++it) it->second->removeQuadraturePoints(material_local_new_numbering);
 
   for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin();
        it != internal_vectors_uint.end();
        ++it) it->second->removeQuadraturePoints(material_local_new_numbering);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::resizeInternals() {
   AKANTU_DEBUG_IN();
   for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin();
        it != internal_vectors_real.end();
        ++it) it->second->resize();
 
   for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin();
        it != internal_vectors_uint.end();
        ++it) it->second->resize();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::onElementsAdded(__attribute__((unused)) const Array<Element> & element_list,
 			       __attribute__((unused)) const NewElementsEvent & event) {
   this->resizeInternals();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::onElementsRemoved(const Array<Element> & element_list,
 				 const ElementTypeMapArray<UInt> & new_numbering,
 				 __attribute__((unused)) const RemovedElementsEvent & event) {
   UInt my_num = model->getInternalIndexFromID(getID());
 
   ElementTypeMapArray<UInt> material_local_new_numbering("remove mat filter elem", getID());
 
   Array<Element>::const_iterator<Element> el_begin = element_list.begin();
   Array<Element>::const_iterator<Element> el_end   = element_list.end();
 
   for (ghost_type_t::iterator g = ghost_type_t::begin(); g != ghost_type_t::end(); ++g) {
     GhostType gt = *g;
 
     ElementTypeMapArray<UInt>::type_iterator it  = new_numbering.firstType(_all_dimensions, gt, _ek_not_defined);
     ElementTypeMapArray<UInt>::type_iterator end = new_numbering.lastType (_all_dimensions, gt, _ek_not_defined);
     for (; it != end; ++it) {
       ElementType type = *it;
       if(element_filter.exists(type, gt)){
 	Array<UInt> & elem_filter = element_filter(type, gt);
 
 	Array<UInt> & mat_indexes = this->model->getMaterialByElement     (*it, gt);
 	Array<UInt> & mat_loc_num = this->model->getMaterialLocalNumbering(*it, gt);
 	UInt nb_element = this->model->getMesh().getNbElement(type, gt);
 
 	// all materials will resize of the same size...
 	mat_indexes.resize(nb_element);
 	mat_loc_num.resize(nb_element);
 
 	if(!material_local_new_numbering.exists(type, gt))
 	  material_local_new_numbering.alloc(elem_filter.getSize(), 1, type, gt);
 
 	Array<UInt> & mat_renumbering = material_local_new_numbering(type, gt);
 	const Array<UInt> & renumbering = new_numbering(type, gt);
 	Array<UInt> elem_filter_tmp;
 	UInt ni = 0;
 	Element el;
 	el.type = type;
 	el.ghost_type = gt;
 	for (UInt i = 0; i < elem_filter.getSize(); ++i) {
 	  el.element = elem_filter(i);
 	  if(std::find(el_begin, el_end, el) == el_end) {
 	    UInt new_el = renumbering(el.element);
 	    AKANTU_DEBUG_ASSERT(new_el != UInt(-1), "A not removed element as been badly renumbered");
 	    elem_filter_tmp.push_back(new_el);
 	    mat_renumbering(i) = ni;
 
 	    mat_indexes(new_el) = my_num;
 	    mat_loc_num(new_el) = ni;
 	    ++ni;
 	  } else {
 	    mat_renumbering(i) = UInt(-1);
 	  }
 	}
 
 	elem_filter.resize(elem_filter_tmp.getSize());
 	elem_filter.copy(elem_filter);
       }
     }
   }
 
   for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin();
        it != internal_vectors_real.end();
        ++it) it->second->removeQuadraturePoints(material_local_new_numbering);
 
   for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin();
        it != internal_vectors_uint.end();
        ++it) it->second->removeQuadraturePoints(material_local_new_numbering);
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::onBeginningSolveStep(const AnalysisMethod & method) {
   this->savePreviousState();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::onEndSolveStep(const AnalysisMethod & method) {
   ElementTypeMapArray<UInt>::type_iterator it
     = this->element_filter.firstType(_all_dimensions, _not_ghost, _ek_not_defined);
   ElementTypeMapArray<UInt>::type_iterator end
     = element_filter.lastType(_all_dimensions, _not_ghost, _ek_not_defined);
 
   for(; it != end; ++it) {
     this->updateEnergies(*it, _not_ghost);
   }
 }
 /* -------------------------------------------------------------------------- */
 void Material::onDamageIteration() {
   this->savePreviousState();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::onDamageUpdate() {
   ElementTypeMapArray<UInt>::type_iterator it
     = this->element_filter.firstType(_all_dimensions, _not_ghost, _ek_not_defined);
   ElementTypeMapArray<UInt>::type_iterator end
     = element_filter.lastType(_all_dimensions, _not_ghost, _ek_not_defined);
 
   for(; it != end; ++it) {
 
     if(!this->potential_energy.exists(*it, _not_ghost)) {
       UInt nb_element = this->element_filter(*it, _not_ghost).getSize();
       UInt nb_quadrature_points = this->model->getFEEngine().getNbQuadraturePoints(*it, _not_ghost);
 
       this->potential_energy.alloc(nb_element * nb_quadrature_points, 1,
 				   *it, _not_ghost);
     }
     this->updateEnergiesAfterDamage(*it, _not_ghost);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::onDump(){
   if(this->isFiniteDeformation())
     this->computeAllCauchyStresses(_not_ghost);
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   std::string type = getID().substr(getID().find_last_of(":") + 1);
 
   stream << space << "Material " << type << " [" << std::endl;
   Parsable::printself(stream, indent);
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::flattenInternal(const std::string & field_id,
 			       ElementTypeMapArray<Real> & internal_flat,
 			       const GhostType ghost_type,
 			       ElementKind element_kind){
 
   typedef ElementTypeMapArray<UInt>::type_iterator iterator;
   iterator tit = this->element_filter.firstType(this->spatial_dimension,
 						ghost_type, element_kind);
   iterator end = this->element_filter.lastType(this->spatial_dimension,
 					       ghost_type, element_kind);
 
 
   for (; tit != end; ++tit) {
 
     ElementType type = *tit;
 
     try {
       __attribute__((unused)) const Array<Real> & src_vect
 	= this->getArray(field_id,type,ghost_type);
 
     } catch(debug::Exception & e) {
       continue;
     }
 
     const Array<Real> & src_vect = this->getArray(field_id,type,ghost_type);
     const Array<UInt> & filter   = this->element_filter(type,ghost_type);
 
     // total number of elements for a given type
     UInt nb_element = this->model->mesh.getNbElement(type,ghost_type);
     // number of filtered elements
     UInt nb_element_src = filter.getSize();
     // number of quadrature points per elem
     UInt nb_quad_per_elem = 0;
     // number of data per quadrature point
     UInt nb_data_per_quad = src_vect.getNbComponent();
 
     if (!internal_flat.exists(type,ghost_type)) {
       internal_flat.alloc(nb_element*nb_quad_per_elem,nb_data_per_quad,type,ghost_type);
     }
 
     if (nb_element_src == 0) continue;
     nb_quad_per_elem = (src_vect.getSize()/nb_element_src);
 
     // number of data per element
     UInt nb_data = nb_quad_per_elem * src_vect.getNbComponent();
 
     Array<Real> & dst_vect = internal_flat(type,ghost_type);
     dst_vect.resize(nb_element*nb_quad_per_elem);
 
     Array<UInt>::const_scalar_iterator it  = filter.begin();
     Array<UInt>::const_scalar_iterator end = filter.end();
     Array<Real>::const_vector_iterator it_src =
       src_vect.begin_reinterpret(nb_data,nb_element_src);
 
     Array<Real>::vector_iterator it_dst =
       dst_vect.begin_reinterpret(nb_data,nb_element);
 
     for (; it != end ; ++it,++it_src) {
       it_dst[*it] = *it_src;
     }
   }
 };
 /* -------------------------------------------------------------------------- */
 
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/material.hh b/src/model/solid_mechanics/material.hh
index c3e3dffb5..e61941c14 100644
--- a/src/model/solid_mechanics/material.hh
+++ b/src/model/solid_mechanics/material.hh
@@ -1,600 +1,616 @@
 /**
  * @file   material.hh
  *
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  *
  * @date creation: Tue Jul 27 2010
  * @date last modification: Tue Sep 16 2014
  *
  * @brief  Mother class for all materials
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "aka_memory.hh"
 #include "aka_voigthelper.hh"
 #include "parser.hh"
 #include "parsable.hh"
 #include "data_accessor.hh"
 #include "internal_field.hh"
 #include "random_internal_field.hh"
 #include "solid_mechanics_model_event_handler.hh"
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_HH__
 #define __AKANTU_MATERIAL_HH__
 
 /* -------------------------------------------------------------------------- */
 namespace akantu {
   class Model;
   class SolidMechanicsModel;
 }
 
 __BEGIN_AKANTU__
 
 /**
  * Interface of all materials
  * Prerequisites for a new material
  * - inherit from this class
  * - implement the following methods:
  * \code
  *  virtual Real getStableTimeStep(Real h, const Element & element = ElementNull);
  *
  *  virtual void computeStress(ElementType el_type,
  *                             GhostType ghost_type = _not_ghost);
  *
  *  virtual void computeTangentStiffness(const ElementType & el_type,
  *                                       Array<Real> & tangent_matrix,
  *                                       GhostType ghost_type = _not_ghost);
  * \endcode
  *
  */
 
 class Material : public Memory, public DataAccessor, public Parsable,
                  public MeshEventHandler,
                  protected SolidMechanicsModelEventHandler {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
+  /// Initialize material with defaults
   Material(SolidMechanicsModel & model, const ID & id = "");
+
+  /// Initialize material with custom mesh & fe_engine
+  Material(SolidMechanicsModel & model,
+           UInt dim,
+           const Mesh & mesh,
+           FEEngine & fe_engine,
+           const ID & id = "");
+
+  /// Destructor
   virtual ~Material();
 
+protected:
+  void initialize();
+
   /* ------------------------------------------------------------------------ */
   /* Function that materials can/should reimplement                           */
   /* ------------------------------------------------------------------------ */
 protected:
   /// constitutive law
   virtual void computeStress(__attribute__((unused)) ElementType el_type,
                              __attribute__((unused)) GhostType ghost_type = _not_ghost)  {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /// compute the tangent stiffness matrix
   virtual void computeTangentModuli(__attribute__((unused)) const ElementType & el_type,
                                     __attribute__((unused)) Array<Real> & tangent_matrix,
                                     __attribute__((unused)) GhostType ghost_type = _not_ghost) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /// compute the potential energy
   virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost);
 
   /// compute the potential energy for an element
   virtual void computePotentialEnergyByElement(__attribute__((unused)) ElementType type,
 					       __attribute__((unused)) UInt index,
                                                __attribute__((unused)) Vector<Real> & epot_on_quad_points) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   virtual void updateEnergies(__attribute__((unused)) ElementType el_type,
                               __attribute__((unused)) GhostType ghost_type = _not_ghost) {  }
 
   virtual void updateEnergiesAfterDamage(__attribute__((unused)) ElementType el_type,
 					 __attribute__((unused)) GhostType ghost_type = _not_ghost) {}
 
   /// set the material to steady state (to be implemented for materials that need it)
   virtual void setToSteadyState(__attribute__((unused)) ElementType el_type,
                                 __attribute__((unused)) GhostType ghost_type = _not_ghost) {  }
 
   /// function called to update the internal parameters when the modifiable
   /// parameters are modified
   virtual void updateInternalParameters() {}
 
 public:
 
   /// compute the p-wave speed in the material
   virtual Real getPushWaveSpeed(const Element & element) const { AKANTU_DEBUG_TO_IMPLEMENT(); }
 
   /// compute the s-wave speed in the material
   virtual Real getShearWaveSpeed(const Element & element) const { AKANTU_DEBUG_TO_IMPLEMENT(); }
 
   /// get a material celerity to compute the stable time step (default: is the push wave speed)
   virtual Real getCelerity(const Element & element) const { return getPushWaveSpeed(element); }
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   template<typename T>
   void registerInternal(__attribute__((unused)) InternalField<T> & vect) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   template<typename T>
   void unregisterInternal(__attribute__((unused)) InternalField<T> & vect) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /// initialize the material computed parameter
   virtual void initMaterial();
 
   /// compute the residual for this material
   virtual void updateResidual(GhostType ghost_type = _not_ghost);
 
   /// assemble the residual for this material
   virtual void assembleResidual(GhostType ghost_type);
 
   /// Operations before and after solveStep in implicit
   virtual void beforeSolveStep() {}
   virtual void afterSolveStep() {}
 
   /// save the stress in the previous_stress if needed
   virtual void savePreviousState();
 
   /// compute the stresses for this material
   virtual void computeAllStresses(GhostType ghost_type = _not_ghost);
   virtual void computeAllNonLocalStresses(__attribute__((unused)) GhostType ghost_type = _not_ghost) {};
   virtual void computeAllStressesFromTangentModuli(GhostType ghost_type = _not_ghost);
   virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost);
 
   /// set material to steady state
   void setToSteadyState(GhostType ghost_type = _not_ghost);
 
   /// compute the stiffness matrix
   virtual void assembleStiffnessMatrix(GhostType ghost_type);
 
   /// add an element to the local mesh filter
   inline UInt addElement(const ElementType & type,
                          UInt element,
                          const GhostType & ghost_type);
 
   /// add many elements at once
   void addElements(const Array<Element> & elements_to_add);
 
   /// remove many element at once
   void removeElements(const Array<Element> & elements_to_remove);
 
   /// function to print the contain of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /**
    * interpolate stress on given positions for each element by means
    * of a geometrical interpolation on quadrature points
    */
   void interpolateStress(ElementTypeMapArray<Real> & result,
                          const GhostType ghost_type = _not_ghost);
 
   /**
    * interpolate stress on given positions for each element by means
    * of a geometrical interpolation on quadrature points and store the
    * results per facet
    */
   void interpolateStressOnFacets(ElementTypeMapArray<Real> & result,
 				 const GhostType ghost_type = _not_ghost);
 
   /**
    * function to initialize the elemental field interpolation
    * function by inverting the quadrature points' coordinates
    */
   void initElementalFieldInterpolation(const ElementTypeMapArray<Real> & interpolation_points_coordinates);
 
   /* ------------------------------------------------------------------------ */
   /* Common part                                                              */
   /* ------------------------------------------------------------------------ */
 protected:
   /// assemble the residual
   template<UInt dim>
   void assembleResidual(GhostType ghost_type);
 
   /// Computation of Cauchy stress tensor in the case of finite deformation
   template<UInt dim>
   void computeCauchyStress(__attribute__((unused)) ElementType el_type,
                            __attribute__((unused)) GhostType ghost_type = _not_ghost);
 
   template<UInt dim >
   inline void computeCauchyStressOnQuad(const Matrix<Real> & F, const Matrix<Real> & S,
 					Matrix<Real> & cauchy,
                                         const Real & C33 = 1.0 ) const;
 
   template<UInt dim>
   void computeAllStressesFromTangentModuli(const ElementType & type,
 					   GhostType ghost_type);
 
   template<UInt dim>
   void assembleStiffnessMatrix(const ElementType & type,
                                GhostType ghost_type);
 
   /// assembling in finite deformation
   template<UInt dim>
   void assembleStiffnessMatrixNL(const ElementType & type,
                                  GhostType ghost_type);
 
   template<UInt dim>
   void assembleStiffnessMatrixL2(const ElementType & type,
                                  GhostType ghost_type);
 
   /// write the stress tensor in the Voigt notation.
   template<UInt dim>
   inline void SetCauchyStressArray(const Matrix<Real> & S_t, Matrix<Real> & Stress_vect);
 
   inline UInt getTangentStiffnessVoigtSize(UInt spatial_dimension) const;
 
   /// Size of the Stress matrix for the case of finite deformation see: Bathe et al, IJNME, Vol 9, 353-386, 1975
   inline UInt getCauchyStressMatrixSize(UInt spatial_dimension) const;
 
   /// Sets the stress matrix according to Bathe et al, IJNME, Vol 9, 353-386, 1975
   template<UInt dim>
   inline void setCauchyStressMatrix(const Matrix<Real> & S_t,
 				    Matrix<Real> & Stress_matrix);
 
   /// compute the potential energy by element
   void computePotentialEnergyByElements();
 
   /// resize the intenals arrays
   virtual void resizeInternals();
 
 public:
   /// compute the coordinates of the quadrature points
   void computeQuadraturePointsCoordinates(ElementTypeMapArray<Real> & quadrature_points_coordinates,
                                           const GhostType & ghost_type) const;
 
 protected:
   /// interpolate an elemental field on given points for each element
   void interpolateElementalField(const ElementTypeMapArray<Real> & field,
                                  ElementTypeMapArray<Real> & result,
                                  const GhostType ghost_type);
 
   /// interpolate an elemental field and store the results per facet
   void interpolateElementalFieldOnFacets(const ElementTypeMapArray<Real> & field,
 					 ElementTypeMapArray<Real> & result,
 					 const GhostType ghost_type);
 
   /// template function to initialize the elemental field interpolation
   template <ElementType type>
   void initElementalFieldInterpolation(const Array<Real> & quad_coordinates,
                                        const Array<Real> & interpolation_points_coordinates,
                                        const UInt nb_interpolation_points_per_elem,
                                        const GhostType ghost_type);
 
   /// build the coordinate matrix for the interpolation on elemental field
   template <ElementType type>
   inline void buildElementalFieldInterpolationCoodinates(const Matrix<Real> & coordinates,
                                                          Matrix<Real> & coordMatrix);
 
   /// build interpolation coordinates for basic linear elements
   inline void buildElementalFieldInterpolationCoodinatesLinear(const Matrix<Real> & coordinates,
                                                                Matrix<Real> & coordMatrix);
 
   /// build interpolation coordinates for basic quadratic elements
   inline void buildElementalFieldInterpolationCoodinatesQuadratic(const Matrix<Real> & coordinates,
                                                                   Matrix<Real> & coordMatrix);
 
 public:
   /* ------------------------------------------------------------------------ */
   /* Conversion functions                                                     */
   /* ------------------------------------------------------------------------ */
   template<UInt dim>
   static inline void gradUToF   (const Matrix<Real> & grad_u, Matrix<Real> & F);
   static inline void rightCauchy(const Matrix<Real> & F,      Matrix<Real> & C);
   static inline void leftCauchy (const Matrix<Real> & F,      Matrix<Real> & B);
 
   template<UInt dim>
   static inline void gradUToEpsilon(const Matrix<Real> & grad_u,
 				    Matrix<Real> & epsilon);
   template<UInt dim>
   static inline void gradUToGreenStrain(const Matrix<Real> & grad_u,
 					Matrix<Real> & epsilon);
 
   static inline Real stressToVonMises(const Matrix<Real> & stress);
 
 protected:
   /// converts global element to local element
   inline Element convertToLocalElement(const Element & global_element) const;
   /// converts local element to global element
   inline Element convertToGlobalElement(const Element & local_element) const;
 
   /// converts global quadrature point to local quadrature point
   inline QuadraturePoint convertToLocalPoint(const QuadraturePoint & global_point) const;
   /// converts local quadrature point to global quadrature point
   inline QuadraturePoint convertToGlobalPoint(const QuadraturePoint & local_point) const;
 
   /* ------------------------------------------------------------------------ */
   /* DataAccessor inherited members                                           */
   /* ------------------------------------------------------------------------ */
 public:
   virtual inline UInt getNbDataForElements(const Array<Element> & elements,
                                            SynchronizationTag tag) const;
 
   virtual inline void packElementData(CommunicationBuffer & buffer,
                                       const Array<Element> & elements,
                                       SynchronizationTag tag) const;
 
   virtual inline void unpackElementData(CommunicationBuffer & buffer,
                                         const Array<Element> & elements,
                                         SynchronizationTag tag);
 
   template<typename T>
   inline void packElementDataHelper(const ElementTypeMapArray<T> & data_to_pack,
                                     CommunicationBuffer & buffer,
                                     const Array<Element> & elements,
                                     const ID & fem_id = ID()) const;
 
   template<typename T>
   inline void unpackElementDataHelper(ElementTypeMapArray<T> & data_to_unpack,
                                       CommunicationBuffer & buffer,
                                       const Array<Element> & elements,
                                       const ID & fem_id = ID());
 
   /* ------------------------------------------------------------------------ */
   /* MeshEventHandler inherited members                                       */
   /* ------------------------------------------------------------------------ */
 public:
   /* ------------------------------------------------------------------------ */
   virtual void onElementsAdded(const Array<Element> & element_list,
                                const NewElementsEvent & event);
 
   virtual void onElementsRemoved(const Array<Element> & element_list,
                                  const ElementTypeMapArray<UInt> & new_numbering,
                                  const RemovedElementsEvent & event);
 
   /* ------------------------------------------------------------------------ */
   /* SolidMechanicsModelEventHandler inherited members                        */
   /* ------------------------------------------------------------------------ */
 public:
   virtual void onBeginningSolveStep(const AnalysisMethod & method);
   virtual void onEndSolveStep(const AnalysisMethod & method);
   virtual void onDamageIteration();
   virtual void onDamageUpdate(); 
   virtual void onDump();
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   AKANTU_GET_MACRO(Model, *model, const SolidMechanicsModel &)
 
   AKANTU_GET_MACRO(ID, Memory::getID(), const ID &);
   AKANTU_GET_MACRO(Rho, rho, Real);
   AKANTU_SET_MACRO(Rho, rho, Real);
 
+  AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt);
+
   /// return the potential energy for the subset of elements contained by the material
   Real getPotentialEnergy();
   /// return the potential energy for the provided element
   Real getPotentialEnergy(ElementType & type, UInt index);
 
   /// return the energy (identified by id) for the subset of elements contained by the material
   virtual Real getEnergy(std::string energy_id);
   /// return the energy (identified by id) for the provided element
   virtual Real getEnergy(std::string energy_id, ElementType type, UInt index);
 
 
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GradU, gradu, Real);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy, Real);
   AKANTU_GET_MACRO(GradU, gradu, const ElementTypeMapArray<Real> &);
   AKANTU_GET_MACRO(Stress, stress, const ElementTypeMapArray<Real> &);
   AKANTU_GET_MACRO(ElementFilter, element_filter, const ElementTypeMapArray<UInt> &);
 
   bool isNonLocal() const { return is_non_local; }
 
   const Array<Real> & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost) const;
   Array<Real> & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost);
 
   const InternalField<Real> & getInternal(const ID & id) const;
   InternalField<Real> & getInternal(const ID & id);
 
   inline bool isInternal(const ID & id, const ElementKind & element_kind) const;
-  inline ElementTypeMap<UInt> getInternalDataPerElem(const ID & id, const ElementKind & element_kind, const ID & fe_engine_id = "") const;
+  inline ElementTypeMap<UInt> getInternalDataPerElem(const ID & id,
+                                                     const ElementKind & element_kind) const;
 
   bool isFiniteDeformation() const { return finite_deformation; }
   bool isInelasticDeformation() const { return inelastic_deformation; }
 
   template <typename T>
   inline void setParam(const ID & param, T value);
 
   template <typename T>
   inline const T & getParam(const ID & param) const;
 
   virtual void flattenInternal(const std::string & field_id,
 		                           ElementTypeMapArray<Real> & internal_flat,
                                const GhostType ghost_type = _not_ghost,
                                ElementKind element_kind = _ek_not_defined);
 
 
 protected:
 
   bool isInit() const { return is_init; }
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   /// boolean to know if the material has been initialized
   bool is_init;
 
   std::map<ID, InternalField<Real> *> internal_vectors_real;
   std::map<ID, InternalField<UInt> *> internal_vectors_uint;
 
 protected:
   /// Finite deformation
   bool finite_deformation;
 
   /// Finite deformation
   bool inelastic_deformation;
 
   /// material name
   std::string name;
 
   /// The model to witch the material belong
   SolidMechanicsModel * model;
 
   /// density : rho
   Real rho;
 
   /// spatial dimension
   UInt spatial_dimension;
 
   /// list of element handled by the material
   ElementTypeMapArray<UInt> element_filter;
 
   /// stresses arrays ordered by element types
   InternalField<Real> stress;
 
   /// eigenstrain arrays ordered by element types
   InternalField<Real> eigenstrain;
 
   /// grad_u arrays ordered by element types
   InternalField<Real> gradu;
 
   /// Green Lagrange strain (Finite deformation)
   InternalField<Real> green_strain;
 
   /// Second Piola-Kirchhoff stress tensor arrays ordered by element types (Finite deformation)
   InternalField<Real> piola_kirchhoff_2;
 
   /// potential energy by element
   InternalField<Real> potential_energy;
 
   /// tell if using in non local mode or not
   bool is_non_local;
 
   /// tell if the material need the previous stress state
   bool use_previous_stress;
 
   /// tell if the material need the previous strain state
   bool use_previous_gradu;
 
   /// elemental field interpolation coordinates
   InternalField<Real> interpolation_inverse_coordinates;
 
   /// elemental field interpolation points
   InternalField<Real> interpolation_points_matrices;
 };
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 #include "material_inline_impl.cc"
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const Material & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 __END_AKANTU__
 
 #include "internal_field_tmpl.hh"
 #include "random_internal_field_tmpl.hh"
 
 /* -------------------------------------------------------------------------- */
 /* Auto loop                                                                  */
 /* -------------------------------------------------------------------------- */
 
 #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type) \
   Array<Real>::matrix_iterator gradu_it =				\
     this->gradu(el_type, ghost_type).begin(this->spatial_dimension,     \
 					  this->spatial_dimension);     \
   Array<Real>::matrix_iterator gradu_end =				\
     this->gradu(el_type, ghost_type).end(this->spatial_dimension,       \
 					this->spatial_dimension);       \
                                                                         \
   this->stress(el_type,                                                 \
                ghost_type).resize(this->gradu(el_type,			\
 					      ghost_type).getSize());	\
                                                                         \
   Array<Real>::iterator< Matrix<Real> > stress_it =			\
     this->stress(el_type, ghost_type).begin(this->spatial_dimension,    \
                                             this->spatial_dimension);   \
                                                                         \
   if(this->isFiniteDeformation()){                                      \
     this->piola_kirchhoff_2(el_type,                                    \
 			    ghost_type).resize(this->gradu(el_type,	\
 							   ghost_type).getSize()); \
     stress_it =                                                         \
       this->piola_kirchhoff_2(el_type,                                  \
 			      ghost_type).begin(this->spatial_dimension, \
 						this->spatial_dimension); \
   }                                                                     \
                                                                         \
   for(;gradu_it != gradu_end; ++gradu_it, ++stress_it) {		\
     Matrix<Real> & __attribute__((unused)) grad_u = *gradu_it;		\
     Matrix<Real> & __attribute__((unused)) sigma  = *stress_it
 
 #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END	                \
   }							                \
 
 
 #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_mat)	\
   Array<Real>::matrix_iterator gradu_it =				\
     this->gradu(el_type, ghost_type).begin(this->spatial_dimension,     \
 					   this->spatial_dimension);    \
   Array<Real>::matrix_iterator gradu_end =				\
     this->gradu(el_type, ghost_type).end(this->spatial_dimension,       \
 					 this->spatial_dimension);      \
   Array<Real>::matrix_iterator sigma_it =				\
     this->stress(el_type, ghost_type).begin(this->spatial_dimension,    \
 					    this->spatial_dimension);   \
   									\
   tangent_mat.resize(this->gradu(el_type, ghost_type).getSize());	\
   									\
   UInt tangent_size =							\
     this->getTangentStiffnessVoigtSize(this->spatial_dimension);        \
   Array<Real>::matrix_iterator tangent_it =				\
     tangent_mat.begin(tangent_size,					\
 		      tangent_size);					\
   									\
   for(;gradu_it != gradu_end; ++gradu_it, ++sigma_it, ++tangent_it) {	\
     Matrix<Real> & __attribute__((unused)) grad_u  = *gradu_it;		\
     Matrix<Real> & __attribute__((unused)) sigma_tensor = *sigma_it;	\
     Matrix<Real> & tangent = *tangent_it
 
 
 #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END			\
   }                                                                     \
 
 /* -------------------------------------------------------------------------- */
 #define INSTANSIATE_MATERIAL(mat_name)			\
   template class mat_name<1>;				\
   template class mat_name<2>;				\
   template class mat_name<3>
 
 #endif /* __AKANTU_MATERIAL_HH__ */
diff --git a/src/model/solid_mechanics/material_inline_impl.cc b/src/model/solid_mechanics/material_inline_impl.cc
index b00185ba2..bb3551113 100644
--- a/src/model/solid_mechanics/material_inline_impl.cc
+++ b/src/model/solid_mechanics/material_inline_impl.cc
@@ -1,491 +1,486 @@
 /**
  * @file   material_inline_impl.cc
  *
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  *
  * @date creation: Tue Jul 27 2010
  * @date last modification: Tue Sep 16 2014
  *
  * @brief  Implementation of the inline functions of the class material
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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/>.
  *
  */
 
 __END_AKANTU__
 
 #include "solid_mechanics_model.hh"
 #include <iostream>
 
 __BEGIN_AKANTU__
 
 
 /* -------------------------------------------------------------------------- */
 inline UInt Material::addElement(const ElementType & type,
 				 UInt element,
 				 const GhostType & ghost_type) {
   Array<UInt> & el_filter = element_filter(type, ghost_type);
   el_filter.push_back(element);
   return el_filter.getSize()-1;
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt Material::getTangentStiffnessVoigtSize(UInt dim) const {
   return (dim * (dim - 1) / 2 + dim);
 }
 /* -------------------------------------------------------------------------- */
 inline UInt Material::getCauchyStressMatrixSize(UInt dim) const {
   return (dim * dim);
 }
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 inline void Material::gradUToF(const Matrix<Real> & grad_u,
 			       Matrix<Real> & F) {
   AKANTU_DEBUG_ASSERT(F.size() >= grad_u.size() && grad_u.size() == dim*dim,
             "The dimension of the tensor F should be greater or equal to the dimension of the tensor grad_u.");
 
   F.eye();
 
   for (UInt i = 0; i < dim; ++i)
     for (UInt j = 0; j < dim; ++j)
       F(i, j) += grad_u(i, j);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim >
 inline void Material::computeCauchyStressOnQuad(const Matrix<Real> & F,
 						const Matrix<Real> & piola,
 						Matrix<Real> & sigma,
                                                 const Real & C33 ) const {
 
   Real J = F.det() * sqrt(C33);
 
   Matrix<Real> F_S(dim, dim);
   F_S.mul<false, false>(F, piola);
   Real constant = J ? 1./J : 0;
   sigma.mul<false, true>(F_S, F, constant);
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Material::rightCauchy(const Matrix<Real> & F,
 				  Matrix<Real> & C) {
   C.mul<true, false>(F, F);
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Material::leftCauchy(const Matrix<Real> & F,
 				 Matrix<Real> & B) {
   B.mul<false, true>(F, F);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 inline void Material::gradUToEpsilon(const Matrix<Real> & grad_u,
 				     Matrix<Real> & epsilon) {
   for (UInt i = 0; i < dim; ++i)
     for (UInt j = 0; j < dim; ++j)
       epsilon(i, j) = 0.5*(grad_u(i, j) + grad_u(j, i));
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 inline void Material::gradUToGreenStrain(const Matrix<Real> & grad_u,
 					 Matrix<Real> & epsilon) {
   epsilon.mul<true, false>(grad_u, grad_u, .5);
 
   for (UInt i = 0; i < dim; ++i)
     for (UInt j = 0; j < dim; ++j)
       epsilon(i, j) += 0.5 * (grad_u(i, j) + grad_u(j, i));
 }
 
 /* -------------------------------------------------------------------------- */
 inline Real Material::stressToVonMises(const Matrix<Real> & stress) {
   // compute deviatoric stress
   UInt dim = stress.cols();
   Matrix<Real> deviatoric_stress = Matrix<Real>::eye(dim, -1. * stress.trace() / 3.);
 
   for (UInt i = 0; i < dim; ++i)
     for (UInt j = 0; j < dim; ++j)
       deviatoric_stress(i,j) += stress(i,j);
 
   // return Von Mises stress
   return std::sqrt(3. * deviatoric_stress.doubleDot(deviatoric_stress) / 2.);
 }
 
 /* ---------------------------------------------------------------------------*/
 template<UInt dim>
 inline void Material::SetCauchyStressArray(const Matrix<Real> & S_t, Matrix<Real> & Stress_vect) {
 
     AKANTU_DEBUG_IN();
 
     Stress_vect.clear();
 
     //UInt cauchy_matrix_size = getCauchyStressArraySize(dim);
 
     //see Finite ekement formulations for large deformation dynamic analysis, Bathe et al. IJNME vol 9, 1975, page 364 ^t\tau
 
     /*
      * 1d: [ s11 ]'
      * 2d: [ s11 s22 s12 ]'
      * 3d: [ s11 s22 s33 s23 s13 s12 ]
      */
     for (UInt i = 0; i < dim; ++i)//diagonal terms
         Stress_vect(i, 0) = S_t(i, i);
 
     for (UInt i = 1; i < dim; ++i)// term s12 in 2D and terms s23 s13 in 3D
         Stress_vect(dim+i-1, 0) = S_t(dim-i-1, dim-1);
 
     for (UInt i = 2; i < dim; ++i)//term s13 in 3D
         Stress_vect(dim+i, 0) = S_t(0, 1);
 
     AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 inline void Material::setCauchyStressMatrix(const Matrix<Real> & S_t, Matrix<Real> & Stress_matrix) {
 
     AKANTU_DEBUG_IN();
 
     Stress_matrix.clear();
 
     /// see Finite ekement formulations for large deformation dynamic analysis,
     /// Bathe et al. IJNME vol 9, 1975, page 364 ^t\tau
 
     for (UInt i = 0; i < dim; ++i) {
         for (UInt m = 0; m < dim; ++m) {
             for (UInt n = 0; n < dim; ++n) {
                 Stress_matrix(i * dim + m, i * dim + n) = S_t(m, n);
             }
         }
     }
 
     //other terms from the diagonal
     /*for (UInt i = 0; i < 3 - dim; ++i) {
         Stress_matrix(dim * dim + i, dim * dim + i) = S_t(dim + i, dim + i);
     }*/
 
 
     AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 inline Element Material::convertToLocalElement(const Element & global_element) const {
   UInt ge = global_element.element;
 #ifndef AKANTU_NDEBUG
   UInt model_mat_index = this->model->getMaterialByElement(global_element.type,
 							   global_element.ghost_type)(ge);
 
   UInt mat_index = this->model->getMaterialIndex(this->name);
   AKANTU_DEBUG_ASSERT(model_mat_index == mat_index,
 		      "Conversion of a global  element in a local element for the wrong material "
 		      << this->name << std::endl);
 #endif
   UInt le = this->model->getMaterialLocalNumbering(global_element.type,
 						   global_element.ghost_type)(ge);
 
   Element tmp_quad(global_element.type,
 		   le,
 		   global_element.ghost_type);
   return tmp_quad;
 }
 
 /* -------------------------------------------------------------------------- */
 inline Element Material::convertToGlobalElement(const Element & local_element) const {
   UInt le = local_element.element;
   UInt ge = this->element_filter(local_element.type, local_element.ghost_type)(le);
 
   Element tmp_quad(local_element.type,
 		   ge,
 		   local_element.ghost_type);
   return tmp_quad;
 }
 
 /* -------------------------------------------------------------------------- */
 inline QuadraturePoint Material::convertToLocalPoint(const QuadraturePoint & global_point) const {
   const FEEngine & fem = this->model->getFEEngine();
   UInt nb_quad = fem.getNbQuadraturePoints(global_point.type);
   Element el = this->convertToLocalElement(static_cast<const Element &>(global_point));
   QuadraturePoint tmp_quad(el, global_point.num_point, nb_quad);
   return tmp_quad;
 }
 
 /* -------------------------------------------------------------------------- */
 inline QuadraturePoint Material::convertToGlobalPoint(const QuadraturePoint & local_point) const {
   const FEEngine & fem = this->model->getFEEngine();
   UInt nb_quad = fem.getNbQuadraturePoints(local_point.type);
   Element el = this->convertToGlobalElement(static_cast<const Element &>(local_point));
   QuadraturePoint tmp_quad(el, local_point.num_point, nb_quad);
   return tmp_quad;
 }
 
 /* -------------------------------------------------------------------------- */
 template<ElementType type>
 inline void Material::buildElementalFieldInterpolationCoodinates(__attribute__((unused)) const Matrix<Real> & coordinates,
 								 __attribute__((unused)) Matrix<Real> & coordMatrix) {
   AKANTU_DEBUG_TO_IMPLEMENT();
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Material::buildElementalFieldInterpolationCoodinatesLinear(const Matrix<Real> & coordinates,
 								       Matrix<Real> & coordMatrix) {
 
   for (UInt i = 0; i < coordinates.cols(); ++i)
     coordMatrix(i, 0) = 1;
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Material::buildElementalFieldInterpolationCoodinatesQuadratic(const Matrix<Real> & coordinates,
 									  Matrix<Real> & coordMatrix) {
 
   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);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline void Material::buildElementalFieldInterpolationCoodinates<_segment_2>(const Matrix<Real> & coordinates,
 									     Matrix<Real> & coordMatrix) {
   buildElementalFieldInterpolationCoodinatesLinear(coordinates, coordMatrix);
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline void Material::buildElementalFieldInterpolationCoodinates<_segment_3>(const Matrix<Real> & coordinates,
 									     Matrix<Real> & coordMatrix) {
 
   buildElementalFieldInterpolationCoodinatesQuadratic(coordinates, coordMatrix);
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline void Material::buildElementalFieldInterpolationCoodinates<_triangle_3>(const Matrix<Real> & coordinates,
 									      Matrix<Real> & coordMatrix) {
   buildElementalFieldInterpolationCoodinatesLinear(coordinates, coordMatrix);
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline void Material::buildElementalFieldInterpolationCoodinates<_triangle_6>(const Matrix<Real> & coordinates,
 									      Matrix<Real> & coordMatrix) {
 
   buildElementalFieldInterpolationCoodinatesQuadratic(coordinates, coordMatrix);
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline void Material::buildElementalFieldInterpolationCoodinates<_tetrahedron_4>(const Matrix<Real> & coordinates,
 										 Matrix<Real> & coordMatrix) {
   buildElementalFieldInterpolationCoodinatesLinear(coordinates, coordMatrix);
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline void Material::buildElementalFieldInterpolationCoodinates<_tetrahedron_10>(const Matrix<Real> & coordinates,
 										  Matrix<Real> & coordMatrix) {
 
   buildElementalFieldInterpolationCoodinatesQuadratic(coordinates, coordMatrix);
 }
 
 /**
  * @todo Write a more efficient interpolation for quadrangles by
  * dropping unnecessary quadrature points
  *
  */
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline void Material::buildElementalFieldInterpolationCoodinates<_quadrangle_4>(const Matrix<Real> & coordinates,
 										Matrix<Real> & coordMatrix) {
 
   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 Material::buildElementalFieldInterpolationCoodinates<_quadrangle_8>(const Matrix<Real> & coordinates,
 										Matrix<Real> & coordMatrix) {
 
   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;
       }
     }
 
   }
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt Material::getNbDataForElements(const Array<Element> & elements,
 					   SynchronizationTag tag) const {
   if(tag == _gst_smm_stress) {
     return (this->isFiniteDeformation() ? 3 : 1) * spatial_dimension * spatial_dimension *
       sizeof(Real) * this->getModel().getNbQuadraturePoints(elements);
   }
   return 0;
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Material::packElementData(CommunicationBuffer & buffer,
 				      const Array<Element> & elements,
 				      SynchronizationTag tag) const {
   if(tag == _gst_smm_stress) {
     if(this->isFiniteDeformation()) {
       packElementDataHelper(piola_kirchhoff_2, buffer, elements);
       packElementDataHelper(gradu, buffer, elements);
     }
     packElementDataHelper(stress, buffer, elements);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Material::unpackElementData(CommunicationBuffer & buffer,
 					const Array<Element> & elements,
 					SynchronizationTag tag) {
   if(tag == _gst_smm_stress) {
     if(this->isFiniteDeformation()) {
       unpackElementDataHelper(piola_kirchhoff_2, buffer, elements);
       unpackElementDataHelper(gradu, buffer, elements);
     }
     unpackElementDataHelper(stress, buffer, elements);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline const T & Material::getParam(const ID & param) const {
   try {
     return get<T>(param);
   } catch (...) {
     AKANTU_EXCEPTION("No parameter " << param << " in the material " << getID());
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 inline void Material::setParam(const ID & param, T value) {
   try {
     set<T>(param, value);
   } catch(...) {
     AKANTU_EXCEPTION("No parameter " << param << " in the material " << getID());
   }
   updateInternalParameters();
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline void Material::packElementDataHelper(const ElementTypeMapArray<T> & data_to_pack,
 					    CommunicationBuffer & buffer,
 					    const Array<Element> & elements,
 					    const ID & fem_id) const {
   DataAccessor::packElementalDataHelper<T>(data_to_pack, buffer, elements, true,
 					   model->getFEEngine(fem_id));
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline void Material::unpackElementDataHelper(ElementTypeMapArray<T> & data_to_unpack,
 					      CommunicationBuffer & buffer,
 					      const Array<Element> & elements,
 					      const ID & fem_id) {
   DataAccessor::unpackElementalDataHelper<T>(data_to_unpack, buffer, elements, true,
 					     model->getFEEngine(fem_id));
 }
 
 /* -------------------------------------------------------------------------- */
 template<> inline void Material::registerInternal<Real>(InternalField<Real> & vect) {
   internal_vectors_real[vect.getID()] = &vect;
 }
 
 template<> inline void Material::registerInternal<UInt>(InternalField<UInt> & vect) {
   internal_vectors_uint[vect.getID()] = &vect;
 }
 
 /* -------------------------------------------------------------------------- */
 template<> inline void Material::unregisterInternal<Real>(InternalField<Real> & vect) {
   internal_vectors_real.erase(vect.getID());
 }
 
 template<> inline void Material::unregisterInternal<UInt>(InternalField<UInt> & vect) {
   internal_vectors_uint.erase(vect.getID());
 }
 
 /* -------------------------------------------------------------------------- */
 inline bool Material::isInternal(const ID & id, const ElementKind & element_kind) const {
 
   std::map<ID, InternalField<Real> *>::const_iterator internal_array =
     internal_vectors_real.find(this->getID()+":"+id);
 
   if (internal_array == internal_vectors_real.end())    return false;
   if (internal_array->second->getElementKind() != element_kind) return false;
   return true;
 }
 
 /* -------------------------------------------------------------------------- */
 
-inline ElementTypeMap<UInt> Material::getInternalDataPerElem(const ID & id, const ElementKind & element_kind,
-                                                             const ID & fe_engine_id) const {
+inline ElementTypeMap<UInt> Material::getInternalDataPerElem(const ID & id,
+                                                             const ElementKind & element_kind) const {
 
   std::map<ID, InternalField<Real> *>::const_iterator internal_array =
     internal_vectors_real.find(this->getID()+":"+id);
 
   if (internal_array == internal_vectors_real.end())  AKANTU_EXCEPTION("cannot find internal " << id);
   if (internal_array->second->getElementKind() != element_kind) AKANTU_EXCEPTION("cannot find internal " << id);
 
   InternalField<Real> & internal = *internal_array->second;
   InternalField<Real>::type_iterator it = internal.firstType(spatial_dimension, _not_ghost,element_kind);
   InternalField<Real>::type_iterator last_type = internal.lastType(spatial_dimension, _not_ghost,element_kind);
 
 
   ElementTypeMap<UInt> res;
   for(; it != last_type; ++it) {
     UInt nb_quadrature_points = 0;
-    if (element_kind == _ek_regular)
-      nb_quadrature_points = model->getFEEngine(fe_engine_id).getNbQuadraturePoints(*it);
-#if defined(AKANTU_COHESIVE_ELEMENT)
-    else if (element_kind == _ek_cohesive)
-      nb_quadrature_points = model->getFEEngine("CohesiveFEEngine").getNbQuadraturePoints(*it);
-#endif
+    nb_quadrature_points = internal.getFEEngine().getNbQuadraturePoints(*it);
     res(*it) = internal.getNbComponent() * nb_quadrature_points;
   }
     return res;
 }
diff --git a/src/model/solid_mechanics/materials/internal_field.hh b/src/model/solid_mechanics/materials/internal_field.hh
index 571e68044..49d5e209e 100644
--- a/src/model/solid_mechanics/materials/internal_field.hh
+++ b/src/model/solid_mechanics/materials/internal_field.hh
@@ -1,194 +1,205 @@
 /**
  * @file   internal_field.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Nov 13 2013
  * @date last modification: Tue Sep 02 2014
  *
  * @brief  Material internal properties
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "element_type_map.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_INTERNAL_FIELD_HH__
 #define __AKANTU_INTERNAL_FIELD_HH__
 
 __BEGIN_AKANTU__
 
 class Material;
 class FEEngine;
 
 template<typename T>
 class InternalField : public ElementTypeMapArray<T> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   InternalField(const ID & id, Material & material);
   virtual ~InternalField();
 
-protected:
-  InternalField(const ID & id, Material & material, FEEngine & fem,
+  /// This constructor is only here to let cohesive elements compile
+  InternalField(const ID & id,
+                Material & material,
+                FEEngine & fem,
+		const ElementTypeMapArray<UInt> & element_filter);
+
+  /// More general constructor
+  InternalField(const ID & id,
+                Material & material,
+                UInt dim,
+                FEEngine & fem,
 		const ElementTypeMapArray<UInt> & element_filter);
 
   InternalField(const ID & id, const InternalField<T> & other);
 
 private:
   InternalField operator=(__attribute__((unused)) const InternalField & other) {};
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialize the field to a given number of component
   virtual void initialize(UInt nb_component);
 
   /// activate the history of this field
   virtual void initializeHistory();
 
   /// resize the arrays and set the new element to 0
   virtual void resize();
 
   /// set the field to a given value v
   virtual void setDefaultValue(const T & v);
 
   /// reset all the fields to the default value
   virtual void reset();
 
   /// save the current values in the history
   virtual void saveCurrentValues();
 
   /// remove the quadrature points corresponding to suppressed elements
   virtual void removeQuadraturePoints(const ElementTypeMapArray<UInt> & new_numbering);
 
   /// print the content
   virtual void printself(std::ostream & stream, UInt indent = 0) const;
 
   /// get the default value
   inline operator T() const;
 
+  AKANTU_GET_MACRO(FEEngine, fem, const FEEngine &);
+
 protected:
   /// initialize the arrays in the ElementTypeMapArray<T>
   void internalInitialize(UInt nb_component);
 
   /// set the values for new internals
   virtual void setArrayValues(T * begin, T * end);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// get the Array corresponding to the type en ghost_type specified
   virtual Array<T> & operator()(const ElementType & type, const GhostType & ghost_type = _not_ghost) {
     return ElementTypeMapArray<T>::operator()(type, ghost_type);
   }
 
   virtual const Array<T> & operator()(const ElementType & type, const GhostType & ghost_type = _not_ghost) const {
     return ElementTypeMapArray<T>::operator()(type, ghost_type);
   }
 
   virtual Array<T> & previous(const ElementType & type, const GhostType & ghost_type = _not_ghost) {
     AKANTU_DEBUG_ASSERT(previous_values != NULL,
 			"The history of the internal " << this->getID()
 			<< " has not been activated");
     return this->previous_values->operator()(type, ghost_type);
   }
 
   virtual const Array<T> & previous(const ElementType & type, const GhostType & ghost_type = _not_ghost) const {
     AKANTU_DEBUG_ASSERT(previous_values != NULL,
 			"The history of the internal " << this->getID()
 			<< " has not been activated");
     return this->previous_values->operator()(type, ghost_type);
   }
 
 
   virtual InternalField<T> & previous() {
     AKANTU_DEBUG_ASSERT(previous_values != NULL,
 			"The history of the internal " << this->getID()
 			<< " has not been activated");
     return *(this->previous_values);
   }
 
   virtual const InternalField<T> & previous() const {
     AKANTU_DEBUG_ASSERT(previous_values != NULL,
 			"The history of the internal " << this->getID()
 			<< " has not been activated");
     return *(this->previous_values);
   }
 
   /// check if the history is used or not
   bool hasHistory() const { return (previous_values != NULL); }
 
   /// get the kind treated by the internal
   const ElementKind & getElementKind() const {return element_kind;};
 
 
   /// return the number of components
   UInt getNbComponent(){return nb_component;}
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// the material for which this is an internal parameter
   Material & material;
 
   /// the fem containing the mesh and the element informations
   FEEngine & fem;
 
   /// Element filter if needed
   const ElementTypeMapArray<UInt> & element_filter;
 
   /// default value
   T default_value;
 
   /// spatial dimension of the element to consider
   UInt spatial_dimension;
 
   /// ElementKind of the element to consider
   ElementKind element_kind;
 
   /// Number of component of the internal field
   UInt nb_component;
 
   /// Is the field initialized
   bool is_init;
 
   /// previous values
   InternalField<T> * previous_values;
 };
 
 /// standard output stream operator
 template<typename T>
 inline std::ostream & operator <<(std::ostream & stream, const InternalField<T> & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 __END_AKANTU__
 
 #endif /* __AKANTU_INTERNAL_FIELD_HH__ */
diff --git a/src/model/solid_mechanics/materials/internal_field_tmpl.hh b/src/model/solid_mechanics/materials/internal_field_tmpl.hh
index e7d11c241..f0f457b1f 100644
--- a/src/model/solid_mechanics/materials/internal_field_tmpl.hh
+++ b/src/model/solid_mechanics/materials/internal_field_tmpl.hh
@@ -1,305 +1,326 @@
 /**
  * @file   internal_field_tmpl.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Nov 13 2013
  * @date last modification: Thu Jun 05 2014
  *
  * @brief  Material internal properties
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_INTERNAL_FIELD_TMPL_HH__
 #define __AKANTU_INTERNAL_FIELD_TMPL_HH__
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 InternalField<T>::InternalField(const ID & id, Material & material) :
   ElementTypeMapArray<T>(id, material.getID(), material.getMemoryID()),
   material(material),
   fem(material.getModel().getFEEngine()),
   element_filter(material.getElementFilter()),
   default_value(T()),
   spatial_dimension(material.getModel().getSpatialDimension()),
   element_kind(_ek_regular),
   nb_component(0),
   is_init(false),
   previous_values(NULL) {
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
-InternalField<T>::InternalField(const ID & id, Material & material, FEEngine & fem,
+InternalField<T>::InternalField(const ID & id,
+                                Material & material,
+                                FEEngine & fem,
 				const ElementTypeMapArray<UInt> & element_filter) :
   ElementTypeMapArray<T>(id, material.getID(), material.getMemoryID()),
   material(material),
   fem(fem),
   element_filter(element_filter),
   default_value(T()),
-  spatial_dimension(material.getModel().getSpatialDimension()),
+  spatial_dimension(material.getSpatialDimension()),
+  element_kind(_ek_regular),
+  nb_component(0),
+  is_init(false),
+  previous_values(NULL) {
+}
+
+/* -------------------------------------------------------------------------- */
+template<typename T>
+InternalField<T>::InternalField(const ID & id,
+                                Material & material,
+                                UInt dim,
+                                FEEngine & fem,
+				const ElementTypeMapArray<UInt> & element_filter) :
+  ElementTypeMapArray<T>(id, material.getID(), material.getMemoryID()),
+  material(material),
+  fem(fem),
+  element_filter(element_filter),
+  default_value(T()),
+  spatial_dimension(dim),
   element_kind(_ek_regular),
   nb_component(0),
   is_init(false),
   previous_values(NULL) {
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 InternalField<T>::InternalField(const ID & id, const InternalField<T> & other) :
   ElementTypeMapArray<T>(id, other.material.getID(), other.material.getMemoryID()),
   material(other.material),
   fem(other.fem),
   element_filter(other.element_filter),
   default_value(other.default_value),
   spatial_dimension(other.spatial_dimension),
   element_kind(other.element_kind),
   nb_component(other.nb_component),
   is_init(false),
   previous_values(NULL) {
 
   AKANTU_DEBUG_ASSERT(other.is_init, "Cannot create a copy of a non initialized field");
   this->internalInitialize(this->nb_component);
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 InternalField<T>::~InternalField() {
   if(this->is_init) {
     this->material.unregisterInternal(*this);
   }
 
   delete previous_values;
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void InternalField<T>::initialize(UInt nb_component) {
   internalInitialize(nb_component);
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void InternalField<T>::initializeHistory() {
   if(!previous_values)
     previous_values = new InternalField<T>("previous_" + this->getID(), *this);
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void InternalField<T>::resize() {
   if(!this->is_init) return;
 
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
 
     typename ElementTypeMapArray<UInt>::type_iterator it
       = element_filter.firstType(spatial_dimension, gt, element_kind);
     typename ElementTypeMapArray<UInt>::type_iterator end
       = element_filter.lastType(spatial_dimension, gt, element_kind);
     for(; it != end; ++it) {
       UInt nb_element = element_filter(*it, gt).getSize();
 
       UInt nb_quadrature_points = fem.getNbQuadraturePoints(*it, gt);
       UInt new_size = nb_element * nb_quadrature_points;
 
       UInt old_size = 0;
       Array<T> * vect = NULL;
 
       if(this->exists(*it, gt)) {
 	vect = &(this->operator()(*it, gt));
 	old_size = vect->getSize();
 	vect->resize(new_size);
       } else {
 	vect = &(this->alloc(nb_element * nb_quadrature_points, nb_component, *it, gt));
       }
 
       this->setArrayValues(vect->storage() + old_size * vect->getNbComponent(),
 			   vect->storage() + new_size * vect->getNbComponent());
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void InternalField<T>::setDefaultValue(const T & value) {
   this->default_value = value;
   this->reset();
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void InternalField<T>::reset() {
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
 
     typename ElementTypeMapArray<T>::type_iterator it  = this->firstType(spatial_dimension, gt, element_kind);
     typename ElementTypeMapArray<T>::type_iterator end = this->lastType(spatial_dimension, gt, element_kind);
     for(; it != end; ++it) {
       Array<T> & vect = this->operator()(*it, gt);
       vect.clear();
       this->setArrayValues(vect.storage(),
 			   vect.storage() + vect.getSize() * vect.getNbComponent());
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void InternalField<T>::internalInitialize(UInt nb_component) {
   if(!this->is_init) {
     this->nb_component = nb_component;
     for(UInt g = _not_ghost; g <= _ghost; ++g) {
       GhostType gt = (GhostType) g;
       typename ElementTypeMapArray<UInt>::type_iterator it
 	= element_filter.firstType(spatial_dimension, gt, element_kind);
       typename ElementTypeMapArray<UInt>::type_iterator end
 	= element_filter.lastType(spatial_dimension, gt, element_kind);
 
       for(; it != end; ++it) {
 	UInt nb_element = element_filter(*it, gt).getSize();
 	UInt nb_quadrature_points = fem.getNbQuadraturePoints(*it, gt);
 	if(this->exists(*it, gt))
 	  this->operator()(*it, gt).resize(nb_element * nb_quadrature_points);
 	else
 	  this->alloc(nb_element * nb_quadrature_points, nb_component, *it, gt);
       }
     }
 
     this->material.registerInternal(*this);
     this->is_init = true;
   }
   this->reset();
 
   if(previous_values) previous_values->internalInitialize(nb_component);
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void InternalField<T>::setArrayValues(T * begin, T * end) {
   for(; begin < end; ++begin) *begin = default_value;
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void InternalField<T>::saveCurrentValues() {
   AKANTU_DEBUG_ASSERT(previous_values != NULL,
 		      "The history of the internal " << this->getID()
 		      << " has not been activated");
 
   if(!is_init) return;
 
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
     typename ElementTypeMapArray<T>::type_iterator it  = this->firstType(spatial_dimension, gt, element_kind);
     typename ElementTypeMapArray<T>::type_iterator end = this->lastType(spatial_dimension, gt, element_kind);
     for(; it != end; ++it) {
       this->previous_values->operator()(*it, gt).copy(this->operator()(*it, gt));
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void InternalField<T>::removeQuadraturePoints(const ElementTypeMapArray<UInt> & new_numbering) {
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
     ElementTypeMapArray<UInt>::type_iterator it  = new_numbering.firstType(_all_dimensions, gt, _ek_not_defined);
     ElementTypeMapArray<UInt>::type_iterator end = new_numbering.lastType(_all_dimensions, gt, _ek_not_defined);
     for (; it != end; ++it) {
       ElementType type = *it;
       if(this->exists(type, gt)){
 	const Array<UInt> & renumbering = new_numbering(type, gt);
 
 	Array<T> & vect = this->operator()(type, gt);
 
 	UInt nb_quad_per_elem = fem.getNbQuadraturePoints(type, gt);
 	UInt nb_component = vect.getNbComponent();
 
 	Array<T> tmp(renumbering.getSize()*nb_quad_per_elem, nb_component);
 
 	AKANTU_DEBUG_ASSERT(tmp.getSize() == vect.getSize(), "Something strange append some mater was created from nowhere!!");
 
 	AKANTU_DEBUG_ASSERT(tmp.getSize() == vect.getSize(), "Something strange append some mater was created or disappeared in "<< vect.getID() << "("<< vect.getSize() <<"!=" << tmp.getSize() <<") ""!!");
 
 	UInt new_size = 0;
 	for (UInt i = 0; i < renumbering.getSize(); ++i) {
 	  UInt new_i = renumbering(i);
 	  if(new_i != UInt(-1)) {
 	    memcpy(tmp.storage() + new_i * nb_component * nb_quad_per_elem,
 		   vect.storage() + i * nb_component * nb_quad_per_elem,
 		   nb_component * nb_quad_per_elem * sizeof(T));
 	    ++new_size;
 	  }
 	}
 	tmp.resize(new_size * nb_quad_per_elem);
 	vect.copy(tmp);
       }
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 void InternalField<T>::printself(std::ostream & stream, unsigned int indent) const {
   stream << "InternalField [ " << this->getID();
 #if !defined(AKANTU_NDEBUG)
   if(AKANTU_DEBUG_TEST(dblDump)) {
     stream << std::endl;
     InternalField<T>::printself(stream, indent + 3);
   } else {
 #endif
     stream << " {"
 	   << this->getData(_not_ghost).size() << " types - "
 	   << this->getData(_ghost).size() << " ghost types"
 	   << "}";
 #if !defined(AKANTU_NDEBUG)
   }
 #endif
   stream << " ]";
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline void ParsableParamTyped< InternalField<Real> >::parseParam(const ParserParameter & in_param) {
   ParsableParam::parseParam(in_param);
   Real r = in_param;
   param.setDefaultValue(r);
 }
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 inline InternalField<T>::operator T() const {
   return default_value;
 }
 
 
 __END_AKANTU__
 
 #endif /* __AKANTU_INTERNAL_FIELD_TMPL_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc
index 918fd45f2..d85dfba96 100644
--- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc
+++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc
@@ -1,696 +1,698 @@
 /**
  * @file   material_cohesive_linear.cc
  *
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Tue May 08 2012
  * @date last modification: Thu Aug 07 2014
  *
  * @brief  Linear irreversible cohesive law of mixed mode loading with
  * random stress definition for extrinsic type
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 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 <numeric>
 
 /* -------------------------------------------------------------------------- */
 #include "material_cohesive_linear.hh"
 #include "solid_mechanics_model_cohesive.hh"
 #include "sparse_matrix.hh"
 #include "dof_synchronizer.hh"
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 MaterialCohesiveLinear<spatial_dimension>::MaterialCohesiveLinear(SolidMechanicsModel & model,
                                                                   const ID & id) :
   MaterialCohesive(model,id),
   sigma_c_eff("sigma_c_eff", *this),
   delta_c_eff("delta_c_eff", *this),
   insertion_stress("insertion_stress", *this) {
   AKANTU_DEBUG_IN();
 
   this->registerParam("beta"   , beta   , 0. ,
                       _pat_parsable | _pat_readable,
                       "Beta parameter"         );
 
   this->registerParam("G_c"   , G_c   , 0. ,
                       _pat_parsable | _pat_readable,
                       "Mode I fracture energy" );
 
   this->registerParam("penalty", penalty, 0. ,
                       _pat_parsable | _pat_readable,
                       "Penalty coefficient"    );
 
   this->registerParam("volume_s", volume_s, 0. ,
                       _pat_parsable | _pat_readable,
                       "Reference volume for sigma_c scaling");
 
   this->registerParam("m_s", m_s, 1. ,
                       _pat_parsable | _pat_readable,
                       "Weibull exponent for sigma_c scaling");
 
   this->registerParam("kappa"  , kappa  , 1. ,
                       _pat_parsable | _pat_readable,
                       "Kappa parameter");
 
   //  if (!model->isExplicit())
     use_previous_delta_max = true;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
   MaterialCohesive::initMaterial();
 
   /// compute scalars
   beta2_kappa2 = beta * beta/kappa/kappa;
   beta2_kappa  = beta * beta/kappa;
 
   if (Math::are_float_equal(beta, 0))
     beta2_inv = 0;
   else
     beta2_inv = 1./beta/beta;
 
   sigma_c_eff.initialize(1);
   delta_c_eff.initialize(1);
   insertion_stress.initialize(spatial_dimension);
 
   if (!Math::are_float_equal(delta_c, 0.))
     delta_c_eff.setDefaultValue(delta_c);
   else
     delta_c_eff.setDefaultValue(2 * G_c / sigma_c);
 
   if (model->getIsExtrinsic()) scaleInsertionTraction();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::scaleInsertionTraction() {
   AKANTU_DEBUG_IN();
 
   // do nothing if volume_s hasn't been specified by the user
   if (Math::are_float_equal(volume_s, 0.)) return;
 
   const Mesh & mesh_facets = model->getMeshFacets();
   const FEEngine & fe_engine = model->getFEEngine();
   const FEEngine & fe_engine_facet = model->getFEEngine("FacetsFEEngine");
 
   // loop over facet type
   Mesh::type_iterator first = mesh_facets.firstType(spatial_dimension - 1);
   Mesh::type_iterator last  = mesh_facets.lastType(spatial_dimension - 1);
 
   Real base_sigma_c = sigma_c;
 
   for(;first != last; ++first) {
     ElementType type_facet = *first;
 
     const Array< std::vector<Element> > & facet_to_element
       = mesh_facets.getElementToSubelement(type_facet);
 
     UInt nb_facet = facet_to_element.getSize();
     UInt nb_quad_per_facet = fe_engine_facet.getNbQuadraturePoints(type_facet);
 
     // iterator to modify sigma_c for all the quadrature points of a facet
     Array<Real>::vector_iterator sigma_c_iterator
       = sigma_c(type_facet).begin_reinterpret(nb_quad_per_facet, nb_facet);
 
     for (UInt f = 0; f < nb_facet; ++f, ++sigma_c_iterator) {
 
       const std::vector<Element> & element_list = facet_to_element(f);
 
       // compute bounding volume
       Real volume = 0;
 
       std::vector<Element>::const_iterator elem = element_list.begin();
       std::vector<Element>::const_iterator elem_end = element_list.end();
 
       for (; elem != elem_end; ++elem) {
         if (*elem == ElementNull) continue;
 
         // unit vector for integration in order to obtain the volume
         UInt nb_quadrature_points = fe_engine.getNbQuadraturePoints(elem->type);
         Vector<Real> unit_vector(nb_quadrature_points, 1);
 
         volume += fe_engine.integrate(unit_vector, elem->type,
                                       elem->element, elem->ghost_type);
       }
 
       // scale sigma_c
       *sigma_c_iterator -= base_sigma_c;
       *sigma_c_iterator *= std::pow(volume_s / volume, 1. / m_s);
       *sigma_c_iterator += base_sigma_c;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::checkInsertion(bool check_only) {
   AKANTU_DEBUG_IN();
 
   const Mesh & mesh_facets = model->getMeshFacets();
   CohesiveElementInserter & inserter = model->getElementInserter();
 
   Real tolerance = Math::getTolerance();
 
   Mesh::type_iterator it   = mesh_facets.firstType(spatial_dimension - 1);
   Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1);
 
   for (; it != last; ++it) {
     ElementType type_facet = *it;
     ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
     const Array<bool> & facets_check = inserter.getCheckFacets(type_facet);
     Array<bool> & f_insertion = inserter.getInsertionFacets(type_facet);
     Array<UInt> & f_filter = facet_filter(type_facet);
     Array<Real> & sig_c_eff = sigma_c_eff(type_cohesive);
     Array<Real> & del_c = delta_c_eff(type_cohesive);
     Array<Real> & ins_stress = insertion_stress(type_cohesive);
     Array<Real> & trac_old = tractions_old(type_cohesive);
     const Array<Real> & f_stress = model->getStressOnFacets(type_facet);
     const Array<Real> & sigma_lim = sigma_c(type_facet);
     Real max_ratio = 0.;
     UInt index_f = 0;
     UInt index_filter = 0;
     UInt nn = 0;
 
 
     UInt nb_quad_facet = model->getFEEngine("FacetsFEEngine").getNbQuadraturePoints(type_facet);
     UInt nb_facet = f_filter.getSize();
     if (nb_facet == 0) continue;
 
     Array<Real>::const_iterator<Real> sigma_lim_it = sigma_lim.begin();
 
     Matrix<Real> stress_tmp(spatial_dimension, spatial_dimension);
     Matrix<Real> normal_traction(spatial_dimension, nb_quad_facet);
     Vector<Real> stress_check(nb_quad_facet);
     UInt sp2 = spatial_dimension * spatial_dimension;
 
     const Array<Real> & tangents = model->getTangents(type_facet);
     const Array<Real> & normals
       = model->getFEEngine("FacetsFEEngine").getNormalsOnQuadPoints(type_facet);
     Array<Real>::const_vector_iterator normal_begin = normals.begin(spatial_dimension);
     Array<Real>::const_vector_iterator tangent_begin = tangents.begin(tangents.getNbComponent());
     Array<Real>::const_matrix_iterator facet_stress_begin =
       f_stress.begin(spatial_dimension, spatial_dimension * 2);
 
     std::vector<Real> new_sigmas;
     std::vector< Vector<Real> > new_normal_traction;
     std::vector<Real> new_delta_c;
 
     // loop over each facet belonging to this material
     for (UInt f = 0; f < nb_facet; ++f, ++sigma_lim_it) {
       UInt facet = f_filter(f);
       // skip facets where check shouldn't be realized
       if (!facets_check(facet)) continue;
 
       // compute the effective norm on each quadrature point of the facet
       for (UInt q = 0; q < nb_quad_facet; ++q) {
 	UInt current_quad = facet * nb_quad_facet + q;
 	const Vector<Real> & normal = normal_begin[current_quad];
 	const Vector<Real> & tangent = tangent_begin[current_quad];
 	const Matrix<Real> & facet_stress_it = facet_stress_begin[current_quad];
 
 	// compute average stress on the current quadrature point
 	Matrix<Real> stress_1(facet_stress_it.storage(),
 			      spatial_dimension,
 			      spatial_dimension);
 
 	Matrix<Real> stress_2(facet_stress_it.storage() + sp2,
 			      spatial_dimension,
 			      spatial_dimension);
 
 	stress_tmp.copy(stress_1);
 	stress_tmp += stress_2;
 	stress_tmp /= 2.;
 
 	Vector<Real> normal_traction_vec(normal_traction(q));
 
 	// compute normal and effective stress
 	stress_check(q) = computeEffectiveNorm(stress_tmp, normal, tangent,
 					       normal_traction_vec);
       }
 
       // verify if the effective stress overcomes the threshold
       if (stress_check.mean() > (*sigma_lim_it - tolerance)) {
 
         if (model->isExplicit()){
           f_insertion(facet) = true;
 
 	  if (!check_only) {
 	    // store the new cohesive material parameters for each quadrature point
 	    for (UInt q = 0; q < nb_quad_facet; ++q) {
 	      Real new_sigma = stress_check(q);
 	      Vector<Real> normal_traction_vec(normal_traction(q));
 
 	      if (spatial_dimension != 3)
 		normal_traction_vec *= -1.;
 
 	      new_sigmas.push_back(new_sigma);
 	      new_normal_traction.push_back(normal_traction_vec);
 
 	      Real new_delta;
 
 	      // set delta_c in function of G_c or a given delta_c value
 	      if (Math::are_float_equal(delta_c, 0.))
 		new_delta = 2 * G_c / new_sigma;
 	      else
 		new_delta = (*sigma_lim_it) / new_sigma * delta_c;
 
 	      new_delta_c.push_back(new_delta);
 	    }
 	  }
 
         }else{
           Real ratio = stress_check.mean()/(*sigma_lim_it);
           if (ratio > max_ratio){
+            std::cout << "ratio = " << ratio << std::endl;
             ++nn;
             max_ratio = ratio;
             index_f = f;
             index_filter = f_filter(f);
           }
         }
       }
     }
 
     /// insertion of only 1 cohesive element in case of implicit approach. The one subjected to the highest stress.
     if (!model->isExplicit()){
       StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
       Array<Real> abs_max(comm.getNbProc());
       abs_max(comm.whoAmI()) = max_ratio;
       comm.allGather(abs_max.storage(), 1);
 
       Array<Real>::scalar_iterator it = std::max_element(abs_max.begin(), abs_max.end());
       Int pos = it - abs_max.begin();
 
       if (pos != comm.whoAmI()) {
       	AKANTU_DEBUG_OUT();
       	return;
       }
 
       if (nn) {
 	f_insertion(index_filter) = true;
 
 	if (!check_only) {
 	  //  Array<Real>::iterator<Matrix<Real> > normal_traction_it =
 	  //  normal_traction.begin_reinterpret(nb_quad_facet, spatial_dimension, nb_facet);
 	  Array<Real>::const_iterator<Real> sigma_lim_it = sigma_lim.begin();
 
 	  for (UInt q = 0; q < nb_quad_facet; ++q) {
 
 	    //  Vector<Real> ins_s(normal_traction_it[index_f].storage() + q * spatial_dimension,
 	    //            spatial_dimension);
 
 	    Real new_sigma = (sigma_lim_it[index_f]);
+            Vector<Real> normal_traction_vec(spatial_dimension, 0.0);
 
 	    new_sigmas.push_back(new_sigma);
-	    new_normal_traction.push_back(0.0);
+	    new_normal_traction.push_back(normal_traction_vec);
 
 	    Real new_delta;
 
 	    //set delta_c in function of G_c or a given delta_c value
 	    if (!Math::are_float_equal(delta_c, 0.))
 	      new_delta = delta_c;
 	    else
 	      new_delta = 2 * G_c / (new_sigma);
 
 	    new_delta_c.push_back(new_delta);
 	  }
 
 	}
       }
     }
 
     // update material data for the new elements
     UInt old_nb_quad_points = sig_c_eff.getSize();
     UInt new_nb_quad_points = new_sigmas.size();
     sig_c_eff.resize(old_nb_quad_points + new_nb_quad_points);
     ins_stress.resize(old_nb_quad_points + new_nb_quad_points);
     trac_old.resize(old_nb_quad_points + new_nb_quad_points);
     del_c.resize(old_nb_quad_points + new_nb_quad_points);
 
     for (UInt q = 0; q < new_nb_quad_points; ++q) {
       sig_c_eff(old_nb_quad_points + q) = new_sigmas[q];
       del_c(old_nb_quad_points + q) = new_delta_c[q];
       for (UInt dim = 0; dim < spatial_dimension; ++dim) {
  	ins_stress(old_nb_quad_points + q, dim) = new_normal_traction[q](dim);
  	trac_old(old_nb_quad_points + q, dim) = new_normal_traction[q](dim);
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::computeTraction(const Array<Real> & normal,
                                                                 ElementType el_type,
                                                                 GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /// define iterators
   Array<Real>::iterator< Vector<Real> > traction_it =
     tractions(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::iterator< Vector<Real> > opening_it =
     opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::iterator< Vector<Real> > contact_traction_it =
     contact_tractions(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::iterator< Vector<Real> > contact_opening_it =
     contact_opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::const_iterator< Vector<Real> > normal_it =
     normal.begin(spatial_dimension);
 
   Array<Real>::iterator< Vector<Real> >traction_end =
     tractions(el_type, ghost_type).end(spatial_dimension);
 
   Array<Real>::iterator<Real>sigma_c_it =
     sigma_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real>delta_max_it =
     delta_max(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real>delta_max_prev_it =
     delta_max.previous(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real>delta_c_it =
     delta_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real>damage_it =
     damage(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Vector<Real> > insertion_stress_it =
     insertion_stress(el_type, ghost_type).begin(spatial_dimension);
 
 
   Real * memory_space = new Real[2*spatial_dimension];
   Vector<Real> normal_opening(memory_space, spatial_dimension);
   Vector<Real> tangential_opening(memory_space + spatial_dimension,
                                   spatial_dimension);
 
   /// loop on each quadrature point
   for (; traction_it != traction_end;
        ++traction_it, ++opening_it, ++normal_it, ++sigma_c_it,
          ++delta_max_it, ++delta_c_it, ++damage_it, ++contact_traction_it,
          ++insertion_stress_it, ++contact_opening_it, ++delta_max_prev_it) {
 
     if (!model->isExplicit())
       *delta_max_it = *delta_max_prev_it;
 
     /// compute normal and tangential opening vectors
     Real normal_opening_norm = opening_it->dot(*normal_it);
     normal_opening  = (*normal_it);
     normal_opening *= normal_opening_norm;
 
     tangential_opening  = *opening_it;
     tangential_opening -=  normal_opening;
 
     Real tangential_opening_norm = tangential_opening.norm();
 
     /**
      * compute effective opening displacement
      * @f$ \delta = \sqrt{
      * \frac{\beta^2}{\kappa^2} \Delta_t^2 + \Delta_n^2 } @f$
      */
     Real delta = tangential_opening_norm * tangential_opening_norm * beta2_kappa2;
 
     bool penetration = normal_opening_norm < -Math::getTolerance();
 
     if (penetration) {
       /// use penalty coefficient in case of penetration
       *contact_traction_it = normal_opening;
       *contact_traction_it *= penalty;
       *contact_opening_it = normal_opening;
       /// don't consider penetration contribution for delta
       *opening_it = tangential_opening;
       normal_opening.clear();
     }
     else {
       delta += normal_opening_norm * normal_opening_norm;
       contact_traction_it->clear();
       contact_opening_it->clear();
     }
 
     delta = std::sqrt(delta);
 
     /// update maximum displacement and damage
     *delta_max_it = std::max(*delta_max_it, delta);
     *damage_it = std::min(*delta_max_it / *delta_c_it, 1.);
 
     /**
      * Compute traction @f$ \mathbf{T} = \left(
      * \frac{\beta^2}{\kappa} \Delta_t \mathbf{t} + \Delta_n
      * \mathbf{n} \right) \frac{\sigma_c}{\delta} \left( 1-
      * \frac{\delta}{\delta_c} \right)@f$
      */
 
     if (Math::are_float_equal(*damage_it, 1.))
       traction_it->clear();
     else if (Math::are_float_equal(*damage_it, 0.)) {
       if (penetration)
         traction_it->clear();
       else
         *traction_it = *insertion_stress_it;
     }
     else {
       *traction_it  = tangential_opening;
       *traction_it *= beta2_kappa;
       *traction_it += normal_opening;
 
       AKANTU_DEBUG_ASSERT(*delta_max_it != 0.,
                           "Division by zero, tolerance might be too low");
 
       *traction_it *= *sigma_c_it / *delta_max_it * (1. - *damage_it);
 
     }
   }
 
   delete [] memory_space;
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::checkDeltaMax(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /// This function set a predefined value to the parameter delta_max_prev of the
   /// elements that have been inserted in the last loading step for which convergence
   /// has not been reached. This is done before reducing the loading and re-doing the step.
   /// Otherwise, the updating of delta_max_prev would be done with reference to the
   /// non-convergent solution.
 
   Mesh & mesh = fem_cohesive->getMesh();
   Mesh::type_iterator it = mesh.firstType(spatial_dimension,
 					  ghost_type, _ek_cohesive);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension,
 						ghost_type, _ek_cohesive);
 
   for(; it != last_type; ++it) {
     Array<UInt> & elem_filter = element_filter(*it, ghost_type);
 
     UInt nb_element = elem_filter.getSize();
     if (nb_element == 0) continue;
 
     ElementType el_type = *it;
 
     /// define iterators
     Array<Real>::iterator<Real>delta_max_it =
       delta_max(el_type, ghost_type).begin();
 
     Array<Real>::iterator<Real>delta_max_end =
       delta_max(el_type, ghost_type).end();
 
     Array<Real>::iterator<Real>delta_max_prev_it =
       delta_max.previous(el_type, ghost_type).begin();
 
     Array<Real>::iterator<Real>delta_c_it =
       delta_c_eff(el_type, ghost_type).begin();
 
 
     /// loop on each quadrature point
     for (; delta_max_it != delta_max_end;
          ++delta_max_it, ++delta_max_prev_it, ++delta_c_it) {
 
       if (*delta_max_prev_it == 0)
         /// elements inserted in the last step, that has not converged
         *delta_max_it = *delta_c_it / 1000;
       else
         /// elements introduced in previous steps, for which a correct
         /// value of delta_max_prev already exists
         *delta_max_it = *delta_max_prev_it;
 
     }
   }
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::computeTangentTraction(const ElementType & el_type,
                                                                        Array<Real> & tangent_matrix,
                                                                        const Array<Real> & normal,
                                                                        GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /// define iterators
   Array<Real>::matrix_iterator tangent_it =
     tangent_matrix.begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::matrix_iterator tangent_end =
     tangent_matrix.end(spatial_dimension, spatial_dimension);
 
   Array<Real>::const_vector_iterator normal_it =
     normal.begin(spatial_dimension);
 
   Array<Real>::vector_iterator opening_it =
     opening(el_type, ghost_type).begin(spatial_dimension);
 
   Array<Real>::iterator<Real>delta_max_it =
     delta_max.previous(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real>sigma_c_it =
     sigma_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real>delta_c_it =
     delta_c_eff(el_type, ghost_type).begin();
 
   Array<Real>::iterator<Real>damage_it =
     damage(el_type, ghost_type).begin();
 
   Array<Real>::iterator< Vector<Real> > contact_opening_it =
     contact_opening(el_type, ghost_type).begin(spatial_dimension);
 
   Vector<Real> normal_opening(spatial_dimension);
   Vector<Real> tangential_opening(spatial_dimension);
 
   Array<Real> tang_output(spatial_dimension,spatial_dimension);
 
   for (; tangent_it != tangent_end;
        ++tangent_it, ++normal_it, ++opening_it, ++ delta_max_it,
          ++sigma_c_it, ++delta_c_it, ++damage_it, ++contact_opening_it) {
 
     /// compute normal and tangential opening vectors
     *opening_it += *contact_opening_it;
     Real normal_opening_norm = opening_it->dot(*normal_it);
     normal_opening = (*normal_it);
     normal_opening *= normal_opening_norm;
 
     tangential_opening = *opening_it;
     tangential_opening -= normal_opening;
 
     Real tangential_opening_norm = tangential_opening.norm();
     bool penetration = normal_opening_norm < -Math::getTolerance();
     Real derivative = 0;
     Real t = 0;
 
     Real delta = tangential_opening_norm * tangential_opening_norm * beta2_kappa2;
     delta += normal_opening_norm * normal_opening_norm;
     delta = std::sqrt(delta);
 
     /// Delta has to be different from 0 to have finite values of tangential stiffness.
     /// At the element insertion, delta = 0. Therefore, a fictictious value is defined,
     /// for the evaluation of the first value of K.
     if (delta < Math::getTolerance())
       delta = (*delta_c_it)/1000.;
 
     if (normal_opening_norm >= 0.0){
       if (delta >= *delta_max_it){
         derivative = -*sigma_c_it/(delta * delta);
         t = *sigma_c_it * (1 - delta / *delta_c_it);
       }	else if (delta < *delta_max_it){
         Real tmax = *sigma_c_it * (1 - *delta_max_it / *delta_c_it);
         t = tmax / *delta_max_it * delta;
       }
     }
 
     Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
     n_outer_n.outerProduct(*normal_it, *normal_it);
 
     if (penetration){
       /// don't consider penetration contribution for delta
       *opening_it = tangential_opening;
       /// stiffness in compression given by the penalty parameter
       *tangent_it += n_outer_n;
       *tangent_it *= penalty;
     }
 
     /// computation of the derivative of the constitutive law (dT/ddelta)
     Matrix<Real> I(spatial_dimension, spatial_dimension);
     I.eye(beta2_kappa);
     Matrix<Real> nn(n_outer_n);
     nn *= (1 - beta2_kappa);
     nn += I;
     nn *= t/delta;
     Vector<Real> t_tilde(normal_opening);
     t_tilde *= (1 - beta2_kappa2);
     Vector<Real> mm(*opening_it);
     mm *= beta2_kappa2;
     t_tilde += mm;
     Vector<Real> t_hat(normal_opening);
     t_hat += beta2_kappa * tangential_opening;
     Matrix<Real> prov(spatial_dimension, spatial_dimension);
     prov.outerProduct(t_hat, t_tilde);
     prov *= derivative/delta;
     prov += nn;
     *tangent_it += prov;
 
     /// check if the tangential stiffness matrix is symmetric
     for (UInt h = 0; h < spatial_dimension; ++h){
       for (UInt l = h; l < spatial_dimension; ++l){
         if (l > h){
           Real k_ls = (*tangent_it)[spatial_dimension*h+l];
           Real k_us =  (*tangent_it)[spatial_dimension*l+h];
           //          std::cout << "k_ls = " << k_ls << std::endl;
           //          std::cout << "k_us = " << k_us << std::endl;
           if (std::abs(k_ls) > 1e-13 && std::abs(k_us) > 1e-13){
             Real error = std::abs((k_ls - k_us) / k_us);
             if (error > 1e-13){
               std::cout << "non symmetric cohesive matrix" << std::endl;
               std::cout << "error " << error << std::endl;
             }
           }
         }
       }
     }
   }
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 
 
 INSTANSIATE_MATERIAL(MaterialCohesiveLinear);
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/materials/material_elastic.cc b/src/model/solid_mechanics/materials/material_elastic.cc
index 4787baf68..999bc7e93 100644
--- a/src/model/solid_mechanics/materials/material_elastic.cc
+++ b/src/model/solid_mechanics/materials/material_elastic.cc
@@ -1,229 +1,248 @@
 /**
  * @file   material_elastic.cc
  *
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  *
  * @date creation: Tue Jul 27 2010
  * @date last modification: Tue Sep 16 2014
  *
  * @brief  Specialization of the material class for the elastic material
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_elastic.hh"
 #include "solid_mechanics_model.hh"
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model, const ID & id)  :
   Material(model, id),
   Parent(model, id) {
   AKANTU_DEBUG_IN();
+  this->initialize();
+  AKANTU_DEBUG_OUT();
+}
 
+/* -------------------------------------------------------------------------- */
+template<UInt dim>
+MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model,
+                                      UInt a_dim,
+                                      const Mesh & mesh,
+                                      FEEngine & fe_engine,
+                                      const ID & id) :
+  Material(model, dim, mesh, fe_engine, id),
+  Parent(model, dim, mesh, fe_engine, id) {
+  AKANTU_DEBUG_IN();
+  this->initialize();
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template<UInt dim>
+void MaterialElastic<dim>::initialize() {
   this->registerParam("lambda"      ,lambda             , _pat_readable, "First Lamé coefficient" );
   this->registerParam("mu"          ,mu                 , _pat_readable, "Second Lamé coefficient");
   this->registerParam("kapa"        ,kpa                , _pat_readable, "Bulk coefficient"       );
-
-  AKANTU_DEBUG_OUT();
 }
 
+
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 void MaterialElastic<dim>::initMaterial() {
   AKANTU_DEBUG_IN();
   Parent::initMaterial();
 
-  if (dim == 1) this->nu = 0.;
+  if (dim == 1) this->nu = 0.5;
 
   this->updateInternalParameters();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 void MaterialElastic<dim>::updateInternalParameters() {
   MaterialThermal<dim>::updateInternalParameters();
 
   this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2*this->nu));
   this->mu     = this->E / (2 * (1 + this->nu));
 
   this->kpa    = this->lambda + 2./3. * this->mu;
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 void MaterialElastic<2>::updateInternalParameters() {
   MaterialThermal<2>::updateInternalParameters();
 
   this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2*this->nu));
   this->mu     = this->E / (2 * (1 + this->nu));
 
   if(this->plane_stress) this->lambda = this->nu * this->E / ((1 + this->nu)*(1 - this->nu));
 
   this->kpa    = this->lambda + 2./3. * this->mu;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialElastic<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Parent::computeStress(el_type, ghost_type);
 
   Array<Real>::const_scalar_iterator sigma_th_it = this->sigma_th(el_type, ghost_type).begin();
 
   if (!this->finite_deformation) {
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
     const Real & sigma_th = *sigma_th_it;
     this->computeStressOnQuad(grad_u, sigma, sigma_th);
     ++sigma_th_it;
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   } else {
     /// finite gradus
     Matrix<Real> E(spatial_dimension, spatial_dimension);
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
     /// compute E
     this->template gradUToGreenStrain<spatial_dimension>(grad_u, E);
 
     const Real & sigma_th = *sigma_th_it;
 
     /// compute second Piola-Kirchhoff stress tensor
     this->computeStressOnQuad(E, sigma, sigma_th);
 
     ++sigma_th_it;
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialElastic<spatial_dimension>::computeTangentModuli(__attribute__((unused)) const ElementType & el_type,
                                                               Array<Real> & tangent_matrix,
                                                               __attribute__((unused)) GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
   this->computeTangentModuliOnQuad(tangent);
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 Real MaterialElastic<spatial_dimension>::getPushWaveSpeed(__attribute__((unused)) const Element & element) const {
   return sqrt((lambda + 2*mu)/this->rho);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 Real MaterialElastic<spatial_dimension>::getShearWaveSpeed(__attribute__((unused)) const Element & element) const {
   return sqrt(mu/this->rho);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialElastic<spatial_dimension>::computePotentialEnergy(ElementType el_type,
                                                                 GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MaterialThermal<spatial_dimension>::computePotentialEnergy(el_type, ghost_type);
 
   if(ghost_type != _not_ghost) return;
   Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin();
 
   if (!this->finite_deformation) {
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
     this->computePotentialEnergyOnQuad(grad_u, sigma, *epot);
     ++epot;
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   } else {
     Matrix<Real> E(spatial_dimension, spatial_dimension);
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
     this->template gradUToGreenStrain<spatial_dimension>(grad_u, E);
 
     this->computePotentialEnergyOnQuad(E, sigma, *epot);
     ++epot;
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialElastic<spatial_dimension>::computePotentialEnergyByElement(ElementType type, UInt index,
                                                                          Vector<Real> & epot_on_quad_points) {
   Array<Real>::matrix_iterator gradu_it =
     this->gradu(type).begin(spatial_dimension,
                              spatial_dimension);
   Array<Real>::matrix_iterator gradu_end =
     this->gradu(type).begin(spatial_dimension,
                              spatial_dimension);
   Array<Real>::matrix_iterator stress_it =
     this->stress(type).begin(spatial_dimension,
                              spatial_dimension);
 
   if (this->finite_deformation)
     stress_it = this->piola_kirchhoff_2(type).begin(spatial_dimension,
                                                          spatial_dimension);
 
   UInt nb_quadrature_points = this->model->getFEEngine().getNbQuadraturePoints(type);
 
   gradu_it  += index*nb_quadrature_points;
   gradu_end += (index+1)*nb_quadrature_points;
   stress_it  += index*nb_quadrature_points;
 
   Real * epot_quad = epot_on_quad_points.storage();
 
   Matrix<Real> grad_u(spatial_dimension, spatial_dimension);
 
   for(;gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) {
 
     if (this->finite_deformation)
       this->template gradUToGreenStrain<spatial_dimension>(*gradu_it, grad_u);
     else
       grad_u.copy(*gradu_it);
 
     this->computePotentialEnergyOnQuad(grad_u, *stress_it, *epot_quad);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 
 
 INSTANSIATE_MATERIAL(MaterialElastic);
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/materials/material_elastic.hh b/src/model/solid_mechanics/materials/material_elastic.hh
index 5f9f0f810..9b0702649 100644
--- a/src/model/solid_mechanics/materials/material_elastic.hh
+++ b/src/model/solid_mechanics/materials/material_elastic.hh
@@ -1,140 +1,148 @@
 /**
  * @file   material_elastic.hh
  *
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Aug 04 2010
  * @date last modification: Tue Sep 16 2014
  *
  * @brief  Material isotropic elastic
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "material_thermal.hh"
 #include "plane_stress_toolbox.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_ELASTIC_HH__
 #define __AKANTU_MATERIAL_ELASTIC_HH__
 
 __BEGIN_AKANTU__
 
 /**
  * Material elastic isotropic
  *
  * parameters in the material files :
  *   - E   : Young's modulus (default: 0)
  *   - nu  : Poisson's ratio (default: 1/2)
  *   - Plane_Stress : if 0: plane strain, else: plane stress (default: 0)
  */
 template<UInt spatial_dimension>
 class MaterialElastic : public PlaneStressToolbox< spatial_dimension,
                                                    MaterialThermal<spatial_dimension> > {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 private:
   typedef  PlaneStressToolbox< spatial_dimension,
                                MaterialThermal<spatial_dimension> > Parent;
 public:
 
   MaterialElastic(SolidMechanicsModel & model, const ID & id = "");
+  MaterialElastic(SolidMechanicsModel & model,
+                  UInt dim,
+                  const Mesh & mesh,
+                  FEEngine & fe_engine,
+                  const ID & id = "");
 
   virtual ~MaterialElastic() {}
 
+protected:
+  void initialize();
+
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   virtual void initMaterial();
 
   /// constitutive law for all element of a type
   virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
 
   /// compute the tangent stiffness matrix for an element type
   virtual void computeTangentModuli(const ElementType & el_type,
 				    Array<Real> & tangent_matrix,
 				    GhostType ghost_type = _not_ghost);
 
   /// compute the elastic potential energy
   virtual void computePotentialEnergy(ElementType el_type,
 				      GhostType ghost_type = _not_ghost);
 
   virtual void computePotentialEnergyByElement(ElementType type, UInt index,
 					       Vector<Real> & epot_on_quad_points);
 
   /// compute the p-wave speed in the material
   virtual Real getPushWaveSpeed(const Element & element) const;
 
   /// compute the s-wave speed in the material
   virtual Real getShearWaveSpeed(const Element & element) const;
 
 protected:
   /// constitutive law for a given quadrature point
   inline void computeStressOnQuad(const Matrix<Real> & grad_u,
 				  Matrix<Real> & sigma,
 				  const Real sigma_th = 0) const;
 
   /// compute the tangent stiffness matrix for an element
-  inline void computeTangentModuliOnQuad(Matrix<Real> & tangent);
+  inline void computeTangentModuliOnQuad(Matrix<Real> & tangent) const;
 
   /// recompute the lame coefficient if E or nu changes
   virtual void updateInternalParameters();
 
   static inline void computePotentialEnergyOnQuad(const Matrix<Real> & grad_u,
 						  const Matrix<Real> & sigma,
 						  Real & epot);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
 
   /// First Lamé coefficient
   Real lambda;
 
   /// Second Lamé coefficient (shear modulus)
   Real mu;
 
   /// Bulk modulus
   Real kpa;
 
 };
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 #include "material_elastic_inline_impl.cc"
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MATERIAL_ELASTIC_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_elastic_inline_impl.cc b/src/model/solid_mechanics/materials/material_elastic_inline_impl.cc
index 8f3bc379d..829b7ac36 100644
--- a/src/model/solid_mechanics/materials/material_elastic_inline_impl.cc
+++ b/src/model/solid_mechanics/materials/material_elastic_inline_impl.cc
@@ -1,107 +1,107 @@
 /**
  * @file   material_elastic_inline_impl.cc
  *
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Aug 04 2010
  * @date last modification: Mon Apr 07 2014
  *
  * @brief  Implementation of the inline functions of the material elastic
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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<UInt spatial_dimension>
 inline void MaterialElastic<spatial_dimension>::computeStressOnQuad(const Matrix<Real> & grad_u,
 								    Matrix<Real> & sigma,
 								    const Real sigma_th) const {
   Real trace = grad_u.trace(); // trace = (\nabla u)_{kk}
 
   // \sigma_{ij} = \lambda * (\nabla u)_{kk} * \delta_{ij} + \mu * (\nabla u_{ij} + \nabla u_{ji})
   for (UInt i = 0; i < spatial_dimension; ++i) {
     for (UInt j = 0; j < spatial_dimension; ++j) {
       sigma(i, j) =  (i == j)*lambda*trace + mu*(grad_u(i, j) + grad_u(j, i)) + (i == j) * sigma_th;
     }
   }
 
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline void MaterialElastic<1>::computeStressOnQuad(const Matrix<Real> & grad_u,
 						    Matrix<Real> & sigma,
 						    Real sigma_th) const {
   sigma(0, 0) = this->E * grad_u(0, 0) + sigma_th;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
-inline void MaterialElastic<spatial_dimension>::computeTangentModuliOnQuad(Matrix<Real> & tangent) {
+inline void MaterialElastic<spatial_dimension>::computeTangentModuliOnQuad(Matrix<Real> & tangent) const {
   UInt n = tangent.cols();
 
   //Real Ep = E/((1+nu)*(1-2*nu));
   Real Miiii = lambda + 2*mu;
   Real Miijj = lambda;
   Real Mijij = mu;
 
   if(spatial_dimension == 1)
     tangent(0, 0) = this->E;
   else
     tangent(0, 0) = Miiii;
 
   // test of dimension should by optimized out by the compiler due to the template
   if(spatial_dimension >= 2) {
     tangent(1, 1) = Miiii;
     tangent(0, 1) = Miijj;
     tangent(1, 0) = Miijj;
 
     tangent(n - 1, n - 1) = Mijij;
   }
 
   if(spatial_dimension == 3) {
     tangent(2, 2) = Miiii;
     tangent(0, 2) = Miijj;
     tangent(1, 2) = Miijj;
     tangent(2, 0) = Miijj;
     tangent(2, 1) = Miijj;
 
     tangent(3, 3) = Mijij;
     tangent(4, 4) = Mijij;
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 inline void MaterialElastic<dim>::computePotentialEnergyOnQuad(const Matrix<Real> & grad_u,
 							       const Matrix<Real> & sigma,
 							       Real & epot) {
   epot = .5 * sigma.doubleDot(grad_u);
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
-inline void MaterialElastic<1>::computeTangentModuliOnQuad(Matrix<Real> & tangent) {
+inline void MaterialElastic<1>::computeTangentModuliOnQuad(Matrix<Real> & tangent) const {
   tangent(0, 0) = E;
 }
 
diff --git a/src/model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh b/src/model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh
index 6370db542..3c20a1b5e 100644
--- a/src/model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh
+++ b/src/model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh
@@ -1,43 +1,43 @@
 /**
  * @file   material_embedded_includes.hh
  *
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @date creation: Fri Mar 13 2015
  * @date last modification: Fri Mar 13 2015
  *
  * @brief  List of includes for embedded elements
  *
  * @section LICENSE
  *
  * Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #ifndef AKANTU_CMAKE_LIST_MATERIALS
 #  include "material_reinforcement.hh"
 #  include "material_reinforcement_template.hh"
 #endif
 
 #define AKANTU_MATERIAL_REINFORCEMENT_LAW_TMPL_LIST       \
-  ((elastic, (MaterialElastic<1>))) 
-  //((plastic_law, (MaterialLinearIsotropicHardening  )))
+  ((elastic, (MaterialElastic<1>)))                       \
+  ((plastic, (MaterialLinearIsotropicHardening<1>)))
 
 #define AKANTU_EMBEDDED_MATERIAL_LIST                     \
   ((3, (reinforcement, MaterialReinforcementTemplate,     \
         AKANTU_MATERIAL_REINFORCEMENT_LAW_TMPL_LIST )))
diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc
index acc78525e..552ba3bd3 100644
--- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc
+++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc
@@ -1,744 +1,758 @@
 /**
  * @file   material_reinforcement.cc
  *
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @date creation: Thu Mar 12 2015
  * @date last modification: Thu Mar 12 2015
  *
  * @brief  Reinforcement material
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #include "aka_common.hh"
 #include "aka_voigthelper.hh"
 #include "material_reinforcement.hh"
 
 __BEGIN_AKANTU__
 
+/* -------------------------------------------------------------------------- */
 template<UInt dim>
-MaterialReinforcement<dim>::MaterialReinforcement(SolidMechanicsModel & model, const ID & id):
-  Material(model, id),
+MaterialReinforcement<dim>::MaterialReinforcement(SolidMechanicsModel & model,
+                                                  UInt spatial_dimension,
+                                                  const Mesh & mesh,
+                                                  FEEngine & fe_engine,
+                                                  const ID & id) :
+  Material(model, dim, mesh, fe_engine, id), // /!\ dim, not spatial_dimension !
   model(NULL),
-  gradu("gradu_embedded", *this),
-  stress("stress_embedded", *this),
-  directing_cosines("directing_cosines", *this),
-  pre_stress("pre_stress", *this),
+  stress_embedded("stress_embedded", *this, 1, fe_engine, this->element_filter),
+  gradu_embedded("gradu_embedded", *this, 1, fe_engine, this->element_filter),
+  directing_cosines("directing_cosines", *this, 1, fe_engine, this->element_filter),
+  pre_stress("pre_stress", *this, 1, fe_engine, this->element_filter),
   area(1.0),
-  shape_derivatives()
-{
-  this->model = dynamic_cast<EmbeddedInterfaceModel *>(&model);
+  shape_derivatives() {
+  AKANTU_DEBUG_IN();
+  this->initialize(model);
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template<UInt dim>
+void MaterialReinforcement<dim>::initialize(SolidMechanicsModel & a_model) {
+  this->model = dynamic_cast<EmbeddedInterfaceModel *>(&a_model);
   AKANTU_DEBUG_ASSERT(this->model != NULL, "MaterialReinforcement needs an EmbeddedInterfaceModel");
 
-  this->model->getInterfaceMesh().initElementTypeMapArray(element_filter, 1, 1,
-                                                          false, _ek_regular);
+  this->registerParam("area", area, _pat_parsable | _pat_modifiable,
+                      "Reinforcement cross-sectional area");
+  this->registerParam("pre_stress", pre_stress, _pat_parsable | _pat_modifiable,
+                      "Uniform pre-stress");
 
-  this->registerParam("area", area, _pat_parsable | _pat_modifiable, "Reinforcement cross-sectional area");
-  this->registerParam("pre_stress", pre_stress, _pat_parsable | _pat_modifiable, "Uniform pre-stress");
+  this->element_filter.free();
+  this->model->getInterfaceMesh().initElementTypeMapArray(this->element_filter,
+                                                          1, 1, false, _ek_regular);
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 MaterialReinforcement<dim>::~MaterialReinforcement() {
   AKANTU_DEBUG_IN();
   
   ElementTypeMap<ElementTypeMapArray<Real> *>::type_iterator it = shape_derivatives.firstType();
   ElementTypeMap<ElementTypeMapArray<Real> *>::type_iterator end = shape_derivatives.lastType();
 
   for (; it != end ; ++it) {
     delete shape_derivatives(*it, _not_ghost);
     delete shape_derivatives(*it, _ghost);
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::initMaterial() {
   Material::initMaterial();
 
-  gradu.initialize(dim * dim);
-  stress.initialize(dim * dim);
+  stress_embedded.initialize(dim * dim); // Check this
+  gradu_embedded.initialize(dim * dim);
   pre_stress.initialize(1);
 
-
   /// We initialise the stuff that is not going to change during the simulation
   this->allocBackgroundShapeDerivatives();
   this->initBackgroundShapeDerivatives();
   this->initDirectingCosines();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::allocBackgroundShapeDerivatives() {
   AKANTU_DEBUG_IN();
   
   Mesh & interface_mesh = model->getInterfaceMesh();
   Mesh & mesh = model->getMesh();
 
 
   ghost_type_t::iterator int_ghost_it = ghost_type_t::begin();
 
   // Loop over interface ghosts
   for (; int_ghost_it != ghost_type_t::end() ; ++int_ghost_it) {
-    Mesh::type_iterator interface_type_it = interface_mesh.firstType();
-    Mesh::type_iterator interface_type_end = interface_mesh.lastType();
+    Mesh::type_iterator interface_type_it = interface_mesh.firstType(1, *int_ghost_it);
+    Mesh::type_iterator interface_type_end = interface_mesh.lastType(1, *int_ghost_it);
 
     for (; interface_type_it != interface_type_end ; ++interface_type_it) {
       Mesh::type_iterator background_type_it = mesh.firstType(dim, *int_ghost_it);
       Mesh::type_iterator background_type_end = mesh.lastType(dim, *int_ghost_it);
 
       for (; background_type_it != background_type_end ; ++background_type_it) {
         const ElementType & int_type = *interface_type_it;
         const ElementType & back_type = *background_type_it;
         const GhostType & int_ghost = *int_ghost_it;
 
         std::string shaped_id = "embedded_shape_derivatives";
 
         if (int_ghost == _ghost) shaped_id += ":ghost";
 
         ElementTypeMapArray<Real> * shaped_etma = new ElementTypeMapArray<Real>(shaped_id, this->name);
 
         UInt nb_points = Mesh::getNbNodesPerElement(back_type);
         UInt nb_quad_points = model->getFEEngine("EmbeddedInterfaceFEEngine").getNbQuadraturePoints(int_type);
         UInt nb_elements = element_filter(int_type, int_ghost).getSize();
 
         shaped_etma->alloc(nb_elements * nb_quad_points,
             dim * nb_points,
             back_type);
 
         shape_derivatives(shaped_etma, int_type, int_ghost);
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::initBackgroundShapeDerivatives() {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh = model->getMesh();
 
   Mesh::type_iterator type_it = mesh.firstType(dim, _not_ghost);
   Mesh::type_iterator type_end = mesh.lastType(dim, _not_ghost);
 
   for (; type_it != type_end ; ++type_it) {
     computeBackgroundShapeDerivatives(*type_it, _not_ghost);
     //computeBackgroundShapeDerivatives(*type_it, _ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::initDirectingCosines() {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh = model->getInterfaceMesh();
 
   Mesh::type_iterator type_it = mesh.firstType(1, _not_ghost);
   Mesh::type_iterator type_end = mesh.lastType(1, _not_ghost);
 
   const UInt voigt_size = getTangentStiffnessVoigtSize(dim);
   directing_cosines.initialize(voigt_size * voigt_size);
 
   for (; type_it != type_end ; ++type_it) {
     computeDirectingCosines(*type_it, _not_ghost);
     computeDirectingCosines(*type_it, _ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::assembleStiffnessMatrix(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Mesh & interface_mesh = model->getInterfaceMesh();
 
-  Mesh::type_iterator type_it = interface_mesh.firstType();
-  Mesh::type_iterator type_end = interface_mesh.lastType();
+  Mesh::type_iterator type_it = interface_mesh.firstType(1, _not_ghost);
+  Mesh::type_iterator type_end = interface_mesh.lastType(1, _not_ghost);
 
   for (; type_it != type_end ; ++type_it) {
     assembleStiffnessMatrix(*type_it, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::updateResidual(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   computeAllStresses(ghost_type);
   assembleResidual(ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::assembleResidual(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Mesh & interface_mesh = model->getInterfaceMesh();
 
-  Mesh::type_iterator type_it = interface_mesh.firstType();
-  Mesh::type_iterator type_end = interface_mesh.lastType();
+  Mesh::type_iterator type_it = interface_mesh.firstType(1, _not_ghost);
+  Mesh::type_iterator type_end = interface_mesh.lastType(1, _not_ghost);
 
   for (; type_it != type_end ; ++type_it) {
     assembleResidual(*type_it, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 void MaterialReinforcement<dim>::computeGradU(const ElementType & type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Array<UInt> & elem_filter = element_filter(type, ghost_type);
   UInt nb_element = elem_filter.getSize();
   UInt nb_quad_points = model->getFEEngine("EmbeddedInterfaceFEEngine").getNbQuadraturePoints(type);
 
-  Array<Real> & gradu_vec = gradu(type, ghost_type);
+  Array<Real> & gradu_vec = gradu_embedded(type, ghost_type);
 
   Mesh::type_iterator back_it = model->getMesh().firstType(dim, ghost_type);
   Mesh::type_iterator back_end = model->getMesh().lastType(dim, ghost_type);
 
   for (; back_it != back_end ; ++back_it) {
     UInt nodes_per_background_e = Mesh::getNbNodesPerElement(*back_it);
 
     Array<Real> & shapesd = shape_derivatives(type, ghost_type)->operator()(*back_it, ghost_type);
 
     Array<UInt> * background_filter = new Array<UInt>(nb_element, 1, "background_filter");
     filterInterfaceBackgroundElements(*background_filter, *back_it, type, ghost_type, ghost_type);
 
     Array<Real> * disp_per_element = new Array<Real>(0, dim * nodes_per_background_e, "disp_elem");
     FEEngine::extractNodalToElementField(model->getMesh(),
         model->getDisplacement(),
         *disp_per_element,
         *back_it, ghost_type, *background_filter);
 
     Array<Real>::matrix_iterator disp_it = disp_per_element->begin(dim, nodes_per_background_e);
     Array<Real>::matrix_iterator disp_end = disp_per_element->end(dim, nodes_per_background_e);
 
     Array<Real>::matrix_iterator shapes_it = shapesd.begin(dim, nodes_per_background_e);
     Array<Real>::matrix_iterator grad_u_it = gradu_vec.begin(dim, dim);
 
     for (; disp_it != disp_end ; ++disp_it) {
       for (UInt i = 0; i < nb_quad_points; i++, ++shapes_it, ++grad_u_it) {
         Matrix<Real> & B = *shapes_it;
         Matrix<Real> & du = *grad_u_it;
         Matrix<Real> & u = *disp_it;
 
         du.mul<false, true>(u, B);
       }
     }
 
     delete background_filter;
     delete disp_per_element;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 template<UInt dim>
 void MaterialReinforcement<dim>::computeAllStresses(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Mesh::type_iterator it = model->getInterfaceMesh().firstType();
   Mesh::type_iterator last_type = model->getInterfaceMesh().lastType();
 
   for(; it != last_type; ++it) {
     computeGradU(*it, ghost_type);
     computeStress(*it, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::assembleResidual(const ElementType & type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh = model->getMesh();
 
   Mesh::type_iterator type_it = mesh.firstType(dim, ghost_type);
   Mesh::type_iterator type_end = mesh.lastType(dim, ghost_type);
 
   for (; type_it != type_end ; ++type_it) {
     assembleResidual(type, *type_it, ghost_type, _not_ghost);
     //assembleResidual(type, *type_it, ghost_type, _ghost);
   }
 
   
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::assembleResidual(const ElementType & interface_type,
                                                   const ElementType & background_type,
                                                   GhostType interface_ghost,
                                                   GhostType background_ghost) {
   AKANTU_DEBUG_IN();
   
   UInt voigt_size = getTangentStiffnessVoigtSize(dim);
 
   Array<Real> & residual = const_cast<Array<Real> &>(model->getResidual());
 
   FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine");
   FEEngine & background_engine = model->getFEEngine();
 
   Array<UInt> & elem_filter = element_filter(interface_type, interface_ghost);
 
   UInt nodes_per_background_e = Mesh::getNbNodesPerElement(background_type);
   UInt nb_quadrature_points = interface_engine.getNbQuadraturePoints(interface_type, interface_ghost);
   UInt nb_element = elem_filter.getSize();
 
   UInt back_dof = dim * nodes_per_background_e;
 
   Array<Real> & shapesd = shape_derivatives(interface_type, interface_ghost)->operator()(background_type, background_ghost);
 
   Array<Real> * integrant = new Array<Real>(nb_quadrature_points * nb_element,
                                             back_dof,
                                             "integrant");
 
   Array<Real>::vector_iterator integrant_it =
     integrant->begin(back_dof);
   Array<Real>::vector_iterator integrant_end =
     integrant->end(back_dof);
 
   Array<Real>::matrix_iterator B_it =
     shapesd.begin(dim, nodes_per_background_e);
   Array<Real>::matrix_iterator C_it =
     directing_cosines(interface_type, interface_ghost).begin(voigt_size, voigt_size);
   Array<Real>::matrix_iterator sigma_it =
-    stress(interface_type, interface_ghost).begin(dim, dim);
+    stress_embedded(interface_type, interface_ghost).begin(dim, dim);
 
   Vector<Real> sigma(voigt_size);
   Matrix<Real> Bvoigt(voigt_size, back_dof);
   Vector<Real> Ct_sigma(voigt_size);
   
   for (; integrant_it != integrant_end ; ++integrant_it,
                                          ++B_it,
                                          ++C_it,
                                          ++sigma_it) {
     VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(*B_it, Bvoigt, nodes_per_background_e);
     Matrix<Real> & C = *C_it;
     Vector<Real> & BtCt_sigma = *integrant_it;
 
     stressTensorToVoigtVector(*sigma_it, sigma);
     
     Ct_sigma.mul<true>(C, sigma);
     BtCt_sigma.mul<true>(Bvoigt, Ct_sigma);
     BtCt_sigma *= area;
   }
 
 
   Array<Real> * residual_interface = new Array<Real>(nb_element, back_dof, "residual_interface");
   interface_engine.integrate(*integrant,
                              *residual_interface,
                              back_dof,
                              interface_type, interface_ghost,
                              elem_filter);
 
   delete integrant;
 
   Array<UInt> * background_filter = new Array<UInt>(nb_element, 1, "background_filter");
 
   filterInterfaceBackgroundElements(*background_filter,
                                     background_type, interface_type,
                                     background_ghost, interface_ghost);
   background_engine.assembleArray(*residual_interface, residual,
                                   model->getDOFSynchronizer().getLocalDOFEquationNumbers(),
                                   dim, background_type, background_ghost, *background_filter, -1.0);
   
   delete residual_interface;
   delete background_filter;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::filterInterfaceBackgroundElements(Array<UInt> & filter,
                                                                    const ElementType & type,
                                                                    const ElementType & interface_type,
                                                                    GhostType ghost_type,
                                                                    GhostType interface_ghost_type) {
   AKANTU_DEBUG_IN();
 
   filter.resize(0);
   filter.clear();
 
   Array<Element> & elements = model->getInterfaceAssociatedElements(interface_type, interface_ghost_type);
   Array<UInt> & elem_filter = element_filter(interface_type, interface_ghost_type);
 
   Array<UInt>::scalar_iterator
     filter_it = elem_filter.begin(),
     filter_end = elem_filter.end();
 
   for (; filter_it != filter_end ; ++filter_it) {
     Element & elem = elements(*filter_it);
     if (elem.type == type) filter.push_back(elem.element);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::computeDirectingCosines(const ElementType & type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Mesh & interface_mesh = this->model->getInterfaceMesh();
   
   const UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
   const UInt steel_dof = dim * nb_nodes_per_element;
   const UInt voigt_size = getTangentStiffnessVoigtSize(dim);
   const UInt nb_quad_points =
     model->getFEEngine("EmbeddedInterfaceFEEngine").getNbQuadraturePoints(type, ghost_type);
 
   Array<Real> node_coordinates(this->element_filter(type, ghost_type).getSize(), steel_dof);
 
   this->model->getFEEngine().template extractNodalToElementField<Real>(interface_mesh,
                                                                        interface_mesh.getNodes(),
                                                                        node_coordinates,
                                                                        type,
                                                                        ghost_type,
                                                                        this->element_filter(type, ghost_type));
 
   Array<Real>::matrix_iterator
     directing_cosines_it = directing_cosines(type, ghost_type).begin(voigt_size, voigt_size);
 
   Array<Real>::matrix_iterator node_coordinates_it = node_coordinates.begin(dim, nb_nodes_per_element);
   Array<Real>::matrix_iterator node_coordinates_end = node_coordinates.end(dim, nb_nodes_per_element);
 
   for (; node_coordinates_it != node_coordinates_end ; ++node_coordinates_it) {
     for (UInt i = 0 ; i < nb_quad_points ; i++, ++directing_cosines_it) {
       Matrix<Real> & nodes = *node_coordinates_it;
       Matrix<Real> & cosines = *directing_cosines_it;
 
       computeDirectingCosinesOnQuad(nodes, cosines);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim>
 void MaterialReinforcement<dim>::assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh = model->getMesh();
 
   Mesh::type_iterator type_it = mesh.firstType(dim, ghost_type);
   Mesh::type_iterator type_end = mesh.lastType(dim, ghost_type);
 
   for (; type_it != type_end ; ++type_it) {
     assembleStiffnessMatrix(type, *type_it, ghost_type, _not_ghost);
     //assembleStiffnessMatrix(type, *type_it, ghost_type, _ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 template<UInt dim>
 void MaterialReinforcement<dim>::assembleStiffnessMatrix(const ElementType & interface_type,
                                                          const ElementType & background_type,
                                                          GhostType interface_ghost,
                                                          GhostType background_ghost) {
   AKANTU_DEBUG_IN();
 
   UInt voigt_size = getTangentStiffnessVoigtSize(dim);
 
   SparseMatrix & K = const_cast<SparseMatrix &>(model->getStiffnessMatrix());
 
   FEEngine & background_engine = model->getFEEngine();
   FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine");
 
   Array<UInt> & elem_filter = element_filter(interface_type, interface_ghost);
-  Array<Real> & grad_u = gradu(interface_type, interface_ghost);
+  Array<Real> & grad_u = gradu_embedded(interface_type, interface_ghost);
 
   UInt nb_element = elem_filter.getSize();
   UInt nodes_per_background_e = Mesh::getNbNodesPerElement(background_type);
   UInt nb_quadrature_points = interface_engine.getNbQuadraturePoints(interface_type, interface_ghost);
 
   UInt back_dof = dim * nodes_per_background_e;
 
   UInt integrant_size = back_dof;
 
   grad_u.resize(nb_quadrature_points * nb_element);
 
   //need function model->getInterfaceDisplacement()
   /*interface_engine.gradientOnQuadraturePoints(model->getInterfaceDisplacement(),
                                               grad_u, dim, interface_type, interface_ghost,
                                               elem_filter);*/
 
   Array<Real> * tangent_moduli = new Array<Real>(nb_element * nb_quadrature_points,
                                                  1, "interface_tangent_moduli");
   tangent_moduli->clear();
   computeTangentModuli(interface_type, *tangent_moduli, interface_ghost);
 
   Array<Real> & shapesd = shape_derivatives(interface_type, interface_ghost)->operator()(background_type, background_ghost);
 
   Array<Real> * integrant = new Array<Real>(nb_element * nb_quadrature_points,
                                             integrant_size * integrant_size,
                                             "B^t*C^t*D*C*B");
   integrant->clear();
 
   /// Temporary matrices for integrant product
   Matrix<Real> Bvoigt(voigt_size, back_dof);
   Matrix<Real> DC(voigt_size, voigt_size);
   Matrix<Real> DCB(voigt_size, back_dof);
   Matrix<Real> CtDCB(voigt_size, back_dof);
 
   Array<Real>::scalar_iterator D_it = tangent_moduli->begin();
   Array<Real>::scalar_iterator D_end = tangent_moduli->end();
 
   Array<Real>::matrix_iterator C_it =
     directing_cosines(interface_type, interface_ghost).begin(voigt_size, voigt_size);
   Array<Real>::matrix_iterator B_it =
     shapesd.begin(dim, nodes_per_background_e);
   Array<Real>::matrix_iterator integrant_it =
     integrant->begin(integrant_size, integrant_size);
 
   for (; D_it != D_end ; ++D_it, ++C_it, ++B_it, ++integrant_it) {
     Real & D = *D_it;
     Matrix<Real> & C = *C_it;
     Matrix<Real> & B = *B_it;
     Matrix<Real> & BtCtDCB = *integrant_it;
 
     VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(B, Bvoigt, nodes_per_background_e);
 
     DC.clear();
     DC(0, 0) = D * area;
     DC *= C;
     DCB.mul<false, false>(DC, Bvoigt);
     CtDCB.mul<true, false>(C, DCB);
     BtCtDCB.mul<true, false>(Bvoigt, CtDCB);
   }
 
   delete tangent_moduli;
 
   Array<Real> * K_interface = new Array<Real>(nb_element, integrant_size * integrant_size, "K_interface");
   interface_engine.integrate(*integrant, *K_interface,
                              integrant_size * integrant_size,
                              interface_type, interface_ghost,
                              elem_filter);
 
   delete integrant;
 
   Array<UInt> * background_filter = new Array<UInt>(nb_element, 1, "background_filter");
 
   filterInterfaceBackgroundElements(*background_filter,
                                     background_type, interface_type,
                                     background_ghost, interface_ghost);
 
   background_engine.assembleMatrix(*K_interface, K, dim, background_type, background_ghost, *background_filter);
 
   delete K_interface;
   delete background_filter;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 /// In this function, type and ghost type refer to background elements
 template<UInt dim>
 void MaterialReinforcement<dim>::computeBackgroundShapeDerivatives(const ElementType & type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Mesh & interface_mesh = model->getInterfaceMesh();
 
   FEEngine & engine = model->getFEEngine();
   FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine");
 
   Mesh::type_iterator interface_type = interface_mesh.firstType();
   Mesh::type_iterator interface_last = interface_mesh.lastType();
 
   for (; interface_type != interface_last ; ++interface_type) {
     Array<UInt> & filter = element_filter(*interface_type, ghost_type);
 
     const UInt nb_elements = filter.getSize();
     const UInt nb_nodes = Mesh::getNbNodesPerElement(type);
     const UInt nb_quad_per_element = interface_engine.getNbQuadraturePoints(*interface_type);
 
     Array<Real> quad_pos(nb_quad_per_element * nb_elements, dim, "interface_quad_points");
     quad_pos.resize(nb_quad_per_element * nb_elements);
     interface_engine.interpolateOnQuadraturePoints(interface_mesh.getNodes(),
                                                    quad_pos, dim, *interface_type,
                                                    ghost_type, filter);
 
 
     Array<Real> & background_shapesd = shape_derivatives(*interface_type, ghost_type)->operator()(type, ghost_type);
     background_shapesd.clear();
 
     Array<UInt> * background_elements = new Array<UInt>(nb_elements, 1, "computeBackgroundShapeDerivatives:background_filter");
     filterInterfaceBackgroundElements(*background_elements, type, *interface_type, ghost_type, ghost_type);
 
     Array<UInt>::scalar_iterator
       back_it = background_elements->begin(),
       back_end = background_elements->end();
 
     Array<Real>::matrix_iterator shapesd_it = background_shapesd.begin(dim, nb_nodes);
 
     Array<Real>::vector_iterator quad_pos_it = quad_pos.begin(dim);
 
 
     for (; back_it != back_end ; ++back_it) {
       for (UInt i = 0 ; i < nb_quad_per_element ; i++, ++shapesd_it, ++quad_pos_it)
         engine.computeShapeDerivatives(*quad_pos_it, *back_it, type, *shapesd_it, ghost_type);
     }
 
     delete background_elements;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 template<UInt dim>
 Real MaterialReinforcement<dim>::getEnergy(std::string id) {
   AKANTU_DEBUG_IN();
   if (id == "potential") {
     Real epot = 0.;
 
     computePotentialEnergyByElements();
 
     Mesh::type_iterator
       it = element_filter.firstType(spatial_dimension),
       end = element_filter.lastType(spatial_dimension);
 
     for (; it != end ; ++it) {
       FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine");
       epot += interface_engine.integrate(potential_energy(*it, _not_ghost),
-                                                          *it, _not_ghost,
-                                                          element_filter(*it, _not_ghost));
+                                         *it, _not_ghost,
+                                         element_filter(*it, _not_ghost));
       epot *= area;
     }
 
     return epot;
   }
 
   AKANTU_DEBUG_OUT();
   return 0;
 }
 
 // Author is Nicolas Richart, see material.cc
 template<UInt dim>
 void MaterialReinforcement<dim>::flattenInternal(const std::string & field_id,
                                                  ElementTypeMapArray<Real> & internal_flat,
                                                  const GhostType ghost_type,
                                                  ElementKind element_kind) {
   AKANTU_DEBUG_IN();
 
   typedef ElementTypeMapArray<UInt>::type_iterator iterator;
   iterator tit = this->element_filter.firstType(1, ghost_type, element_kind);
   iterator end = this->element_filter.lastType(1, ghost_type, element_kind);
 
   for (; tit != end; ++tit) {
     ElementType type = *tit;
 
     try {
       __attribute__((unused)) const Array<Real> & src_vect
         = this->getArray(field_id,type,ghost_type);
 
     } catch(debug::Exception & e) {
       continue;
     }
 
     const Array<Real> & src_vect = this->getArray(field_id,type,ghost_type);
     const Array<UInt> & filter   = this->element_filter(type,ghost_type);
 
     // total number of elements for a given type
     UInt nb_element = this->model->getInterfaceMesh().getNbElement(type,ghost_type);
     // number of filtered elements
     UInt nb_element_src = filter.getSize();
     // number of quadrature points per elem
     UInt nb_quad_per_elem = 0;
     // number of data per quadrature point
     UInt nb_data_per_quad = src_vect.getNbComponent();
 
     if (!internal_flat.exists(type,ghost_type)) {
       internal_flat.alloc(nb_element*nb_quad_per_elem,nb_data_per_quad,type,ghost_type);
     }
 
     if (nb_element_src == 0) continue;
     nb_quad_per_elem = (src_vect.getSize()/nb_element_src);
 
     // number of data per element
     UInt nb_data = nb_quad_per_elem * src_vect.getNbComponent();
 
     Array<Real> & dst_vect = internal_flat(type,ghost_type);
     dst_vect.resize(nb_element*nb_quad_per_elem);
 
     Array<UInt>::const_scalar_iterator it  = filter.begin();
     Array<UInt>::const_scalar_iterator end = filter.end();
     Array<Real>::const_vector_iterator it_src =
       src_vect.begin_reinterpret(nb_data,nb_element_src);
 
     Array<Real>::vector_iterator it_dst =
       dst_vect.begin_reinterpret(nb_data,nb_element);
 
     for (; it != end ; ++it,++it_src) {
       it_dst[*it] = *it_src;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 INSTANSIATE_MATERIAL(MaterialReinforcement);
 
 /* -------------------------------------------------------------------------- */
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh
index fd77ec62a..ec22703b8 100644
--- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh
+++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh
@@ -1,212 +1,222 @@
 /**
  * @file   material_reinforcement.hh
  *
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @date creation: Thu Mar 12 2015
  * @date last modification: Thu Mar 12 2015
  *
  * @brief  Reinforcement material
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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_MATERIAL_REINFORCEMENT_HH__
 #define __AKANTU_MATERIAL_REINFORCEMENT_HH__
 
 #include "aka_common.hh"
 
 #include "material.hh"
 #include "embedded_interface_model.hh"
 #include "embedded_internal_field.hh"
 
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 /**
  * @brief Material used to represent embedded reinforcements
  *
  * This class is used for computing the reinforcement stiffness matrix
  * along with the reinforcement residual. Room is made for constitutive law,
  * but actual use of contitutive laws is made in MaterialReinforcementTemplate.
+ *
+ * Be careful with the dimensions in this class :
+ *  -  this->spatial_dimension is always 1
+ *  -  the template parameter dim is the dimension of the problem
  */
 template<UInt dim>
 class MaterialReinforcement : virtual public Material {
 
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   /// Constructor
-  MaterialReinforcement(SolidMechanicsModel & model, const ID & id = "");
+  MaterialReinforcement(SolidMechanicsModel & model,
+                        UInt spatial_dimension,
+                        const Mesh & mesh,
+                        FEEngine & fe_engine,
+                        const ID & id = "");
 
   /// Destructor
   virtual ~MaterialReinforcement();
 
+protected:
+  void initialize(SolidMechanicsModel & a_model);
+
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// Init the material
   virtual void initMaterial();
 
   /// Init the background shape derivatives
   void initBackgroundShapeDerivatives();
 
   /// Init the cosine matrices
   void initDirectingCosines();
 
   /// Assemble stiffness matrix
   virtual void assembleStiffnessMatrix(GhostType ghost_type);
 
   /// Update the residual
   virtual void updateResidual(GhostType ghost_type = _not_ghost);
 
   /// Assembled the residual
   virtual void assembleResidual(GhostType ghost_type);
 
   /// Compute all the stresses !
   virtual void computeAllStresses(GhostType ghost_type);
 
   /// Compute the stiffness parameter for elements of a type
   virtual void computeTangentModuli(const ElementType & type,
                                     Array<Real> & tangent,
                                     GhostType ghost_type) = 0;
 
   virtual Real getEnergy(std::string id);
 
-  /// Reimplementation of Material's function to accomodate for interface mesh
-  virtual void flattenInternal(const std::string & field_id,
-		                           ElementTypeMapArray<Real> & internal_flat,
-                               const GhostType ghost_type = _not_ghost,
-                               ElementKind element_kind = _ek_not_defined);
+  void flattenInternal(const std::string & field_id,
+                       ElementTypeMapArray<Real> & internal_flat,
+                       const GhostType ghost_type,
+                       ElementKind element_kind);
 
   /* ------------------------------------------------------------------------ */
   /* Protected methods                                                        */
   /* ------------------------------------------------------------------------ */
 protected:
   /// Allocate the background shape derivatives
   void allocBackgroundShapeDerivatives();
 
   /// Compute the directing cosines matrix for one element type
   void computeDirectingCosines(const ElementType & type, GhostType ghost_type);
 
   /**
    * @brief Compute the directing cosines matrix on quadrature points.
    *
    * The structure of the directing cosines matrix is :
    * \f{eqnarray*}{
    *  C_{1,\cdot} & = & (l^2, m^2, n^2, lm, mn, ln) \\
    *  C_{i,j} & = & 0
    * \f}
    *
    * with :
    * \f[
    * (l, m, n) = \frac{1}{\|\frac{\mathrm{d}\vec{r}(s)}{\mathrm{d}s}\|} \cdot \frac{\mathrm{d}\vec{r}(s)}{\mathrm{d}s}
    * \f]
    */
   inline void computeDirectingCosinesOnQuad(const Matrix<Real> & nodes,
                                             Matrix<Real> & cosines);
 
   /// Assemble the stiffness matrix for an element type (typically _segment_2)
   void assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type);
 
   /**
    * @brief Assemble the stiffness matrix for background & interface types
    *
    * Computes the reinforcement stiffness matrix (Gomes & Awruch, 2001)
    * \f[
    * \mathbf{K}_e = \sum_{i=1}^R{A_i\int_{S_i}{\mathbf{B}^T
    * \mathbf{C}_i^T \mathbf{D}_{s, i} \mathbf{C}_i \mathbf{B}\,\mathrm{d}s}}
    * \f]
    */
   void assembleStiffnessMatrix(const ElementType & interface_type,
                                const ElementType & background_type,
                                GhostType interface_ghost,
                                GhostType background_ghost);
 
   /// Compute the background shape derivatives for a type
   void computeBackgroundShapeDerivatives(const ElementType & type, GhostType ghost_type);
 
   /// Filter elements crossed by interface of a type
   void filterInterfaceBackgroundElements(Array<UInt> & filter,
                                          const ElementType & type,
                                          const ElementType & interface_type,
                                          GhostType ghost_type,
                                          GhostType interface_ghost_type);
 
   /// Assemble the residual of one type of element (typically _segment_2)
   void assembleResidual(const ElementType & type, GhostType ghost_type);
 
   /**
    * @brief Assemble the residual for a pair of elements
    *
    * Computes and assemble the residual. Residual in reinforcement is computed as :
    * \f[
    * \vec{r} = A_s \int_S{\mathbf{B}^T\mathbf{C}^T \vec{\sigma_s}\,\mathrm{d}s}
    * \f]
    */
   void assembleResidual(const ElementType & interface_type,
                         const ElementType & background_type,
                         GhostType interface_ghost,
                         GhostType background_ghost);
 
   // TODO figure out why voigt size is 4 in 2D
   inline void stressTensorToVoigtVector(const Matrix<Real> & tensor, Vector<Real> & vector);
   inline void strainTensorToVoigtVector(const Matrix<Real> & tensor, Vector<Real> & vector);
 
   /// Compute gradu on the interface quadrature points
   virtual void computeGradU(const ElementType & type, GhostType ghost_type);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// Embedded model
   EmbeddedInterfaceModel * model;
 
-  /// grad_u
-  EmbeddedInternalField<Real> gradu;
+  /// Stress in the reinforcement
+  InternalField<Real> stress_embedded;
 
-  /// stress
-  EmbeddedInternalField<Real> stress;
+  /// Gradu of concrete on reinforcement
+  InternalField<Real> gradu_embedded;
 
   /// C matrix on quad
-  EmbeddedInternalField<Real> directing_cosines;
+  InternalField<Real> directing_cosines;
 
   /// Prestress on quad
-  EmbeddedInternalField<Real> pre_stress;
+  InternalField<Real> pre_stress;
 
   /// Cross-sectional area
   Real area;
 
   /// Background mesh shape derivatives
   ElementTypeMap< ElementTypeMapArray<Real> * > shape_derivatives;
 
 };
 
 #include "material_reinforcement_inline_impl.cc"
 
 __END_AKANTU__
 
 #endif // __AKANTU_MATERIAL_REINFORCEMENT_HH__
diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh
index aeb473d5e..226758880 100644
--- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh
+++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh
@@ -1,112 +1,117 @@
 /**
  * @file   material_reinforcement_template.hh
  *
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @date creation: Mon Mar 16 2015
  * @date last modification: Mon Mar 16 2015
  *
  * @brief  Reinforcement material templated with constitutive law
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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_MATERIAL_REINFORCEMENT_TEMPLATE_HH__
 #define __AKANTU_MATERIAL_REINFORCEMENT_TEMPLATE_HH__
 
 /* -------------------------------------------------------------------------- */
 
 #include "aka_common.hh"
 #include "material_reinforcement.hh"
 #include "material_elastic.hh"
+#include "material_linear_isotropic_hardening.hh"
 
 __BEGIN_AKANTU__
 
 /**
  * @brief Implementation of MaterialReinforcement with 1D constitutive law
  * @see MaterialReinforcement, MaterialElastic
  *
  * This class is a reinforcement featuring a constitutive law.
  * <strong>Be careful !</strong> Because of multiple inheritance, this class
  * forms a diamond.
  */
 template<UInt dim, class ConstLaw = MaterialElastic<1> >
 class MaterialReinforcementTemplate : public MaterialReinforcement<dim>,
                                       public ConstLaw {
 
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   /// Constructor
   MaterialReinforcementTemplate(SolidMechanicsModel & a_model, const ID & id = "");
 
   /// Destructor
   virtual ~MaterialReinforcementTemplate();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// Initialises the material
   void initMaterial();
 
   /// Compute the stiffness parameter for elements of a type
   virtual void computeTangentModuli(const ElementType & type,
                                     Array<Real> & tangent,
                                     GhostType ghost_type);
 
   /// Computes stress used by constitutive law
   virtual void computeStress(ElementType type, GhostType ghost_type);
 
   /// Computes gradu to be used by the constitutive law
   virtual void computeGradU(const ElementType & type, GhostType ghost_type);
 
   /// Compute the potential energy of the reinforcement
   virtual void computePotentialEnergy(ElementType type, GhostType ghost_type = _not_ghost);
 
   /// Get energy in reinforcement (currently limited to potential)
   virtual Real getEnergy(std::string id);
 
   virtual void flattenInternal(const std::string & field_id,
-		                           ElementTypeMapArray<Real> & internal_flat,
+                               ElementTypeMapArray<Real> & internal_flat,
                                const GhostType ghost_type = _not_ghost,
                                ElementKind element_kind = _ek_not_defined);
 
+  /// Save the previous internals
+  virtual void savePreviousState();
+
 protected:
   /**
    * @brief Compute interface gradu from bulk gradu
    * \f[
    *  \varepsilon_s = C \varepsilon_c
    * \f]
    */
   inline void computeInterfaceGradUOnQuad(const Matrix<Real> & full_gradu,
                                           Real & gradu,
                                           const Matrix<Real> & C);
 
 };
 
-#include "material_reinforcement_template_inline_impl.cc"
+#include "material_reinforcement_template_tmpl.hh"
 
 __END_AKANTU__
 
+
 #endif // __AKANTU_MATERIAL_REINFORCEMENT_TEMPLATE_HH__
diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_inline_impl.cc b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_tmpl.hh
similarity index 74%
rename from src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_inline_impl.cc
rename to src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_tmpl.hh
index 7639c9c7b..ef6a80696 100644
--- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_inline_impl.cc
+++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_tmpl.hh
@@ -1,205 +1,194 @@
 /**
- * @file   material_reinforcement_template.cc
+ * @file   material_reinforcement_template_tmpl.hh
  *
  * @author Lucas Frérot <lucas.frerot@epfl.ch>
  *
  * @date creation: Mon Mar 16 2015
  * @date last modification: Mon Mar 16 2015
  *
  * @brief  Reinforcement material templated with constitutive law
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2012, 2014 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/>.
  *
  */
 
+// /!\ no namespace here !
+
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim, class ConstLaw>
-MaterialReinforcementTemplate<dim, ConstLaw>::MaterialReinforcementTemplate(SolidMechanicsModel & model,
-	                                                      								    const ID & id):
-  Material(model, id),
-  MaterialReinforcement<dim>(model, id),
-  ConstLaw(model, id)
+MaterialReinforcementTemplate<dim, ConstLaw>::MaterialReinforcementTemplate(SolidMechanicsModel & a_model,
+                                                                            const ID & id):
+  Material(a_model, 1,
+           dynamic_cast<EmbeddedInterfaceModel &>(a_model).getInterfaceMesh(),
+           a_model.getFEEngine("EmbeddedInterfaceFEEngine"), id),
+  MaterialReinforcement<dim>(a_model, 1,
+                             dynamic_cast<EmbeddedInterfaceModel &>(a_model).getInterfaceMesh(),
+                             a_model.getFEEngine("EmbeddedInterfaceFEEngine"), id),
+  ConstLaw(a_model, 1,
+           dynamic_cast<EmbeddedInterfaceModel &>(a_model).getInterfaceMesh(),
+           a_model.getFEEngine("EmbeddedInterfaceFEEngine"), id)
 {}
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim, class ConstLaw>
 MaterialReinforcementTemplate<dim, ConstLaw>::~MaterialReinforcementTemplate()
 {}
 
 /* -------------------------------------------------------------------------- */
 
+/// TODO this function is super ugly. Find better way to initialize internals
 template<UInt dim, class ConstLaw>
 void MaterialReinforcementTemplate<dim, ConstLaw>::initMaterial() {
   MaterialReinforcement<dim>::initMaterial();
-  
-  // Gotta change the dimension from here onwards
-  this->ConstLaw::spatial_dimension = 1;
   ConstLaw::initMaterial();
-  
-  this->ConstLaw::gradu.free();
-  this->ConstLaw::stress.free();
-  this->ConstLaw::delta_T.free();
-  this->ConstLaw::sigma_th.free();
-  this->ConstLaw::potential_energy.free();
-
-  Mesh::type_iterator type_it = this->MaterialReinforcement<dim>::model->getInterfaceMesh().firstType();
-  Mesh::type_iterator type_end = this->MaterialReinforcement<dim>::model->getInterfaceMesh().lastType();
-
-  
-  // Reshape the ConstLaw internal fields
-  for (; type_it != type_end ; ++type_it) {
-    UInt nb_elements = this->MaterialReinforcement<dim>::element_filter(*type_it).getSize();
-
-    FEEngine & interface_engine =
-      this->MaterialReinforcement<dim>::model->getFEEngine("EmbeddedInterfaceFEEngine");
-
-    UInt nb_quad = interface_engine.getNbQuadraturePoints(*type_it);
-
-    this->ConstLaw::gradu.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost);
-    this->ConstLaw::stress.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost);
-    this->ConstLaw::stress.initialize(1);
-    this->ConstLaw::delta_T.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost);
-    this->ConstLaw::sigma_th.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost);
-    this->ConstLaw::potential_energy.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost);
-    //this->ConstLaw::gradu.alloc(0, dim * dim, *type_it, _ghost);
-  }
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim, class ConstLaw>
 void MaterialReinforcementTemplate<dim, ConstLaw>::computeGradU(const ElementType & el_type,
                                                                 GhostType ghost_type) {
   AKANTU_DEBUG_IN();
   
   MaterialReinforcement<dim>::computeGradU(el_type, ghost_type);
 
   const UInt voigt_size = Material::getTangentStiffnessVoigtSize(dim);
 
   Array<Real>::matrix_iterator full_gradu_it =
-    this->MaterialReinforcement<dim>::gradu(el_type, ghost_type).begin(dim, dim);
+    this->MaterialReinforcement<dim>::gradu_embedded(el_type, ghost_type).begin(dim, dim);
   Array<Real>::matrix_iterator full_gradu_end =
-    this->MaterialReinforcement<dim>::gradu(el_type, ghost_type).end(dim, dim);
+    this->MaterialReinforcement<dim>::gradu_embedded(el_type, ghost_type).end(dim, dim);
 
   Array<Real>::scalar_iterator gradu_it =
     this->ConstLaw::gradu(el_type, ghost_type).begin();
 
   Array<Real>::matrix_iterator cosines_it = 
     this->directing_cosines(el_type, ghost_type).begin(voigt_size, voigt_size);
 
 
   for (; full_gradu_it != full_gradu_end ; ++full_gradu_it,
                                           ++gradu_it,
                                           ++cosines_it) {
     Matrix<Real> & full_gradu = *full_gradu_it;
     Real & gradu = *gradu_it;
     Matrix<Real> & C = *cosines_it;
     
     computeInterfaceGradUOnQuad(full_gradu, gradu, C);
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim, class ConstLaw>
 void MaterialReinforcementTemplate<dim, ConstLaw>::computeInterfaceGradUOnQuad(const Matrix<Real> & full_gradu,
                                                                                Real & gradu,
                                                                                const Matrix<Real> & C) {
   const UInt voigt_size = Material::getTangentStiffnessVoigtSize(dim);
 
   Matrix<Real> epsilon(dim, dim);
   Vector<Real> e_voigt(voigt_size);
   Vector<Real> e_interface_voigt(voigt_size);
 
   epsilon = 0.5 * (full_gradu + full_gradu.transpose());
   MaterialReinforcement<dim>::strainTensorToVoigtVector(epsilon, e_voigt);
   e_interface_voigt.mul<false>(C, e_voigt);
 
   gradu = e_interface_voigt(0);
 }
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim, class ConstLaw>
 void MaterialReinforcementTemplate<dim, ConstLaw>::computeTangentModuli(const ElementType & el_type,
-								 Array<Real> & tangent,
-								 GhostType ghost_type) {
+                                                                        Array<Real> & tangent,
+                                                                        GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(tangent.getNbComponent() == 1, "Reinforcements only work in 1D");
 
   ConstLaw::computeTangentModuli(el_type, tangent, ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim, class ConstLaw>
 void MaterialReinforcementTemplate<dim, ConstLaw>::computeStress(ElementType type,
                                                                  GhostType ghost_type) {
   AKANTU_DEBUG_IN();
   
   ConstLaw::computeStress(type, ghost_type);
 
   Array<Real>::matrix_iterator full_sigma_it =
-    this->MaterialReinforcement<dim>::stress(type, ghost_type).begin(dim, dim);
+    this->MaterialReinforcement<dim>::stress_embedded(type, ghost_type).begin(dim, dim);
   Array<Real>::matrix_iterator full_sigma_end =
-    this->MaterialReinforcement<dim>::stress(type, ghost_type).end(dim, dim);
+    this->MaterialReinforcement<dim>::stress_embedded(type, ghost_type).end(dim, dim);
   Array<Real>::scalar_iterator sigma_it =
     this->ConstLaw::stress(type, ghost_type).begin();
   Array<Real>::scalar_iterator pre_stress_it =
     this->MaterialReinforcement<dim>::pre_stress(type, ghost_type).begin();
 
   for (; full_sigma_it != full_sigma_end ; ++full_sigma_it, ++sigma_it, ++pre_stress_it) {
     Matrix<Real> & sigma = *full_sigma_it;
 
     sigma(0, 0) = *sigma_it + *pre_stress_it;
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 template<UInt dim, class ConstLaw>
 Real MaterialReinforcementTemplate<dim, ConstLaw>::getEnergy(std::string id) {
   return MaterialReinforcement<dim>::getEnergy(id);
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <UInt dim, class ConstLaw>
 void MaterialReinforcementTemplate<dim, ConstLaw>::computePotentialEnergy(ElementType type,
                                                                           GhostType ghost_type) {
+  const UInt nb_elements = this->element_filter(type, ghost_type).getSize();
+  const UInt nb_quad = this->model->getFEEngine("EmbeddedInterfaceFEEngine").getNbQuadraturePoints(type);
+  this->ConstLaw::potential_energy.alloc(nb_quad * nb_elements, 1, type, ghost_type, 0.);
+
   ConstLaw::computePotentialEnergy(type, ghost_type);
 }
 
+/* -------------------------------------------------------------------------- */
+
 template <UInt dim, class ConstLaw>
 void MaterialReinforcementTemplate<dim, ConstLaw>::flattenInternal(const std::string & field_id,
                                                                    ElementTypeMapArray<Real> & internal_flat,
                                                                    const GhostType ghost_type,
                                                                    ElementKind element_kind) {
-  if (field_id == "stress_embedded")
+  if (field_id == "stress_embedded" || field_id == "inelastic_strain")
     MaterialReinforcement<dim>::flattenInternal(field_id, internal_flat, ghost_type, element_kind);
 }
+
+template<UInt dim, class ConstLaw>
+void MaterialReinforcementTemplate<dim, ConstLaw>::savePreviousState() {
+  ConstLaw::savePreviousState();
+}
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc
index c55e1d2ec..4e8a818c3 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc
+++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc
@@ -1,201 +1,215 @@
 /**
  * @file   material_linear_isotropic_hardening.cc
  *
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
  * @author Benjamin Paccaud <benjamin.paccaud@epfl.ch>
  *
  * @date creation: Thu Oct 03 2013
  * @date last modification: Fri Jun 13 2014
  *
  * @brief  Specialization of the material class for isotropic finite deformation linear hardening plasticity
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_linear_isotropic_hardening.hh"
 #include "solid_mechanics_model.hh"
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 MaterialLinearIsotropicHardening<dim>::MaterialLinearIsotropicHardening(SolidMechanicsModel & model,
                                                                         const ID & id) :
   Material(model, id), MaterialPlastic<dim>(model, id) {
   AKANTU_DEBUG_IN();
   
   AKANTU_DEBUG_OUT();
 }
 
+/* -------------------------------------------------------------------------- */
+template<UInt spatial_dimension>
+MaterialLinearIsotropicHardening<spatial_dimension>::MaterialLinearIsotropicHardening(
+  SolidMechanicsModel & model,
+  UInt dim,
+  const Mesh & mesh,
+  FEEngine & fe_engine,
+  const ID & id) :
+
+  Material(model, dim, mesh, fe_engine, id),
+  MaterialPlastic<spatial_dimension>(model, dim, mesh, fe_engine, id)
+{}
+
+
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialLinearIsotropicHardening<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MaterialThermal<spatial_dimension>::computeStress(el_type, ghost_type);
   // infinitesimal and finite deformation
   Array<Real>::iterator<> sigma_th_it =
     this->sigma_th(el_type, ghost_type).begin();
 
   Array<Real>::iterator<> previous_sigma_th_it =
     this->sigma_th.previous(el_type, ghost_type).begin();
 
   Array<Real>::matrix_iterator previous_gradu_it =
     this->gradu.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::matrix_iterator previous_stress_it =
     this->stress.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::matrix_iterator inelastic_strain_it =
     this->inelastic_strain(el_type, ghost_type).begin(spatial_dimension,spatial_dimension);
 
   Array<Real>::matrix_iterator previous_inelastic_strain_it =
     this->inelastic_strain.previous(el_type, ghost_type).begin(spatial_dimension,spatial_dimension);
 
   Array<Real>::iterator<> iso_hardening_it =
     this->iso_hardening(el_type, ghost_type).begin();
 
   Array<Real>::iterator<> previous_iso_hardening_it =
     this->iso_hardening.previous(el_type, ghost_type).begin();
   
 
 
   //
   // Finite Deformations
   //
   if (this->finite_deformation) {
         Array<Real>::matrix_iterator previous_piola_kirchhoff_2_it =
       this->piola_kirchhoff_2.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
     
     Array<Real>::matrix_iterator green_strain_it =
       this->green_strain(el_type, ghost_type).begin(spatial_dimension,spatial_dimension);
 
     
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
     Matrix<Real> & inelastic_strain_tensor = *inelastic_strain_it;
     Matrix<Real> & previous_inelastic_strain_tensor = *previous_inelastic_strain_it;
     Matrix<Real> & previous_grad_u = *previous_gradu_it;    
     Matrix<Real> & previous_sigma = *previous_piola_kirchhoff_2_it;
 
     Matrix<Real> & green_strain = *green_strain_it;
     this->template gradUToGreenStrain<spatial_dimension>(grad_u, green_strain);
     Matrix<Real> previous_green_strain(spatial_dimension,spatial_dimension);
     this->template gradUToGreenStrain<spatial_dimension>(previous_grad_u, previous_green_strain);
     Matrix<Real> F_tensor(spatial_dimension,spatial_dimension);
     this->template gradUToF<spatial_dimension>(grad_u,F_tensor);
   
     computeStressOnQuad(green_strain,
 			previous_green_strain,
 			sigma,
 			previous_sigma,
 			inelastic_strain_tensor,
 			previous_inelastic_strain_tensor,
 			*iso_hardening_it,
 			*previous_iso_hardening_it,
 			*sigma_th_it,
 			*previous_sigma_th_it,
 			F_tensor);
 
   ++sigma_th_it;
   ++inelastic_strain_it;
   ++iso_hardening_it;
   ++previous_sigma_th_it;
   //++previous_stress_it;
   ++previous_gradu_it;
   ++green_strain_it;
   ++previous_inelastic_strain_it;
   ++previous_iso_hardening_it;
   ++previous_piola_kirchhoff_2_it;
   
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   } 
   // Infinitesimal deformations
   else {
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
     Matrix<Real> & inelastic_strain_tensor = *inelastic_strain_it;
     Matrix<Real> & previous_inelastic_strain_tensor = *previous_inelastic_strain_it;
     Matrix<Real> & previous_grad_u = *previous_gradu_it;    
     Matrix<Real> & previous_sigma = *previous_stress_it; 
 
     computeStressOnQuad(grad_u,
 			previous_grad_u,
 			sigma,
 			previous_sigma,
 			inelastic_strain_tensor,
 			previous_inelastic_strain_tensor,
 			*iso_hardening_it,
 			*previous_iso_hardening_it,
 			*sigma_th_it,
 			*previous_sigma_th_it);
     ++sigma_th_it;
     ++inelastic_strain_it;
     ++iso_hardening_it;
     ++previous_sigma_th_it;
     ++previous_stress_it;
     ++previous_gradu_it;
     ++previous_inelastic_strain_it;
     ++previous_iso_hardening_it;
 
     MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialLinearIsotropicHardening<spatial_dimension>::computeTangentModuli(__attribute__((unused)) const ElementType & el_type,
                                                                     Array<Real> & tangent_matrix,
                                                                     __attribute__((unused)) GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Array<Real>::const_matrix_iterator previous_gradu_it =
     this->gradu.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::const_matrix_iterator previous_stress_it =
     this->stress.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::const_scalar_iterator iso_hardening= this->iso_hardening(el_type, ghost_type).begin();
 
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix);
 
   computeTangentModuliOnQuad(tangent, grad_u, *previous_gradu_it, sigma_tensor, *previous_stress_it, *iso_hardening);
 
   ++previous_gradu_it;
   ++previous_stress_it;
   ++iso_hardening;
 
   MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 INSTANSIATE_MATERIAL(MaterialLinearIsotropicHardening);
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh
index 1cc27030a..933bd414a 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh
+++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh
@@ -1,113 +1,118 @@
 /**
  * @file   material_linear_isotropic_hardening.hh
  *
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
  *
  * @date creation: Thu Oct 03 2013
  * @date last modification: Mon Apr 07 2014
  *
  * @brief  Specialization of the material class for isotropic finite deformation linear hardening plasticity
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "aka_voigthelper.hh"
 #include "material_plastic.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH__
 #define __AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH__
 
 __BEGIN_AKANTU__
 
 /**
  * Material plastic with a linear evolution of the yielding stress
  */
 template <UInt spatial_dimension>
 class MaterialLinearIsotropicHardening : public MaterialPlastic<spatial_dimension> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   MaterialLinearIsotropicHardening(SolidMechanicsModel & model, const ID & id = "");
+  MaterialLinearIsotropicHardening(SolidMechanicsModel & model,
+                                   UInt dim,
+                                   const Mesh & mesh,
+                                   FEEngine & fe_engine,
+                                   const ID & id = "");
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// constitutive law for all element of a type
   virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost);
 
   /// compute the tangent stiffness matrix for an element type
   void computeTangentModuli(const ElementType & el_type,
                             Array<Real> & tangent_matrix,
                             GhostType ghost_type = _not_ghost);
 
 protected:
   /// Infinitesimal deformations
   inline void computeStressOnQuad(const Matrix<Real> & grad_u,
                                   const Matrix<Real> & previous_grad_u,
                                   Matrix<Real> & sigma,
                                   const Matrix<Real> & previous_sigma,
                                   Matrix<Real> & inelas_strain,
                                   const Matrix<Real> & previous_inelas_strain,
                                   Real & iso_hardening,
                                   const Real & previous_iso_hardening,
                                   const Real & sigma_th,
                                   const Real & previous_sigma_th);
   /// Finite deformations
   inline void computeStressOnQuad(const Matrix<Real> & grad_u,
                                   const Matrix<Real> & previous_grad_u,
                                   Matrix<Real> & sigma,
                                   const Matrix<Real> & previous_sigma,
                                   Matrix<Real> & inelas_strain,
                                   const Matrix<Real> & previous_inelas_strain,
                                   Real & iso_hardening,
                                   const Real & previous_iso_hardening,
                                   const Real & sigma_th,
                                   const Real & previous_sigma_th,
 				  const Matrix<Real> & F_tensor);
 
   inline void computeTangentModuliOnQuad(Matrix<Real> & tangent,
                                          const Matrix<Real> & grad_u,
                                          const Matrix<Real> & previous_grad_u,
                                          const Matrix<Real> & sigma_tensor,
                                          const Matrix<Real> & previous_sigma_tensor,
                                          const Real & iso_hardening) const;
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
 
 };
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 #include "material_linear_isotropic_hardening_inline_impl.cc"
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc
index 0477f4fca..609e3b199 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc
+++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc
@@ -1,301 +1,307 @@
 /**
  * @file   material_linear_isotropic_hardening_inline_impl.cc
  *
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch>
  * @author Benjamin Paccaud <benjamin.paccaud@epfl.ch>
  *
  * @date creation: Thu Oct 03 2013
  * @date last modification: Mon Jun 09 2014
  *
  * @brief  Implementation of the inline functions of the material plasticity
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 #include "material_linear_isotropic_hardening.hh"
 
 
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 ///Infinitesimal deformations
 template<UInt dim>
 inline void
 MaterialLinearIsotropicHardening<dim>::computeStressOnQuad(const Matrix<Real> & grad_u,
                                                            const Matrix<Real> & previous_grad_u,
                                                            Matrix<Real> & sigma,
                                                            const Matrix<Real> & previous_sigma,
                                                            Matrix<Real> & inelastic_strain,
                                                            const Matrix<Real> & previous_inelastic_strain,
                                                            Real & iso_hardening,
                                                            const Real & previous_iso_hardening,
                                                            const Real & sigma_th,
                                                            const Real & previous_sigma_th) {
   //Infinitesimal plasticity
-  //Real r=iso_hardening;
-  Real dp=0.0;
-  Real d_dp=0.0;
-  UInt n=0;
+  Real dp   = 0.0;
+  Real d_dp = 0.0;
+  UInt n    = 0;
 
   Real delta_sigma_th = sigma_th - previous_sigma_th;
 
   Matrix<Real> grad_delta_u(grad_u);
   grad_delta_u -= previous_grad_u;
 
   //Compute trial stress, sigma_tr
   Matrix<Real> sigma_tr(dim, dim);
   MaterialElastic<dim>::computeStressOnQuad(grad_delta_u, sigma_tr, delta_sigma_th);
   sigma_tr += previous_sigma;
 
   // Compute deviatoric trial stress,  sigma_tr_dev
   Matrix<Real> sigma_tr_dev(sigma_tr);
   sigma_tr_dev -= Matrix<Real>::eye(dim, sigma_tr.trace() / 3.0);
 
   // Compute effective deviatoric trial stress
   Real s = sigma_tr_dev.doubleDot(sigma_tr_dev);
   Real sigma_tr_dev_eff = std::sqrt(3./2. * s);
 
+  // In 1D Von-Mises stress is the stress
+  if (dim == 1) sigma_tr_dev_eff = sigma_tr(0, 0);
+
   const Real iso_hardening_t = previous_iso_hardening;
   iso_hardening = iso_hardening_t;
  
   //Loop for correcting stress based on yield function
   bool initial_yielding = ( (sigma_tr_dev_eff - iso_hardening - this->sigma_y) > 0) ;
-  while ( initial_yielding && std::abs(sigma_tr_dev_eff - iso_hardening - this->sigma_y) > Math::getTolerance() ) {
 
+  while (initial_yielding && std::abs(sigma_tr_dev_eff - iso_hardening - this->sigma_y) > Math::getTolerance()) {
     d_dp = (sigma_tr_dev_eff - 3. * this->mu *dp -  iso_hardening - this->sigma_y)
       / (3. * this->mu + this->h);
 
-    //r = r +  h * dp;    
     dp = dp + d_dp;
     iso_hardening = iso_hardening_t + this->h * dp;
-
     ++n;
-   
-    /// TODO : explicit this criterion with an error message
-    if ((d_dp < 1e-5) || (n>50))
-      {
-	break;
-      }
+
+    if (d_dp < 1e-5) {
+      break;
+    } else if (n > 50) {
+      AKANTU_DEBUG_WARNING("Isotropic hardening convergence failed");
+      break;
+    }
   }
 
   //Update internal variable
   Matrix<Real> delta_inelastic_strain(dim, dim, 0.);
   if (std::abs(sigma_tr_dev_eff) >
       sigma_tr_dev.norm<L_inf>() * Math::getTolerance()) {
     delta_inelastic_strain.copy(sigma_tr_dev);
     delta_inelastic_strain *= 3./2. * dp / sigma_tr_dev_eff;
   }
 
   MaterialPlastic<dim>::computeStressAndInelasticStrainOnQuad(grad_delta_u, sigma, previous_sigma,
                                                               inelastic_strain, previous_inelastic_strain,
                                                               delta_inelastic_strain);
 }
 
 /* -------------------------------------------------------------------------- */
 ///Finite deformations
 template<UInt dim>
 inline void
 MaterialLinearIsotropicHardening<dim>::computeStressOnQuad(const Matrix<Real> & grad_u,
 								   const Matrix<Real> & previous_grad_u,
 								   Matrix<Real> & sigma,
 								   const Matrix<Real> & previous_sigma,
 								   Matrix<Real> & inelastic_strain,
 								   const Matrix<Real> & previous_inelastic_strain,
 								   Real & iso_hardening,
 								   const Real & previous_iso_hardening,
 								   const Real & sigma_th,
 								   const Real & previous_sigma_th,
 								   const Matrix<Real> & F_tensor) {
   //Finite plasticity
   Real dp=0.0;
   Real d_dp=0.0;
   UInt n=0;
  
   Real delta_sigma_th = sigma_th - previous_sigma_th;
 
   Matrix<Real> grad_delta_u(grad_u);
   grad_delta_u -= previous_grad_u;
   
   //Compute trial stress, sigma_tr
   Matrix<Real> sigma_tr(dim, dim);
   MaterialElastic<dim>::computeStressOnQuad(grad_delta_u, sigma_tr, delta_sigma_th);
   sigma_tr += previous_sigma;
 
   // Compute deviatoric trial stress,  sigma_tr_dev
   Matrix<Real> sigma_tr_dev(sigma_tr);
   sigma_tr_dev -= Matrix<Real>::eye(dim, sigma_tr.trace() / 3.0);
 
   // Compute effective deviatoric trial stress
   Real s = sigma_tr_dev.doubleDot(sigma_tr_dev);
   Real sigma_tr_dev_eff = std::sqrt(3./2. * s);
 
   // compute the cauchy stress to apply the Von-Mises criterion
   Matrix<Real> cauchy_stress(dim,dim);
   Material::computeCauchyStressOnQuad<dim>(F_tensor,sigma_tr,cauchy_stress);
   Matrix<Real> cauchy_stress_dev(cauchy_stress);
   cauchy_stress_dev -= Matrix<Real>::eye(dim, cauchy_stress.trace() / 3.0);
   Real c = cauchy_stress_dev.doubleDot(cauchy_stress_dev);
   Real cauchy_stress_dev_eff = std::sqrt(3./2. * c);
   
 
   const Real iso_hardening_t = previous_iso_hardening;
   iso_hardening = iso_hardening_t;
   //Loop for correcting stress based on yield function
 
   // F is written in terms of S
   // bool initial_yielding = ( (sigma_tr_dev_eff - iso_hardening - this->sigma_y) > 0) ;
   // while ( initial_yielding && std::abs(sigma_tr_dev_eff - iso_hardening - this->sigma_y) > Math::getTolerance() ) {
     
   //   d_dp = (sigma_tr_dev_eff - 3. * this->mu *dp -  iso_hardening - this->sigma_y)
   //     / (3. * this->mu + this->h);
 
   //   //r = r +  h * dp;    
   //   dp = dp + d_dp;
   //   iso_hardening = iso_hardening_t + this->h * dp;
 
   //   ++n;
    
   //   /// TODO : explicit this criterion with an error message
   //   if ((std::abs(d_dp) < 1e-9) || (n>50)){
   //     AKANTU_DEBUG_INFO("convergence of increment of plastic strain. d_dp:" << d_dp << "\tNumber of iteration:"<<n);
   //     break;
   //   }
   // }
  
   // F is written in terms of cauchy stress 
   bool initial_yielding = ( (cauchy_stress_dev_eff - iso_hardening - this->sigma_y) > 0) ;
   while ( initial_yielding && std::abs(cauchy_stress_dev_eff - iso_hardening - this->sigma_y) > Math::getTolerance() ) { 
  
     d_dp = ( cauchy_stress_dev_eff - 3. * this->mu *dp -  iso_hardening - this->sigma_y)
       / (3. * this->mu + this->h);
 
     //r = r +  h * dp;
     dp = dp + d_dp;
     iso_hardening = iso_hardening_t + this->h * dp; 
     
 
     ++n;
     /// TODO : explicit this criterion with an error message
     if ((d_dp < 1e-5) || (n>50)){
       AKANTU_DEBUG_INFO("convergence of increment of plastic strain. d_dp:" << d_dp << "\tNumber of iteration:"<<n);
       break;
     }
   }
 
   //Update internal variable
   Matrix<Real> delta_inelastic_strain(dim, dim, 0.);
   if (std::abs(sigma_tr_dev_eff) >
       sigma_tr_dev.norm<L_inf>() * Math::getTolerance()) {
     
     // /// compute the direction of the plastic strain as \frac{\partial F}{\partial S} = \frac{3}{2J\sigma_{effective}}} Ft \sigma_{dev} F
     Matrix<Real> cauchy_dev_F(dim,dim);
     cauchy_dev_F.mul<false,false>(F_tensor,cauchy_stress_dev);
     Real J = F_tensor.det();
     Real constant = J ? 1./J : 0;
     constant *= 3. * dp / (2. * cauchy_stress_dev_eff);
     delta_inelastic_strain.mul<true,false>(F_tensor,cauchy_dev_F,constant);
     
     //Direction given by the piola kirchhoff deviatoric tensor \frac{\partial F}{\partial S} = \frac{3}{2\sigma_{effective}}}S_{dev}
     // delta_inelastic_strain.copy(sigma_tr_dev);
     // delta_inelastic_strain *= 3./2. * dp / sigma_tr_dev_eff;
   }
  
   MaterialPlastic<dim>::computeStressAndInelasticStrainOnQuad(grad_delta_u, sigma, previous_sigma,
                                                               inelastic_strain, previous_inelastic_strain,
                                                               delta_inelastic_strain);
 }
 
 /* -------------------------------------------------------------------------- */
 
 
 template<UInt dim>
 inline void
 MaterialLinearIsotropicHardening<dim>::computeTangentModuliOnQuad(Matrix<Real> & tangent,
                                                                   const Matrix<Real> & grad_u,
                                                                   const Matrix<Real> & previous_grad_u,
                                                                   const Matrix<Real> & sigma_tensor,
                                                                   const Matrix<Real> & previous_sigma_tensor,
                                                                   const Real & iso_hardening) const {
   // Real r=iso_hardening;
 
   // Matrix<Real> grad_delta_u(grad_u);
   // grad_delta_u -= previous_grad_u;
 
   // //Compute trial stress, sigma_tr
   // Matrix<Real> sigma_tr(dim, dim);
   // MaterialElastic<dim>::computeStressOnQuad(grad_delta_u, sigma_tr);
   // sigma_tr += previous_sigma_tensor;
 
   // // Compute deviatoric trial stress,  sigma_tr_dev
   // Matrix<Real> sigma_tr_dev(sigma_tr);
   // sigma_tr_dev -= Matrix<Real>::eye(dim, sigma_tr.trace() / 3.0);
 
   // // Compute effective deviatoric trial stress
   // Real s = sigma_tr_dev.doubleDot(sigma_tr_dev);
   // Real sigma_tr_dev_eff=std::sqrt(3./2. * s);
 
   // // Compute deviatoric stress,  sigma_dev
   // Matrix<Real> sigma_dev(sigma_tensor);
   // sigma_dev -= Matrix<Real>::eye(dim, sigma_tensor.trace() / 3.0);
 
   // // Compute effective deviatoric stress
   // s =  sigma_dev.doubleDot(sigma_dev);
   // Real sigma_dev_eff = std::sqrt(3./2. * s);
 
   // Real xr = 0.0;
   // if(sigma_tr_dev_eff > sigma_dev_eff * Math::getTolerance())
   //   xr = sigma_dev_eff / sigma_tr_dev_eff;
 
   // Real __attribute__((unused)) q = 1.5 * (1. / (1. +  3. * this->mu  / this->h) - xr);
 
+  /*
   UInt cols = tangent.cols();
   UInt rows = tangent.rows();
 
   for (UInt m = 0; m < rows; ++m) {
     UInt i = VoigtHelper<dim>::vec[m][0];
     UInt j = VoigtHelper<dim>::vec[m][1];
 
     for (UInt n = 0; n < cols; ++n) {
       UInt k = VoigtHelper<dim>::vec[n][0];
       UInt l = VoigtHelper<dim>::vec[n][1];
+      */
 
       // This section of the code is commented
       // There were some problems with the convergence of plastic-coupled simulations with thermal expansion
       // XXX: DO NOT REMOVE
       /*if (((sigma_tr_dev_eff-iso_hardening-sigmay) > 0) && (xr > 0)) {
         tangent(m,n) =
         2. * this->mu * q * (sigma_tr_dev (i,j) / sigma_tr_dev_eff) * (sigma_tr_dev (k,l) / sigma_tr_dev_eff) +
         (i==k) * (j==l) * 2. * this->mu * xr +
         (i==j) * (k==l) * (this->kpa - 2./3. * this->mu * xr);
         if ((m == n) && (m>=dim))
         tangent(m, n) = tangent(m, n) - this->mu * xr;
         } else {*/
+      /*
       tangent(m,n) =  (i==k) * (j==l) * 2. * this->mu +
         (i==j) * (k==l) * this->lambda;
       tangent(m,n) -= (m==n) * (m>=dim) * this->mu;
+      */
       //}
       //correct tangent stiffness for shear component
-    }
-  }
+    //}
+  //}
+  MaterialElastic<dim>::computeTangentModuliOnQuad(tangent);
 }
 
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc
index 5bd012b8a..4b7e97329 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc
+++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc
@@ -1,184 +1,206 @@
 /**
  * @file   material_plastic.cc
  *
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  *
  * @date creation: Mon Apr 07 2014
  * @date last modification: Fri Jun 13 2014
  *
  * @brief  Implemantation of the akantu::MaterialPlastic class
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_plastic.hh"
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model, const ID & id) :
   Material(model, id),
   MaterialElastic<spatial_dimension>(model, id),
   iso_hardening("iso_hardening", *this),
   inelastic_strain("inelastic_strain", *this),
   plastic_energy("plastic_energy", *this),
   d_plastic_energy("d_plastic_energy", *this) {
   AKANTU_DEBUG_IN();
+  this->initialize();
+  AKANTU_DEBUG_OUT();
+}
 
+template<UInt spatial_dimension>
+MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model,
+                                                    UInt dim,
+                                                    const Mesh & mesh,
+                                                    FEEngine & fe_engine,
+                                                    const ID & id) :
+  Material(model, dim, mesh, fe_engine, id),
+  MaterialElastic<spatial_dimension>(model, dim, mesh, fe_engine, id),
+  iso_hardening("iso_hardening", *this, dim, fe_engine, this->element_filter),
+  inelastic_strain("inelastic_strain", *this, dim, fe_engine, this->element_filter),
+  plastic_energy("plastic_energy", *this, dim, fe_engine, this->element_filter),
+  d_plastic_energy("d_plastic_energy", *this, dim, fe_engine, this->element_filter) {
+  AKANTU_DEBUG_IN();
+  this->initialize();
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template<UInt spatial_dimension>
+void MaterialPlastic<spatial_dimension>::initialize() {
   this->registerParam("h", h, 0., _pat_parsable | _pat_modifiable, "Hardening  modulus");
   this->registerParam("sigma_y", sigma_y, 0., _pat_parsable | _pat_modifiable, "Yield stress");
 
   //already registered in material
   //  this->registerParam("finite_deformation",finite_deformation, false,  _pat_parsable | _pat_modifiable, "Flag for large deformation");
 
   this->iso_hardening.initialize(1);
   this->iso_hardening.initializeHistory();
 
   this->plastic_energy.initialize(1);
   this->d_plastic_energy.initialize(1);
 
   this->use_previous_stress           = true;
   this->use_previous_gradu            = true;
   this->use_previous_stress_thermal   = true;
 
 
   this->inelastic_strain.initialize(spatial_dimension * spatial_dimension);
   this->inelastic_strain.initializeHistory();
-
-  AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 Real MaterialPlastic<spatial_dimension>::getEnergy(std::string type) {
   if (type == "plastic") return getPlasticEnergy();
   else return MaterialElastic<spatial_dimension>::getEnergy(type);
 
   return 0.;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 Real MaterialPlastic<spatial_dimension>::getPlasticEnergy() {
   AKANTU_DEBUG_IN();
 
   Real penergy = 0.;
 
   const Mesh & mesh = this->model->getFEEngine().getMesh();
 
   Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost);
 
   for(; it != end; ++it) {
     penergy += this->model->getFEEngine().integrate(plastic_energy(*it, _not_ghost),
-					       *it, _not_ghost,
-					       this->element_filter(*it, _not_ghost));
+                                                    *it, _not_ghost,
+                                                    this->element_filter(*it, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return penergy;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
-void MaterialPlastic<spatial_dimension>::computePotentialEnergy(ElementType el_type, GhostType ghost_type) {
+void MaterialPlastic<spatial_dimension>::computePotentialEnergy(ElementType el_type,
+                                                                GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   if(ghost_type != _not_ghost) return;
 
   Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin();
 
    Array<Real>::const_iterator< Matrix<Real> > inelastic_strain_it
      = this->inelastic_strain(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Matrix<Real> elastic_strain(spatial_dimension, spatial_dimension);
   elastic_strain.copy(grad_u);
   elastic_strain -= *inelastic_strain_it;
 
   MaterialElastic<spatial_dimension>::computePotentialEnergyOnQuad(elastic_strain, sigma, *epot);
 
   ++epot;
   ++inelastic_strain_it;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialPlastic<spatial_dimension>::updateEnergies(ElementType el_type,
 							GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MaterialElastic<spatial_dimension>::updateEnergies(el_type, ghost_type);
 
   Array<Real>::iterator<> pe_it =
     this->plastic_energy(el_type, ghost_type).begin();
 
   Array<Real>::iterator<> wp_it =
     this->d_plastic_energy(el_type, ghost_type).begin();
 
   Array<Real>::iterator< Matrix<Real> > inelastic_strain_it =
     this->inelastic_strain(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::iterator< Matrix<Real> > previous_inelastic_strain_it =
     this->inelastic_strain.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::matrix_iterator previous_sigma =
     this->stress.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Matrix<Real> delta_strain_it(*inelastic_strain_it);
   delta_strain_it -= *previous_inelastic_strain_it;
 
   Matrix<Real> sigma_h(sigma);
   sigma_h += *previous_sigma;
 
   *wp_it = .5 * sigma_h.doubleDot(delta_strain_it);
 
   *pe_it += *wp_it;
 
   ++pe_it;
   ++wp_it;
   ++inelastic_strain_it;
   ++previous_inelastic_strain_it;
   ++previous_sigma;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 INSTANSIATE_MATERIAL(MaterialPlastic);
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh b/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh
index abcd54021..dc06edb44 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh
+++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh
@@ -1,129 +1,137 @@
 /**
  * @file   material_plastic.hh
  *
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  *
  * @date creation: Mon Apr 07 2014
  * @date last modification: Mon Apr 07 2014
  *
  * @brief  Common interface for plastic materials
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_elastic.hh"
 /* -------------------------------------------------------------------------- */
 
 
 #ifndef __AKANTU_MATERIAL_PLASTIC_HH__
 #define __AKANTU_MATERIAL_PLASTIC_HH__
 
 __BEGIN_AKANTU__
 
 /**
  * Parent class for the plastic constitutive laws
  * parameters in the material files :
  *   - h : Hardening parameter (default: 0)
  *   - sigmay : Yield stress
  */
 template<UInt dim>
 class MaterialPlastic : public MaterialElastic<dim> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   MaterialPlastic(SolidMechanicsModel & model, const ID & id = "");
+  MaterialPlastic(SolidMechanicsModel & model,
+                  UInt a_dim,
+                  const Mesh & mesh,
+                  FEEngine & fe_engine,
+                  const ID & id = "");
+
+protected:
+  void initialize();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   virtual Real getEnergy(std::string type);
 
   /// Compute the plastic energy
   virtual void updateEnergies(ElementType el_type, GhostType ghost_type = _not_ghost);
 
   /// Compute the true potential energy
   virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type);
 
 protected:
   inline void computeStressAndInelasticStrainOnQuad(const Matrix<Real> & grad_u,
                                                     const Matrix<Real> & previous_grad_u,
                                                     Matrix<Real> & sigma,
                                                     const Matrix<Real> & previous_sigma,
                                                     Matrix<Real> & inelas_strain,
                                                     const Matrix<Real> & previous_inelas_strain,
                                                     const Matrix<Real> & delta_inelastic_strain) const;
 
   inline void computeStressAndInelasticStrainOnQuad(const Matrix<Real> & delta_grad_u,
                                                     Matrix<Real> & sigma,
                                                     const Matrix<Real> & previous_sigma,
                                                     Matrix<Real> & inelas_strain,
                                                     const Matrix<Real> & previous_inelas_strain,
                                                     const Matrix<Real> & delta_inelastic_strain) const;
 
 
   Real getPlasticEnergy();
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// Yield stresss
   Real sigma_y;
 
   /// hardening modulus
   Real h;
 
   /// isotropic hardening, r
   InternalField<Real> iso_hardening;
 
   /// inelastic strain arrays ordered by element types (inelastic deformation)
   InternalField<Real> inelastic_strain;
 
   /// Plastic energy
   InternalField<Real> plastic_energy;
 
   /// @todo : add a coefficient beta that will multiply the plastic energy increment
   /// to compute the energy converted to heat
 
   /// Plastic energy increment
   InternalField<Real> d_plastic_energy;
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 #include "material_plastic_inline_impl.cc"
 
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MATERIAL_PLASTIC_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_thermal.cc b/src/model/solid_mechanics/materials/material_thermal.cc
index 50001d6aa..d37508f7e 100644
--- a/src/model/solid_mechanics/materials/material_thermal.cc
+++ b/src/model/solid_mechanics/materials/material_thermal.cc
@@ -1,101 +1,122 @@
 /**
  * @file   material_thermal.cc
  *
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  *
  * @date creation: Thu Oct 17 2013
  * @date last modification: Thu Apr 03 2014
  *
  * @brief  Specialization of the material class for the thermal material
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_thermal.hh"
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 MaterialThermal<spatial_dimension>::MaterialThermal(SolidMechanicsModel & model, const ID & id)  :
   Material(model, id),
   delta_T("delta_T", *this),
   sigma_th("sigma_th", *this),
   use_previous_stress_thermal(false) {
   AKANTU_DEBUG_IN();
+  this->initialize();
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template<UInt spatial_dimension>
+MaterialThermal<spatial_dimension>::MaterialThermal(SolidMechanicsModel & model,
+                                                    UInt dim,
+                                                    const Mesh & mesh,
+                                                    FEEngine & fe_engine,
+                                                    const ID & id) :
+  Material(model, dim, mesh, fe_engine, id),
+  delta_T("delta_T", *this, dim, fe_engine, this->element_filter),
+  sigma_th("sigma_th", *this, dim, fe_engine, this->element_filter),
+  use_previous_stress_thermal(false) {
+  AKANTU_DEBUG_IN();
+  this->initialize();
+  AKANTU_DEBUG_OUT();
+}
 
+template<UInt spatial_dimension>
+void MaterialThermal<spatial_dimension>::initialize() {
   this->registerParam("E"      , E      , 0.  , _pat_parsable | _pat_modifiable, "Young's modulus"        );
   this->registerParam("nu"     , nu     , 0.5 , _pat_parsable | _pat_modifiable, "Poisson's ratio"        );
   this->registerParam("alpha"  , alpha  , 0.  , _pat_parsable | _pat_modifiable, "Thermal expansion coefficient");
   this->registerParam("delta_T", delta_T,       _pat_parsable | _pat_modifiable, "Uniform temperature field");
 
   delta_T.initialize(1);
-  AKANTU_DEBUG_OUT();
 }
 
+
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialThermal<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
   sigma_th.initialize(1);
 
 
   if(use_previous_stress_thermal) {
     sigma_th.initializeHistory();
   }
 
   Material::initMaterial();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 void MaterialThermal<dim>::computeStress(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   Array<Real>::iterator<> delta_t_it = this->delta_T(el_type, ghost_type).begin();
   Array<Real>::iterator<> sigma_th_it = this->sigma_th(el_type, ghost_type).begin();
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   /// TODO : implement with the matrix alpha
   if (dim == 1) {
     *sigma_th_it = - this->E * this->alpha * *delta_t_it;
   }
   else {
     *sigma_th_it = - this->E/(1.-2.*this->nu) * this->alpha * *delta_t_it;
   }
 
   ++delta_t_it;
   ++sigma_th_it;
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 
 INSTANSIATE_MATERIAL(MaterialThermal);
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/materials/material_thermal.hh b/src/model/solid_mechanics/materials/material_thermal.hh
index a15c04f06..9e120c0d2 100644
--- a/src/model/solid_mechanics/materials/material_thermal.hh
+++ b/src/model/solid_mechanics/materials/material_thermal.hh
@@ -1,96 +1,104 @@
 /**
  * @file   material_thermal.hh
  *
  * @author Lucas Frerot <lucas.frerot@epfl.ch>
  *
  * @date creation: Thu Oct 17 2013
  * @date last modification: Thu Apr 03 2014
  *
  * @brief  Material isotropic thermo-elastic
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "material.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_THERMAL_HH__
 #define __AKANTU_MATERIAL_THERMAL_HH__
 
 __BEGIN_AKANTU__
 template<UInt spatial_dimension>
 class MaterialThermal : public virtual Material {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   MaterialThermal(SolidMechanicsModel & model, const ID & id = "");
+  MaterialThermal(SolidMechanicsModel & model,
+                  UInt dim,
+                  const Mesh & mesh,
+                  FEEngine & fe_engine,
+                  const ID & id = "");
 
   virtual ~MaterialThermal() {};
 
+protected:
+  void initialize();
+
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   virtual void initMaterial();
 
   /// constitutive law for all element of a type
   virtual void computeStress(ElementType el_type, GhostType ghost_type);
 
   /* ------------------------------------------------------------------------ */
   /* DataAccessor inherited members                                           */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// Young modulus
   Real E;
 
   /// Poisson ratio
   Real nu;
 
   /// Thermal expansion coefficient
   /// TODO : implement alpha as a matrix
   Real alpha;
 
   /// Temperature field
   InternalField<Real> delta_T;
 
   /// Current thermal stress
   InternalField<Real> sigma_th;
 
   /// Tell if we need to use the previous thermal stress
   bool use_previous_stress_thermal;
 };
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MATERIAL_THERMAL_HH__ */
diff --git a/src/model/solid_mechanics/materials/plane_stress_toolbox.hh b/src/model/solid_mechanics/materials/plane_stress_toolbox.hh
index 840ae01de..aca90d1ed 100644
--- a/src/model/solid_mechanics/materials/plane_stress_toolbox.hh
+++ b/src/model/solid_mechanics/materials/plane_stress_toolbox.hh
@@ -1,87 +1,98 @@
 /**
  * @file   plane_stress_toolbox.hh
  *
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Tue Sep 16 2014
  * @date last modification: Tue Sep 16 2014
  *
  * @brief  Tools to implement the plane stress behavior in a material
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 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_PLANE_STRESS_TOOLBOX_HH__
 #define __AKANTU_PLANE_STRESS_TOOLBOX_HH__
 
 __BEGIN_AKANTU__
 
 /**
  * Empty class in dimensions different from 2
  * This class is only specialized for 2D in the tmpl file
  */
 template<UInt dim, class ParentMaterial = Material>
 class PlaneStressToolbox : public ParentMaterial {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   PlaneStressToolbox(SolidMechanicsModel & model, const ID & id = "") : Material(model, id),
                                                                         ParentMaterial(model, id) {}
+  PlaneStressToolbox(SolidMechanicsModel & model,
+                     UInt spatial_dimension,
+                     const Mesh & mesh,
+                     FEEngine & fe_engine,
+                     const ID & id = "") : Material(model, spatial_dimension, mesh, fe_engine, id),
+                                           ParentMaterial(model, spatial_dimension, mesh, fe_engine, id) {}
+
   virtual ~PlaneStressToolbox() {}
 
+protected:
+  void initialize();
+
+public:
   virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost){
     AKANTU_DEBUG_IN();
 
     ParentMaterial::computeAllCauchyStresses(ghost_type);
 
     AKANTU_DEBUG_OUT();
   }
 
   virtual void computeCauchyStressPlaneStress(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ERROR("The function \"computeCauchyStressPlaneStress\" can only be used in 2D Plane stress problems, which means that you made a mistake somewhere!! ");
 
   AKANTU_DEBUG_OUT();
   }
 
 protected:
   bool initialize_third_axis_deformation;
 };
 
 #define AKANTU_PLANE_STRESS_TOOL_SPEC(dim)\
   template<>                                                            \
   inline PlaneStressToolbox<dim, Material>::PlaneStressToolbox(SolidMechanicsModel & model, \
                                                                const ID & id) : \
     Material(model, id) {}                                              \
 
 AKANTU_PLANE_STRESS_TOOL_SPEC(1)
 AKANTU_PLANE_STRESS_TOOL_SPEC(3)
 
 __END_AKANTU__
 
 #include "plane_stress_toolbox_tmpl.hh"
 
 #endif /* __AKANTU_PLANE_STRESS_TOOLBOX_HH__ */
 
diff --git a/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh b/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh
index dc3e57a78..5b20c9eda 100644
--- a/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh
+++ b/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh
@@ -1,147 +1,171 @@
 /**
  * @file   plane_stress_toolbox_tmpl.hh
  *
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  *
  * @date creation: Tue Sep 16 2014
  * @date last modification: Tue Sep 16 2014
  *
  * @brief  2D specialization of the akantu::PlaneStressToolbox class
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 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_PLANE_STRESS_TOOLBOX_TMPL_HH__
 #define __AKANTU_PLANE_STRESS_TOOLBOX_TMPL_HH__
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<class ParentMaterial>
 class PlaneStressToolbox<2, ParentMaterial> : public ParentMaterial {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   PlaneStressToolbox(SolidMechanicsModel & model, const ID & id = "");
+  PlaneStressToolbox(SolidMechanicsModel & model,
+                     UInt dim,
+                     const Mesh & mesh,
+                     FEEngine & fe_engine,
+                     const ID & id = "");
 
   virtual ~PlaneStressToolbox() {}
 
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ThirdAxisDeformation, third_axis_deformation, Real);
 
+protected:
+  void initialize() {
+    this->registerParam("Plane_Stress", plane_stress, false, _pat_parsmod, "Is plane stress");
+  }
+
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   virtual void initMaterial() {
 
     ParentMaterial::initMaterial();
     if(this->plane_stress && this->initialize_third_axis_deformation){
       this->third_axis_deformation.initialize(1);
       this->third_axis_deformation.resize();
     }
   }
 
   /* ------------------------------------------------------------------------ */
   virtual void computeStress(ElementType el_type, GhostType ghost_type)  {
     ParentMaterial::computeStress(el_type, ghost_type);
     if(this->plane_stress) computeThirdAxisDeformation(el_type, ghost_type);
   }
 
   /* ------------------------------------------------------------------------ */
   virtual void computeThirdAxisDeformation(__attribute__((unused)) ElementType el_type,
                                            __attribute__((unused)) GhostType ghost_type)  {
   }
 
   /// Computation of Cauchy stress tensor in the case of finite deformation
   virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost){
     AKANTU_DEBUG_IN();
 
     if(this->plane_stress){
 
       AKANTU_DEBUG_ASSERT(this->finite_deformation,"The Cauchy stress can only be computed if you are working in finite deformation.");
 
       //resizeInternalArray(stress);
 
       Mesh::type_iterator it = this->model->getFEEngine().getMesh().firstType(2, ghost_type);
       Mesh::type_iterator last_type = this->model->getFEEngine().getMesh().lastType(2, ghost_type);
 
       for(; it != last_type; ++it)
         this->computeCauchyStressPlaneStress(*it, ghost_type);
     }
     else
       ParentMaterial::computeAllCauchyStresses(ghost_type);
 
   AKANTU_DEBUG_OUT();
 
   }
 
   virtual void computeCauchyStressPlaneStress(ElementType el_type, GhostType ghost_type = _not_ghost){};
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// third axis strain measure value
   InternalField<Real> third_axis_deformation;
 
   /// Plane stress or plane strain
   bool plane_stress;
 
   /// For non linear materials, the \epsilon_{zz} might be required
   bool initialize_third_axis_deformation;
 };
 
 template<class ParentMaterial>
 inline PlaneStressToolbox<2, ParentMaterial>::PlaneStressToolbox(SolidMechanicsModel & model, const ID & id) :
   Material(model, id),
   ParentMaterial(model, id),
   third_axis_deformation("third_axis_deformation", *this),
   plane_stress(false),
   initialize_third_axis_deformation(false) {
 
   /// @todo Plane_Stress should not be possible to be modified after initMaterial (but before)
-  this->registerParam("Plane_Stress", plane_stress, false, _pat_parsmod, "Is plane stress");
+  this->initialize();
+}
+
+template<class ParentMaterial>
+inline PlaneStressToolbox<2, ParentMaterial>::PlaneStressToolbox(SolidMechanicsModel & model,
+                                                                 UInt dim,
+                                                                 const Mesh & mesh,
+                                                                 FEEngine & fe_engine,
+                                                                 const ID & id):
+  Material(model, dim, mesh, fe_engine, id),
+  ParentMaterial(model, dim, mesh, fe_engine, id),
+  third_axis_deformation("third_axis_deformation", *this, dim, fe_engine, this->element_filter),
+  plane_stress(false),
+  initialize_third_axis_deformation(false) {
+  this->initialize();
 }
 
 template<>
 inline PlaneStressToolbox<2, Material>::PlaneStressToolbox(SolidMechanicsModel & model, const ID & id) :
   Material(model, id),
   third_axis_deformation("third_axis_deformation", *this),
   plane_stress(false),
   initialize_third_axis_deformation(false) {
 
   /// @todo Plane_Stress should not be possible to be modified after initMaterial (but before)
   this->registerParam("Plane_Stress", plane_stress, false, _pat_parsmod, "Is plane stress");
 }
 
 
 __END_AKANTU__
 
 #endif /* __AKANTU_PLANE_STRESS_TOOLBOX_TMPL_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh
index daba20874..90d6356a5 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh
@@ -1,290 +1,290 @@
 /**
  * @file   solid_mechanics_model_cohesive.hh
  *
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Tue May 08 2012
  * @date last modification: Tue Sep 02 2014
  *
  * @brief  Solid mechanics model for cohesive elements
  *
  * @section LICENSE
  *
  * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #ifndef __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__
 #define __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__
 
 #include "solid_mechanics_model.hh"
 #include "solid_mechanics_model_event_handler.hh"
 #include "cohesive_element_inserter.hh"
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
 #  include "facet_synchronizer.hh"
 #  include "facet_stress_synchronizer.hh"
 #endif
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 struct SolidMechanicsModelCohesiveOptions : public SolidMechanicsModelOptions {
   SolidMechanicsModelCohesiveOptions(AnalysisMethod analysis_method = _explicit_lumped_mass,
 				     bool extrinsic = false,
 				     bool no_init_materials = false) :
     SolidMechanicsModelOptions(analysis_method, no_init_materials),
     extrinsic(extrinsic) {}
   bool extrinsic;
 };
 
 extern const SolidMechanicsModelCohesiveOptions default_solid_mechanics_model_cohesive_options;
 
 /* -------------------------------------------------------------------------- */
 /* Solid Mechanics Model for Cohesive elements                                */
 /* -------------------------------------------------------------------------- */
 
 class SolidMechanicsModelCohesive : public SolidMechanicsModel,
                                     public SolidMechanicsModelEventHandler{
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   class NewCohesiveNodesEvent : public NewNodesEvent {
   public:
     AKANTU_GET_MACRO_NOT_CONST(OldNodesList, old_nodes, Array<UInt> &);
     AKANTU_GET_MACRO(OldNodesList, old_nodes, const Array<UInt> &);
   protected:
     Array<UInt> old_nodes;
   };
 
   typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive> MyFEEngineCohesiveType;
 
   SolidMechanicsModelCohesive(Mesh & mesh,
 			      UInt spatial_dimension = _all_dimensions,
 			      const ID & id = "solid_mechanics_model_cohesive",
 			      const MemoryID & memory_id = 0);
 
   virtual ~SolidMechanicsModelCohesive();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// set the value of the time step
   void setTimeStep(Real time_step);
 
   /// assemble the residual for the explicit scheme
   virtual void updateResidual(bool need_initialize = true);
 
   /// function to print the contain of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /// function to perform a stress check on each facet and insert
   /// cohesive elements if needed (returns the number of new cohesive
   /// elements)
   UInt checkCohesiveStress();
 
   /// interpolate stress on facets
   void interpolateStress();
 
   /// initialize the cohesive model
   void initFull(const ModelOptions & options = default_solid_mechanics_model_cohesive_options);
 
   /// initialize the model
   void initModel();
 
   /// initialize cohesive material
   void initMaterials();
 
   /// init facet filters for cohesive materials
   void initFacetFilter();
 
   /// limit the cohesive element insertion to a given area
   void limitInsertion(BC::Axis axis, Real first_limit, Real second_limit);
 
   /// update automatic insertion after a change in the element inserter
   void updateAutomaticInsertion();
 
   /// insert intrinsic cohesive elements
   void insertIntrinsicElements();
 
   template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria>
   bool solveStepCohesive(Real tolerance,
                          Real & error,
                          UInt max_iteration = 100,
-                         UInt cont = 1,
+                         bool load_reduction = false,
                          bool do_not_factorize = false);
 
   /// initialize stress interpolation
   void initStressInterpolation();
 
 private:
 
   /// initialize completely the model for extrinsic elements
   void initAutomaticInsertion();
 
   /// compute facets' normals
   void computeNormals();
 
   /// resize facet stress
   void resizeFacetStress();
 
   /// init facets_check array
   void initFacetsCheck();
 
   /* ------------------------------------------------------------------------ */
   /* Mesh Event Handler inherited members                                     */
   /* ------------------------------------------------------------------------ */
 
 protected:
 
   virtual void onNodesAdded  (const Array<UInt> & nodes_list,
 			      const NewNodesEvent & event);
   virtual void onElementsAdded  (const Array<Element> & nodes_list,
 				 const NewElementsEvent & event);
 
   /* ------------------------------------------------------------------------ */
   /* SolidMechanicsModelEventHandler inherited members                        */
   /* ------------------------------------------------------------------------ */
 public:
   virtual void onEndSolveStep(const AnalysisMethod & method);
 
   /* ------------------------------------------------------------------------ */
   /* Dumpable interface                                                       */
   /* ------------------------------------------------------------------------ */
 public:
 
   virtual void onDump();
 
   virtual void addDumpGroupFieldToDumper(const std::string & dumper_name,
 					 const std::string & field_id,
 					 const std::string & group_name,
 					 const ElementKind & element_kind,
 					 bool padding_flag);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /// get facet mesh
   AKANTU_GET_MACRO(MeshFacets, mesh.getMeshFacets(), const Mesh &);
 
   /// get stress on facets vector
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(StressOnFacets, facet_stress, Real);
 
   /// get facet material
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetMaterial, facet_material, UInt);
 
   /// get facet material
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetMaterial, facet_material, UInt);
 
   /// get facet material
   AKANTU_GET_MACRO(FacetMaterial, facet_material, const ElementTypeMapArray<UInt> &);
 
   /// @todo THIS HAS TO BE CHANGED
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Tangents, tangents, Real);
 
   /// get element inserter
   AKANTU_GET_MACRO_NOT_CONST(ElementInserter, *inserter, CohesiveElementInserter &);
 
   /// get is_extrinsic boolean
   AKANTU_GET_MACRO(IsExtrinsic, is_extrinsic, bool);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
 
   /// @todo store tangents when normals are computed:
   ElementTypeMapArray<Real> tangents;
 
   /// stress on facets on the two sides by quadrature point
   ElementTypeMapArray<Real> facet_stress;
 
   /// material to use if a cohesive element is created on a facet
   ElementTypeMapArray<UInt> facet_material;
 
   bool is_extrinsic;
 
   /// cohesive element inserter
   CohesiveElementInserter * inserter;
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
 #include "solid_mechanics_model_cohesive_parallel.hh"
 #endif
 
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 class DefaultMaterialCohesiveSelector : public DefaultMaterialSelector {
 public:
   DefaultMaterialCohesiveSelector(const SolidMechanicsModelCohesive & model) :
     DefaultMaterialSelector(model.getMaterialByElement()),
     facet_material(model.getFacetMaterial()),
     mesh(model.getMesh()) { }
 
   inline virtual UInt operator()(const Element & element) {
     if(Mesh::getKind(element.type) == _ek_cohesive) {
       try {
 	const Array<Element> & cohesive_el_to_facet
 	  = mesh.getMeshFacets().getSubelementToElement(element.type, element.ghost_type);
 	bool third_dimension = (mesh.getSpatialDimension() == 3);
 	const Element & facet = cohesive_el_to_facet(element.element, third_dimension);
 	if(facet_material.exists(facet.type, facet.ghost_type)) {
 	  return facet_material(facet.type, facet.ghost_type)(facet.element);
 	} else {
 	  return MaterialSelector::operator()(element);
 	}
       } catch (...) {
 	return MaterialSelector::operator()(element);
       }
     } else if (Mesh::getSpatialDimension(element.type) == mesh.getSpatialDimension() - 1) {
       return facet_material(element.type, element.ghost_type)(element.element);
     } else {
       return DefaultMaterialSelector::operator()(element);
     }
   }
 
 private:
   const ElementTypeMapArray<UInt> & facet_material;
   const Mesh & mesh;
 };
 
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const SolidMechanicsModelCohesive & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 
 __END_AKANTU__
 
 #if defined (AKANTU_INCLUDE_INLINE_IMPL)
 #  include "solid_mechanics_model_cohesive_inline_impl.cc"
 #endif
 
 #endif /* __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive_inline_impl.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive_inline_impl.cc
index 384f50e4c..d538d5e68 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive_inline_impl.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive_inline_impl.cc
@@ -1,255 +1,261 @@
 /**
  * @file   solid_mechanics_model_cohesive_inline_impl.cc
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  *
  * @date   Thu Feb 26 14:23:45 2015
  *
  * @brief  Implementation of inline functions for the Cohesive element model
  *
  * @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 <algorithm>
 #include "material_cohesive.hh"
 
 #ifndef __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_CC__
 #define __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_CC__
 
 __BEGIN_AKANTU__
 
 
 
 /* -------------------------------------------------------------------------- */
 template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria>
 bool SolidMechanicsModelCohesive::solveStepCohesive(Real tolerance,
                                                     Real & error,
                                                     UInt max_iteration,
-                                                    UInt cont,
+                                                    bool load_reduction,
                                                     bool do_not_factorize) {
 
   EventManager::sendEvent(SolidMechanicsModelEvent::BeforeSolveStepEvent(method));
   this->implicitPred();
 
   bool insertion_new_element = true;
   bool converged = false;
   Array<Real> * displacement_tmp = NULL;
   Array<Real> * velocity_tmp = NULL;
   Array<Real> * acceleration_tmp = NULL;
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   Int prank = comm.whoAmI();
 
   while (insertion_new_element) {  //loop for insertion of new cohesive elements
     if (is_extrinsic) {
       // If in extrinsic saves the current displacements, velocities and accelerations
       Array<Real> * tmp_swap;
 
       if(!displacement_tmp) {
         displacement_tmp = new Array<Real>(*(this->displacement));
       } else {
         (*displacement_tmp).resize(this->displacement->getSize());
         //displacement_tmp->resize(this->displacement->getSize());
         (*displacement_tmp).copy(*(this->displacement));
         //displacement_tmp->copy(*(this->displacement));
       }
       tmp_swap = displacement_tmp;
       displacement_tmp = this->displacement;
       this->displacement = tmp_swap;
 
       if(!velocity_tmp) {
         velocity_tmp = new Array<Real>(*(this->velocity));
       } else {
         velocity_tmp->resize(this->velocity->getSize());
         velocity_tmp->copy(*(this->velocity));
       }
       tmp_swap = velocity_tmp;
       velocity_tmp = this->velocity;
       this->velocity = tmp_swap;
 
       if(!acceleration_tmp) {
         acceleration_tmp = new Array<Real>(*(this->acceleration));
       } else {
         acceleration_tmp->resize(this->acceleration->getSize());
         acceleration_tmp->copy(*(this->acceleration));
       }
       tmp_swap = acceleration_tmp;
       acceleration_tmp = this->acceleration;
       this->acceleration = tmp_swap;
     }
 
     this->updateResidual();
 
     AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL,
                         "You should first initialize the implicit solver and assemble the stiffness matrix");
 
     bool need_factorize = !do_not_factorize;
 
     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;
     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, 1., need_factorize);
 
       this->implicitCorr();
 
       this->updateResidual();
 
       converged = this->testConvergence<criteria> (tolerance, error);
 
       iter++;
       AKANTU_DEBUG_INFO("[" << criteria << "] Convergence iteration "
                         << std::setw(std::log10(max_iteration)) << iter
                         << ": error " << error << (converged ? " < " : " > ") << tolerance);
 
       switch (cmethod) {
       case _scm_newton_raphson_tangent:
         need_factorize = true;
         break;
       case _scm_newton_raphson_tangent_not_computed:
       case _scm_newton_raphson_tangent_modified:
         need_factorize = false;
         break;
       default:
         AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not been implemented!");
       }
 
     } while (!converged && iter < max_iteration);
 
+    //    dump();
+    //    dump("cohesive elements");
+
+    if (load_reduction && (error < tolerance * 1000)) converged = true;
 
     if (converged) {
       ////      EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method));
       // !!! add sendEvent to call computeCauchyStress !!!!
       if (prank==0){
         std::cout << "Error after convergence: " << error << std::endl;
         std::cout << "no. of iterations: " << iter << std::endl;
       }
     } else if(iter == max_iteration) {
       if (prank==0){
         AKANTU_DEBUG_WARNING("[" << criteria << "] Convergence not reached after "
                              << std::setw(std::log10(max_iteration)) << iter <<
                              " iteration" << (iter == 1 ? "" : "s") << "!" << std::endl);
         std::cout << "Error after NON convergence: " << error << std::endl;
       }
     }
 
     if (is_extrinsic) {
       Array<Real> * tmp_swap;
 
       tmp_swap = displacement_tmp;
       displacement_tmp = this->displacement;
       this->displacement = tmp_swap;
 
       tmp_swap = velocity_tmp;
       velocity_tmp = this->velocity;
       this->velocity = tmp_swap;
 
       tmp_swap = acceleration_tmp;
       acceleration_tmp = this->acceleration;
       this->acceleration = tmp_swap;
 
-      if (converged || cont == 2){
-        UInt nb_cohesive_elements = this->mesh.getNbElement(this->spatial_dimension, _not_ghost, _ek_cohesive);
 
-        this->checkCohesiveStress();
+      if (converged){   // || load_reduction){
+        //        UInt nb_cohesive_elements = this->mesh.getNbElement(this->spatial_dimension, _not_ghost, _ek_cohesive);
+        //        this->checkCohesiveStress();
+        //        UInt new_nb_cohesive_elements = this->mesh.getNbElement(this->spatial_dimension, _not_ghost, _ek_cohesive);
 
-        UInt new_nb_cohesive_elements = this->mesh.getNbElement(this->spatial_dimension, _not_ghost, _ek_cohesive);
+        UInt new_cohesive_elements = checkCohesiveStress();
 
-        UInt nb_cohe[2];
-        nb_cohe[0] = nb_cohesive_elements;
-        nb_cohe[1] = new_nb_cohesive_elements;
+        //        UInt nb_cohe[2];
+        //nb_cohe[0] = nb_cohesive_elements;
+        //nb_cohe[1] = new_nb_cohesive_elements;
 
-        StaticCommunicator::getStaticCommunicator().allReduce(nb_cohe, 2, _so_sum);
+        //        StaticCommunicator::getStaticCommunicator().allReduce(nb_cohe, 2, _so_sum);
 
-        if(nb_cohe[0] == nb_cohe[1]) {
+        //        if(nb_cohe[0] == nb_cohe[1]) {
+        if(new_cohesive_elements == 0){
           insertion_new_element = false;
         } else {
           insertion_new_element = true;
           if (prank==0)
-            std::cout << "1 cohesive element has been inserted" << std::endl;
+            std::cout << "No. cohesive elements inserted = " << new_cohesive_elements << std::endl;
         }
       }
     }
 
-    if (!converged && cont != 2){
+    if (!converged){   // && !load_reduction){
       insertion_new_element = false;
 
       for (UInt m = 0; m < materials.size(); ++m) {
         try {
           MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*materials[m]);
           mat.checkDeltaMax(_not_ghost);
         } catch(std::bad_cast&) { }
       }
 
     }
 
   } //end while insertion_new_element
 
 
-  if ((is_extrinsic && converged) || (is_extrinsic && cont == 2))  {
+  if ((is_extrinsic && converged)){   // || (is_extrinsic && load_reduction))  {
 
     EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method));
 
     this->displacement->copy(*displacement_tmp);
     this->velocity    ->copy(*velocity_tmp);
     this->acceleration->copy(*acceleration_tmp);
 
     delete displacement_tmp;
     delete velocity_tmp;
     delete acceleration_tmp;
   }
 
   return insertion_new_element;
 
 }
 
 __END_AKANTU__
 
 #if defined (AKANTU_PARALLEL_COHESIVE_ELEMENT)
 #  include "solid_mechanics_model_cohesive_parallel_inline_impl.cc"
 #endif
 
 #endif /* __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_CC__ */
diff --git a/test/test_model/test_solid_mechanics_model/test_embedded_interface/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_embedded_interface/CMakeLists.txt
index 84a2ddabf..31ac629ff 100644
--- a/test/test_model/test_solid_mechanics_model/test_embedded_interface/CMakeLists.txt
+++ b/test/test_model/test_solid_mechanics_model/test_embedded_interface/CMakeLists.txt
@@ -1,49 +1,49 @@
 #===============================================================================
 # @file   CMakeLists.txt
 #
 # @author Lucas Frérot <lucas.frerot@epfl.ch>
 #
 # @date creation: Wed Mar 25 2015
 # @date last modification: Wed Mar 25 2015
 #
 # @brief  configuration for embedded interface tests
 #
 # @section LICENSE
 #
 # Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne)
 # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
 #
 # Akantu is free  software: you can redistribute it and/or  modify it under the
 # terms  of the  GNU Lesser  General Public  License as  published by  the Free
 # Software Foundation, either version 3 of the License, or (at your option) any
 # later version.
 #
 # Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 # A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
 # details.
 #
 # You should  have received  a copy  of the GNU  Lesser General  Public License
 # along with Akantu. If not, see <http://www.gnu.org/licenses/>.
 #
 # @section DESCRIPTION
 #
 #===============================================================================
 
 register_test(test_embedded_element_matrix
   SOURCES test_embedded_element_matrix.cc
   FILES_TO_COPY triangle.msh embedded_element.dat
-  PACKAGE embedded
+  PACKAGE embedded implicit
   )
 
 register_test(test_embedded_interface_model
   SOURCES test_embedded_interface_model.cc
   FILES_TO_COPY embedded_mesh.msh material.dat matrix
-  PACKAGE embedded
+  PACKAGE embedded implicit
   )
 
 register_test(test_embedded_interface_model_prestress
   SOURCES test_embedded_interface_model_prestress.cc
   FILES_TO_COPY embedded_mesh_prestress.msh embedded_mesh_prestress_reinforcement.msh prestress.dat
-  PACKAGE embedded
+  PACKAGE embedded implicit
   )
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt
index 4f9679296..245621a12 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt
+++ b/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt
@@ -1,61 +1,61 @@
 #===============================================================================
 # @file   CMakeLists.txt
 #
 # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
 #
 # @date creation: Fri Nov 26 2010
 # @date last modification: Fri Feb 14 2014
 #
 # @brief  configuration for materials tests
 #
 # @section LICENSE
 #
 # Copyright (©) 2010-2012, 2014 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
 #
 #===============================================================================
 
 add_mesh(test_local_material_barre_trou_mesh barre_trou.geo 2 2)
 register_test(test_local_material
   SOURCES  test_local_material.cc local_material_damage.cc
   EXTRA_FILES local_material_damage.hh local_material_damage_inline_impl.cc
   DEPENDENCIES test_local_material_barre_trou_mesh
   FILES_TO_COPY material.dat
   DIRECTORIES_TO_CREATE paraview
   PACKAGE core
   )
 
 add_mesh(test_material_thermal_mesh square.geo 2 1)
 register_test(test_material_thermal
   SOURCES test_material_thermal.cc
   DEPENDENCIES test_material_thermal_mesh
   FILES_TO_COPY material_thermal.dat
   PACKAGE core
   )
 # ==============================================================================
 add_mesh(test_interpolate_stress_mesh interpolation.geo 3 2)
 register_test(test_interpolate_stress test_interpolate_stress.cc
   FILES_TO_COPY material.dat
   DEPENDENCIES test_interpolate_stress_mesh
   DIRECTORIES_TO_CREATE paraview
-  PACKAGE core
+  PACKAGE lapack core
   )
 
 # ==============================================================================
 add_akantu_test(test_material_viscoelastic "test the visco elastic materials")
 add_akantu_test(test_material_non_local "test the non-local materials")