diff --git a/cmake/AkantuMacros.cmake b/cmake/AkantuMacros.cmake
index 65326f516..15d9822f8 100644
--- a/cmake/AkantuMacros.cmake
+++ b/cmake/AkantuMacros.cmake
@@ -1,152 +1,152 @@
 #===============================================================================
 # @file   AkantuMacros.cmake
 #
 # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
 # @author Nicolas Richart <nicolas.richart@epfl.ch>
 #
 # @date creation: Thu Feb 17 2011
 # @date last modification: Tue Aug 19 2014
 #
 # @brief  Set of macros used by akantu cmake 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/>.
 #
 #===============================================================================
 
 #===============================================================================
 function(set_third_party_shared_libirary_name _var _lib)
   set(${_var}
     ${PROJECT_BINARY_DIR}/third-party/lib/${CMAKE_SHARED_LIBRARY_PREFIX}${_lib}${CMAKE_SHARED_LIBRARY_SUFFIX}
     CACHE FILEPATH "" FORCE)
 endfunction()
 
 #===============================================================================
 # Generate the list of currently loaded materials
 function(generate_material_list)
   message(STATUS "Determining the list of recognized materials...")
 
-  package_get_include_directories(
+  package_get_all_include_directories(
     AKANTU_LIBRARY_INCLUDE_DIRS
     )
 
-  package_get_external_informations(
+  package_get_all_external_informations(
     AKANTU_EXTERNAL_INCLUDE_DIR
     AKANTU_EXTERNAL_LIBRARIES
     )
 
   set(_include_dirs ${AKANTU_INCLUDE_DIRS} ${AKANTU_EXTERNAL_INCLUDE_DIR})
 
   try_run(_material_list_run _material_list_compile
     ${CMAKE_BINARY_DIR}
     ${PROJECT_SOURCE_DIR}/cmake/material_lister.cc
     CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${_include_dirs}"
     COMPILE_DEFINITIONS "-DAKANTU_CMAKE_LIST_MATERIALS"
     COMPILE_OUTPUT_VARIABLE _compile_results
     RUN_OUTPUT_VARIABLE _result_material_list)
 
   if(_material_list_compile AND "${_material_list_run}" EQUAL 0)
     message(STATUS "Materials included in Akantu:")
     string(REPLACE "\n" ";" _material_list "${_result_material_list}")
     foreach(_mat ${_material_list})
       string(REPLACE ":" ";" _mat_key "${_mat}")
       list(GET _mat_key 0 _key)
       list(GET _mat_key 1 _class)
       list(LENGTH _mat_key _l)
 
       if("${_l}" GREATER 2)
 	list(REMOVE_AT _mat_key 0 1)
 	set(_opt " -- options: [")
 	foreach(_o ${_mat_key})
 	  set(_opt "${_opt} ${_o}")
 	endforeach()
 	set(_opt "${_opt} ]")
       else()
 	set(_opt "")
       endif()
 
       message(STATUS "   ${_class} -- key: ${_key}${_opt}")
     endforeach()
   else()
     message(STATUS "Could not determine the list of materials.")
     message("${_compile_results}")
   endif()
 endfunction()
 
 #===============================================================================
 if(__CMAKE_PARSE_ARGUMENTS_INCLUDED)
   return()
 endif()
 set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE)
 
 function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames)
   # first set all result variables to empty/FALSE
   foreach(arg_name ${_singleArgNames} ${_multiArgNames})
     set(${prefix}_${arg_name})
   endforeach(arg_name)
 
   foreach(option ${_optionNames})
     set(${prefix}_${option} FALSE)
   endforeach(option)
 
   set(${prefix}_UNPARSED_ARGUMENTS)
 
   set(insideValues FALSE)
   set(currentArgName)
 
   # now iterate over all arguments and fill the result variables
   foreach(currentArg ${ARGN})
     list(FIND _optionNames "${currentArg}" optionIndex)  # ... then this marks the end of the arguments belonging to this keyword
     list(FIND _singleArgNames "${currentArg}" singleArgIndex)  # ... then this marks the end of the arguments belonging to this keyword
     list(FIND _multiArgNames "${currentArg}" multiArgIndex)  # ... then this marks the end of the arguments belonging to this keyword
 
     if(${optionIndex} EQUAL -1  AND  ${singleArgIndex} EQUAL -1  AND  ${multiArgIndex} EQUAL -1)
       if(insideValues)
         if("${insideValues}" STREQUAL "SINGLE")
           set(${prefix}_${currentArgName} ${currentArg})
           set(insideValues FALSE)
         elseif("${insideValues}" STREQUAL "MULTI")
           list(APPEND ${prefix}_${currentArgName} ${currentArg})
         endif()
       else(insideValues)
         list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg})
       endif(insideValues)
     else()
       if(NOT ${optionIndex} EQUAL -1)
         set(${prefix}_${currentArg} TRUE)
         set(insideValues FALSE)
       elseif(NOT ${singleArgIndex} EQUAL -1)
         set(currentArgName ${currentArg})
         set(${prefix}_${currentArgName})
         set(insideValues "SINGLE")
       elseif(NOT ${multiArgIndex} EQUAL -1)
         set(currentArgName ${currentArg})
         set(${prefix}_${currentArgName})
         set(insideValues "MULTI")
       endif()
     endif()
 
   endforeach(currentArg)
 
   # propagate the result variables to the caller:
   foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames})
     set(${prefix}_${arg_name}  ${${prefix}_${arg_name}} PARENT_SCOPE)
   endforeach(arg_name)
   set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
 endfunction(CMAKE_PARSE_ARGUMENTS _options _singleArgs _multiArgs)
 
diff --git a/cmake/Modules/CMakePackagesSystem.cmake b/cmake/Modules/CMakePackagesSystem.cmake
index a68c32a8a..196ef26f4 100644
--- a/cmake/Modules/CMakePackagesSystem.cmake
+++ b/cmake/Modules/CMakePackagesSystem.cmake
@@ -1,1209 +1,1213 @@
 #===============================================================================
 # @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 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)
 
 
 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)
 
 # ==============================================================================
 # 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_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()
 
 # ------------------------------------------------------------------------------
 # 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}}")
   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_extra_options pkg_name)
   set(${pkg_name}_OPTIONS ${ARGN}
     CACHE INTERNAL "Extra option for the fin_package function" FORCE)
 endfunction()
 
 function(package_get_extra_options pkg_name options)
   set(${options} "${${pkg_name}_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)
   set(${libraries} ${${pkg_name}_LIBRARIES} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # Extra dependencies like custom commands of ExternalProject
 function(package_add_extra_dependency PACKAGE)
   package_get_name(${PACKAGE} _pkg_name)
 
   set(_tmp_dep ${${pkg_name}_EXTRA_DEPENDS})
   list(APPEND _tmp_dep ${ARGN})
   list(REMOVE_DUPLICATES _tmp_dep)
   set(${pkg_name}_EXTRA_DEPENDS ${_tmp_dep} CACHE INTERNAL "External dependencies" FORCE)
 endfunction()
 
 function(package_get_extra_dependency PACKAGE deps)
   package_get_name(${PACKAGE} _pkg_name)
   set(${deps} ${${pkg_name}_EXTRA_DEPENDS} PARENT_SCOPE)
 endfunction()
 
 function(_package_unset_extra_dependency pkg_name)
   unset(${pkg_name}_EXTRA_DEPENDS 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_set_dependencies pkg_name)
   set(${pkg_name}_DEPENDENCIES "${ARGN}"
     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()
 
 # ------------------------------------------------------------------------------
 # 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_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_get_documentation pkg _doc)
   # \n replaced by && and \\ by ££ to avoid cache problems
   package_get_name(${pkg} _pkg_name)
   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()
 # ------------------------------------------------------------------------------
 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()
 
 # ------------------------------------------------------------------------------
 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()
 
 # ==============================================================================
 # 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)
 
   foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST})
     _package_unset_activated(${_pkg_name})
     _package_unset_extra_dependency(${_pkg_name})
   endforeach()
 
   # 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)
     package_is_deactivated(${_pkg_name} _deactivated)
 
     if(NOT _deactivated AND ${_option_name})
       _package_load_package(${_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()
     # deactivate the packages than can already be deactivated
     package_deactivate(${pkg_name})
 
     #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)
     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_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
-      package_set_libraries(${_pkg_name} ${${_prefix}_LIBRARIES})
+      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_SOURCE_DIR}/tmp/)
   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_SOURCE_DIR}/tmp/${_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_SOURCE_DIR}/tmp/")
     endif()
     message(SEND_ERROR "Please register them in the good package or clean the sources")
   endif()
 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)
 
   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)
     list(APPEND _package_files ${_basename})
   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_get_name(Boost _boost_pkg)
   package_is_activated(${_boost_pkg} _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> ...]
 #                 [EXTRA_PACKAGE_OPTIONS <opt> ...]
 #                 [COMPILE_FLAGS <flags>])
 # ------------------------------------------------------------------------------
 function(package_declare PACKAGE)
   package_get_name(${PACKAGE} _pkg_name)
   _package_set_real_name(${_pkg_name} ${PACKAGE})
 
   cmake_parse_arguments(_opt_pkg
     "EXTERNAL;NOT_OPTIONAL;META;ADVANCED"
     "DEFAULT;DESCRIPTION;SYSTEM"
     "DEPENDS;EXTRA_PACKAGE_OPTIONS;COMPILE_FLAGS"
     ${ARGN})
 
   if(_opt_pkg_UNPARSED_ARGUMENTS)
     message("You gave to many arguments while registering the package ${PACKAGE} \"${_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)
     _package_set_system_option(${_pkg_name} ${_opt_pkg_SYSTEM})
   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_set_dependencies(${_pkg_name} ${_depends})
     package_get_dependencies(${_pkg_name} _deps)
   endif()
 
   # keep the extra option for the future find package
   if(_opt_pkg_EXTRA_PACKAGE_OPTIONS)
     _package_set_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()
 
 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()
 
 # ------------------------------------------------------------------------------
 # get the list of source files for a given package
 # ------------------------------------------------------------------------------
 function(package_get_source_files PKG 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}_${_type}})
       string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" _rel_file "${_file}")
       list(APPEND tmp_${_type} "${_rel_file}")
     endforeach()
   endforeach()
   
 #  message(__tmp_SRCS ":   " ${tmp_SRCS})
 
   set(${SRCS}            ${tmp_SRCS}            PARENT_SCOPE)
   set(${PUBLIC_HEADERS}  ${tmp_PUBLIC_HEADERS}  PARENT_SCOPE)
   set(${PRIVATE_HEADERS} ${tmp_PRIVATE_HEADERS} PARENT_SCOPE)
 endfunction()
 
 # ------------------------------------------------------------------------------
 # 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)
 
   foreach(_pkg_name ${${_project}_ACTIVATED_PACKAGE_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)
   foreach(_pkg_name ${${_project}_ACTIVATED_PACKAGE_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)
   foreach(_pkg_name ${${_project}_ACTIVATED_PACKAGE_LIST})
     package_get_nature(${_pkg_name} _nature)
     if(${_nature} MATCHES "external")
       package_get_include_dir(${_pkg_name} _inc)
       package_get_libraries  (${_pkg_name} _lib)
 
       list(APPEND tmp_INCLUDE_DIR ${_inc})
       list(APPEND tmp_LIBRARIES   ${_lib})
     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)
   foreach(_pkg_name ${${_project}_ACTIVATED_PACKAGE_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_dependency DEPS)
   string(TOUPPER ${PROJECT_NAME} _project)
   set(_tmp_DEPS)
   foreach(_pkg_name ${${_project}_ACTIVATED_PACKAGE_LIST})
     package_get_extra_dependency(${_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)
   foreach(_pkg_name ${${_project}_ACTIVATED_PACKAGE_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()
 
 # ------------------------------------------------------------------------------
 function(package_get_all_documentation_files doc_files)
   string(TOUPPER ${PROJECT_NAME} _project)
   set(_tmp_DOC_FILES)
 
   foreach(_pkg_name ${${_project}_ACTIVATED_PACKAGE_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()
 
 # ------------------------------------------------------------------------------
 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()
 
 
 # ------------------------------------------------------------------------------
 # Special boost thingy
 # ------------------------------------------------------------------------------
 function(package_boost_component_needed)
   string(TOUPPER ${PROJECT_NAME} _project)
 
   set(_tmp ${${_project}_BOOST_COMPONENTS_NEEDED})
   list(APPEND _tmp ${ARGN})
   list(REMOVE_DUPLICATES _tmp)
   set(${_project}_BOOST_COMPONENTS_NEEDED ${_tmp}
       CACHE INTERNAL "List of Boost component needed by ${PROJECT_NAME}" FORCE)
 endfunction()
 
 function(package_load_boost_components)
   string(TOUPPER ${PROJECT_NAME} _project)
   package_get_name(Boost _pkg_name)
 
   if(${_project}_BOOST_COMPONENTS_NEEDED)
     message(STATUS "Looking for Boost liraries")
     foreach(_comp ${${_project}_BOOST_COMPONENTS_NEEDED})
       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()
diff --git a/packages/80_cpparray.cmake b/packages/80_cpparray.cmake
index 94d6c5296..dadd0aade 100644
--- a/packages/80_cpparray.cmake
+++ b/packages/80_cpparray.cmake
@@ -1,83 +1,66 @@
 #===============================================================================
 # @file   cpp_array.cmake
 #
 # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
 # @author Nicolas Richart <nicolas.richart@epfl.ch>
 #
 # @date   Mon Nov 21 18:19:15 2011
 #
 # @brief  package description for cpp_array project
 #
 # @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/>.
 #
 #===============================================================================
 package_declare(CppArray EXTERNAL
   DESCRIPTION "Use cpp-array library"
   SYSTEM OFF)
 
-if(AKANTU_USE_CPPARRAY AND AKANTU_USE_THIRD_PARTY_CPPARRAY)
-  find_package(Git)
+package_get_name(CppArray _pkg_name)
+package_use_system(${_pkg_name} _use_system)
+package_get_option_name(${_pkg_name} _option_name)
 
-  if(GIT_FOUND)
-    if(EXISTS ${PROJECT_SOURCE_DIR}/third-party/cpp-array)
-      execute_process(
-	COMMAND ${GIT_EXECUTABLE} pull
-	WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/third-party/cpp-array
-	OUTPUT_VARIABLE _revision)
-      message(STATUS "Updating Cpp-Array")
-    else()
-      message(STATUS "Cloning Cpp-Array")
-      execute_process(
-	COMMAND ${GIT_EXECUTABLE} clone https://code.google.com/p/cpp-array.git ${PROJECT_SOURCE_DIR}/third-party/cpp-array
-	OUTPUT_QUIET)
+if(NOT ${_use_system})
+  if(${_option_name})
+    if(TARGET cpparray)
+      return()
     endif()
-  endif()
-
-  if(EXISTS ${PROJECT_SOURCE_DIR}/third-party/cpp-array/)
-    set(cpp-array_TESTS OFF CACHE BOOL "cpparray tests" FORCE)
-    add_subdirectory(${PROJECT_SOURCE_DIR}/third-party/cpp-array/)
-    set(cpp-array_TESTS OFF CACHE BOOL "cpparray tests" FORCE)
 
-    mark_as_advanced(cpp-array_DEV)
-    mark_as_advanced(cpp-array_DOCUMENTATION)
-    mark_as_advanced(cpp-array_TESTS)
-    mark_as_advanced(CUDA)
-    mark_as_advanced(ARRAY_USER_LIB_PATH)
+    set(CPPARRAY_DIR ${PROJECT_BINARY_DIR}/third-party)
 
-    list(APPEND AKANTU_EXTERNAL_LIB_INCLUDE_DIR ${cpp-array_INCLUDE_DIRS} ${CPP-ARRAY_INCLUDE_DIRS})
-    list(APPEND AKANTU_EXTERNAL_LIBRARIES ${CPP-ARRAY_LIBRARIES})
-    list(APPEND AKANTU_EXTERNAL_LIB_INCLUDE_DIR ${CPP-ARRAY_INCLUDE_DIRS})
-    list(APPEND CPACK_SOURCE_IGNORE_FILES ${PROJECT_SOURCE_DIR}/third-party/cpp-array/)
-    set(AKANTU_CPPARRAY_INCLUDE_DIR ${cpp-array_INCLUDE_DIRS} ${CPP-ARRAY_INCLUDE_DIRS})
+    include(ExternalProject)
+    ExternalProject_Add(cpparray
+      PREFIX ${CPPARRAY_DIR}
+      GIT_REPOSITORY https://code.google.com/p/cpp-array.git
+      CMAKE_ARGS <SOURCE_DIR>/cpp-array
+      CMAKE_CACHE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -Dcpp-array_TESTS:BOOL=OFF -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER} -DCMAKE_Fortran_COMPILER:PATH=${CMAKE_Fortran_COMPILER}
+      )
 
+    set(CPPARRAY_INCLUDE_DIR ${CPPARRAY_DIR}/include CACHE PATH "" FORCE)
 
-    set(AKANTU_CPPARRAY ON)
-    list(APPEND AKANTU_OPTION_LIST CPPARRAY)
-    set(AKANTU_CPPARRAY ${AKANTU_CPPARRAY} CACHE INTERNAL "Use cpp-array library" FORCE)
-  else()
-    message(STATUS "Cpp-Array could not be found! Please install git and/or place cpp-array in the third-party folder of Akantu")
+    package_set_include_dir(${_pkg_name} ${CPPARRAY_INCLUDE_DIR})
+    package_add_extra_dependency(CppArray cpparray)
   endif()
 endif()
 
 
 package_declare_documentation(CppArray
   "This package provides access to the \\href{https://code.google.com/p/cpp-array/}{cpp-array}"
   "open-source project. If internet is accessible when configuring the project (during cmake call)"
   "this package will be auto-downloaded."
   )
diff --git a/packages/80_nlopt.cmake b/packages/80_nlopt.cmake
index c506d4dd9..2f6269bc0 100644
--- a/packages/80_nlopt.cmake
+++ b/packages/80_nlopt.cmake
@@ -1,79 +1,82 @@
 #===============================================================================
 # @file   80_nlopt.cmake
 #
 # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
 # @author Nicolas Richart <nicolas.richart@epfl.ch>
 #
 # @date creation: Thu Jun 05 2014
 # @date last modification: Thu Sep 18 2014
 #
 # @brief  package for the opitmization library NLopt
 #
 # @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/>.
 #
 #===============================================================================
 package_declare(nlopt EXTERNAL
   DESCRIPTION "Use NLOPT library"
   SYSTEM OFF)
 
-set(NLOPT_VERSION "2.4.2")
-set(NLOPT_ARCHIVE "${PROJECT_SOURCE_DIR}/third-party/nlopt-${NLOPT_VERSION}.tar.gz")
-set(NLOPT_ARCHIVE_HASH "MD5=d0b8f139a4acf29b76dbae69ade8ac54")
-if(NOT EXISTS ${NLOPT_ARCHIVE})
-  set(NLOPT_ARCHIVE "http://ab-initio.mit.edu/nlopt/nlopt-${NLOPT_VERSION}.tar.gz")
-endif()
+package_get_name(nlopt _pkg_name)
+package_use_system(${_pkg_name} _use_system)
 
-if (AKANTU_USE_THIRD_PARTY_NLOPT AND AKANTU_USE_NLOPT)
-  set(NLOPT_CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> --enable-shared --with-cxx)
-  set(NLOPT_DIR ${PROJECT_BINARY_DIR}/third-party)
+if(NOT ${_use_system})
+  package_get_option_name(${_pkg_name} _option_name)
 
-  include(ExternalProject)
+  if(${_option_name})
+    set(NLOPT_VERSION "2.4.2")
+    set(NLOPT_ARCHIVE "${PROJECT_SOURCE_DIR}/third-party/nlopt-${NLOPT_VERSION}.tar.gz")
+    set(NLOPT_ARCHIVE_HASH "MD5=d0b8f139a4acf29b76dbae69ade8ac54")
+    if(NOT EXISTS ${NLOPT_ARCHIVE})
+      set(NLOPT_ARCHIVE "http://ab-initio.mit.edu/nlopt/nlopt-${NLOPT_VERSION}.tar.gz")
+    endif()
 
-  ExternalProject_Add(NLopt
-    PREFIX ${NLOPT_DIR}
-    URL ${NLOPT_ARCHIVE}
-    URL_HASH ${NLOPT_ARCHIVE_HASH}
-    CONFIGURE_COMMAND ${NLOPT_CONFIGURE_COMMAND}
-    BUILD_COMMAND make
-    INSTALL_COMMAND make install
-    )
+    string(TOUPPER "${CMAKE_BUILD_TYPE}" _u_build_type)
+    set(NLOPT_CONFIGURE_COMMAND CXX=${CMAKE_CXX_COMPILER} CXX_FLAGS=${CMAKE_CXX_FLAGS_${_u_build_type}} <SOURCE_DIR>/configure
+      --prefix=<INSTALL_DIR> --enable-shared --with-cxx --without-threadlocal
+      --without-guile --without-python --without-octave --without-matlab)
+  set(NLOPT_DIR ${PROJECT_BINARY_DIR}/third-party)
 
-  set(NLOPT_LIBRARIES   ${NLOPT_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}nlopt_cxx${CMAKE_SHARED_LIBRARY_SUFFIX} CACHE PATH "Libraries for NLopt" FORCE)
-  set(NLOPT_INCLUDE_DIR ${NLOPT_DIR}/include CACHE PATH "Include directories for NLopt" FORCE)
+    include(ExternalProject)
 
-  mark_as_advanced(NLOPT_INCLUDE_DIR NLOPT_LIBRARIES)
+    ExternalProject_Add(NLopt
+      PREFIX ${NLOPT_DIR}
+      URL ${NLOPT_ARCHIVE}
+      URL_HASH ${NLOPT_ARCHIVE_HASH}
+      CONFIGURE_COMMAND ${NLOPT_CONFIGURE_COMMAND}
+      BUILD_COMMAND make
+      INSTALL_COMMAND make install
+      )
 
-  list(APPEND AKANTU_EXTERNAL_LIBRARIES ${NLOPT_LIBRARIES})
-  list(APPEND AKANTU_EXTERNAL_LIB_INCLUDE_DIR ${NLOPT_INCLUDE_DIR})
-  set(AKANTU_NLOPT_INCLUDE_DIR ${NLOPT_INCLUDE_DIR})
-  set(AKANTU_NLOPT_LIBRARIES ${NLOPT_LIBRARIES})
-  list(APPEND AKANTU_OPTION_LIST NLOPT)
-  set(NLOPT_FOUND TRUE CACHE INTERNAL "" FORCE)
-  set(AKANTU_NLOPT ON)
+    set_third_party_shared_libirary_name(NLOPT_LIBRARIES nlopt_cxx)
+    set(NLOPT_INCLUDE_DIR ${NLOPT_DIR}/include CACHE PATH "Include directories for NLopt" FORCE)
+    mark_as_advanced(NLOPT_INCLUDE_DIR)
 
-  list(APPEND AKANTU_EXTRA_TARGET_DEPENDENCIES NLopt)
-endif()
+    package_set_libraries(${_pkg_name} ${NLOPT_LIBRARIES})
+    package_set_include_dir(${_pkg_name} ${NLOPT_INCLUDE_DIR})
 
+    package_add_extra_dependency(nlopt NLopt)
+  endif()
+endif()
 
 package_declare_documentation(nlopt
   "This package enable the use of the optimization alogorithm library \\href{http://ab-initio.mit.edu/wiki/index.php/NLopt}{NLopt}."
   "Since there are no packaging for the common operating system by default \\akantu compiles it as a third-party project. This behavior can be modified with the option \\code{AKANTU\\_USE\\_THIRD\\_PARTY\\_NLOPT}."
   ""
   "If the automated download fails please download \\href{http://ab-initio.mit.edu/nlopt/nlopt-${NLOPT_VERSION}.tar.gz}{nlopt-${NLOPT_VERSION}.tar.gz} and place it in \\shellcode{<akantu source>/third-party} download."
   )
diff --git a/packages/84_petsc.cmake b/packages/84_petsc.cmake
index 46623d851..6412f42ab 100644
--- a/packages/84_petsc.cmake
+++ b/packages/84_petsc.cmake
@@ -1,51 +1,46 @@
 #===============================================================================
 # @file   petsc.cmake
 #
 # @author Nicolas Richart <nicolas.richart@epfl.ch>
 # @author Alejandro M. Aragón <alejandro.aragon@epfl.ch>
 # @author Aurelia Cuba Ramos <aurelia.cubaramos@epfl.ch>
 #
 # @date   Mon Nov 21 18:19:15 2011
 #
 # @brief  package description for PETSc support
 #
 # @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/>.
 #
 #===============================================================================
 
 package_declare(PETSc EXTERNAL
   DESCRIPTION "Add PETSc support in akantu"
   EXTRA_PACKAGE_OPTIONS ARGS COMPONENTS CXX
   DEPENDS parallel)
 
 
 package_declare_sources(petsc
   solver/petsc_matrix.hh
   solver/petsc_matrix.cc
   solver/petsc_matrix_inline_impl.cc
   solver/solver_petsc.hh
   solver/solver_petsc.cc
   solver/petsc_wrapper.hh
   )
 
-set(AKANTU_PETSC_TESTS
-  test_petsc_matrix_profile
-  test_petsc_matrix_apply_boundary
-  test_solver_petsc
-  )
diff --git a/src/common/aka_fwd.hh b/src/common/aka_fwd.hh
index c452445fa..d5c0c4a99 100644
--- a/src/common/aka_fwd.hh
+++ b/src/common/aka_fwd.hh
@@ -1,71 +1,70 @@
 /**
  * @file   aka_fwd.hh
  *
  * @author Alejandro M. Aragón <alejandro.aragon@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jan 04 2013
  * @date last modification: Mon Jun 02 2014
  *
  * @brief  File containing forward declarations in akantu.
  * This file helps if circular #include would be needed because two classes
  * refer both to each other. This file usually does not need any modification.
  *
  * @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_FWD_HH__
 #define __AKANTU_FWD_HH__
 
 
 namespace cppargparse {
   class ArgumentParser;
 }
 
 namespace akantu {
-  
   // forward declaration
   template <int dim, class model_type>
   struct ContactData;
-  
+
   template<typename T> class Matrix;
   template<typename T> class Vector;
   template<typename T> class Tensor3;
 
   template<typename T, bool is_scal = is_scalar<T>::value > class Array;
 
   template <class T> class SpatialGrid;
 
   // Model element
   template <class ModelPolicy> class ModelElement;
 
   extern const Array<UInt> empty_filter;
 
   class Parser;
   class ParserSection;
 
   extern Parser static_parser;
 
   extern cppargparse::ArgumentParser static_argparser;
 }
 
 
 #endif /* __AKANTU_FWD_HH__ */
diff --git a/src/fe_engine/fe_engine.hh b/src/fe_engine/fe_engine.hh
index 61ee2f43b..c24dd3a79 100644
--- a/src/fe_engine/fe_engine.hh
+++ b/src/fe_engine/fe_engine.hh
@@ -1,393 +1,398 @@
 /**
  * @file   fe_engine.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Tue Jul 20 2010
  * @date last modification: Mon Jul 07 2014
  *
  * @brief  FEM 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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_FE_ENGINE_HH__
 #define __AKANTU_FE_ENGINE_HH__
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "aka_memory.hh"
 #include "mesh.hh"
 #include "element_class.hh"
 #include "sparse_matrix.hh"
 
 /* -------------------------------------------------------------------------- */
 namespace akantu {
   class Integrator;
   class ShapeFunctions;
 }
 
 __BEGIN_AKANTU__
 
 class QuadraturePoint : public Element {
 public:
   typedef Vector<Real> position_type;
 public:
+  QuadraturePoint(const Element & element, UInt num_point = 0, UInt nb_quad_per_element = 0) :
+    Element(element), num_point(num_point),
+    global_num(element.element*nb_quad_per_element + num_point),
+    position((Real *)NULL, 0) { };
+
   QuadraturePoint(ElementType type = _not_defined, UInt element = 0,
 		  UInt num_point = 0, GhostType ghost_type = _not_ghost) :
     Element(type, element, ghost_type), num_point(num_point), global_num(0),
     position((Real *)NULL, 0) { };
 
   QuadraturePoint(UInt element, UInt num_point,
 		  UInt global_num,
 		  const position_type & position,
 		  ElementType type,
 		  GhostType ghost_type = _not_ghost) :
     Element(type, element, ghost_type), num_point(num_point), global_num(global_num),
     position((Real *)NULL, 0) { this->position.shallowCopy(position); };
 
   QuadraturePoint(const QuadraturePoint & quad) :
     Element(quad), num_point(quad.num_point), global_num(quad.global_num), position((Real *) NULL, 0) {
     position.shallowCopy(quad.position);
   };
 
   inline QuadraturePoint & operator=(const QuadraturePoint & q) {
     if(this != &q) {
       element    = q.element;
       type       = q.type;
       ghost_type = q.ghost_type;
       num_point  = q.num_point;
       global_num = q.global_num;
       position.shallowCopy(q.position);
     }
 
     return *this;
   }
 
   AKANTU_GET_MACRO(Position, position, const position_type &);
 
   void setPosition(const position_type & position) {
     this->position.shallowCopy(position);
   }
 
   /// 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 << space << "QuadraturePoint [";
     Element::printself(stream, 0);
     stream << ", " << num_point << "]";
   }
 
 public:
   UInt num_point;
   UInt global_num;
 private:
   position_type position;
 };
 
 /**
  * The  generic  FEEngine class  derived  in  a  FEEngineTemplate class  containing  the
  * shape functions and the integration method
  */
 class FEEngine : protected Memory {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   FEEngine(Mesh & mesh, UInt spatial_dimension = _all_dimensions,
       ID id = "fem", MemoryID memory_id = 0);
 
   virtual ~FEEngine();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// pre-compute all the shape functions, their derivatives and the jacobians
   virtual void initShapeFunctions(const GhostType & ghost_type = _not_ghost) = 0;
 
   /// extract the nodal values and store them per element
   template<typename T>
   static void extractNodalToElementField(const Mesh & mesh,
 					 const Array<T> & nodal_f,
 					 Array<T> & elemental_f,
 					 const ElementType & type,
 					 const GhostType & ghost_type = _not_ghost,
 					 const Array<UInt> & filter_elements = empty_filter);
 
   /// filter a field
   template<typename T>
   static void filterElementalData(const Mesh & mesh,
                                   const Array<T> & quad_f,
                                   Array<T> & filtered_f,
                                   const ElementType & type,
                                   const GhostType & ghost_type = _not_ghost,
                                   const Array<UInt> & filter_elements = empty_filter);
 
 
 
   /* ------------------------------------------------------------------------ */
   /* Integration method bridges                                               */
   /* ------------------------------------------------------------------------ */
   /// integrate f for all elements of type "type"
   virtual void integrate(const Array<Real> & f,
 			 Array<Real> &intf,
 			 UInt nb_degree_of_freedom,
 			 const ElementType & type,
 			 const GhostType & ghost_type = _not_ghost,
 			 const Array<UInt> & filter_elements = empty_filter) const = 0;
 
   /// integrate a scalar value on all elements of type "type"
   virtual Real integrate(const Array<Real> & f,
 			 const ElementType & type,
 			 const GhostType & ghost_type = _not_ghost,
 			 const Array<UInt> & filter_elements = empty_filter) const = 0;
 
   /// integrate f for all quadrature points of type "type" but don't sum over all quadrature points
   virtual void integrateOnQuadraturePoints(const Array<Real> & f,
 					   Array<Real> &intf,
 					   UInt nb_degree_of_freedom,
 					   const ElementType & type,
 					   const GhostType & ghost_type = _not_ghost,
 					   const Array<UInt> & filter_elements = empty_filter) const = 0;
 
   /// integrate one element scalar value on all elements of type "type"
   virtual Real integrate(const Vector<Real> & f,
 			 const ElementType & type,
 			 UInt index, const GhostType & ghost_type = _not_ghost) const = 0;
 
 
   /* ------------------------------------------------------------------------ */
   /* compatibility with old FEEngine fashion */
   /* ------------------------------------------------------------------------ */
 #ifndef SWIG
   /// get the number of quadrature points
   virtual UInt getNbQuadraturePoints(const ElementType & type,
 				     const GhostType & ghost_type = _not_ghost) const = 0;
   /// get the precomputed shapes
   const virtual Array<Real> & getShapes(const ElementType & type,
 					const GhostType & ghost_type = _not_ghost,
 					UInt id = 0) const = 0;
 
   /// get the derivatives of shapes
   const virtual Array<Real> & getShapesDerivatives(const ElementType & type,
 						   const GhostType & ghost_type = _not_ghost,
 						   UInt id = 0) const = 0;
 
   /// get quadrature points
   const virtual Matrix<Real> & getQuadraturePoints(const ElementType & type,
 						   const GhostType & ghost_type = _not_ghost) const = 0;
 #endif
   /* ------------------------------------------------------------------------ */
   /* Shape method bridges                                                     */
   /* ------------------------------------------------------------------------ */
   virtual
   void gradientOnQuadraturePoints(const Array<Real> &u,
 				  Array<Real> &nablauq,
 				  const UInt nb_degree_of_freedom,
 				  const ElementType & type,
 				  const GhostType & ghost_type = _not_ghost,
                                   const Array<UInt> & filter_elements = empty_filter) const = 0;
 
   virtual
   void interpolateOnQuadraturePoints(const Array<Real> &u,
 				     Array<Real> &uq,
 				     UInt nb_degree_of_freedom,
 				     const ElementType & type,
 				     const GhostType & ghost_type = _not_ghost,
                                      const Array<UInt> & filter_elements = empty_filter) const = 0;
 
   virtual
   void interpolateOnQuadraturePoints(const Array<Real> & u,
 				     ElementTypeMapArray<Real> & uq,
                                      const ElementTypeMapArray<UInt> * filter_elements = NULL) const = 0;
 
   /* ------------------------------------------------------------------------ */
   /* Other methods                                                            */
   /* ------------------------------------------------------------------------ */
 
   /// pre-compute normals on control points
   virtual void computeNormalsOnControlPoints(const GhostType & ghost_type = _not_ghost) = 0;
 
   /// pre-compute normals on control points
   virtual void computeNormalsOnControlPoints(__attribute__((unused)) const Array<Real> & field,
 					     __attribute__((unused)) const GhostType & ghost_type = _not_ghost) {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
   /// pre-compute normals on control points
   virtual void computeNormalsOnControlPoints(__attribute__((unused)) const Array<Real> & field,
 					     __attribute__((unused)) Array<Real> & normal,
 					     __attribute__((unused)) const ElementType & type,
 					     __attribute__((unused)) const GhostType & ghost_type = _not_ghost) const {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
 
 
 
   /// assemble vectors
   void assembleArray(const Array<Real> & elementary_vect,
 		      Array<Real> & nodal_values,
 		      const Array<Int> & equation_number,
 		      UInt nb_degree_of_freedom,
 		      const ElementType & type,
 		      const GhostType & ghost_type = _not_ghost,
 		      const Array<UInt> & filter_elements = empty_filter,
 		      Real scale_factor = 1) const;
 
   /// assemble matrix in the complete sparse matrix
   void assembleMatrix(const Array<Real> & elementary_mat,
 		      SparseMatrix & matrix,
 		      UInt nb_degree_of_freedom,
 		      const ElementType & type,
 		      const GhostType & ghost_type = _not_ghost,
 		      const Array<UInt> & filter_elements = empty_filter) const;
 
 
   /// assemble a field as a lumped matrix (ex. rho in lumped mass)
   virtual void assembleFieldLumped(__attribute__ ((unused)) const Array<Real> & field_1,
 				   __attribute__ ((unused)) UInt nb_degree_of_freedom,
   				   __attribute__ ((unused)) Array<Real> & lumped,
   				   __attribute__ ((unused)) const Array<Int> & equation_number,
   				   __attribute__ ((unused)) ElementType type,
   				   __attribute__ ((unused)) const GhostType & ghost_type) const {
     AKANTU_DEBUG_TO_IMPLEMENT();
   };
 
 
   /// assemble a field as a matrix (ex. rho to mass matrix)
   virtual void assembleFieldMatrix(__attribute__ ((unused)) const Array<Real> & field_1,
 				   __attribute__ ((unused)) UInt nb_degree_of_freedom,
 				   __attribute__ ((unused)) SparseMatrix & matrix,
 				   __attribute__ ((unused)) ElementType type,
 				   __attribute__ ((unused)) const GhostType & ghost_type) const {
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
 
 #ifdef AKANTU_STRUCTURAL_MECHANICS
 
  virtual  void assembleFieldMatrix(__attribute__ ((unused)) const Array<Real> & field_1,
 				   __attribute__ ((unused)) UInt nb_degree_of_freedom,
 				   __attribute__ ((unused)) SparseMatrix & M,
 				   __attribute__ ((unused)) Array<Real> * n,
 				   __attribute__ ((unused)) ElementTypeMapArray<Real> & rotation_mat,
 				   __attribute__ ((unused)) ElementType type,
 				   __attribute__ ((unused)) const GhostType & ghost_type) const {
 
    AKANTU_DEBUG_TO_IMPLEMENT();
  }
 
   virtual void computeShapesMatrix(__attribute__ ((unused))const ElementType & type,
 				   __attribute__ ((unused))UInt nb_degree_of_freedom,
 				   __attribute__ ((unused))UInt nb_nodes_per_element,
 				   __attribute__ ((unused))Array<Real> * n,
 				   __attribute__ ((unused))UInt id,
 				   __attribute__ ((unused))UInt degree_to_interpolate,
 				   __attribute__ ((unused))UInt degree_interpolated,
 				   __attribute__ ((unused))const bool sign,
 				   __attribute__ ((unused))const GhostType & ghost_type) const {
 
     AKANTU_DEBUG_TO_IMPLEMENT();
   }
 
 #endif
 
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
 private:
   /// initialise the class
   void init();
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// get the dimension of the element handeled by this fe_engine object
   AKANTU_GET_MACRO(ElementDimension, element_dimension, UInt);
 
   /// get the mesh contained in the fem object
   AKANTU_GET_MACRO(Mesh, mesh, const Mesh &);
   /// get the mesh contained in the fem object
   AKANTU_GET_MACRO_NOT_CONST(Mesh, mesh, Mesh &);
 
   /// get the in-radius of an element
   static inline Real getElementInradius(const Matrix<Real> & coord, const ElementType & type);
 
   /// get the normals on quadrature points
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NormalsOnQuadPoints, normals_on_quad_points, Real);
 
   /// get cohesive element type for a given facet type
   static inline ElementType getCohesiveElementType(const ElementType & type_facet);
 
   /// get the interpolation element associated to an element type
   static inline InterpolationType getInterpolationType(const ElementType & el_type);
 
 
   virtual const ShapeFunctions & getShapeFunctionsInterface() const = 0;
   virtual const Integrator & getIntegratorInterface() const = 0;
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// spatial dimension of the problem
   UInt element_dimension;
 
   /// the mesh on which all computation are made
   Mesh & mesh;
 
   /// normals at quadrature points
   ElementTypeMapArray<Real> normals_on_quad_points;
 
 };
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const FEEngine & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const QuadraturePoint & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 __END_AKANTU__
 
 #include "fe_engine_inline_impl.cc"
 #include "fe_engine_template.hh"
 
 #endif /* __AKANTU_FE_ENGINE_HH__ */
diff --git a/src/io/dumper/dumper_material_padders.hh b/src/io/dumper/dumper_material_padders.hh
index a54fad56f..db4a43bb2 100644
--- a/src/io/dumper/dumper_material_padders.hh
+++ b/src/io/dumper/dumper_material_padders.hh
@@ -1,168 +1,167 @@
 /**
  * @file   dumper_material_padders.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Tue Sep 02 2014
  * @date last modification: Fri Sep 19 2014
  *
  * @brief  Material padders for plane stress/ plane strain
  *
  * @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_DUMPER_MATERIAL_PADDERS_HH__
 #define __AKANTU_DUMPER_MATERIAL_PADDERS_HH__
 /* -------------------------------------------------------------------------- */
 #include "dumper_padding_helper.hh"
 /* -------------------------------------------------------------------------- */
 __BEGIN_AKANTU__
 __BEGIN_AKANTU_DUMPER__
 /* -------------------------------------------------------------------------- */
 
 
 template<class T, class R>
 class MaterialPadder : public PadderGeneric<Vector<T>, R > {
 
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 
 public:
   MaterialPadder(const SolidMechanicsModel & model) :
     model(model),
-    element_index_by_material(model.getElementIndexByMaterial()) { }
+    material_index(model.getMaterialByElement()) {}
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 
   /// return the material from the global element index
   const Material & getMaterialFromGlobalIndex(Element global_index){
 
     UInt index = global_index.getIndex();
-    UInt material_id = element_index_by_material(global_index.getType())(index);
+    UInt material_id = material_index(global_index.getType())(index);
     const Material & material = model.getMaterial(material_id);
     return material;
   }
 
   /// return the type of the element from global index
   ElementType getElementTypeFromGlobalIndex(Element global_index){
     return global_index.getType();
   }
 
 protected:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 
   /// all material padders probably need access to solid mechanics model
   const SolidMechanicsModel & model;
   /// they also need an access to the map from global ids to material id and local ids
-  const ElementTypeMapArray<UInt>  & element_index_by_material;
+  const ElementTypeMapArray<UInt>  & material_index;
+
   /// the number of data per element
   const ElementTypeMapArray<UInt>  nb_data_per_element;
 
 };
 
 /* -------------------------------------------------------------------------- */
 
 template <UInt spatial_dimension>
 class StressPadder :
   public MaterialPadder<Real,Matrix<Real> > {
 
 public:
   StressPadder(const SolidMechanicsModel & model) :
     MaterialPadder<Real, Matrix<Real> >(model){
     this->setPadding(3,3);
   }
 
   inline Matrix<Real> func(const Vector<Real> & in, Element global_element_id){
-
     UInt nrows = spatial_dimension;
     UInt ncols = in.size() / nrows;
-    UInt nb_data = in.size() / (ncols*ncols);
+    UInt nb_data = in.size() / (nrows*nrows);
 
     Matrix<Real> stress = this->pad(in, nrows,ncols, nb_data);
     const Material & material = this->getMaterialFromGlobalIndex(global_element_id);
     bool plane_strain = true;
     if(spatial_dimension == 2)
       plane_strain = !material.getParam<bool>("Plane_Stress");
 
     if(plane_strain) {
       Real nu = material.getParam<Real>("nu");
       for (UInt d = 0; d < nb_data; ++d) {
 	stress(2, 2 + 3*d) = nu * (stress(0, 0 + 3*d) + stress(1, 1 + 3*d));
       }
     }
     return stress;
   }
 
   UInt getDim(){return 9;};
 
   UInt getNbComponent(UInt old_nb_comp){
     return this->getDim();
   };
-
 };
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 class StrainPadder : public MaterialPadder<Real, Matrix<Real> > {
 public:
   StrainPadder(const SolidMechanicsModel & model) :
     MaterialPadder<Real, Matrix<Real> >(model) {
     this->setPadding(3,3);
   }
 
   inline Matrix<Real> func(const Vector<Real> & in, Element global_element_id){
 
     UInt nrows = spatial_dimension;
     UInt ncols = in.size() / nrows;
     UInt nb_data = in.size() / ncols;
 
     Matrix<Real> strain = this->pad(in, nrows,ncols, nb_data);
     const Material & material = this->getMaterialFromGlobalIndex(global_element_id);
     bool plane_stress = material.getParam<bool>("Plane_Stress");
     if(plane_stress) {
       Real nu = material.getParam<Real>("nu");
       for (UInt d = 0; d < nb_data; ++d) {
 	strain(2, 2 + 3*d) = nu / (nu - 1) * (strain(0, 0 + 3*d) + strain(1, 1 + 3*d));
       }
     }
     return strain;
   }
 
   UInt getDim(){return 9;};
 
   UInt getNbComponent(UInt old_nb_comp){
     return this->getDim();
   };
 
 };
 
 /* -------------------------------------------------------------------------- */
 
 __END_AKANTU_DUMPER__
 __END_AKANTU__
 
 
 #endif /* __AKANTU_DUMPER_MATERIAL_PADDERS_HH__ */
diff --git a/src/model/solid_mechanics/fragment_manager.cc b/src/model/solid_mechanics/fragment_manager.cc
index 2516987f5..a571afa86 100644
--- a/src/model/solid_mechanics/fragment_manager.cc
+++ b/src/model/solid_mechanics/fragment_manager.cc
@@ -1,644 +1,646 @@
 /**
  * @file   fragment_manager.cc
  *
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Thu Jan 23 2014
  * @date last modification: Tue Aug 19 2014
  *
  * @brief  Group manager to handle fragments
  *
  * @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 "fragment_manager.hh"
 #include "material_cohesive.hh"
 #include <numeric>
 #include <algorithm>
 #include <functional>
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 FragmentManager::FragmentManager(SolidMechanicsModelCohesive & model,
 				 bool dump_data,
 				 const ID & id,
 				 const MemoryID & memory_id) :
   GroupManager(model.getMesh(), id, memory_id),
   model(model),
   mass_center(0, model.getSpatialDimension(), "mass_center"),
   mass(0, model.getSpatialDimension(), "mass"),
   velocity(0, model.getSpatialDimension(), "velocity"),
   inertia_moments(0, model.getSpatialDimension(), "inertia_moments"),
   principal_directions(0, model.getSpatialDimension() * model.getSpatialDimension(),
 		       "principal_directions"),
   quad_coordinates("quad_coordinates", id),
   mass_density("mass_density", id),
   nb_elements_per_fragment(0, 1, "nb_elements_per_fragment"),
   dump_data(dump_data) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   /// compute quadrature points' coordinates
   mesh.initElementTypeMapArray(quad_coordinates,
 			       spatial_dimension,
 			       spatial_dimension,
 			       _not_ghost);
 
   model.getFEEngine().interpolateOnQuadraturePoints(model.getMesh().getNodes(),
 						    quad_coordinates);
 
   /// store mass density per quadrature point
   mesh.initElementTypeMapArray(mass_density,
 			       1,
 			       spatial_dimension,
 			       _not_ghost);
 
   storeMassDensityPerQuadraturePoint();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 class CohesiveElementFilter : public GroupManager::ClusteringFilter {
 public:
   CohesiveElementFilter(const SolidMechanicsModelCohesive & model,
 			const Real max_damage = 1.) :
     model(model), is_unbroken(max_damage) {}
 
   bool operator() (const Element & el) const {
     if (el.kind == _ek_regular)
       return true;
 
-    const Array<UInt> & el_id_by_mat = model.getElementIndexByMaterial(el.type,
-								       el.ghost_type);
+    const Array<UInt> & mat_indexes = model.getMaterialByElement(el.type,
+								 el.ghost_type);
+    const Array<UInt> & mat_loc_num = model.getMaterialLocalNumbering(el.type,
+								      el.ghost_type);
 
     const MaterialCohesive & mat
       = static_cast<const MaterialCohesive &>
-      (model.getMaterial(el_id_by_mat(el.element, 0)));
+      (model.getMaterial(mat_indexes(el.element)));
 
-    UInt el_index = el_id_by_mat(el.element, 1);
+    UInt el_index = mat_loc_num(el.element);
     UInt nb_quad_per_element
       = model.getFEEngine("CohesiveFEEngine").getNbQuadraturePoints(el.type, el.ghost_type);
 
     const Array<Real> & damage_array = mat.getDamage(el.type, el.ghost_type);
 
     AKANTU_DEBUG_ASSERT(nb_quad_per_element * el_index < damage_array.getSize(),
 			"This quadrature point is out of range");
 
     const Real * element_damage
       = damage_array.storage() + nb_quad_per_element * el_index;
 
     UInt unbroken_quads = std::count_if(element_damage,
 					element_damage + nb_quad_per_element,
 					is_unbroken);
 
     if (unbroken_quads > 0)
       return true;
     return false;
   }
 
 private:
 
   struct IsUnbrokenFunctor {
     IsUnbrokenFunctor(const Real & max_damage) : max_damage(max_damage) {}
     bool operator() (const Real & x) {return x < max_damage;}
     const Real max_damage;
   };
 
   const SolidMechanicsModelCohesive & model;
   const IsUnbrokenFunctor is_unbroken;
 };
 
 /* -------------------------------------------------------------------------- */
 void FragmentManager::buildFragments(Real damage_limit) {
   AKANTU_DEBUG_IN();
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   DistributedSynchronizer * cohesive_synchronizer
     = const_cast<DistributedSynchronizer *>(model.getCohesiveSynchronizer());
 
   if (cohesive_synchronizer) {
     cohesive_synchronizer->computeBufferSize(model, _gst_smmc_damage);
     cohesive_synchronizer->asynchronousSynchronize(model, _gst_smmc_damage);
     cohesive_synchronizer->waitEndSynchronize(model, _gst_smmc_damage);
   }
 #endif
 
   DistributedSynchronizer & synchronizer
     = const_cast<DistributedSynchronizer &>(model.getSynchronizer());
 
   Mesh & mesh_facets = const_cast<Mesh &>(mesh.getMeshFacets());
 
   UInt spatial_dimension = model.getSpatialDimension();
   std::string fragment_prefix("fragment");
 
   /// generate fragments
   global_nb_fragment = createClusters(spatial_dimension,
 				      fragment_prefix,
 				      CohesiveElementFilter(model,
 							    damage_limit),
 				      &synchronizer,
 				      &mesh_facets);
 
   nb_fragment = getNbElementGroups(spatial_dimension);
   fragment_index.resize(nb_fragment);
 
   UInt * fragment_index_it = fragment_index.storage();
 
   /// loop over fragments
   for(const_element_group_iterator it(element_group_begin());
       it != element_group_end(); ++it, ++fragment_index_it) {
 
     /// get fragment index
     std::string fragment_index_string
       = it->first.substr(fragment_prefix.size() + 1);
     std::stringstream sstr(fragment_index_string.c_str());
     sstr >> *fragment_index_it;
 
     AKANTU_DEBUG_ASSERT(!sstr.fail(), "fragment_index is not an integer");
   }
 
   /// compute fragments' mass
   computeMass();
 
   if (dump_data) {
     createDumpDataArray(fragment_index, "fragments", true);
     createDumpDataArray(mass, "fragments mass");
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void FragmentManager::computeMass() {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model.getSpatialDimension();
 
   /// create a unit field per quadrature point, since to compute mass
   /// it's neccessary to integrate only density
   ElementTypeMapArray<Real> unit_field("unit_field", id);
   mesh.initElementTypeMapArray(unit_field,
 			       spatial_dimension,
 			       spatial_dimension,
 			       _not_ghost);
 
   ElementTypeMapArray<Real>::type_iterator it = unit_field.firstType(spatial_dimension,
 								     _not_ghost,
 								     _ek_regular);
   ElementTypeMapArray<Real>::type_iterator end = unit_field.lastType(spatial_dimension,
 								     _not_ghost,
 								     _ek_regular);
 
   for (; it != end; ++it) {
     ElementType type = *it;
     Array<Real> & field_array = unit_field(type);
     UInt nb_element = mesh.getNbElement(type);
     UInt nb_quad_per_element = model.getFEEngine().getNbQuadraturePoints(type);
 
     field_array.resize(nb_element * nb_quad_per_element);
     field_array.set(1.);
   }
 
   integrateFieldOnFragments(unit_field, mass);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void FragmentManager::computeCenterOfMass() {
   AKANTU_DEBUG_IN();
 
   /// integrate position multiplied by density
   integrateFieldOnFragments(quad_coordinates, mass_center);
 
   /// divide it by the fragments' mass
   Real * mass_storage = mass.storage();
   Real * mass_center_storage = mass_center.storage();
 
   UInt total_components = mass_center.getSize() * mass_center.getNbComponent();
 
   for (UInt i = 0; i < total_components; ++i)
     mass_center_storage[i] /= mass_storage[i];
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void FragmentManager::computeVelocity() {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model.getSpatialDimension();
 
   /// compute velocity per quadrature point
   ElementTypeMapArray<Real> velocity_field("velocity_field", id);
 
   mesh.initElementTypeMapArray(velocity_field,
 			       spatial_dimension,
 			       spatial_dimension,
 			       _not_ghost);
 
   model.getFEEngine().interpolateOnQuadraturePoints(model.getVelocity(),
 						    velocity_field);
 
   /// integrate on fragments
   integrateFieldOnFragments(velocity_field, velocity);
 
   /// divide it by the fragments' mass
   Real * mass_storage = mass.storage();
   Real * velocity_storage = velocity.storage();
 
   UInt total_components = velocity.getSize() * velocity.getNbComponent();
 
   for (UInt i = 0; i < total_components; ++i)
     velocity_storage[i] /= mass_storage[i];
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Given the distance @f$ \mathbf{r} @f$ between a quadrature point
  * and its center of mass, the moment of inertia is computed as \f[
  * I_\mathrm{CM} = \mathrm{tr}(\mathbf{r}\mathbf{r}^\mathrm{T})
  * \mathbf{I} - \mathbf{r}\mathbf{r}^\mathrm{T} \f] for more
  * information check Wikipedia
  * (http://en.wikipedia.org/wiki/Moment_of_inertia#Identities_for_a_skew-symmetric_matrix)
  *
  */
 
 void FragmentManager::computeInertiaMoments() {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model.getSpatialDimension();
 
   computeCenterOfMass();
 
   /// compute local coordinates products with respect to the center of match
   ElementTypeMapArray<Real> moments_coords("moments_coords", id);
 
   mesh.initElementTypeMapArray(moments_coords,
 			       spatial_dimension * spatial_dimension,
 			       spatial_dimension,
 			       _not_ghost);
 
   /// resize the by element type
   ElementTypeMapArray<Real>::type_iterator it = moments_coords.firstType(spatial_dimension,
 									 _not_ghost,
 									 _ek_regular);
   ElementTypeMapArray<Real>::type_iterator end = moments_coords.lastType(spatial_dimension,
 									 _not_ghost,
 									 _ek_regular);
 
   for (; it != end; ++it) {
     ElementType type = *it;
     Array<Real> & field_array = moments_coords(type);
     UInt nb_element = mesh.getNbElement(type);
     UInt nb_quad_per_element = model.getFEEngine().getNbQuadraturePoints(type);
 
     field_array.resize(nb_element * nb_quad_per_element);
   }
 
 
   /// compute coordinates
   Array<Real>::const_vector_iterator mass_center_it
     = mass_center.begin(spatial_dimension);
 
   /// loop over fragments
   for(const_element_group_iterator it(element_group_begin());
       it != element_group_end(); ++it, ++mass_center_it) {
 
     const ElementTypeMapArray<UInt> & el_list = it->second->getElements();
 
     ElementTypeMapArray<UInt>::type_iterator type_it = el_list.firstType(spatial_dimension,
 									 _not_ghost,
 									 _ek_regular);
     ElementTypeMapArray<UInt>::type_iterator type_end = el_list.lastType(spatial_dimension,
 									 _not_ghost,
 									 _ek_regular);
 
     /// loop over elements of the fragment
     for (; type_it != type_end; ++type_it) {
       ElementType type = *type_it;
       UInt nb_quad_per_element = model.getFEEngine().getNbQuadraturePoints(type);
 
       Array<Real> & moments_coords_array = moments_coords(type);
       const Array<Real> & quad_coordinates_array = quad_coordinates(type);
       const Array<UInt> & el_list_array = el_list(type);
 
       Array<Real>::matrix_iterator moments_begin
 	= moments_coords_array.begin(spatial_dimension, spatial_dimension);
       Array<Real>::const_vector_iterator quad_coordinates_begin
 	= quad_coordinates_array.begin(spatial_dimension);
 
       Vector<Real> relative_coords(spatial_dimension);
 
       for (UInt el = 0; el < el_list_array.getSize(); ++el) {
 	UInt global_el = el_list_array(el);
 
 	/// loop over quadrature points
 	for (UInt q = 0; q < nb_quad_per_element; ++q) {
 	  UInt global_q = global_el * nb_quad_per_element + q;
 	  Matrix<Real> & moments_matrix = moments_begin[global_q];
 	  const Vector<Real> & quad_coord_vector = quad_coordinates_begin[global_q];
 
 	  /// to understand this read the documentation written just
 	  /// before this function
 	  relative_coords = quad_coord_vector;
 	  relative_coords -= *mass_center_it;
 
 	  moments_matrix.outerProduct(relative_coords, relative_coords);
 	  Real trace = moments_matrix.trace();
 	  moments_matrix *= -1.;
 	  moments_matrix += Matrix<Real>::eye(spatial_dimension, trace);
 	}
       }
     }
   }
 
   /// integrate moments
   Array<Real> integrated_moments(global_nb_fragment,
 				 spatial_dimension * spatial_dimension);
 
   integrateFieldOnFragments(moments_coords, integrated_moments);
 
   /// compute and store principal moments
   inertia_moments.resize(global_nb_fragment);
   principal_directions.resize(global_nb_fragment);
 
   Array<Real>::matrix_iterator integrated_moments_it
     = integrated_moments.begin(spatial_dimension, spatial_dimension);
   Array<Real>::vector_iterator inertia_moments_it
     = inertia_moments.begin(spatial_dimension);
   Array<Real>::matrix_iterator principal_directions_it
     = principal_directions.begin(spatial_dimension, spatial_dimension);
 
   for (UInt frag = 0; frag < global_nb_fragment; ++frag, ++integrated_moments_it,
 	 ++inertia_moments_it, ++principal_directions_it) {
     integrated_moments_it->eig(*inertia_moments_it, *principal_directions_it);
   }
 
   if (dump_data)
     createDumpDataArray(inertia_moments, "moments of inertia");
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void FragmentManager::computeAllData() {
   AKANTU_DEBUG_IN();
 
   buildFragments();
   computeVelocity();
   computeInertiaMoments();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void FragmentManager::storeMassDensityPerQuadraturePoint() {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model.getSpatialDimension();
 
   Mesh::type_iterator it = mesh.firstType(spatial_dimension);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension);
 
   for (; it != end; ++it) {
     ElementType type = *it;
 
     Array<Real> & mass_density_array = mass_density(type);
 
     UInt nb_element = mesh.getNbElement(type);
     UInt nb_quad_per_element = model.getFEEngine().getNbQuadraturePoints(type);
     mass_density_array.resize(nb_element * nb_quad_per_element);
 
-    Array<UInt> & el_index_by_mat = model.getElementIndexByMaterial(type);
+    const Array<UInt> & mat_indexes = model.getMaterialByElement(type);
 
     Real * mass_density_it = mass_density_array.storage();
 
     /// store mass_density for each element and quadrature point
     for (UInt el = 0; el < nb_element; ++el) {
-      Material & mat = model.getMaterial(el_index_by_mat(el, 0));
+      Material & mat = model.getMaterial(mat_indexes(el));
 
       for (UInt q = 0; q < nb_quad_per_element; ++q, ++mass_density_it)
 	*mass_density_it = mat.getRho();
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void FragmentManager::integrateFieldOnFragments(ElementTypeMapArray<Real> & field,
 						Array<Real> & output) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model.getSpatialDimension();
   UInt nb_component = output.getNbComponent();
 
   /// integration part
   output.resize(global_nb_fragment);
   output.clear();
 
   UInt * fragment_index_it = fragment_index.storage();
   Array<Real>::vector_iterator output_begin = output.begin(nb_component);
 
   /// loop over fragments
   for(const_element_group_iterator it(element_group_begin());
       it != element_group_end(); ++it, ++fragment_index_it) {
 
     const ElementTypeMapArray<UInt> & el_list = it->second->getElements();
 
     ElementTypeMapArray<UInt>::type_iterator type_it = el_list.firstType(spatial_dimension,
 									 _not_ghost,
 									 _ek_regular);
     ElementTypeMapArray<UInt>::type_iterator type_end = el_list.lastType(spatial_dimension,
 									 _not_ghost,
 									 _ek_regular);
 
     /// loop over elements of the fragment
     for (; type_it != type_end; ++type_it) {
       ElementType type = *type_it;
       UInt nb_quad_per_element = model.getFEEngine().getNbQuadraturePoints(type);
 
       const Array<Real> & density_array = mass_density(type);
       Array<Real> & field_array = field(type);
       const Array<UInt> & elements = el_list(type);
       UInt nb_element = elements.getSize();
 
       /// generate array to be integrated by filtering fragment's elements
       Array<Real> integration_array(elements.getSize() * nb_quad_per_element,
 				    nb_component);
 
       Array<Real>::matrix_iterator int_array_it
 	= integration_array.begin_reinterpret(nb_quad_per_element,
 					      nb_component, nb_element);
       Array<Real>::matrix_iterator int_array_end
 	= integration_array.end_reinterpret(nb_quad_per_element,
 					    nb_component, nb_element);
       Array<Real>::matrix_iterator field_array_begin
 	= field_array.begin_reinterpret(nb_quad_per_element,
 					nb_component,
 					field_array.getSize() / nb_quad_per_element);
       Array<Real>::const_vector_iterator density_array_begin
 	= density_array.begin_reinterpret(nb_quad_per_element,
 					  density_array.getSize() / nb_quad_per_element);
 
       for (UInt el = 0; int_array_it != int_array_end; ++int_array_it, ++el) {
 	UInt global_el = elements(el);
 	*int_array_it = field_array_begin[global_el];
 
 	/// multiply field by density
 	const Vector<Real> & density_vector = density_array_begin[global_el];
 
 	for (UInt i = 0; i < nb_quad_per_element; ++i) {
 	  for (UInt j = 0; j < nb_component; ++j) {
 	    (*int_array_it)(i, j) *= density_vector(i);
 	  }
 	}
       }
 
 
       /// integrate the field over the fragment
       Array<Real> integrated_array(elements.getSize(), nb_component);
       model.getFEEngine().integrate(integration_array,
 				    integrated_array,
 				    nb_component,
 				    type,
 				    _not_ghost,
 				    elements);
 
       /// sum over all elements and store the result
       output_begin[*fragment_index_it]
 	+= std::accumulate(integrated_array.begin(nb_component),
 			   integrated_array.end(nb_component),
 			   Vector<Real>(nb_component));
     }
   }
 
   /// sum output over all processors
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   comm.allReduce(output.storage(), global_nb_fragment * nb_component, _so_sum);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void FragmentManager::computeNbElementsPerFragment() {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = model.getSpatialDimension();
   nb_elements_per_fragment.resize(global_nb_fragment);
   nb_elements_per_fragment.clear();
 
   UInt * fragment_index_it = fragment_index.storage();
 
   /// loop over fragments
   for(const_element_group_iterator it(element_group_begin());
       it != element_group_end(); ++it, ++fragment_index_it) {
 
     const ElementTypeMapArray<UInt> & el_list = it->second->getElements();
 
     ElementTypeMapArray<UInt>::type_iterator type_it = el_list.firstType(spatial_dimension,
 									 _not_ghost,
 									 _ek_regular);
     ElementTypeMapArray<UInt>::type_iterator type_end = el_list.lastType(spatial_dimension,
 									 _not_ghost,
 									 _ek_regular);
 
     /// loop over elements of the fragment
     for (; type_it != type_end; ++type_it) {
       ElementType type = *type_it;
       UInt nb_element = el_list(type).getSize();
 
       nb_elements_per_fragment(*fragment_index_it) += nb_element;
     }
   }
 
   /// sum values over all processors
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   comm.allReduce(nb_elements_per_fragment.storage(), global_nb_fragment, _so_sum);
 
   if (dump_data)
     createDumpDataArray(nb_elements_per_fragment, "elements per fragment");
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename T>
 void FragmentManager::createDumpDataArray(Array<T> & data,
 					  std::string name,
 					  bool fragment_index_output) {
   AKANTU_DEBUG_IN();
 
   if (data.getSize() == 0) return;
 
   typedef typename Array<T>::template iterator< Vector<T> > data_iterator;
   Mesh & mesh_not_const = const_cast<Mesh &>(mesh);
 
   UInt spatial_dimension = mesh.getSpatialDimension();
   UInt nb_component = data.getNbComponent();
   UInt * fragment_index_it = fragment_index.storage();
 
   data_iterator data_begin = data.begin(nb_component);
 
   /// loop over fragments
   for(const_element_group_iterator it(element_group_begin());
       it != element_group_end(); ++it, ++fragment_index_it) {
 
     const ElementGroup & fragment = *(it->second);
 
     /// loop over cluster types
     ElementGroup::type_iterator type_it = fragment.firstType(spatial_dimension);
     ElementGroup::type_iterator type_end = fragment.lastType(spatial_dimension);
 
     for(; type_it != type_end; ++type_it) {
       ElementType type = *type_it;
 
       /// init mesh data
       Array<T> * mesh_data
 	= mesh_not_const.getDataPointer<T>(name, type, _not_ghost, nb_component);
 
       data_iterator mesh_data_begin = mesh_data->begin(nb_component);
 
       ElementGroup::const_element_iterator el_it = fragment.element_begin(type);
       ElementGroup::const_element_iterator el_end = fragment.element_end(type);
 
       /// fill mesh data
       if (fragment_index_output) {
 	for (; el_it != el_end; ++el_it)
 	  mesh_data_begin[*el_it](0) = *fragment_index_it;
       } else {
 	for (; el_it != el_end; ++el_it)
 	  mesh_data_begin[*el_it] = data_begin[*fragment_index_it];
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/material.cc b/src/model/solid_mechanics/material.cc
index 69e0f11ad..3e4800bae 100644
--- a/src/model/solid_mechanics/material.cc
+++ b/src/model/solid_mechanics/material.cc
@@ -1,1559 +1,1569 @@
 /**
  * @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");
 
   /// allocate gradu stress for local elements
   eigenstrain.initialize(spatial_dimension * spatial_dimension);
   gradu.initialize(spatial_dimension * spatial_dimension);
   stress.initialize(spatial_dimension * spatial_dimension);
 
   model.registerEventHandler(*this);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Material::~Material() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 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();
 
   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);
+										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);
+								    ghost_type);
 
   gradu_vect.resize(nb_quadrature_points * nb_element);
 
   model->getFEEngine().gradientOnQuadraturePoints(model->getDisplacement(),
-                                             gradu_vect, dim, type, ghost_type,
-                                             elem_filter);
+					     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);
+			   *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);
+				 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->getFEEngine().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,	\
+					    interp_points_coord,	\
 					    nb_interpolation_points_per_elem, \
-                                            ghost_type)			\
+					    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 Array<Real> & interpolation_points_coordinates,
 					       const UInt nb_interpolation_points_per_elem,
-                                               const GhostType ghost_type) {
+					       const GhostType ghost_type) {
   AKANTU_DEBUG_IN();
   UInt size_inverse_coords =
     getSizeElementalFieldInterpolationCoodinates<type>(ghost_type);
 
   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,
-                                            size_inverse_coords*size_inverse_coords,
-                                            type, ghost_type);
+					    size_inverse_coords*size_inverse_coords,
+					    type, ghost_type);
 
   if(!interpolation_points_matrices.exists(type, ghost_type))
     interpolation_points_matrices.alloc(nb_element,
-                                        nb_interpolation_points_per_elem * size_inverse_coords,
-                                        type, ghost_type);
+					nb_interpolation_points_per_elem * size_inverse_coords,
+					type, ghost_type);
 
   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(size_inverse_coords, size_inverse_coords);
 
   Array<Real>::const_matrix_iterator quad_coords_it =
     quad_coordinates.begin_reinterpret(spatial_dimension,
-                                       nb_quad_per_element,
-                                       nb_element);
+				       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);
+						       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(size_inverse_coords, size_inverse_coords);
 
   Array<Real>::matrix_iterator inv_points_mat_it =
     interp_points_mat.begin(nb_interpolation_points_per_elem, size_inverse_coords);
 
   /// 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);
+						     inv_points_coord_matrix);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void Material::interpolateStress(ElementTypeMapArray<Real> & result,
 				 const GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   const Mesh & mesh = model->getFEEngine().getMesh();
 
   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;
 
     Array<Real> & res = result(type, ghost_type);
 
 #define INTERPOLATE_ELEMENTAL_FIELD(type)			\
     interpolateElementalField<type>(stress(type, ghost_type),	\
 				    res,			\
 				    ghost_type)
 
     AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(INTERPOLATE_ELEMENTAL_FIELD);
 #undef INTERPOLATE_ELEMENTAL_FIELD
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <ElementType type>
 void Material::interpolateElementalField(const Array<Real> & field,
 					 Array<Real> & result,
 					 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);
   UInt size_inverse_coords = getSizeElementalFieldInterpolationCoodinates<type>(ghost_type);
 
   Matrix<Real> coefficients(nb_quad_per_element, field.getNbComponent());
 
   const Array<Real> & interp_inv_coord = interpolation_inverse_coordinates(type,
-                                                                           ghost_type);
+									   ghost_type);
   const Array<Real> & interp_points_coord = interpolation_points_matrices(type,
-                                                                          ghost_type);
+									  ghost_type);
 
   UInt nb_interpolation_points_per_elem = interp_points_coord.getNbComponent() / size_inverse_coords;
 
   Array<Real>::const_matrix_iterator field_it
     = field.begin_reinterpret(field.getNbComponent(),
-                              nb_quad_per_element,
-                              nb_element);
+			      nb_quad_per_element,
+			      nb_element);
 
   Array<Real>::const_matrix_iterator interpolation_points_coordinates_it =
     interp_points_coord.begin(nb_interpolation_points_per_elem, size_inverse_coords);
 
   Array<Real>::matrix_iterator result_begin
     = result.begin_reinterpret(field.getNbComponent(),
-                               nb_interpolation_points_per_elem,
-                               result.getSize() / nb_interpolation_points_per_elem);
+			       nb_interpolation_points_per_elem,
+			       result.getSize() / nb_interpolation_points_per_elem);
 
   Array<Real>::const_matrix_iterator inv_quad_coord_it =
     interp_inv_coord.begin(size_inverse_coords, size_inverse_coords);
 
   /// 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_begin[elem_fil(el)].mul<true, true>(coefficients, coord);
   }
 
 
   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) << ")");
+		     << ") 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) << ")");
+		     << ") 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> & element_index_material = model->getElementIndexByMaterial(element.type, element.ghost_type);
+    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);
-    element_index_material(element.element, 0) = mat_id;
-    element_index_material(element.element, 1) = index;
+    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> & element_index_material = model->getElementIndexByMaterial(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;
-	  element_index_material(element.element, 1) = 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);
+    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> & element_index_material = model->getElementIndexByMaterial(type, gt);
-	element_index_material.resize(model->getFEEngine().getMesh().getNbElement(type, gt)); // all materials will resize of the same size...
+	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;
-	    element_index_material(new_el, 0) = my_num;
-	    element_index_material(new_el, 1) = 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,  
+			       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);
+  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;
+  for (; tit != end; ++tit) {
 
-      try {
-	__attribute__((unused)) const Array<Real> & src_vect 
-	  = this->getArray(field_id,type,ghost_type);
+    ElementType type = *tit;
 
-      } catch(debug::Exception & e) { 
-	continue; 
-      }
+    try {
+      __attribute__((unused)) const Array<Real> & src_vect
+	= this->getArray(field_id,type,ghost_type);
 
-      const Array<Real> & src_vect = this->getArray(field_id,type,ghost_type);
-      const Array<UInt> & filter   = this->element_filter(type,ghost_type);
+    } catch(debug::Exception & e) {
+      continue;
+    }
 
-      // 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();
+    const Array<Real> & src_vect = this->getArray(field_id,type,ghost_type);
+    const Array<UInt> & filter   = this->element_filter(type,ghost_type);
 
-      if (!internal_flat.exists(type,ghost_type)){
-	internal_flat.alloc(nb_element*nb_quad_per_elem,nb_data_per_quad,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 (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();
+    if (!internal_flat.exists(type,ghost_type)) {
+      internal_flat.alloc(nb_element*nb_quad_per_elem,nb_data_per_quad,type,ghost_type);
+    }
 
-      Array<Real> & dst_vect = internal_flat(type,ghost_type);
-      dst_vect.resize(nb_element*nb_quad_per_elem);
+    if (nb_element_src == 0) continue;
+    nb_quad_per_elem = (src_vect.getSize()/nb_element_src);
 
-      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);
+    // number of data per element
+    UInt nb_data = nb_quad_per_elem * src_vect.getNbComponent();
 
-      Array<Real>::vector_iterator it_dst = 
-	dst_vect.begin_reinterpret(nb_data,nb_element);
+    Array<Real> & dst_vect = internal_flat(type,ghost_type);
+    dst_vect.resize(nb_element*nb_quad_per_elem);
 
-      for (; it != end ; ++it,++it_src) {
-	it_dst[*it] = *it_src;
-      }
+    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 a1bdba331..46186b53a 100644
--- a/src/model/solid_mechanics/material.hh
+++ b/src/model/solid_mechanics/material.hh
@@ -1,575 +1,588 @@
 /**
  * @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:
 
   Material(SolidMechanicsModel & model, const ID & id = "");
   virtual ~Material();
 
   /* ------------------------------------------------------------------------ */
   /* 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);
 
   /**
    * 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
   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
   template <ElementType type>
   void interpolateElementalField(const Array<Real> & field,
                                  Array<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);
 
   /// get the size of the coordiante matrix used in the interpolation
   template <ElementType type>
   inline UInt getSizeElementalFieldInterpolationCoodinates(GhostType ghost_type = _not_ghost);
 
 public:
   /* ------------------------------------------------------------------------ */
   /* Conversion functions                                                     */
   /* ------------------------------------------------------------------------ */
   template<UInt dim>
   inline void gradUToF   (const Matrix<Real> & grad_u, Matrix<Real> & F) const;
   inline void rightCauchy(const Matrix<Real> & F,      Matrix<Real> & C) const;
   inline void leftCauchy (const Matrix<Real> & F,      Matrix<Real> & B) const;
 
   template<UInt dim>
   inline void gradUToEpsilon(const Matrix<Real> & grad_u, Matrix<Real> & epsilon) const;
   template<UInt dim>
   inline void gradUToGreenStrain(const Matrix<Real> & grad_u,
                                  Matrix<Real> & epsilon) const;
+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);
 
   /// 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;
 
   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;
 
   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 918455b6e..f7e3fb1e4 100644
--- a/src/model/solid_mechanics/material_inline_impl.cc
+++ b/src/model/solid_mechanics/material_inline_impl.cc
@@ -1,432 +1,482 @@
 /**
  * @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) const {
   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) const {
   C.mul<true, false>(F, F);
 }
 
 /* -------------------------------------------------------------------------- */
 inline void Material::leftCauchy(const Matrix<Real> & F,
 				 Matrix<Real> & B) const {
   B.mul<false, true>(F, F);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim>
 inline void Material::gradUToEpsilon(const Matrix<Real> & grad_u,
 				     Matrix<Real> & epsilon) const {
   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) const {
   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));
 }
 
 /* ---------------------------------------------------------------------------*/
 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;
       }
     }
 
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<ElementType type>
 inline UInt Material::getSizeElementalFieldInterpolationCoodinates(GhostType ghost_type) {
   return model->getFEEngine().getNbQuadraturePoints(type, ghost_type);
 }
 
 /* -------------------------------------------------------------------------- */
 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, 
+  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 {
 
   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().getNbQuadraturePoints(*it);
 #if defined(AKANTU_COHESIVE_ELEMENT)
     else if (element_kind == _ek_cohesive)
       nb_quadrature_points = model->getFEEngine("CohesiveFEEngine").getNbQuadraturePoints(*it);
 #endif
     res(*it) = internal.getNbComponent() * nb_quadrature_points;
   }
     return res;
 }
diff --git a/src/model/solid_mechanics/material_selector.hh b/src/model/solid_mechanics/material_selector.hh
index a71d3a514..29f672bd4 100644
--- a/src/model/solid_mechanics/material_selector.hh
+++ b/src/model/solid_mechanics/material_selector.hh
@@ -1,100 +1,100 @@
 /**
  * @file   material_selector.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Nov 13 2013
  * @date last modification: Thu Jun 05 2014
  *
  * @brief  class describing how to choose a material for a given element
  *
  * @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 "mesh.hh"
 
 
 
 #ifndef __AKANTU_MATERIAL_SELECTOR_HH__
 #define __AKANTU_MATERIAL_SELECTOR_HH__
 
 __BEGIN_AKANTU__
 
 class SolidMechanicsModel;
 
 /* -------------------------------------------------------------------------- */
 class MaterialSelector {
 public:
   MaterialSelector() : fallback_value(0) {}
   virtual ~MaterialSelector() {}
   virtual UInt operator()(const Element & element) {
     return fallback_value;
   }
 
   void setFallback(UInt f) { fallback_value = f; }
 protected:
   UInt fallback_value;
 };
 
 /* -------------------------------------------------------------------------- */
 class DefaultMaterialSelector : public MaterialSelector {
 public:
-  DefaultMaterialSelector(const ElementTypeMapArray<UInt> & element_index_by_material) :
-    element_index_by_material(element_index_by_material) { }
+  DefaultMaterialSelector(const ElementTypeMapArray<UInt> & material_index) :
+    material_index(material_index) { }
 
   UInt operator()(const Element & element) {
     try {
       DebugLevel dbl = debug::getDebugLevel();
       debug::setDebugLevel(dblError);
 
-      const Array<UInt> & el_by_mat = element_index_by_material(element.type, element.ghost_type);
+      const Array<UInt> & mat_indexes = material_index(element.type, element.ghost_type);
       UInt mat = this->fallback_value;
-      if(element.element < el_by_mat.getSize())
-	 mat = el_by_mat(element.element, 0);
+      if(element.element < mat_indexes.getSize())
+	 mat = mat_indexes(element.element);
 
       debug::setDebugLevel(dbl);
       return mat;
     } catch (...) {
       return MaterialSelector::operator()(element);
     }
   }
 
 private:
-  const ElementTypeMapArray<UInt> & element_index_by_material;
+  const ElementTypeMapArray<UInt> & material_index;
 };
 
 /* -------------------------------------------------------------------------- */
 template<typename T>
 class MeshDataMaterialSelector : public MaterialSelector {
 public:
   MeshDataMaterialSelector(const std::string & name, const SolidMechanicsModel & model) : mesh_data(name), model(model) { }
   UInt operator() (const Element & element) {
     return 0;
   }
 private:
   std::string mesh_data;
   const SolidMechanicsModel & model;
 };
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MATERIAL_SELECTOR_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc b/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc
index 20e395e06..2168ff6b9 100644
--- a/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc
+++ b/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc
@@ -1,618 +1,618 @@
 /**
  * @file   material_cohesive.cc
  *
  * @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Feb 22 2012
  * @date last modification: Tue Jul 29 2014
  *
  * @brief  Specialization of the material class 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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_cohesive.hh"
 #include "solid_mechanics_model_cohesive.hh"
 #include "sparse_matrix.hh"
 #include "dof_synchronizer.hh"
 #include "aka_random_generator.hh"
 #include "shape_cohesive.hh"
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 MaterialCohesive::MaterialCohesive(SolidMechanicsModel & model, const ID & id) :
   Material(model, id),
   facet_filter("facet_filter", id, this->getMemoryID()),
   fem_cohesive(&(model.getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine"))),
   reversible_energy("reversible_energy", *this),
   total_energy("total_energy", *this),
   opening("opening", *this),
   opening_old("opening (old)", *this),
   tractions("tractions", *this),
   tractions_old("tractions (old)", *this),
   contact_tractions("contact_tractions", *this),
   contact_opening("contact_opening", *this),
   delta_max("delta max", *this),
   use_previous_delta_max(false),
   damage("damage", *this),
   sigma_c("sigma_c", *this) {
 
   AKANTU_DEBUG_IN();
 
   this->model = dynamic_cast<SolidMechanicsModelCohesive*>(&model);
 
   this->registerParam("sigma_c", sigma_c,
 		      _pat_parsable | _pat_readable, "Critical stress");
   this->registerParam("delta_c", delta_c, 0.,
 		      _pat_parsable | _pat_readable, "Critical displacement");
 
   this->model->getMesh().initElementTypeMapArray(this->element_filter,
-						1,
-						spatial_dimension,
-						false,
-						_ek_cohesive);
+						 1,
+						 spatial_dimension,
+						 false,
+						 _ek_cohesive);
 
   if (this->model->getIsExtrinsic())
     this->model->getMeshFacets().initElementTypeMapArray(facet_filter, 1,
 							 spatial_dimension - 1);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 MaterialCohesive::~MaterialCohesive() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::initMaterial() {
   AKANTU_DEBUG_IN();
   Material::initMaterial();
 
   this->reversible_energy.initialize(1                );
   this->total_energy     .initialize(1                );
   this->tractions_old    .initialize(spatial_dimension);
   this->tractions        .initialize(spatial_dimension);
   this->opening_old      .initialize(spatial_dimension);
   this->contact_tractions.initialize(spatial_dimension);
   this->contact_opening  .initialize(spatial_dimension);
   this->opening          .initialize(spatial_dimension);
   this->delta_max        .initialize(1                );
   this->damage           .initialize(1                );
 
   if (model->getIsExtrinsic()) this->sigma_c.initialize(1);
   if (use_previous_delta_max) delta_max.initializeHistory();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::assembleResidual(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
 #if defined(AKANTU_DEBUG_TOOLS)
   debug::element_manager.printData(debug::_dm_material_cohesive,
 				   "Cohesive Tractions",
 				   tractions);
 #endif
 
   Array<Real> & residual = const_cast<Array<Real> &>(model->getResidual());
 
   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;
 
     const Array<Real> & shapes = fem_cohesive->getShapes(*it, ghost_type);
     Array<Real> & traction = tractions(*it, ghost_type);
     Array<Real> & contact_traction = contact_tractions(*it, ghost_type);
 
     UInt size_of_shapes       = shapes.getNbComponent();
     UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it);
     UInt nb_quadrature_points = fem_cohesive->getNbQuadraturePoints(*it, ghost_type);
 
 
     /// compute @f$t_i N_a@f$
 
     Array<Real> * traction_cpy = new Array<Real>(nb_element * nb_quadrature_points,
 						 spatial_dimension * size_of_shapes);
 
     Array<Real>::iterator<Matrix<Real> > traction_it
       = traction.begin(spatial_dimension, 1);
     Array<Real>::iterator<Matrix<Real> > contact_traction_it
       = contact_traction.begin(spatial_dimension, 1);
     Array<Real>::const_iterator<Matrix<Real> > shapes_filtered_begin
       = shapes.begin(1, size_of_shapes);
     Array<Real>::iterator<Matrix<Real> > traction_cpy_it
       = traction_cpy->begin(spatial_dimension, size_of_shapes);
 
     Matrix<Real> traction_tmp(spatial_dimension, 1);
 
 
     for (UInt el = 0; el < nb_element; ++el) {
 
       UInt current_quad = elem_filter(el) * nb_quadrature_points;
 
       for (UInt q = 0; q < nb_quadrature_points; ++q, ++traction_it,
 	     ++contact_traction_it, ++current_quad, ++traction_cpy_it) {
 
 	const Matrix<Real> & shapes_filtered = shapes_filtered_begin[current_quad];
 
 	traction_tmp.copy(*traction_it);
 	traction_tmp += *contact_traction_it;
 
 	traction_cpy_it->mul<false, false>(traction_tmp, shapes_filtered);
       }
     }
 
     /**
      * compute @f$\int t \cdot N\, dS@f$ by  @f$ \sum_q \mathbf{N}^t
      * \mathbf{t}_q \overline w_q J_q@f$
      */
     Array<Real> * int_t_N = new Array<Real>(nb_element,
 					    spatial_dimension*size_of_shapes,
 					    "int_t_N");
 
     fem_cohesive->integrate(*traction_cpy, *int_t_N,
 			    spatial_dimension * size_of_shapes,
 			    *it, ghost_type,
 			    elem_filter);
 
     delete traction_cpy;
 
     int_t_N->extendComponentsInterlaced(2, int_t_N->getNbComponent());
 
     Real * int_t_N_val = int_t_N->storage();
     for (UInt el = 0; el < nb_element; ++el) {
       for (UInt n = 0; n < size_of_shapes * spatial_dimension; ++n)
 	int_t_N_val[n] *= -1.;
       int_t_N_val += nb_nodes_per_element * spatial_dimension;
     }
 
     /// assemble
     model->getFEEngineBoundary().assembleArray(*int_t_N, residual,
 					  model->getDOFSynchronizer().getLocalDOFEquationNumbers(),
 					  residual.getNbComponent(),
 					  *it, ghost_type, elem_filter, 1);
 
     delete int_t_N;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::assembleStiffnessMatrix(GhostType ghost_type) {
 
   AKANTU_DEBUG_IN();
 
   SparseMatrix & K = const_cast<SparseMatrix &>(model->getStiffnessMatrix());
 
   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) {
     UInt nb_quadrature_points = fem_cohesive->getNbQuadraturePoints(*it, ghost_type);
     UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it);
 
     const Array<Real> & shapes = fem_cohesive->getShapes(*it, ghost_type);
     Array<UInt> & elem_filter = element_filter(*it, ghost_type);
 
     UInt nb_element = elem_filter.getSize();
 
     if(!nb_element) continue;
 
     UInt size_of_shapes       = shapes.getNbComponent();
 
     Array<Real> * shapes_filtered =
       new Array<Real>(nb_element*nb_quadrature_points,
 		      size_of_shapes, "filtered shapes");
 
     Real * shapes_val       = shapes.storage();
     Real * shapes_filtered_val = shapes_filtered->storage();
     UInt * elem_filter_val  = elem_filter.storage();
 
     for (UInt el = 0; el < nb_element; ++el) {
       shapes_val = shapes.storage() + elem_filter_val[el] *
     	size_of_shapes * nb_quadrature_points;
       memcpy(shapes_filtered_val, shapes_val,
     	     size_of_shapes * nb_quadrature_points * sizeof(Real));
       shapes_filtered_val += size_of_shapes * nb_quadrature_points;
     }
 
     /**
      * compute A matrix @f$ \mathbf{A} = \left[\begin{array}{c c c c c c c c c c c c}
      * 1 & 0 & 0 & 0 & 0 & 0 & -1 &  0 &  0 &  0 &  0 &  0 \\
      * 0 & 1 & 0 & 0 & 0 & 0 &  0 & -1 &  0 &  0 &  0 &  0 \\
      * 0 & 0 & 1 & 0 & 0 & 0 &  0 &  0 & -1 &  0 &  0 &  0 \\
      * 0 & 0 & 0 & 1 & 0 & 0 &  0 &  0 &  0 & -1 &  0 &  0 \\
      * 0 & 0 & 0 & 0 & 1 & 0 &  0 &  0 &  0 &  0 & -1 &  0 \\
      * 0 & 0 & 0 & 0 & 0 & 1 &  0 &  0 &  0 &  0 &  0 & -1
      * \end{array} \right]@f$
      **/
 
     // UInt size_of_A =  spatial_dimension*size_of_shapes*spatial_dimension*nb_nodes_per_element;
     // Real * A = new Real[size_of_A];
     // memset(A, 0, size_of_A*sizeof(Real));
     Matrix<Real> A(spatial_dimension*size_of_shapes,
 		   spatial_dimension*nb_nodes_per_element);
 
     for ( UInt i = 0; i < spatial_dimension*size_of_shapes; ++i) {
       A(i, i) = 1;
       A(i, i + spatial_dimension*size_of_shapes) = -1;
     }
 
     /// compute traction
     computeTraction(ghost_type);
 
     /// get the tangent matrix @f$\frac{\partial{(t/\delta)}}{\partial{\delta}} @f$
     Array<Real> * tangent_stiffness_matrix =
       new Array<Real>(nb_element * nb_quadrature_points,
 		      spatial_dimension * spatial_dimension,
 		      "tangent_stiffness_matrix");
 
     //    Array<Real> * normal = new Array<Real>(nb_element * nb_quadrature_points, spatial_dimension, "normal");
     Array<Real> normal(nb_quadrature_points, spatial_dimension, "normal");
 
 
     computeNormal(model->getCurrentPosition(), normal, *it, ghost_type);
 
     tangent_stiffness_matrix->clear();
 
     computeTangentTraction(*it, *tangent_stiffness_matrix, normal, ghost_type);
 
     // delete normal;
 
     UInt size_at_nt_d_n_a = spatial_dimension*nb_nodes_per_element*spatial_dimension*nb_nodes_per_element;
     Array<Real> * at_nt_d_n_a = new Array<Real> (nb_element*nb_quadrature_points,
 						   size_at_nt_d_n_a,
 						   "A^t*N^t*D*N*A");
 
     Array<Real>::iterator<Vector<Real> > shapes_filt_it =
       shapes_filtered->begin(size_of_shapes);
 
     Array<Real>::matrix_iterator D_it =
       tangent_stiffness_matrix->begin(spatial_dimension, spatial_dimension);
 
     Array<Real>::matrix_iterator At_Nt_D_N_A_it =
       at_nt_d_n_a->begin(spatial_dimension * nb_nodes_per_element,
 			 spatial_dimension * nb_nodes_per_element);
 
     Array<Real>::matrix_iterator At_Nt_D_N_A_end =
       at_nt_d_n_a->end(spatial_dimension * nb_nodes_per_element,
 		       spatial_dimension * nb_nodes_per_element);
 
     Matrix<Real> N    (spatial_dimension, spatial_dimension * size_of_shapes);
     Matrix<Real> N_A  (spatial_dimension, spatial_dimension * nb_nodes_per_element);
     Matrix<Real> D_N_A(spatial_dimension, spatial_dimension * nb_nodes_per_element);
 
     for(; At_Nt_D_N_A_it != At_Nt_D_N_A_end; ++At_Nt_D_N_A_it, ++D_it, ++shapes_filt_it) {
       N.clear();
       /**
        * store  the   shapes  in  voigt   notations  matrix  @f$\mathbf{N}  =
        * \begin{array}{cccccc} N_0(\xi) & 0 & N_1(\xi)  &0 & N_2(\xi) & 0 \\
        * 0 & * N_0(\xi)& 0 &N_1(\xi)& 0 & N_2(\xi) \end{array} @f$
        **/
       for (UInt i = 0; i < spatial_dimension ; ++i)
 	for (UInt n = 0; n < size_of_shapes; ++n)
 	  N(i, i + spatial_dimension * n) = (*shapes_filt_it)(n);
 
       /**
        * compute stiffness matrix  @f$   \mathbf{K}    =    \delta    \mathbf{U}^T
        * \int_{\Gamma_c}    {\mathbf{P}^t \frac{\partial{\mathbf{t}}} {\partial{\delta}}
        * \mathbf{P} d\Gamma \Delta \mathbf{U}}  @f$
        **/
       N_A.mul<false, false>(N, A);
       D_N_A.mul<false, false>(*D_it, N_A);
       (*At_Nt_D_N_A_it).mul<true, false>(D_N_A, N_A);
     }
 
     delete tangent_stiffness_matrix;
     delete shapes_filtered;
 
     Array<Real> * K_e = new Array<Real>(nb_element, size_at_nt_d_n_a,
 					  "K_e");
 
     fem_cohesive->integrate(*at_nt_d_n_a, *K_e,
 			    size_at_nt_d_n_a,
 			    *it, ghost_type,
 			    elem_filter);
 
     delete at_nt_d_n_a;
 
     model->getFEEngine().assembleMatrix(*K_e, K, spatial_dimension,
 				   *it, ghost_type, elem_filter);
     delete K_e;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- *
  * Compute traction from displacements
  *
  * @param[in] ghost_type compute the residual for _ghost or _not_ghost element
  */
 void MaterialCohesive::computeTraction(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
 #if defined(AKANTU_DEBUG_TOOLS)
   debug::element_manager.printData(debug::_dm_material_cohesive,
 				   "Cohesive Openings",
 				   opening);
 #endif
 
   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;
     UInt nb_quadrature_points =
       nb_element*fem_cohesive->getNbQuadraturePoints(*it, ghost_type);
 
     Array<Real> normal(nb_quadrature_points, spatial_dimension, "normal");
 
     /// compute normals @f$\mathbf{n}@f$
     computeNormal(model->getCurrentPosition(), normal, *it, ghost_type);
 
     /// compute openings @f$\mathbf{\delta}@f$
     computeOpening(model->getDisplacement(), opening(*it, ghost_type), *it, ghost_type);
 
     /// compute traction @f$\mathbf{t}@f$
     computeTraction(normal, *it, ghost_type);
 
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::computeNormal(const Array<Real> & position,
 				     Array<Real> & normal,
 				     ElementType type,
 				     GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   if (type == _cohesive_1d_2)
     fem_cohesive->computeNormalsOnControlPoints(position,
 						normal,
 						type, ghost_type);
   else {
 #define COMPUTE_NORMAL(type)						\
     fem_cohesive->getShapeFunctions().					\
       computeNormalsOnControlPoints<type, CohesiveReduceFunctionMean>(position, \
 								      normal, \
 								      ghost_type, \
 								      element_filter(type, ghost_type));
 
     AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(COMPUTE_NORMAL);
 #undef COMPUTE_NORMAL
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::computeOpening(const Array<Real> & displacement,
 				      Array<Real> & opening,
 				      ElementType type,
 				      GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
 #define COMPUTE_OPENING(type)						\
   fem_cohesive->getShapeFunctions().					\
     interpolateOnControlPoints<type, CohesiveReduceFunctionOpening>(displacement, \
 								    opening, \
 								    spatial_dimension, \
 								    ghost_type, \
 								    element_filter(type, ghost_type));
 
   AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(COMPUTE_OPENING);
 #undef COMPUTE_OPENING
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::computeEnergies() {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh = fem_cohesive->getMesh();
   Mesh::type_iterator it =
     mesh.firstType(spatial_dimension, _not_ghost, _ek_cohesive);
   Mesh::type_iterator last_type =
     mesh.lastType(spatial_dimension, _not_ghost, _ek_cohesive);
 
   Real * memory_space = new Real[2*spatial_dimension];
   Vector<Real> b(memory_space, spatial_dimension);
   Vector<Real> h(memory_space + spatial_dimension, spatial_dimension);
 
   for(; it != last_type; ++it) {
     Array<Real>::iterator<Real> erev =
       reversible_energy(*it, _not_ghost).begin();
     Array<Real>::iterator<Real> etot =
       total_energy(*it, _not_ghost).begin();
     Array<Real>::vector_iterator traction_it =
       tractions(*it, _not_ghost).begin(spatial_dimension);
     Array<Real>::vector_iterator traction_old_it =
       tractions_old(*it, _not_ghost).begin(spatial_dimension);
     Array<Real>::vector_iterator opening_it =
       opening(*it, _not_ghost).begin(spatial_dimension);
     Array<Real>::vector_iterator opening_old_it =
       opening_old(*it, _not_ghost).begin(spatial_dimension);
 
     Array<Real>::vector_iterator traction_end =
       tractions(*it, _not_ghost).end(spatial_dimension);
 
     /// loop on each quadrature point
     for (; traction_it != traction_end;
 	 ++traction_it, ++traction_old_it,
 	   ++opening_it, ++opening_old_it,
 	   ++erev, ++etot) {
 
       /// trapezoidal integration
       b  = *opening_it;
       b -= *opening_old_it;
 
       h  = *traction_old_it;
       h += *traction_it;
 
       *etot += .5 * b.dot(h);
       *erev  = .5 * traction_it->dot(*opening_it);
     }
   }
 
   delete [] memory_space;
 
   /// update old values
   it = mesh.firstType(spatial_dimension, _not_ghost, _ek_cohesive);
   GhostType ghost_type = _not_ghost;
   for(; it != last_type; ++it) {
     tractions_old(*it, ghost_type).copy(tractions(*it, ghost_type));
     opening_old(*it, ghost_type).copy(opening(*it, ghost_type));
   }
 
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getReversibleEnergy() {
   AKANTU_DEBUG_IN();
   Real erev = 0.;
 
   /// integrate reversible energy for each type of elements
   Mesh & mesh = fem_cohesive->getMesh();
   Mesh::type_iterator it = mesh.firstType(spatial_dimension,
 					  _not_ghost, _ek_cohesive);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension,
 						_not_ghost, _ek_cohesive);
 
   for(; it != last_type; ++it) {
     erev += fem_cohesive->integrate(reversible_energy(*it, _not_ghost), *it,
 				    _not_ghost, element_filter(*it, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return erev;
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getDissipatedEnergy() {
   AKANTU_DEBUG_IN();
   Real edis = 0.;
 
   /// integrate dissipated energy for each type of elements
   Mesh & mesh = fem_cohesive->getMesh();
   Mesh::type_iterator it = mesh.firstType(spatial_dimension,
 					  _not_ghost, _ek_cohesive);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension,
 						_not_ghost, _ek_cohesive);
 
   for(; it != last_type; ++it) {
     Array<Real> dissipated_energy(total_energy(*it, _not_ghost));
     dissipated_energy -= reversible_energy(*it, _not_ghost);
     edis += fem_cohesive->integrate(dissipated_energy, *it,
 				    _not_ghost, element_filter(*it, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return edis;
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getContactEnergy() {
   AKANTU_DEBUG_IN();
   Real econ = 0.;
 
   /// integrate contact energy for each type of elements
   Mesh & mesh = fem_cohesive->getMesh();
   Mesh::type_iterator it = mesh.firstType(spatial_dimension,
 					  _not_ghost, _ek_cohesive);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension,
 						_not_ghost, _ek_cohesive);
 
   for(; it != last_type; ++it) {
     Array<UInt> & el_filter = element_filter(*it, _not_ghost);
     UInt nb_quad_per_el = fem_cohesive->getNbQuadraturePoints(*it, _not_ghost);
     UInt nb_quad_points = el_filter.getSize() * nb_quad_per_el;
     Array<Real> contact_energy(nb_quad_points);
 
     Array<Real>::vector_iterator contact_traction_it =
       contact_tractions(*it, _not_ghost).begin(spatial_dimension);
     Array<Real>::vector_iterator contact_opening_it =
       contact_opening(*it, _not_ghost).begin(spatial_dimension);
 
     /// loop on each quadrature point
     for (UInt el = 0; el < nb_quad_points;
 	 ++contact_traction_it, ++contact_opening_it, ++el) {
 
       contact_energy(el) = .5 * contact_traction_it->dot(*contact_opening_it);
     }
 
     econ += fem_cohesive->integrate(contact_energy, *it,
 				    _not_ghost, el_filter);
   }
 
   AKANTU_DEBUG_OUT();
   return econ;
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getEnergy(std::string type) {
   AKANTU_DEBUG_IN();
 
   if (type == "reversible") return getReversibleEnergy();
   else if (type == "dissipated") return getDissipatedEnergy();
   else if (type == "cohesive contact") return getContactEnergy();
 
   AKANTU_DEBUG_OUT();
   return 0.;
 }
 
 /* -------------------------------------------------------------------------- */
 
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/materials/material_non_local.hh b/src/model/solid_mechanics/materials/material_non_local.hh
index 0b3007bd9..905d6f3ff 100644
--- a/src/model/solid_mechanics/materials/material_non_local.hh
+++ b/src/model/solid_mechanics/materials/material_non_local.hh
@@ -1,180 +1,185 @@
 /**
  * @file   material_non_local.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Aug 31 2011
  * @date last modification: Thu Jun 05 2014
  *
  * @brief  Material class that handle the non locality of a law for example damage.
  *
  * @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"
 #include "aka_grid_dynamic.hh"
 #include "fe_engine.hh"
 
 #include "weight_function.hh"
 
 namespace akantu {
   class GridSynchronizer;
 }
 
 /* -------------------------------------------------------------------------- */
 #ifndef __AKANTU_MATERIAL_NON_LOCAL_HH__
 #define __AKANTU_MATERIAL_NON_LOCAL_HH__
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt dim, template <UInt> class WeightFunction = BaseWeightFunction>
 class MaterialNonLocal : public virtual Material {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
 
   MaterialNonLocal(SolidMechanicsModel & model, const ID & id = "");
   virtual ~MaterialNonLocal();
 
-  template<typename T>
-  class PairList : public ElementTypeMap< ElementTypeMapArray<T> > {};
+  typedef std::vector< std::pair<QuadraturePoint, QuadraturePoint> > PairList;
+
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialize the material computed parameter
   virtual void initMaterial();
 
   virtual void updateResidual(GhostType ghost_type);
 
   virtual void computeAllNonLocalStresses(GhostType ghost_type = _not_ghost);
 
   void savePairs(const std::string & filename) const;
   void neighbourhoodStatistics(const std::string & filename) const;
 
 protected:
   void updatePairList(const ElementTypeMapArray<Real> & quadrature_points_coordinates);
 
   void computeWeights(const ElementTypeMapArray<Real> & quadrature_points_coordinates);
 
   void createCellList(ElementTypeMapArray<Real> & quadrature_points_coordinates);
 
   void cleanupExtraGhostElement(const ElementTypeMap<UInt> & nb_ghost_protected);
 
   void fillCellList(const ElementTypeMapArray<Real> & quadrature_points_coordinates,
 		    const GhostType & ghost_type);
 
   /// constitutive law
   virtual void computeNonLocalStresses(GhostType ghost_type = _not_ghost) = 0;
 
   template<typename T>
-  void weightedAvergageOnNeighbours(const ElementTypeMapArray<T> & to_accumulate,
-				    ElementTypeMapArray<T> & accumulated,
+  void weightedAvergageOnNeighbours(const InternalField<T> & to_accumulate,
+				    InternalField<T> & accumulated,
 				    UInt nb_degree_of_freedom,
 				    GhostType ghost_type2 = _not_ghost) const;
 
   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);
 
-  //  virtual inline void onElementsAdded(const Array<Element> & element_list);
+  virtual inline void onElementsAdded(const Array<Element> & element_list);
   virtual inline void onElementsRemoved(const Array<Element> & element_list,
 					const ElementTypeMapArray<UInt> & new_numbering,
 					const RemovedElementsEvent & event);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   void registerNonLocalVariable(InternalField<Real> & local,
 				InternalField<Real> & non_local,
 				UInt nb_degree_of_freedom) {
     ID id = local.getID();
     NonLocalVariable & non_local_variable = non_local_variables[id];
 
     non_local_variable.local = &local;
     non_local_variable.non_local = &non_local;
     non_local_variable.nb_component = nb_degree_of_freedom;
   }
 
-  AKANTU_GET_MACRO(PairList, pair_list, const PairList<UInt> &)
+  AKANTU_GET_MACRO(PairList, pair_list, const PairList &)
   Real getRadius() const { return weight_func->getRadius(); }
   AKANTU_GET_MACRO(CellList, *spatial_grid, const SpatialGrid<QuadraturePoint> &)
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
 
   /// the weight function used
   WeightFunction<dim> * weight_func;
 
 private:
-  /// the pairs of quadrature points
-  PairList<UInt> pair_list;
+  /**
+   * the pairs of quadrature points
+   * 0: not ghost to not ghost
+   * 1: not ghost to ghost
+   */
+  PairList pair_list[2];
+
   /// the weights associated to the pairs
-  PairList<Real> pair_weight;
+  Array<Real> * pair_weight[2];
 
   /// the regular grid to construct/update the pair lists
   SpatialGrid<QuadraturePoint> * spatial_grid;
 
   /// the types of the existing pairs
   typedef std::set< std::pair<ElementType, ElementType> > pair_type;
   pair_type existing_pairs[2];
 
   /// count the number of calls of computeStress
   UInt compute_stress_calls;
 
   struct NonLocalVariable {
     InternalField<Real> * local;
     InternalField<Real> * non_local;
     UInt nb_component;
   };
 
   std::map<ID, NonLocalVariable> non_local_variables;
 
   bool is_creating_grid;
 
   GridSynchronizer * grid_synchronizer;
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 #include "material_non_local_inline_impl.cc"
 
 
 __END_AKANTU__
 
 #endif /* __AKANTU_MATERIAL_NON_LOCAL_HH__ */
diff --git a/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc b/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc
index 3a0a5f204..d24e51914 100644
--- a/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc
+++ b/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc
@@ -1,853 +1,781 @@
 /**
  * @file   material_non_local_inline_impl.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Aug 31 2011
  * @date last modification: Mon Jun 23 2014
  *
  * @brief  Non-local inline implementation
  *
  * @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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 __END_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 #include "aka_types.hh"
 #include "grid_synchronizer.hh"
 #include "synchronizer_registry.hh"
 #include "integrator.hh"
 /* -------------------------------------------------------------------------- */
 #include <fstream>
 /* -------------------------------------------------------------------------- */
 
 #if defined(AKANTU_DEBUG_TOOLS)
 #  include "aka_debug_tools.hh"
 #endif
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template<UInt DIM, template <UInt> class WeightFunction>
 MaterialNonLocal<DIM, WeightFunction>::MaterialNonLocal(SolidMechanicsModel & model,
 							const ID & id)  :
   Material(model, id), weight_func(NULL), spatial_grid(NULL),
   compute_stress_calls(0), is_creating_grid(false), grid_synchronizer(NULL) {
   AKANTU_DEBUG_IN();
 
+
+  for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
+    GhostType ghost_type = (GhostType) gt;
+    pair_weight[ghost_type] = NULL;
+  }
+
+
   this->is_non_local = true;
   this->weight_func = new WeightFunction<DIM>(*this);
 
   this->registerSubSection(_st_non_local, "weight_function", *weight_func);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 MaterialNonLocal<spatial_dimension, WeightFunction>::~MaterialNonLocal() {
   AKANTU_DEBUG_IN();
 
   delete spatial_grid;
   delete weight_func;
   delete grid_synchronizer;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::initMaterial() {
   AKANTU_DEBUG_IN();
   //  Material::initMaterial();
   Mesh & mesh = this->model->getFEEngine().getMesh();
 
   InternalField<Real> quadrature_points_coordinates("quadrature_points_coordinates_tmp_nl", *this);
   quadrature_points_coordinates.initialize(spatial_dimension);
 
   ElementTypeMap<UInt> nb_ghost_protected;
   Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _ghost);
   for(; it != last_type; ++it)
     nb_ghost_protected(mesh.getNbElement(*it, _ghost), *it, _ghost);
 
   AKANTU_DEBUG_INFO("Creating cell list");
   createCellList(quadrature_points_coordinates);
 
   AKANTU_DEBUG_INFO("Creating pairs");
   updatePairList(quadrature_points_coordinates);
 
 #if not defined(AKANTU_NDEBUG)
   if(AKANTU_DEBUG_TEST(dblDump))
      neighbourhoodStatistics("material_non_local.stats");
 #endif
 
   AKANTU_DEBUG_INFO("Cleaning extra ghosts");
   cleanupExtraGhostElement(nb_ghost_protected);
 
   AKANTU_DEBUG_INFO("Computing weights");
   weight_func->setRadius(weight_func->getRadius());
   weight_func->init();
 
   computeWeights(quadrature_points_coordinates);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::cleanupExtraGhostElement(const ElementTypeMap<UInt> & nb_ghost_protected) {
   AKANTU_DEBUG_IN();
 
   // Create list of element to keep
   std::set<Element> relevant_ghost_element;
 
-  pair_type::const_iterator first_pair_types = existing_pairs[1].begin();
-  pair_type::const_iterator last_pair_types = existing_pairs[1].end();
-  for (; first_pair_types != last_pair_types; ++first_pair_types) {
-    ElementType type2 = first_pair_types->second;
-    GhostType ghost_type2 = _ghost;
-    UInt nb_quad2 = this->model->getFEEngine().getNbQuadraturePoints(type2);
-    Array<UInt> & elem_filter = element_filter(type2, ghost_type2);
-
-    const Array<UInt> & pairs =
-      pair_list(first_pair_types->first, _not_ghost)(first_pair_types->second, ghost_type2);
-    Array<UInt>::const_iterator< Vector<UInt> > first_pair = pairs.begin(2);
-    Array<UInt>::const_iterator< Vector<UInt> > last_pair  = pairs.end(2);
-    for(;first_pair != last_pair; ++first_pair) {
-      UInt _q2 = (*first_pair)(1);
-      QuadraturePoint q2(type2, elem_filter(_q2 / nb_quad2), _q2 % nb_quad2, ghost_type2);
-      relevant_ghost_element.insert(q2);
-    }
+  PairList::const_iterator first_pair = pair_list[_ghost].begin();
+  PairList::const_iterator last_pair  = pair_list[_ghost].end();
+  for(;first_pair != last_pair; ++first_pair) {
+    const QuadraturePoint & q2 = first_pair->second;
+    relevant_ghost_element.insert(q2);
   }
 
   // Create list of element to remove and new numbering for element to keep
   Mesh & mesh = this->model->getFEEngine().getMesh();
   std::set<Element> ghost_to_erase;
 
-  Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost);
+  Mesh::type_iterator it        = mesh.firstType(spatial_dimension, _ghost);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _ghost);
 
   RemovedElementsEvent remove_elem(mesh);
 
-  Element element;
-  element.ghost_type = _ghost;
+
+  Element element_global;   // member element corresponds to global element number
+  element_global.ghost_type = _ghost;
+
   for(; it != last_type; ++it) {
-    element.type = *it;
+    element_global.type = *it;
     UInt nb_ghost_elem = mesh.getNbElement(*it, _ghost);
     UInt nb_ghost_elem_protected = 0;
     try {
       nb_ghost_elem_protected = nb_ghost_protected(*it, _ghost);
     } catch (...) {}
 
     if(!remove_elem.getNewNumbering().exists(*it, _ghost))
       remove_elem.getNewNumbering().alloc(nb_ghost_elem, 1, *it, _ghost);
     else remove_elem.getNewNumbering(*it, _ghost).resize(nb_ghost_elem);
 
-    Array<UInt> & elem_filter = element_filter(*it, _ghost);
     Array<UInt> & new_numbering = remove_elem.getNewNumbering(*it, _ghost);
     UInt ng = 0;
     for (UInt g = 0; g < nb_ghost_elem; ++g) {
-      element.element = g;
-      if(element.element >= nb_ghost_elem_protected &&
-	 (std::find(relevant_ghost_element.begin(),
-		    relevant_ghost_element.end(),
-		    element) == relevant_ghost_element.end())) {
-	remove_elem.getList().push_back(element);
+      if (element_global.element >= nb_ghost_elem_protected) {
+	Element element_local = this->convertToLocalElement(element_global);
+
+	if (std::find(relevant_ghost_element.begin(),
+		      relevant_ghost_element.end(),
+		      element_local) == relevant_ghost_element.end()) {
+	remove_elem.getList().push_back(element_global);
 	new_numbering(g) = UInt(-1);
-      } else {
-	new_numbering(g) = ng;
+      }
+    } else {
+      new_numbering(g) = ng;
 	++ng;
       }
     }
   }
 
   mesh.sendEvent(remove_elem);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::createCellList(ElementTypeMapArray<Real> & quadrature_points_coordinates) {
   AKANTU_DEBUG_IN();
 
   const Real safety_factor = 1.2; // for the cell grid spacing
   Mesh & mesh = this->model->getFEEngine().getMesh();
   mesh.computeBoundingBox();
 
   const Vector<Real> & lower_bounds = mesh.getLocalLowerBounds();
   const Vector<Real> & upper_bounds = mesh.getLocalUpperBounds();
   Vector<Real> center = 0.5 * (upper_bounds + lower_bounds);
 
   Vector<Real> spacing(spatial_dimension, weight_func->getRadius() * safety_factor);
 
   spatial_grid = new SpatialGrid<QuadraturePoint>(spatial_dimension, spacing, center);
 
   this->computeQuadraturePointsCoordinates(quadrature_points_coordinates, _not_ghost);
   this->fillCellList(quadrature_points_coordinates, _not_ghost);
-
+ 
   is_creating_grid = true;
   SynchronizerRegistry & synch_registry = this->model->getSynchronizerRegistry();
   std::stringstream sstr; sstr << getID() << ":grid_synchronizer";
   grid_synchronizer = GridSynchronizer::createGridSynchronizer(mesh,
 							       *spatial_grid,
+							       synch_registry,
 							       sstr.str());
   synch_registry.registerSynchronizer(*grid_synchronizer, _gst_mnl_for_average);
   synch_registry.registerSynchronizer(*grid_synchronizer, _gst_mnl_weight);
   is_creating_grid = false;
-
+ 
   this->computeQuadraturePointsCoordinates(quadrature_points_coordinates, _ghost);
   fillCellList(quadrature_points_coordinates, _ghost);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::fillCellList(const ElementTypeMapArray<Real> & quadrature_points_coordinates,
 								       const GhostType & ghost_type) {
-  Mesh & mesh = this->model->getFEEngine().getMesh();
-
   QuadraturePoint q;
   q.ghost_type = ghost_type;
 
   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) {
     Array<UInt> & elem_filter = element_filter(*it, ghost_type);
     UInt nb_element = elem_filter.getSize();
     UInt nb_quad    = this->model->getFEEngine().getNbQuadraturePoints(*it, ghost_type);
 
     const Array<Real> & quads = quadrature_points_coordinates(*it, ghost_type);
     q.type = *it;
 
     Array<Real>::const_vector_iterator quad = quads.begin(spatial_dimension);
     UInt * elem = elem_filter.storage();
 
     for (UInt e = 0; e < nb_element; ++e) {
       q.element = *elem;
       for (UInt nq = 0; nq < nb_quad; ++nq) {
 	q.num_point = nq;
 	//q.setPosition(*quad);
 	spatial_grid->insert(q, *quad);
 	++quad;
       }
       ++elem;
     }
   }
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::updatePairList(const ElementTypeMapArray<Real> & quadrature_points_coordinates) {
   AKANTU_DEBUG_IN();
 
-  Mesh & mesh = this->model->getFEEngine().getMesh();
-
   GhostType ghost_type = _not_ghost;
-  QuadraturePoint quad_point;
-  quad_point.ghost_type = ghost_type;
+  QuadraturePoint q1;
+  q1.ghost_type = ghost_type;
 
   // generate the pair of neighbor depending of the cell_list
   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) {
     // Preparing datas
     const Array<Real> & quads = quadrature_points_coordinates(*it, ghost_type);
-    Array<Real>::const_vector_iterator first_quad = quads.begin(spatial_dimension);
-    Array<Real>::const_vector_iterator last_quad  = quads.end(spatial_dimension);
+    Array<Real>::const_vector_iterator q1_coord_it = quads.begin(spatial_dimension);
+    Array<Real>::const_vector_iterator last_quad   = quads.end(spatial_dimension);
 
-    ElementTypeMapArray<UInt> & pairs = pair_list(ElementTypeMapArray<UInt>("pairs", getID(), memory_id),
-						  *it,
-						  ghost_type);
-
-    ElementType current_element_type = _not_defined;
-    GhostType current_ghost_type = _casper;
-    UInt existing_pairs_num = 0;
-
-    Array<UInt> * neighbors = NULL;
-    Array<UInt>::const_iterator< Vector<UInt> > element_index_material_it;
-    Array<Real>::const_vector_iterator quad_coord_it;
-
-    UInt my_num_quad = 0;
-    quad_point.type = *it;
+    q1.type = *it;
+    q1.global_num = 0;
     // loop over quad points
-    for(;first_quad != last_quad; ++first_quad, ++my_num_quad) {
-      SpatialGrid<QuadraturePoint>::CellID cell_id = spatial_grid->getCellID(*first_quad);
-
+    for(;q1_coord_it != last_quad; ++q1_coord_it, ++(q1.global_num)) {
+      UInt nb_quad1 =
+	this->model->getFEEngine().getNbQuadraturePoints(q1.type,
+							 q1.ghost_type);
+      q1.element = q1.global_num / nb_quad1;
+      const Vector<Real> & q1_coord = *q1_coord_it;
+
+      SpatialGrid<QuadraturePoint>::CellID cell_id = spatial_grid->getCellID(q1_coord);
       SpatialGrid<QuadraturePoint>::neighbor_cells_iterator first_neigh_cell =
 	spatial_grid->beginNeighborCells(cell_id);
       SpatialGrid<QuadraturePoint>::neighbor_cells_iterator last_neigh_cell =
 	spatial_grid->endNeighborCells(cell_id);
 
-      UInt nb_quad_per_elem_1 =
-	this->model->getFEEngine().getNbQuadraturePoints(*it, quad_point.ghost_type);
-
-      quad_point.element = my_num_quad / nb_quad_per_elem_1;
-
       // loop over neighbors cells of the one containing the current quadrature
       // point
       for (; first_neigh_cell != last_neigh_cell; ++first_neigh_cell) {
 	SpatialGrid<QuadraturePoint>::Cell::iterator first_neigh_quad =
 	  spatial_grid->beginCell(*first_neigh_cell);
 	SpatialGrid<QuadraturePoint>::Cell::iterator last_neigh_quad =
 	  spatial_grid->endCell(*first_neigh_cell);
 
 	// loop over the quadrature point in the current cell of the cell list
 	for (;first_neigh_quad != last_neigh_quad; ++first_neigh_quad){
-	  QuadraturePoint quad = *first_neigh_quad;
-	  UInt nb_quad_per_elem_2 =
-	    this->model->getFEEngine().getNbQuadraturePoints(quad.type,
-							     quad.ghost_type);
-
-	  // little optimization to not search in the map at each quad points
-	  if(quad.type != current_element_type ||
-	     quad.ghost_type != current_ghost_type) {
-
-	    current_element_type = quad.type;
-	    current_ghost_type   = quad.ghost_type;
-	    existing_pairs_num = quad.ghost_type == _not_ghost ? 0 : 1;
-	    if(!pairs.exists(current_element_type, current_ghost_type)) {
-	      neighbors = &(pairs.alloc(0, 2,
-					current_element_type,
-					current_ghost_type));
-	    } else {
-	      neighbors = &(pairs(current_element_type,
-				  current_ghost_type));
-	    }
-	    existing_pairs[existing_pairs_num].insert(std::pair<ElementType,
-						      ElementType>(*it,
-								   current_element_type));
-
-	    element_index_material_it = this->model->getElementIndexByMaterial(current_element_type,
-									       current_ghost_type).begin(2);
-
-	    quad_coord_it = quadrature_points_coordinates(current_element_type,
-							  current_ghost_type).begin(spatial_dimension);
-	  }
+	  QuadraturePoint q2 = this->convertToLocalPoint(*first_neigh_quad);
 
-	  const Vector<UInt> & el_mat = element_index_material_it[quad.element];
-	  UInt neigh_num_quad = el_mat(1) * nb_quad_per_elem_2 + quad.num_point;
-	  const Vector<Real> & neigh_quad = quad_coord_it[neigh_num_quad];
+	  Array<Real>::const_vector_iterator q2_coord_it =
+	    quadrature_points_coordinates(q2.type,
+					  q2.ghost_type).begin(spatial_dimension);
 
-	  if(neigh_num_quad > (element_filter(quad.type, quad.ghost_type).getSize()*nb_quad_per_elem_2)) {
-	    std::cout << "AAAAAAAAAAAAAAAA: " << quad << " " << neigh_num_quad << " " << el_mat << std::endl;
-	  }
+	  const Vector<Real> & q2_coord = q2_coord_it[q2.global_num];
+
+	  Real distance = q1_coord.distance(q2_coord);
 
-	  Real distance = first_quad->distance(neigh_quad);
 	  if(distance <= weight_func->getRadius() &&
-	     (quad.ghost_type == _ghost ||
-	      (quad.ghost_type == _not_ghost && my_num_quad <= neigh_num_quad))) { // storing only half lists
-	    UInt pair[2];
-	    pair[0] = my_num_quad;
-	    pair[1] = neigh_num_quad;
-	    neighbors->push_back(pair);
+	     (q2.ghost_type == _ghost ||
+	      (q2.ghost_type == _not_ghost && q1.global_num <= q2.global_num))) { // storing only half lists
+	    pair_list[q2.ghost_type].push_back(std::make_pair(q1, q2));
 	  }
 	}
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::computeWeights(const ElementTypeMapArray<Real> & quadrature_points_coordinates) {
   AKANTU_DEBUG_IN();
 
-  GhostType ghost_type1;
-  ghost_type1 = _not_ghost;
-
   InternalField<Real> quadrature_points_volumes("quadrature_points_volumes", *this);
   quadrature_points_volumes.initialize(1);
 
   const FEEngine & fem = this->model->getFEEngine();
 
   weight_func->updateInternals(quadrature_points_volumes);
 
   for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
     GhostType ghost_type2 = (GhostType) gt;
-    UInt existing_pairs_num = gt - _not_ghost;
-    pair_type::iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
-    pair_type::iterator last_pair_types = existing_pairs[existing_pairs_num].end();
-
-    // Compute the weights
-    for (; first_pair_types != last_pair_types; ++first_pair_types) {
-      ElementType type1 = first_pair_types->first;
-      ElementType type2 = first_pair_types->second;
-
-      const Array<UInt> & pairs = pair_list(type1, ghost_type1)(type2, ghost_type2);
 
+    if(!(pair_weight[ghost_type2])) {
       std::string ghost_id = "";
-      if (ghost_type1 == _ghost) ghost_id = ":ghost";
+      if (ghost_type2 == _ghost) ghost_id = ":ghost";
+      std::stringstream sstr; sstr << getID() << ":pair_weight:" << ghost_id;
+      pair_weight[ghost_type2] = new Array<Real>(0, 2, sstr.str());
+    }
 
-      ElementTypeMapArray<Real> & weights_type_1 = pair_weight(type1, ghost_type1);
-      std::stringstream sstr; sstr << getID() << ":pair_weight:" << type1 << ghost_id;
-      weights_type_1.setID(sstr.str());
+    pair_weight[ghost_type2]->resize(pair_list[ghost_type2].size());
+    pair_weight[ghost_type2]->clear();
 
-      Array<Real> * tmp_weight = NULL;
-      if(!weights_type_1.exists(type2, ghost_type2)) {
-	tmp_weight = &(weights_type_1.alloc(0, 2, type2, ghost_type2));
-      } else {
-	tmp_weight = &(weights_type_1(type2, ghost_type2));
-      }
-      Array<Real> & weights = *tmp_weight;
-      weights.resize(pairs.getSize());
-      weights.clear();
+    PairList::const_iterator first_pair = pair_list[ghost_type2].begin();
+    PairList::const_iterator last_pair  = pair_list[ghost_type2].end();
 
-      const Array<Real> & jacobians_1 = fem.getIntegratorInterface().getJacobians(type1, ghost_type1);
-      const Array<Real> & jacobians_2 = fem.getIntegratorInterface().getJacobians(type2, ghost_type2);
+    Array<Real>::vector_iterator weight_it = pair_weight[ghost_type2]->begin(2);
 
-      const Array<UInt> & elem_mat_1 = element_filter(type1, ghost_type1);
-      const Array<UInt> & elem_mat_2 = element_filter(type2, ghost_type2);
+    // Compute the weights
+    for(;first_pair != last_pair; ++first_pair, ++weight_it) {
+      Vector<Real> & weight = *weight_it;
+
+      const QuadraturePoint & lq1 = first_pair->first;
+      const QuadraturePoint & lq2 = first_pair->second;
 
-      UInt nb_quad1 = fem.getNbQuadraturePoints(type1);
-      UInt nb_quad2 = fem.getNbQuadraturePoints(type2);
+      QuadraturePoint gq1 = this->convertToGlobalPoint(lq1);
+      QuadraturePoint gq2 = this->convertToGlobalPoint(lq2);
 
-      Array<Real> & quads_volumes1 = quadrature_points_volumes(type1, ghost_type1);
-      Array<Real> & quads_volumes2 = quadrature_points_volumes(type2, ghost_type2);
+      const Real & q2_wJ = fem.getIntegratorInterface().getJacobians(gq2.type, gq2.ghost_type)(gq2.global_num);
 
-      Array<Real>::const_vector_iterator iquads1;
-      Array<Real>::const_vector_iterator iquads2;
-      iquads1 = quadrature_points_coordinates(type1, ghost_type1).begin(spatial_dimension);
-      iquads2 = quadrature_points_coordinates(type2, ghost_type2).begin(spatial_dimension);
+      Real & q1_volume = quadrature_points_volumes(lq1.type, lq1.ghost_type)(lq1.global_num);
 
-      Array<UInt>::const_iterator< Vector<UInt> > first_pair = pairs.begin(2);
-      Array<UInt>::const_iterator< Vector<UInt> > last_pair  = pairs.end(2);
-      Array<Real>::vector_iterator weight  = weights.begin(2);
+      const Vector<Real> & q1_coord =
+	quadrature_points_coordinates(lq1.type, lq1.ghost_type).begin(spatial_dimension)[lq1.global_num];
+      const Vector<Real> & q2_coord =
+	quadrature_points_coordinates(lq1.type, lq1.ghost_type).begin(spatial_dimension)[lq2.global_num];
 
-      this->weight_func->selectType(type1, ghost_type1, type2, ghost_type2);
+      this->weight_func->selectType(lq1.type, lq1.ghost_type, lq2.type, lq2.ghost_type);
 
       // Weight function
-      for(;first_pair != last_pair; ++first_pair, ++weight) {
-	UInt _q1 = (*first_pair)(0);
-	UInt _q2 = (*first_pair)(1);
-	const Vector<Real> & pos1 = iquads1[_q1];
-	const Vector<Real> & pos2 = iquads2[_q2];
-	QuadraturePoint q1(_q1 / nb_quad1, _q1 % nb_quad1, _q1, pos1, type1, ghost_type1);
-	QuadraturePoint q2(_q2 / nb_quad2, _q2 % nb_quad2, _q2, pos2, type2, ghost_type2);
-
-	Real r = pos1.distance(pos2);
-
-	Real w2J2 = jacobians_2(elem_mat_2(q2.element)*nb_quad2 + q2.num_point);
-	Real w = this->weight_func->operator()(r, q1, q2);
-	(*weight)(0) = w2J2 * w;
-	quads_volumes1(_q1) += (*weight)(0);
-
-	if(ghost_type2 != _ghost && _q1 != _q2) {
-	  Real w1J1 = jacobians_1(elem_mat_1(q1.element)*nb_quad1 + q1.num_point);
-	  (*weight)(1) = w1J1 * this->weight_func->operator()(r, q2, q1);
-	  quads_volumes2(_q2) += (*weight)(1);
-	} else
-	  (*weight)(1) = 0;
-      }
+      Real r = q1_coord.distance(q2_coord);
+      Real w1 = this->weight_func->operator()(r, lq1, lq2);
+      weight(0) = q2_wJ * w1;
+      q1_volume += weight(0);
+
+      if(lq2.ghost_type != _ghost && lq1.global_num != lq2.global_num) {
+	const Real & q1_wJ = fem.getIntegratorInterface().getJacobians(gq1.type, gq1.ghost_type)(gq1.global_num);
+	Real & q2_volume = quadrature_points_volumes(lq2.type, lq2.ghost_type)(lq2.global_num);
+
+	Real w2 = this->weight_func->operator()(r, lq2, lq1);
+	weight(1) = q1_wJ * w2;
+
+	q2_volume += weight(1);
+      } else
+	weight(1) = 0.;
     }
   }
 
   //normalize the weights
   for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
     GhostType ghost_type2 = (GhostType) gt;
-    UInt existing_pairs_num = gt - _not_ghost;
-    pair_type::iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
-    pair_type::iterator last_pair_types = existing_pairs[existing_pairs_num].end();
 
-    first_pair_types = existing_pairs[existing_pairs_num].begin();
-    for (; first_pair_types != last_pair_types; ++first_pair_types) {
-      ElementType type1 = first_pair_types->first;
-      ElementType type2 = first_pair_types->second;
+    PairList::const_iterator first_pair = pair_list[ghost_type2].begin();
+    PairList::const_iterator last_pair  = pair_list[ghost_type2].end();
 
-      const Array<UInt> & pairs = pair_list(type1, ghost_type1)(type2, ghost_type2);
-      Array<Real> & weights = pair_weight(type1, ghost_type1)(type2, ghost_type2);
+    Array<Real>::vector_iterator weight_it = pair_weight[ghost_type2]->begin(2);
 
-      Array<Real> & quads_volumes1 = quadrature_points_volumes(type1, ghost_type1);
-      Array<Real> & quads_volumes2 = quadrature_points_volumes(type2, ghost_type2);
+    // Compute the weights
+    for(;first_pair != last_pair; ++first_pair, ++weight_it) {
+      Vector<Real> & weight = *weight_it;
 
-      Array<UInt>::const_iterator< Vector<UInt> > first_pair = pairs.begin(2);
-      Array<UInt>::const_iterator< Vector<UInt> > last_pair  = pairs.end(2);
-      Array<Real>::vector_iterator weight  = weights.begin(2);
+      const QuadraturePoint & lq1 = first_pair->first;
+      const QuadraturePoint & lq2 = first_pair->second;
 
-      for(;first_pair != last_pair; ++first_pair, ++weight) {
-	UInt q1 = (*first_pair)(0);
-	UInt q2 = (*first_pair)(1);
+      Real & q1_volume = quadrature_points_volumes(lq1.type, lq1.ghost_type)(lq1.global_num);
 
-	(*weight)(0) *= 1. / quads_volumes1(q1);
-	if(ghost_type2 != _ghost) (*weight)(1) *= 1. / quads_volumes2(q2);
+      weight(0) *= 1. / q1_volume;
+      if(ghost_type2 != _ghost) {
+	Real & q2_volume = quadrature_points_volumes(lq2.type, lq2.ghost_type)(lq2.global_num);
+	weight(1) *= 1. / q2_volume;
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 template<typename T>
-void MaterialNonLocal<spatial_dimension, WeightFunction>::weightedAvergageOnNeighbours(const ElementTypeMapArray<T> & to_accumulate,
-										       ElementTypeMapArray<T> & accumulated,
+void MaterialNonLocal<spatial_dimension, WeightFunction>::weightedAvergageOnNeighbours(const InternalField<T> & to_accumulate,
+										       InternalField<T> & accumulated,
 										       UInt nb_degree_of_freedom,
 										       GhostType ghost_type2) const {
   AKANTU_DEBUG_IN();
 
-  UInt existing_pairs_num = 0;
-  if (ghost_type2 == _ghost) existing_pairs_num = 1;
+  if(ghost_type2 == _not_ghost)  {
+    accumulated.reset();
+  }
 
-  pair_type::const_iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
-  pair_type::const_iterator last_pair_types = existing_pairs[existing_pairs_num].end();
+  PairList::const_iterator first_pair = pair_list[ghost_type2].begin();
+  PairList::const_iterator last_pair  = pair_list[ghost_type2].end();
 
-  GhostType ghost_type1 = _not_ghost; // does not make sens the ghost vs ghost so this should always by _not_ghost
+  Array<Real>::vector_iterator weight_it = pair_weight[ghost_type2]->begin(2);
 
-  for (; first_pair_types != last_pair_types; ++first_pair_types) {
-    const Array<UInt> & pairs =
-      pair_list(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2);
-    const Array<Real> & weights =
-      pair_weight(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2);
+  // Compute the weights
+  for(;first_pair != last_pair; ++first_pair, ++weight_it) {
+    Vector<Real> & weight = *weight_it;
 
-    const Array<T> & to_acc = to_accumulate(first_pair_types->second, ghost_type2);
-    Array<T> & acc = accumulated(first_pair_types->first, ghost_type1);
+    const QuadraturePoint & lq1 = first_pair->first;
+    const QuadraturePoint & lq2 = first_pair->second;
 
-    if(ghost_type2 == _not_ghost) acc.clear();
+    const Vector<T> & q2_to_acc = to_accumulate(lq2.type, lq2.ghost_type).begin(nb_degree_of_freedom)[lq2.global_num];
+    Vector<T> & q1_acc = accumulated(lq1.type, lq1.ghost_type).begin(nb_degree_of_freedom)[lq1.global_num];
 
-    Array<UInt>::const_iterator< Vector<UInt> > first_pair = pairs.begin(2);
-    Array<UInt>::const_iterator< Vector<UInt> > last_pair  = pairs.end(2);
-    Array<Real>::const_vector_iterator pair_w = weights.begin(2);
+    q1_acc += weight(0) * q2_to_acc;
 
-    for(;first_pair != last_pair; ++first_pair, ++pair_w) {
-      UInt q1 = (*first_pair)(0);
-      UInt q2 = (*first_pair)(1);
-      for(UInt d = 0; d < nb_degree_of_freedom; ++d){
-	acc(q1, d) += (*pair_w)(0) * to_acc(q2, d);
-	if(ghost_type2 != _ghost) acc(q2, d) += (*pair_w)(1) * to_acc(q1, d);
-      }
+    if(ghost_type2 != _ghost) {
+      const Vector<T> & q1_to_acc = to_accumulate(lq1.type, lq1.ghost_type).begin(nb_degree_of_freedom)[lq1.global_num];
+      Vector<T> & q2_acc = accumulated(lq2.type, lq2.ghost_type).begin(nb_degree_of_freedom)[lq2.global_num];
+
+      q2_acc += weight(1) * q1_to_acc;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::updateResidual(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   // Update the weights for the non local variable averaging
   if(ghost_type == _not_ghost &&
      this->weight_func->getUpdateRate() &&
      (this->compute_stress_calls % this->weight_func->getUpdateRate() == 0)) {
     ElementTypeMapArray<Real> quadrature_points_coordinates("quadrature_points_coordinates", getID());
     Mesh & mesh = this->model->getFEEngine().getMesh();
     mesh.initElementTypeMapArray(quadrature_points_coordinates, spatial_dimension, spatial_dimension);
     computeQuadraturePointsCoordinates(quadrature_points_coordinates, _not_ghost);
     computeQuadraturePointsCoordinates(quadrature_points_coordinates, _ghost);
     computeWeights(quadrature_points_coordinates);
   }
   if(ghost_type == _not_ghost) ++this->compute_stress_calls;
 
   computeAllStresses(ghost_type);
 
   computeNonLocalStresses(ghost_type);
   assembleResidual(ghost_type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::computeAllNonLocalStresses(GhostType ghost_type) {
   // Update the weights for the non local variable averaging
   if(ghost_type == _not_ghost) {
     if(this->weight_func->getUpdateRate() &&
        (this->compute_stress_calls % this->weight_func->getUpdateRate() == 0)) {
       this->model->getSynchronizerRegistry().asynchronousSynchronize(_gst_mnl_weight);
 
       ElementTypeMapArray<Real> quadrature_points_coordinates("quadrature_points_coordinates", getID());
       Mesh & mesh = this->model->getFEEngine().getMesh();
       mesh.initElementTypeMapArray(quadrature_points_coordinates, spatial_dimension, spatial_dimension);
       computeQuadraturePointsCoordinates(quadrature_points_coordinates, _not_ghost);
       computeQuadraturePointsCoordinates(quadrature_points_coordinates, _ghost);
 
       this->model->getSynchronizerRegistry().waitEndSynchronize(_gst_mnl_weight);
 
       computeWeights(quadrature_points_coordinates);
     }
 
     typename std::map<ID, NonLocalVariable>::iterator it = non_local_variables.begin();
     typename std::map<ID, NonLocalVariable>::iterator end = non_local_variables.end();
     for(;it != end; ++it) {
       NonLocalVariable & non_local_variable = it->second;
 
       non_local_variable.non_local->resize();
       this->weightedAvergageOnNeighbours(*non_local_variable.local, *non_local_variable.non_local,
 					 non_local_variable.nb_component, _not_ghost);
     }
 
     ++this->compute_stress_calls;
   } else {
     typename std::map<ID, NonLocalVariable>::iterator it = non_local_variables.begin();
     typename std::map<ID, NonLocalVariable>::iterator end = non_local_variables.end();
     for(;it != end; ++it) {
       NonLocalVariable & non_local_variable = it->second;
       this->weightedAvergageOnNeighbours(*non_local_variable.local, *non_local_variable.non_local,
 					 non_local_variable.nb_component, _ghost);
     }
 
     computeNonLocalStresses(_not_ghost);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::savePairs(const std::string & filename) const {
   std::ofstream pout;
 
   std::stringstream sstr;
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   Int prank = comm.whoAmI();
   sstr << filename << "." << prank;
 
   pout.open(sstr.str().c_str());
 
-  GhostType ghost_type1;
-  ghost_type1 = _not_ghost;
-
   for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
     GhostType ghost_type2 = (GhostType) gt;
-    UInt existing_pairs_num = gt - _not_ghost;
-
-    pair_type::const_iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
-    pair_type::const_iterator last_pair_types = existing_pairs[existing_pairs_num].end();
 
-    for (; first_pair_types != last_pair_types; ++first_pair_types) {
-      const Array<UInt> & pairs =
-	(*pair_list(first_pair_types->first, ghost_type1))(first_pair_types->second, ghost_type2);
-      const Array<Real> & weights =
-	(*pair_weight(first_pair_types->first, ghost_type1))(first_pair_types->second, ghost_type2);
+    PairList::const_iterator first_pair = pair_list[ghost_type2].begin();
+    PairList::const_iterator last_pair  = pair_list[ghost_type2].end();
 
-      pout << "Types : " << first_pair_types->first << " (" << ghost_type1 << ") - " << first_pair_types->second << " (" << ghost_type2 << ")" << std::endl;
+    Array<Real>::vector_iterator weight_it = pair_weight[ghost_type2]->begin(2);
 
-      Array<UInt>::const_iterator< Vector<UInt> > first_pair = pairs.begin(2);
-      Array<UInt>::const_iterator< Vector<UInt> > last_pair  = pairs.end(2);
-      Array<Real>::const_vector_iterator pair_w = weights.begin(2);
+    for(;first_pair != last_pair; ++first_pair, ++weight_it) {
+      Vector<Real> & weight = *weight_it;
 
-      for(;first_pair != last_pair; ++first_pair, ++pair_w) {
-	UInt q1 = (*first_pair)(0);
-	UInt q2 = (*first_pair)(1);
-	pout << q1 << " " << q2 << " "<< (*pair_w)(0) << " " << (*pair_w)(1) << std::endl;
-      }
+      const QuadraturePoint & lq1 = first_pair->first;
+      const QuadraturePoint & lq2 = first_pair->second;
+      pout << lq1 << " " << lq2 << " " << weight << std::endl;
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 void MaterialNonLocal<spatial_dimension, WeightFunction>::neighbourhoodStatistics(const std::string & filename) const {
-  std::ofstream pout;
-  pout.open(filename.c_str());
-
-  const Mesh & mesh = this->model->getFEEngine().getMesh();
-
-  GhostType ghost_type1;
-  ghost_type1 = _not_ghost;
-
-  StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
-  Int prank = comm.whoAmI();
-
-  InternalField<UInt> nb_neighbors("nb_neighbours", *const_cast<MaterialNonLocal *>(this));
-  nb_neighbors.initialize(1);
-
-  for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
-    GhostType ghost_type2 = (GhostType) gt;
-    UInt existing_pairs_num = gt - _not_ghost;
-
-    pair_type::const_iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
-    pair_type::const_iterator last_pair_types = existing_pairs[existing_pairs_num].end();
-
-    for (; first_pair_types != last_pair_types; ++first_pair_types) {
-      const Array<UInt> & pairs =
-	pair_list(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2);
-      if(prank == 0) {
-	pout << ghost_type2 << " ";
-	pout << "Types : " << first_pair_types->first << " " << first_pair_types->second << std::endl;
-      }
-      Array<UInt>::const_iterator< Vector<UInt> > first_pair = pairs.begin(2);
-      Array<UInt>::const_iterator< Vector<UInt> > last_pair  = pairs.end(2);
-      Array<UInt> & nb_neigh_1 = nb_neighbors(first_pair_types->first, ghost_type1);
-      Array<UInt> & nb_neigh_2 = nb_neighbors(first_pair_types->second, ghost_type2);
-      for(;first_pair != last_pair; ++first_pair) {
-	UInt q1 = (*first_pair)(0);
-	UInt q2 = (*first_pair)(1);
-	++(nb_neigh_1(q1));
-	if(q1 != q2) ++(nb_neigh_2(q2));
-      }
-    }
-
-    Mesh::type_iterator it        = mesh.firstType(spatial_dimension, ghost_type1);
-    Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type1);
-    UInt nb_quads = 0;
-    Real sum_nb_neig = 0;
-    UInt max_nb_neig = 0;
-    UInt min_nb_neig = std::numeric_limits<UInt>::max();
-    for(; it != last_type; ++it) {
-      Array<UInt> & nb_neighor = nb_neighbors(*it, ghost_type1);
-      Array<UInt>::iterator<UInt> nb_neigh = nb_neighor.begin();
-      Array<UInt>::iterator<UInt> end_neigh  = nb_neighor.end();
-
-      for (; nb_neigh != end_neigh; ++nb_neigh, ++nb_quads) {
-	UInt nb = *nb_neigh;
-	sum_nb_neig += nb;
-	max_nb_neig = std::max(max_nb_neig, nb);
-	min_nb_neig = std::min(min_nb_neig, nb);
-      }
-    }
-
-
-    comm.allReduce(&nb_quads,    1, _so_sum);
-    comm.allReduce(&sum_nb_neig, 1, _so_sum);
-    comm.allReduce(&max_nb_neig, 1, _so_max);
-    comm.allReduce(&min_nb_neig, 1, _so_min);
-
-    if(prank == 0) {
-      pout << ghost_type2 << " ";
-      pout << "Nb quadrature points: " << nb_quads << std::endl;
-
-      Real mean_nb_neig = sum_nb_neig / Real(nb_quads);
-      pout << ghost_type2 << " ";
-      pout << "Average nb neighbors: " << mean_nb_neig << "(" << sum_nb_neig << ")" << std::endl;
-
-      pout << ghost_type2 << " ";
-      pout << "Max nb neighbors:     " << max_nb_neig << std::endl;
-
-      pout << ghost_type2 << " ";
-      pout << "Min nb neighbors:     " << min_nb_neig << std::endl;
-    }
-  }
-  pout.close();
+  //   std::ofstream pout;
+  // pout.open(filename.c_str());
+
+  // const Mesh & mesh = this->model->getFEEngine().getMesh();
+
+  // GhostType ghost_type1;
+  // ghost_type1 = _not_ghost;
+
+  // StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
+  // Int prank = comm.whoAmI();
+
+  // InternalField<UInt> nb_neighbors("nb_neighbours", *const_cast<MaterialNonLocal *>(this));
+  // nb_neighbors.initialize(1);
+
+  // for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
+  //   GhostType ghost_type2 = (GhostType) gt;
+  //   UInt existing_pairs_num = gt - _not_ghost;
+
+  //   pair_type::const_iterator first_pair_types = existing_pairs[existing_pairs_num].begin();
+  //   pair_type::const_iterator last_pair_types = existing_pairs[existing_pairs_num].end();
+
+  //   for (; first_pair_types != last_pair_types; ++first_pair_types) {
+  //     const Array<UInt> & pairs =
+  //	pair_list(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2);
+  //     if(prank == 0) {
+  //	pout << ghost_type2 << " ";
+  //	pout << "Types : " << first_pair_types->first << " " << first_pair_types->second << std::endl;
+  //     }
+  //     Array<UInt>::const_iterator< Vector<UInt> > first_pair = pairs.begin(2);
+  //     Array<UInt>::const_iterator< Vector<UInt> > last_pair  = pairs.end(2);
+  //     Array<UInt> & nb_neigh_1 = nb_neighbors(first_pair_types->first, ghost_type1);
+  //     Array<UInt> & nb_neigh_2 = nb_neighbors(first_pair_types->second, ghost_type2);
+  //     for(;first_pair != last_pair; ++first_pair) {
+  //	UInt q1 = (*first_pair)(0);
+  //	UInt q2 = (*first_pair)(1);
+  //	++(nb_neigh_1(q1));
+  //	if(q1 != q2) ++(nb_neigh_2(q2));
+  //     }
+  //   }
+
+  //   Mesh::type_iterator it        = mesh.firstType(spatial_dimension, ghost_type1);
+  //   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type1);
+  //   UInt nb_quads = 0;
+  //   Real sum_nb_neig = 0;
+  //   UInt max_nb_neig = 0;
+  //   UInt min_nb_neig = std::numeric_limits<UInt>::max();
+  //   for(; it != last_type; ++it) {
+  //     Array<UInt> & nb_neighor = nb_neighbors(*it, ghost_type1);
+  //     Array<UInt>::iterator<UInt> nb_neigh = nb_neighor.begin();
+  //     Array<UInt>::iterator<UInt> end_neigh  = nb_neighor.end();
+
+  //     for (; nb_neigh != end_neigh; ++nb_neigh, ++nb_quads) {
+  //	UInt nb = *nb_neigh;
+  //	sum_nb_neig += nb;
+  //	max_nb_neig = std::max(max_nb_neig, nb);
+  //	min_nb_neig = std::min(min_nb_neig, nb);
+  //     }
+  //   }
+
+
+  //   comm.allReduce(&nb_quads,    1, _so_sum);
+  //   comm.allReduce(&sum_nb_neig, 1, _so_sum);
+  //   comm.allReduce(&max_nb_neig, 1, _so_max);
+  //   comm.allReduce(&min_nb_neig, 1, _so_min);
+
+  //   if(prank == 0) {
+  //     pout << ghost_type2 << " ";
+  //     pout << "Nb quadrature points: " << nb_quads << std::endl;
+
+  //     Real mean_nb_neig = sum_nb_neig / Real(nb_quads);
+  //     pout << ghost_type2 << " ";
+  //     pout << "Average nb neighbors: " << mean_nb_neig << "(" << sum_nb_neig << ")" << std::endl;
+
+  //     pout << ghost_type2 << " ";
+  //     pout << "Max nb neighbors:     " << max_nb_neig << std::endl;
+
+  //     pout << ghost_type2 << " ";
+  //     pout << "Min nb neighbors:     " << min_nb_neig << std::endl;
+  //   }
+  // }
+  // pout.close();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 inline UInt MaterialNonLocal<spatial_dimension, WeightFunction>::getNbDataForElements(const Array<Element> & elements,
 										      SynchronizationTag tag) const {
   UInt nb_quadrature_points = this->getModel().getNbQuadraturePoints(elements);
   UInt size = 0;
 
   if(tag == _gst_mnl_for_average) {
     typename std::map<ID, NonLocalVariable>::const_iterator it = non_local_variables.begin();
     typename std::map<ID, NonLocalVariable>::const_iterator end = non_local_variables.end();
 
     for(;it != end; ++it) {
       const NonLocalVariable & non_local_variable = it->second;
       size += non_local_variable.nb_component * sizeof(Real) * nb_quadrature_points;
     }
   }
 
   size += weight_func->getNbDataForElements(elements, tag);
 
   return size;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 inline void MaterialNonLocal<spatial_dimension, WeightFunction>::packElementData(CommunicationBuffer & buffer,
 										 const Array<Element> & elements,
 										 SynchronizationTag tag) const {
   if(tag == _gst_mnl_for_average) {
     typename std::map<ID, NonLocalVariable>::const_iterator it = non_local_variables.begin();
     typename std::map<ID, NonLocalVariable>::const_iterator end = non_local_variables.end();
 
     for(;it != end; ++it) {
       const NonLocalVariable & non_local_variable = it->second;
       this->packElementDataHelper(*non_local_variable.local,
 				  buffer, elements);
     }
   }
 
   weight_func->packElementData(buffer, elements, tag);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 inline void MaterialNonLocal<spatial_dimension, WeightFunction>::unpackElementData(CommunicationBuffer & buffer,
 										   const Array<Element> & elements,
 										   SynchronizationTag tag) {
   if(tag == _gst_mnl_for_average) {
     typename std::map<ID, NonLocalVariable>::iterator it = non_local_variables.begin();
     typename std::map<ID, NonLocalVariable>::iterator end = non_local_variables.end();
 
     for(;it != end; ++it) {
       NonLocalVariable & non_local_variable = it->second;
       this->unpackElementDataHelper(*non_local_variable.local,
 				    buffer, elements);
     }
   }
 
   weight_func->unpackElementData(buffer, elements, tag);
 }
 
 /* -------------------------------------------------------------------------- */
-// template<UInt spatial_dimension, template <UInt> class WeightFunction>
-// inline void MaterialNonLocal<spatial_dimension, WeightFunction>::onElementsAdded(const Array<Element> & element_list) {
-//   AKANTU_DEBUG_IN();
-
-//   Material::onElementsAdded(element_list, event);
-
-//   AKANTU_DEBUG_OUT();
-// }
+template<UInt spatial_dimension, template <UInt> class WeightFunction>
+inline void MaterialNonLocal<spatial_dimension, WeightFunction>::onElementsAdded(const Array<Element> & element_list) {
+  AKANTU_DEBUG_IN();
+  AKANTU_DEBUG_ERROR("This is a case not taken into account!!!");
+  AKANTU_DEBUG_OUT();
+}
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension, template <UInt> class WeightFunction>
 inline void MaterialNonLocal<spatial_dimension, WeightFunction>::onElementsRemoved(const Array<Element> & element_list,
 										   const ElementTypeMapArray<UInt> & new_numbering,
 										   __attribute__((unused)) const RemovedElementsEvent & event) {
   AKANTU_DEBUG_IN();
 
+  // Change the pairs in new global numbering
+  for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
+    GhostType ghost_type2 = (GhostType) gt;
+
+    PairList::iterator first_pair = pair_list[ghost_type2].begin();
+    PairList::iterator last_pair  = pair_list[ghost_type2].end();
+
+    //   Array<Real>::vector_iterator weight_it = pair_weight[ghost_type2]->begin(2);
+
+    for(;first_pair != last_pair; ++first_pair) {
+      QuadraturePoint & q1 = first_pair->first;
+      QuadraturePoint gq1  = this->convertToGlobalPoint(q1);
+      q1 = gq1;
+
+      if(new_numbering.exists(q1.type, q1.ghost_type)) {
+	UInt q1_new_el = new_numbering(q1.type, q1.ghost_type)(gq1.element);
+	AKANTU_DEBUG_ASSERT(q1_new_el != UInt(-1), "A local quadrature_point as been removed instead of just being renumbered");
+	q1.element = q1_new_el;
+      }
+
+
+      QuadraturePoint & q2 = first_pair->second;
+      QuadraturePoint gq2  = this->convertToGlobalPoint(q2);
+      q2 = gq2;
+
+      if(new_numbering.exists(q2.type, q2.ghost_type)) {
+	UInt q2_new_el = new_numbering(q2.type, q2.ghost_type)(gq2.element);
+	AKANTU_DEBUG_ASSERT(q2_new_el != UInt(-1), "A local quadrature_point as been removed instead of just being renumbered");
+	q2.element = q2_new_el;
+      }
+    }
+  }
+
+
+  // Change the material numbering
   Material::onElementsRemoved(element_list, new_numbering, event);
 
-  pair_type::const_iterator first_pair_types = existing_pairs[1].begin();
-  pair_type::const_iterator last_pair_types = existing_pairs[1].end();
+  // Change back the pairs to the new material numbering
+  for(UInt gt = _not_ghost; gt <= _ghost; ++gt) {
+    GhostType ghost_type2 = (GhostType) gt;
+
+    PairList::iterator first_pair = pair_list[ghost_type2].begin();
+    PairList::iterator last_pair  = pair_list[ghost_type2].end();
 
-  // Renumber element to keep
-  for (; first_pair_types != last_pair_types; ++first_pair_types) {
-    ElementType type2 = first_pair_types->second;
-    GhostType ghost_type2 = _ghost;
-    UInt nb_quad2 = this->model->getFEEngine().getNbQuadraturePoints(type2);
+    //   Array<Real>::vector_iterator weight_it = pair_weight[ghost_type2]->begin(2);
 
-    Array<UInt> & pairs =
-      pair_list(first_pair_types->first, _not_ghost)(first_pair_types->second, ghost_type2);
-    Array<UInt>::iterator< Vector<UInt> > first_pair = pairs.begin(2);
-    Array<UInt>::iterator< Vector<UInt> > last_pair  = pairs.end(2);
     for(;first_pair != last_pair; ++first_pair) {
-      UInt _q2 = (*first_pair)(1);
-      const Array<UInt> & renumbering = new_numbering(type2, ghost_type2);
-      UInt el = _q2 / nb_quad2;
-      UInt new_el = renumbering(el);
-      AKANTU_DEBUG_ASSERT(new_el != UInt(-1), "A local quad as been removed instead f just renumbered");
-      (*first_pair)(1) = new_el * nb_quad2 + _q2 % nb_quad2;
+      first_pair->first  = this->convertToLocalPoint(first_pair->first );
+      first_pair->second = this->convertToLocalPoint(first_pair->second);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
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 f3c0d5ad7..c55e1d2ec 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,144 +1,201 @@
 /**
  * @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>
 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);
 
-
-  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_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 f7611c93d..1cc27030a 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,100 +1,113 @@
 /**
  * @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 = "");
 
   /* ------------------------------------------------------------------------ */
   /* 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 0c744dfcf..0477f4fca 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,178 +1,301 @@
 /**
  * @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 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);
 
   const Real iso_hardening_t = previous_iso_hardening;
+  iso_hardening = iso_hardening_t;
+ 
   //Loop for correcting stress based on yield function
-  while ((sigma_tr_dev_eff - iso_hardening - this->sigma_y) > 0) {
+  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;
-    iso_hardening = iso_hardening_t + this->h * d_dp;
+    //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;
+      {
+	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
     }
   }
 }
 
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 f35c6e322..716b9db4e 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,187 @@
 /**
  * @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->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->finite_deformation            = false;
   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) {
   AKANTU_DEBUG_IN();
 
   if (type == "plastic") return getPlasticEnergy();
   else return MaterialElastic<spatial_dimension>::getEnergy(type);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 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));
   }
 
   AKANTU_DEBUG_OUT();
   return penergy;
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialPlastic<spatial_dimension>::computePotentialEnergy(ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   if(ghost_type != _not_ghost) return;
 
   Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin();
 
    Array<Real>::const_iterator< Matrix<Real> > inelastic_strain_it
      = this->inelastic_strain(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Matrix<Real> elastic_strain(spatial_dimension, spatial_dimension);
   elastic_strain.copy(grad_u);
   elastic_strain -= *inelastic_strain_it;
 
   MaterialElastic<spatial_dimension>::computePotentialEnergyOnQuad(elastic_strain, sigma, *epot);
 
   ++epot;
   ++inelastic_strain_it;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void MaterialPlastic<spatial_dimension>::updateEnergies(ElementType el_type,
                                                         GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MaterialElastic<spatial_dimension>::updateEnergies(el_type, ghost_type);
 
   Array<Real>::iterator<> pe_it =
     this->plastic_energy(el_type, ghost_type).begin();
 
   Array<Real>::iterator<> wp_it =
     this->d_plastic_energy(el_type, ghost_type).begin();
 
   Array<Real>::iterator< Matrix<Real> > inelastic_strain_it =
     this->inelastic_strain(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::iterator< Matrix<Real> > previous_inelastic_strain_it =
     this->inelastic_strain.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
   Array<Real>::matrix_iterator previous_sigma =
     this->stress.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension);
 
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type);
 
   Matrix<Real> delta_strain_it(*inelastic_strain_it);
   delta_strain_it -= *previous_inelastic_strain_it;
 
   Matrix<Real> sigma_h(sigma);
   sigma_h += *previous_sigma;
 
   *wp_it = .5 * sigma_h.doubleDot(delta_strain_it);
 
   *pe_it += *wp_it;
 
   ++pe_it;
   ++wp_it;
   ++inelastic_strain_it;
   ++previous_inelastic_strain_it;
   ++previous_sigma;
 
   MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
 
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 INSTANSIATE_MATERIAL(MaterialPlastic);
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/materials/weight_function.hh b/src/model/solid_mechanics/materials/weight_function.hh
index 224825d2f..2b22ac394 100644
--- a/src/model/solid_mechanics/materials/weight_function.hh
+++ b/src/model/solid_mechanics/materials/weight_function.hh
@@ -1,398 +1,369 @@
 /**
  * @file   weight_function.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Cyprien Wolff <cyprien.wolff@epfl.ch>
  *
  * @date creation: Fri Apr 13 2012
  * @date last modification: Thu Jun 05 2014
  *
  * @brief  Weight functions for non local 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 "aka_common.hh"
 #include "aka_types.hh"
 #include "solid_mechanics_model.hh"
 #include "parsable.hh"
 #include <cmath>
 #if defined(AKANTU_DEBUG_TOOLS)
 #include "aka_debug_tools.hh"
 #include <string>
 #endif
 
 /* -------------------------------------------------------------------------- */
 #include <vector>
 
 
 #ifndef __AKANTU_WEIGHT_FUNCTION_HH__
 #define __AKANTU_WEIGHT_FUNCTION_HH__
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /*  Normal weight function                                                    */
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 class BaseWeightFunction : public Parsable {
 public:
   BaseWeightFunction(Material & material, const std::string & type = "base") :
     Parsable(_st_non_local, "weight_function:" + type), material(material), type(type) {
     this->registerParam("radius"       , R             , 100.,
 			_pat_parsable | _pat_readable  , "Non local radius");
     this->registerParam("update_rate"  , update_rate, 0U  ,
 			_pat_parsmod, "Update frequency");
   }
 
   virtual ~BaseWeightFunction() {}
 
   virtual void init() { R2 = R * R; };
 
   virtual void updateInternals(__attribute__((unused)) const ElementTypeMapArray<Real> & quadrature_points_coordinates) {};
 
   /* ------------------------------------------------------------------------ */
   inline void setRadius(Real radius) { R = radius; R2 = R * R; }
 
   /* ------------------------------------------------------------------------ */
   inline void selectType(__attribute__((unused)) ElementType type1,
                          __attribute__((unused)) GhostType   ghost_type1,
                          __attribute__((unused)) ElementType type2,
                          __attribute__((unused)) GhostType   ghost_type2) {
   }
 
   /* ------------------------------------------------------------------------ */
   inline Real operator()(Real r,
-                         __attribute__((unused)) QuadraturePoint & q1,
-                         __attribute__((unused)) QuadraturePoint & q2) {
+                         const __attribute__((unused)) QuadraturePoint & q1,
+                         const __attribute__((unused)) QuadraturePoint & q2) {
     Real w = 0;
     if(r <= R) {
       Real alpha = (1. - r*r / R2);
       w = alpha * alpha;
       // *weight = 1 - sqrt(r / radius);
     }
     return w;
   }
 
   void printself(std::ostream & stream, int indent) const {
     std::string space;
     for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
     stream << space << "WeightFunction " << type << " [" << std::endl;
     Parsable::printself(stream, indent);
     stream << space << "]" << std::endl;
   }
 
 public:
   Real getRadius() { return R; }
   UInt getUpdateRate() { return update_rate; }
 
 public:
   virtual UInt getNbDataForElements(__attribute__((unused)) const Array<Element> & elements,
                                     __attribute__((unused)) SynchronizationTag tag) const {
     return 0;
   }
 
   virtual inline void packElementData(__attribute__((unused)) CommunicationBuffer & buffer,
                                       __attribute__((unused)) const Array<Element> & elements,
                                       __attribute__((unused)) SynchronizationTag tag) const {}
 
   virtual inline void unpackElementData(__attribute__((unused)) CommunicationBuffer & buffer,
                                         __attribute__((unused)) const Array<Element> & elements,
                                         __attribute__((unused)) SynchronizationTag tag) {}
 protected:
   Material & material;
 
   Real R;
   Real R2;
 
   UInt update_rate;
 
   const std::string type;
 };
 
 /* -------------------------------------------------------------------------- */
 /*  Damage weight function                                                    */
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 class DamagedWeightFunction : public BaseWeightFunction<spatial_dimension> {
 public:
   DamagedWeightFunction(Material & material) : BaseWeightFunction<spatial_dimension>(material, "damaged") {}
 
   inline void selectType(__attribute__((unused)) ElementType type1,
                          __attribute__((unused)) GhostType ghost_type1,
                          ElementType type2,
                          GhostType ghost_type2) {
     selected_damage = &this->material.getArray("damage", type2, ghost_type2);
   }
 
-  inline Real operator()(Real r, __attribute__((unused)) QuadraturePoint & q1, QuadraturePoint & q2) {
+  inline Real operator()(Real r,
+			 const __attribute__((unused)) QuadraturePoint & q1,
+			 const QuadraturePoint & q2) {
     UInt quad = q2.global_num;
     Real D = (*selected_damage)(quad);
     Real Radius_t = 0;
     Real Radius_init = this->R2;
 
 //    if(D <= 0.5)
 //      {
 //	Radius_t = 2*D*Radius_init;
 //      }
 //    else
 //      {
 //	Radius_t = 2*Radius_init*(1-D);
 //      }
 //
 
 	Radius_t = Radius_init*(1-D);
 
 
     Radius_init *= Radius_init;
     Radius_t *= Radius_t;
 
     if(Radius_t < Math::getTolerance()) {
       Radius_t = 0.001*Radius_init;
     }
 
     Real expb = (2*std::log(0.51))/(std::log(1.0-0.49*Radius_t/Radius_init));
     Int  expb_floor=std::floor(expb);
     Real b = expb_floor + expb_floor%2;
     Real alpha = std::max(0., 1. - r*r / Radius_init);
     Real w = std::pow(alpha,b);
     return w;
   }
 
 private:
   const Array<Real> * selected_damage;
 };
 
 /* -------------------------------------------------------------------------- */
 /*  Remove damaged weight function                                            */
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 class RemoveDamagedWeightFunction : public BaseWeightFunction<spatial_dimension> {
 public:
   RemoveDamagedWeightFunction(Material & material) : BaseWeightFunction<spatial_dimension>(material, "remove_damaged") {
     this->registerParam("damage_limit", this->damage_limit, 1., _pat_parsable, "Damage Threshold");
   }
 
   inline void selectType(__attribute__((unused)) ElementType type1,
                          __attribute__((unused)) GhostType ghost_type1,
                          ElementType type2,
                          GhostType ghost_type2) {
     selected_damage = &this->material.getArray("damage", type2, ghost_type2);
   }
 
-  inline Real operator()(Real r, __attribute__((unused)) QuadraturePoint & q1, QuadraturePoint & q2) {
+  inline Real operator()(Real r,
+			 const __attribute__((unused)) QuadraturePoint & q1,
+			 const QuadraturePoint & q2) {
     UInt quad = q2.global_num;
 
     if(q1 == q2) return 1.;
 
     Real D = (*selected_damage)(quad);
     Real w = 0.;
     if(D < damage_limit) {
       Real alpha = std::max(0., 1. - r*r / this->R2);
       w = alpha * alpha;
     }
     return w;
   }
 
 
   virtual UInt getNbDataForElements(const Array<Element> & elements,
                                     SynchronizationTag tag) const {
     if(tag == _gst_mnl_weight)
       return this->material.getModel().getNbQuadraturePoints(elements) * sizeof(Real);
 
     return 0;
   }
 
   virtual inline void packElementData(CommunicationBuffer & buffer,
                                       const Array<Element> & elements,
                                       SynchronizationTag tag) const {
     if(tag == _gst_mnl_weight) {
       ElementTypeMapArray<Real> & damage = this->material.getInternal("damage");
       this->material.packElementDataHelper(damage,
                                            buffer,
                                            elements);
-#if defined(AKANTU_DEBUG_TOOLS)
-#if defined(AKANTU_CORE_CXX11)
-      debug::element_manager.print(debug::_dm_material,
-                                   [&elements, &mat](const Element & el)->std::string {
-                                     std::stringstream out;
-                                     UInt pos = elements.find(el);
-                                     if(pos != UInt(-1)) {
-                                       Real d = mat.getArray("damage", el.type, el.ghost_type)(el.element);
-                                       if(d > 0.3)
-                                         out << " damage sent: " << d;
-                                     }
-                                     return out.str();
-                                   });
-#else
-      debug::element_manager.printData(debug::_dm_material, "RemoveDamagedWeightFunction: packElementData",
-                                       mat.getDamage(), mat.getElementFilter());
-#endif
-#endif
     }
   }
 
   virtual inline void unpackElementData(CommunicationBuffer & buffer,
                                         const Array<Element> & elements,
                                         SynchronizationTag tag) {
     if(tag == _gst_mnl_weight) {
       ElementTypeMapArray<Real> & damage = this->material.getInternal("damage");
       this->material.unpackElementDataHelper(damage,
                                              buffer,
                                              elements);
-#if defined(AKANTU_DEBUG_TOOLS)
-#if defined(AKANTU_CORE_CXX11)
-      debug::element_manager.print(debug::_dm_material,
-                                   [&elements, &mat](const Element & el)->std::string {
-                                     std::stringstream out;
-                                     UInt pos = elements.find(el);
-                                     if(pos != UInt(-1)) {
-                                       Real d = mat.getArray("damage", el.type, el.ghost_type)(el.element);
-                                       if(d > 0.3)
-                                         out << " damage recv: " << d;
-                                     }
-                                     return out.str();
-                                   });
-#else
-      debug::element_manager.printData(debug::_dm_material, "RemoveDamagedWeightFunction: unpackElementData",
-                                       mat.getDamage(), mat.getElementFilter());
-#endif
-#endif
-
     }
   }
 
 
 private:
   /// limit at which a point is considered as complitely broken
   Real damage_limit;
 
   /// internal pointer to the current damage vector
   const Array<Real> * selected_damage;
 };
 /* -------------------------------------------------------------------------- */
 /* Remove damaged with damage rate weight function                                             */
 /* -------------------------------------------------------------------------- */
 
 template<UInt spatial_dimension>
 class RemoveDamagedWithDamageRateWeightFunction : public BaseWeightFunction<spatial_dimension> {
 public:
   RemoveDamagedWithDamageRateWeightFunction(Material & material) : BaseWeightFunction<spatial_dimension>(material, "remove_damage_with_damage_rate") {
     this->registerParam("damage_limit", this->damage_limit_with_damage_rate, 1, _pat_parsable, "Damage Threshold");
   }
 
   inline void selectType(__attribute__((unused)) ElementType type1,
                          __attribute__((unused)) GhostType ghost_type1,
                          ElementType type2,
                          GhostType ghost_type2) {
     selected_damage_with_damage_rate = &(this->material.getArray("damage",type2, ghost_type2));
     selected_damage_rate_with_damage_rate = &(this->material.getArray("damage-rate",type2, ghost_type2));
   }
 
-  inline Real operator()(Real r, __attribute__((unused)) QuadraturePoint & q1, QuadraturePoint & q2) {
+  inline Real operator()(Real r,
+			 const __attribute__((unused)) QuadraturePoint & q1,
+			 const QuadraturePoint & q2) {
     UInt quad = q2.global_num;
 
     if(q1.global_num == quad) return 1.;
 
     Real D = (*selected_damage_with_damage_rate)(quad);
     Real w = 0.;
     Real alphaexp = 1.;
     Real betaexp = 2.;
     if(D < damage_limit_with_damage_rate) {
       Real alpha = std::max(0., 1. - pow((r*r / this->R2),alphaexp));
       w = pow(alpha, betaexp);
     }
 
     return w;
   }
 
 private:
   /// limit at which a point is considered as complitely broken
   Real damage_limit_with_damage_rate;
 
   /// internal pointer to the current damage vector
   const Array<Real> * selected_damage_with_damage_rate;
 
   /// internal pointer to the current damage rate vector
   const Array<Real> * selected_damage_rate_with_damage_rate;
 };
 
 /* -------------------------------------------------------------------------- */
 /* Stress Based Weight                                                        */
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 class StressBasedWeightFunction : public BaseWeightFunction<spatial_dimension> {
 public:
   StressBasedWeightFunction(Material & material);
 
   void init();
 
   virtual void updateInternals(__attribute__((unused)) const ElementTypeMapArray<Real> & quadrature_points_coordinates) {
     updatePrincipalStress(_not_ghost);
     updatePrincipalStress(_ghost);
   };
 
   void updatePrincipalStress(GhostType ghost_type);
 
   inline void updateQuadraturePointsCoordinates(ElementTypeMapArray<Real> & quadrature_points_coordinates);
 
   inline void selectType(ElementType type1, GhostType ghost_type1,
                          ElementType type2, GhostType ghost_type2);
 
-  inline Real operator()(Real r, QuadraturePoint & q1, QuadraturePoint & q2);
+  inline Real operator()(Real r,
+			 const QuadraturePoint & q1,
+			 const QuadraturePoint & q2);
 
   inline Real computeRhoSquare(Real r,
                                Vector<Real> & eigs,
                                Matrix<Real> & eigenvects,
                                Vector<Real> & x_s);
 
 private:
   Real ft;
 
   InternalField<Real> stress_diag;
   Array<Real> * selected_stress_diag;
   InternalField<Real> stress_base;
   Array<Real> * selected_stress_base;
 
 
   //  InternalField<Real> quadrature_points_coordinates;
   Array<Real> * selected_position_1;
   Array<Real> * selected_position_2;
 
   InternalField<Real> characteristic_size;
   Array<Real> * selected_characteristic_size;
 };
 
 
 template<UInt spatial_dimension>
 inline std::ostream & operator <<(std::ostream & stream,
                                   const BaseWeightFunction<spatial_dimension> & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 
 #include "weight_function_tmpl.hh"
 
 __END_AKANTU__
 
 #endif /* __AKANTU_WEIGHT_FUNCTION_HH__ */
diff --git a/src/model/solid_mechanics/materials/weight_function_tmpl.hh b/src/model/solid_mechanics/materials/weight_function_tmpl.hh
index 516b3b5e4..92dc9dabd 100644
--- a/src/model/solid_mechanics/materials/weight_function_tmpl.hh
+++ b/src/model/solid_mechanics/materials/weight_function_tmpl.hh
@@ -1,279 +1,279 @@
 /**
  * @file   weight_function_tmpl.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Apr 13 2012
  * @date last modification: Thu Jun 05 2014
  *
  * @brief  implementation of the weight function classes
  *
  * @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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 /* Stress based weight function                                               */
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 StressBasedWeightFunction<spatial_dimension>::StressBasedWeightFunction(Material & material) :
   BaseWeightFunction<spatial_dimension>(material, "stress_based"),
   stress_diag("stress_diag", material), selected_stress_diag(NULL),
   stress_base("stress_base", material), selected_stress_base(NULL),
   characteristic_size("lc", material),  selected_characteristic_size(NULL) {
 
   this->registerParam("ft", this->ft, 0., _pat_parsable, "Tensile strength");
   stress_diag.initialize(spatial_dimension);
   stress_base.initialize(spatial_dimension * spatial_dimension);
   characteristic_size.initialize(1);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void StressBasedWeightFunction<spatial_dimension>::init() {
   const Mesh & mesh = this->material.getModel().getFEEngine().getMesh();
   for (UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = GhostType(g);
     Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt);
     Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, gt);
     for(; it != last_type; ++it) {
       UInt nb_quadrature_points =
 	this->material.getModel().getFEEngine().getNbQuadraturePoints(*it, gt);
       const Array<UInt> & element_filter = this->material.getElementFilter(*it, gt);
       UInt nb_element = element_filter.getSize();
 
       Array<Real> ones(nb_element*nb_quadrature_points, 1, 1.);
       Array<Real> & lc = characteristic_size(*it, gt);
       this->material.getModel().getFEEngine().integrateOnQuadraturePoints(ones,
 								     lc,
 								     1,
 								     *it,
 								     gt,
 								     element_filter);
 
       for (UInt q = 0;  q < nb_quadrature_points * nb_element; q++) {
 	lc(q) = pow(lc(q), 1./ Real(spatial_dimension));
       }
     }
   }
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 void StressBasedWeightFunction<spatial_dimension>::updatePrincipalStress(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   const Mesh & mesh = this->material.getModel().getFEEngine().getMesh();
 
   Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type);
   for(; it != last_type; ++it) {
     Array<Real>::const_matrix_iterator sigma =
       this->material.getStress(*it, ghost_type).begin(spatial_dimension, spatial_dimension);
     Array<Real>::vector_iterator eigenvalues =
       stress_diag(*it, ghost_type).begin(spatial_dimension);
     Array<Real>::vector_iterator eigenvalues_end =
       stress_diag(*it, ghost_type).end(spatial_dimension);
     Array<Real>::matrix_iterator eigenvector =
       stress_base(*it, ghost_type).begin(spatial_dimension, spatial_dimension);
 
 #ifndef __trick__
     Array<Real>::iterator<Real> cl = characteristic_size(*it, ghost_type).begin();
 #endif
     UInt q = 0;
     for(;eigenvalues != eigenvalues_end; ++sigma, ++eigenvalues, ++eigenvector, ++cl, ++q) {
       sigma->eig(*eigenvalues, *eigenvector);
       *eigenvalues /= ft;
 #ifndef __trick__
       // specify a lower bound for principal stress based on the size of the element
       for (UInt i = 0; i < spatial_dimension; ++i) {
         (*eigenvalues)(i) = std::max(*cl / this->R, (*eigenvalues)(i));
       }
 #endif
     }
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 inline void StressBasedWeightFunction<spatial_dimension>::selectType(ElementType type1,
 								     GhostType ghost_type1,
 								     ElementType type2,
 								     GhostType ghost_type2) {
   selected_stress_diag = &stress_diag(type2, ghost_type2);
   selected_stress_base = &stress_base(type2, ghost_type2);
 
   selected_characteristic_size = &characteristic_size(type1, ghost_type1);
 }
 
 /* -------------------------------------------------------------------------- */
 template<UInt spatial_dimension>
 inline Real StressBasedWeightFunction<spatial_dimension>::operator()(Real r,
-								     QuadraturePoint & q1,
-								     QuadraturePoint & q2) {
+								     const QuadraturePoint & q1,
+								     const QuadraturePoint & q2) {
   Real zero = std::numeric_limits<Real>::epsilon();
 
   if(r < zero) return 1.; // means x and s are the same points
 
   const Vector<Real> & x = q1.getPosition();
   const Vector<Real> & s = q2.getPosition();
 
   Vector<Real> eigs =
     selected_stress_diag->begin(spatial_dimension)[q2.global_num];
 
   Matrix<Real> eigenvects =
     selected_stress_base->begin(spatial_dimension, spatial_dimension)[q2.global_num];
 
   Real min_rho_lc = selected_characteristic_size->begin()[q1.global_num];
 
   Vector<Real> x_s(spatial_dimension);
   x_s  = x;
   x_s -= s;
 
   Real rho_2 = computeRhoSquare(r, eigs, eigenvects, x_s);
 
   Real rho_lc_2 = std::max(this->R2 * rho_2, min_rho_lc*min_rho_lc);
 
   // Real w = std::max(0., 1. - r*r / rho_lc_2);
   // w = w*w;
   Real w = exp(- 2*2*r*r / rho_lc_2);
   return w;
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline Real StressBasedWeightFunction<1>::computeRhoSquare(__attribute__ ((unused)) Real r,
 							   Vector<Real> & eigs,
 							   __attribute__ ((unused)) Matrix<Real> & eigenvects,
 							   __attribute__ ((unused)) Vector<Real> & x_s) {
   return eigs[0];
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline Real StressBasedWeightFunction<2>::computeRhoSquare(__attribute__ ((unused)) Real r,
 							   Vector<Real> & eigs,
 							   Matrix<Real> & eigenvects,
 							   Vector<Real> & x_s) {
   Vector<Real> u1(eigenvects.storage(), 2);
   Real cos_t = x_s.dot(u1) / (x_s.norm() * u1.norm());
 
   Real cos_t_2;
   Real sin_t_2;
 
   Real sigma1_2 = eigs[0]*eigs[0];
   Real sigma2_2 = eigs[1]*eigs[1];
 
 #ifdef __trick__
   Real zero = std::numeric_limits<Real>::epsilon();
   if(std::abs(cos_t) < zero) {
     cos_t_2 = 0;
     sin_t_2 = 1;
   } else {
     cos_t_2 = cos_t * cos_t;
     sin_t_2 = (1 - cos_t_2);
   }
 
   Real rhop1 = std::max(0., cos_t_2 / sigma1_2);
   Real rhop2 = std::max(0., sin_t_2 / sigma2_2);
 #else
   cos_t_2 = cos_t * cos_t;
   sin_t_2 = (1 - cos_t_2);
 
   Real rhop1 = cos_t_2 / sigma1_2;
   Real rhop2 = sin_t_2 / sigma2_2;
 #endif
 
   return 1./ (rhop1 + rhop2);
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 inline Real StressBasedWeightFunction<3>::computeRhoSquare(Real r,
 							   Vector<Real> & eigs,
 							   Matrix<Real> & eigenvects,
 							   Vector<Real> & x_s) {
   Vector<Real> u1(eigenvects.storage() + 0*3, 3);
 //Vector<Real> u2(eigenvects.storage() + 1*3, 3);
   Vector<Real> u3(eigenvects.storage() + 2*3, 3);
 
   Real zero = std::numeric_limits<Real>::epsilon();
 
   Vector<Real> tmp(3);
   tmp.crossProduct(x_s, u3);
 
   Vector<Real> u3_C_x_s_C_u3(3);
   u3_C_x_s_C_u3.crossProduct(u3, tmp);
 
   Real norm_u3_C_x_s_C_u3 = u3_C_x_s_C_u3.norm();
   Real cos_t = 0.;
   if(std::abs(norm_u3_C_x_s_C_u3) > zero) {
     Real inv_norm_u3_C_x_s_C_u3 = 1. / norm_u3_C_x_s_C_u3;
     cos_t = u1.dot(u3_C_x_s_C_u3) * inv_norm_u3_C_x_s_C_u3;
   }
 
   Real cos_p = u3.dot(x_s) / r;
 
   Real cos_t_2;
   Real sin_t_2;
   Real cos_p_2;
   Real sin_p_2;
 
   Real sigma1_2 = eigs[0]*eigs[0];
   Real sigma2_2 = eigs[1]*eigs[1];
   Real sigma3_2 = eigs[2]*eigs[2];
 
 #ifdef __trick__
   if(std::abs(cos_t) < zero) {
     cos_t_2 = 0;
     sin_t_2 = 1;
   } else {
     cos_t_2 = cos_t * cos_t;
     sin_t_2 = (1 - cos_t_2);
   }
 
   if(std::abs(cos_p) < zero) {
     cos_p_2 = 0;
     sin_p_2 = 1;
   } else {
     cos_p_2 = cos_p * cos_p;
     sin_p_2 = (1 - cos_p_2);
   }
 
   Real rhop1 = std::max(0., sin_p_2 * cos_t_2 / sigma1_2);
   Real rhop2 = std::max(0., sin_p_2 * sin_t_2 / sigma2_2);
   Real rhop3 = std::max(0., cos_p_2 / sigma3_2);
 #else
   cos_t_2 = cos_t * cos_t;
   sin_t_2 = (1 - cos_t_2);
 
   cos_p_2 = cos_p * cos_p;
   sin_p_2 = (1 - cos_p_2);
 
   Real rhop1 = sin_p_2 * cos_t_2 / sigma1_2;
   Real rhop2 = sin_p_2 * sin_t_2 / sigma2_2;
   Real rhop3 = cos_p_2 / sigma3_2;
 #endif
 
   return 1./ (rhop1 + rhop2 + rhop3);
 }
diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc
index 43eb5e79e..ed785385a 100644
--- a/src/model/solid_mechanics/solid_mechanics_model.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model.cc
@@ -1,1793 +1,1796 @@
 /**
  * @file   solid_mechanics_model.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author David Simon Kammer <david.kammer@epfl.ch>
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Tue Jul 27 2010
  * @date last modification: Fri Sep 19 2014
  *
  * @brief  Implementation of the SolidMechanicsModel 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 "aka_math.hh"
 #include "aka_common.hh"
 #include "solid_mechanics_model.hh"
 #include "group_manager_inline_impl.cc"
 #include "dumpable_inline_impl.hh"
 #include "integration_scheme_2nd_order.hh"
 #include "element_group.hh"
 
 #include "static_communicator.hh"
 
 #include "dof_synchronizer.hh"
 #include "element_group.hh"
 
 #include <cmath>
 
 #ifdef AKANTU_USE_MUMPS
 #include "solver_mumps.hh"
 #endif
 
 #ifdef AKANTU_USE_PETSC
 #include "solver_petsc.hh"
 #include "petsc_matrix.hh"
 #endif
 
 #ifdef AKANTU_USE_IOHELPER
 #  include "dumper_field.hh"
 #  include "dumper_paraview.hh"
 #  include "dumper_homogenizing_field.hh"
 #  include "dumper_material_internal_field.hh"
 #  include "dumper_elemental_field.hh"
 #  include "dumper_material_padders.hh"
 #  include "dumper_element_partition.hh"
 #  include "dumper_iohelper.hh"
 #endif
 
 /* -------------------------------------------------------------------------- */
 __BEGIN_AKANTU__
 
 const SolidMechanicsModelOptions default_solid_mechanics_model_options(_explicit_lumped_mass, false);
 
 /* -------------------------------------------------------------------------- */
 /**
  * A solid mechanics model need a mesh  and a dimension to be created. the model
  * by it  self can not  do a lot,  the good init  functions should be  called in
  * order to configure the model depending on what we want to do.
  *
  * @param  mesh mesh  representing  the model  we  want to  simulate
  * @param dim spatial  dimension of the problem, if dim =  0 (default value) the
  * dimension of the problem is assumed to be the on of the mesh
  * @param id an id to identify the model
  */
 SolidMechanicsModel::SolidMechanicsModel(Mesh & mesh,
 					 UInt dim,
 					 const ID & id,
 					 const MemoryID & memory_id) :
   Model(mesh, dim, id, memory_id),
   BoundaryCondition<SolidMechanicsModel>(),
   time_step(NAN), f_m2a(1.0),
   mass_matrix(NULL),
   velocity_damping_matrix(NULL),
   stiffness_matrix(NULL),
   jacobian_matrix(NULL),
-  element_index_by_material("element index by material", id),
-  material_selector(new DefaultMaterialSelector(element_index_by_material)),
+  material_index("material index", id),
+  material_local_numbering("material local numbering", id),
+  material_selector(new DefaultMaterialSelector(material_index)),
   is_default_material_selector(true),
   integrator(NULL),
   increment_flag(false), solver(NULL),
   synch_parallel(NULL),
   are_materials_instantiated(false) {
 
   AKANTU_DEBUG_IN();
 
   createSynchronizerRegistry(this);
 
   registerFEEngineObject<MyFEEngineType>("SolidMechanicsFEEngine", mesh, spatial_dimension);
 
   this->displacement = NULL;
   this->mass         = NULL;
   this->velocity     = NULL;
   this->acceleration = NULL;
   this->force        = NULL;
   this->residual     = NULL;
   this->blocked_dofs = NULL;
 
   this->increment    = NULL;
   this->increment_acceleration = NULL;
 
   this->dof_synchronizer = NULL;
 
   this->previous_displacement = NULL;
 
   materials.clear();
 
   mesh.registerEventHandler(*this);
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.registerDumper<DumperParaview>("paraview_all", id, true);
   this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_regular);
 #endif
   AKANTU_DEBUG_OUT();
 }
 
 
 
 /* -------------------------------------------------------------------------- */
 SolidMechanicsModel::~SolidMechanicsModel() {
   AKANTU_DEBUG_IN();
 
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     delete *mat_it;
   }
 
   materials.clear();
 
   delete integrator;
 
   delete solver;
   delete mass_matrix;
   delete velocity_damping_matrix;
 
   if(stiffness_matrix && stiffness_matrix != jacobian_matrix)
     delete stiffness_matrix;
 
   delete jacobian_matrix;
 
   delete synch_parallel;
 
   if(is_default_material_selector) {
     delete material_selector;
     material_selector = NULL;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 void SolidMechanicsModel::setTimeStep(Real time_step) {
   this->time_step = time_step;
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.getDumper().setTimeStep(time_step);
 #endif
 }
 
 /* -------------------------------------------------------------------------- */
 /* Initialisation                                                             */
 /* -------------------------------------------------------------------------- */
 /**
  * This function groups  many of the initialization in on  function. For most of
  * basics  case the  function should  be  enough. The  functions initialize  the
  * model, the internal  vectors, set them to 0, and  depending on the parameters
  * it also initialize the explicit or implicit solver.
  *
  * @param material_file the  file containing the materials to  use
  * @param method the analysis method wanted.  See the akantu::AnalysisMethod for
  * the different possibilities
  */
 void SolidMechanicsModel::initFull(const ModelOptions & options) {
   Model::initFull(options);
 
   const SolidMechanicsModelOptions & smm_options =
     dynamic_cast<const SolidMechanicsModelOptions &>(options);
 
   method = smm_options.analysis_method;
 
   // initialize the vectors
   initArrays();
 
   // set the initial condition to 0
   force->clear();
   velocity->clear();
   acceleration->clear();
   displacement->clear();
 
   // initialize pcb
   if(pbc_pair.size()!=0)
     initPBC();
 
   // initialize the time integration schemes
   switch(method) {
   case _explicit_lumped_mass:
     initExplicit();
     break;
   case _explicit_consistent_mass:
     initSolver();
     initExplicit();
     break;
   case _implicit_dynamic:
     initImplicit(true);
     break;
   case _static:
     initImplicit(false);
     break;
   default:
     AKANTU_EXCEPTION("analysis method not recognised by SolidMechanicsModel");
     break;
   }
 
   // initialize the materials
   if(this->parser->getLastParsedFile() != "") {
     instantiateMaterials();
   }
 
   if(!smm_options.no_init_materials) {
     initMaterials();
   }
 
   if(increment_flag)
     initBC(*this, *displacement, *increment, *force);
   else
     initBC(*this, *displacement, *force);
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initParallel(MeshPartition * partition,
 				       DataAccessor * data_accessor) {
   AKANTU_DEBUG_IN();
 
   if (data_accessor == NULL) data_accessor = this;
   synch_parallel = &createParallelSynch(partition,data_accessor);
 
   synch_registry->registerSynchronizer(*synch_parallel, _gst_material_id);
   synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_mass);
   synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_stress);
   synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_boundary);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initFEEngineBoundary() {
   FEEngine & fem_boundary = getFEEngineBoundary();
   fem_boundary.initShapeFunctions(_not_ghost);
   fem_boundary.initShapeFunctions(_ghost);
 
   fem_boundary.computeNormalsOnControlPoints(_not_ghost);
   fem_boundary.computeNormalsOnControlPoints(_ghost);
 }
 
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initExplicit(AnalysisMethod analysis_method) {
   AKANTU_DEBUG_IN();
 
   //in case of switch from implicit to explicit
   if(!this->isExplicit())
     method = analysis_method;
 
   if (integrator) delete integrator;
   integrator = new CentralDifference();
 
   UInt nb_nodes = acceleration->getSize();
   UInt nb_degree_of_freedom = acceleration->getNbComponent();
 
   std::stringstream sstr; sstr << id << ":increment_acceleration";
   increment_acceleration = &(alloc<Real>(sstr.str(), nb_nodes, nb_degree_of_freedom, Real()));
 
   AKANTU_DEBUG_OUT();
 }
 
 void SolidMechanicsModel::initArraysPreviousDisplacment() {
   AKANTU_DEBUG_IN();
 
   SolidMechanicsModel::setIncrementFlagOn();
   UInt nb_nodes = mesh.getNbNodes();
   std::stringstream sstr_disp_t;
   sstr_disp_t << id << ":previous_displacement";
   previous_displacement = &(alloc<Real > (sstr_disp_t.str(), nb_nodes, spatial_dimension, 0.));
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Allocate all the needed vectors. By  default their are not necessarily set to
  * 0
  *
  */
 void SolidMechanicsModel::initArrays() {
   AKANTU_DEBUG_IN();
 
   UInt nb_nodes = mesh.getNbNodes();
   std::stringstream sstr_disp; sstr_disp << id << ":displacement";
   //  std::stringstream sstr_mass; sstr_mass << id << ":mass";
   std::stringstream sstr_velo; sstr_velo << id << ":velocity";
   std::stringstream sstr_acce; sstr_acce << id << ":acceleration";
   std::stringstream sstr_forc; sstr_forc << id << ":force";
   std::stringstream sstr_resi; sstr_resi << id << ":residual";
   std::stringstream sstr_boun; sstr_boun << id << ":blocked_dofs";
 
   displacement = &(alloc<Real>(sstr_disp.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE));
   //  mass         = &(alloc<Real>(sstr_mass.str(), nb_nodes, spatial_dimension, 0));
   velocity     = &(alloc<Real>(sstr_velo.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE));
   acceleration = &(alloc<Real>(sstr_acce.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE));
   force        = &(alloc<Real>(sstr_forc.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE));
   residual     = &(alloc<Real>(sstr_resi.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE));
   blocked_dofs = &(alloc<bool>(sstr_boun.str(), nb_nodes, spatial_dimension, false));
 
   std::stringstream sstr_curp; sstr_curp << id << ":current_position";
   current_position = &(alloc<Real>(sstr_curp.str(), 0, spatial_dimension, REAL_INIT_VALUE));
 
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
     Mesh::type_iterator it  = mesh.firstType(spatial_dimension, gt, _ek_not_defined);
     Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, _ek_not_defined);
     for(; it != end; ++it) {
       UInt nb_element = mesh.getNbElement(*it, gt);
-      element_index_by_material.alloc(nb_element, 2, *it, gt);
+      material_index.alloc(nb_element, 1, *it, gt);
+      material_local_numbering.alloc(nb_element, 1, *it, gt);
     }
   }
 
   dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension);
   dof_synchronizer->initLocalDOFEquationNumbers();
   dof_synchronizer->initGlobalDOFEquationNumbers();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Initialize the model,basically it  pre-compute the shapes, shapes derivatives
  * and jacobian
  *
  */
 void SolidMechanicsModel::initModel() {
   /// \todo add  the current position  as a parameter to  initShapeFunctions for
   /// large deformation
   getFEEngine().initShapeFunctions(_not_ghost);
   getFEEngine().initShapeFunctions(_ghost);
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initPBC() {
   Model::initPBC();
   registerPBCSynchronizer();
 
   // as long as there are ones on the diagonal of the matrix, we can put boudandary true for slaves
   std::map<UInt, UInt>::iterator it = pbc_pair.begin();
   std::map<UInt, UInt>::iterator end = pbc_pair.end();
   UInt dim = mesh.getSpatialDimension();
   while(it != end) {
     for (UInt i=0; i<dim; ++i)
       (*blocked_dofs)((*it).first,i) = true;
     ++it;
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::registerPBCSynchronizer(){
   PBCSynchronizer * synch = new PBCSynchronizer(pbc_pair);
   synch_registry->registerSynchronizer(*synch, _gst_smm_uv);
   synch_registry->registerSynchronizer(*synch, _gst_smm_mass);
   synch_registry->registerSynchronizer(*synch, _gst_smm_res);
   synch_registry->registerSynchronizer(*synch, _gst_for_dump);
   changeLocalEquationNumberForPBC(pbc_pair, mesh.getSpatialDimension());
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateCurrentPosition() {
   AKANTU_DEBUG_IN();
   UInt nb_nodes = mesh.getNbNodes();
 
   current_position->resize(nb_nodes);
   Real * current_position_val = current_position->storage();
   Real * position_val         = mesh.getNodes().storage();
   Real * displacement_val     = displacement->storage();
 
   /// compute current_position = initial_position + displacement
   memcpy(current_position_val, position_val, nb_nodes*spatial_dimension*sizeof(Real));
   for (UInt n = 0; n < nb_nodes*spatial_dimension; ++n) {
     *current_position_val++ += *displacement_val++;
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initializeUpdateResidualData() {
   AKANTU_DEBUG_IN();
   UInt nb_nodes = mesh.getNbNodes();
   residual->resize(nb_nodes);
 
   /// copy the forces in residual for boundary conditions
   memcpy(residual->storage(), force->storage(), nb_nodes*spatial_dimension*sizeof(Real));
 
   // start synchronization
   synch_registry->asynchronousSynchronize(_gst_smm_uv);
   synch_registry->waitEndSynchronize(_gst_smm_uv);
 
   updateCurrentPosition();
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* Explicit scheme                                                            */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 /**
  * This function compute  the second member of the motion  equation.  That is to
  * say the sum of forces @f$ r = F_{ext} - F_{int} @f$. @f$ F_{ext} @f$ is given
  * by the  user in  the force  vector, and @f$  F_{int} @f$  is computed  as @f$
  * F_{int} = \int_{\Omega} N \sigma d\Omega@f$
  *
  */
 void SolidMechanicsModel::updateResidual(bool need_initialize) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_INFO("Assemble the internal forces");
   // f = f_ext - f_int
 
   // f = f_ext
   if(need_initialize) initializeUpdateResidualData();
 
   AKANTU_DEBUG_INFO("Compute local stresses");
 
   std::vector<Material *>::iterator mat_it;
   for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     Material & mat = **mat_it;
     mat.computeAllStresses(_not_ghost);
   }
 
 #ifdef AKANTU_DAMAGE_NON_LOCAL
   /* ------------------------------------------------------------------------ */
   /* Computation of the non local part */
   synch_registry->asynchronousSynchronize(_gst_mnl_for_average);
   AKANTU_DEBUG_INFO("Compute non local stresses for local elements");
 
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     Material & mat = **mat_it;
     mat.computeAllNonLocalStresses(_not_ghost);
   }
 
 
   AKANTU_DEBUG_INFO("Wait distant non local stresses");
   synch_registry->waitEndSynchronize(_gst_mnl_for_average);
 
   AKANTU_DEBUG_INFO("Compute non local stresses for ghosts elements");
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     Material & mat = **mat_it;
     mat.computeAllNonLocalStresses(_ghost);
   }
 #endif
 
   /* ------------------------------------------------------------------------ */
   /* assembling the forces internal */
   // communicate the stress
   AKANTU_DEBUG_INFO("Send data for residual assembly");
   synch_registry->asynchronousSynchronize(_gst_smm_stress);
 
   AKANTU_DEBUG_INFO("Assemble residual for local elements");
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     Material & mat = **mat_it;
     mat.assembleResidual(_not_ghost);
   }
 
 
   AKANTU_DEBUG_INFO("Wait distant stresses");
   // finalize communications
   synch_registry->waitEndSynchronize(_gst_smm_stress);
 
   AKANTU_DEBUG_INFO("Assemble residual for ghost elements");
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     Material & mat = **mat_it;
     mat.assembleResidual(_ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::computeStresses() {
   if (isExplicit()) {
     // start synchronization
     synch_registry->asynchronousSynchronize(_gst_smm_uv);
     synch_registry->waitEndSynchronize(_gst_smm_uv);
 
     // compute stresses on all local elements for each materials
     std::vector<Material *>::iterator mat_it;
     for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
       Material & mat = **mat_it;
       mat.computeAllStresses(_not_ghost);
     }
 
     /* ------------------------------------------------------------------------ */
 #ifdef AKANTU_DAMAGE_NON_LOCAL
     /* Computation of the non local part */
     synch_registry->asynchronousSynchronize(_gst_mnl_for_average);
 
     for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
       Material & mat = **mat_it;
       mat.computeAllNonLocalStresses(_not_ghost);
     }
 
     synch_registry->waitEndSynchronize(_gst_mnl_for_average);
 
     for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
       Material & mat = **mat_it;
       mat.computeAllNonLocalStresses(_ghost);
     }
 #endif
   } else {
     std::vector<Material *>::iterator mat_it;
     for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
       Material & mat = **mat_it;
       mat.computeAllStressesFromTangentModuli(_not_ghost);
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateResidualInternal() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_INFO("Update the residual");
   // f = f_ext - f_int - Ma - Cv = r - Ma - Cv;
 
   if(method != _static) {
     // f -= Ma
     if(mass_matrix) {
       // if full mass_matrix
       Array<Real> * Ma = new Array<Real>(*acceleration, true, "Ma");
       *Ma *= *mass_matrix;
       /// \todo check unit conversion for implicit dynamics
       //      *Ma /= f_m2a
       *residual -= *Ma;
       delete Ma;
     } else if (mass) {
 
       // else lumped mass
       UInt nb_nodes = acceleration->getSize();
       UInt nb_degree_of_freedom = acceleration->getNbComponent();
 
       Real * mass_val     = mass->storage();
       Real * accel_val    = acceleration->storage();
       Real * res_val      = residual->storage();
       bool * blocked_dofs_val = blocked_dofs->storage();
 
       for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) {
 	if(!(*blocked_dofs_val)) {
 	  *res_val -= *accel_val * *mass_val /f_m2a;
 	}
 	blocked_dofs_val++;
 	res_val++;
 	mass_val++;
 	accel_val++;
       }
     } else {
       AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix.");
     }
 
     // f -= Cv
     if(velocity_damping_matrix) {
       Array<Real> * Cv = new Array<Real>(*velocity);
       *Cv *= *velocity_damping_matrix;
       *residual -= *Cv;
       delete Cv;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateAcceleration() {
   AKANTU_DEBUG_IN();
 
   updateResidualInternal();
 
   if(method == _explicit_lumped_mass) {
     /* residual = residual_{n+1} - M * acceleration_n therefore
        solution = increment acceleration not acceleration */
     solveLumped(*increment_acceleration,
 		*mass,
 		*residual,
 		*blocked_dofs,
 		f_m2a);
   } else if (method == _explicit_consistent_mass) {
     solve<NewmarkBeta::_acceleration_corrector>(*increment_acceleration);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::solveLumped(Array<Real> & x,
 				      const Array<Real> & A,
 				      const Array<Real> & b,
 				      const Array<bool> & blocked_dofs,
 				      Real alpha) {
 
   Real * A_val = A.storage();
   Real * b_val = b.storage();
   Real * x_val = x.storage();
   bool * blocked_dofs_val = blocked_dofs.storage();
 
   UInt nb_degrees_of_freedom = x.getSize() * x.getNbComponent();
 
   for (UInt n = 0; n < nb_degrees_of_freedom; ++n) {
     if(!(*blocked_dofs_val)) {
       *x_val = alpha * (*b_val / *A_val);
     }
     x_val++;
     A_val++;
     b_val++;
     blocked_dofs_val++;
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::explicitPred() {
   AKANTU_DEBUG_IN();
 
   if(increment_flag) {
     if(previous_displacement) increment->copy(*previous_displacement);
     else increment->copy(*displacement);
   }
 
   AKANTU_DEBUG_ASSERT(integrator,"itegrator should have been allocated: "
 		      << "have called initExplicit ? "
 		      << "or initImplicit ?");
 
   integrator->integrationSchemePred(time_step,
 				    *displacement,
 				    *velocity,
 				    *acceleration,
 				    *blocked_dofs);
 
   if(increment_flag) {
     Real * inc_val = increment->storage();
     Real * dis_val = displacement->storage();
     UInt nb_degree_of_freedom = displacement->getSize() * displacement->getNbComponent();
 
     for (UInt n = 0; n < nb_degree_of_freedom; ++n) {
       *inc_val = *dis_val - *inc_val;
       inc_val++;
       dis_val++;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::explicitCorr() {
   AKANTU_DEBUG_IN();
 
   integrator->integrationSchemeCorrAccel(time_step,
 					 *displacement,
 					 *velocity,
 					 *acceleration,
 					 *blocked_dofs,
 					 *increment_acceleration);
 
   if(previous_displacement) previous_displacement->copy(*displacement);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::solveStep() {
   AKANTU_DEBUG_IN();
 
   EventManager::sendEvent(SolidMechanicsModelEvent::BeforeSolveStepEvent(method));
 
   this->explicitPred();
   this->updateResidual();
   this->updateAcceleration();
   this->explicitCorr();
 
   EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method));
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* Implicit scheme                                                            */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 /**
  * Initialize the solver and create the sparse matrices needed.
  *
  */
 void SolidMechanicsModel::initSolver(__attribute__((unused)) SolverOptions & options) {
 #if !defined(AKANTU_USE_MUMPS) && !defined(AKANTU_USE_PETSC)// or other solver in the future \todo add AKANTU_HAS_SOLVER in CMake
   AKANTU_DEBUG_ERROR("You should at least activate one solver.");
 #else
   UInt nb_global_nodes = mesh.getNbGlobalNodes();
 
   delete jacobian_matrix;
   std::stringstream sstr; sstr << id << ":jacobian_matrix";
 
 #ifdef AKANTU_USE_PETSC
   jacobian_matrix = new PETScMatrix(nb_global_nodes * spatial_dimension, _symmetric, sstr.str(), memory_id);
 #else
   jacobian_matrix = new SparseMatrix(nb_global_nodes * spatial_dimension, _symmetric, sstr.str(), memory_id);
 #endif //AKANTU_USE PETSC
   jacobian_matrix->buildProfile(mesh, *dof_synchronizer, spatial_dimension);
 
   if (!isExplicit()) {
     delete stiffness_matrix;
     std::stringstream sstr_sti; sstr_sti << id << ":stiffness_matrix";
 #ifdef AKANTU_USE_PETSC
     stiffness_matrix = new SparseMatrix(nb_global_nodes * spatial_dimension, _symmetric, sstr.str(), memory_id);
     stiffness_matrix->buildProfile(mesh, *dof_synchronizer, spatial_dimension);
 #else
     stiffness_matrix = new SparseMatrix(*jacobian_matrix, sstr_sti.str(), memory_id);
 #endif //AKANTU_USE_PETSC
   }
 
   std::stringstream sstr_solv; sstr_solv << id << ":solver";
 #ifdef AKANTU_USE_PETSC
   solver = new SolverPETSc(*jacobian_matrix, sstr_solv.str());
 #elif defined(AKANTU_USE_MUMPS)
   solver = new SolverMumps(*jacobian_matrix, sstr_solv.str());
   dof_synchronizer->initScatterGatherCommunicationScheme();
 #else
   AKANTU_DEBUG_ERROR("You should at least activate one solver.");
 #endif //AKANTU_USE_MUMPS
 
   if(solver)
     solver->initialize(options);
 #endif //AKANTU_HAS_SOLVER
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initJacobianMatrix() {
 #if defined(AKANTU_USE_MUMPS) && !defined(AKANTU_USE_PETSC)
 
   // @todo make it more flexible: this is an ugly patch to treat the case of non
   // fix profile of the K matrix
   delete jacobian_matrix;
   std::stringstream sstr_sti; sstr_sti << id << ":jacobian_matrix";
   jacobian_matrix = new SparseMatrix(*stiffness_matrix, sstr_sti.str(), memory_id);
 
   std::stringstream sstr_solv; sstr_solv << id << ":solver";
   delete solver;
   solver = new SolverMumps(*jacobian_matrix, sstr_solv.str());
   if(solver)
     solver->initialize(_solver_no_options);
 #else
   AKANTU_DEBUG_ERROR("You need to activate the solver mumps.");
 #endif
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Initialize the implicit solver, either for dynamic or static cases,
  *
  * @param dynamic
  */
 void SolidMechanicsModel::initImplicit(bool dynamic, SolverOptions & solver_options) {
   AKANTU_DEBUG_IN();
 
   method = dynamic ? _implicit_dynamic : _static;
 
   if (!increment) setIncrementFlagOn();
 
   initSolver(solver_options);
 
   if(method == _implicit_dynamic) {
     if(integrator) delete integrator;
     integrator = new TrapezoidalRule2();
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initialAcceleration() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_INFO("Solving Ma = f");
 
   Solver * acc_solver = NULL;
 
   std::stringstream sstr; sstr << id << ":tmp_mass_matrix";
   SparseMatrix * tmp_mass = new SparseMatrix(*mass_matrix, sstr.str(), memory_id);
 
 #ifdef AKANTU_USE_MUMPS
   std::stringstream sstr_solver; sstr << id << ":solver_mass_matrix";
   acc_solver = new SolverMumps(*mass_matrix, sstr_solver.str());
 
   dof_synchronizer->initScatterGatherCommunicationScheme();
 #else
   AKANTU_DEBUG_ERROR("You should at least activate one solver.");
 #endif //AKANTU_USE_MUMPS
 
   acc_solver->initialize();
 
   tmp_mass->applyBoundary(*blocked_dofs);
 
   acc_solver->setRHS(*residual);
   acc_solver->solve(*acceleration);
 
   delete acc_solver;
   delete tmp_mass;
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleStiffnessMatrix() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_INFO("Assemble the new stiffness matrix.");
 
   stiffness_matrix->clear();
 
   // call compute stiffness matrix on each local elements
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     (*mat_it)->assembleStiffnessMatrix(_not_ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 SparseMatrix & SolidMechanicsModel::initVelocityDampingMatrix() {
   if(!velocity_damping_matrix)
     velocity_damping_matrix =
       new SparseMatrix(*jacobian_matrix, id + ":velocity_damping_matrix", memory_id);
 
   return *velocity_damping_matrix;
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 bool SolidMechanicsModel::testConvergence<_scc_increment>(Real tolerance, Real & error){
   AKANTU_DEBUG_IN();
 
   UInt nb_nodes = displacement->getSize();
   UInt nb_degree_of_freedom = displacement->getNbComponent();
 
   error = 0;
   Real norm[2] = {0., 0.};
   Real * increment_val    = increment->storage();
   bool * blocked_dofs_val     = blocked_dofs->storage();
   Real * displacement_val = displacement->storage();
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     bool is_local_node = mesh.isLocalOrMasterNode(n);
     for (UInt d = 0; d < nb_degree_of_freedom; ++d) {
       if(!(*blocked_dofs_val) && is_local_node) {
 	norm[0] += *increment_val * *increment_val;
 	norm[1] += *displacement_val * *displacement_val;
       }
       blocked_dofs_val++;
       increment_val++;
       displacement_val++;
     }
   }
 
   StaticCommunicator::getStaticCommunicator().allReduce(norm, 2, _so_sum);
 
   norm[0] = sqrt(norm[0]);
   norm[1] = sqrt(norm[1]);
 
   AKANTU_DEBUG_ASSERT(!Math::isnan(norm[0]), "Something goes wrong in the solve phase");
 
   if (norm[1] < Math::getTolerance()) {
     error = norm[0];
     AKANTU_DEBUG_OUT();
     //    cout<<"Error 1: "<<error<<endl;
     return error < tolerance;
   }
 
 
   AKANTU_DEBUG_OUT();
   if(norm[1] > Math::getTolerance())
     error = norm[0] / norm[1];
   else
     error = norm[0]; //In case the total displacement is zero!
 
   //  cout<<"Error 2: "<<error<<endl;
 
   return (error < tolerance);
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<>
 bool SolidMechanicsModel::testConvergence<_scc_residual>(Real tolerance, Real & norm) {
   AKANTU_DEBUG_IN();
 
 
 
   UInt nb_nodes = residual->getSize();
 
   norm = 0;
   Real * residual_val = residual->storage();
   bool * blocked_dofs_val = blocked_dofs->storage();
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     bool is_local_node = mesh.isLocalOrMasterNode(n);
     if(is_local_node) {
       for (UInt d = 0; d < spatial_dimension; ++d) {
 	if(!(*blocked_dofs_val)) {
 	  norm += *residual_val * *residual_val;
 	}
 	blocked_dofs_val++;
 	residual_val++;
       }
     } else {
       blocked_dofs_val += spatial_dimension;
       residual_val += spatial_dimension;
     }
   }
 
   StaticCommunicator::getStaticCommunicator().allReduce(&norm, 1, _so_sum);
 
   norm = sqrt(norm);
 
   AKANTU_DEBUG_ASSERT(!Math::isnan(norm), "Something goes wrong in the solve phase");
 
   AKANTU_DEBUG_OUT();
   return (norm < tolerance);
 }
 
 /* -------------------------------------------------------------------------- */
 template<>
 bool SolidMechanicsModel::testConvergence<_scc_residual_mass_wgh>(Real tolerance,
 								  Real & norm) {
   AKANTU_DEBUG_IN();
 
 
 
   UInt nb_nodes = residual->getSize();
 
   norm = 0;
   Real * residual_val = residual->storage();
   Real * mass_val = this->mass->storage();
   bool * blocked_dofs_val = blocked_dofs->storage();
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     bool is_local_node = mesh.isLocalOrMasterNode(n);
     if(is_local_node) {
       for (UInt d = 0; d < spatial_dimension; ++d) {
 	if(!(*blocked_dofs_val)) {
 	  norm += *residual_val * *residual_val/(*mass_val * *mass_val);
 	}
 	blocked_dofs_val++;
 	residual_val++;
 	mass_val++;
       }
     } else {
       blocked_dofs_val += spatial_dimension;
       residual_val += spatial_dimension;
       mass_val += spatial_dimension;
     }
   }
 
   StaticCommunicator::getStaticCommunicator().allReduce(&norm, 1, _so_sum);
 
   norm = sqrt(norm);
 
   AKANTU_DEBUG_ASSERT(!Math::isnan(norm), "Something goes wrong in the solve phase");
 
   AKANTU_DEBUG_OUT();
   return (norm < tolerance);
 }
 
 /* -------------------------------------------------------------------------- */
 bool SolidMechanicsModel::testConvergenceResidual(Real tolerance){
   AKANTU_DEBUG_IN();
 
   Real error=0;
   bool res = this->testConvergence<_scc_residual>(tolerance, error);
   AKANTU_DEBUG_OUT();
   return res;
 }
 
 /* -------------------------------------------------------------------------- */
 bool SolidMechanicsModel::testConvergenceResidual(Real tolerance, Real & error){
   AKANTU_DEBUG_IN();
 
   bool res = this->testConvergence<_scc_residual>(tolerance, error);
 
   AKANTU_DEBUG_OUT();
   return res;
 }
 
 /* -------------------------------------------------------------------------- */
 bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance){
   AKANTU_DEBUG_IN();
 
   Real error=0;
   bool res = this->testConvergence<_scc_increment>(tolerance, error);
 
   AKANTU_DEBUG_OUT();
   return res;
 }
 
 /* -------------------------------------------------------------------------- */
 bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance, Real & error){
   AKANTU_DEBUG_IN();
 
   bool res = this->testConvergence<_scc_increment>(tolerance, error);
 
   AKANTU_DEBUG_OUT();
   return res;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::implicitPred() {
   AKANTU_DEBUG_IN();
 
   if(previous_displacement) previous_displacement->copy(*displacement);
 
   if(method == _implicit_dynamic)
     integrator->integrationSchemePred(time_step,
 				      *displacement,
 				      *velocity,
 				      *acceleration,
 				      *blocked_dofs);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::implicitCorr() {
   AKANTU_DEBUG_IN();
 
   if(method == _implicit_dynamic) {
     integrator->integrationSchemeCorrDispl(time_step,
 					   *displacement,
 					   *velocity,
 					   *acceleration,
 					   *blocked_dofs,
 					   *increment);
   } else {
     UInt nb_nodes = displacement->getSize();
     UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes;
 
     Real * incr_val = increment->storage();
     Real * disp_val = displacement->storage();
     bool * boun_val = blocked_dofs->storage();
 
     for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++disp_val, ++incr_val, ++boun_val){
       *incr_val *= (1. - *boun_val);
       *disp_val += *incr_val;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateIncrement() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(previous_displacement,"The previous displacement has to be initialized."
 		      << " Are you working with Finite or Ineslactic deformations?");
 
   UInt nb_nodes = displacement->getSize();
   UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes;
 
   Real * incr_val = increment->storage();
   Real * disp_val = displacement->storage();
   Real * prev_disp_val = previous_displacement->storage();
 
   for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++disp_val, ++incr_val, ++prev_disp_val)
     *incr_val = (*disp_val - *prev_disp_val);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updatePreviousDisplacement() {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(previous_displacement,"The previous displacement has to be initialized."
 		      << " Are you working with Finite or Ineslactic deformations?");
 
   previous_displacement->copy(*displacement);
 
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 /* Information                                                                */
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::synchronizeBoundaries() {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT(synch_registry,"Synchronizer registry was not initialized."
 		      << " Did you call initParallel?");
   synch_registry->synchronize(_gst_smm_boundary);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::synchronizeResidual() {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT(synch_registry,"Synchronizer registry was not initialized."
 		      << " Did you call initPBC?");
   synch_registry->synchronize(_gst_smm_res);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::setIncrementFlagOn() {
   AKANTU_DEBUG_IN();
 
   if(!increment) {
     UInt nb_nodes = mesh.getNbNodes();
     std::stringstream sstr_inc; sstr_inc << id << ":increment";
     increment = &(alloc<Real>(sstr_inc.str(), nb_nodes, spatial_dimension, 0.));
   }
 
   increment_flag = true;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getStableTimeStep() {
   AKANTU_DEBUG_IN();
 
   Real min_dt = getStableTimeStep(_not_ghost);
 
   /// reduction min over all processors
   StaticCommunicator::getStaticCommunicator().allReduce(&min_dt, 1, _so_min);
 
   AKANTU_DEBUG_OUT();
   return min_dt;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getStableTimeStep(const GhostType & ghost_type) {
   AKANTU_DEBUG_IN();
 
   Material ** mat_val = &(materials.at(0));
   Real min_dt = std::numeric_limits<Real>::max();
 
   updateCurrentPosition();
 
   Element elem;
   elem.ghost_type = ghost_type;
   elem.kind = _ek_regular;
 
   Mesh::type_iterator it  = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type);
   for(; it != end; ++it) {
     elem.type = *it;
     UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it);
     UInt nb_element           = mesh.getNbElement(*it);
 
-    Array<UInt>::iterator< Vector<UInt> > eibm =
-      element_index_by_material(*it, ghost_type).begin(2);
+    Array<UInt>::const_scalar_iterator mat_indexes = material_index(*it, ghost_type).begin();
+    Array<UInt>::const_scalar_iterator mat_loc_num = material_local_numbering(*it, ghost_type).begin();
 
     Array<Real> X(0, nb_nodes_per_element*spatial_dimension);
     FEEngine::extractNodalToElementField(mesh, *current_position,
 					 X, *it, _not_ghost);
 
     Array<Real>::matrix_iterator X_el =
       X.begin(spatial_dimension, nb_nodes_per_element);
 
-    for (UInt el = 0; el < nb_element; ++el, ++X_el, ++eibm) {
-      elem.element = (*eibm)(1);
+    for (UInt el = 0; el < nb_element; ++el, ++X_el, ++mat_indexes, ++mat_loc_num) {
+      elem.element = *mat_loc_num;
       Real el_h  = getFEEngine().getElementInradius(*X_el, *it);
-      Real el_c  = mat_val[(*eibm)(0)]->getCelerity(elem);
+      Real el_c  = mat_val[*mat_indexes]->getCelerity(elem);
       Real el_dt = el_h / el_c;
 
       min_dt = std::min(min_dt, el_dt);
     }
   }
 
   AKANTU_DEBUG_OUT();
   return min_dt;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getPotentialEnergy() {
   AKANTU_DEBUG_IN();
   Real energy = 0.;
 
   /// call update residual on each local elements
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     energy += (*mat_it)->getPotentialEnergy();
   }
 
   /// reduction sum over all processors
   StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _so_sum);
 
   AKANTU_DEBUG_OUT();
   return energy;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getKineticEnergy() {
   AKANTU_DEBUG_IN();
 
   if (!mass && !mass_matrix)
     AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix.");
 
 
   Real ekin = 0.;
 
   UInt nb_nodes = mesh.getNbNodes();
 
   Real * vel_val  = velocity->storage();
   Real * mass_val = mass->storage();
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     Real mv2 = 0;
     bool is_local_node = mesh.isLocalOrMasterNode(n);
     bool is_not_pbc_slave_node = !isPBCSlaveNode(n);
     bool count_node = is_local_node && is_not_pbc_slave_node;
     for (UInt i = 0; i < spatial_dimension; ++i) {
       if (count_node)
 	mv2 += *vel_val * *vel_val * *mass_val;
 
       vel_val++;
       mass_val++;
     }
     ekin += mv2;
   }
 
   StaticCommunicator::getStaticCommunicator().allReduce(&ekin, 1, _so_sum);
 
   AKANTU_DEBUG_OUT();
   return ekin * .5;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getKineticEnergy(const ElementType & type, UInt index) {
   AKANTU_DEBUG_IN();
 
   UInt nb_quadrature_points = getFEEngine().getNbQuadraturePoints(type);
 
   Array<Real> vel_on_quad(nb_quadrature_points, spatial_dimension);
   Array<UInt> filter_element(1, 1, index);
 
   getFEEngine().interpolateOnQuadraturePoints(*velocity, vel_on_quad,
 					      spatial_dimension,
 					      type, _not_ghost,
 					      filter_element);
 
   Array<Real>::vector_iterator vit   = vel_on_quad.begin(spatial_dimension);
   Array<Real>::vector_iterator vend  = vel_on_quad.end(spatial_dimension);
 
   Vector<Real> rho_v2(nb_quadrature_points);
 
-  Real rho = materials[element_index_by_material(type)(index, 0)]->getRho();
+  Real rho = materials[material_index(type)(index)]->getRho();
 
   for (UInt q = 0; vit != vend; ++vit, ++q) {
     rho_v2(q) = rho * vit->dot(*vit);
   }
 
   AKANTU_DEBUG_OUT();
 
   return .5*getFEEngine().integrate(rho_v2, type, index);
 }
 
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getExternalWork() {
   AKANTU_DEBUG_IN();
 
   Real * velo = velocity->storage();
   Real * forc = force->storage();
   Real * resi = residual->storage();
   bool * boun = blocked_dofs->storage();
 
   Real work = 0.;
 
   UInt nb_nodes = mesh.getNbNodes();
 
   for (UInt n = 0; n < nb_nodes; ++n) {
     bool is_local_node = mesh.isLocalOrMasterNode(n);
     bool is_not_pbc_slave_node = !isPBCSlaveNode(n);
     bool count_node = is_local_node && is_not_pbc_slave_node;
 
     for (UInt i = 0; i < spatial_dimension; ++i) {
       if (count_node) {
 	if(*boun)
 	  work -= *resi * *velo * time_step;
 	else
 	  work += *forc * *velo * time_step;
       }
 
       ++velo;
       ++forc;
       ++resi;
       ++boun;
     }
   }
 
   StaticCommunicator::getStaticCommunicator().allReduce(&work, 1, _so_sum);
 
   AKANTU_DEBUG_OUT();
   return work;
 }
 
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getEnergy(const std::string & energy_id) {
   AKANTU_DEBUG_IN();
 
   if (energy_id == "kinetic") {
     return getKineticEnergy();
   } else if (energy_id == "external work"){
     return getExternalWork();
   }
 
   Real energy = 0.;
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     energy += (*mat_it)->getEnergy(energy_id);
   }
 
   /// reduction sum over all processors
   StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _so_sum);
 
   AKANTU_DEBUG_OUT();
   return energy;
 }
 /* -------------------------------------------------------------------------- */
 Real SolidMechanicsModel::getEnergy(const std::string & energy_id,
 				    const ElementType & type,
 				    UInt index){
   AKANTU_DEBUG_IN();
 
   if (energy_id == "kinetic") {
     return getKineticEnergy(type, index);
   }
 
   std::vector<Material *>::iterator mat_it;
-  Vector<UInt> mat = element_index_by_material(type, _not_ghost).begin(2)[index];
-  Real energy = materials[mat(0)]->getEnergy(energy_id, type, mat(1));
+  UInt mat_index   = this->material_index(type, _not_ghost)(index);
+  UInt mat_loc_num = this->material_local_numbering(type, _not_ghost)(index);
+  Real energy = this->materials[mat_index]->getEnergy(energy_id, type, mat_loc_num);
 
   AKANTU_DEBUG_OUT();
   return energy;
 }
 
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::onNodesAdded(const Array<UInt> & nodes_list,
 				       __attribute__((unused)) const NewNodesEvent & event) {
   AKANTU_DEBUG_IN();
   UInt nb_nodes = mesh.getNbNodes();
 
   if(displacement) displacement->resize(nb_nodes);
   if(mass        ) mass        ->resize(nb_nodes);
   if(velocity    ) velocity    ->resize(nb_nodes);
   if(acceleration) acceleration->resize(nb_nodes);
   if(force       ) force       ->resize(nb_nodes);
   if(residual    ) residual    ->resize(nb_nodes);
   if(blocked_dofs) blocked_dofs->resize(nb_nodes);
 
   if(previous_displacement) previous_displacement->resize(nb_nodes);
   if(increment_acceleration) increment_acceleration->resize(nb_nodes);
   if(increment) increment->resize(nb_nodes);
 
   if(current_position) current_position->resize(nb_nodes);
 
   delete dof_synchronizer;
   dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension);
   dof_synchronizer->initLocalDOFEquationNumbers();
   dof_synchronizer->initGlobalDOFEquationNumbers();
 
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     (*mat_it)->onNodesAdded(nodes_list, event);
   }
 
   if (method != _explicit_lumped_mass) {
     this->initJacobianMatrix();
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::onElementsAdded(const Array<Element> & element_list,
 					  const NewElementsEvent & event) {
   AKANTU_DEBUG_IN();
 
   this->getFEEngine().initShapeFunctions(_not_ghost);
   this->getFEEngine().initShapeFunctions(_ghost);
 
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
     Mesh::type_iterator it  = this->mesh.firstType(spatial_dimension, gt, _ek_not_defined);
     Mesh::type_iterator end = this->mesh.lastType(spatial_dimension, gt, _ek_not_defined);
     for(; it != end; ++it) {
       UInt nb_element = this->mesh.getNbElement(*it, gt);
-      if(!element_index_by_material.exists(*it, gt))
-	this->element_index_by_material.alloc(nb_element, 2, *it, gt);
-      else
-	this->element_index_by_material(*it, gt).resize(nb_element);
+      if(!material_index.exists(*it, gt)) {
+	this->material_index          .alloc(nb_element, 1, *it, gt);
+	this->material_local_numbering.alloc(nb_element, 1, *it, gt);
+      } else {
+	this->material_index          (*it, gt).resize(nb_element);
+	this->material_local_numbering(*it, gt).resize(nb_element);
+      }
     }
   }
 
   Array<Element>::const_iterator<Element> it  = element_list.begin();
   Array<Element>::const_iterator<Element> end = element_list.end();
 
   ElementTypeMapArray<UInt> filter("new_element_filter", this->getID());
 
   for (UInt el = 0; it != end; ++it, ++el) {
     const Element & elem = *it;
 
     if(!filter.exists(elem.type, elem.ghost_type))
-      filter.alloc(0, 2, elem.type, elem.ghost_type);
+      filter.alloc(0, 1, elem.type, elem.ghost_type);
 
     filter(elem.type, elem.ghost_type).push_back(elem.element);
   }
 
   this->assignMaterialToElements(&filter);
 
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     (*mat_it)->onElementsAdded(element_list, event);
   }
 
   if(method == _explicit_lumped_mass) this->assembleMassLumped();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::onElementsRemoved(__attribute__((unused)) const Array<Element> & element_list,
 					    const ElementTypeMapArray<UInt> & new_numbering,
 					    const RemovedElementsEvent & event) {
   this->getFEEngine().initShapeFunctions(_not_ghost);
   this->getFEEngine().initShapeFunctions(_ghost);
 
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     (*mat_it)->onElementsRemoved(element_list, new_numbering, event);
   }
-
-  this->element_index_by_material.onElementsRemoved(new_numbering);
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::onNodesRemoved(__attribute__((unused)) const Array<UInt> & element_list,
 					 const Array<UInt> & new_numbering,
 					 __attribute__((unused)) const RemovedNodesEvent & event) {
   if(displacement) mesh.removeNodesFromArray(*displacement, new_numbering);
   if(mass        ) mesh.removeNodesFromArray(*mass        , new_numbering);
   if(velocity    ) mesh.removeNodesFromArray(*velocity    , new_numbering);
   if(acceleration) mesh.removeNodesFromArray(*acceleration, new_numbering);
   if(force       ) mesh.removeNodesFromArray(*force       , new_numbering);
   if(residual    ) mesh.removeNodesFromArray(*residual    , new_numbering);
   if(blocked_dofs) mesh.removeNodesFromArray(*blocked_dofs, new_numbering);
 
   if(increment_acceleration) mesh.removeNodesFromArray(*increment_acceleration, new_numbering);
   if(increment)              mesh.removeNodesFromArray(*increment             , new_numbering);
 
   delete dof_synchronizer;
   dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension);
   dof_synchronizer->initLocalDOFEquationNumbers();
   dof_synchronizer->initGlobalDOFEquationNumbers();
 }
 
 /* -------------------------------------------------------------------------- */
 bool SolidMechanicsModel::isInternal(const std::string & field_name,
 				     const ElementKind & element_kind){
 
   bool is_internal = false;
 
   /// check if at least one material contains field_id as an internal
   for (UInt m = 0; m < materials.size() && !is_internal; ++m) {
     is_internal |= materials[m]->isInternal(field_name, element_kind);
   }
 
   return is_internal;
 }
 /* -------------------------------------------------------------------------- */
 
 ElementTypeMap<UInt> SolidMechanicsModel::getInternalDataPerElem(const std::string & field_name,
 								const ElementKind & element_kind){
 
 
   if (!(this->isInternal(field_name,element_kind))) AKANTU_EXCEPTION("unknown internal " << field_name);
 
   for (UInt m = 0; m < materials.size() ; ++m) {
     if (materials[m]->isInternal(field_name, element_kind))
       return materials[m]->getInternalDataPerElem(field_name,element_kind);
   }
 
   return ElementTypeMap<UInt>();
 }
 
 
 /* -------------------------------------------------------------------------- */
 ElementTypeMapArray<Real> & SolidMechanicsModel::flattenInternal(const std::string & field_name,
 								const ElementKind & kind){
 
   std::pair<std::string,ElementKind> key(field_name,kind);
   if (this->registered_internals.count(key) == 0){
     this->registered_internals[key] =
       new ElementTypeMapArray<Real>(field_name,this->id);
   }
 
   ElementTypeMapArray<Real> * internal_flat = this->registered_internals[key];
   for (UInt m = 0; m < materials.size(); ++m)
     materials[m]->flattenInternal(field_name,*internal_flat,_not_ghost,kind);
 
   return  *internal_flat;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::flattenAllRegisteredInternals(const ElementKind & kind){
 
   std::map<std::pair<std::string,ElementKind>,ElementTypeMapArray<Real> *> ::iterator it = this->registered_internals.begin();
   std::map<std::pair<std::string,ElementKind>,ElementTypeMapArray<Real> *>::iterator end = this->registered_internals.end();
 
   while (it != end){
     if (kind == it->first.second)
       this->flattenInternal(it->first.first,kind);
     ++it;
   }
 }
 
 /* -------------------------------------------------------------------------- */
 
 void SolidMechanicsModel::onDump(){
   this->flattenAllRegisteredInternals(_ek_regular);
 }
 /* -------------------------------------------------------------------------- */
 
 #ifdef AKANTU_USE_IOHELPER
 
 dumper::Field * SolidMechanicsModel
 ::createElementalField(const std::string & field_name,
 		       const std::string & group_name,
 		       bool padding_flag,
 		       const ElementKind & kind){
 
   dumper::Field * field = NULL;
 
   if(field_name == "partitions")
     field = mesh.createElementalField<UInt, dumper::ElementPartitionField>(mesh.getConnectivities(),group_name,this->spatial_dimension,kind);
-  else if(field_name == "element_index_by_material")
-    field = mesh.createElementalField<UInt, Vector, dumper::ElementalField >(element_index_by_material,group_name,this->spatial_dimension,kind);
+  else if(field_name == "material_index")
+    field = mesh.createElementalField<UInt, Vector, dumper::ElementalField >(material_index,group_name,this->spatial_dimension,kind);
   else {
 
     bool is_internal = this->isInternal(field_name,kind);
 
     if (is_internal) {
-
       ElementTypeMap<UInt> nb_data_per_elem = this->getInternalDataPerElem(field_name,kind);
       ElementTypeMapArray<Real> & internal_flat = this->flattenInternal(field_name,kind);
       field = mesh.createElementalField<Real, dumper::InternalMaterialField>(internal_flat,
 									     group_name,
 									     this->spatial_dimension,kind,nb_data_per_elem);
 
       //treat the paddings
       if (padding_flag){
 	if (field_name == "stress"){
 	  if (this->spatial_dimension == 2) {
 	    dumper::StressPadder<2> * foo = new dumper::StressPadder<2>(*this);
 	    field = dumper::FieldComputeProxy::createFieldCompute(field,*foo);
 	  }
 	}
 	// else if (field_name == "strain"){
 	//   if (this->spatial_dimension == 2) {
 	//     dumper::StrainPadder<2> * foo = new dumper::StrainPadder<2>(*this);
 	//     field = dumper::FieldComputeProxy::createFieldCompute(field,*foo);
 	//   }
 	// }
       }
 
       // homogenize the field
       dumper::ComputeFunctorInterface * foo =
 	dumper::HomogenizerProxy::createHomogenizer(*field);
 
       field = dumper::FieldComputeProxy::createFieldCompute(field,*foo);
 
     }
   }
   return field;
 }
 
 /* -------------------------------------------------------------------------- */
 
 dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string & field_name,
 							  const std::string & group_name,
 							  bool padding_flag) {
 
   std::map<std::string,Array<Real>* > real_nodal_fields;
   real_nodal_fields["displacement"             ] = displacement;
   real_nodal_fields["mass"                     ] = mass;
   real_nodal_fields["velocity"                 ] = velocity;
   real_nodal_fields["acceleration"             ] = acceleration;
   real_nodal_fields["force"                    ] = force;
   real_nodal_fields["residual"                 ] = residual;
   real_nodal_fields["increment"                ] = increment;
 
   dumper::Field * field = NULL;
   if (padding_flag)
     field = mesh.createNodalField(real_nodal_fields[field_name],group_name, 3);
   else
     field = mesh.createNodalField(real_nodal_fields[field_name],group_name);
 
   return field;
 }
 /* -------------------------------------------------------------------------- */
 
 dumper::Field * SolidMechanicsModel::createNodalFieldBool(const std::string & field_name,
 							  const std::string & group_name,
 bool padding_flag) {
 
   std::map<std::string,Array<bool>* > uint_nodal_fields;
   uint_nodal_fields["blocked_dofs"             ] = blocked_dofs;
 
   dumper::Field * field = NULL;
   field = mesh.createNodalField(uint_nodal_fields[field_name],group_name);
   return field;
 
 }
 /* -------------------------------------------------------------------------- */
 #else
 /* -------------------------------------------------------------------------- */
 
 dumper::Field * SolidMechanicsModel
 ::createElementalField(const std::string & field_name,
 		       const std::string & group_name,
 		       bool padding_flag,
 		       const ElementKind & kind){
   return NULL;
 }
 
 /* -------------------------------------------------------------------------- */
 
 dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string & field_name,
 							  const std::string & group_name,
 							  bool padding_flag) {
   return NULL;
 }
 
 /* -------------------------------------------------------------------------- */
 
 dumper::Field * SolidMechanicsModel::createNodalFieldBool(const std::string & field_name,
 							  const std::string & group_name,
 bool padding_flag) {
   return NULL;
 }
 
 #endif
 /* -------------------------------------------------------------------------- */
 
 void SolidMechanicsModel::dump(const std::string & dumper_name) {
   this->onDump();
   EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
   synch_registry->synchronize(_gst_for_dump);
   mesh.dump(dumper_name);
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::dump(const std::string & dumper_name, UInt step) {
   this->onDump();
   EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
   synch_registry->synchronize(_gst_for_dump);
   mesh.dump(dumper_name, step);
 }
 
 /* ------------------------------------------------------------------------- */
 void SolidMechanicsModel::dump(const std::string & dumper_name, Real time, UInt step) {
   this->onDump();
   EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
   synch_registry->synchronize(_gst_for_dump);
   mesh.dump(dumper_name, time, step);
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::dump() {
   this->onDump();
   EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
   mesh.dump();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::dump(UInt step) {
   this->onDump();
   EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
   mesh.dump(step);
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::dump(Real time, UInt step) {
   this->onDump();
   EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
   mesh.dump(time, step);
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::computeCauchyStresses() {
   AKANTU_DEBUG_IN();
 
   // call compute stiffness matrix on each local elements
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     Material & mat = **mat_it;
     if(mat.isFiniteDeformation())
       mat.computeAllCauchyStresses(_not_ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::saveStressAndStrainBeforeDamage() {
   EventManager::sendEvent(SolidMechanicsModelEvent::BeginningOfDamageIterationEvent());
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::updateEnergiesAfterDamage() {
   EventManager::sendEvent(SolidMechanicsModelEvent::AfterDamageEvent());
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   stream << space << "Solid Mechanics Model [" << std::endl;
   stream << space << " + id                : " << id << std::endl;
   stream << space << " + spatial dimension : " << spatial_dimension << std::endl;
   stream << space << " + fem [" << std::endl;
   getFEEngine().printself(stream, indent + 2);
   stream << space << AKANTU_INDENT << "]" << std::endl;
   stream << space << " + nodals information [" << std::endl;
   displacement->printself(stream, indent + 2);
   mass        ->printself(stream, indent + 2);
   velocity    ->printself(stream, indent + 2);
   acceleration->printself(stream, indent + 2);
   force       ->printself(stream, indent + 2);
   residual    ->printself(stream, indent + 2);
   blocked_dofs->printself(stream, indent + 2);
   stream << space << AKANTU_INDENT << "]" << std::endl;
 
-  stream << space << " + connectivity type information [" << std::endl;
-  element_index_by_material.printself(stream, indent + 2);
+  stream << space << " + material information [" << std::endl;
+  material_index.printself(stream, indent + 2);
   stream << space << AKANTU_INDENT << "]" << std::endl;
 
   stream << space << " + materials [" << std::endl;
   std::vector<Material *>::const_iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     const Material & mat = *(*mat_it);
     mat.printself(stream, indent + 1);
   }
   stream << space << AKANTU_INDENT << "]" << std::endl;
 
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/solid_mechanics_model.hh b/src/model/solid_mechanics/solid_mechanics_model.hh
index 2575a72db..568500513 100644
--- a/src/model/solid_mechanics/solid_mechanics_model.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model.hh
@@ -1,738 +1,741 @@
 /**
  * @file   solid_mechanics_model.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Tue Jul 27 2010
  * @date last modification: Tue Sep 16 2014
  *
  * @brief  Model of Solid Mechanics
  *
  * @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_SOLID_MECHANICS_MODEL_HH__
 #define __AKANTU_SOLID_MECHANICS_MODEL_HH__
 
 
 /* -------------------------------------------------------------------------- */
 #include <fstream>
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "aka_types.hh"
 #include "model.hh"
 #include "data_accessor.hh"
 #include "mesh.hh"
 #include "dumpable.hh"
 #include "boundary_condition.hh"
 #include "integrator_gauss.hh"
 #include "shape_lagrange.hh"
 #include "integration_scheme_2nd_order.hh"
 #include "solver.hh"
 #include "material_selector.hh"
 #include "solid_mechanics_model_event_handler.hh"
 /* -------------------------------------------------------------------------- */
 namespace akantu {
   class Material;
   class IntegrationScheme2ndOrder;
   class SparseMatrix;
   class DumperIOHelper;
 }
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 struct SolidMechanicsModelOptions : public ModelOptions {
   SolidMechanicsModelOptions(AnalysisMethod analysis_method = _explicit_lumped_mass,
 			     bool no_init_materials = false) :
     analysis_method(analysis_method),
     no_init_materials(no_init_materials)  {  }
   AnalysisMethod analysis_method;
   bool no_init_materials;
 };
 
 extern const SolidMechanicsModelOptions default_solid_mechanics_model_options;
 
 
 class SolidMechanicsModel : public Model,
 			    public DataAccessor,
 			    public MeshEventHandler,
 			    public BoundaryCondition<SolidMechanicsModel>,
                             public EventHandlerManager<SolidMechanicsModelEventHandler> {
 
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   class NewMaterialElementsEvent : public NewElementsEvent {
   public:
     AKANTU_GET_MACRO_NOT_CONST(MaterialList, material, Array <UInt> &);
     AKANTU_GET_MACRO(MaterialList, material, const Array <UInt> &);
   protected:
     Array <UInt> material;
   };
 
   typedef FEEngineTemplate <IntegratorGauss, ShapeLagrange> MyFEEngineType;
 
 protected:
   typedef EventHandlerManager <SolidMechanicsModelEventHandler> EventManager;
 
 public:
   SolidMechanicsModel(Mesh & mesh,
 		      UInt spatial_dimension = _all_dimensions,
 		      const ID & id = "solid_mechanics_model",
 		      const MemoryID & memory_id = 0);
 
   virtual ~SolidMechanicsModel();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialize completely the model
   virtual void initFull(const ModelOptions & options = default_solid_mechanics_model_options);
 
   /// initialize the fem object needed for boundary conditions
   void initFEEngineBoundary();
 
   /// register the tags associated with the parallel synchronizer
   void initParallel(MeshPartition *partition, DataAccessor *data_accessor = NULL);
 
   /// allocate all vectors
   void initArrays();
 
   /// allocate all vectors
   void initArraysPreviousDisplacment();
 
   /// initialize all internal arrays for materials
   virtual void initMaterials();
 
   /// initialize the model
   virtual void initModel();
 
   /// init PBC synchronizer
   void initPBC();
 
   /// function to print the containt of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /* ------------------------------------------------------------------------ */
   /* PBC                                                                      */
   /* ------------------------------------------------------------------------ */
 public:
   /// change the equation number for proper assembly when using PBC
   //  void changeEquationNumberforPBC(std::map <UInt, UInt> & pbc_pair);
 
   /// synchronize Residual for output
   void synchronizeResidual();
 
 protected:
   /// register PBC synchronizer
   void registerPBCSynchronizer();
 
   /* ------------------------------------------------------------------------ */
   /* Explicit                                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialize the stuff for the explicit scheme
   void initExplicit(AnalysisMethod analysis_method = _explicit_lumped_mass);
 
   bool isExplicit() {
     return method == _explicit_lumped_mass || method == _explicit_consistent_mass;
   }
 
   /// initialize the array needed by updateResidual (residual, current_position)
   void initializeUpdateResidualData();
 
   /// update the current position vector
   void updateCurrentPosition();
 
   /// assemble the residual for the explicit scheme
   virtual void updateResidual(bool need_initialize = true);
 
   /**
    * \brief compute the acceleration from the residual
    * this function is the explicit equivalent to solveDynamic in implicit
    * In the case of lumped mass just divide the residual by the mass
    * In the case of not lumped mass call solveDynamic<_acceleration_corrector>
    */
   void updateAcceleration();
 
   void updateIncrement();
   void updatePreviousDisplacement();
   void saveStressAndStrainBeforeDamage();
   void updateEnergiesAfterDamage();
 
   /// Solve the system @f[ A x = \alpha b @f] with A a lumped matrix
   void solveLumped(Array <Real> &       x,
 		   const Array <Real> & A,
 		   const Array <Real> & b,
 		   const Array <bool> & blocked_dofs,
 		   Real                 alpha);
 
   /// explicit integration predictor
   void explicitPred();
 
   /// explicit integration corrector
   void explicitCorr();
 
 public:
   void solveStep();
 
   /* ------------------------------------------------------------------------ */
   /* Implicit                                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialize the solver and the jacobian_matrix (called by initImplicit)
   void initSolver(SolverOptions & options = _solver_no_options);
 
   /// initialize the stuff for the implicit solver
   void initImplicit(bool            dynamic = false,
 		    SolverOptions & solver_options = _solver_no_options);
 
   /// solve Ma = f to get the initial acceleration
   void initialAcceleration();
 
   /// assemble the stiffness matrix
   void assembleStiffnessMatrix();
 
 public:
   /**
    * solve a step (predictor + convergence loop + corrector) using the
    * the given convergence method (see akantu::SolveConvergenceMethod)
    * and the given convergence criteria (see
    * akantu::SolveConvergenceCriteria)
    **/
   template <SolveConvergenceMethod method, SolveConvergenceCriteria criteria>
   bool solveStep(Real tolerance, UInt max_iteration = 100);
 
   template <SolveConvergenceMethod method, SolveConvergenceCriteria criteria>
   bool solveStep(Real   tolerance,
 		 Real & error,
 		 UInt   max_iteration = 100,
 		 bool   do_not_factorize = false);
 
 public:
   /**
    * solve Ku = f using the the given convergence method (see
    * akantu::SolveConvergenceMethod) and the given convergence
    * criteria (see akantu::SolveConvergenceCriteria)
    **/
   template <SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria>
   bool solveStatic(Real tolerance, UInt max_iteration,
 		   bool do_not_factorize = false);
 
   /// test if the system is converged
   template <SolveConvergenceCriteria criteria>
   bool testConvergence(Real tolerance, Real & error);
 
   /// test the convergence (norm of increment)
   bool testConvergenceIncrement(Real tolerance) __attribute__((deprecated));
   bool testConvergenceIncrement(Real tolerance, Real & error) __attribute__((deprecated));
 
   /// test the convergence (norm of residual)
   bool testConvergenceResidual(Real tolerance) __attribute__((deprecated));
   bool testConvergenceResidual(Real tolerance, Real & error) __attribute__((deprecated));
 
   /// create and return the velocity damping matrix
   SparseMatrix & initVelocityDampingMatrix();
 
   /// implicit time integration predictor
   void implicitPred();
 
   /// implicit time integration corrector
   void implicitCorr();
 
   /// compute the Cauchy stress on user demand.
   void computeCauchyStresses();
 
 protected:
   /// finish the computation of residual to solve in increment
   void updateResidualInternal();
 
   /// compute the support reaction and store it in force
   void updateSupportReaction();
 
 
 public:
 
   //protected: Daniel changed it just for a test
   /// compute A and solve @f[ A\delta u = f_ext - f_int @f]
   template <NewmarkBeta::IntegrationSchemeCorrectorType type>
   void solve(Array<Real> &increment, Real block_val = 1.,
              bool need_factorize = true, bool has_profile_changed = false);
 
 private:
   /// re-initialize the J matrix (to use if the profile of K changed)
   void initJacobianMatrix();
 
   /* ------------------------------------------------------------------------ */
   /* Explicit/Implicit                                                        */
   /* ------------------------------------------------------------------------ */
 
 public:
   /// Update the stresses for the computation of the residual of the Stiffness
   /// matrix in the case of finite deformation
   void computeStresses();
 
   /// synchronize the ghost element boundaries values
   void synchronizeBoundaries();
 
   /* ------------------------------------------------------------------------ */
   /* Materials (solid_mechanics_model_material.cc)                            */
   /* ------------------------------------------------------------------------ */
 public:
   /// registers all the custom materials of a given type present in the input file
   template <typename M>
   void registerNewCustomMaterials(const ID & mat_type);
 
   /// register an empty material of a given type
   template <typename M>
   Material & registerNewEmptyMaterial(const std::string & name);
 
   // /// Use a UIntData in the mesh to specify the material to use per element
   // void setMaterialIDsFromIntData(const std::string & data_name);
 
   /// reassigns materials depending on the material selector
   virtual void reassignMaterial();
 
 protected:
   /// register a material in the dynamic database
   template <typename M>
   Material & registerNewMaterial(const ParserSection & mat_section);
 
   /// read the material files to instantiate all the materials
   void instantiateMaterials();
 
   /// set the element_id_by_material and add the elements to the good materials
   void assignMaterialToElements(const ElementTypeMapArray<UInt> * filter = NULL);
 
   /* ------------------------------------------------------------------------ */
   /* Mass (solid_mechanics_model_mass.cc)                                     */
   /* ------------------------------------------------------------------------ */
 public:
   /// assemble the lumped mass matrix
   void assembleMassLumped();
 
   /// assemble the mass matrix for consistent mass resolutions
   void assembleMass();
 
 
 protected:
   /// assemble the lumped mass matrix for local and ghost elements
   void assembleMassLumped(GhostType ghost_type);
 
   /// assemble the mass matrix for either _ghost or _not_ghost elements
   void assembleMass(GhostType ghost_type);
 
   /// fill a vector of rho
   void computeRho(Array <Real> & rho,
 		  ElementType    type,
 		  GhostType      ghost_type);
 
 
   /* ------------------------------------------------------------------------ */
   /* Data Accessor inherited members                                          */
   /* ------------------------------------------------------------------------ */
 public:
   inline virtual UInt getNbDataForElements(const Array <Element> & elements,
 					   SynchronizationTag tag) const;
 
   inline virtual void packElementData(CommunicationBuffer &   buffer,
 				      const Array <Element> & elements,
 				      SynchronizationTag      tag) const;
 
   inline virtual void unpackElementData(CommunicationBuffer &   buffer,
 					const Array <Element> & elements,
 					SynchronizationTag      tag);
 
   inline virtual UInt getNbDataToPack(SynchronizationTag tag) const;
   inline virtual UInt getNbDataToUnpack(SynchronizationTag tag) const;
 
   inline virtual void packData(CommunicationBuffer & buffer,
 			       const UInt            index,
 			       SynchronizationTag    tag) const;
 
   inline virtual void unpackData(CommunicationBuffer & buffer,
 				 const UInt            index,
 				 SynchronizationTag    tag);
 
 protected:
   inline void splitElementByMaterial(const Array <Element> & elements,
 				     Array <Element> *       elements_per_mat) const;
 
   /* ------------------------------------------------------------------------ */
   /* Mesh Event Handler inherited members                                     */
   /* ------------------------------------------------------------------------ */
 protected:
   virtual void onNodesAdded(const Array <UInt> &  nodes_list,
 			    const NewNodesEvent & event);
   virtual void onNodesRemoved(const Array <UInt> &      element_list,
 			      const Array <UInt> &      new_numbering,
 			      const RemovedNodesEvent & event);
   virtual void onElementsAdded(const Array <Element> &  nodes_list,
 			       const NewElementsEvent & event);
   virtual void onElementsRemoved(const Array <Element> &      element_list,
 				 const ElementTypeMapArray<UInt> &    new_numbering,
 				 const RemovedElementsEvent & event);
 
   /* ------------------------------------------------------------------------ */
   /* Dumpable interface (kept for convenience) and dumper relative functions  */
   /* ------------------------------------------------------------------------ */
 public:
 
 
   virtual void onDump();
 
   //! decide wether a field is a material internal or not
   bool isInternal(const std::string & field_name, const ElementKind & element_kind);
 #ifndef SWIG  
   //! give the amount of data per element
   ElementTypeMap<UInt> getInternalDataPerElem(const std::string & field_name,
 					     const ElementKind & kind);
 
   //! flatten a given material internal field 
   ElementTypeMapArray<Real> & flattenInternal(const std::string & field_name,
 					     const ElementKind & kind);
   //! flatten all the registered material internals
   void flattenAllRegisteredInternals(const ElementKind & kind);
 #endif
 
   virtual dumper::Field * createNodalFieldReal(const std::string & field_name,
 					       const std::string & group_name,
 					       bool padding_flag);
 
   virtual dumper::Field * createNodalFieldBool(const std::string & field_name,
 					       const std::string & group_name,
 					       bool padding_flag);
   
 
   virtual dumper::Field * createElementalField(const std::string & field_name, 
 					       const std::string & group_name,
 					       bool padding_flag,
 					       const ElementKind & kind);
 
 
 
   virtual void dump(const std::string & dumper_name);
 
   virtual void dump(const std::string & dumper_name, UInt step);
 
   virtual void dump(const std::string & dumper_name, Real time, UInt step);
 
   virtual void dump();
 
   virtual void dump(UInt step);
 
   virtual void dump(Real time, UInt step);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// return the dimension of the system space
   AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt);
 
   /// get the current value of the time step
   AKANTU_GET_MACRO(TimeStep, time_step, Real);
   /// set the value of the time step
   void setTimeStep(Real time_step);
 
   /// get the value of the conversion from forces/ mass to acceleration
   AKANTU_GET_MACRO(F_M2A, f_m2a, Real);
 
   /// set the value of the conversion from forces/ mass to acceleration
   AKANTU_SET_MACRO(F_M2A, f_m2a, Real);
 
   /// get the SolidMechanicsModel::displacement vector
   AKANTU_GET_MACRO(Displacement,    *displacement,           Array <Real> &);
 
   /// get the SolidMechanicsModel::previous_displacement vector
   AKANTU_GET_MACRO(PreviousDisplacement, *previous_displacement, Array <Real> &);
 
   /// get the SolidMechanicsModel::current_position vector \warn only consistent
   /// after a call to SolidMechanicsModel::updateCurrentPosition
   AKANTU_GET_MACRO(CurrentPosition, *current_position, const Array <Real> &);
 
   /// get  the SolidMechanicsModel::increment  vector \warn  only  consistent if
   /// SolidMechanicsModel::setIncrementFlagOn has been called before
   AKANTU_GET_MACRO(Increment,       *increment,              Array <Real> &);
 
   /// get the lumped SolidMechanicsModel::mass vector
   AKANTU_GET_MACRO(Mass,            *mass,                   Array <Real> &);
 
   /// get the SolidMechanicsModel::velocity vector
   AKANTU_GET_MACRO(Velocity,        *velocity,               Array <Real> &);
 
   /// get    the    SolidMechanicsModel::acceleration    vector,   updated    by
   /// SolidMechanicsModel::updateAcceleration
   AKANTU_GET_MACRO(Acceleration,    *acceleration,           Array <Real> &);
 
   /// get the SolidMechanicsModel::force vector (boundary forces)
   AKANTU_GET_MACRO(Force,           *force,                  Array <Real> &);
 
   /// get     the    SolidMechanicsModel::residual    vector,     computed    by
   /// SolidMechanicsModel::updateResidual
   AKANTU_GET_MACRO(Residual,        *residual,               Array <Real> &);
 
   /// get the SolidMechanicsModel::blocked_dofs vector
   AKANTU_GET_MACRO(BlockedDOFs,     *blocked_dofs,           Array <bool> &);
 
   /// get the SolidMechnicsModel::incrementAcceleration vector
   AKANTU_GET_MACRO(IncrementAcceleration, *increment_acceleration, Array <Real> &);
 
   /// get the value of the SolidMechanicsModel::increment_flag
   AKANTU_GET_MACRO(IncrementFlag, increment_flag, bool);
 
   /// get a particular material (by material index)
   inline Material & getMaterial(UInt mat_index);
 
   /// get a particular material (by material index)
   inline const Material & getMaterial(UInt mat_index) const;
 
   /// get a particular material (by material name)
   inline Material & getMaterial(const std::string & name);
 
   /// get a particular material (by material name)
   inline const Material & getMaterial(const std::string & name) const;
 
   /// get a particular material id from is name
   inline UInt getMaterialIndex(const std::string & name) const;
 
   /// give the number of materials
   inline UInt getNbMaterials() const {
     return materials.size();
   }
 
   inline void setMaterialSelector(MaterialSelector & selector);
 
   /// give the material internal index from its id
   Int getInternalIndexFromID(const ID & id) const;
 
   /// compute the stable time step
   Real getStableTimeStep();
 
   /// compute the potential energy
   Real getPotentialEnergy();
 
   /// compute the kinetic energy
   Real getKineticEnergy();
   Real getKineticEnergy(const ElementType & type, UInt index);
 
   /// compute the external work (for impose displacement, the velocity should be given too)
   Real getExternalWork();
 
   /// get the energies
   Real getEnergy(const std::string & energy_id);
 
   /// compute the energy for energy
   Real getEnergy(const std::string & energy_id, const ElementType & type, UInt index);
 
   /**
    * @brief set the SolidMechanicsModel::increment_flag  to on, the activate the
    * update of the SolidMechanicsModel::increment vector
    */
   void setIncrementFlagOn();
 
   /// get the stiffness matrix
   AKANTU_GET_MACRO(StiffnessMatrix, *stiffness_matrix, SparseMatrix &);
 
   /// get the global jacobian matrix of the system
   AKANTU_GET_MACRO(GlobalJacobianMatrix, *jacobian_matrix, const SparseMatrix &);
 
   /// get the mass matrix
   AKANTU_GET_MACRO(MassMatrix, *mass_matrix, SparseMatrix &);
 
   /// get the velocity damping matrix
   AKANTU_GET_MACRO(VelocityDampingMatrix, *velocity_damping_matrix, SparseMatrix &);
 
   /// get the FEEngine object to integrate or interpolate on the boundary
   inline FEEngine & getFEEngineBoundary(const ID & name = "");
 
   /// get integrator
   AKANTU_GET_MACRO(Integrator, *integrator, const IntegrationScheme2ndOrder &);
 
   /// get access to the internal solver
   AKANTU_GET_MACRO(Solver, *solver, Solver &);
 
   /// get synchronizer
   AKANTU_GET_MACRO(Synchronizer, *synch_parallel, const DistributedSynchronizer &);
 
-  AKANTU_GET_MACRO(ElementIndexByMaterial, element_index_by_material, const ElementTypeMapArray <UInt> &);
+  AKANTU_GET_MACRO(MaterialByElement, material_index, const ElementTypeMapArray<UInt> &);
 
   /// vectors containing local material element index for each global element index
-  AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementIndexByMaterial, element_index_by_material, UInt);
-  AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementIndexByMaterial, element_index_by_material, UInt);
+  AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialByElement, material_index, UInt);
+  AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialByElement, material_index, UInt);
+  AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialLocalNumbering, material_local_numbering, UInt);
+  AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialLocalNumbering, material_local_numbering, UInt);
 
   /// Get the type of analysis method used
   AKANTU_GET_MACRO(AnalysisMethod, method, AnalysisMethod);
 
-
   template <int dim, class model_type>
   friend struct ContactData;
 
   template <int Dim, AnalysisMethod s, ContactResolutionMethod r>
   friend class ContactResolution;
-            
 
 protected:
   friend class Material;
 
 protected:
   /// compute the stable time step
   Real getStableTimeStep(const GhostType & ghost_type);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// time step
   Real time_step;
 
   /// conversion coefficient form force/mass to acceleration
   Real f_m2a;
 
   /// displacements array
   Array <Real> *displacement;
 
   /// displacements array at the previous time step (used in finite deformation)
   Array <Real> *previous_displacement;
 
   /// lumped mass array
   Array <Real> *mass;
 
   /// velocities array
   Array <Real> *velocity;
 
   /// accelerations array
   Array <Real> *acceleration;
 
   /// accelerations array
   Array <Real> *increment_acceleration;
 
   /// forces array
   Array <Real> *force;
 
   /// residuals array
   Array <Real> *residual;
 
   /// array specifing if a degree of freedom is blocked or not
   Array <bool> *blocked_dofs;
 
   /// array of current position used during update residual
   Array <Real> *current_position;
 
   /// mass matrix
   SparseMatrix *mass_matrix;
 
   /// velocity damping matrix
   SparseMatrix *velocity_damping_matrix;
 
   /// stiffness matrix
   SparseMatrix *stiffness_matrix;
 
   /// jacobian matrix @f[A = cM + dD + K@f] with @f[c = \frac{1}{\beta \Delta
   /// t^2}, d = \frac{\gamma}{\beta \Delta t} @f]
   SparseMatrix *jacobian_matrix;
 
-  /// vectors containing local material element index for each global element index
-  ElementTypeMapArray<UInt> element_index_by_material;
+  /// Arrays containing the material index for each element
+  ElementTypeMapArray<UInt> material_index;
+
+  /// Arrays containing the position in the element filter of the material (material's local numbering)
+  ElementTypeMapArray<UInt> material_local_numbering;
 
   /// list of used materials
   std::vector <Material *> materials;
 
   /// mapping between material name and material internal id
   std::map <std::string, UInt> materials_names_to_id;
 
   /// class defining of to choose a material
   MaterialSelector *material_selector;
 
   /// define if it is the default selector or not
   bool is_default_material_selector;
 
   /// integration scheme of second order used
   IntegrationScheme2ndOrder *integrator;
 
   /// increment of displacement
   Array <Real> *increment;
 
   /// flag defining if the increment must be computed or not
   bool increment_flag;
 
   /// solver for implicit
   Solver *solver;
 
   /// analysis method check the list in akantu::AnalysisMethod
   AnalysisMethod method;
 
   /// internal synchronizer for parallel computations
   DistributedSynchronizer *synch_parallel;
 
   /// tells if the material are instantiated
   bool are_materials_instantiated;
 
   /// map a registered internals to be flattened for dump purposes
   std::map<std::pair<std::string,ElementKind>,ElementTypeMapArray<Real> *> registered_internals;
 };
 
 
 /* -------------------------------------------------------------------------- */
 namespace BC {
   namespace Neumann {
     typedef FromHigherDim FromStress;
     typedef FromSameDim   FromTraction;
   }
 }
 
 __END_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 #include "parser.hh"
 #include "material.hh"
 
 __BEGIN_AKANTU__
 
 #include "solid_mechanics_model_tmpl.hh"
 
 #if defined (AKANTU_INCLUDE_INLINE_IMPL)
 #  include "solid_mechanics_model_inline_impl.cc"
 #endif
 
 /// standard output stream operator
 inline std::ostream & operator << (std::ostream & stream, const SolidMechanicsModel &_this) {
   _this.printself(stream);
   return stream;
 }
 
 __END_AKANTU__
 
 
 #include "material_selector_tmpl.hh"
 
 #endif /* __AKANTU_SOLID_MECHANICS_MODEL_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc
index a77393efa..526a01317 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc
@@ -1,906 +1,862 @@
 /**
  * @file   solid_mechanics_model_cohesive.cc
  *
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Tue May 08 2012
  * @date last modification: Fri Sep 05 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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include <algorithm>
 #include "shape_cohesive.hh"
 #include "solid_mechanics_model_cohesive.hh"
 #include "dumpable_inline_impl.hh"
 #include "material_cohesive.hh"
 
 #ifdef AKANTU_USE_IOHELPER
 #  include "dumper_paraview.hh"
 #endif
 
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 const SolidMechanicsModelCohesiveOptions default_solid_mechanics_model_cohesive_options(_explicit_lumped_mass,
 											false,
 											false,
 											true);
 
 /* -------------------------------------------------------------------------- */
 
 SolidMechanicsModelCohesive::SolidMechanicsModelCohesive(Mesh & mesh,
 							 UInt dim,
 							 const ID & id,
 							 const MemoryID & memory_id) :
   SolidMechanicsModel(mesh, dim, id, memory_id),
   tangents("tangents", id),
   stress_on_facet("stress_on_facet", id),
   facet_stress("facet_stress", id),
   facet_material("facet_material", id) {
   AKANTU_DEBUG_IN();
 
   inserter = NULL;
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   facet_synchronizer = NULL;
   facet_stress_synchronizer = NULL;
   cohesive_distributed_synchronizer = NULL;
   global_connectivity = NULL;
 #endif
 
   delete material_selector;
   material_selector = new DefaultMaterialCohesiveSelector(*this);
 
   this->registerEventHandler(*this);
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.registerDumper<DumperParaview>("cohesive elements", id);
   this->mesh.addDumpMeshToDumper("cohesive elements",
-			    mesh, spatial_dimension, _not_ghost, _ek_cohesive);
+				 mesh, spatial_dimension, _not_ghost, _ek_cohesive);
 #endif
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 SolidMechanicsModelCohesive::~SolidMechanicsModelCohesive() {
   AKANTU_DEBUG_IN();
 
   delete inserter;
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   delete cohesive_distributed_synchronizer;
   delete facet_synchronizer;
   delete facet_stress_synchronizer;
 #endif
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::setTimeStep(Real time_step) {
   SolidMechanicsModel::setTimeStep(time_step);
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.getDumper("cohesive elements").setTimeStep(time_step);
 #endif
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initFull(const ModelOptions & options) {
   AKANTU_DEBUG_IN();
 
   const SolidMechanicsModelCohesiveOptions & smmc_options =
     dynamic_cast<const SolidMechanicsModelCohesiveOptions &>(options);
 
   this->stress_interpolation = smmc_options.stress_interpolation;
   this->is_extrinsic = smmc_options.extrinsic;
 
   if (!inserter)
     inserter = new CohesiveElementInserter(mesh, is_extrinsic, synch_parallel,
 					   id+":cohesive_element_inserter");
 
   SolidMechanicsModel::initFull(options);
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   if (facet_synchronizer != NULL)
     inserter->initParallel(facet_synchronizer);
 #endif
 
   if (is_extrinsic)
     initAutomaticInsertion();
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initMaterials() {
   AKANTU_DEBUG_IN();
 
   // make sure the material are instantiated
   if(!are_materials_instantiated) instantiateMaterials();
 
   /// find the first cohesive material
   UInt cohesive_index = 0;
 
   while ((dynamic_cast<MaterialCohesive *>(materials[cohesive_index]) == NULL)
 	 && cohesive_index <= materials.size())
     ++cohesive_index;
 
   AKANTU_DEBUG_ASSERT(cohesive_index != materials.size(),
 		      "No cohesive materials in the material input file");
 
   material_selector->setFallback(cohesive_index);
 
   // set the facet information in the material in case of dynamic insertion
   if (is_extrinsic) {
     const Mesh & mesh_facets = inserter->getMeshFacets();
     mesh_facets.initElementTypeMapArray(facet_material, 1, spatial_dimension - 1);
 
     Element element;
     for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) {
       element.ghost_type = *gt;
       Mesh::type_iterator first = mesh_facets.firstType(spatial_dimension - 1, *gt);
       Mesh::type_iterator last  = mesh_facets.lastType(spatial_dimension - 1, *gt);
       for(;first != last; ++first) {
 	element.type = *first;
 	Array<UInt> & f_material = facet_material(*first, *gt);
 	UInt nb_element = mesh_facets.getNbElement(*first, *gt);
 	f_material.resize(nb_element);
 	f_material.set(cohesive_index);
 	for (UInt el = 0; el < nb_element; ++el) {
 	  element.element = el;
 	  UInt mat_index = (*material_selector)(element);
 	  f_material(el) = mat_index;
 	  MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*materials[mat_index]);
 	  mat.addFacet(element);
 	}
       }
     }
   } else {
     for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) {
       Mesh::type_iterator first = mesh.firstType(spatial_dimension, *gt, _ek_cohesive);
       Mesh::type_iterator last  = mesh.lastType(spatial_dimension, *gt, _ek_cohesive);
 
       for(;first != last; ++first) {
-	Array<UInt> & el_id_by_mat = element_index_by_material(*first, *gt);
-	Vector<UInt> el_mat(2); el_mat(0) = cohesive_index; el_mat(1) = 0;
-	el_id_by_mat.set(el_mat);
+	Array<UInt> & mat_indexes = this->material_index(*first, *gt);
+	Array<UInt> & mat_loc_num = this->material_local_numbering(*first, *gt);
+	mat_indexes.set(cohesive_index);
+	mat_loc_num.clear();
       }
     }
   }
 
   SolidMechanicsModel::initMaterials();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /**
  * Initialize the model,basically it  pre-compute the shapes, shapes derivatives
  * and jacobian
  *
  */
 void SolidMechanicsModelCohesive::initModel() {
   AKANTU_DEBUG_IN();
 
   SolidMechanicsModel::initModel();
 
   registerFEEngineObject<MyFEEngineCohesiveType>("CohesiveFEEngine", mesh, spatial_dimension);
 
   /// add cohesive type connectivity
   ElementType type = _not_defined;
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType type_ghost = *gt;
 
     Mesh::type_iterator it   = mesh.firstType(spatial_dimension, type_ghost);
     Mesh::type_iterator last = mesh.lastType(spatial_dimension, type_ghost);
 
     for (; it != last; ++it) {
       const Array<UInt> & connectivity = mesh.getConnectivity(*it, type_ghost);
       if (connectivity.getSize() != 0) {
 	type = *it;
 	ElementType type_facet = Mesh::getFacetType(type);
 	ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
 	mesh.addConnectivityType(type_cohesive, type_ghost);
       }
     }
   }
 
   AKANTU_DEBUG_ASSERT(type != _not_defined, "No elements in the mesh");
 
   getFEEngine("CohesiveFEEngine").initShapeFunctions(_not_ghost);
   getFEEngine("CohesiveFEEngine").initShapeFunctions(_ghost);
 
   registerFEEngineObject<MyFEEngineType>("FacetsFEEngine",
 					 mesh.getMeshFacets(),
 					 spatial_dimension - 1);
 
   if (is_extrinsic) {
     getFEEngine("FacetsFEEngine").initShapeFunctions(_not_ghost);
     getFEEngine("FacetsFEEngine").initShapeFunctions(_ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::limitInsertion(BC::Axis axis,
 						 Real first_limit,
 						 Real second_limit) {
   AKANTU_DEBUG_IN();
   inserter->setLimit(axis, first_limit, second_limit);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::insertIntrinsicElements() {
   AKANTU_DEBUG_IN();
   inserter->insertIntrinsicElements();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initAutomaticInsertion() {
   AKANTU_DEBUG_IN();
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
   if (facet_stress_synchronizer != NULL) {
     DataAccessor * data_accessor = this;
     const ElementTypeMapArray<UInt> & rank_to_element = synch_parallel->getPrankToElement();
 
     facet_stress_synchronizer->updateFacetStressSynchronizer(*inserter,
 							     rank_to_element,
 							     *data_accessor);
   }
 #endif
 
   inserter->getMeshFacets().initElementTypeMapArray(facet_stress,
 						    2 * spatial_dimension * spatial_dimension,
 						    spatial_dimension - 1);
 
   resizeFacetStress();
 
   /// compute normals on facets
   computeNormals();
 
   /// allocate stress_on_facet to store element stress on facets
   mesh.initElementTypeMapArray(stress_on_facet,
 			      spatial_dimension * spatial_dimension,
 			      spatial_dimension);
 
   Mesh::type_iterator it   = mesh.firstType(spatial_dimension);
   Mesh::type_iterator last = mesh.lastType(spatial_dimension);
 
   for (; it != last; ++it) {
     ElementType type = *it;
     UInt nb_element = mesh.getNbElement(type);
 
     UInt nb_facet_per_elem = Mesh::getNbFacetsPerElement(type);
     ElementType type_facet = Mesh::getFacetType(type);
     UInt nb_quad_per_facet = getFEEngine("FacetsFEEngine").getNbQuadraturePoints(type_facet);
 
     stress_on_facet(type).resize(nb_quad_per_facet * nb_facet_per_elem * nb_element);
   }
 
   if (stress_interpolation)
     initStressInterpolation();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::updateAutomaticInsertion() {
   AKANTU_DEBUG_IN();
 
   inserter->limitCheckFacets();
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
     if (facet_stress_synchronizer != NULL) {
       DataAccessor * data_accessor = this;
       const ElementTypeMapArray<UInt> & rank_to_element = synch_parallel->getPrankToElement();
 
       facet_stress_synchronizer->updateFacetStressSynchronizer(*inserter,
 							       rank_to_element,
 							       *data_accessor);
     }
 #endif
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initStressInterpolation() {
   Mesh & mesh_facets = inserter->getMeshFacets();
 
   /// compute quadrature points coordinates on facets
   Array<Real> & position = mesh.getNodes();
 
   ElementTypeMapArray<Real> quad_facets("quad_facets", id);
   mesh_facets.initElementTypeMapArray(quad_facets,
 				     spatial_dimension, spatial_dimension - 1);
 
   getFEEngine("FacetsFEEngine").interpolateOnQuadraturePoints(position, quad_facets);
 
   /// compute elements quadrature point positions and build
   /// element-facet quadrature points data structure
   ElementTypeMapArray<Real> elements_quad_facets("elements_quad_facets", id);
 
   mesh.initElementTypeMapArray(elements_quad_facets,
 			      spatial_dimension,
 			      spatial_dimension);
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end(); ++gt) {
 
     GhostType elem_gt = *gt;
 
     Mesh::type_iterator it   = mesh.firstType(spatial_dimension, elem_gt);
     Mesh::type_iterator last = mesh.lastType(spatial_dimension, elem_gt);
 
     for (; it != last; ++it) {
       ElementType type = *it;
       UInt nb_element = mesh.getNbElement(type, elem_gt);
       if (nb_element == 0) continue;
 
       /// compute elements' quadrature points and list of facet
       /// quadrature points positions by element
       Array<Element> & facet_to_element = mesh_facets.getSubelementToElement(type,
 									     elem_gt);
       UInt nb_facet_per_elem = facet_to_element.getNbComponent();
 
       Array<Real> & el_q_facet = elements_quad_facets(type, elem_gt);
 
       ElementType facet_type = Mesh::getFacetType(type);
 
       UInt nb_quad_per_facet =
 	getFEEngine("FacetsFEEngine").getNbQuadraturePoints(facet_type);
 
       el_q_facet.resize(nb_element * nb_facet_per_elem * nb_quad_per_facet);
 
       for (UInt el = 0; el < nb_element; ++el) {
 	for (UInt f = 0; f < nb_facet_per_elem; ++f) {
 	  Element global_facet_elem = facet_to_element(el, f);
 	  UInt global_facet = global_facet_elem.element;
 	  GhostType facet_gt = global_facet_elem.ghost_type;
 	  const Array<Real> & quad_f = quad_facets(facet_type, facet_gt);
 
 	  for (UInt q = 0; q < nb_quad_per_facet; ++q) {
 	    for (UInt s = 0; s < spatial_dimension; ++s) {
 	      el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet
 			 + f * nb_quad_per_facet + q, s)
 		= quad_f(global_facet * nb_quad_per_facet + q, s);
 	    }
 	  }
 	}
       }
     }
   }
 
   /// loop over non cohesive materials
   for (UInt m = 0; m < materials.size(); ++m) {
     try {
       MaterialCohesive & mat __attribute__((unused)) =
 	dynamic_cast<MaterialCohesive &>(*materials[m]);
     } catch(std::bad_cast&) {
       /// initialize the interpolation function
       materials[m]->initElementalFieldInterpolation(elements_quad_facets);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::updateResidual(bool need_initialize) {
   AKANTU_DEBUG_IN();
 
   if (need_initialize) initializeUpdateResidualData();
 
   // f -= fint
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     try {
       MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(**mat_it);
       mat.computeTraction(_not_ghost);
     } catch (std::bad_cast & bce) { }
   }
 
   SolidMechanicsModel::updateResidual(false);
 
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     try {
       MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(**mat_it);
       mat.computeEnergies();
     } catch (std::bad_cast & bce) { }
   }
 
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::computeNormals() {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh_facets = inserter->getMeshFacets();
   getFEEngine("FacetsFEEngine").computeNormalsOnControlPoints(_not_ghost);
 
   /**
    *  @todo store tangents while computing normals instead of
    *  recomputing them as follows:
    */
   /* ------------------------------------------------------------------------ */
   UInt tangent_components = spatial_dimension * (spatial_dimension - 1);
 
   mesh_facets.initElementTypeMapArray(tangents,
 				     tangent_components,
 				     spatial_dimension - 1);
 
   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 facet_type = *it;
 
     const Array<Real> & normals =
       getFEEngine("FacetsFEEngine").getNormalsOnQuadPoints(facet_type);
 
     UInt nb_quad = normals.getSize();
 
     Array<Real> & tang = tangents(facet_type);
     tang.resize(nb_quad);
 
     Real * normal_it = normals.storage();
     Real * tangent_it = tang.storage();
 
     /// compute first tangent
     for (UInt q = 0; q < nb_quad; ++q) {
 
       /// if normal is orthogonal to xy plane, arbitrarly define tangent
       if ( Math::are_float_equal(Math::norm2(normal_it), 0) )
 	tangent_it[0] = 1;
       else
 	Math::normal2(normal_it, tangent_it);
 
       normal_it += spatial_dimension;
       tangent_it += tangent_components;
     }
 
     /// compute second tangent (3D case)
     if (spatial_dimension == 3) {
       normal_it = normals.storage();
       tangent_it = tang.storage();
 
       for (UInt q = 0; q < nb_quad; ++q) {
 	Math::normal3(normal_it, tangent_it, tangent_it + spatial_dimension);
 	normal_it += spatial_dimension;
 	tangent_it += tangent_components;
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::averageStressOnFacets(UInt material_index) {
   AKANTU_DEBUG_IN();
 
   Mesh::type_iterator it   = mesh.firstType(spatial_dimension);
   Mesh::type_iterator last = mesh.lastType(spatial_dimension);
 
   /// loop over element type
   for (; it != last; ++it) {
     ElementType type = *it;
     UInt nb_element = mesh.getNbElement(type);
     UInt nb_quad_per_element = getFEEngine().getNbQuadraturePoints(type);
     const Array<Real> & stress = materials[material_index]->getStress(type);
     Array<Real> & s_on_facet = stress_on_facet(type);
 
     UInt nb_facet_per_elem = Mesh::getNbFacetsPerElement(type);
     ElementType type_facet = Mesh::getFacetType(type);
     UInt nb_quad_per_facet = getFEEngine("FacetsFEEngine").getNbQuadraturePoints(type_facet);
     UInt nb_facet_quad_per_elem = nb_quad_per_facet * nb_facet_per_elem;
 
     Array<Real>::const_iterator<Matrix<Real> > stress_it
       = stress.begin(spatial_dimension, spatial_dimension);
     Array<Real>::iterator<Matrix<Real> > s_on_facet_it
       = s_on_facet.begin(spatial_dimension, spatial_dimension);
 
     Matrix<Real> average_stress(spatial_dimension, spatial_dimension);
 
     for (UInt el = 0; el < nb_element; ++el) {
 
       /// compute average stress
       average_stress.clear();
 
       for (UInt q = 0; q < nb_quad_per_element; ++q, ++stress_it)
 	average_stress += *stress_it;
 
       average_stress /= nb_quad_per_element;
 
       /// store average stress
       for (UInt q = 0; q < nb_facet_quad_per_elem; ++q, ++s_on_facet_it)
 	*s_on_facet_it = average_stress;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::fillStressOnFacet() {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh_facets = inserter->getMeshFacets();
   UInt sp2 = spatial_dimension * spatial_dimension;
   UInt sp4 = sp2 * 2;
 
   /// loop over materials
   for (UInt m = 0; m < materials.size(); ++m) {
     try {
       MaterialCohesive & mat __attribute__((unused)) =
 	dynamic_cast<MaterialCohesive &>(*materials[m]);
     } catch(std::bad_cast&) {
 
       if (stress_interpolation)
 	/// interpolate stress on facet quadrature points positions
 	materials[m]->interpolateStress(stress_on_facet);
       else
 	averageStressOnFacets(m);
 
       GhostType ghost_type = _not_ghost;
 
       Mesh::type_iterator it   = mesh.firstType(spatial_dimension, ghost_type);
       Mesh::type_iterator last = mesh.lastType(spatial_dimension, ghost_type);
 
       /// loop over element type
       for (; it != last; ++it) {
 	ElementType type = *it;
 	UInt nb_element = mesh.getNbElement(type, ghost_type);
 	if (nb_element == 0) continue;
 
 	Array<Real> & stress_on_f = stress_on_facet(type, ghost_type);
 
 	/// store the interpolated stresses on the facet_stress vector
 	Array<Element> & facet_to_element =
 	  mesh_facets.getSubelementToElement(type, ghost_type);
 
 	UInt nb_facet_per_elem = facet_to_element.getNbComponent();
 
 	Array<Element>::iterator<Vector<Element> > facet_to_el_it =
 	  facet_to_element.begin(nb_facet_per_elem);
 
 	Array<Real>::iterator< Matrix<Real> > stress_on_f_it =
 	  stress_on_f.begin(spatial_dimension, spatial_dimension);
 
 	ElementType facet_type = _not_defined;
 	GhostType facet_gt = _casper;
 	Array<std::vector<Element> > * element_to_facet = NULL;
 	Array<Real> * f_stress = NULL;
 	Array<bool> * f_check = NULL;
 	UInt nb_quad_per_facet = 0;
 	UInt element_rank = 0;
 
 	Element current_el(type, 0, ghost_type);
 
 	for (UInt el = 0; el < nb_element; ++el, ++facet_to_el_it) {
 	  current_el.element = el;
 	  for (UInt f = 0; f < nb_facet_per_elem; ++f) {
 	    Element global_facet_elem = (*facet_to_el_it)(f);
 	    UInt global_facet = global_facet_elem.element;
 
 	    if (facet_type != global_facet_elem.type ||
 		facet_gt != global_facet_elem.ghost_type) {
 	      facet_type = global_facet_elem.type;
 	      facet_gt = global_facet_elem.ghost_type;
 
 	      element_to_facet =
 		&( mesh_facets.getElementToSubelement(facet_type, facet_gt) );
 	      f_stress = &( facet_stress(facet_type, facet_gt) );
 
 	      nb_quad_per_facet =
 		getFEEngine("FacetsFEEngine").getNbQuadraturePoints(facet_type, facet_gt);
 
 	      f_check = &( inserter->getCheckFacets(facet_type, facet_gt) );
 	    }
 
 	    if (!(*f_check)(global_facet)) {
 	      stress_on_f_it += nb_quad_per_facet;
 	      continue;
 	    }
 
 	    for (UInt q = 0; q < nb_quad_per_facet; ++q, ++stress_on_f_it) {
 
 	      element_rank = (*element_to_facet)(global_facet)[0] != current_el;
 
 	      Matrix<Real> facet_stress_local(f_stress->storage()
 					      + (global_facet * nb_quad_per_facet + q) * sp4
 					      + element_rank * sp2,
 					      spatial_dimension,
 					      spatial_dimension);
 
 	      facet_stress_local = *stress_on_f_it;
 	    }
 	  }
 	}
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
-/* -------------------------------------------------------------------------- */
-void SolidMechanicsModelCohesive::reassignMaterial() {
-  AKANTU_DEBUG_IN();
-
-  SolidMechanicsModel::reassignMaterial();
-
-  std::vector< Array<Element> > element_to_add   (materials.size());
-  std::vector< Array<Element> > element_to_remove(materials.size());
-
-  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;
-
-    Mesh::type_iterator it  = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive);
-    Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive);
-    for(; it != end; ++it) {
-
-      ElementType type = *it;
-      element.type = type;
-      element.kind = Mesh::getKind(type);
-
-      UInt nb_element = mesh.getNbElement(type, ghost_type);
-
-      Array<UInt> & el_index_by_mat = element_index_by_material(type, ghost_type);
-
-      for (UInt el = 0; el < nb_element; ++el) {
-	element.element = el;
-
-	UInt old_material = el_index_by_mat(el, 0);
-	UInt new_material = (*material_selector)(element);
-
-	if(old_material != new_material) {
-	  element_to_add   [new_material].push_back(element);
-	  element_to_remove[old_material].push_back(element);
-	}
-      }
-    }
-  }
-
-  std::vector<Material *>::iterator mat_it;
-  UInt mat_index = 0;
-  for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it, ++mat_index) {
-    (*mat_it)->removeElements(element_to_remove[mat_index]);
-    (*mat_it)->addElements   (element_to_add[mat_index]);
-  }
-
-  AKANTU_DEBUG_OUT();
-}
-
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::checkCohesiveStress() {
   AKANTU_DEBUG_IN();
 
   fillStressOnFacet();
 
 #if defined(AKANTU_DEBUG_TOOLS)
   debug::element_manager.printData(debug::_dm_model_cohesive,
 				   "Interpolated stresses before",
 				   facet_stress);
 #endif
 
   synch_registry->synchronize(_gst_smmc_facets_stress);
 
 #if defined(AKANTU_DEBUG_TOOLS)
   debug::element_manager.printData(debug::_dm_model_cohesive,
 				   "Interpolated stresses",
 				   facet_stress);
 #endif
 
   for (UInt m = 0; m < materials.size(); ++m) {
     try {
       MaterialCohesive & mat_cohesive = dynamic_cast<MaterialCohesive &>(*materials[m]);
       /// check which not ghost cohesive elements are to be created
       mat_cohesive.checkInsertion();
     } catch(std::bad_cast&) { }
   }
 
   /// communicate data among processors
   synch_registry->synchronize(_gst_smmc_facets);
 
   /// insert cohesive elements
   inserter->insertElements();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::onElementsAdded(const Array<Element> & element_list,
 						  const NewElementsEvent & event) {
   AKANTU_DEBUG_IN();
 
+#if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
+  updateCohesiveSynchronizers();
+#endif
+
   SolidMechanicsModel::onElementsAdded(element_list, event);
 
+#if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
+  if (cohesive_distributed_synchronizer != NULL)
+    cohesive_distributed_synchronizer->computeAllBufferSizes(*this);
+#endif
+
   /// update shape functions
   getFEEngine("CohesiveFEEngine").initShapeFunctions(_not_ghost);
   getFEEngine("CohesiveFEEngine").initShapeFunctions(_ghost);
 
-#if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
-  updateCohesiveSynchronizers();
-#endif
-
   if (is_extrinsic) resizeFacetStress();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::onNodesAdded(const Array<UInt> & doubled_nodes,
 					       __attribute__((unused)) const NewNodesEvent & event) {
   AKANTU_DEBUG_IN();
 
   UInt nb_new_nodes = doubled_nodes.getSize();
   Array<UInt> nodes_list(nb_new_nodes);
 
   for (UInt n = 0; n < nb_new_nodes; ++n)
     nodes_list(n) = doubled_nodes(n, 1);
 
   SolidMechanicsModel::onNodesAdded(nodes_list, event);
 
   for (UInt n = 0; n < nb_new_nodes; ++n) {
 
     UInt old_node = doubled_nodes(n, 0);
     UInt new_node = doubled_nodes(n, 1);
 
     for (UInt dim = 0; dim < spatial_dimension; ++dim) {
       (*displacement)(new_node, dim) = (*displacement)(old_node, dim);
       (*velocity)    (new_node, dim) = (*velocity)    (old_node, dim);
       (*acceleration)(new_node, dim) = (*acceleration)(old_node, dim);
       (*blocked_dofs)(new_node, dim) = (*blocked_dofs)(old_node, dim);
 
       if (current_position)
 	(*current_position)(new_node, dim) = (*current_position)(old_node, dim);
 
       if (increment_acceleration)
 	(*increment_acceleration)(new_node, dim)
 	  = (*increment_acceleration)(old_node, dim);
 
       if (increment)
 	(*increment)(new_node, dim) = (*increment)(old_node, dim);
 
       if (previous_displacement)
 	(*previous_displacement)(new_node, dim)
 	  = (*previous_displacement)(old_node, dim);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::onEndSolveStep(const AnalysisMethod & method) {
 
   AKANTU_DEBUG_IN();
 
   /******************************************************************************
     This is required because the Cauchy stress is the stress measure that is used
      to check the insertion of cohesive elements
   ******************************************************************************/
 
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     Material & mat = **mat_it;
     if(mat.isFiniteDeformation())
       mat.computeAllCauchyStresses(_not_ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   stream << space << "SolidMechanicsModelCohesive [" << std::endl;
 
   SolidMechanicsModel::printself(stream, indent + 1);
 
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::resizeFacetStress() {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh_facets = inserter->getMeshFacets();
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();
        gt != ghost_type_t::end();
        ++gt) {
     GhostType ghost_type = *gt;
 
     Mesh::type_iterator it  = mesh_facets.firstType(spatial_dimension - 1, ghost_type);
     Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, ghost_type);
     for(; it != end; ++it) {
       ElementType type = *it;
 
       UInt nb_facet = mesh_facets.getNbElement(type, ghost_type);
 
       UInt nb_quadrature_points =
 	getFEEngine("FacetsFEEngine").getNbQuadraturePoints(type, ghost_type);
 
       UInt new_size = nb_facet * nb_quadrature_points;
 
       facet_stress(type, ghost_type).resize(new_size);
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::addDumpGroupFieldToDumper(const std::string & dumper_name,
 							    const std::string & field_id,
 							    const std::string & group_name,
 							    const ElementKind & element_kind,
 							    bool padding_flag) {
   AKANTU_DEBUG_IN();
 
   ElementKind _element_kind = element_kind;
   if (dumper_name == "cohesive elements") {
     _element_kind = _ek_cohesive;
   }
   SolidMechanicsModel::addDumpGroupFieldToDumper(dumper_name, 
 						 field_id,
 						 group_name,
 						 _element_kind,
 						 padding_flag);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 void SolidMechanicsModelCohesive::onDump(){
   this->flattenAllRegisteredInternals(_ek_cohesive);
   SolidMechanicsModel::onDump();
 }
 
 /* -------------------------------------------------------------------------- */
 
 
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh
index a8bc4dfe7..9d6ec740e 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh
@@ -1,299 +1,295 @@
 /**
  * @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,
 				     bool stress_interpolation = true) :
     SolidMechanicsModelOptions(analysis_method, no_init_materials),
     extrinsic(extrinsic),
     stress_interpolation(stress_interpolation) {}
   bool extrinsic;
   bool stress_interpolation;
 };
 
 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:
-
-  /// reassigns materials depending on the material selector
-  virtual void reassignMaterial();
-
   /// 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
   void checkCohesiveStress();
 
   /// 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();
 
 private:
 
   /// initialize completely the model for extrinsic elements
   void initAutomaticInsertion();
 
   /// initialize stress interpolation
   void initStressInterpolation();
 
   /// compute facets' normals
   void computeNormals();
 
   /// resize facet stress
   void resizeFacetStress();
 
   /// init facets_check array
   void initFacetsCheck();
 
   /// fill stress_on_facet
   void fillStressOnFacet();
 
   /// compute average stress on elements
   void averageStressOnFacets(UInt material_index);
 
   /* ------------------------------------------------------------------------ */
   /* 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;
 
   /// list of stresses on facet quadrature points for every element
   ElementTypeMapArray<Real> stress_on_facet;
 
   /// 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;
 
   /// stress interpolation flag
   bool stress_interpolation;
 
   bool is_extrinsic;
 
   /// cohesive element inserter
   CohesiveElementInserter * inserter;
 
 #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT)
 #include "solid_mechanics_model_cohesive_parallel.hh"
 #endif
 
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 #if defined (AKANTU_PARALLEL_COHESIVE_ELEMENT)
 #  include "solid_mechanics_model_cohesive_inline_impl.cc"
 #endif
 
 /* -------------------------------------------------------------------------- */
 class DefaultMaterialCohesiveSelector : public DefaultMaterialSelector {
 public:
   DefaultMaterialCohesiveSelector(const SolidMechanicsModelCohesive & model) :
-    DefaultMaterialSelector(model.getElementIndexByMaterial()),
+    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__
 
 
 #endif /* __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc
index 15dd25b04..d9f89f870 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc
@@ -1,611 +1,613 @@
 /**
  * @file   solid_mechanics_model_inline_impl.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Wed Aug 04 2010
  * @date last modification: Mon Sep 15 2014
  *
  * @brief  Implementation of the inline functions of the SolidMechanicsModel 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/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 inline Material & SolidMechanicsModel::getMaterial(UInt mat_index) {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT(mat_index < materials.size(),
                      "The model " << id << " has no material no "<< mat_index);
   AKANTU_DEBUG_OUT();
   return *materials[mat_index];
 }
 
 /* -------------------------------------------------------------------------- */
 inline const Material & SolidMechanicsModel::getMaterial(UInt mat_index) const {
   AKANTU_DEBUG_IN();
   AKANTU_DEBUG_ASSERT(mat_index < materials.size(),
                      "The model " << id << " has no material no "<< mat_index);
   AKANTU_DEBUG_OUT();
   return *materials[mat_index];
 }
 
 /* -------------------------------------------------------------------------- */
 inline Material & SolidMechanicsModel::getMaterial(const std::string & name) {
   AKANTU_DEBUG_IN();
   std::map<std::string, UInt>::const_iterator it = materials_names_to_id.find(name);
   AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(),
                      "The model " << id << " has no material named "<< name);
   AKANTU_DEBUG_OUT();
   return *materials[it->second];
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt SolidMechanicsModel::getMaterialIndex(const std::string & name) const {
   AKANTU_DEBUG_IN();
   std::map<std::string, UInt>::const_iterator it = materials_names_to_id.find(name);
   AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(),
                       "The model " << id << " has no material named "<< name);
   AKANTU_DEBUG_OUT();
   return it->second;
 }
 
 /* -------------------------------------------------------------------------- */
 inline const Material & SolidMechanicsModel::getMaterial(const std::string & name) const {
   AKANTU_DEBUG_IN();
   std::map<std::string, UInt>::const_iterator it = materials_names_to_id.find(name);
   AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(),
                       "The model " << id << " has no material named "<< name);
   AKANTU_DEBUG_OUT();
   return *materials[it->second];
 }
 
 /* -------------------------------------------------------------------------- */
 inline void SolidMechanicsModel::setMaterialSelector(MaterialSelector & selector) {
   if(is_default_material_selector) delete material_selector;
   material_selector = &selector;
   is_default_material_selector = false;
 }
 
 /* -------------------------------------------------------------------------- */
 inline FEEngine & SolidMechanicsModel::getFEEngineBoundary(const ID & name) {
   return dynamic_cast<FEEngine &>(getFEEngineClassBoundary<MyFEEngineType>(name));
 }
 
 /* -------------------------------------------------------------------------- */
 inline void SolidMechanicsModel::splitElementByMaterial(const Array<Element> & elements,
                                                        Array<Element> * elements_per_mat) const {
   ElementType current_element_type = _not_defined;
   GhostType current_ghost_type = _casper;
-  const Array<UInt> * elem_mat = NULL;
+  const Array<UInt> * mat_indexes = NULL;
+  const Array<UInt> * mat_loc_num = NULL;
 
   Array<Element>::const_iterator<Element> it  = elements.begin();
   Array<Element>::const_iterator<Element> end = elements.end();
   for (; it != end; ++it) {
     Element el = *it;
 
     if(el.type != current_element_type || el.ghost_type != current_ghost_type) {
       current_element_type = el.type;
       current_ghost_type   = el.ghost_type;
-      elem_mat = &element_index_by_material(el.type, el.ghost_type);
+      mat_indexes = &(this->material_index(el.type, el.ghost_type));
+      mat_loc_num = &(this->material_local_numbering(el.type, el.ghost_type));
     }
 
     UInt old_id = el.element;
-    el.element = (*elem_mat)(old_id, 1);
-    elements_per_mat[(*elem_mat)(old_id, 0)].push_back(el);
+    el.element = (*mat_loc_num)(old_id);
+    elements_per_mat[(*mat_indexes)(old_id)].push_back(el);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt SolidMechanicsModel::getNbDataForElements(const Array<Element> & elements,
                                                      SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
   UInt size = 0;
   UInt nb_nodes_per_element = 0;
 
   Array<Element>::const_iterator<Element> it  = elements.begin();
   Array<Element>::const_iterator<Element> end = elements.end();
   for (; it != end; ++it) {
     const Element & el = *it;
     nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type);
   }
 
   switch(tag) {
   case _gst_material_id: {
-    size += elements.getSize() * 2 * sizeof(UInt);
+    size += elements.getSize() * sizeof(UInt);
     break;
   }
   case _gst_smm_mass: {
     size += nb_nodes_per_element * sizeof(Real) * spatial_dimension; // mass vector
     break;
   }
   case _gst_smm_for_gradu: {
     size += nb_nodes_per_element * spatial_dimension * sizeof(Real); // displacement
    break;
   }
   case _gst_smm_boundary: {
     // force, displacement, boundary
     size += nb_nodes_per_element * spatial_dimension * (2 * sizeof(Real) + sizeof(bool));
     break;
   }
   default: {  }
   }
 
   if(tag != _gst_material_id) {
     Array<Element> * elements_per_mat = new Array<Element>[materials.size()];
     this->splitElementByMaterial(elements, elements_per_mat);
 
     for (UInt i = 0; i < materials.size(); ++i) {
       size += materials[i]->getNbDataForElements(elements_per_mat[i], tag);
     }
     delete [] elements_per_mat;
   }
 
   AKANTU_DEBUG_OUT();
   return size;
 }
 
 /* -------------------------------------------------------------------------- */
 inline void SolidMechanicsModel::packElementData(CommunicationBuffer & buffer,
                                                 const Array<Element> & elements,
                                                 SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
   switch(tag) {
   case _gst_material_id: {
-    packElementalDataHelper(element_index_by_material, buffer, elements, false, getFEEngine());
+    packElementalDataHelper(material_index, buffer, elements, false, getFEEngine());
     break;
   }
   case _gst_smm_mass: {
     packNodalDataHelper(*mass, buffer, elements, mesh);
     break;
   }
   case _gst_smm_for_gradu: {
     packNodalDataHelper(*displacement, buffer, elements, mesh);
     break;
   }
   case _gst_smm_boundary: {
     packNodalDataHelper(*force, buffer, elements, mesh);
     packNodalDataHelper(*velocity, buffer, elements, mesh);
     packNodalDataHelper(*blocked_dofs, buffer, elements, mesh);
     break;
   }
   default: {
   }
   }
 
   if(tag != _gst_material_id) {
     Array<Element> * elements_per_mat = new Array<Element>[materials.size()];
     splitElementByMaterial(elements, elements_per_mat);
 
     for (UInt i = 0; i < materials.size(); ++i) {
       materials[i]->packElementData(buffer, elements_per_mat[i], tag);
     }
 
     delete [] elements_per_mat;
   }
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 inline void SolidMechanicsModel::unpackElementData(CommunicationBuffer & buffer,
                                                   const Array<Element> & elements,
                                                   SynchronizationTag tag) {
   AKANTU_DEBUG_IN();
 
   switch(tag) {
   case _gst_material_id: {
-    unpackElementalDataHelper(element_index_by_material, buffer, elements,
+    unpackElementalDataHelper(material_index, buffer, elements,
                              false, getFEEngine());
     break;
   }
   case _gst_smm_mass: {
     unpackNodalDataHelper(*mass, buffer, elements, mesh);
     break;
   }
   case _gst_smm_for_gradu: {
     unpackNodalDataHelper(*displacement, buffer, elements, mesh);
     break;
   }
   case _gst_smm_boundary: {
     unpackNodalDataHelper(*force, buffer, elements, mesh);
     unpackNodalDataHelper(*velocity, buffer, elements, mesh);
     unpackNodalDataHelper(*blocked_dofs, buffer, elements, mesh);
     break;
   }
   default: {
   }
   }
 
   if(tag != _gst_material_id) {
     Array<Element> * elements_per_mat = new Array<Element>[materials.size()];
     splitElementByMaterial(elements, elements_per_mat);
 
     for (UInt i = 0; i < materials.size(); ++i) {
       materials[i]->unpackElementData(buffer, elements_per_mat[i], tag);
     }
 
     delete [] elements_per_mat;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 inline UInt SolidMechanicsModel::getNbDataToPack(SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
   UInt size = 0;
   //  UInt nb_nodes = mesh.getNbNodes();
 
   switch(tag) {
   case _gst_smm_uv: {
     size += sizeof(Real) * spatial_dimension * 2;
     break;
   }
   case _gst_smm_res: {
     size += sizeof(Real) * spatial_dimension;
     break;
   }
   case _gst_smm_mass: {
     size += sizeof(Real) * spatial_dimension;
     break;
   }
   case _gst_for_dump: {
     size += sizeof(Real) * spatial_dimension * 5;
     break;
   }
   default: {
     AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
   AKANTU_DEBUG_OUT();
   return size;
 }
 
 /* -------------------------------------------------------------------------- */
 inline UInt SolidMechanicsModel::getNbDataToUnpack(SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
   UInt size = 0;
   //  UInt nb_nodes = mesh.getNbNodes();
 
   switch(tag) {
   case _gst_smm_uv: {
     size += sizeof(Real) * spatial_dimension * 2;
     break;
   }
   case _gst_smm_res: {
     size += sizeof(Real) * spatial_dimension;
     break;
   }
   case _gst_smm_mass: {
     size += sizeof(Real) * spatial_dimension;
     break;
   }
   case _gst_for_dump: {
     size += sizeof(Real) * spatial_dimension * 5;
     break;
   }
   default: {
     AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
   AKANTU_DEBUG_OUT();
   return size;
 }
 
 /* -------------------------------------------------------------------------- */
 inline void SolidMechanicsModel::packData(CommunicationBuffer & buffer,
                                          const UInt index,
                                          SynchronizationTag tag) const {
   AKANTU_DEBUG_IN();
 
   switch(tag) {
   case _gst_smm_uv: {
     Array<Real>::const_vector_iterator it_disp = displacement->begin(spatial_dimension);
     Array<Real>::const_vector_iterator it_velo = velocity->begin(spatial_dimension);
     buffer << it_disp[index];
     buffer << it_velo[index];
     break;
   }
   case _gst_smm_res: {
     Array<Real>::const_vector_iterator it_res = residual->begin(spatial_dimension);
     buffer << it_res[index];
     break;
   }
   case _gst_smm_mass: {
     AKANTU_DEBUG_INFO("pack mass of node " << index << " which is " << (*mass)(index,0));
     Array<Real>::const_vector_iterator it_mass = mass->begin(spatial_dimension);
     buffer << it_mass[index];
     break;
   }
   case _gst_for_dump: {
     Array<Real>::const_vector_iterator it_disp = displacement->begin(spatial_dimension);
     Array<Real>::const_vector_iterator it_velo = velocity->begin(spatial_dimension);
     Array<Real>::const_vector_iterator it_acce = acceleration->begin(spatial_dimension);
     Array<Real>::const_vector_iterator it_resi = residual->begin(spatial_dimension);
     Array<Real>::const_vector_iterator it_forc = force->begin(spatial_dimension);
     buffer << it_disp[index];
     buffer << it_velo[index];
     buffer << it_acce[index];
     buffer << it_resi[index];
     buffer << it_forc[index];
     break;
   }
   default: {
     AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 inline void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer,
                                            const UInt index,
                                            SynchronizationTag tag) {
   AKANTU_DEBUG_IN();
 
   switch(tag) {
   case _gst_smm_uv: {
     Array<Real>::vector_iterator it_disp = displacement->begin(spatial_dimension);
     Array<Real>::vector_iterator it_velo = velocity->begin(spatial_dimension);
     buffer >> it_disp[index];
     buffer >> it_velo[index];
     break;
   }
   case _gst_smm_res: {
     Array<Real>::vector_iterator it_res = residual->begin(spatial_dimension);
     buffer >> it_res[index];
     break;
   }
   case _gst_smm_mass: {
     AKANTU_DEBUG_INFO("mass of node " << index << " was " << (*mass)(index,0));
     Array<Real>::vector_iterator it_mass = mass->begin(spatial_dimension);
     buffer >> it_mass[index];
     AKANTU_DEBUG_INFO("mass of node " << index << " is now " << (*mass)(index,0));
     break;
   }
   case _gst_for_dump: {
     Array<Real>::vector_iterator it_disp = displacement->begin(spatial_dimension);
     Array<Real>::vector_iterator it_velo = velocity->begin(spatial_dimension);
     Array<Real>::vector_iterator it_acce = acceleration->begin(spatial_dimension);
     Array<Real>::vector_iterator it_resi = residual->begin(spatial_dimension);
     Array<Real>::vector_iterator it_forc = force->begin(spatial_dimension);
     buffer >> it_disp[index];
     buffer >> it_velo[index];
     buffer >> it_acce[index];
     buffer >> it_resi[index];
     buffer >> it_forc[index];
     break;
   }
   default: {
     AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag);
   }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 __END_AKANTU__
 
 #include "sparse_matrix.hh"
 #include "solver.hh"
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 template <NewmarkBeta::IntegrationSchemeCorrectorType type>
 void SolidMechanicsModel::solve(Array<Real> &increment, Real block_val,
                                 bool need_factorize, bool has_profile_changed) {
 
   if(has_profile_changed) {
     this->initJacobianMatrix();
     need_factorize = true;
   }
 
   updateResidualInternal(); //doesn't do anything for static
 
   if(need_factorize) {
     Real c = 0.,d = 0.,e = 0.;
 
     if(method == _static) {
       AKANTU_DEBUG_INFO("Solving K inc = r");
       e = 1.;
     } else {
       AKANTU_DEBUG_INFO("Solving (c M + d C + e K) inc = r");
 
       NewmarkBeta * nmb_int = dynamic_cast<NewmarkBeta *>(integrator);
       c = nmb_int->getAccelerationCoefficient<type>(time_step);
       d = nmb_int->getVelocityCoefficient<type>(time_step);
       e = nmb_int->getDisplacementCoefficient<type>(time_step);
     }
 
 
     jacobian_matrix->clear();
     // J = c M + d C + e K
     if(stiffness_matrix)
       jacobian_matrix->add(*stiffness_matrix, e);
 
     if(mass_matrix)
       jacobian_matrix->add(*mass_matrix, c);
 
 #if !defined(AKANTU_NDEBUG)
     if(mass_matrix && AKANTU_DEBUG_TEST(dblDump))
       mass_matrix->saveMatrix("M.mtx");
 #endif
 
     if(velocity_damping_matrix)
       jacobian_matrix->add(*velocity_damping_matrix, d);
 
     jacobian_matrix->applyBoundary(*blocked_dofs, block_val);
 
 #if !defined(AKANTU_NDEBUG)
     if(AKANTU_DEBUG_TEST(dblDump))
       jacobian_matrix->saveMatrix("J.mtx");
 #endif
     solver->factorize();
   }
 
   // if (rhs.getSize() != 0)
   //  solver->setRHS(rhs);
   // else
 
   solver->setOperators();
 
   solver->setRHS(*residual);
 
   // solve @f[ J \delta w = r @f]
   solver->solve(increment);
 
   UInt nb_nodes = displacement-> getSize();
   UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes;
 
   bool * blocked_dofs_val = blocked_dofs->storage();
   Real * increment_val = increment.storage();
 
   for (UInt j = 0; j < nb_degree_of_freedom;
        ++j,++increment_val, ++blocked_dofs_val) {
     if ((*blocked_dofs_val))
       *increment_val = 0.0;
     }
 
 }
 
 
 /* -------------------------------------------------------------------------- */
 template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria>
 bool SolidMechanicsModel::solveStatic(Real tolerance, UInt max_iteration,
 				      bool do_not_factorize) {
 
   AKANTU_DEBUG_INFO("Solving Ku = f");
   AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL,
                       "You should first initialize the implicit solver and assemble the stiffness matrix by calling initImplicit");
 
   AnalysisMethod analysis_method=method;
   Real error = 0.;
   method=_static;
   bool converged = this->template solveStep<cmethod, criteria>(tolerance, error, max_iteration, do_not_factorize);
   method=analysis_method;
   return converged;
 
 }
 
 /* -------------------------------------------------------------------------- */
 template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria>
 bool SolidMechanicsModel::solveStep(Real tolerance,
                                     UInt max_iteration) {
   Real error = 0.;
   return this->template solveStep<cmethod,criteria>(tolerance,
                                                     error,
                                                     max_iteration);
 }
 
 /* -------------------------------------------------------------------------- */
 template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria>
 bool SolidMechanicsModel::solveStep(Real tolerance, Real & error, UInt max_iteration,
 				    bool do_not_factorize) {
   EventManager::sendEvent(SolidMechanicsModelEvent::BeforeSolveStepEvent(method));
   this->implicitPred();
   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;
   bool converged = false;
   error = 0.;
   if(criteria == _scc_residual) {
     converged = this->testConvergence<criteria> (tolerance, error);
     if(converged) return converged;
   }
 
   do {
     if (cmethod == _scm_newton_raphson_tangent)
       this->assembleStiffnessMatrix();
 
     solve<NewmarkBeta::_displacement_corrector> (*increment, 1., need_factorize);
 
     this->implicitCorr();
 
     if(criteria == _scc_residual) this->updateResidual();
 
     converged = this->testConvergence<criteria> (tolerance, error);
 
     if(criteria == _scc_increment && !converged) this->updateResidual();
     //this->dump();
 
     iter++;
     AKANTU_DEBUG_INFO("[" << criteria << "] Convergence iteration "
                       << std::setw(std::log10(max_iteration)) << iter
                       << ": error " << error << (converged ? " < " : " > ") << tolerance);
 
     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);
 
   // this makes sure that you have correct strains and stresses after the solveStep function (e.g., for dumping)
   if(criteria == _scc_increment) this->updateResidual();
 
   if (converged) {
     EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method));
   } else if(iter == max_iteration) {
     AKANTU_DEBUG_WARNING("[" << criteria << "] Convergence not reached after "
                          << std::setw(std::log10(max_iteration)) << iter <<
                          " iteration" << (iter == 1 ? "" : "s") << "!" << std::endl);
   }
 
   return converged;
 }
diff --git a/src/model/solid_mechanics/solid_mechanics_model_mass.cc b/src/model/solid_mechanics/solid_mechanics_model_mass.cc
index b3602402a..073e44e9c 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_mass.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_mass.cc
@@ -1,158 +1,158 @@
 /**
  * @file   solid_mechanics_model_mass.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Tue Oct 05 2010
  * @date last modification: Thu Jun 05 2014
  *
  * @brief  function handling mass computation
  *
  * @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 "solid_mechanics_model.hh"
 #include "material.hh"
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleMassLumped() {
   AKANTU_DEBUG_IN();
 
   UInt nb_nodes = mesh.getNbNodes();
 
   if (!mass) {
     std::stringstream sstr_mass; sstr_mass << id << ":mass";
     mass         = &(alloc<Real>(sstr_mass.str(), nb_nodes, spatial_dimension, 0));
   } else
     mass->clear();
 
   assembleMassLumped(_not_ghost);
   assembleMassLumped(_ghost);
 
   /// for not connected nodes put mass to one in order to avoid
   /// wrong range in paraview
   Real * mass_values = mass->storage();
   for (UInt i = 0; i < nb_nodes; ++i) {
     if (fabs(mass_values[i]) < std::numeric_limits<Real>::epsilon() || Math::isnan(mass_values[i]))
       mass_values[i] = 1.;
   }
 
   synch_registry->synchronize(_gst_smm_mass);
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleMassLumped(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   FEEngine & fem = getFEEngine();
 
   Array<Real> rho_1(0,1);
 
   Mesh::type_iterator it  = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type);
   for(; it != end; ++it) {
     ElementType type = *it;
 
     computeRho(rho_1, type, ghost_type);
 
     AKANTU_DEBUG_ASSERT(dof_synchronizer,
 			"DOFSynchronizer number must not be initialized");
     fem.assembleFieldLumped(rho_1, spatial_dimension,*mass,
 			    dof_synchronizer->getLocalDOFEquationNumbers(),
 			    type, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleMass() {
   AKANTU_DEBUG_IN();
 
   if(!mass_matrix) {
     std::stringstream sstr; sstr << id << ":mass_matrix";
     mass_matrix = new SparseMatrix(*jacobian_matrix, sstr.str(), memory_id);
   }
 
   assembleMass(_not_ghost);
   //  assembleMass(_ghost);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assembleMass(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>();
 
   Array<Real> rho_1(0,1);
   //UInt nb_element;
   mass_matrix->clear();
 
   Mesh::type_iterator it  = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type);
   for(; it != end; ++it) {
     ElementType type = *it;
 
     computeRho(rho_1, type, ghost_type);
     fem.assembleFieldMatrix(rho_1, spatial_dimension, *mass_matrix, type, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::computeRho(Array<Real> & rho,
 				     ElementType type,
 				     GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
-  Material ** mat_val = &(materials.at(0));
+  Material ** mat_val = &(this->materials.at(0));
 
-  FEEngine & fem = getFEEngine();
+  FEEngine & fem = this->getFEEngine();
   UInt nb_element = fem.getMesh().getNbElement(type,ghost_type);
 
-  Array<UInt> & elem_mat_val = element_index_by_material(type, ghost_type);
+  Array<UInt> & mat_indexes = this->material_index(type, ghost_type);
 
   UInt nb_quadrature_points = fem.getNbQuadraturePoints(type, ghost_type);
 
   rho.resize(nb_element * nb_quadrature_points);
   Real * rho_1_val = rho.storage();
 
   /// compute @f$ rho @f$ for each nodes of each element
   for (UInt el = 0; el < nb_element; ++el) {
-    Real mat_rho = mat_val[elem_mat_val(el, 0)]->getParam<Real>("rho"); /// here rho is constant in an element
+    Real mat_rho = mat_val[mat_indexes(el)]->getParam<Real>("rho"); /// here rho is constant in an element
 
     for (UInt n = 0; n < nb_quadrature_points; ++n) {
       *rho_1_val++ = mat_rho;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 __END_AKANTU__
diff --git a/src/model/solid_mechanics/solid_mechanics_model_material.cc b/src/model/solid_mechanics/solid_mechanics_model_material.cc
index fcd6b6fc8..4a188c53f 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_material.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_material.cc
@@ -1,310 +1,311 @@
 /**
  * @file   solid_mechanics_model_material.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Nov 26 2010
  * @date last modification: Tue Jun 24 2014
  *
  * @brief  instatiation of 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 "solid_mechanics_model.hh"
 #include "material_list.hh"
 #include "aka_math.hh"
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 #define AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL(dim, elem)		\
   registerNewMaterial< BOOST_PP_ARRAY_ELEM(1, elem)< dim > >(section)
 
 #define AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL_EACH(r, data, i, elem)	\
   BOOST_PP_EXPR_IF(BOOST_PP_NOT_EQUAL(0, i), else )			\
   if(opt_param == BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem))) { \
     registerNewMaterial< BOOST_PP_ARRAY_ELEM(1, data)< BOOST_PP_ARRAY_ELEM(0, data), \
 						       BOOST_PP_SEQ_ENUM(BOOST_PP_TUPLE_ELEM(2, 1, elem)) > >(section); \
     }
 
 
 #define AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL(dim, elem)		\
   BOOST_PP_SEQ_FOR_EACH_I(AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL_EACH,	\
 			  (2, (dim, BOOST_PP_ARRAY_ELEM(1, elem))),	\
 			  BOOST_PP_ARRAY_ELEM(2, elem))			\
   else {								\
     AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL(dim, elem);		\
   }
 
 #define AKANTU_INTANTIATE_MATERIAL_BY_DIM(dim, elem)			\
   BOOST_PP_IF(BOOST_PP_EQUAL(3, BOOST_PP_ARRAY_SIZE(elem) ),		\
 	      AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL,			\
 	      AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL)(dim, elem)
 
 
 #define AKANTU_INTANTIATE_MATERIAL(elem)				\
   switch(spatial_dimension) {						\
   case 1: { AKANTU_INTANTIATE_MATERIAL_BY_DIM(1, elem); break; }	\
   case 2: { AKANTU_INTANTIATE_MATERIAL_BY_DIM(2, elem); break; }	\
   case 3: { AKANTU_INTANTIATE_MATERIAL_BY_DIM(3, elem); break; }	\
   }
 
 
 #define AKANTU_INTANTIATE_MATERIAL_IF(elem)				\
   if (mat_type == BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(0, elem))) {	\
     AKANTU_INTANTIATE_MATERIAL(elem);					\
   }
 
 #define AKANTU_INTANTIATE_OTHER_MATERIAL(r, data, elem)			\
   else AKANTU_INTANTIATE_MATERIAL_IF(elem)
 
 #define AKANTU_INSTANTIATE_MATERIALS()					\
   do {									\
     AKANTU_INTANTIATE_MATERIAL_IF(BOOST_PP_SEQ_HEAD(AKANTU_MATERIAL_LIST)) \
       BOOST_PP_SEQ_FOR_EACH(AKANTU_INTANTIATE_OTHER_MATERIAL,		\
 			    _,						\
 			    BOOST_PP_SEQ_TAIL(AKANTU_MATERIAL_LIST))	\
     else {								\
       if(getStaticParser().isPermissive())				\
 	AKANTU_DEBUG_INFO("Malformed material file " <<			\
 			  ": unknown material type '"			\
 			  << mat_type << "'");				\
       else								\
 	AKANTU_DEBUG_WARNING("Malformed material file "			\
 			     <<": unknown material type " << mat_type	\
 			     << ". This is perhaps a user"		\
 			     << " defined material ?");			\
     }									\
   } while(0)
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::instantiateMaterials() {
   std::pair<Parser::const_section_iterator, Parser::const_section_iterator>
     sub_sect = this->parser->getSubSections(_st_material);
 
   Parser::const_section_iterator it = sub_sect.first;
   for (; it != sub_sect.second; ++it) {
     const ParserSection & section = *it;
     std::string mat_type  = section.getName();
     std::string opt_param = section.getOption();
     AKANTU_INSTANTIATE_MATERIALS();
   }
 
   are_materials_instantiated = true;
 }
 
 
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::assignMaterialToElements(const ElementTypeMapArray<UInt> * filter) {
   Material ** mat_val = &(materials.at(0));
 
   Element element;
   element.ghost_type = _not_ghost;
   Mesh::type_iterator it  = mesh.firstType(spatial_dimension, _not_ghost, _ek_not_defined);
   Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost, _ek_not_defined);
   if(filter != NULL) {
      it  = filter->firstType(spatial_dimension, _not_ghost, _ek_not_defined);
      end = filter->lastType(spatial_dimension, _not_ghost, _ek_not_defined);
   }
 
   // Fill the element material array from the material selector
   for(; it != end; ++it) {
     UInt nb_element = mesh.getNbElement(*it, _not_ghost);
 
     const Array<UInt> * filter_array = NULL;
     if (filter != NULL) {
       filter_array = &((*filter)(*it, _not_ghost));
       nb_element = filter_array->getSize();
     }
 
     element.type = *it;
     element.kind = mesh.getKind(element.type);
-    Array<UInt> & el_id_by_mat = element_index_by_material(*it, _not_ghost);
+    Array<UInt> & mat_indexes = material_index(*it, _not_ghost);
     for (UInt el = 0; el < nb_element; ++el) {
       if (filter != NULL)
 	element.element = (*filter_array)(el);
       else
 	element.element = el;
 
       UInt mat_index = (*material_selector)(element);
       AKANTU_DEBUG_ASSERT(mat_index < materials.size(),
 			  "The material selector returned an index that does not exists");
-      el_id_by_mat(element.element, 0) = mat_index;
+      mat_indexes(element.element) = mat_index;
 
     }
   }
 
   // synchronize the element material arrays
   synch_registry->synchronize(_gst_material_id);
 
 
   /// fill the element filters of the materials using the element_material arrays
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
     it  = mesh.firstType(spatial_dimension, gt, _ek_not_defined);
     end = mesh.lastType(spatial_dimension, gt, _ek_not_defined);
 
      if(filter != NULL) {
        it  = filter->firstType(spatial_dimension, gt, _ek_not_defined);
        end = filter->lastType(spatial_dimension, gt, _ek_not_defined);
      }
 
     for(; it != end; ++it) {
       UInt nb_element = mesh.getNbElement(*it, gt);
 
       const Array<UInt> * filter_array = NULL;
       if (filter != NULL) {
 	filter_array = &((*filter)(*it, gt));
 	nb_element = filter_array->getSize();
       }
 
-      Array<UInt> & el_id_by_mat = element_index_by_material(*it, gt);
+      Array<UInt> & mat_indexes   = material_index(*it, gt);
+      Array<UInt> & mat_local_num = material_local_numbering(*it, gt);
       for (UInt el = 0; el < nb_element; ++el) {
 	UInt element;
 
 	if (filter != NULL) element = (*filter_array)(el);
 	else element = el;
 
-	UInt mat_index = el_id_by_mat(element, 0);
+	UInt mat_index = mat_indexes(element);
 	UInt index = mat_val[mat_index]->addElement(*it, element, gt);
-	el_id_by_mat(element, 1) = index;
+	mat_local_num(element) = index;
       }
     }
   }
 }
 
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::initMaterials() {
   AKANTU_DEBUG_ASSERT(materials.size() != 0, "No material to initialize !");
 
   if(!are_materials_instantiated) instantiateMaterials();
 
   this->assignMaterialToElements();
 
   std::vector<Material *>::iterator mat_it;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     /// init internals properties
     (*mat_it)->initMaterial();
   }
 
   synch_registry->synchronize(_gst_smm_init_mat);
 
   // initialize mass
   switch(method) {
     case _explicit_lumped_mass:
       assembleMassLumped();
       break;
     case _explicit_consistent_mass:
     case _implicit_dynamic:
       assembleMass();
       break;
     case _static:
       break;
     default:
       AKANTU_EXCEPTION("analysis method not recognised by SolidMechanicsModel");
       break;
   }
 
   // initialize the previous displacement array if at least on material needs it
   for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) {
     Material & mat = **mat_it;
     if (mat.isFiniteDeformation() || mat.isInelasticDeformation()) {
       initArraysPreviousDisplacment();
       break;
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 Int SolidMechanicsModel::getInternalIndexFromID(const ID & id) const {
   AKANTU_DEBUG_IN();
 
   std::vector<Material *>::const_iterator first = materials.begin();
   std::vector<Material *>::const_iterator last  = materials.end();
 
   for (; first != last; ++first)
     if ((*first)->getID() == id) {
       AKANTU_DEBUG_OUT();
       return (first - materials.begin());
     }
 
   AKANTU_DEBUG_OUT();
   return -1;
 }
 
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModel::reassignMaterial() {
   AKANTU_DEBUG_IN();
 
   std::vector< Array<Element> > element_to_add   (materials.size());
   std::vector< Array<Element> > element_to_remove(materials.size());
 
   Element element;
   for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) {
     GhostType ghost_type = *gt;
     element.ghost_type = ghost_type;
 
-    Mesh::type_iterator it  = mesh.firstType(spatial_dimension, ghost_type, _ek_regular);
-    Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type, _ek_regular);
+    Mesh::type_iterator it  = mesh.firstType(spatial_dimension, ghost_type, _ek_not_defined);
+    Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type, _ek_not_defined);
     for(; it != end; ++it) {
       ElementType type = *it;
       element.type = type;
       element.kind = Mesh::getKind(type);
 
       UInt nb_element = mesh.getNbElement(type, ghost_type);
-      Array<UInt> & el_index_by_mat = element_index_by_material(type, ghost_type);
+      Array<UInt> & mat_indexes = material_index(type, ghost_type);
 
       for (UInt el = 0; el < nb_element; ++el) {
 	element.element = el;
 
-	UInt old_material = el_index_by_mat(el, 0);
+	UInt old_material = mat_indexes(el);
 	UInt new_material = (*material_selector)(element);
 
 	if(old_material != new_material) {
 	  element_to_add   [new_material].push_back(element);
 	  element_to_remove[old_material].push_back(element);
 	}
       }
     }
   }
 
   std::vector<Material *>::iterator mat_it;
   UInt mat_index = 0;
   for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it, ++mat_index) {
     (*mat_it)->removeElements(element_to_remove[mat_index]);
     (*mat_it)->addElements   (element_to_add[mat_index]);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 
 __END_AKANTU__
diff --git a/src/synchronizer/distributed_synchronizer.cc b/src/synchronizer/distributed_synchronizer.cc
index d698c9fea..ab9b4e10f 100644
--- a/src/synchronizer/distributed_synchronizer.cc
+++ b/src/synchronizer/distributed_synchronizer.cc
@@ -1,1651 +1,1663 @@
 /**
  * @file   distributed_synchronizer.cc
  *
  * @author Dana Christen <dana.christen@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Thu Jun 16 2011
  * @date last modification: Fri Sep 05 2014
  *
  * @brief  implementation of a  communicator using a static_communicator for real
  * send/receive
  *
  * @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 "distributed_synchronizer.hh"
 #include "static_communicator.hh"
 #include "mesh_utils.hh"
 #include "mesh_data.hh"
 #include "element_group.hh"
 /* -------------------------------------------------------------------------- */
 #include <map>
 #include <iostream>
 #include <algorithm>
 
 #if defined(AKANTU_DEBUG_TOOLS)
 #  include "aka_debug_tools.hh"
 #endif
 
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 DistributedSynchronizer::DistributedSynchronizer(Mesh & mesh,
 						 SynchronizerID id,
 						 MemoryID memory_id) :
   Synchronizer(id, memory_id),
   mesh(mesh),
   prank_to_element("prank_to_element", id)
 {
   AKANTU_DEBUG_IN();
 
   nb_proc = static_communicator->getNbProc();
   rank    = static_communicator->whoAmI();
 
   send_element = new Array<Element>[nb_proc];
   recv_element = new Array<Element>[nb_proc];
 
   mesh.registerEventHandler(*this);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 DistributedSynchronizer::~DistributedSynchronizer() {
   AKANTU_DEBUG_IN();
 
   for (UInt p = 0; p < nb_proc; ++p) {
     send_element[p].clear();
     recv_element[p].clear();
   }
 
   delete [] send_element;
   delete [] recv_element;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 DistributedSynchronizer * DistributedSynchronizer::
 createDistributedSynchronizerMesh(Mesh & mesh,
 				  const MeshPartition * partition,
 				  UInt root,
 				  SynchronizerID id,
 				  MemoryID memory_id) {
   AKANTU_DEBUG_IN();
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   UInt nb_proc = comm.getNbProc();
   UInt my_rank = comm.whoAmI();
 
   DistributedSynchronizer & communicator = *(new DistributedSynchronizer(mesh, id, memory_id));
 
   if(nb_proc == 1) return &communicator;
 
   UInt * local_connectivity = NULL;
   UInt * local_partitions = NULL;
   Array<UInt> * old_nodes = mesh.getNodesGlobalIdsPointer();
   old_nodes->resize(0);
   Array<Real> * nodes = mesh.getNodesPointer();
 
 
   UInt spatial_dimension = nodes->getNbComponent();
 
   mesh.synchronizeGroupNames();
 
   /* ------------------------------------------------------------------------ */
   /*  Local (rank == root)                                                    */
   /* ------------------------------------------------------------------------ */
   if(my_rank == root) {
     AKANTU_DEBUG_ASSERT(partition->getNbPartition() == nb_proc,
 			"The number of partition does not match the number of processors: " <<
 			partition->getNbPartition() << " != " << nb_proc);
 
     /**
      * connectivity and communications scheme construction
      */
     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);
     UInt count = 0;
     /* --- MAIN LOOP ON TYPES --- */
     for(; it != end; ++it) {
       ElementType type = *it;
 
       UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
       UInt nb_element = mesh.getNbElement(*it);
       UInt nb_local_element[nb_proc];
       UInt nb_ghost_element[nb_proc];
       UInt nb_element_to_send[nb_proc];
 
       memset(nb_local_element, 0, nb_proc*sizeof(UInt));
       memset(nb_ghost_element, 0, nb_proc*sizeof(UInt));
       memset(nb_element_to_send, 0, nb_proc*sizeof(UInt));
 
       /// \todo change this ugly way to avoid a problem if an element
       /// type is present in the mesh but not in the partitions
       const Array<UInt> * tmp_partition_num = NULL;
       try {
 	tmp_partition_num = &partition->getPartition(type, _not_ghost);
       } catch(...) {
 	continue;
       }
       const Array<UInt> & partition_num = *tmp_partition_num;
 
       const CSR<UInt> & ghost_partition = partition->getGhostPartitionCSR()(type, _not_ghost);
 
       /* -------------------------------------------------------------------- */
       /// constructing the reordering structures
       for (UInt el = 0; el < nb_element; ++el) {
 	nb_local_element[partition_num(el)]++;
 	for (CSR<UInt>::const_iterator part = ghost_partition.begin(el);
 	     part != ghost_partition.end(el);
 	     ++part) {
 	  nb_ghost_element[*part]++;
 	}
 	nb_element_to_send[partition_num(el)] += ghost_partition.getNbCols(el) + 1;
       }
 
       /// allocating buffers
       UInt * buffers[nb_proc];
       UInt * buffers_tmp[nb_proc];
       for (UInt p = 0; p < nb_proc; ++p) {
 	UInt size = nb_nodes_per_element * (nb_local_element[p] +
 					    nb_ghost_element[p]);
 	buffers[p] = new UInt[size];
 	buffers_tmp[p] = buffers[p];
       }
 
       /// copying the local connectivity
       UInt * conn_val = mesh.getConnectivity(type, _not_ghost).storage();
       for (UInt el = 0; el < nb_element; ++el) {
 	memcpy(buffers_tmp[partition_num(el)],
 	       conn_val + el * nb_nodes_per_element,
 	       nb_nodes_per_element * sizeof(UInt));
 	buffers_tmp[partition_num(el)] += nb_nodes_per_element;
       }
 
       /// copying the connectivity of ghost element
       for (UInt el = 0; el < nb_element; ++el) {
 	for (CSR<UInt>::const_iterator part = ghost_partition.begin(el);
 	     part != ghost_partition.end(el);
 	     ++part) {
 	  UInt proc = *part;
 	  memcpy(buffers_tmp[proc],
 		 conn_val + el * nb_nodes_per_element,
 		 nb_nodes_per_element * sizeof(UInt));
 	  buffers_tmp[proc] += nb_nodes_per_element;
 	}
       }
 
 
       /// tag info
       std::vector<std::string> tag_names;
       mesh.getMeshData().getTagNames(tag_names, type);
 
       UInt nb_tags = tag_names.size();
 
       /* -------->>>>-SIZE + CONNECTIVITY------------------------------------ */
       /// send all connectivity and ghost information to all processors
       std::vector<CommunicationRequest *> requests;
       for (UInt p = 0; p < nb_proc; ++p) {
 	if(p != root) {
 	  UInt size[5];
 	  size[0] = (UInt) type;
 	  size[1] = nb_local_element[p];
 	  size[2] = nb_ghost_element[p];
 	  size[3] = nb_element_to_send[p];
 	  size[4] = nb_tags;
 	  AKANTU_DEBUG_INFO("Sending connectivities informations to proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_SIZES) <<")");
 	  comm.send(size, 5, p, Tag::genTag(my_rank, count, TAG_SIZES));
 
 	  AKANTU_DEBUG_INFO("Sending connectivities to proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_CONNECTIVITY) <<")");
 	  requests.push_back(comm.asyncSend(buffers[p],
 					    nb_nodes_per_element * (nb_local_element[p] +
 								    nb_ghost_element[p]),
 					    p, Tag::genTag(my_rank, count, TAG_CONNECTIVITY)));
 	} else {
 	  local_connectivity = buffers[p];
 	}
       }
 
       /// create the renumbered connectivity
       AKANTU_DEBUG_INFO("Renumbering local connectivities");
       MeshUtils::renumberMeshNodes(mesh,
 				   local_connectivity,
 				   nb_local_element[root],
 				   nb_ghost_element[root],
 				   type,
 				   *old_nodes);
 
       comm.waitAll(requests);
       comm.freeCommunicationRequest(requests);
       requests.clear();
 
       for (UInt p = 0; p < nb_proc; ++p) {
 	delete [] buffers[p];
       }
 
       /* -------------------------------------------------------------------- */
       for (UInt p = 0; p < nb_proc; ++p) {
 	buffers[p] = new UInt[nb_ghost_element[p] + nb_element_to_send[p]];
 	buffers_tmp[p] = buffers[p];
       }
 
       /// splitting the partition information to send them to processors
       UInt count_by_proc[nb_proc];
       memset(count_by_proc, 0, nb_proc*sizeof(UInt));
       for (UInt el = 0; el < nb_element; ++el) {
 	*(buffers_tmp[partition_num(el)]++) = ghost_partition.getNbCols(el);
 	UInt i(0);
 	for (CSR<UInt>::const_iterator part = ghost_partition.begin(el);
 	     part != ghost_partition.end(el);
 	     ++part, ++i) {
 	  *(buffers_tmp[partition_num(el)]++) = *part;
 	}
       }
 
       for (UInt el = 0; el < nb_element; ++el) {
 	UInt i(0);
 	for (CSR<UInt>::const_iterator part = ghost_partition.begin(el);
 	     part != ghost_partition.end(el);
 	     ++part, ++i) {
 	  *(buffers_tmp[*part]++) = partition_num(el);
 	}
       }
 
       /* -------->>>>-PARTITIONS--------------------------------------------- */
       /// last data to compute the communication scheme
       for (UInt p = 0; p < nb_proc; ++p) {
 	if(p != root) {
 	  AKANTU_DEBUG_INFO("Sending partition informations to proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_PARTITIONS) <<")");
 	  requests.push_back(comm.asyncSend(buffers[p],
 					     nb_element_to_send[p] + nb_ghost_element[p],
 					    p, Tag::genTag(my_rank, count, TAG_PARTITIONS)));
 	} else {
 	  local_partitions = buffers[p];
 	}
       }
 
       if(Mesh::getSpatialDimension(type) == mesh.getSpatialDimension()) {
 	AKANTU_DEBUG_INFO("Creating communications scheme");
 	communicator.fillCommunicationScheme(local_partitions,
 					     nb_local_element[root],
 					     nb_ghost_element[root],
 					     type);
       }
 
       comm.waitAll(requests);
       comm.freeCommunicationRequest(requests);
       requests.clear();
 
       for (UInt p = 0; p < nb_proc; ++p) {
 	delete [] buffers[p];
       }
 
       /* -------------------------------------------------------------------- */
       /// send  data assossiated to the mesh
       /* -------->>>>-TAGS--------------------------------------------------- */
       synchronizeTagsSend(communicator, root, mesh, nb_tags, type,
 			  partition_num,
 			  ghost_partition,
 			  nb_local_element[root],
 			  nb_ghost_element[root]);
 
 
       /* -------------------------------------------------------------------- */
       /// send  data assossiated to groups
       /* -------->>>>-GROUPS------------------------------------------------- */
       synchronizeElementGroups(communicator, root, mesh, type,
       			       partition_num,
       			       ghost_partition,
 			       nb_element);
 
       ++count;
     }
 
     /* -------->>>>-SIZE----------------------------------------------------- */
     for (UInt p = 0; p < nb_proc; ++p) {
       if(p != root) {
 	UInt size[5];
 	size[0] = (UInt) _not_defined;
 	size[1] = 0;
 	size[2] = 0;
 	size[3] = 0;
 	size[4] = 0;
 	AKANTU_DEBUG_INFO("Sending empty connectivities informations to proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_SIZES) <<")");
 	comm.send(size, 5, p, Tag::genTag(my_rank, count, TAG_SIZES));
       }
     }
 
     /* ---------------------------------------------------------------------- */
     /* ---------------------------------------------------------------------- */
     /**
      * Nodes coordinate construction and synchronization
      */
     std::multimap< UInt, std::pair<UInt, UInt> > nodes_to_proc;
     /// get the list of nodes to send and send them
     Real * local_nodes = NULL;
     UInt nb_nodes_per_proc[nb_proc];
     UInt * nodes_per_proc[nb_proc];
 
     comm.broadcast(&(mesh.nb_global_nodes), 1, root);
 
     /* --------<<<<-NB_NODES + NODES----------------------------------------- */
     for (UInt p = 0; p < nb_proc; ++p) {
       UInt nb_nodes = 0;
       //      UInt * buffer;
       if(p != root) {
 	AKANTU_DEBUG_INFO("Receiving number of nodes from proc " << p << " TAG("<< Tag::genTag(p, 0, TAG_NB_NODES) <<")");
 	comm.receive(&nb_nodes, 1, p, Tag::genTag(p, 0, TAG_NB_NODES));
 	nodes_per_proc[p] = new UInt[nb_nodes];
 	nb_nodes_per_proc[p] = nb_nodes;
 	AKANTU_DEBUG_INFO("Receiving list of nodes from proc " << p << " TAG("<< Tag::genTag(p, 0, TAG_NODES) <<")");
 	comm.receive(nodes_per_proc[p], nb_nodes, p, Tag::genTag(p, 0, TAG_NODES));
       } else {
 	nb_nodes = old_nodes->getSize();
 	nb_nodes_per_proc[p] = nb_nodes;
 	nodes_per_proc[p] = old_nodes->storage();
       }
 
       /// get the coordinates for the selected nodes
       Real * nodes_to_send = new Real[nb_nodes * spatial_dimension];
       Real * nodes_to_send_tmp = nodes_to_send;
       for (UInt n = 0; n < nb_nodes; ++n) {
 	memcpy(nodes_to_send_tmp,
 	       nodes->storage() + spatial_dimension * nodes_per_proc[p][n],
 	       spatial_dimension * sizeof(Real));
 	// nodes_to_proc.insert(std::make_pair(buffer[n], std::make_pair(p, n)));
 	nodes_to_send_tmp += spatial_dimension;
       }
 
       /* -------->>>>-COORDINATES-------------------------------------------- */
       if(p != root) { /// send them for distant processors
 	AKANTU_DEBUG_INFO("Sending coordinates to proc " << p << " TAG("<< Tag::genTag(my_rank, 0, TAG_COORDINATES) <<")");
 	comm.send(nodes_to_send, nb_nodes * spatial_dimension, p, Tag::genTag(my_rank, 0, TAG_COORDINATES));
 	delete [] nodes_to_send;
       } else { /// save them for local processor
 	local_nodes = nodes_to_send;
       }
     }
 
 
     /// construct the local nodes coordinates
     UInt nb_nodes = old_nodes->getSize();
     nodes->resize(nb_nodes);
     memcpy(nodes->storage(), local_nodes, nb_nodes * spatial_dimension * sizeof(Real));
     delete [] local_nodes;
 
     Array<Int> * nodes_type_per_proc[nb_proc];
     for (UInt p = 0; p < nb_proc; ++p) {
       nodes_type_per_proc[p] = new Array<Int>(nb_nodes_per_proc[p]);
     }
 
     communicator.fillNodesType(mesh);
 
     /* --------<<<<-NODES_TYPE-1--------------------------------------------- */
     for (UInt p = 0; p < nb_proc; ++p) {
       if(p != root) {
 	AKANTU_DEBUG_INFO("Receiving first nodes types from proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_NODES_TYPE) <<")");
 	comm.receive(nodes_type_per_proc[p]->storage(),
 		     nb_nodes_per_proc[p], p, Tag::genTag(p, 0, TAG_NODES_TYPE));
       } else {
 	nodes_type_per_proc[p]->copy(mesh.getNodesType());
       }
       for (UInt n = 0; n < nb_nodes_per_proc[p]; ++n) {
 	if((*nodes_type_per_proc[p])(n) == -2)
 	  nodes_to_proc.insert(std::make_pair(nodes_per_proc[p][n], std::make_pair(p, n)));
       }
     }
 
     std::multimap< UInt, std::pair<UInt, UInt> >::iterator it_node;
     std::pair< std::multimap< UInt, std::pair<UInt, UInt> >::iterator,
 	       std::multimap< UInt, std::pair<UInt, UInt> >::iterator > it_range;
     for (UInt i = 0; i < mesh.nb_global_nodes; ++i) {
       it_range = nodes_to_proc.equal_range(i);
       if(it_range.first == nodes_to_proc.end() || it_range.first->first != i) continue;
 
       UInt node_type = (it_range.first)->second.first;
       for (it_node = it_range.first; it_node != it_range.second; ++it_node) {
 	UInt proc = it_node->second.first;
 	UInt node = it_node->second.second;
 	if(proc != node_type)
 	  nodes_type_per_proc[proc]->storage()[node] = node_type;
       }
     }
 
     /* -------->>>>-NODES_TYPE-2--------------------------------------------- */
     std::vector<CommunicationRequest *> requests;
     for (UInt p = 0; p < nb_proc; ++p) {
       if(p != root) {
 	AKANTU_DEBUG_INFO("Sending nodes types to proc " << p << " TAG("<< Tag::genTag(my_rank, 0, TAG_NODES_TYPE) <<")");
 	requests.push_back(comm.asyncSend(nodes_type_per_proc[p]->storage(),
 					  nb_nodes_per_proc[p], p, Tag::genTag(my_rank, 0, TAG_NODES_TYPE)));
       } else {
 	mesh.getNodesTypePointer()->copy(*nodes_type_per_proc[p]);
       }
     }
 
     comm.waitAll(requests);
     comm.freeCommunicationRequest(requests);
     requests.clear();
 
     for (UInt p = 0; p < nb_proc; ++p) {
       if(p != root) delete [] nodes_per_proc[p];
       delete nodes_type_per_proc[p];
     }
 
     /* -------->>>>-NODE GROUPS --------------------------------------------- */
     synchronizeNodeGroupsMaster(communicator, root, mesh);
 
     /* ---------------------------------------------------------------------- */
     /*  Distant (rank != root)                                                */
     /* ---------------------------------------------------------------------- */
   } else {
     /**
      * connectivity and communications scheme construction on distant processors
      */
     ElementType type = _not_defined;
     UInt count = 0;
     do {
       /* --------<<<<-SIZE--------------------------------------------------- */
       UInt size[5] = { 0 };
       comm.receive(size, 5, root, Tag::genTag(root, count, TAG_SIZES));
 
       type        = (ElementType) size[0];
       UInt nb_local_element     = size[1];
       UInt nb_ghost_element     = size[2];
       UInt nb_element_to_send   = size[3];
       UInt nb_tags              = size[4];
 
       if(type != _not_defined) {
 	UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
 	/* --------<<<<-CONNECTIVITY----------------------------------------- */
 	local_connectivity = new UInt[(nb_local_element + nb_ghost_element) *
 				      nb_nodes_per_element];
 	AKANTU_DEBUG_INFO("Receiving connectivities from proc " << root);
 	comm.receive(local_connectivity, nb_nodes_per_element * (nb_local_element +
 								  nb_ghost_element),
 		     root, Tag::genTag(root, count, TAG_CONNECTIVITY));
 
 	AKANTU_DEBUG_INFO("Renumbering local connectivities");
 	MeshUtils::renumberMeshNodes(mesh,
 				     local_connectivity,
 				     nb_local_element,
 				     nb_ghost_element,
 				     type,
 				     *old_nodes);
 
 	delete [] local_connectivity;
 
 	/* --------<<<<-PARTITIONS--------------------------------------------- */
 	local_partitions = new UInt[nb_element_to_send + nb_ghost_element * 2];
 	AKANTU_DEBUG_INFO("Receiving partition informations from proc " << root);
 	comm.receive(local_partitions,
 		     nb_element_to_send + nb_ghost_element * 2,
 		     root, Tag::genTag(root, count, TAG_PARTITIONS));
 
 	if(Mesh::getSpatialDimension(type) == mesh.getSpatialDimension()) {
 	  AKANTU_DEBUG_INFO("Creating communications scheme");
 	  communicator.fillCommunicationScheme(local_partitions,
 					       nb_local_element,
 					       nb_ghost_element,
 					       type);
 	}
 	delete [] local_partitions;
 
 	/* --------<<<<-TAGS------------------------------------------------- */
 	synchronizeTagsRecv(communicator, root, mesh, nb_tags, type,
 			    nb_local_element,
 			    nb_ghost_element);
 
 	/* --------<<<<-GROUPS----------------------------------------------- */
 	synchronizeElementGroups(communicator, root, mesh, type);
       }
       ++count;
     } while(type != _not_defined);
 
     /**
      * Nodes coordinate construction and synchronization on distant processors
      */
     comm.broadcast(&(mesh.nb_global_nodes), 1, root);
 
     /* -------->>>>-NB_NODES + NODES----------------------------------------- */
     AKANTU_DEBUG_INFO("Sending list of nodes to proc " << root);
     UInt nb_nodes = old_nodes->getSize();
     comm.send(&nb_nodes, 1, root, Tag::genTag(my_rank, 0, TAG_NB_NODES));
     comm.send(old_nodes->storage(), nb_nodes, root, Tag::genTag(my_rank, 0, TAG_NODES));
 
     /* --------<<<<-COORDINATES---------------------------------------------- */
     nodes->resize(nb_nodes);
     AKANTU_DEBUG_INFO("Receiving coordinates from proc " << root);
     comm.receive(nodes->storage(), nb_nodes * spatial_dimension, root, Tag::genTag(root, 0, TAG_COORDINATES));
 
     communicator.fillNodesType(mesh);
     /* -------->>>>-NODES_TYPE-1--------------------------------------------- */
     Int * nodes_types = mesh.getNodesTypePointer()->storage();
     AKANTU_DEBUG_INFO("Sending first nodes types to proc " << root);
     comm.send(nodes_types, nb_nodes,
 	      root, Tag::genTag(my_rank, 0, TAG_NODES_TYPE));
 
     /* --------<<<<-NODES_TYPE-2--------------------------------------------- */
     AKANTU_DEBUG_INFO("Receiving nodes types from proc " << root);
     comm.receive(nodes_types, nb_nodes,
 		 root, Tag::genTag(root, 0, TAG_NODES_TYPE));
 
     /* --------<<<<-NODE GROUPS --------------------------------------------- */
     synchronizeNodeGroupsSlaves(communicator, root, mesh);
   }
 
   MeshUtils::fillElementToSubElementsData(mesh);
 
   mesh.is_distributed = true;
 
   AKANTU_DEBUG_OUT();
   return &communicator;
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::fillTagBuffer(const MeshData & mesh_data,
 					    DynamicCommunicationBuffer * buffers,
 					    const std::string & tag_name,
 					    const ElementType & el_type,
 					    const Array<UInt> & partition_num,
 					    const CSR<UInt> & ghost_partition) {
   #define AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA(r, extra_param, elem)	\
     case BOOST_PP_TUPLE_ELEM(2, 0, elem) : { \
       fillTagBufferTemplated<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(mesh_data, buffers, tag_name, el_type, partition_num, ghost_partition); \
       break; \
     } \
 
   MeshDataTypeCode data_type_code = mesh_data.getTypeCode(tag_name);
   switch(data_type_code) {
     BOOST_PP_SEQ_FOR_EACH(AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA, , AKANTU_MESH_DATA_TYPES)
   default : AKANTU_DEBUG_ERROR("Could not obtain the type of tag" << tag_name << "!"); break;
   }
   #undef AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::fillNodesType(Mesh & mesh) {
   AKANTU_DEBUG_IN();
 
   UInt nb_nodes = mesh.getNbNodes();
   Int * nodes_type = mesh.getNodesTypePointer()->storage();
 
   UInt * nodes_set = new UInt[nb_nodes];
   std::fill_n(nodes_set, nb_nodes, 0);
 
   const UInt NORMAL_SET = 1;
   const UInt GHOST_SET  = 2;
 
   bool * already_seen = new bool[nb_nodes];
 
   for(UInt g = _not_ghost; g <= _ghost; ++g) {
     GhostType gt = (GhostType) g;
     UInt set = NORMAL_SET;
     if (gt == _ghost) set = GHOST_SET;
 
     std::fill_n(already_seen, nb_nodes, false);
     Mesh::type_iterator it  = mesh.firstType(_all_dimensions, gt, _ek_not_defined);
     Mesh::type_iterator end = mesh.lastType(_all_dimensions, gt, _ek_not_defined);
     for(; it != end; ++it) {
       ElementType type = *it;
 
       UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
       UInt nb_element = mesh.getNbElement(type, gt);
       Array<UInt>::iterator< Vector<UInt> > conn_it = mesh.getConnectivity(type, gt).begin(nb_nodes_per_element);
 
       for (UInt e = 0; e < nb_element; ++e, ++conn_it) {
 	Vector<UInt> & conn = *conn_it;
 	for (UInt n = 0; n < nb_nodes_per_element; ++n) {
 	  AKANTU_DEBUG_ASSERT(conn(n) < nb_nodes, "Node " << conn(n)
 			      << " bigger than number of nodes " << nb_nodes);
 	  if(!already_seen[conn(n)]) {
 	    nodes_set[conn(n)] += set;
 	    already_seen[conn(n)] = true;
 	  }
 	}
       }
     }
   }
 
   delete [] already_seen;
 
   for (UInt i = 0; i < nb_nodes; ++i) {
     if(nodes_set[i] == NORMAL_SET) nodes_type[i] = -1;
     else if(nodes_set[i] == GHOST_SET) nodes_type[i] = -3;
     else if(nodes_set[i] == (GHOST_SET + NORMAL_SET)) nodes_type[i] = -2;
   }
 
   delete [] nodes_set;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::fillCommunicationScheme(const UInt * partition,
 						      UInt nb_local_element,
 						      UInt nb_ghost_element,
 						      ElementType type) {
   AKANTU_DEBUG_IN();
 
   Element element;
   element.type = type;
   element.kind = Mesh::getKind(type);
 
   const UInt * part = partition;
 
   part = partition;
   for (UInt lel = 0; lel < nb_local_element; ++lel) {
     UInt nb_send = *part; part++;
     element.element = lel;
     element.ghost_type = _not_ghost;
     for (UInt p = 0; p < nb_send; ++p) {
       UInt proc = *part; part++;
 
       AKANTU_DEBUG(dblAccessory, "Must send : " << element << " to proc " << proc);
       (send_element[proc]).push_back(element);
     }
   }
 
   for (UInt gel = 0; gel < nb_ghost_element; ++gel) {
     UInt proc = *part; part++;
     element.element = gel;
     element.ghost_type = _ghost;
     AKANTU_DEBUG(dblAccessory, "Must recv : " << element << " from proc " << proc);
     recv_element[proc].push_back(element);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::asynchronousSynchronize(DataAccessor & data_accessor,
 						      SynchronizationTag tag) {
   AKANTU_DEBUG_IN();
 
   if (communications.find(tag) == communications.end())
     computeBufferSize(data_accessor, tag);
 
   Communication & communication = communications[tag];
 
   AKANTU_DEBUG_ASSERT(communication.send_requests.size() == 0,
 		      "There must be some pending sending communications. Tag is " << tag);
 
   std::map<SynchronizationTag, UInt>::iterator t_it = tag_counter.find(tag);
   UInt counter = 0;
   if(t_it == tag_counter.end()) {
     tag_counter[tag] = 0;
   } else {
     counter = ++(t_it->second);
   }
 
   for (UInt p = 0; p < nb_proc; ++p) {
     UInt ssize = communication.size_to_send[p];
     if(p == rank || ssize == 0) continue;
 
     CommunicationBuffer & buffer = communication.send_buffer[p];
     buffer.resize(ssize);
 #ifndef AKANTU_NDEBUG
     UInt nb_elements   =  send_element[p].getSize();
     AKANTU_DEBUG_INFO("Packing data for proc " << p
 		      << " (" << ssize << "/" << nb_elements
 		      <<" data to send/elements)");
 
     /// pack barycenters in debug mode
     Array<Element>::const_iterator<Element> bit  = send_element[p].begin();
     Array<Element>::const_iterator<Element> bend = send_element[p].end();
     for (; bit != bend; ++bit) {
       const Element & element = *bit;
       Vector<Real> barycenter(mesh.getSpatialDimension());
       mesh.getBarycenter(element.element, element.type, barycenter.storage(), element.ghost_type);
       buffer << barycenter;
     }
 #endif
 
     data_accessor.packElementData(buffer, send_element[p], tag);
 
     AKANTU_DEBUG_ASSERT(buffer.getPackedSize() == ssize,
 			"a problem have been introduced with "
 			<< "false sent sizes declaration "
 			<< buffer.getPackedSize() << " != " << ssize);
     AKANTU_DEBUG_INFO("Posting send to proc " << p
 		      << " (tag: " << tag << " - " << ssize << " data to send)"
 		      << " [" << Tag::genTag(rank, counter, tag) << "]");
     communication.send_requests.push_back(static_communicator->asyncSend(buffer.storage(),
 									 ssize,
 									 p,
 									 Tag::genTag(rank, counter, tag)));
   }
 
   AKANTU_DEBUG_ASSERT(communication.recv_requests.size() == 0,
 		      "There must be some pending receive communications");
 
   for (UInt p = 0; p < nb_proc; ++p) {
     UInt rsize = communication.size_to_receive[p];
     if(p == rank || rsize == 0) continue;
     CommunicationBuffer & buffer = communication.recv_buffer[p];
     buffer.resize(rsize);
 
     AKANTU_DEBUG_INFO("Posting receive from proc " << p
 		      << " (tag: " << tag << " - " << rsize << " data to receive) "
 		      << " [" << Tag::genTag(p, counter, tag) << "]");
     communication.recv_requests.push_back(static_communicator->asyncReceive(buffer.storage(),
 									    rsize,
 									    p,
 									    Tag::genTag(p, counter, tag)));
   }
 
 
 #if defined(AKANTU_DEBUG_TOOLS) && defined(AKANTU_CORE_CXX11)
   static std::set<SynchronizationTag> tags;
   if(tags.find(tag) == tags.end()) {
     debug::element_manager.print(debug::_dm_synch,
 				 [&send_element, rank, nb_proc, tag, id](const Element & el)->std::string {
 				   std::stringstream out;
 				   UInt elp = 0;
 				   for (UInt p = 0; p < nb_proc; ++p) {
 				     UInt pos = send_element[p].find(el);
 				     if(pos != UInt(-1)) {
 				       if(elp > 0) out << std::endl;
 				       out << id << " send (" << pos << "/" << send_element[p].getSize() << ") to proc " << p << " tag:" << tag;
 				       ++elp;
 				     }
 				   }
 				   return out.str();
 				 });
 
     debug::element_manager.print(debug::_dm_synch,
 				 [&recv_element, rank, nb_proc, tag, id](const Element & el)->std::string {
 				   std::stringstream out;
 				   UInt elp = 0;
 				   for (UInt p = 0; p < nb_proc; ++p) {
 				     if(p == rank) continue;
 				     UInt pos = recv_element[p].find(el);
 				     if(pos != UInt(-1)) {
 				       if(elp > 0) out << std::endl;
 				       out << id << " recv (" << pos << "/" << recv_element[p].getSize() << ") from proc " << p << " tag:" << tag;
 				       ++elp;
 				     }
 				   }
 				   return out.str();
 				 });
     tags.insert(tag);
   }
 #endif
 
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::waitEndSynchronize(DataAccessor & data_accessor,
 						 SynchronizationTag tag) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_ASSERT(communications.find(tag) != communications.end(), "No communication with the tag \""
 		      << tag <<"\" started");
 
   Communication & communication = communications[tag];
 
   std::vector<CommunicationRequest *> req_not_finished;
   std::vector<CommunicationRequest *> * req_not_finished_tmp = &req_not_finished;
   std::vector<CommunicationRequest *> * recv_requests_tmp = &(communication.recv_requests);
 
   //  static_communicator->waitAll(recv_requests);
   while(!recv_requests_tmp->empty()) {
     for (std::vector<CommunicationRequest *>::iterator req_it = recv_requests_tmp->begin();
 	 req_it != recv_requests_tmp->end() ; ++req_it) {
       CommunicationRequest * req = *req_it;
 
       if(static_communicator->testRequest(req)) {
 	UInt proc = req->getSource();
 	AKANTU_DEBUG_INFO("Unpacking data coming from proc " << proc);
 	CommunicationBuffer & buffer = communication.recv_buffer[proc];
 
 #ifndef AKANTU_NDEBUG
 	Array<Element>::const_iterator<Element> bit  = recv_element[proc].begin();
 	Array<Element>::const_iterator<Element> bend = recv_element[proc].end();
 
 	UInt spatial_dimension = mesh.getSpatialDimension();
 
 	for (; bit != bend; ++bit) {
 	  const Element & element = *bit;
 
 	  Vector<Real> barycenter_loc(spatial_dimension);
 	  mesh.getBarycenter(element.element,
 			     element.type,
 			     barycenter_loc.storage(),
 			     element.ghost_type);
 	  Vector<Real> barycenter(spatial_dimension);
 	  buffer >> barycenter;
 	  Real tolerance = Math::getTolerance();
 	  Real bary_norm = barycenter.norm();
 	  for (UInt i = 0; i < spatial_dimension; ++i) {
 	    if((std::abs((barycenter(i) - barycenter_loc(i))/bary_norm) <= tolerance) ||
 	       (std::abs(barycenter_loc(i)) <= tolerance && std::abs(barycenter(i)) <= tolerance)) continue;
 	    AKANTU_DEBUG_ERROR("Unpacking an unknown value for the element: "
 			       << element
 			       << "(barycenter[" << i << "] = " << barycenter_loc(i)
 			       << " and buffer[" << i << "] = " << barycenter(i) << ") ["
 			       << std::abs((barycenter(i) - barycenter_loc(i))/barycenter_loc(i))
 			       << "] - tag: " << tag);
 	  }
 	}
 #endif
 
 	data_accessor.unpackElementData(buffer, recv_element[proc], tag);
 	buffer.resize(0);
 
 	AKANTU_DEBUG_ASSERT(buffer.getLeftToUnpack() == 0,
 			    "all data have not been unpacked: "
 			    << buffer.getLeftToUnpack() << " bytes left");
 	static_communicator->freeCommunicationRequest(req);
       } else {
 	req_not_finished_tmp->push_back(req);
       }
     }
 
     std::vector<CommunicationRequest *> * swap = req_not_finished_tmp;
     req_not_finished_tmp = recv_requests_tmp;
     recv_requests_tmp = swap;
 
     req_not_finished_tmp->clear();
   }
 
 
   AKANTU_DEBUG_INFO("Waiting that every send requests are received");
   static_communicator->waitAll(communication.send_requests);
   for (std::vector<CommunicationRequest *>::iterator req_it = communication.send_requests.begin();
        req_it != communication.send_requests.end() ; ++req_it) {
     CommunicationRequest & req = *(*req_it);
 
     if(static_communicator->testRequest(&req)) {
       UInt proc = req.getDestination();
       CommunicationBuffer & buffer = communication.send_buffer[proc];
       buffer.resize(0);
       static_communicator->freeCommunicationRequest(&req);
     }
   }
   communication.send_requests.clear();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::computeBufferSize(DataAccessor & data_accessor,
 						SynchronizationTag tag) {
   AKANTU_DEBUG_IN();
 
   communications[tag].resize(nb_proc);
 
   for (UInt p = 0; p < nb_proc; ++p) {
     UInt ssend    = 0;
     UInt sreceive = 0;
     if(p != rank) {
       if(send_element[p].getSize() != 0) {
 #ifndef AKANTU_NDEBUG
 	ssend += send_element[p].getSize() * mesh.getSpatialDimension() * sizeof(Real);
 #endif
 	ssend += data_accessor.getNbDataForElements(send_element[p], tag);
 	AKANTU_DEBUG_INFO("I have " << ssend << "(" << ssend / 1024.
 			  << "kB - "<< send_element[p].getSize() <<" element(s)) data to send to " << p << " for tag "
 			  << tag);
       }
 
       if(recv_element[p].getSize() != 0) {
 #ifndef AKANTU_NDEBUG
 	sreceive += recv_element[p].getSize() * mesh.getSpatialDimension() * sizeof(Real);
 #endif
 	sreceive += data_accessor.getNbDataForElements(recv_element[p], tag);
 	AKANTU_DEBUG_INFO("I have " << sreceive << "(" << sreceive / 1024.
 			  << "kB - "<< recv_element[p].getSize() <<" element(s)) data to receive for tag "
 			  << tag);
       }
     }
 
     communications[tag].size_to_send   [p] = ssend;
     communications[tag].size_to_receive[p] = sreceive;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
+/* -------------------------------------------------------------------------- */
+void DistributedSynchronizer::computeAllBufferSizes(DataAccessor & data_accessor) {
+  std::map<SynchronizationTag, Communication>::iterator it = this->communications.begin();
+  std::map<SynchronizationTag, Communication>::iterator end = this->communications.end();
+
+  for (; it != end; ++it) {
+    SynchronizationTag tag = it->first;
+    this->computeBufferSize(data_accessor, tag);
+  }
+
+}
+
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::printself(std::ostream & stream, int indent) const {
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
 
   Int prank = StaticCommunicator::getStaticCommunicator().whoAmI();
   Int psize = StaticCommunicator::getStaticCommunicator().getNbProc();
   stream << "[" << prank << "/" << psize << "]" << space << "DistributedSynchronizer [" << std::endl;
   for (UInt p = 0; p < nb_proc; ++p) {
     if (p == UInt(prank)) continue;
     stream << "[" << prank << "/" << psize << "]" << space
 	   << " + Communication to proc " << p << " [" << std::endl;
     if(AKANTU_DEBUG_TEST(dblDump)) {
       stream << "[" << prank << "/" << psize << "]" << space
 	     << "    - Element to send to proc " << p << " [" << std::endl;
 
       Array<Element>::iterator<Element> it_el  = send_element[p].begin();
       Array<Element>::iterator<Element> end_el = send_element[p].end();
       for(;it_el != end_el; ++it_el)
 	stream << "[" << prank << "/" << psize << "]" << space << "       " << *it_el << std::endl;
       stream << "[" << prank << "/" << psize << "]" << space << "   ]" << std::endl;
 
       stream << "[" << prank << "/" << psize << "]" << space
 	     << "    - Element to recv from proc " << p << " [" << std::endl;
 
       it_el  = recv_element[p].begin();
       end_el = recv_element[p].end();
       for(;it_el != end_el; ++it_el)
 	stream << "[" << prank << "/" << psize << "]"
 	       << space << "       " << *it_el << std::endl;
 
       stream << "[" << prank << "/" << psize << "]" << space << "   ]" << std::endl;
     }
 
     std::map< SynchronizationTag, Communication>::const_iterator it = communications.begin();
     std::map< SynchronizationTag, Communication>::const_iterator end = communications.end();
     for (; it != end; ++it) {
       const SynchronizationTag & tag = it->first;
       const Communication & communication = it->second;
       UInt ssend    = communication.size_to_send[p];
       UInt sreceive = communication.size_to_receive[p];
       stream << "[" << prank << "/" << psize << "]" << space << "     - Tag " << tag << " -> " << ssend << "byte(s) -- <- " << sreceive << "byte(s)" << std::endl;
     }
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::onElementsRemoved(const Array<Element> & element_to_remove,
 						const ElementTypeMapArray<UInt> & new_numbering,
 						__attribute__((unused)) const RemovedElementsEvent & event) {
   AKANTU_DEBUG_IN();
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   UInt psize = comm.getNbProc();
   UInt prank = comm.whoAmI();
 
   std::vector<CommunicationRequest *> isend_requests;
   Array<UInt> * list_of_el = new Array<UInt>[nb_proc];
   // Handling ghost elements
   for (UInt p = 0; p < psize; ++p) {
     if (p == prank) continue;
 
     Array<Element> & recv = recv_element[p];
     if(recv.getSize() == 0) continue;
 
     Array<Element>::iterator<Element> recv_begin = recv.begin();
     Array<Element>::iterator<Element> recv_end   = recv.end();
 
     Array<Element>::const_iterator<Element> er_it  = element_to_remove.begin();
     Array<Element>::const_iterator<Element> er_end = element_to_remove.end();
 
     Array<UInt> & list = list_of_el[p];
     for (UInt i = 0; recv_begin != recv_end; ++i, ++recv_begin) {
       const Element & el = *recv_begin;
       Array<Element>::const_iterator<Element> pos = std::find(er_it, er_end, el);
       if(pos == er_end) {
 	list.push_back(i);
       }
     }
 
     if(list.getSize() == recv.getSize())
       list.push_back(UInt(0));
     else list.push_back(UInt(-1));
 
     AKANTU_DEBUG_INFO("Sending a message of size " << list.getSize() << " to proc " << p << " TAG(" << Tag::genTag(prank, 0, 0) << ")");
     isend_requests.push_back(comm.asyncSend(list.storage(), list.getSize(),
 					    p, Tag::genTag(prank, 0, 0)));
 
     list.erase(list.getSize() - 1);
     if(list.getSize() == recv.getSize()) continue;
 
     Array<Element> new_recv;
     for (UInt nr = 0; nr < list.getSize(); ++nr) {
       Element & el = recv(list(nr));
       el.element = new_numbering(el.type, el.ghost_type)(el.element);
       new_recv.push_back(el);
     }
 
     AKANTU_DEBUG_INFO("I had " << recv.getSize() << " elements to recv from proc " << p << " and "
 		      << list.getSize() << " elements to keep. I have "
 		      << new_recv.getSize() << " elements left.");
     recv.copy(new_recv);
   }
 
   for (UInt p = 0; p < psize; ++p) {
     if (p == prank) continue;
     Array<Element> & send = send_element[p];
 
     if(send.getSize() == 0) continue;
 
     CommunicationStatus status;
     AKANTU_DEBUG_INFO("Getting number of elements of proc " << p << " not needed anymore TAG("<< Tag::genTag(p, 0, 0) <<")");
     comm.probe<UInt>(p, Tag::genTag(p, 0, 0), status);
     Array<UInt> list(status.getSize());
 
     AKANTU_DEBUG_INFO("Receiving list of elements (" << status.getSize() - 1
 		      << " elements) no longer needed by proc " << p
 		      << " TAG("<< Tag::genTag(p, 0, 0) <<")");
     comm.receive(list.storage(), list.getSize(),
 		 p, Tag::genTag(p, 0, 0));
 
     if(list.getSize() == 1 && list(0) == 0) continue;
 
     list.erase(list.getSize() - 1);
 
     Array<Element> new_send;
     for (UInt ns = 0; ns < list.getSize(); ++ns) {
       new_send.push_back(send(list(ns)));
     }
 
     AKANTU_DEBUG_INFO("I had " << send.getSize() << " elements to send to proc " << p << " and "
 		      << list.getSize() << " elements to keep. I have "
 		      << new_send.getSize() << " elements left.");
     send.copy(new_send);
   }
 
   comm.waitAll(isend_requests);
   comm.freeCommunicationRequest(isend_requests);
 
   delete [] list_of_el;
   AKANTU_DEBUG_OUT();
 }
 
 
 // void DistributedSynchronizer::checkCommunicationScheme() {
 //   for (UInt p = 0; p < psize; ++p) {
 //     if (p == prank) continue;
 //     for(UInt e(0), e < recv_element.getSize())
 //   }
 // }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::buildPrankToElement() {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   mesh.initElementTypeMapArray(prank_to_element,
 			      1,
 			      spatial_dimension,
 			      false,
 			      _ek_not_defined,
 			      true);
 
   Mesh::type_iterator it  = mesh.firstType(spatial_dimension,
 					   _not_ghost,
 					   _ek_not_defined);
 
   Mesh::type_iterator end = mesh.lastType(spatial_dimension,
 					  _not_ghost,
 					  _ek_not_defined);
 
   /// assign prank to all not ghost elements
   for (; it != end; ++it) {
     UInt nb_element = mesh.getNbElement(*it);
     Array<UInt> & prank_to_el = prank_to_element(*it);
     for (UInt el = 0; el < nb_element; ++el) {
       prank_to_el(el) = rank;
     }
   }
 
   /// assign prank to all ghost elements
   for (UInt p = 0; p < nb_proc; ++p) {
     UInt nb_ghost_element = recv_element[p].getSize();
 
     for (UInt el = 0; el < nb_ghost_element; ++el) {
       UInt element = recv_element[p](el).element;
       ElementType type = recv_element[p](el).type;
       GhostType ghost_type = recv_element[p](el).ghost_type;
 
       Array<UInt> & prank_to_el = prank_to_element(type, ghost_type);
       prank_to_el(element) = p;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::filterElementsByKind(DistributedSynchronizer * new_synchronizer,
 						   ElementKind kind) {
   AKANTU_DEBUG_IN();
 
   Array<Element> * newsy_send_element = new_synchronizer->send_element;
   Array<Element> * newsy_recv_element = new_synchronizer->recv_element;
 
   Array<Element> * new_send_element = new Array<Element>[nb_proc];
   Array<Element> * new_recv_element = new Array<Element>[nb_proc];
 
   for (UInt p = 0; p < nb_proc; ++p) {
 
     /// send element copying part
     new_send_element[p].resize(0);
 
     for (UInt el = 0; el < send_element[p].getSize(); ++el) {
       Element & element = send_element[p](el);
 
       if (element.kind == kind)
 	newsy_send_element[p].push_back(element);
       else
 	new_send_element[p].push_back(element);
     }
 
     /// recv element copying part
     new_recv_element[p].resize(0);
 
     for (UInt el = 0; el < recv_element[p].getSize(); ++el) {
       Element & element = recv_element[p](el);
 
       if (element.kind == kind)
 	newsy_recv_element[p].push_back(element);
       else
 	new_recv_element[p].push_back(element);
     }
   }
 
   /// deleting and reassigning old pointers
   delete [] send_element;
   delete [] recv_element;
 
   send_element = new_send_element;
   recv_element = new_recv_element;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::reset() {
   AKANTU_DEBUG_IN();
 
   for (UInt p = 0; p < nb_proc; ++p) {
     send_element[p].resize(0);
     recv_element[p].resize(0);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::synchronizeTagsSend(DistributedSynchronizer & communicator,
 						  UInt root,
 						  Mesh & mesh,
 						  UInt nb_tags,
 						  const ElementType & type,
 						  const Array<UInt> & partition_num,
 						  const CSR<UInt> & ghost_partition,
 						  UInt nb_local_element,
 						  UInt nb_ghost_element) {
   AKANTU_DEBUG_IN();
 
   static UInt count = 0;
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   UInt nb_proc = comm.getNbProc();
   UInt my_rank = comm.whoAmI();
 
   if(nb_tags == 0) {
     AKANTU_DEBUG_OUT();
     return;
   }
 
   UInt mesh_data_sizes_buffer_length;
   MeshData & mesh_data = mesh.getMeshData();
 
   /// tag info
   std::vector<std::string> tag_names;
   mesh.getMeshData().getTagNames(tag_names, type);
   // Make sure the tags are sorted (or at least not in random order),
   // because they come from a map !!
   std::sort(tag_names.begin(), tag_names.end());
 
 
   // Sending information about the tags in mesh_data: name, data type and
   // number of components of the underlying array associated to the current type
   DynamicCommunicationBuffer mesh_data_sizes_buffer;
   std::vector<std::string>::const_iterator names_it  = tag_names.begin();
   std::vector<std::string>::const_iterator names_end = tag_names.end();
   for(;names_it != names_end; ++names_it) {
     mesh_data_sizes_buffer << *names_it;
     mesh_data_sizes_buffer << mesh_data.getTypeCode(*names_it);
     mesh_data_sizes_buffer << mesh_data.getNbComponent(*names_it, type);
   }
 
   mesh_data_sizes_buffer_length = mesh_data_sizes_buffer.getSize();
   AKANTU_DEBUG_INFO("Broadcasting the size of the information about the mesh data tags: (" << mesh_data_sizes_buffer_length << ")." );
   comm.broadcast(&mesh_data_sizes_buffer_length, 1, root);
   AKANTU_DEBUG_INFO("Broadcasting the information about the mesh data tags, addr " << (void*)mesh_data_sizes_buffer.storage());
 
   if(mesh_data_sizes_buffer_length !=0)
     comm.broadcast(mesh_data_sizes_buffer.storage(), mesh_data_sizes_buffer.getSize(), root);
 
 
   if(mesh_data_sizes_buffer_length !=0) {
     //Sending the actual data to each processor
     DynamicCommunicationBuffer buffers[nb_proc];
     std::vector<std::string>::const_iterator names_it  = tag_names.begin();
     std::vector<std::string>::const_iterator names_end = tag_names.end();
 
     // Loop over each tag for the current type
     for(;names_it != names_end; ++names_it) {
       // Type code of the current tag (i.e. the tag named *names_it)
       communicator.fillTagBuffer(mesh_data,
 				 buffers,
 				 *names_it,
 				 type,
 				 partition_num,
 				 ghost_partition);
     }
 
     std::vector<CommunicationRequest *> requests;
     for (UInt p = 0; p < nb_proc; ++p) {
       if(p != root) {
 	AKANTU_DEBUG_INFO("Sending " << buffers[p].getSize() << " bytes of mesh data to proc " << p << " TAG("<< Tag::genTag(my_rank, count, TAG_MESH_DATA) <<")");
 
 	requests.push_back(comm.asyncSend(buffers[p].storage(),
 					  buffers[p].getSize(), p, Tag::genTag(my_rank, count, TAG_MESH_DATA)));
       }
     }
 
     names_it  = tag_names.begin();
     // Loop over each tag for the current type
     for(;names_it != names_end; ++names_it) {
       // Reinitializing the mesh data on the master
       communicator.populateMeshData(mesh_data,
 				    buffers[root],
 				    *names_it,
 				    type,
 				    mesh_data.getTypeCode(*names_it),
 				    mesh_data.getNbComponent(*names_it, type),
 				    nb_local_element,
 				    nb_ghost_element);
     }
 
 
     comm.waitAll(requests);
     comm.freeCommunicationRequest(requests);
     requests.clear();
   }
 
   ++count;
 
   AKANTU_DEBUG_OUT();
 }
 
 
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::synchronizeTagsRecv(DistributedSynchronizer & communicator,
 						  UInt root,
 						  Mesh & mesh,
 						  UInt nb_tags,
 						  const ElementType & type,
 						  UInt nb_local_element,
 						  UInt nb_ghost_element) {
   AKANTU_DEBUG_IN();
 
   static UInt count = 0;
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
 
   if(nb_tags == 0) {
     AKANTU_DEBUG_OUT();
     return;
   }
 
   /* --------<<<<-TAGS------------------------------------------------- */
   UInt mesh_data_sizes_buffer_length = 0;
   CommunicationBuffer mesh_data_sizes_buffer;
   MeshData & mesh_data = mesh.getMeshData();
 
   AKANTU_DEBUG_INFO("Receiving the size of the information about the mesh data tags.");
   comm.broadcast(&mesh_data_sizes_buffer_length, 1, root);
 
   if(mesh_data_sizes_buffer_length != 0) {
     mesh_data_sizes_buffer.resize(mesh_data_sizes_buffer_length);
     AKANTU_DEBUG_INFO("Receiving the information about the mesh data tags, addr " << (void*)mesh_data_sizes_buffer.storage());
     comm.broadcast(mesh_data_sizes_buffer.storage(), mesh_data_sizes_buffer_length, root);
     AKANTU_DEBUG_INFO("Size of the information about the mesh data: " << mesh_data_sizes_buffer_length);
 
     std::vector<std::string> tag_names;
     std::vector<MeshDataTypeCode> tag_type_codes;
     std::vector<UInt> tag_nb_component;
     tag_names.resize(nb_tags);
     tag_type_codes.resize(nb_tags);
     tag_nb_component.resize(nb_tags);
     CommunicationBuffer mesh_data_buffer;
     UInt type_code_int;
     for(UInt i(0); i < nb_tags; ++i) {
       mesh_data_sizes_buffer >> tag_names[i];
       mesh_data_sizes_buffer >> type_code_int;
       tag_type_codes[i] = static_cast<MeshDataTypeCode>(type_code_int);
       mesh_data_sizes_buffer >> tag_nb_component[i];
     }
 
     std::vector<std::string>::const_iterator names_it  = tag_names.begin();
     std::vector<std::string>::const_iterator names_end = tag_names.end();
 
     CommunicationStatus mesh_data_comm_status;
     AKANTU_DEBUG_INFO("Checking size of data to receive for mesh data TAG("
 		      << Tag::genTag(root, count, TAG_MESH_DATA) << ")");
     comm.probe<char>(root, Tag::genTag(root, count, TAG_MESH_DATA), mesh_data_comm_status);
     UInt mesh_data_buffer_size(mesh_data_comm_status.getSize());
     AKANTU_DEBUG_INFO("Receiving " << mesh_data_buffer_size
 		      << " bytes of mesh data TAG("
 		      << Tag::genTag(root, count, TAG_MESH_DATA) << ")");
     mesh_data_buffer.resize(mesh_data_buffer_size);
     comm.receive(mesh_data_buffer.storage(),
 		 mesh_data_buffer_size,
 		 root,
 		 Tag::genTag(root, count, TAG_MESH_DATA));
 
     // Loop over each tag for the current type
     UInt k(0);
     for(; names_it != names_end; ++names_it, ++k) {
       communicator.populateMeshData(mesh_data, mesh_data_buffer,
 				    *names_it, type,
 				    tag_type_codes[k],
 				    tag_nb_component[k],
 				    nb_local_element, nb_ghost_element);
     }
   }
 
   ++count;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<class CommunicationBuffer>
 void DistributedSynchronizer::fillElementGroupsFromBuffer(DistributedSynchronizer & communicator,
 							  Mesh & mesh,
 							  const ElementType & type,
 							  CommunicationBuffer & buffer) {
   AKANTU_DEBUG_IN();
 
   Element el;
   el.type = type;
 
   for (ghost_type_t::iterator gt = ghost_type_t::begin();  gt != ghost_type_t::end(); ++gt) {
     UInt nb_element = mesh.getNbElement(type, *gt);
     el.ghost_type = *gt;
 
     for (UInt e = 0; e < nb_element; ++e) {
       el.element = e;
 
       std::vector<std::string> element_to_group;
       buffer >> element_to_group;
 
       AKANTU_DEBUG_ASSERT(e < mesh.getNbElement(type, *gt), "The mesh does not have the element " << e);
 
       std::vector<std::string>::iterator it  = element_to_group.begin();
       std::vector<std::string>::iterator end = element_to_group.end();
       for (; it != end; ++it) {
 	mesh.getElementGroup(*it).add(el, false, false);
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::synchronizeElementGroups(DistributedSynchronizer & communicator,
 						       UInt root,
 						       Mesh & mesh,
 						       const ElementType & type,
 						       const Array<UInt> & partition_num,
 						       const CSR<UInt> & ghost_partition,
 						       UInt nb_element) {
   AKANTU_DEBUG_IN();
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
 
   UInt nb_proc = comm.getNbProc();
   UInt my_rank = comm.whoAmI();
 
   DynamicCommunicationBuffer buffers[nb_proc];
 
   typedef std::vector< std::vector<std::string> > ElementToGroup;
   ElementToGroup element_to_group;
   element_to_group.resize(nb_element);
 
   GroupManager::const_element_group_iterator egi = mesh.element_group_begin();
   GroupManager::const_element_group_iterator ege = mesh.element_group_end();
   for (; egi != ege; ++egi) {
     ElementGroup & eg = *(egi->second);
 
     std::string name = egi->first;
 
     ElementGroup::const_element_iterator eit  = eg.element_begin(type, _not_ghost);
     ElementGroup::const_element_iterator eend = eg.element_end(type, _not_ghost);
     for (; eit != eend; ++eit) {
       element_to_group[*eit].push_back(name);
     }
 
     eit  = eg.element_begin(type, _not_ghost);
     if(eit != eend)
       const_cast<Array<UInt> &>(eg.getElements(type)).empty();
   }
 
   /// preparing the buffers
   const UInt * part = partition_num.storage();
 
   /// copying the data, element by element
   ElementToGroup::const_iterator data_it  = element_to_group.begin();
   ElementToGroup::const_iterator data_end = element_to_group.end();
   for (; data_it != data_end; ++part, ++data_it) {
     buffers[*part] << *data_it;
   }
 
   data_it = element_to_group.begin();
   /// copying the data for the ghost element
   for (UInt el(0); data_it != data_end; ++data_it, ++el) {
     CSR<UInt>::const_iterator it  = ghost_partition.begin(el);
     CSR<UInt>::const_iterator end = ghost_partition.end(el);
     for (;it != end; ++it) {
       UInt proc = *it;
       buffers[proc] << *data_it;
     }
   }
 
 
   std::vector<CommunicationRequest *> requests;
   for (UInt p = 0; p < nb_proc; ++p) {
     if(p == my_rank) continue;
     AKANTU_DEBUG_INFO("Sending element groups to proc " << p
 		      << " TAG("<< Tag::genTag(my_rank, p, TAG_ELEMENT_GROUP) <<")");
     requests.push_back(comm.asyncSend(buffers[p].storage(),
 				      buffers[p].getSize(),
 				      p,
 				      Tag::genTag(my_rank, p, TAG_ELEMENT_GROUP)));
   }
 
   fillElementGroupsFromBuffer(communicator, mesh, type, buffers[my_rank]);
 
   comm.waitAll(requests);
   comm.freeCommunicationRequest(requests);
   requests.clear();
 
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::synchronizeElementGroups(DistributedSynchronizer & communicator,
 						       UInt root,
 						       Mesh & mesh,
 						       const ElementType & type) {
   AKANTU_DEBUG_IN();
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   UInt my_rank = comm.whoAmI();
 
 
   AKANTU_DEBUG_INFO("Receiving element groups from proc " << root
 		    << " TAG("<< Tag::genTag(root, my_rank, TAG_ELEMENT_GROUP) <<")");
 
   CommunicationStatus status;
   comm.probe<char>(root, Tag::genTag(root, my_rank, TAG_ELEMENT_GROUP), status);
 
   CommunicationBuffer buffer(status.getSize());
   comm.receive(buffer.storage(), buffer.getSize(), root, Tag::genTag(root, my_rank, TAG_ELEMENT_GROUP));
 
   fillElementGroupsFromBuffer(communicator, mesh, type, buffer);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template<class CommunicationBuffer>
 void DistributedSynchronizer::fillNodeGroupsFromBuffer(DistributedSynchronizer & communicator,
 						       Mesh & mesh,
 						       CommunicationBuffer & buffer) {
   AKANTU_DEBUG_IN();
 
   std::vector< std::vector<std::string> > node_to_group;
 
   buffer >> node_to_group;
 
   AKANTU_DEBUG_ASSERT(node_to_group.size() == mesh.getNbGlobalNodes(),
 		      "Not the good amount of nodes where transmitted");
 
   const Array<UInt> & global_nodes = mesh.getGlobalNodesIds();
 
   Array<UInt>::const_scalar_iterator nbegin = global_nodes.begin();
   Array<UInt>::const_scalar_iterator nit    = global_nodes.begin();
   Array<UInt>::const_scalar_iterator nend   = global_nodes.end();
 
   for (; nit != nend; ++nit) {
     std::vector<std::string>::iterator it    = node_to_group[*nit].begin();
     std::vector<std::string>::iterator end   = node_to_group[*nit].end();
 
     for (; it != end; ++it) {
       mesh.getNodeGroup(*it).add(nit - nbegin, false);
     }
   }
 
   GroupManager::const_node_group_iterator ngi = mesh.node_group_begin();
   GroupManager::const_node_group_iterator nge = mesh.node_group_end();
   for (; ngi != nge; ++ngi) {
     NodeGroup & ng = *(ngi->second);
     ng.optimize();
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::synchronizeNodeGroupsMaster(DistributedSynchronizer & communicator,
 							  UInt root,
 							  Mesh & mesh) {
   AKANTU_DEBUG_IN();
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
 
   UInt nb_proc = comm.getNbProc();
   UInt my_rank = comm.whoAmI();
 
   UInt nb_total_nodes = mesh.getNbGlobalNodes();
 
   DynamicCommunicationBuffer buffer;
 
   typedef std::vector< std::vector<std::string> > NodeToGroup;
   NodeToGroup node_to_group;
   node_to_group.resize(nb_total_nodes);
 
   GroupManager::const_node_group_iterator ngi = mesh.node_group_begin();
   GroupManager::const_node_group_iterator nge = mesh.node_group_end();
   for (; ngi != nge; ++ngi) {
     NodeGroup & ng = *(ngi->second);
 
     std::string name = ngi->first;
 
     NodeGroup::const_node_iterator nit  = ng.begin();
     NodeGroup::const_node_iterator nend = ng.end();
     for (; nit != nend; ++nit) {
       node_to_group[*nit].push_back(name);
     }
 
     nit  = ng.begin();
     if(nit != nend)
       ng.empty();
   }
 
   buffer << node_to_group;
 
   std::vector<CommunicationRequest *> requests;
   for (UInt p = 0; p < nb_proc; ++p) {
     if(p == my_rank) continue;
     AKANTU_DEBUG_INFO("Sending node groups to proc " << p
 		      << " TAG("<< Tag::genTag(my_rank, p, TAG_NODE_GROUP) <<")");
     requests.push_back(comm.asyncSend(buffer.storage(),
 				      buffer.getSize(),
 				      p,
 				      Tag::genTag(my_rank, p, TAG_NODE_GROUP)));
   }
 
   fillNodeGroupsFromBuffer(communicator, mesh, buffer);
 
   comm.waitAll(requests);
   comm.freeCommunicationRequest(requests);
   requests.clear();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void DistributedSynchronizer::synchronizeNodeGroupsSlaves(DistributedSynchronizer & communicator,
 							  UInt root,
 							  Mesh & mesh) {
   AKANTU_DEBUG_IN();
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   UInt my_rank = comm.whoAmI();
 
 
   AKANTU_DEBUG_INFO("Receiving node groups from proc " << root
 		    << " TAG("<< Tag::genTag(root, my_rank, TAG_NODE_GROUP) <<")");
 
   CommunicationStatus status;
   comm.probe<char>(root, Tag::genTag(root, my_rank, TAG_NODE_GROUP), status);
 
   CommunicationBuffer buffer(status.getSize());
   comm.receive(buffer.storage(), buffer.getSize(), root, Tag::genTag(root, my_rank, TAG_NODE_GROUP));
 
   fillNodeGroupsFromBuffer(communicator, mesh, buffer);
 
   AKANTU_DEBUG_OUT();
 }
 
 __END_AKANTU__
diff --git a/src/synchronizer/distributed_synchronizer.hh b/src/synchronizer/distributed_synchronizer.hh
index 2edd12ab1..3630c7a70 100644
--- a/src/synchronizer/distributed_synchronizer.hh
+++ b/src/synchronizer/distributed_synchronizer.hh
@@ -1,268 +1,271 @@
 /**
  * @file   distributed_synchronizer.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  * @author Dana Christen <dana.christen@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Thu Jun 16 2011
  * @date last modification: Fri Sep 05 2014
  *
  * @brief  wrapper to the static communicator
  *
  * @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_DISTRIBUTED_SYNCHRONIZER_HH__
 #define __AKANTU_DISTRIBUTED_SYNCHRONIZER_HH__
 
 /* -------------------------------------------------------------------------- */
 #include "aka_common.hh"
 #include "aka_array.hh"
 #include "synchronizer.hh"
 #include "mesh.hh"
 #include "mesh_partition.hh"
 #include "communication_buffer.hh"
 
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_AKANTU__
 
 class DistributedSynchronizer : public Synchronizer, public MeshEventHandler {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   DistributedSynchronizer(Mesh & mesh,
                           SynchronizerID id = "distributed_synchronizer",
                           MemoryID memory_id = 0);
 
 public:
   virtual ~DistributedSynchronizer();
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// get a  mesh and a partition and  create the local mesh  and the associated
   /// DistributedSynchronizer
   static DistributedSynchronizer *
   createDistributedSynchronizerMesh(Mesh & mesh,
                                     const MeshPartition * partition,
                                     UInt root = 0,
                                     SynchronizerID id = "distributed_synchronizer",
                                     MemoryID memory_id = 0);
 
   /* ------------------------------------------------------------------------ */
   /* Inherited from Synchronizer                                              */
   /* ------------------------------------------------------------------------ */
 
   /// asynchronous synchronization of ghosts
   void asynchronousSynchronize(DataAccessor & data_accessor,SynchronizationTag tag);
 
   /// wait end of asynchronous synchronization of ghosts
   void waitEndSynchronize(DataAccessor & data_accessor,SynchronizationTag tag);
 
   /// build processor to element corrispondance
   void buildPrankToElement();
 
   virtual void printself(std::ostream & stream, int indent = 0) const;
 
   /// mesh event handler onRemovedElement
   virtual void onElementsRemoved(const Array<Element> & element_list,
                                  const ElementTypeMapArray<UInt> & new_numbering,
                                  const RemovedElementsEvent & event);
 
   /// filter elements of a certain kind and copy them into a new synchronizer
   void filterElementsByKind(DistributedSynchronizer * new_synchronizer,
 			    ElementKind kind);
 
   /// reset send and recv element lists
   void reset();
 
   /// compute buffer size for a given tag and data accessor
   void computeBufferSize(DataAccessor & data_accessor, SynchronizationTag tag);
 
+  /// recalculate buffer sizes for all tags
+  void computeAllBufferSizes(DataAccessor & data_accessor);
+
 protected:
   /// fill the nodes type vector
   void fillNodesType(Mesh & mesh);
 
   void fillNodesType(const MeshData & mesh_data,
                      DynamicCommunicationBuffer * buffers,
                      const std::string & tag_name,
                      const ElementType & el_type,
                      const Array<UInt> & partition_num);
 
   template<typename T>
   void fillTagBufferTemplated(const MeshData & mesh_data,
                               DynamicCommunicationBuffer * buffers,
                               const std::string & tag_name,
                               const ElementType & el_type,
                               const Array<UInt> & partition_num,
                               const CSR<UInt> & ghost_partition);
 
   void fillTagBuffer(const MeshData & mesh_data,
                      DynamicCommunicationBuffer * buffers,
                      const std::string & tag_name,
                      const ElementType & el_type,
                      const Array<UInt> & partition_num,
                      const CSR<UInt> & ghost_partition);
 
   template<typename T, typename BufferType>
   void populateMeshDataTemplated(MeshData & mesh_data,
                                  BufferType & buffer,
                                  const std::string & tag_name,
                                  const ElementType & el_type,
                                  UInt nb_component,
                                  UInt nb_local_element,
                                  UInt nb_ghost_element);
 
   template <typename BufferType>
   void populateMeshData(MeshData & mesh_data,
                         BufferType & buffer,
                         const std::string & tag_name,
                         const ElementType & el_type,
                         const MeshDataTypeCode & type_code,
                         UInt nb_component,
                         UInt nb_local_element,
                         UInt nb_ghost_element);
 
   /// fill the communications array of a distributedSynchronizer based on a partition array
   void fillCommunicationScheme(const UInt * partition,
                                UInt nb_local_element,
                                UInt nb_ghost_element,
                                ElementType type);
 
   /// function that handels the MeshData to be split (root side)
   static void synchronizeTagsSend(DistributedSynchronizer & communicator,
 				  UInt root,
 				  Mesh & mesh,
 				  UInt nb_tags,
 				  const ElementType & type,
 				  const Array<UInt> & partition_num,
 				  const CSR<UInt> & ghost_partition,
 				  UInt nb_local_element,
 				  UInt nb_ghost_element);
 
   /// function that handles the MeshData to be split (other nodes)
   static void synchronizeTagsRecv(DistributedSynchronizer & communicator,
 				  UInt root,
 				  Mesh & mesh,
 				  UInt nb_tags,
 				  const ElementType & type,
 				  UInt nb_local_element,
 				  UInt nb_ghost_element);
 
   /// function that handles the preexisting groups in the mesh
   static void synchronizeElementGroups(DistributedSynchronizer & communicator,
 				       UInt root,
 				       Mesh & mesh,
 				       const ElementType & type,
 				       const Array<UInt> & partition_num,
 				       const CSR<UInt> & ghost_partition,
 				       UInt nb_element);
 
 
   /// function that handles the preexisting groups in the mesh
   static void synchronizeElementGroups(DistributedSynchronizer & communicator,
 				       UInt root,
 				       Mesh & mesh,
 				       const ElementType & type);
 
   template<class CommunicationBuffer>
   static void fillElementGroupsFromBuffer(DistributedSynchronizer & communicator,
 					  Mesh & mesh,
 					  const ElementType & type,
 					  CommunicationBuffer & buffer);
 
   /// function that handles the preexisting groups in the mesh
   static void synchronizeNodeGroupsMaster(DistributedSynchronizer & communicator,
 					  UInt root,
 					  Mesh & mesh);
 
 
   /// function that handles the preexisting groups in the mesh
   static void synchronizeNodeGroupsSlaves(DistributedSynchronizer & communicator,
 					  UInt root,
 					  Mesh & mesh);
 
   template<class CommunicationBuffer>
   static void fillNodeGroupsFromBuffer(DistributedSynchronizer & communicator,
 					  Mesh & mesh,
 					  CommunicationBuffer & buffer);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   AKANTU_GET_MACRO(PrankToElement, prank_to_element, const ElementTypeMapArray<UInt> &);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   enum CommTags {
     TAG_SIZES        = 0,
     TAG_CONNECTIVITY = 1,
     TAG_DATA         = 2,
     TAG_PARTITIONS   = 3,
     TAG_NB_NODES     = 4,
     TAG_NODES        = 5,
     TAG_COORDINATES  = 6,
     TAG_NODES_TYPE   = 7,
     TAG_MESH_DATA    = 8,
     TAG_ELEMENT_GROUP = 9,
     TAG_NODE_GROUP = 10,
   };
 
 protected:
   /// reference to the underlying mesh
   Mesh & mesh;
 
   std::map<SynchronizationTag, Communication> communications;
 
   /// list of element to send to proc p
   Array<Element> * send_element;
   /// list of element to receive from proc p
   Array<Element> * recv_element;
 
   UInt nb_proc;
   UInt rank;
 
   friend class FilteredSynchronizer;
   friend class FacetSynchronizer;
 
   ElementTypeMapArray<UInt> prank_to_element;
 
 };
 
 __END_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 #include "distributed_synchronizer_tmpl.hh"
 
 
 #endif /* __AKANTU_DISTRIBUTED_SYNCHRONIZER_HH__ */
diff --git a/src/synchronizer/grid_synchronizer.cc b/src/synchronizer/grid_synchronizer.cc
index 426117c90..a4da85ce2 100644
--- a/src/synchronizer/grid_synchronizer.cc
+++ b/src/synchronizer/grid_synchronizer.cc
@@ -1,509 +1,514 @@
 /**
  * @file   grid_synchronizer.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Mon Oct 03 2011
  * @date last modification: Thu Jun 05 2014
  *
  * @brief  implementation of the grid synchronizer
  *
  * @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 "grid_synchronizer.hh"
 #include "aka_grid_dynamic.hh"
 #include "mesh.hh"
 #include "fe_engine.hh"
 #include "static_communicator.hh"
 #include "mesh_io.hh"
 #include <iostream>
 
 /* -------------------------------------------------------------------------- */
 
 
 __BEGIN_AKANTU__
 
 /* -------------------------------------------------------------------------- */
 GridSynchronizer::GridSynchronizer(Mesh & mesh,
 				   const ID & id,
                                    MemoryID memory_id) :
   DistributedSynchronizer(mesh, id, memory_id) {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <class E>
 GridSynchronizer * GridSynchronizer::createGridSynchronizer(Mesh & mesh,
                                                             const SpatialGrid<E> & grid,
+							    SynchronizerRegistry & synch_registry,
                                                             SynchronizerID id,
                                                             MemoryID memory_id) {
   AKANTU_DEBUG_IN();
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   UInt nb_proc = comm.getNbProc();
   UInt my_rank = comm.whoAmI();
 
   GridSynchronizer & communicator = *(new GridSynchronizer(mesh, id, memory_id));
   if(nb_proc == 1) return &communicator;
 
   UInt spatial_dimension = mesh.getSpatialDimension();
 
   Real * bounding_boxes = new Real[2 * spatial_dimension * nb_proc];
   Real * my_bounding_box = bounding_boxes + 2 * spatial_dimension * my_rank;
 
   // mesh.getLocalLowerBounds(my_bounding_box);
   // mesh.getLocalUpperBounds(my_bounding_box + spatial_dimension);
 
   const Vector<Real> & lower = grid.getLowerBounds();
   const Vector<Real> & upper = grid.getUpperBounds();
   const Vector<Real> & spacing = grid.getSpacing();
 
   for (UInt i = 0; i < spatial_dimension; ++i) {
     my_bounding_box[i                    ] = lower(i) - spacing(i);
     my_bounding_box[spatial_dimension + i] = upper(i) + spacing(i);
   }
 
   AKANTU_DEBUG_INFO("Exchange of bounding box to detect the overlapping regions.");
 
   comm.allGather(bounding_boxes, spatial_dimension * 2);
 
   bool * intersects_proc = new bool[nb_proc];
   std::fill_n(intersects_proc, nb_proc, true);
 
   Int * first_cells = new Int[3 * nb_proc];
   Int * last_cells = new Int[3 * nb_proc];
   std::fill_n(first_cells, 3 * nb_proc, 0);
   std::fill_n(first_cells, 3 * nb_proc, 0);
 
   ElementTypeMapArray<UInt> ** element_per_proc = new ElementTypeMapArray<UInt>* [nb_proc];
   for (UInt p = 0; p < nb_proc; ++p) element_per_proc[p] = NULL;
 
   // check the overlapping between my box and the one from other processors
   for (UInt p = 0; p < nb_proc; ++p) {
     if(p == my_rank) continue;
 
     Real * proc_bounding_box = bounding_boxes + 2 * spatial_dimension * p;
 
     bool intersects = false;
     Int * first_cell_p = first_cells + p * spatial_dimension;
     Int * last_cell_p =  last_cells  + p * spatial_dimension;
     for (UInt s = 0; s < spatial_dimension; ++s) {
 
       // check overlapping of grid
       intersects = Math::intersects(my_bounding_box[s],
                                     my_bounding_box[spatial_dimension + s],
                                     proc_bounding_box[s],
                                     proc_bounding_box[spatial_dimension + s]);
 
       intersects_proc[p] &= intersects;
 
       if(intersects) {
         AKANTU_DEBUG_INFO("I intersects with processor " << p << " in direction " << s);
 
         // is point 1 of proc p in the dimension s in the range ?
         bool point1 = Math::is_in_range(proc_bounding_box[s],
                                         my_bounding_box[s],
                                         my_bounding_box[s+spatial_dimension]);
 
         // is point 2 of proc p in the dimension s in the range ?
         bool point2 = Math::is_in_range(proc_bounding_box[s+spatial_dimension],
                                         my_bounding_box[s],
                                         my_bounding_box[s+spatial_dimension]);
 
         Real start = 0.;
         Real end = 0.;
 
         if(point1 && !point2) {
           /* |-----------|         my_bounding_box(i)
            *       |-----------|   proc_bounding_box(i)
            *       1           2
            */
           start = proc_bounding_box[s];
           end   = my_bounding_box[s+spatial_dimension];
 
           AKANTU_DEBUG_INFO("Intersection scheme 1 in direction " << s << " with processor " << p << " [" << start << ", " << end <<"]");
         } else if(point1 && point2) {
           /* |-----------------|   my_bounding_box(i)
            *   |-----------|       proc_bounding_box(i)
            *   1           2
            */
           start = proc_bounding_box[s];
           end   = proc_bounding_box[s+spatial_dimension];
 
           AKANTU_DEBUG_INFO("Intersection scheme 2 in direction " << s << " with processor " << p << " [" << start << ", " << end << "]");
         } else if(!point1 && point2) {
           /*       |-----------|   my_bounding_box(i)
            * |-----------|         proc_bounding_box(i)
            * 1           2
            */
           start = my_bounding_box[s];
           end   = proc_bounding_box[s+spatial_dimension];
 
           AKANTU_DEBUG_INFO("Intersection scheme 3 in direction " << s << " with processor " << p << " [" << start << ", " << end <<"]");
         } else {
           /*   |-----------|       my_bounding_box(i)
            * |-----------------|   proc_bounding_box(i)
            * 1                 2
            */
           start = my_bounding_box[s];
           end   = my_bounding_box[s+spatial_dimension];
 
           AKANTU_DEBUG_INFO("Intersection scheme 4 in direction " << s << " with processor " << p << " [" << start << ", " << end <<"]");
         }
 
 
         first_cell_p[s] = grid.getCellID(start, s);
         last_cell_p [s] = grid.getCellID(end, s);
       }
     }
 
 
     //create the list of cells in the overlapping
     typedef typename SpatialGrid<E>::CellID CellID;
 
     std::vector<CellID> * cell_ids = new std::vector<CellID>;
 
     if(intersects_proc[p]) {
       AKANTU_DEBUG_INFO("I intersects with processor " << p);
 
       CellID cell_id(spatial_dimension);
 
       // for (UInt i = 0; i < spatial_dimension; ++i) {
       //   if(first_cell_p[i] != 0) --first_cell_p[i];
       //   if(last_cell_p[i] != 0) ++last_cell_p[i];
       // }
 
       for (Int fd = first_cell_p[0]; fd <= last_cell_p[0]; ++fd) {
         cell_id.setID(0, fd);
         if(spatial_dimension == 1) {
           cell_ids->push_back(cell_id);
 	}
         else {
           for (Int sd = first_cell_p[1]; sd <= last_cell_p[1] ; ++sd) {
             cell_id.setID(1, sd);
             if(spatial_dimension == 2) {
               cell_ids->push_back(cell_id);
             } else {
               for (Int ld = first_cell_p[2]; ld <= last_cell_p[2] ; ++ld) {
                 cell_id.setID(2, ld);
                 cell_ids->push_back(cell_id);
               }
             }
           }
         }
       }
 
       // get the list of elements in the cells of the overlapping
       typename std::vector<CellID>::iterator cur_cell_id = cell_ids->begin();
       typename std::vector<CellID>::iterator last_cell_id = cell_ids->end();
       std::set<Element> * to_send = new std::set<Element>();
 
       for (; cur_cell_id != last_cell_id; ++cur_cell_id) {
         typename SpatialGrid<E>::Cell::const_iterator cur_elem = grid.beginCell(*cur_cell_id);
         typename SpatialGrid<E>::Cell::const_iterator last_elem = grid.endCell(*cur_cell_id);
 
         for (; cur_elem != last_elem; ++cur_elem) {
           to_send->insert(*cur_elem);
         }
       }
 
       AKANTU_DEBUG_INFO("I have prepared " << to_send->size() << " elements to send to processor " << p);
 
       std::stringstream sstr; sstr << "element_per_proc_" << p;
       element_per_proc[p] = new ElementTypeMapArray<UInt>(sstr.str(), id);
       ElementTypeMapArray<UInt> & elempproc = *(element_per_proc[p]);
 
       typename std::set<Element>::iterator elem = to_send->begin();
       typename std::set<Element>::iterator last_elem = to_send->end();
       for (; elem != last_elem; ++elem) {
         ElementType type = elem->type;
         UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);
 
         // /!\ this part must be slow due to the access in the ElementTypeMapArray<UInt>
         if(!elempproc.exists(type))
           elempproc.alloc(0, nb_nodes_per_element, type, _not_ghost);
 
         UInt global_connect[nb_nodes_per_element];
         UInt * local_connect = mesh.getConnectivity(type).storage() + elem->element * nb_nodes_per_element;
         for (UInt i = 0; i < nb_nodes_per_element; ++i) {
           global_connect[i] = mesh.getNodeGlobalId(local_connect[i]);
           AKANTU_DEBUG_ASSERT(global_connect[i] < mesh.getNbGlobalNodes(),
                               "This global node send in the connectivity does not seem correct "
                               << global_connect[i] << " corresponding to "
                               << local_connect[i] << " from element " << elem->element);
         }
 
         elempproc(type).push_back(global_connect);
         communicator.send_element[p].push_back(*elem);
       }
 
       delete to_send;
     }
 
     delete cell_ids;
   }
 
 
   delete [] first_cells;
   delete [] last_cells;
   delete [] bounding_boxes;
 
   AKANTU_DEBUG_INFO("I have finished to compute intersection,"
                     << " no it's time to communicate with my neighbors");
 
   /**
    * Sending loop, sends the connectivity asynchronously to all concerned proc
    */
   std::vector<CommunicationRequest *> isend_requests;
   for (UInt p = 0; p < nb_proc; ++p) {
     if(p == my_rank) continue;
     if(intersects_proc[p]) {
       ElementTypeMapArray<UInt> & elempproc = *(element_per_proc[p]);
 
       ElementTypeMapArray<UInt>::type_iterator it_type   = elempproc.firstType(_all_dimensions, _not_ghost);
       ElementTypeMapArray<UInt>::type_iterator last_type = elempproc.lastType (_all_dimensions, _not_ghost);
 
       UInt count = 0;
       for (; it_type != last_type; ++it_type) {
         Array<UInt> & conn = elempproc(*it_type, _not_ghost);
         UInt info[2];
         info[0] = (UInt) *it_type;
         info[1] = conn.getSize() * conn.getNbComponent();
 
         AKANTU_DEBUG_INFO("I have " << conn.getSize() << " elements of type " << *it_type
                           << " to send to processor " << p
                           << " (communication tag : " << Tag::genTag(my_rank, count, DATA_TAG) << ")");
 
         isend_requests.push_back(comm.asyncSend(info, 2, p, Tag::genTag(my_rank, count, SIZE_TAG)));
         if(info[1])
           isend_requests.push_back(comm.asyncSend<UInt>(conn.storage(),
                                                         info[1],
                                                         p, Tag::genTag(my_rank, count, DATA_TAG)));
 
         ++count;
       }
 
       UInt info[2];
       info[0] = (UInt) _not_defined;
       info[1] = 0;
       isend_requests.push_back(comm.asyncSend(info, 2, p, Tag::genTag(my_rank, count, SIZE_TAG)));
     }
   }
 
   /**
    * Receives the connectivity and store them in the ghosts elements
    */
   Array<UInt> & global_nodes_ids = const_cast<Array<UInt> &>(mesh.getGlobalNodesIds());
   Array<Int> & nodes_type = const_cast<Array<Int> &>(const_cast<const Mesh &>(mesh).getNodesType());
   std::vector<CommunicationRequest *> isend_nodes_requests;
   UInt nb_nodes_to_recv[nb_proc];
   UInt nb_total_nodes_to_recv = 0;
   UInt nb_current_nodes = global_nodes_ids.getSize();
 
   NewNodesEvent new_nodes;
   NewElementsEvent new_elements;
 
   Array<UInt> * ask_nodes_per_proc = new Array<UInt>[nb_proc];
 
   for (UInt p = 0; p < nb_proc; ++p) {
     nb_nodes_to_recv[p] = 0;
     if(p == my_rank) continue;
 
     Array<UInt> & ask_nodes = ask_nodes_per_proc[p];
     UInt count = 0;
     if(intersects_proc[p]) {
       ElementType type = _not_defined;
       do {
         UInt info[2] = { 0 };
         comm.receive(info, 2, p, Tag::genTag(p, count, SIZE_TAG));
 
         type = (ElementType) info[0];
         if(type != _not_defined) {
           UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type);;
           UInt nb_element = info[1] / nb_nodes_per_element;
 
           Array<UInt> tmp_conn(nb_element, nb_nodes_per_element);
           tmp_conn.clear();
           if(info[1])
             comm.receive<UInt>(tmp_conn.storage(), info[1], p, Tag::genTag(p, count, DATA_TAG));
 
           AKANTU_DEBUG_INFO("I will receive " << nb_element << " elements of type " << ElementType(info[0])
                           << " from processor " << p
                           << " (communication tag : " << Tag::genTag(p, count, DATA_TAG) << ")");
 
 
           Array<UInt> & ghost_connectivity = const_cast<Array<UInt> &>(mesh.getConnectivity(type, _ghost));
 
           UInt nb_ghost_element = ghost_connectivity.getSize();
           Element element(type, 0, _ghost);
 
           UInt conn[nb_nodes_per_element];
           for (UInt el = 0; el < nb_element; ++el) {
             UInt nb_node_to_ask_for_elem = 0;
 
             for (UInt n = 0; n < nb_nodes_per_element; ++n) {
               UInt gn = tmp_conn(el, n);
               UInt ln = global_nodes_ids.find(gn);
 
               AKANTU_DEBUG_ASSERT(gn < mesh.getNbGlobalNodes(), "This global node seems not correct " << gn << " from element " << el << " node " << n);
 
               if(ln == UInt(-1)) {
                 global_nodes_ids.push_back(gn);
 		nodes_type.push_back(-3); // pure ghost node
                 ln = nb_current_nodes;
 
 		new_nodes.getList().push_back(ln);
                 ++nb_current_nodes;
                 ask_nodes.push_back(gn);
                 ++nb_node_to_ask_for_elem;
               }
 
               conn[n] = ln;
             }
 
             // all the nodes are already known locally, the element should already exists
             UInt c = UInt(-1);
             if(nb_node_to_ask_for_elem == 0) {
               c = ghost_connectivity.find(conn);
 	      element.element = c;
             }
 
             if(c == UInt(-1)) {
               element.element = nb_ghost_element;
               ++nb_ghost_element;
               ghost_connectivity.push_back(conn);
 	      new_elements.getList().push_back(element);
             }
 
             communicator.recv_element[p].push_back(element);
           }
         }
         count++;
       } while(type != _not_defined);
 
       AKANTU_DEBUG_INFO("I have " << ask_nodes.getSize()
                         << " missing nodes for elements coming from processor " << p
                         << " (communication tag : " << Tag::genTag(my_rank, 0, ASK_NODES_TAG) << ")");
 
       isend_nodes_requests.push_back(comm.asyncSend(ask_nodes.storage(), ask_nodes.getSize(),
                                                      p, Tag::genTag(my_rank, 0, ASK_NODES_TAG)));
       nb_nodes_to_recv[p] = ask_nodes.getSize();
       nb_total_nodes_to_recv += ask_nodes.getSize();
     }
   }
 
   comm.waitAll(isend_requests);
   comm.freeCommunicationRequest(isend_requests);
 
   for (UInt p = 0; p < nb_proc; ++p) {
     if(element_per_proc[p]) delete element_per_proc[p];
   }
   delete [] element_per_proc;
 
   /**
    * Sends requested nodes to proc
    */
   Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes());
   UInt nb_nodes = nodes.getSize();
 
   std::vector<CommunicationRequest *> isend_coordinates_requests;
   Array<Real> * nodes_to_send_per_proc = new Array<Real>[nb_proc];
   for (UInt p = 0; p < nb_proc; ++p) {
     if(p == my_rank || !intersects_proc[p]) continue;
 
     Array<UInt> asked_nodes;
     CommunicationStatus status;
     AKANTU_DEBUG_INFO("Waiting list of nodes to send to processor " << p
                       << "(communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
 
     comm.probe<UInt>(p, Tag::genTag(p, 0, ASK_NODES_TAG), status);
     UInt nb_nodes_to_send = status.getSize();
     asked_nodes.resize(nb_nodes_to_send);
 
     AKANTU_DEBUG_INFO("I have " << nb_nodes_to_send
                       << " nodes to send to processor " << p
                       << " (communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
 
     AKANTU_DEBUG_INFO("Getting list of nodes to send to processor " << p
                       << " (communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
 
     comm.receive(asked_nodes.storage(), nb_nodes_to_send, p, Tag::genTag(p, 0, ASK_NODES_TAG));
 
     Array<Real> & nodes_to_send = nodes_to_send_per_proc[p];
     nodes_to_send.extendComponentsInterlaced(spatial_dimension, 1);
     for (UInt n = 0; n < nb_nodes_to_send; ++n) {
       UInt ln = global_nodes_ids.find(asked_nodes(n));
       AKANTU_DEBUG_ASSERT(ln != UInt(-1), "The node [" << asked_nodes(n) << "] requested by proc " << p << " was not found locally!");
       nodes_to_send.push_back(nodes.storage() + ln * spatial_dimension);
     }
 
     AKANTU_DEBUG_INFO("Sending the nodes to processor " << p
                       << " (communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
 
     isend_coordinates_requests.push_back(comm.asyncSend(nodes_to_send.storage(), nb_nodes_to_send * spatial_dimension, p, Tag::genTag(my_rank, 0, SEND_NODES_TAG)));
   }
 
   comm.waitAll(isend_nodes_requests);
   comm.freeCommunicationRequest(isend_nodes_requests);
   delete [] ask_nodes_per_proc;
 
   nodes.resize(nb_total_nodes_to_recv + nb_nodes);
   for (UInt p = 0; p < nb_proc; ++p) {
     if((p != my_rank) && (nb_nodes_to_recv[p] > 0)) {
       AKANTU_DEBUG_INFO("Receiving the nodes from processor " << p
 			<< " (communication tag : " << Tag::genTag(p, 0, ASK_NODES_TAG) << ")");
 
       comm.receive(nodes.storage() + nb_nodes * spatial_dimension,
 		   nb_nodes_to_recv[p] * spatial_dimension,
 		   p, Tag::genTag(p, 0, SEND_NODES_TAG));
       nb_nodes += nb_nodes_to_recv[p];
     }
   }
 
   comm.waitAll(isend_coordinates_requests);
   comm.freeCommunicationRequest(isend_coordinates_requests);
   delete [] nodes_to_send_per_proc;
 
+  synch_registry.registerSynchronizer(communicator, _gst_material_id);
+
   mesh.sendEvent(new_nodes);
   mesh.sendEvent(new_elements);
 
   delete [] intersects_proc;
 
   AKANTU_DEBUG_OUT();
   return &communicator;
 }
 
 /* -------------------------------------------------------------------------- */
 template GridSynchronizer *
 GridSynchronizer::createGridSynchronizer<QuadraturePoint>(Mesh & mesh,
                                                           const SpatialGrid<QuadraturePoint> & grid,
+							  SynchronizerRegistry & synch_registry,
                                                           SynchronizerID id,
                                                           MemoryID memory_id);
 template GridSynchronizer *
 GridSynchronizer::createGridSynchronizer<Element>(Mesh & mesh,
                                                   const SpatialGrid<Element> & grid,
+						  SynchronizerRegistry & synch_registry,
                                                   SynchronizerID id,
                                                   MemoryID memory_id);
 
 __END_AKANTU__
diff --git a/src/synchronizer/grid_synchronizer.hh b/src/synchronizer/grid_synchronizer.hh
index 8f381fd2d..d1062f18f 100644
--- a/src/synchronizer/grid_synchronizer.hh
+++ b/src/synchronizer/grid_synchronizer.hh
@@ -1,92 +1,94 @@
 /**
  * @file   grid_synchronizer.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Mon Oct 03 2011
  * @date last modification: Thu Feb 21 2013
  *
  * @brief  synchronizer based in RegularGrid
  *
  * @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 "distributed_synchronizer.hh"
+#include "synchronizer_registry.hh"
 
 /* -------------------------------------------------------------------------- */
 
 
 #ifndef __AKANTU_GRID_SYNCHRONIZER_HH__
 #define __AKANTU_GRID_SYNCHRONIZER_HH__
 
 __BEGIN_AKANTU__
 
 class Mesh;
 template<class T>
 class SpatialGrid;
 
 class GridSynchronizer : public DistributedSynchronizer {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 protected:
   GridSynchronizer(Mesh & mesh, const ID & id = "grid_synchronizer", MemoryID memory_id = 0);
 
 public:
   virtual ~GridSynchronizer() { };
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   template <class E>
   static GridSynchronizer *
   createGridSynchronizer(Mesh & mesh,
 			 const SpatialGrid<E> & grid,
+			 SynchronizerRegistry & synch_registry,
 			 SynchronizerID id = "grid_synchronizer",
 			 MemoryID memory_id = 0);
 
 
 protected:
   enum CommTags {
     SIZE_TAG        = 0,
     DATA_TAG        = 1,
     ASK_NODES_TAG   = 2,
     SEND_NODES_TAG  = 3
   };
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
 
 };
 
 
 __END_AKANTU__
 
 #endif /* __AKANTU_GRID_SYNCHRONIZER_HH__ */
diff --git a/test/test_model/test_solid_mechanics_model/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/CMakeLists.txt
index 8a3aca11e..cfc6762bb 100644
--- a/test/test_model/test_solid_mechanics_model/CMakeLists.txt
+++ b/test/test_model/test_solid_mechanics_model/CMakeLists.txt
@@ -1,214 +1,214 @@
 #===============================================================================
 # @file   CMakeLists.txt
 #
 # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
 #
 # @date creation: Fri Sep 03 2010
 # @date last modification: Thu Mar 27 2014
 #
 # @brief  configuratio for SolidMechanicsModel 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_akantu_test(test_materials "test_materials")
 add_akantu_test(patch_tests "patch_tests")
 add_akantu_test(test_cohesive "cohesive_test")
 
 #===============================================================================
 add_mesh(test_solid_mechanics_model_square_mesh square.geo 2 1)
 add_mesh(test_solid_mechanics_model_circle_mesh1 circle.geo 2 1 OUTPUT circle1.msh)
 add_mesh(test_solid_mechanics_model_circle_mesh2 circle.geo 2 2 OUTPUT circle2.msh)
 
 register_test(test_solid_mechanics_model_square
   SOURCES test_solid_mechanics_model_square.cc
   DEPENDENCIES test_solid_mechanics_model_square_mesh
   FILES_TO_COPY material.dat test_cst_energy.pl
   DIRECTORIES_TO_CREATE paraview
   PACKAGE core
   )
 
 register_test(test_solid_mechanics_model_circle_2
   SOURCES test_solid_mechanics_model_circle_2.cc
   DEPENDENCIES test_solid_mechanics_model_circle_mesh2
   FILES_TO_COPY material.dat
   DIRECTORIES_TO_CREATE paraview
   PACKAGE core
   )
 
 #===============================================================================
 add_mesh(test_bar_traction_2d_mesh1 bar.geo 2 1 OUTPUT bar1.msh)
 add_mesh(test_bar_traction_2d_mesh2 bar.geo 2 2 OUTPUT bar2.msh)
 add_mesh(test_bar_traction_2d_mesh_structured1 bar_structured.geo 2 1 OUTPUT bar_structured1.msh)
 
 register_test(test_solid_mechanics_model_bar_traction2d
   SOURCES test_solid_mechanics_model_bar_traction2d.cc
   DEPENDENCIES test_bar_traction_2d_mesh1 test_bar_traction_2d_mesh2
   FILES_TO_COPY material.dat test_cst_energy.pl
   DIRECTORIES_TO_CREATE paraview
   PACKAGE core
   )
 
 register_test(test_solid_mechanics_model_bar_traction2d_structured
   SOURCES test_solid_mechanics_model_bar_traction2d_structured.cc
   DEPENDENCIES test_bar_traction_2d_mesh_structured1
   FILES_TO_COPY material.dat test_cst_energy.pl
   DIRECTORIES_TO_CREATE paraview
   PACKAGE core
   )
 
 #===============================================================================
 add_mesh(test_solid_mechanics_model_segment_mesh segment.geo 1 2)
 
 register_test(test_solid_mechanics_model_bar_traction2d_parallel
   SOURCES test_solid_mechanics_model_bar_traction2d_parallel.cc
   DEPENDENCIES test_bar_traction_2d_mesh2
   FILES_TO_COPY material.dat test_cst_energy.pl
   DIRECTORIES_TO_CREATE paraview
   PACKAGE parallel
   )
 
 register_test(test_solid_mechanics_model_segment_parallel
   SOURCES test_solid_mechanics_model_segment_parallel.cc
   DEPENDENCIES test_solid_mechanics_model_segment_mesh
   FILES_TO_COPY material.dat test_cst_energy.pl
   DIRECTORIES_TO_CREATE paraview
   PACKAGE parallel
   )
 
 
 #===============================================================================
 #register_test(test_solid_mechanics_model_bar_traction2d_mass_not_lumped
 #  SOURCES test_solid_mechanics_model_bar_traction2d_mass_not_lumped.cc
 #  DEPENDENCIES test_bar_traction_2d_mesh1 test_bar_traction_2d_mesh2
 #  FILES_TO_COPY material.dat
 #  DIRECTORIES_TO_CREATE paraview
 #  PACKAGE implicit
 #  )
 
 #===============================================================================
 add_mesh(test_solid_mechanics_model_segment_mesh1 segment.geo 1 1 OUTPUT segment1.msh)
 add_mesh(test_implicit_mesh1 square_implicit.geo 2 1 OUTPUT square_implicit1.msh)
 add_mesh(test_implicit_mesh2 square_implicit.geo 2 2 OUTPUT square_implicit2.msh)
 
 register_test(test_solid_mechanics_model_implicit_1d
   SOURCES test_solid_mechanics_model_implicit_1d.cc
   DEPENDENCIES test_solid_mechanics_model_segment_mesh1
   FILES_TO_COPY material.dat
   DIRECTORIES_TO_CREATE paraview
   PACKAGE implicit
   )
 
 register_test(test_solid_mechanics_model_implicit_2d
   SOURCES test_solid_mechanics_model_implicit_2d.cc
   DEPENDENCIES test_implicit_mesh1 test_implicit_mesh2
   FILES_TO_COPY material.dat
   DIRECTORIES_TO_CREATE paraview
   PACKAGE implicit
   )
 
 #===============================================================================
 add_mesh(test_implicit_beam_2d_1 beam_2d.geo 2 1 OUTPUT beam_2d_lin.msh)
 add_mesh(test_implicit_beam_2d_2 beam_2d.geo 2 2 OUTPUT beam_2d_quad.msh)
 add_mesh(test_implicit_beam_3d_2 beam_3d.geo 3 2 OUTPUT beam_3d_quad.msh)
 add_mesh(test_implicit_beam_3d_1 beam_3d.geo 3 1 OUTPUT beam_3d_lin.msh)
 register_test(test_solid_mechanics_model_implicit_dynamic_2d
   SOURCES test_solid_mechanics_model_implicit_dynamic_2d.cc
   DEPENDENCIES test_implicit_beam_2d_1 test_implicit_beam_2d_2 test_implicit_beam_3d_2 test_implicit_beam_3d_1
   FILES_TO_COPY  material_implicit_dynamic.dat
   DIRECTORIES_TO_CREATE paraview
   PACKAGE implicit
   )
 
 #===============================================================================
 add_mesh(test_pbc_parallel_mesh square_structured.geo 2 1 OUTPUT square_structured.msh)
 
 register_test(test_solid_mechanics_model_bar_traction2d_structured_pbc
   SOURCES test_solid_mechanics_model_bar_traction2d_structured_pbc.cc
   DEPENDENCIES test_bar_traction_2d_mesh_structured1
   FILES_TO_COPY material.dat test_cst_energy.pl
   DIRECTORIES_TO_CREATE paraview
   PACKAGE core
   )
 
 #register_test(test_solid_mechanics_model_pbc_parallel
 #  SOURCES  test_solid_mechanics_model_pbc_parallel.cc
 #  DEPENDENCIES test_pbc_parallel_mesh
 #  FILES_TO_COPY  material.dat
 #  DIRECTORIES_TO_CREATE paraview
 #  PACKAGE parallel
 #  )
 
 
 #===============================================================================
 add_mesh(test_cube3d_mesh1 cube.geo 3 1 OUTPUT cube1.msh)
 add_mesh(test_cube3d_mesh2 cube.geo 3 2 OUTPUT cube2.msh)
 add_mesh(test_cube3d_mesh_structured cube_structured.geo 3 1 OUTPUT cube_structured.msh)
 
 register_test(test_solid_mechanics_model_cube3d
   SOURCES test_solid_mechanics_model_cube3d.cc
   DEPENDENCIES test_cube3d_mesh1
   FILES_TO_COPY  material.dat
   DIRECTORIES_TO_CREATE paraview
   PACKAGE core
   )
 
 register_test(test_solid_mechanics_model_cube3d_tetra10
   SOURCES test_solid_mechanics_model_cube3d_tetra10.cc
   DEPENDENCIES test_cube3d_mesh2
   FILES_TO_COPY  material.dat
   DIRECTORIES_TO_CREATE paraview
   PACKAGE core
   )
 
 register_test(test_solid_mechanics_model_cube3d_pbc
   SOURCES test_solid_mechanics_model_cube3d_pbc.cc
   DEPENDENCIES test_cube3d_mesh_structured
   FILES_TO_COPY  material.dat
   DIRECTORIES_TO_CREATE paraview
   PACKAGE core
   )
 
 #add_mesh(test_solid_mechanics_model_boundary_condition_mesh cube_physical_names.geo 3 1)
 
 register_test(test_solid_mechanics_model_boundary_condition
   SOURCES test_solid_mechanics_model_boundary_condition.cc
   FILES_TO_COPY material.dat cube_physical_names.msh
   PACKAGE core
   )
 
 #===============================================================================
 add_mesh(test_cube3d_two_mat_mesh cube_two_materials.geo 3 1)
 
 register_test(test_solid_mechanics_model_reassign_material
   SOURCES test_solid_mechanics_model_reassign_material.cc
   DEPENDENCIES test_cube3d_two_mat_mesh
   FILES_TO_COPY two_materials.dat
-  PACKAGE scotch
+  PACKAGE implicit
   )
 
 #===============================================================================
 register_test(test_solid_mechanics_model_material_eigenstrain
   SOURCES test_solid_mechanics_model_material_eigenstrain.cc
   FILES_TO_COPY cube_3d_tet_4.msh; material_elastic_plane_strain.dat
   PACKAGE core
   )
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/CMakeLists.txt
index c7b02c9a6..3b120af1d 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/CMakeLists.txt
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/CMakeLists.txt
@@ -1,41 +1,51 @@
 #===============================================================================
 # @file   CMakeLists.txt
 #
 # @author Nicolas Richart <nicolas.richart@epfl.ch>
 #
 # @date creation: Mon Jan 20 2014
 # @date last modification: Mon Jan 20 2014
 #
 # @brief  configuration for materials tests
 #
 # @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/>.
 #
 # @section DESCRIPTION
 #
 #===============================================================================
 
 add_mesh(test_material_non_local_mesh mesh.geo 2 2 OUTPUT mesh.msh)
+add_mesh(test_two_materials_mesh two_materials.geo 2 1 OUTPUT two_materials.msh)
+
 register_test(test_material_damage_non_local
   SOURCES test_material_damage_non_local.cc
   DEPENDENCIES test_material_non_local_mesh
   FILES_TO_COPY material_damage_non_local.dat
   DIRECTORIES_TO_CREATE paraview
   PACKAGE damage_non_local
   )
 
+register_test(test_material_damage_non_local_two_materials
+  SOURCES test_material_damage_non_local_two_materials.cc
+  DEPENDENCIES test_two_materials_mesh
+  FILES_TO_COPY two_materials_non_local.dat
+  DIRECTORIES_TO_CREATE paraview
+  PACKAGE damage_non_local
+  )
+
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_damage_non_local_two_materials.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_damage_non_local_two_materials.cc
new file mode 100644
index 000000000..131d03d3b
--- /dev/null
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_damage_non_local_two_materials.cc
@@ -0,0 +1,156 @@
+/**
+ * @file   test_material_damage_non_local_two_materials.cc
+ * @author Aurelia Cuba Ramos <aurelia.cubaramos@epfl.ch>
+ * @date   Fri Feb 20 15:30:27 2015
+ *
+ * @brief  test to check if two non-local materials can be used together
+ *
+ * @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 <iostream>
+/* -------------------------------------------------------------------------- */
+#include "aka_common.hh"
+#include "mesh.hh"
+#include "mesh_io.hh"
+#include "solid_mechanics_model.hh"
+#include "material.hh"
+/* -------------------------------------------------------------------------- */
+
+using namespace akantu;
+
+int main(int argc, char *argv[]) {
+  initialize("two_materials_non_local.dat", argc, argv);
+  debug::setDebugLevel(akantu::dblWarning);
+
+  const UInt spatial_dimension = 2;
+  Mesh mesh(spatial_dimension);
+  akantu::MeshPartition * partition = NULL;
+
+  StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator();
+  Int psize = comm.getNbProc();
+  Int prank = comm.whoAmI();
+
+  if(prank == 0) {
+
+    mesh.read("two_materials.msh");
+
+    /// partition the mesh
+    partition = new MeshPartitionScotch(mesh, spatial_dimension);
+
+    partition->partitionate(psize);
+  }
+
+  SolidMechanicsModel model(mesh);
+  model.initParallel(partition);
+  delete partition;
+
+  model.setBaseName("damage_in_ASR_sample");
+  model.addDumpField("partitions");
+
+  model.dump();
+  /// assign the materials
+  MeshDataMaterialSelector<UInt> * mat_selector;
+  mat_selector = new MeshDataMaterialSelector<UInt>("tag_0", model, 1);
+
+  model.setMaterialSelector(*mat_selector);
+  model.initFull(SolidMechanicsModelOptions(_static));
+
+  /// displaying the material data
+  if (prank == 0) {
+    for (UInt m = 0; m  < model.getNbMaterials(); ++m)
+      std::cout << model.getMaterial(m) << std::endl;
+  }
+
+
+  //  model.getFEEngine().getMesh().initElementTypeMapArray(quadrature_points_volumes, 1, 0);
+  // const MaterialNonLocal<spatial_dimension, BaseWeightFunction> & mat =
+  //   dynamic_cast<const MaterialNonLocal<spatial_dimension, BaseWeightFunction> &>(model.getMaterial(0));
+  // //  mat.computeQuadraturePointsNeighborhoudVolumes(quadrature_points_volumes);
+  // Real radius = mat.getRadius();
+
+  // UInt nb_element  = mesh.getNbElement(TYPE);
+  // UInt nb_tot_quad = model.getFEEngine().getNbQuadraturePoints(TYPE) * nb_element;
+
+  // std::cout << mat << std::endl;
+
+  // Array<Real> quads(0, spatial_dimension);
+  // quads.resize(nb_tot_quad);
+
+  // model.getFEEngine().interpolateOnQuadraturePoints(mesh.getNodes(),
+  // 					       quads, spatial_dimension,
+  // 					       TYPE);
+
+  // Array<Real>::iterator< Vector<Real> > first_quad_1 = quads.begin(spatial_dimension);
+  // Array<Real>::iterator< Vector<Real> > last_quad_1 = quads.end(spatial_dimension);
+
+  // std::ofstream pout;
+  // pout.open("bf_pairs");
+  // UInt q1 = 0;
+
+  // Real R = mat.getRadius();
+
+  // for(;first_quad_1 != last_quad_1; ++first_quad_1, ++q1) {
+  //   Array<Real>::iterator< Vector<Real> > first_quad_2 = quads.begin(spatial_dimension);
+  //   //Array<Real>::iterator< Vector<Real> > last_quad_2 = quads.end(spatial_dimension);
+  //   UInt q2 = 0;
+  //   for(;first_quad_2 != last_quad_1; ++first_quad_2, ++q2) {
+  //     Real d = first_quad_2->distance(*first_quad_1);
+  //     if(d <= radius) {
+  // 	Real alpha = (1 - d*d/(R*R));
+  // 	alpha = alpha*alpha;
+  // 	pout << q1 << " " << q2 << " " << alpha << std::endl;
+  //     }
+  //   }
+  // }
+  // pout.close();
+
+  // mat.savePairs("cl_pairs");
+
+  // ElementTypeMapArray<Real> constant("constant_value", "test");
+  // mesh.initElementTypeMapArray(constant, 1, 0);
+  // Mesh::type_iterator it = mesh.firstType(spatial_dimension);
+  // Mesh::type_iterator last_type = mesh.lastType(spatial_dimension);
+  // for(; it != last_type; ++it) {
+  //   UInt nb_quadrature_points = model.getFEEngine().getNbQuadraturePoints(*it);
+  //   UInt _nb_element = mesh.getNbElement(*it);
+
+  //   Array<Real> & constant_vect = constant(*it);
+  //   constant_vect.resize(_nb_element * nb_quadrature_points);
+
+  //   std::fill_n(constant_vect.storage(), nb_quadrature_points * _nb_element, 1.);
+  // }
+
+  // ElementTypeMapArray<Real> constant_avg("constant_value_avg", "test");
+  // mesh.initElementTypeMapArray(constant_avg, 1, 0);
+
+  // mat.weightedAvergageOnNeighbours(constant, constant_avg, 1);
+
+  // debug::setDebugLevel(akantu::dblTest);
+  // std::cout << constant(TYPE) << std::endl;
+  // std::cout << constant_avg(TYPE) << std::endl;
+  // debug::setDebugLevel(akantu::dblWarning);
+
+  finalize();
+
+  return EXIT_SUCCESS;
+}
+
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/two_materials.geo b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/two_materials.geo
new file mode 100644
index 000000000..c9f459f12
--- /dev/null
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/two_materials.geo
@@ -0,0 +1,49 @@
+// Mesh size
+h  = 0.25;    // Top cube
+
+// Dimensions of top cube
+Lx = 1;
+Ly = 1;
+
+
+// ------------------------------------------
+// Geometry
+// ------------------------------------------
+
+// Base Cube
+Point(101) = { 0.0, 0.0, 0.0, h}; // Bottom Face
+Point(102) = { Lx/4, 0.0, 0.0, h};
+Point(103) = { Lx,  0.0, 0.0, h}; // Bottom Face
+Point(104) = { Lx,  Ly, 0.0,  h}; // Bottom Face
+Point(105) = { Lx/4, Ly, 0.0, h};
+Point(106) = { 0.0, Ly, 0.0,  h}; // Bottom Face
+
+// Base Cube
+Line(101) = {101,102}; // Bottom Face
+Line(102) = {102,105}; // Bottom Face
+Line(103) = {105,106}; // Bottom Face
+Line(104) = {106,101}; // Bottom Face
+
+Line(105) = {102,103}; // Bottom Face
+Line(106) = {103,104}; // Bottom Face
+Line(107) = {104,105}; // Bottom Face
+// Line(108) = {105,102}; // Bottom Face
+// 
+// // Base Cube
+// Line Loop(101) = {101:104};
+// Line Loop(102) = {105:108};
+// 
+// Plane Surface(101) = {101};
+// Plane Surface(102) = {102};
+// Physical Surface(1) = {101};
+// Physical Surface(2) = {102};
+
+Line Loop(108) = {105, 106, 107, -102};
+Plane Surface(209) = {108};
+Line Loop(110) = {101, 102, 103, 104};
+Plane Surface(210) = {110};
+
+Physical Surface(1) = {209};
+Physical Surface(2) = {210};
+
+Transfinite Surface "*";
diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/two_materials_non_local.dat b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/two_materials_non_local.dat
new file mode 100644
index 000000000..fc50cb6a5
--- /dev/null
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/two_materials_non_local.dat
@@ -0,0 +1,21 @@
+seed = 1
+
+material elastic [
+	 name = aggregate
+	 rho = 2.7e-9   # density
+	 E   = 60e9 # young's modulus
+	 nu  = 0.3    # poisson's ratio
+]
+
+material damage_iterative_non_local base_wf [
+	 name = mortar
+	 rho = 2.2e-9   # density
+	 E   = 12e9 # young's modulus
+	 nu  = 0.3    # poisson's ratio
+	 Sc = 9.6e6 weibull [2.4e6, 5.]
+	 prescribed_dam = 0.1
+	 max_damage = 0.95
+	 non_local weight_function [
+	 	   radius = 1.0
+	 ]	    
+]
\ No newline at end of file
diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc
index 3af8a370c..02480414b 100644
--- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc
+++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc
@@ -1,217 +1,217 @@
 /**
  * @file   test_solid_mechanics_model_reassign_material.cc
  *
  * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
  *
  * @date creation: Mon Feb 10 2014
  * @date last modification: Thu Jun 05 2014
  *
  * @brief  test the function reassign 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 "static_communicator.hh"
 #include "solid_mechanics_model.hh"
 #include "material.hh"
 #include "aka_grid_dynamic.hh"
 using namespace akantu;
 
 
 class StraightInterfaceMaterialSelector : public MaterialSelector {
 public:
   StraightInterfaceMaterialSelector(SolidMechanicsModel & model,
 				    const std::string & mat_1_material,
 				    const std::string & mat_2_material,
 				    bool & horizontal,
 				    Real & pos_interface) :
     model(model),
     mat_1_material(mat_1_material),
     mat_2_material(mat_2_material), 
     horizontal(horizontal), 
     pos_interface(pos_interface) {
     Mesh & mesh = model.getMesh();
     UInt spatial_dimension = mesh.getSpatialDimension();
 
     /// store barycenters of all elements
     mesh.initElementTypeMapArray(barycenters, spatial_dimension, spatial_dimension);
 
     for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) {
       GhostType ghost_type = *gt;
       Element e;
       e.ghost_type = ghost_type;
 
       Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
       Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type);
       for(; it != last_type; ++it) {
 	UInt nb_element = mesh.getNbElement(*it, ghost_type);
 	e.type = *it;
 	Array<Real> & barycenter = barycenters(*it, ghost_type);
 	barycenter.resize(nb_element);
 
 	Array<Real>::iterator< Vector<Real> > bary_it = barycenter.begin(spatial_dimension);
 	for (UInt elem = 0; elem < nb_element; ++elem) {
 	  e.element = elem;
 	  mesh.getBarycenter(e, *bary_it);
 	  ++bary_it;
 	}
       }
     }
   }
 
   UInt operator()(const Element & elem) {
     UInt spatial_dimension = model.getSpatialDimension();
     const Vector<Real> & bary = barycenters(elem.type, elem.ghost_type).begin(spatial_dimension)[elem.element];
  
     /// check for a given element on which side of the material interface plane the bary center lies and assign corresponding material
     if (bary(!horizontal) < pos_interface) {
       return model.getMaterialIndex(mat_1_material);;
     }
     return model.getMaterialIndex(mat_2_material);;
    
   }
   
   bool isConditonVerified() {
 
     /// check if material has been (re)-assigned correctly
     Mesh & mesh = model.getMesh();
     UInt spatial_dimension = mesh.getSpatialDimension();
     GhostType ghost_type = _not_ghost;
 
     Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
     Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type);
     for(; it != last_type; ++it) {
-      Array<UInt> & el_idx_by_mat = model.getElementIndexByMaterial(*it, ghost_type);
+      Array<UInt> & mat_indexes = model.getMaterialByElement(*it, ghost_type);
       UInt nb_element = mesh.getNbElement(*it, ghost_type);
       Array<Real>::iterator<Vector<Real> > bary = barycenters(*it, ghost_type).begin(spatial_dimension);
       for (UInt elem = 0; elem < nb_element; ++elem, ++bary) {
 	/// compare element_index_by material to material index that should be assigned due to the geometry of the interface
   	UInt mat_index;
   	if ((*bary)(!horizontal) < pos_interface)
   	  mat_index = model.getMaterialIndex(mat_1_material);
   	else
   	  mat_index = model.getMaterialIndex(mat_2_material);
 
-  	if (el_idx_by_mat(elem,0) != mat_index)
+  	if (mat_indexes(elem) != mat_index)
 	  /// wrong material index, make test fail
   	  return false;
 
 
       }
     }
     return true;
   }
 
   void moveInterface(Real & pos_new, bool & horizontal_new) {
     /// update position and orientation of material interface plane
     pos_interface = pos_new;
     horizontal = horizontal_new;
     model.reassignMaterial();
   }
 
 protected:
   SolidMechanicsModel & model;
   ElementTypeMapArray<Real> barycenters;
   std::string mat_1_material;
   std::string mat_2_material;
   bool horizontal;
   Real pos_interface;
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* Main                                                                       */
 /* -------------------------------------------------------------------------- */
 int main(int argc, char *argv[]) {
 
   bool test_passed;
 
   debug::setDebugLevel(dblWarning);
   initialize("two_materials.dat", argc, argv);
 
   /// specify position and orientation of material interface plane
   bool horizontal = true;
   Real pos_interface = 0.;
 
   UInt spatial_dimension = 3;
 
   akantu::StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator();
   akantu::Int psize = comm.getNbProc();
   akantu::Int prank = comm.whoAmI();
 
   Mesh mesh(spatial_dimension);
 
   akantu::MeshPartition * partition = NULL;
   if(prank == 0) {
     /// creation mesh
     mesh.read("cube_two_materials.msh");
 
     partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension);
     partition->partitionate(psize);
   }
 
   /// model creation
   SolidMechanicsModel model(mesh);
   model.initParallel(partition);
   delete partition;
 
   /// assign the two different materials using the StraightInterfaceMaterialSelector
   StraightInterfaceMaterialSelector * mat_selector;
   mat_selector = new StraightInterfaceMaterialSelector(model, "mat_1", "mat_2", horizontal, pos_interface);
 
   model.setMaterialSelector(*mat_selector);
   model.initFull(SolidMechanicsModelOptions(_static));
   MeshUtils::buildFacets(mesh);
   // model.setBaseName("test_reassign_material");
   // model.addDumpField("element_index_by_material");
   // model.addDumpField("partitions");
   // model.dump();
 
   /// check if different materials have been assigned correctly
   test_passed = mat_selector->isConditonVerified();
   if (!test_passed) {
     AKANTU_DEBUG_ERROR("materials not correctly assigned");
     return EXIT_FAILURE;
   }
 
   /// change orientation of material interface plane
   horizontal = false;
   mat_selector->moveInterface(pos_interface, horizontal);
 
   // model.dump();
 
   /// test if material has been reassigned correctly
   test_passed = mat_selector->isConditonVerified();
   if (!test_passed) {
     AKANTU_DEBUG_ERROR("materials not correctly reassigned");
     return EXIT_FAILURE;
   }
 
   finalize();
 
   if(prank == 0)
     std::cout << "OK: test passed!" << std::endl;
   
   return EXIT_SUCCESS;
 }
 
 /* -------------------------------------------------------------------------- */
 
diff --git a/test/test_synchronizer/test_grid_synchronizer.cc b/test/test_synchronizer/test_grid_synchronizer.cc
index 8807881d1..f5e47b010 100644
--- a/test/test_synchronizer/test_grid_synchronizer.cc
+++ b/test/test_synchronizer/test_grid_synchronizer.cc
@@ -1,296 +1,297 @@
 /**
  * @file   test_grid_synchronizer.cc
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Nov 25 2011
  * @date last modification: Tue Jun 24 2014
  *
  * @brief  test the GridSynchronizer object
  *
  * @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_grid_dynamic.hh"
 #include "mesh.hh"
 #include "grid_synchronizer.hh"
 #include "mesh_partition.hh"
 #include "synchronizer_registry.hh"
 #include "test_data_accessor.hh"
 #ifdef AKANTU_USE_IOHELPER
 #  include "io_helper.hh"
 #endif //AKANTU_USE_IOHELPER
 
 using namespace akantu;
 
 const UInt spatial_dimension = 3;
 
 typedef std::map<std::pair<Element, Element>, Real> pair_list;
 
 #include "test_grid_tools.hh"
 
 static void updatePairList(const ElementTypeMapArray<Real> & barycenter,
                              const SpatialGrid<Element> & grid,
                              Real radius,
                              pair_list & neighbors,
                              neighbors_map_t<spatial_dimension>::type & neighbors_map) {
   AKANTU_DEBUG_IN();
 
   GhostType ghost_type = _not_ghost;
 
   Element e;
   e.ghost_type = ghost_type;
 
   // generate the pair of neighbor depending of the cell_list
   ElementTypeMapArray<Real>::type_iterator it        = barycenter.firstType(_all_dimensions, ghost_type);
   ElementTypeMapArray<Real>::type_iterator last_type = barycenter.lastType(0, ghost_type);
   for(; it != last_type; ++it) {
     // loop over quad points
 
     e.type = *it;
     e.element = 0;
 
     const Array<Real> & barycenter_vect = barycenter(*it, ghost_type);
     UInt sp = barycenter_vect.getNbComponent();
 
     Array<Real>::const_iterator< Vector<Real> > bary =
       barycenter_vect.begin(sp);
     Array<Real>::const_iterator< Vector<Real> > bary_end =
       barycenter_vect.end(sp);
 
     for(;bary != bary_end; ++bary, e.element++) {
 #if !defined(AKANTU_NDEBUG)
       Point<spatial_dimension> pt1(*bary);
 #endif
 
       SpatialGrid<Element>::CellID cell_id = grid.getCellID(*bary);
       SpatialGrid<Element>::neighbor_cells_iterator first_neigh_cell =
         grid.beginNeighborCells(cell_id);
       SpatialGrid<Element>::neighbor_cells_iterator last_neigh_cell =
         grid.endNeighborCells(cell_id);
 
       // loop over neighbors cells of the one containing the current element
       for (; first_neigh_cell != last_neigh_cell; ++first_neigh_cell) {
         SpatialGrid<Element>::Cell::const_iterator first_neigh_el =
           grid.beginCell(*first_neigh_cell);
         SpatialGrid<Element>::Cell::const_iterator last_neigh_el =
           grid.endCell(*first_neigh_cell);
 
         // loop over the quadrature point in the current cell of the cell list
         for (;first_neigh_el != last_neigh_el; ++first_neigh_el){
           const Element & elem = *first_neigh_el;
 
 	  Array<Real>::const_iterator< Vector<Real> > neigh_it =
 	    barycenter(elem.type, elem.ghost_type).begin(sp);
 
 	  const Vector<Real> & neigh_bary = neigh_it[elem.element];
 
           Real distance = bary->distance(neigh_bary);
           if(distance <= radius) {
 #if !defined(AKANTU_NDEBUG)
             Point<spatial_dimension> pt2(neigh_bary);
             neighbors_map[pt1].push_back(pt2);
 #endif
             std::pair<Element, Element> pair = std::make_pair(e, elem);
             pair_list::iterator p = neighbors.find(pair);
             if(p != neighbors.end()) {
               AKANTU_DEBUG_ERROR("Pair already registered [" << e << " " << elem << "] -> " << p->second << " " << distance);
             } else {
               neighbors[pair] = distance;
             }
           }
         }
       }
     }
   }
   AKANTU_DEBUG_OUT();
 }
 
 
 /* -------------------------------------------------------------------------- */
 /* Main                                                                       */
 /* -------------------------------------------------------------------------- */
 int main(int argc, char *argv[]) {
   akantu::initialize(argc, argv);
 
   Real radius = 0.2;
 
   Mesh mesh(spatial_dimension);
 
   StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator();
   Int psize = comm.getNbProc();
   Int prank = comm.whoAmI();
   DistributedSynchronizer * dist = NULL;
 
   if(prank == 0) {
     mesh.read("bar3d.msh");
     MeshPartition * partition = new MeshPartitionScotch(mesh, spatial_dimension);
     partition->partitionate(psize);
     dist = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, partition);
     delete partition;
   } else {
     dist = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, NULL);
   }
 
   mesh.computeBoundingBox();
 
   const Vector<Real> & lower_bounds = mesh.getLowerBounds();
   const Vector<Real> & upper_bounds = mesh.getUpperBounds();
 
   Vector<Real> center = 0.5 * (upper_bounds + lower_bounds);
 
   Vector<Real> spacing(spatial_dimension);
   for (UInt i = 0; i < spatial_dimension; ++i) {
     spacing[i] = radius * 1.2;
   }
 
   SpatialGrid<Element> grid(spatial_dimension, spacing, center);
 
   GhostType ghost_type = _not_ghost;
 
   Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type);
   Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type);
 
   ElementTypeMapArray<Real> barycenters("", "");
   mesh.initElementTypeMapArray(barycenters, spatial_dimension, spatial_dimension);
 
   Element e;
   e.ghost_type = ghost_type;
 
   for(; it != last_type; ++it) {
     UInt nb_element = mesh.getNbElement(*it, ghost_type);
     e.type = *it;
     Array<Real> & barycenter = barycenters(*it, ghost_type);
     barycenter.resize(nb_element);
 
     Array<Real>::iterator< Vector<Real> > bary_it = barycenter.begin(spatial_dimension);
     for (UInt elem = 0; elem < nb_element; ++elem) {
       mesh.getBarycenter(elem, *it, bary_it->storage(), ghost_type);
       e.element = elem;
       grid.insert(e, *bary_it);
       ++bary_it;
     }
   }
 
   std::stringstream sstr; sstr << "mesh_" << prank << ".msh";
   mesh.write(sstr.str());
 
   Mesh grid_mesh(spatial_dimension, "grid_mesh", 0);
   std::stringstream sstr_grid; sstr_grid << "grid_mesh_" << prank << ".msh";
   grid.saveAsMesh(grid_mesh);
   grid_mesh.write(sstr_grid.str());
 
 
 
   std::cout << "Pouet 1" << std::endl;
 
-  GridSynchronizer * grid_communicator = GridSynchronizer::createGridSynchronizer(mesh, grid);
+  AKANTU_DEBUG_INFO("Creating TestAccessor");
+  TestAccessor test_accessor(mesh, barycenters);
+  SynchronizerRegistry synch_registry(test_accessor);
+
+  GridSynchronizer * grid_communicator = GridSynchronizer::createGridSynchronizer(mesh, grid, synch_registry);
 
   std::cout << "Pouet 2" << std::endl;
 
   ghost_type = _ghost;
 
   it = mesh.firstType(spatial_dimension, ghost_type);
   last_type = mesh.lastType(spatial_dimension, ghost_type);
   e.ghost_type = ghost_type;
   for(; it != last_type; ++it) {
     UInt nb_element = mesh.getNbElement(*it, ghost_type);
     e.type = *it;
     Array<Real> & barycenter = barycenters(*it, ghost_type);
     barycenter.resize(nb_element);
 
     Array<Real>::iterator< Vector<Real> > bary_it = barycenter.begin(spatial_dimension);
     for (UInt elem = 0; elem < nb_element; ++elem) {
       mesh.getBarycenter(elem, *it, bary_it->storage(), ghost_type);
       e.element = elem;
       grid.insert(e, *bary_it);
       ++bary_it;
     }
   }
 
   Mesh grid_mesh_ghost(spatial_dimension, "grid_mesh_ghost", 0);
   std::stringstream sstr_gridg; sstr_gridg << "grid_mesh_ghost_" << prank << ".msh";
   grid.saveAsMesh(grid_mesh_ghost);
   grid_mesh_ghost.write(sstr_gridg.str());
 
   std::cout << "Pouet 3" << std::endl;
 
 
   neighbors_map_t<spatial_dimension>::type neighbors_map;
   pair_list neighbors;
 
   updatePairList(barycenters, grid, radius, neighbors, neighbors_map);
   pair_list::iterator nit  = neighbors.begin();
   pair_list::iterator nend = neighbors.end();
 
   std::stringstream sstrp; sstrp << "pairs_" << prank;
   std::ofstream fout(sstrp.str().c_str());
   for(;nit != nend; ++nit) {
     fout << "[" << nit->first.first << "," << nit->first.second << "] -> "
          << nit->second << std::endl;
   }
 
   std::string file = "neighbors_ref";
   std::stringstream sstrf; sstrf << file << "_" << prank;
   file = sstrf.str();
 
   std::ofstream nout;
   nout.open(file.c_str());
   neighbors_map_t<spatial_dimension>::type::iterator it_n = neighbors_map.begin();
   neighbors_map_t<spatial_dimension>::type::iterator end_n = neighbors_map.end();
   for(;it_n != end_n; ++it_n) {
     std::sort(it_n->second.begin(), it_n->second.end());
 
     std::vector< Point<spatial_dimension> >::iterator it_v = it_n->second.begin();
     std::vector< Point<spatial_dimension> >::iterator end_v = it_n->second.end();
 
     nout << "####" << std::endl;
     nout << it_n->second.size() << std::endl;
     nout << it_n->first << std::endl;
     nout << "#" << std::endl;
     for(;it_v != end_v; ++it_v) {
       nout << *it_v << std::endl;
     }
   }
 
   fout.close();
 
-  AKANTU_DEBUG_INFO("Creating TestAccessor");
-  TestAccessor test_accessor(mesh, barycenters);
-  SynchronizerRegistry synch_registry(test_accessor);
 
   synch_registry.registerSynchronizer(*dist, _gst_smm_mass);
 
   synch_registry.registerSynchronizer(*grid_communicator, _gst_test);
 
   AKANTU_DEBUG_INFO("Synchronizing tag on Dist");
   synch_registry.synchronize(_gst_smm_mass);
 
   AKANTU_DEBUG_INFO("Synchronizing tag on Grid");
   synch_registry.synchronize(_gst_test);
 
   delete grid_communicator;
   delete dist;
   akantu::finalize();
 
   return EXIT_SUCCESS;
 }